protocol_fdx_b.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. #include <furi.h>
  2. #include "toolbox/level_duration.h"
  3. #include "protocol_fdx_b.h"
  4. #include <toolbox/manchester_decoder.h>
  5. #include <lfrfid/tools/bit_lib.h>
  6. #include "lfrfid_protocols.h"
  7. #define FDX_B_ENCODED_BIT_SIZE (128)
  8. #define FDX_B_ENCODED_BYTE_SIZE (((FDX_B_ENCODED_BIT_SIZE) / 8))
  9. #define FDX_B_PREAMBLE_BIT_SIZE (11)
  10. #define FDX_B_PREAMBLE_BYTE_SIZE (2)
  11. #define FDX_B_ENCODED_BYTE_FULL_SIZE (FDX_B_ENCODED_BYTE_SIZE + FDX_B_PREAMBLE_BYTE_SIZE)
  12. #define FDXB_DECODED_DATA_SIZE (11)
  13. #define FDX_B_SHORT_TIME (128)
  14. #define FDX_B_LONG_TIME (256)
  15. #define FDX_B_JITTER_TIME (60)
  16. #define FDX_B_SHORT_TIME_LOW (FDX_B_SHORT_TIME - FDX_B_JITTER_TIME)
  17. #define FDX_B_SHORT_TIME_HIGH (FDX_B_SHORT_TIME + FDX_B_JITTER_TIME)
  18. #define FDX_B_LONG_TIME_LOW (FDX_B_LONG_TIME - FDX_B_JITTER_TIME)
  19. #define FDX_B_LONG_TIME_HIGH (FDX_B_LONG_TIME + FDX_B_JITTER_TIME)
  20. typedef struct {
  21. bool last_short;
  22. bool last_level;
  23. size_t encoded_index;
  24. uint8_t encoded_data[FDX_B_ENCODED_BYTE_FULL_SIZE];
  25. uint8_t data[FDXB_DECODED_DATA_SIZE];
  26. } ProtocolFDXB;
  27. ProtocolFDXB* protocol_fdx_b_alloc(void) {
  28. ProtocolFDXB* protocol = malloc(sizeof(ProtocolFDXB));
  29. return protocol;
  30. };
  31. void protocol_fdx_b_free(ProtocolFDXB* protocol) {
  32. free(protocol);
  33. };
  34. uint8_t* protocol_fdx_b_get_data(ProtocolFDXB* proto) {
  35. return proto->data;
  36. };
  37. void protocol_fdx_b_decoder_start(ProtocolFDXB* protocol) {
  38. memset(protocol->encoded_data, 0, FDX_B_ENCODED_BYTE_FULL_SIZE);
  39. protocol->last_short = false;
  40. };
  41. static bool protocol_fdx_b_can_be_decoded(ProtocolFDXB* protocol) {
  42. bool result = false;
  43. /*
  44. msb lsb
  45. 0 10000000000 Header pattern. 11 bits.
  46. 11 1nnnnnnnn
  47. 20 1nnnnnnnn 38 bit (12 digit) National code.
  48. 29 1nnnnnnnn eg. 000000001008 (decimal).
  49. 38 1nnnnnnnn
  50. 47 1nnnnnncc 10 bit (3 digit) Country code.
  51. 56 1cccccccc eg. 999 (decimal).
  52. 65 1s------- 1 bit data block status flag.
  53. 74 1-------a 1 bit animal application indicator.
  54. 83 1xxxxxxxx 16 bit checksum.
  55. 92 1xxxxxxxx
  56. 101 1eeeeeeee 24 bits of extra data if present.
  57. 110 1eeeeeeee eg. $123456.
  58. 119 1eeeeeeee
  59. */
  60. do {
  61. // check 11 bits preamble
  62. if(bit_lib_get_bits_16(protocol->encoded_data, 0, 11) != 0b10000000000) break;
  63. // check next 11 bits preamble
  64. if(bit_lib_get_bits_16(protocol->encoded_data, 128, 11) != 0b10000000000) break;
  65. // check control bits
  66. if(!bit_lib_test_parity(protocol->encoded_data, 3, 13 * 9, BitLibParityAlways1, 9)) break;
  67. // compute checksum
  68. uint8_t crc_data[8];
  69. for(size_t i = 0; i < 8; i++) {
  70. bit_lib_copy_bits(crc_data, i * 8, 8, protocol->encoded_data, 12 + 9 * i);
  71. }
  72. uint16_t crc_res = bit_lib_crc16(crc_data, 8, 0x1021, 0x0000, false, false, 0x0000);
  73. // read checksum
  74. uint16_t crc_ex = 0;
  75. bit_lib_copy_bits((uint8_t*)&crc_ex, 8, 8, protocol->encoded_data, 84);
  76. bit_lib_copy_bits((uint8_t*)&crc_ex, 0, 8, protocol->encoded_data, 93);
  77. // compare checksum
  78. if(crc_res != crc_ex) break;
  79. result = true;
  80. } while(false);
  81. return result;
  82. }
  83. void protocol_fdx_b_decode(ProtocolFDXB* protocol) {
  84. // remove parity
  85. bit_lib_remove_bit_every_nth(protocol->encoded_data, 3, 13 * 9, 9);
  86. // remove header pattern
  87. for(size_t i = 0; i < 11; i++)
  88. bit_lib_push_bit(protocol->encoded_data, FDX_B_ENCODED_BYTE_FULL_SIZE, 0);
  89. // 0 nnnnnnnn
  90. // 8 nnnnnnnn 38 bit (12 digit) National code.
  91. // 16 nnnnnnnn eg. 000000001008 (decimal).
  92. // 24 nnnnnnnn
  93. // 32 nnnnnncc 10 bit (3 digit) Country code.
  94. // 40 cccccccc eg. 999 (decimal).
  95. // 48 s------- 1 bit data block status flag.
  96. // 56 -------a 1 bit animal application indicator.
  97. // 64 xxxxxxxx 16 bit checksum.
  98. // 72 xxxxxxxx
  99. // 80 eeeeeeee 24 bits of extra data if present.
  100. // 88 eeeeeeee eg. $123456.
  101. // 92 eeeeeeee
  102. // copy data without checksum
  103. bit_lib_copy_bits(protocol->data, 0, 64, protocol->encoded_data, 0);
  104. bit_lib_copy_bits(protocol->data, 64, 24, protocol->encoded_data, 80);
  105. // const BitLibRegion regions_encoded[] = {
  106. // {'n', 0, 38},
  107. // {'c', 38, 10},
  108. // {'b', 48, 16},
  109. // {'x', 64, 16},
  110. // {'e', 80, 24},
  111. // };
  112. // bit_lib_print_regions(regions_encoded, 5, protocol->encoded_data, FDX_B_ENCODED_BIT_SIZE);
  113. // const BitLibRegion regions_decoded[] = {
  114. // {'n', 0, 38},
  115. // {'c', 38, 10},
  116. // {'b', 48, 16},
  117. // {'e', 64, 24},
  118. // };
  119. // bit_lib_print_regions(regions_decoded, 4, protocol->data, FDXB_DECODED_DATA_SIZE * 8);
  120. }
  121. bool protocol_fdx_b_decoder_feed(ProtocolFDXB* protocol, bool level, uint32_t duration) {
  122. bool result = false;
  123. UNUSED(level);
  124. bool pushed = false;
  125. // Bi-Phase Manchester decoding
  126. if(duration >= FDX_B_SHORT_TIME_LOW && duration <= FDX_B_SHORT_TIME_HIGH) {
  127. if(protocol->last_short == false) {
  128. protocol->last_short = true;
  129. } else {
  130. pushed = true;
  131. bit_lib_push_bit(protocol->encoded_data, FDX_B_ENCODED_BYTE_FULL_SIZE, false);
  132. protocol->last_short = false;
  133. }
  134. } else if(duration >= FDX_B_LONG_TIME_LOW && duration <= FDX_B_LONG_TIME_HIGH) {
  135. if(protocol->last_short == false) {
  136. pushed = true;
  137. bit_lib_push_bit(protocol->encoded_data, FDX_B_ENCODED_BYTE_FULL_SIZE, true);
  138. } else {
  139. // reset
  140. protocol->last_short = false;
  141. }
  142. } else {
  143. // reset
  144. protocol->last_short = false;
  145. }
  146. if(pushed && protocol_fdx_b_can_be_decoded(protocol)) {
  147. protocol_fdx_b_decode(protocol);
  148. result = true;
  149. }
  150. return result;
  151. };
  152. bool protocol_fdx_b_encoder_start(ProtocolFDXB* protocol) {
  153. memset(protocol->encoded_data, 0, FDX_B_ENCODED_BYTE_FULL_SIZE);
  154. bit_lib_set_bit(protocol->encoded_data, 0, 1);
  155. for(size_t i = 0; i < 13; i++) {
  156. bit_lib_set_bit(protocol->encoded_data, 11 + 9 * i, 1);
  157. if(i == 8 || i == 9) continue;
  158. if(i < 8) {
  159. bit_lib_copy_bits(protocol->encoded_data, 12 + 9 * i, 8, protocol->data, i * 8);
  160. } else {
  161. bit_lib_copy_bits(protocol->encoded_data, 12 + 9 * i, 8, protocol->data, (i - 2) * 8);
  162. }
  163. }
  164. uint16_t crc_res = bit_lib_crc16(protocol->data, 8, 0x1021, 0x0000, false, false, 0x0000);
  165. bit_lib_copy_bits(protocol->encoded_data, 84, 8, (uint8_t*)&crc_res, 8);
  166. bit_lib_copy_bits(protocol->encoded_data, 93, 8, (uint8_t*)&crc_res, 0);
  167. protocol->encoded_index = 0;
  168. protocol->last_short = false;
  169. protocol->last_level = false;
  170. return true;
  171. };
  172. LevelDuration protocol_fdx_b_encoder_yield(ProtocolFDXB* protocol) {
  173. uint32_t duration;
  174. protocol->last_level = !protocol->last_level;
  175. bool bit = bit_lib_get_bit(protocol->encoded_data, protocol->encoded_index);
  176. // Bi-Phase Manchester encoder
  177. if(bit) {
  178. // one long pulse for 1
  179. duration = FDX_B_LONG_TIME / 8;
  180. bit_lib_increment_index(protocol->encoded_index, FDX_B_ENCODED_BIT_SIZE);
  181. } else {
  182. // two short pulses for 0
  183. duration = FDX_B_SHORT_TIME / 8;
  184. if(protocol->last_short) {
  185. bit_lib_increment_index(protocol->encoded_index, FDX_B_ENCODED_BIT_SIZE);
  186. protocol->last_short = false;
  187. } else {
  188. protocol->last_short = true;
  189. }
  190. }
  191. return level_duration_make(protocol->last_level, duration);
  192. };
  193. // 0 nnnnnnnn
  194. // 8 nnnnnnnn 38 bit (12 digit) National code.
  195. // 16 nnnnnnnn eg. 000000001008 (decimal).
  196. // 24 nnnnnnnn
  197. // 32 nnnnnnnn 10 bit (3 digit) Country code.
  198. // 40 cccccccc eg. 999 (decimal).
  199. // 48 s------- 1 bit data block status flag.
  200. // 56 -------a 1 bit animal application indicator.
  201. // 64 eeeeeeee 24 bits of extra data if present.
  202. // 72 eeeeeeee eg. $123456.
  203. // 80 eeeeeeee
  204. static uint64_t protocol_fdx_b_get_national_code(const uint8_t* data) {
  205. uint64_t national_code = bit_lib_get_bits_32(data, 0, 32);
  206. national_code = national_code << 32;
  207. national_code |= bit_lib_get_bits_32(data, 32, 6) << (32 - 6);
  208. bit_lib_reverse_bits((uint8_t*)&national_code, 0, 64);
  209. return national_code;
  210. }
  211. static uint16_t protocol_fdx_b_get_country_code(const uint8_t* data) {
  212. uint16_t country_code = bit_lib_get_bits_16(data, 38, 10) << 6;
  213. bit_lib_reverse_bits((uint8_t*)&country_code, 0, 16);
  214. return country_code;
  215. }
  216. static bool protocol_fdx_b_get_temp(const uint8_t* data, float* temp) {
  217. uint32_t extended = bit_lib_get_bits_32(data, 64, 24) << 8;
  218. bit_lib_reverse_bits((uint8_t*)&extended, 0, 32);
  219. uint8_t ex_parity = (extended & 0x100) >> 8;
  220. uint8_t ex_temperature = extended & 0xff;
  221. uint8_t ex_calc_parity = bit_lib_test_parity_32(ex_temperature, BitLibParityOdd);
  222. bool ex_temperature_present = (ex_calc_parity == ex_parity) && !(extended & 0xe00);
  223. if(ex_temperature_present) {
  224. float temperature_f = 74 + ex_temperature * 0.2;
  225. *temp = temperature_f;
  226. return true;
  227. } else {
  228. return false;
  229. }
  230. }
  231. void protocol_fdx_b_render_data(ProtocolFDXB* protocol, FuriString* result) {
  232. // 38 bits of national code
  233. uint64_t national_code = protocol_fdx_b_get_national_code(protocol->data);
  234. // 10 bit of country code
  235. uint16_t country_code = protocol_fdx_b_get_country_code(protocol->data);
  236. bool block_status = bit_lib_get_bit(protocol->data, 48);
  237. bool rudi_bit = bit_lib_get_bit(protocol->data, 49);
  238. uint8_t reserved = bit_lib_get_bits(protocol->data, 50, 5);
  239. uint8_t user_info = bit_lib_get_bits(protocol->data, 55, 5);
  240. uint8_t replacement_number = bit_lib_get_bits(protocol->data, 60, 3);
  241. bool animal_flag = bit_lib_get_bit(protocol->data, 63);
  242. furi_string_printf(result, "ID: %03u-%012llu\r\n", country_code, national_code);
  243. furi_string_cat_printf(result, "Animal: %s, ", animal_flag ? "Yes" : "No");
  244. float temperature;
  245. if(protocol_fdx_b_get_temp(protocol->data, &temperature)) {
  246. float temperature_c = (temperature - 32) / 1.8;
  247. furi_string_cat_printf(
  248. result, "T: %.2fF, %.2fC\r\n", (double)temperature, (double)temperature_c);
  249. } else {
  250. furi_string_cat_printf(result, "T: ---\r\n");
  251. }
  252. furi_string_cat_printf(
  253. result,
  254. "Bits: %X-%X-%X-%X-%X",
  255. block_status,
  256. rudi_bit,
  257. reserved,
  258. user_info,
  259. replacement_number);
  260. };
  261. void protocol_fdx_b_render_brief_data(ProtocolFDXB* protocol, FuriString* result) {
  262. // 38 bits of national code
  263. uint64_t national_code = protocol_fdx_b_get_national_code(protocol->data);
  264. // 10 bit of country code
  265. uint16_t country_code = protocol_fdx_b_get_country_code(protocol->data);
  266. bool animal_flag = bit_lib_get_bit(protocol->data, 63);
  267. furi_string_printf(result, "ID: %03u-%012llu\r\n", country_code, national_code);
  268. furi_string_cat_printf(result, "Animal: %s, ", animal_flag ? "Yes" : "No");
  269. float temperature;
  270. if(protocol_fdx_b_get_temp(protocol->data, &temperature)) {
  271. float temperature_c = (temperature - 32) / 1.8;
  272. furi_string_cat_printf(result, "T: %.2fC", (double)temperature_c);
  273. } else {
  274. furi_string_cat_printf(result, "T: ---");
  275. }
  276. };
  277. bool protocol_fdx_b_write_data(ProtocolFDXB* protocol, void* data) {
  278. LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
  279. bool result = false;
  280. // Correct protocol data by redecoding
  281. protocol_fdx_b_encoder_start(protocol);
  282. protocol_fdx_b_decode(protocol);
  283. protocol_fdx_b_encoder_start(protocol);
  284. if(request->write_type == LFRFIDWriteTypeT5577) {
  285. request->t5577.block[0] = LFRFID_T5577_MODULATION_DIPHASE | LFRFID_T5577_BITRATE_RF_32 |
  286. (4 << LFRFID_T5577_MAXBLOCK_SHIFT);
  287. request->t5577.block[1] = bit_lib_get_bits_32(protocol->encoded_data, 0, 32);
  288. request->t5577.block[2] = bit_lib_get_bits_32(protocol->encoded_data, 32, 32);
  289. request->t5577.block[3] = bit_lib_get_bits_32(protocol->encoded_data, 64, 32);
  290. request->t5577.block[4] = bit_lib_get_bits_32(protocol->encoded_data, 96, 32);
  291. request->t5577.blocks_to_write = 5;
  292. result = true;
  293. }
  294. return result;
  295. };
  296. const ProtocolBase protocol_fdx_b = {
  297. .name = "FDX-B",
  298. .manufacturer = "ISO",
  299. .data_size = FDXB_DECODED_DATA_SIZE,
  300. .features = LFRFIDFeatureASK,
  301. .validate_count = 3,
  302. .alloc = (ProtocolAlloc)protocol_fdx_b_alloc,
  303. .free = (ProtocolFree)protocol_fdx_b_free,
  304. .get_data = (ProtocolGetData)protocol_fdx_b_get_data,
  305. .decoder =
  306. {
  307. .start = (ProtocolDecoderStart)protocol_fdx_b_decoder_start,
  308. .feed = (ProtocolDecoderFeed)protocol_fdx_b_decoder_feed,
  309. },
  310. .encoder =
  311. {
  312. .start = (ProtocolEncoderStart)protocol_fdx_b_encoder_start,
  313. .yield = (ProtocolEncoderYield)protocol_fdx_b_encoder_yield,
  314. },
  315. .render_data = (ProtocolRenderData)protocol_fdx_b_render_data,
  316. .render_brief_data = (ProtocolRenderData)protocol_fdx_b_render_brief_data,
  317. .write_data = (ProtocolWriteData)protocol_fdx_b_write_data,
  318. };