protocol_cyfral.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include "protocol_cyfral.h"
  4. #define CYFRAL_DATA_SIZE sizeof(uint16_t)
  5. #define CYFRAL_PERIOD (125 * furi_hal_cortex_instructions_per_microsecond())
  6. #define CYFRAL_0_LOW (CYFRAL_PERIOD * 0.66f)
  7. #define CYFRAL_0_HI (CYFRAL_PERIOD * 0.33f)
  8. #define CYFRAL_1_LOW (CYFRAL_PERIOD * 0.33f)
  9. #define CYFRAL_1_HI (CYFRAL_PERIOD * 0.66f)
  10. #define CYFRAL_MAX_PERIOD_US 230
  11. typedef enum {
  12. CYFRAL_BIT_WAIT_FRONT_HIGH,
  13. CYFRAL_BIT_WAIT_FRONT_LOW,
  14. } CyfralBitState;
  15. typedef enum {
  16. CYFRAL_WAIT_START_NIBBLE,
  17. CYFRAL_READ_NIBBLE,
  18. CYFRAL_READ_STOP_NIBBLE,
  19. } CyfralState;
  20. typedef struct {
  21. CyfralState state;
  22. CyfralBitState bit_state;
  23. // high + low period time
  24. uint32_t period_time;
  25. // temporary nibble storage
  26. uint8_t nibble;
  27. // data valid flag
  28. // MUST be checked only in READ_STOP_NIBBLE state
  29. bool data_valid;
  30. // nibble index, we expect 8 nibbles
  31. uint8_t index;
  32. // bit index in nibble, 4 bit per nibble
  33. uint8_t bit_index;
  34. // max period, 230us x clock per us
  35. uint32_t max_period;
  36. } ProtocolCyfralDecoder;
  37. typedef struct {
  38. uint32_t data;
  39. uint32_t index;
  40. } ProtocolCyfralEncoder;
  41. typedef struct {
  42. uint16_t data;
  43. ProtocolCyfralDecoder decoder;
  44. ProtocolCyfralEncoder encoder;
  45. } ProtocolCyfral;
  46. static void* protocol_cyfral_alloc(void) {
  47. ProtocolCyfral* proto = malloc(sizeof(ProtocolCyfral));
  48. return (void*)proto;
  49. }
  50. static void protocol_cyfral_free(ProtocolCyfral* proto) {
  51. free(proto);
  52. }
  53. static uint8_t* protocol_cyfral_get_data(ProtocolCyfral* proto) {
  54. return (uint8_t*)&proto->data;
  55. }
  56. static void protocol_cyfral_decoder_start(ProtocolCyfral* proto) {
  57. ProtocolCyfralDecoder* cyfral = &proto->decoder;
  58. cyfral->state = CYFRAL_WAIT_START_NIBBLE;
  59. cyfral->bit_state = CYFRAL_BIT_WAIT_FRONT_LOW;
  60. cyfral->period_time = 0;
  61. cyfral->bit_index = 0;
  62. cyfral->index = 0;
  63. cyfral->nibble = 0;
  64. cyfral->data_valid = true;
  65. cyfral->max_period = CYFRAL_MAX_PERIOD_US * furi_hal_cortex_instructions_per_microsecond();
  66. proto->data = 0;
  67. }
  68. static bool protocol_cyfral_decoder_process_bit(
  69. ProtocolCyfralDecoder* cyfral,
  70. bool polarity,
  71. uint32_t length,
  72. bool* bit_ready,
  73. bool* bit_value) {
  74. bool result = true;
  75. *bit_ready = false;
  76. // bit start from low
  77. switch(cyfral->bit_state) {
  78. case CYFRAL_BIT_WAIT_FRONT_LOW:
  79. if(polarity == true) {
  80. cyfral->period_time += length;
  81. *bit_ready = true;
  82. if(cyfral->period_time <= cyfral->max_period) {
  83. if((cyfral->period_time / 2) > length) {
  84. *bit_value = false;
  85. } else {
  86. *bit_value = true;
  87. }
  88. } else {
  89. result = false;
  90. }
  91. cyfral->bit_state = CYFRAL_BIT_WAIT_FRONT_HIGH;
  92. } else {
  93. result = false;
  94. }
  95. break;
  96. case CYFRAL_BIT_WAIT_FRONT_HIGH:
  97. if(polarity == false) {
  98. cyfral->period_time = length;
  99. cyfral->bit_state = CYFRAL_BIT_WAIT_FRONT_LOW;
  100. } else {
  101. result = false;
  102. }
  103. break;
  104. }
  105. return result;
  106. }
  107. static bool protocol_cyfral_decoder_feed(ProtocolCyfral* proto, bool level, uint32_t duration) {
  108. ProtocolCyfralDecoder* cyfral = &proto->decoder;
  109. bool bit_ready;
  110. bool bit_value;
  111. bool decoded = false;
  112. switch(cyfral->state) {
  113. case CYFRAL_WAIT_START_NIBBLE:
  114. // wait for start word
  115. if(protocol_cyfral_decoder_process_bit(cyfral, level, duration, &bit_ready, &bit_value)) {
  116. if(bit_ready) {
  117. cyfral->nibble = ((cyfral->nibble << 1) | bit_value) & 0x0F;
  118. if(cyfral->nibble == 0b0001) {
  119. cyfral->nibble = 0;
  120. cyfral->state = CYFRAL_READ_NIBBLE;
  121. }
  122. }
  123. } else {
  124. protocol_cyfral_decoder_start(proto);
  125. }
  126. break;
  127. case CYFRAL_READ_NIBBLE:
  128. // read nibbles
  129. if(protocol_cyfral_decoder_process_bit(cyfral, level, duration, &bit_ready, &bit_value)) {
  130. if(bit_ready) {
  131. cyfral->nibble = (cyfral->nibble << 1) | bit_value;
  132. cyfral->bit_index++;
  133. //convert every nibble to 2-bit index
  134. if(cyfral->bit_index == 4) {
  135. switch(cyfral->nibble) {
  136. case 0b1110:
  137. proto->data = (proto->data << 2) | 0b11;
  138. break;
  139. case 0b1101:
  140. proto->data = (proto->data << 2) | 0b10;
  141. break;
  142. case 0b1011:
  143. proto->data = (proto->data << 2) | 0b01;
  144. break;
  145. case 0b0111:
  146. proto->data = (proto->data << 2) | 0b00;
  147. break;
  148. default:
  149. cyfral->data_valid = false;
  150. break;
  151. }
  152. cyfral->nibble = 0;
  153. cyfral->bit_index = 0;
  154. cyfral->index++;
  155. }
  156. // successfully read 8 nibbles
  157. if(cyfral->index == 8) {
  158. cyfral->state = CYFRAL_READ_STOP_NIBBLE;
  159. }
  160. }
  161. } else {
  162. protocol_cyfral_decoder_start(proto);
  163. }
  164. break;
  165. case CYFRAL_READ_STOP_NIBBLE:
  166. // read stop nibble
  167. if(protocol_cyfral_decoder_process_bit(cyfral, level, duration, &bit_ready, &bit_value)) {
  168. if(bit_ready) {
  169. cyfral->nibble = ((cyfral->nibble << 1) | bit_value) & 0x0F;
  170. cyfral->bit_index++;
  171. switch(cyfral->bit_index) {
  172. case 0:
  173. case 1:
  174. case 2:
  175. case 3:
  176. break;
  177. case 4:
  178. if(cyfral->nibble == 0b0001) {
  179. // validate data
  180. if(cyfral->data_valid) {
  181. decoded = true;
  182. } else {
  183. protocol_cyfral_decoder_start(proto);
  184. }
  185. } else {
  186. protocol_cyfral_decoder_start(proto);
  187. }
  188. break;
  189. default:
  190. protocol_cyfral_decoder_start(proto);
  191. break;
  192. }
  193. }
  194. } else {
  195. protocol_cyfral_decoder_start(proto);
  196. }
  197. break;
  198. }
  199. return decoded;
  200. }
  201. static uint32_t protocol_cyfral_encoder_encode(const uint16_t data) {
  202. uint32_t value = 0;
  203. for(int8_t i = 0; i <= 7; i++) {
  204. switch((data >> (i * 2)) & 0b00000011) {
  205. case 0b11:
  206. value = value << 4;
  207. value += 0b00000111;
  208. break;
  209. case 0b10:
  210. value = value << 4;
  211. value += 0b00001011;
  212. break;
  213. case 0b01:
  214. value = value << 4;
  215. value += 0b00001101;
  216. break;
  217. case 0b00:
  218. value = value << 4;
  219. value += 0b00001110;
  220. break;
  221. default:
  222. break;
  223. }
  224. }
  225. return value;
  226. }
  227. static bool protocol_cyfral_encoder_start(ProtocolCyfral* proto) {
  228. proto->encoder.index = 0;
  229. proto->encoder.data = protocol_cyfral_encoder_encode(proto->data);
  230. return true;
  231. }
  232. static LevelDuration protocol_cyfral_encoder_yield(ProtocolCyfral* proto) {
  233. LevelDuration result;
  234. if(proto->encoder.index < 8) {
  235. // start word (0b0001)
  236. switch(proto->encoder.index) {
  237. case 0:
  238. result = level_duration_make(false, CYFRAL_0_LOW); //-V1037
  239. break;
  240. case 1:
  241. result = level_duration_make(true, CYFRAL_0_HI); //-V1037
  242. break;
  243. case 2:
  244. result = level_duration_make(false, CYFRAL_0_LOW);
  245. break;
  246. case 3:
  247. result = level_duration_make(true, CYFRAL_0_HI);
  248. break;
  249. case 4:
  250. result = level_duration_make(false, CYFRAL_0_LOW);
  251. break;
  252. case 5:
  253. result = level_duration_make(true, CYFRAL_0_HI);
  254. break;
  255. case 6:
  256. result = level_duration_make(false, CYFRAL_1_LOW);
  257. break;
  258. case 7:
  259. result = level_duration_make(true, CYFRAL_1_HI);
  260. break;
  261. }
  262. } else {
  263. // data
  264. uint8_t data_start_index = proto->encoder.index - 8;
  265. bool clock_polarity = (data_start_index) % 2;
  266. uint8_t bit_index = (data_start_index) / 2;
  267. bool bit_value = ((proto->encoder.data >> bit_index) & 1);
  268. if(!clock_polarity) {
  269. if(bit_value) {
  270. result = level_duration_make(false, CYFRAL_1_LOW);
  271. } else {
  272. result = level_duration_make(false, CYFRAL_0_LOW);
  273. }
  274. } else {
  275. if(bit_value) {
  276. result = level_duration_make(true, CYFRAL_1_HI);
  277. } else {
  278. result = level_duration_make(true, CYFRAL_0_HI);
  279. }
  280. }
  281. }
  282. proto->encoder.index++;
  283. if(proto->encoder.index >= (9 * 4 * 2)) {
  284. proto->encoder.index = 0;
  285. }
  286. return result;
  287. }
  288. static void protocol_cyfral_render_brief_data(ProtocolCyfral* proto, FuriString* result) {
  289. for(size_t i = 0; i < CYFRAL_DATA_SIZE; ++i) {
  290. furi_string_cat_printf(result, "%02X ", ((uint8_t*)&proto->data)[i]);
  291. }
  292. }
  293. const ProtocolBase ibutton_protocol_misc_cyfral = {
  294. .name = "Cyfral",
  295. .manufacturer = "Cyfral",
  296. .data_size = CYFRAL_DATA_SIZE,
  297. .alloc = (ProtocolAlloc)protocol_cyfral_alloc,
  298. .free = (ProtocolFree)protocol_cyfral_free,
  299. .get_data = (ProtocolGetData)protocol_cyfral_get_data,
  300. .decoder =
  301. {
  302. .start = (ProtocolDecoderStart)protocol_cyfral_decoder_start,
  303. .feed = (ProtocolDecoderFeed)protocol_cyfral_decoder_feed,
  304. },
  305. .encoder =
  306. {
  307. .start = (ProtocolEncoderStart)protocol_cyfral_encoder_start,
  308. .yield = (ProtocolEncoderYield)protocol_cyfral_encoder_yield,
  309. },
  310. .render_brief_data = (ProtocolRenderData)protocol_cyfral_render_brief_data,
  311. };