subghz_protocol_somfy_keytis.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. #include "subghz_protocol_somfy_keytis.h"
  2. #include "subghz_protocol_common.h"
  3. #include <lib/toolbox/manchester_decoder.h>
  4. #define TAG "SubGhzSomfyKeytis"
  5. struct SubGhzProtocolSomfyKeytis {
  6. SubGhzProtocolCommon common;
  7. ManchesterState manchester_saved_state;
  8. uint32_t press_duration_counter;
  9. };
  10. typedef enum {
  11. SomfyKeytisDecoderStepReset = 0,
  12. SomfyKeytisDecoderStepCheckPreambula,
  13. SomfyKeytisDecoderStepFoundPreambula,
  14. SomfyKeytisDecoderStepStartDecode,
  15. SomfyKeytisDecoderStepDecoderData,
  16. } SomfyKeytisDecoderStep;
  17. SubGhzProtocolSomfyKeytis* subghz_protocol_somfy_keytis_alloc() {
  18. SubGhzProtocolSomfyKeytis* instance = furi_alloc(sizeof(SubGhzProtocolSomfyKeytis));
  19. instance->common.name = "Somfy Keytis";
  20. instance->common.code_min_count_bit_for_found = 80;
  21. instance->common.te_short = 640;
  22. instance->common.te_long = 1280;
  23. instance->common.te_delta = 250;
  24. instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
  25. instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_somfy_keytis_to_str;
  26. instance->common.to_load_protocol =
  27. (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_somfy_keytis_to_load_protocol;
  28. return instance;
  29. }
  30. void subghz_protocol_somfy_keytis_free(SubGhzProtocolSomfyKeytis* instance) {
  31. furi_assert(instance);
  32. free(instance);
  33. }
  34. /** Analysis of received data
  35. *
  36. * @param instance SubGhzProtocolSomfyKeytis instance
  37. */
  38. void subghz_protocol_somfy_keytis_remote_controller(SubGhzProtocolSomfyKeytis* instance) {
  39. //https://pushstack.wordpress.com/somfy-rts-protocol/
  40. /*
  41. * 604 us
  42. * /
  43. * | 2416us | 2416us | 2416us | 2416us | 4550 us | |
  44. *
  45. * +--------+ +--------+ +---...---+
  46. * + +--------+ +--------+ +--+XXXX...XXX+
  47. *
  48. * | hw. sync. | soft. | |
  49. * | | sync. | data |
  50. *
  51. *
  52. * encrypt | decrypt
  53. *
  54. * package 80 bit pdc key btn crc cnt serial
  55. *
  56. * 0xA453537C4B9855 C40019 => 0xA 4 F 7 002F 37D3CD
  57. * 0xA453537C4B9855 C80026 => 0xA 4 F 7 002F 37D3CD
  58. * 0xA453537C4B9855 CC0033 => 0xA 4 F 7 002F 37D3CD
  59. * 0xA453537C4B9855 D00049 => 0xA 4 F 7 002F 37D3CD
  60. * 0xA453537C4B9855 D4005C => 0xA 4 F 7 002F 37D3CD
  61. * 0xA453537C4B9855 D80063 => 0xA 4 F 7 002F 37D3CD
  62. * 0xA453537C4B9855 DC0076 => 0xA 4 F 7 002F 37D3CD
  63. * 0xA453537C4B9855 E00086 => 0xA 4 F 7 002F 37D3CD
  64. * 0xA453537C4B9855 E40093 => 0xA 4 F 7 002F 37D3CD
  65. * 0xA453537C4B9855 E800AC => 0xA 4 F 7 002F 37D3CD
  66. * 0xA453537C4B9855 EC00B9 => 0xA 4 F 7 002F 37D3CD
  67. * 0xA453537C4B9855 F000C3 => 0xA 4 F 7 002F 37D3CD
  68. * 0xA453537C4B9855 F400D6 => 0xA 4 F 7 002F 37D3CD
  69. * 0xA453537C4B9855 F800E9 => 0xA 4 F 7 002F 37D3CD
  70. * 0xA453537C4B9855 FC00FC => 0xA 4 F 7 002F 37D3CD
  71. * 0xA453537C4B9855 FC0102 => 0xA 4 F 7 002F 37D3CD
  72. * 0xA453537C4B9855 FC0113 => 0xA 4 F 7 002F 37D3CD
  73. * 0xA453537C4B9855 FC0120 => 0xA 4 F 7 002F 37D3CD
  74. * ..........
  75. * 0xA453537C4B9855 FC048F => 0xA 4 F 7 002F 37D3CD
  76. *
  77. * Pdc: "Press Duration Counter" the total delay of the button is sent 72 parcels,
  78. * pdc cnt4b cnt8b pdc_crc
  79. * C40019 => 11 0001 00 0000 00000001 1001
  80. * C80026 => 11 0010 00 0000 00000010 0110
  81. * CC0033 => 11 0011 00 0000 00000011 0011
  82. * D00049 => 11 0100 00 0000 00000100 1001
  83. * D4005C => 11 0101 00 0000 00000101 1100
  84. * D80063 => 11 0110 00 0000 00000110 0011
  85. * DC0076 => 11 0111 00 0000 00000111 0110
  86. * E00086 => 11 1000 00 0000 00001000 0110
  87. * E40093 => 11 1001 00 0000 00001001 0011
  88. * E800AC => 11 1010 00 0000 00001010 1100
  89. * EC00B9 => 11 1011 00 0000 00001011 1001
  90. * F000C3 => 11 1100 00 0000 00001100 0011
  91. * F400D6 => 11 1101 00 0000 00001101 0110
  92. * F800E9 => 11 1110 00 0000 00001110 1001
  93. * FC00FC => 11 1111 00 0000 00001111 1100
  94. * FC0102 => 11 1111 00 0000 00010000 0010
  95. * FC0113 => 11 1111 00 0000 00010001 0011
  96. * FC0120 => 11 1111 00 0000 00010010 0000
  97. *
  98. * Cnt4b: 4-bit counter changes from 1 to 15 then always equals 15
  99. * Cnt8b: 8-bit counter changes from 1 to 72 (0x48)
  100. * Ppdc_crc:
  101. * uint8_t crc=0;
  102. * for(i=4; i<24; i+=4){
  103. * crc ^=(pdc>>i);
  104. * }
  105. * return crc;
  106. * example: crc = 1^0^0^4^C = 9
  107. * 11, 00, 0000: const
  108. *
  109. * Key: “Encryption Key”, Most significant 4-bit are always 0xA, Least Significant bits is
  110. * a linear counter. In the Smoove Origin this counter is increased together with the
  111. * rolling code. But leaving this on a constant value also works. Gerardwr notes that
  112. * for some other types of remotes the MSB is not constant.
  113. * Btn: 4-bit Control codes, this indicates the button that is pressed
  114. * CRC: 4-bit Checksum.
  115. * Ctn: 16-bit rolling code (big-endian) increased with every button press.
  116. * Serial: 24-bit identifier of sending device (little-endian)
  117. *
  118. *
  119. * Decrypt
  120. *
  121. * uint8_t frame[7];
  122. * for (i=1; i < 7; i++) {
  123. * frame[i] = frame[i] ^ frame[i-1];
  124. * }
  125. * or
  126. * uint64 Decrypt = frame ^ (frame>>8);
  127. *
  128. * CRC
  129. *
  130. * uint8_t frame[7];
  131. * for (i=0; i < 7; i++) {
  132. * crc = crc ^ frame[i] ^ (frame[i] >> 4);
  133. * }
  134. * crc = crc & 0xf;
  135. *
  136. */
  137. uint64_t data = instance->common.code_last_found ^ (instance->common.code_last_found >> 8);
  138. instance->common.btn = (data >> 48) & 0xF;
  139. instance->common.cnt = (data >> 24) & 0xFFFF;
  140. instance->common.serial = data & 0xFFFFFF;
  141. }
  142. uint8_t subghz_protocol_somfy_keytis_crc(uint64_t data) {
  143. uint8_t crc = 0;
  144. data &= 0xFFF0FFFFFFFFFF;
  145. for(uint8_t i = 0; i < 56; i += 8) {
  146. crc = crc ^ data >> i ^ (data >> (i + 4));
  147. }
  148. return crc & 0xf;
  149. }
  150. const char* subghz_protocol_somfy_keytis_get_name_button(uint8_t btn) {
  151. const char* name_btn[0x10] = {
  152. "Unknown",
  153. "0x01",
  154. "0x02",
  155. "Prog",
  156. "Key_1",
  157. "0x05",
  158. "0x06",
  159. "0x07",
  160. "0x08",
  161. "0x09",
  162. "0x0A",
  163. "0x0B",
  164. "0x0C",
  165. "0x0D",
  166. "0x0E",
  167. "0x0F"};
  168. return btn <= 0xf ? name_btn[btn] : name_btn[0];
  169. }
  170. uint32_t subghz_protocol_somfy_keytis_get_press_duration(void* context) {
  171. SubGhzProtocolSomfyKeytis* instance = context;
  172. return instance->press_duration_counter;
  173. }
  174. void subghz_protocol_somfy_keytis_reset(SubGhzProtocolSomfyKeytis* instance) {
  175. instance->common.parser_step = SomfyKeytisDecoderStepReset;
  176. manchester_advance(
  177. instance->manchester_saved_state,
  178. ManchesterEventReset,
  179. &instance->manchester_saved_state,
  180. NULL);
  181. }
  182. void subghz_protocol_somfy_keytis_parse(
  183. SubGhzProtocolSomfyKeytis* instance,
  184. bool level,
  185. uint32_t duration) {
  186. ManchesterEvent event = ManchesterEventReset;
  187. switch(instance->common.parser_step) {
  188. case SomfyKeytisDecoderStepReset:
  189. if((level) && DURATION_DIFF(duration, instance->common.te_short * 4) <
  190. instance->common.te_delta * 4) {
  191. instance->common.parser_step = SomfyKeytisDecoderStepFoundPreambula;
  192. instance->common.header_count++;
  193. }
  194. break;
  195. case SomfyKeytisDecoderStepFoundPreambula:
  196. if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 4) <
  197. instance->common.te_delta * 4)) {
  198. instance->common.parser_step = SomfyKeytisDecoderStepCheckPreambula;
  199. } else {
  200. instance->common.header_count = 0;
  201. instance->common.parser_step = SomfyKeytisDecoderStepReset;
  202. }
  203. break;
  204. case SomfyKeytisDecoderStepCheckPreambula:
  205. if(level) {
  206. if(DURATION_DIFF(duration, instance->common.te_short * 4) <
  207. instance->common.te_delta * 4) {
  208. instance->common.parser_step = SomfyKeytisDecoderStepFoundPreambula;
  209. instance->common.header_count++;
  210. } else if(
  211. (instance->common.header_count > 1) &&
  212. (DURATION_DIFF(duration, instance->common.te_short * 7) <
  213. instance->common.te_delta * 4)) {
  214. instance->common.parser_step = SomfyKeytisDecoderStepDecoderData;
  215. instance->common.code_found = 0;
  216. instance->common.code_count_bit = 0;
  217. instance->press_duration_counter = 0;
  218. manchester_advance(
  219. instance->manchester_saved_state,
  220. ManchesterEventReset,
  221. &instance->manchester_saved_state,
  222. NULL);
  223. manchester_advance(
  224. instance->manchester_saved_state,
  225. ManchesterEventLongHigh,
  226. &instance->manchester_saved_state,
  227. NULL);
  228. }
  229. }
  230. break;
  231. case SomfyKeytisDecoderStepDecoderData:
  232. if(!level) {
  233. if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
  234. event = ManchesterEventShortLow;
  235. } else if(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta) {
  236. event = ManchesterEventLongLow;
  237. } else if(duration >= (instance->common.te_long + instance->common.te_delta)) {
  238. if(instance->common.code_count_bit ==
  239. instance->common.code_min_count_bit_for_found) {
  240. instance->common.code_last_found = instance->common.code_found;
  241. instance->common.code_last_count_bit = instance->common.code_count_bit;
  242. //check crc
  243. uint64_t data_tmp = instance->common.code_last_found ^
  244. (instance->common.code_last_found >> 8);
  245. if(((data_tmp >> 40) & 0xF) == subghz_protocol_somfy_keytis_crc(data_tmp)) {
  246. if(instance->common.callback)
  247. instance->common.callback(
  248. (SubGhzProtocolCommon*)instance, instance->common.context);
  249. }
  250. }
  251. instance->common.code_found = 0;
  252. instance->common.code_count_bit = 0;
  253. manchester_advance(
  254. instance->manchester_saved_state,
  255. ManchesterEventReset,
  256. &instance->manchester_saved_state,
  257. NULL);
  258. manchester_advance(
  259. instance->manchester_saved_state,
  260. ManchesterEventLongHigh,
  261. &instance->manchester_saved_state,
  262. NULL);
  263. instance->common.parser_step = SomfyKeytisDecoderStepReset;
  264. } else {
  265. instance->common.parser_step = SomfyKeytisDecoderStepReset;
  266. }
  267. } else {
  268. if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
  269. event = ManchesterEventShortHigh;
  270. } else if(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta) {
  271. event = ManchesterEventLongHigh;
  272. } else {
  273. instance->common.parser_step = SomfyKeytisDecoderStepReset;
  274. }
  275. }
  276. if(event != ManchesterEventReset) {
  277. bool data;
  278. bool data_ok = manchester_advance(
  279. instance->manchester_saved_state, event, &instance->manchester_saved_state, &data);
  280. if(data_ok) {
  281. if(instance->common.code_count_bit < 56) {
  282. instance->common.code_found = (instance->common.code_found << 1) | data;
  283. } else {
  284. instance->press_duration_counter = (instance->press_duration_counter << 1) |
  285. data;
  286. }
  287. instance->common.code_count_bit++;
  288. }
  289. }
  290. break;
  291. }
  292. }
  293. void subghz_protocol_somfy_keytis_to_str(SubGhzProtocolSomfyKeytis* instance, string_t output) {
  294. subghz_protocol_somfy_keytis_remote_controller(instance);
  295. uint32_t code_found_hi = instance->common.code_last_found >> 32;
  296. uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
  297. string_cat_printf(
  298. output,
  299. "%s %db\r\n"
  300. "%lX%08lX%06lX\r\n"
  301. "Sn:0x%06lX \r\n"
  302. "Cnt:0x%04X\r\n"
  303. "Btn:%s\r\n",
  304. instance->common.name,
  305. instance->common.code_last_count_bit,
  306. code_found_hi,
  307. code_found_lo,
  308. instance->press_duration_counter,
  309. instance->common.serial,
  310. instance->common.cnt,
  311. subghz_protocol_somfy_keytis_get_name_button(instance->common.btn));
  312. }
  313. void subghz_decoder_somfy_keytis_to_load_protocol(
  314. SubGhzProtocolSomfyKeytis* instance,
  315. void* context) {
  316. furi_assert(context);
  317. furi_assert(instance);
  318. SubGhzProtocolCommonLoad* data = context;
  319. instance->common.code_last_found = data->code_found;
  320. instance->common.code_last_count_bit = data->code_count_bit;
  321. instance->press_duration_counter = data->param1;
  322. subghz_protocol_somfy_keytis_remote_controller(instance);
  323. }