subghz_protocol_came_twee.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. #include "subghz_protocol_came_twee.h"
  2. #include "subghz_protocol_common.h"
  3. #include <lib/toolbox/manchester-decoder.h>
  4. #include <lib/toolbox/manchester-encoder.h>
  5. /*
  6. * Help
  7. * https://phreakerclub.com/forum/showthread.php?t=635&highlight=came+twin
  8. *
  9. */
  10. #define DIP_PATTERN "%c%c%c%c%c%c%c%c%c%c"
  11. #define CNT_TO_DIP(dip) \
  12. (dip & 0x0200 ? '1' : '0'), (dip & 0x0100 ? '1' : '0'), (dip & 0x0080 ? '1' : '0'), \
  13. (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'), (dip & 0x0010 ? '1' : '0'), \
  14. (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), (dip & 0x0002 ? '1' : '0'), \
  15. (dip & 0x0001 ? '1' : '0')
  16. struct SubGhzProtocolCameTwee {
  17. SubGhzProtocolCommon common;
  18. ManchesterState manchester_saved_state;
  19. };
  20. typedef enum {
  21. CameTweeDecoderStepReset = 0,
  22. CameTweeDecoderStepDecoderData,
  23. } CameTweeDecoderStep;
  24. SubGhzProtocolCameTwee* subghz_protocol_came_twee_alloc() {
  25. SubGhzProtocolCameTwee* instance = furi_alloc(sizeof(SubGhzProtocolCameTwee));
  26. instance->common.name = "CAME TWEE";
  27. instance->common.code_min_count_bit_for_found = 54;
  28. instance->common.te_short = 500;
  29. instance->common.te_long = 1000;
  30. instance->common.te_delta = 250;
  31. instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
  32. instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_came_twee_to_str;
  33. instance->common.to_save_string =
  34. (SubGhzProtocolCommonGetStrSave)subghz_protocol_came_twee_to_save_str;
  35. instance->common.to_load_protocol_from_file =
  36. (SubGhzProtocolCommonLoadFromFile)subghz_protocol_came_twee_to_load_protocol_from_file;
  37. instance->common.to_load_protocol =
  38. (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_came_twee_to_load_protocol;
  39. instance->common.get_upload_protocol =
  40. (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_came_twee_send_key;
  41. return instance;
  42. }
  43. void subghz_protocol_came_twee_free(SubGhzProtocolCameTwee* instance) {
  44. furi_assert(instance);
  45. free(instance);
  46. }
  47. LevelDuration subghz_protocol_came_twee_add_duration_to_upload(
  48. SubGhzProtocolCameTwee* instance,
  49. ManchesterEncoderResult result) {
  50. LevelDuration data;
  51. switch(result) {
  52. case ManchesterEncoderResultShortLow:
  53. data.duration = instance->common.te_short;
  54. data.level = false;
  55. break;
  56. case ManchesterEncoderResultLongLow:
  57. data.duration = instance->common.te_long;
  58. data.level = false;
  59. break;
  60. case ManchesterEncoderResultLongHigh:
  61. data.duration = instance->common.te_long;
  62. data.level = true;
  63. break;
  64. case ManchesterEncoderResultShortHigh:
  65. data.duration = instance->common.te_short;
  66. data.level = true;
  67. break;
  68. default:
  69. printf("DO CRASH HERE\r\n");
  70. // furi_crash
  71. break;
  72. }
  73. return level_duration_make(data.level, data.duration);
  74. }
  75. bool subghz_protocol_came_twee_send_key(
  76. SubGhzProtocolCameTwee* instance,
  77. SubGhzProtocolCommonEncoder* encoder) {
  78. furi_assert(instance);
  79. furi_assert(encoder);
  80. const uint32_t magic_numbers_xor[15] = {
  81. 0x0E0E0E00,
  82. 0x1D1D1D11,
  83. 0x2C2C2C22,
  84. 0x3B3B3B33,
  85. 0x4A4A4A44,
  86. 0x59595955,
  87. 0x68686866,
  88. 0x77777777,
  89. 0x86868688,
  90. 0x95959599,
  91. 0xA4A4A4AA,
  92. 0xB3B3B3BB,
  93. 0xC2C2C2CC,
  94. 0xD1D1D1DD,
  95. 0xE0E0E0EE,
  96. };
  97. size_t index = 0;
  98. ManchesterEncoderState enc_state;
  99. manchester_encoder_reset(&enc_state);
  100. ManchesterEncoderResult result;
  101. // encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
  102. // if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
  103. uint64_t temp_parcel = 0x003FFF7200000000; //parcel mask
  104. for(int i = 14; i >= 0; i--) {
  105. temp_parcel = (temp_parcel & 0xFFFFFFFF00000000) |
  106. (instance->common.serial ^ magic_numbers_xor[i]);
  107. for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
  108. if(!manchester_encoder_advance(&enc_state, !bit_read(temp_parcel, i - 1), &result)) {
  109. encoder->upload[index++] =
  110. subghz_protocol_came_twee_add_duration_to_upload(instance, result);
  111. manchester_encoder_advance(&enc_state, !bit_read(temp_parcel, i - 1), &result);
  112. }
  113. encoder->upload[index++] =
  114. subghz_protocol_came_twee_add_duration_to_upload(instance, result);
  115. }
  116. encoder->upload[index] = subghz_protocol_came_twee_add_duration_to_upload(
  117. instance, manchester_encoder_finish(&enc_state));
  118. if(level_duration_get_level(encoder->upload[index])) {
  119. index++;
  120. }
  121. encoder->upload[index++] =
  122. level_duration_make(false, (uint32_t)instance->common.te_long * 51);
  123. }
  124. encoder->size_upload = index;
  125. return true;
  126. }
  127. /** Analysis of received data
  128. *
  129. * @param instance SubGhzProtocolCameTwee instance
  130. */
  131. void subghz_protocol_came_twee_remote_controller(SubGhzProtocolCameTwee* instance) {
  132. /* Came Twee 54 bit, rolling code 15 parcels with
  133. * a decreasing counter from 0xE to 0x0
  134. * with originally coded dip switches on the console 10 bit code
  135. *
  136. * 0x003FFF72E04A6FEE
  137. * 0x003FFF72D17B5EDD
  138. * 0x003FFF72C2684DCC
  139. * 0x003FFF72B3193CBB
  140. * 0x003FFF72A40E2BAA
  141. * 0x003FFF72953F1A99
  142. * 0x003FFF72862C0988
  143. * 0x003FFF7277DDF877
  144. * 0x003FFF7268C2E766
  145. * 0x003FFF7259F3D655
  146. * 0x003FFF724AE0C544
  147. * 0x003FFF723B91B433
  148. * 0x003FFF722C86A322
  149. * 0x003FFF721DB79211
  150. * 0x003FFF720EA48100
  151. *
  152. * decryption
  153. * the last 32 bits, do XOR by the desired number, divide the result by 4,
  154. * convert the first 16 bits of the resulting 32-bit number to bin and do
  155. * bit-by-bit mirroring, adding up to 10 bits
  156. *
  157. * Example
  158. * Step 1. 0x003FFF721DB79211 => 0x1DB79211
  159. * Step 4. 0x1DB79211 xor 0x1D1D1D11 => 0x00AA8F00
  160. * Step 4. 0x00AA8F00 / 4 => 0x002AA3C0
  161. * Step 5. 0x002AA3C0 => 0x002A
  162. * Step 6. 0x002A bin => b101010
  163. * Step 7. b101010 => b0101010000
  164. * Step 8. b0101010000 => (Dip) Off ON Off ON Off ON Off Off Off Off
  165. */
  166. const uint32_t magic_numbers_xor[15] = {
  167. 0x0E0E0E00,
  168. 0x1D1D1D11,
  169. 0x2C2C2C22,
  170. 0x3B3B3B33,
  171. 0x4A4A4A44,
  172. 0x59595955,
  173. 0x68686866,
  174. 0x77777777,
  175. 0x86868688,
  176. 0x95959599,
  177. 0xA4A4A4AA,
  178. 0xB3B3B3BB,
  179. 0xC2C2C2CC,
  180. 0xD1D1D1DD,
  181. 0xE0E0E0EE,
  182. };
  183. uint8_t cnt_parcel = (uint8_t)(instance->common.code_last_found & 0xF);
  184. uint32_t data = (uint32_t)(instance->common.code_last_found & 0x0FFFFFFFF);
  185. data = (data ^ magic_numbers_xor[cnt_parcel]);
  186. instance->common.serial = data;
  187. data /= 4;
  188. instance->common.btn = (data >> 4) & 0x0F;
  189. data >>= 16;
  190. data = (uint16_t)subghz_protocol_common_reverse_key(data, 16);
  191. instance->common.cnt = data >> 6;
  192. }
  193. void subghz_protocol_came_twee_reset(SubGhzProtocolCameTwee* instance) {
  194. instance->common.parser_step = CameTweeDecoderStepReset;
  195. manchester_advance(
  196. instance->manchester_saved_state,
  197. ManchesterEventReset,
  198. &instance->manchester_saved_state,
  199. NULL);
  200. }
  201. void subghz_protocol_came_twee_parse(
  202. SubGhzProtocolCameTwee* instance,
  203. bool level,
  204. uint32_t duration) {
  205. ManchesterEvent event = ManchesterEventReset;
  206. switch(instance->common.parser_step) {
  207. case CameTweeDecoderStepReset:
  208. if((!level) && (DURATION_DIFF(duration, instance->common.te_long * 51) <
  209. instance->common.te_delta * 20)) {
  210. //Found header CAME
  211. instance->common.parser_step = CameTweeDecoderStepDecoderData;
  212. instance->common.code_found = 0;
  213. instance->common.code_count_bit = 0;
  214. manchester_advance(
  215. instance->manchester_saved_state,
  216. ManchesterEventLongLow,
  217. &instance->manchester_saved_state,
  218. NULL);
  219. manchester_advance(
  220. instance->manchester_saved_state,
  221. ManchesterEventLongHigh,
  222. &instance->manchester_saved_state,
  223. NULL);
  224. manchester_advance(
  225. instance->manchester_saved_state,
  226. ManchesterEventShortLow,
  227. &instance->manchester_saved_state,
  228. NULL);
  229. } else {
  230. instance->common.parser_step = CameTweeDecoderStepReset;
  231. }
  232. break;
  233. case CameTweeDecoderStepDecoderData:
  234. if(!level) {
  235. if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
  236. event = ManchesterEventShortLow;
  237. } else if(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta) {
  238. event = ManchesterEventLongLow;
  239. } else if(duration >= (instance->common.te_long * 2 + instance->common.te_delta)) {
  240. if(instance->common.code_count_bit >=
  241. instance->common.code_min_count_bit_for_found) {
  242. instance->common.code_last_found = instance->common.code_found;
  243. instance->common.code_last_count_bit = instance->common.code_count_bit;
  244. if(instance->common.callback)
  245. instance->common.callback(
  246. (SubGhzProtocolCommon*)instance, instance->common.context);
  247. }
  248. instance->common.code_found = 0;
  249. instance->common.code_count_bit = 0;
  250. manchester_advance(
  251. instance->manchester_saved_state,
  252. ManchesterEventLongLow,
  253. &instance->manchester_saved_state,
  254. NULL);
  255. manchester_advance(
  256. instance->manchester_saved_state,
  257. ManchesterEventLongHigh,
  258. &instance->manchester_saved_state,
  259. NULL);
  260. manchester_advance(
  261. instance->manchester_saved_state,
  262. ManchesterEventShortLow,
  263. &instance->manchester_saved_state,
  264. NULL);
  265. } else {
  266. instance->common.parser_step = CameTweeDecoderStepReset;
  267. }
  268. } else {
  269. if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
  270. event = ManchesterEventShortHigh;
  271. } else if(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta) {
  272. event = ManchesterEventLongHigh;
  273. } else {
  274. instance->common.parser_step = CameTweeDecoderStepReset;
  275. }
  276. }
  277. if(event != ManchesterEventReset) {
  278. bool data;
  279. bool data_ok = manchester_advance(
  280. instance->manchester_saved_state, event, &instance->manchester_saved_state, &data);
  281. if(data_ok) {
  282. instance->common.code_found = (instance->common.code_found << 1) | !data;
  283. instance->common.code_count_bit++;
  284. }
  285. }
  286. break;
  287. }
  288. }
  289. void subghz_protocol_came_twee_to_str(SubGhzProtocolCameTwee* instance, string_t output) {
  290. uint32_t code_found_hi = instance->common.code_last_found >> 32;
  291. uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
  292. string_cat_printf(
  293. output,
  294. "%s %dbit\r\n"
  295. "Key:0x%lX%08lX\r\n"
  296. "Btn:%lX\r\n"
  297. "DIP:" DIP_PATTERN,
  298. instance->common.name,
  299. instance->common.code_last_count_bit,
  300. code_found_hi,
  301. code_found_lo,
  302. instance->common.btn,
  303. CNT_TO_DIP(instance->common.cnt));
  304. }
  305. void subghz_protocol_came_twee_to_save_str(SubGhzProtocolCameTwee* instance, string_t output) {
  306. string_printf(
  307. output,
  308. "Protocol: %s\n"
  309. "Bit: %d\n"
  310. "Key: %08lX%08lX\r\n",
  311. instance->common.name,
  312. instance->common.code_last_count_bit,
  313. (uint32_t)(instance->common.code_last_found >> 32),
  314. (uint32_t)(instance->common.code_last_found & 0xFFFFFFFF));
  315. }
  316. bool subghz_protocol_came_twee_to_load_protocol_from_file(
  317. FileWorker* file_worker,
  318. SubGhzProtocolCameTwee* instance) {
  319. bool loaded = false;
  320. string_t temp_str;
  321. string_init(temp_str);
  322. int res = 0;
  323. int data = 0;
  324. do {
  325. // Read and parse bit data from 2nd line
  326. if(!file_worker_read_until(file_worker, temp_str, '\n')) {
  327. break;
  328. }
  329. res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
  330. if(res != 1) {
  331. break;
  332. }
  333. instance->common.code_last_count_bit = (uint8_t)data;
  334. // Read and parse key data from 3nd line
  335. if(!file_worker_read_until(file_worker, temp_str, '\n')) {
  336. break;
  337. }
  338. // strlen("Key: ") = 5
  339. string_right(temp_str, 5);
  340. uint8_t buf_key[8] = {0};
  341. if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)) {
  342. break;
  343. }
  344. for(uint8_t i = 0; i < 8; i++) {
  345. instance->common.code_last_found = instance->common.code_last_found << 8 | buf_key[i];
  346. }
  347. loaded = true;
  348. } while(0);
  349. string_clear(temp_str);
  350. subghz_protocol_came_twee_remote_controller(instance);
  351. return loaded;
  352. }
  353. void subghz_decoder_came_twee_to_load_protocol(SubGhzProtocolCameTwee* instance, void* context) {
  354. furi_assert(context);
  355. furi_assert(instance);
  356. SubGhzProtocolCommonLoad* data = context;
  357. instance->common.code_last_found = data->code_found;
  358. instance->common.code_last_count_bit = data->code_count_bit;
  359. subghz_protocol_came_twee_remote_controller(instance);
  360. }