EM41XX.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #include "EM41XX.h"
  2. #include "core/check.h"
  3. #include "core/log.h"
  4. #define EM41XX_LINES (10)
  5. #define EM41XX_COLUMNS (4)
  6. #define EM41XX_CONFIG_1_KEY (0b00000000000101001000000001000000)
  7. #define EM41XX_CONFIG_2_KEYS (0b00000000000101001000000010000000)
  8. #define EM41XX_CONFIG_3_KEYS (0b00000000000101001000000011000000)
  9. #define EM41XX_CONFIG_BLANK (0b00000000000101001000000000000000)
  10. #define EM41XX_HEADER (0b111111111)
  11. #define T5577_MAX_BLOCKS (8)
  12. #define EM41XX_BLOCKS (2)
  13. bool get_parity(uint16_t data) {
  14. bool result = 0;
  15. for(int i = 0; i < 16; i++) result ^= ((data >> i) & 1);
  16. return result;
  17. }
  18. bool get_line_parity_bit(uint8_t line_num, uint64_t data) {
  19. uint8_t line = (data >> (EM41XX_COLUMNS * line_num)) & 0x0F;
  20. return get_parity(line);
  21. }
  22. bool get_column_parity_bit(uint8_t column_num, uint64_t data) {
  23. uint16_t column = 0;
  24. for(int i = 0; i < EM41XX_LINES; i++) {
  25. column <<= 1;
  26. column |= (data >> (EM41XX_COLUMNS * i + column_num)) & 1;
  27. }
  28. return get_parity(column);
  29. }
  30. uint64_t em41xx_encode(uint64_t data) {
  31. uint64_t result = EM41XX_HEADER;
  32. for(int i = EM41XX_LINES - 1; i >= 0; i--) {
  33. result <<= EM41XX_COLUMNS;
  34. uint8_t line = (data >> (i * EM41XX_COLUMNS)) & 0x0F;
  35. result |= line;
  36. result <<= 1;
  37. result |= get_line_parity_bit(i, data);
  38. }
  39. for(int i = EM41XX_COLUMNS - 1; i >= 0; i--) {
  40. result <<= 1;
  41. result |= get_column_parity_bit(i, data);
  42. }
  43. result <<= 1;
  44. return result;
  45. }
  46. bool add_em41xx_data(LFRFIDT5577* data, uint64_t key, uint8_t from_index) {
  47. if(from_index + EM41XX_BLOCKS > (T5577_MAX_BLOCKS - 1)) return false;
  48. uint64_t blocks_data = em41xx_encode(key);
  49. data->block[from_index] = blocks_data >> 32;
  50. data->block[from_index + 1] = blocks_data & 0xFFFFFFFF;
  51. data->blocks_to_write = T5577_MAX_BLOCKS;
  52. uint8_t mask_addition = (1 << from_index);
  53. mask_addition |= (1 << (from_index + 1));
  54. data->mask |= mask_addition;
  55. FURI_LOG_D("ADDDATA", "%u", data->mask);
  56. return true;
  57. }
  58. uint32_t get_config(uint8_t keys_count) {
  59. if(keys_count > 3) return 0;
  60. uint32_t result = EM41XX_CONFIG_BLANK;
  61. result |= ((keys_count * EM41XX_BLOCKS) << 5);
  62. return result;
  63. }
  64. bool set_em41xx_config(LFRFIDT5577* data, uint8_t keys_count) {
  65. if(keys_count > 3) return false;
  66. data->block[0] = get_config(keys_count);
  67. data->mask |= 1;
  68. FURI_LOG_D("SETCONFIG", "%u", data->mask);
  69. return true;
  70. }
  71. uint64_t bytes2num(const uint8_t* src, uint8_t len) {
  72. furi_assert(src);
  73. furi_assert(len <= 8);
  74. uint64_t res = 0;
  75. while(len--) {
  76. res = (res << 8) | (*src);
  77. src++;
  78. }
  79. return res;
  80. }