EM41XX.c 2.7 KB

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