came_twee.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. #include "came_twee.h"
  2. #include <lib/toolbox/manchester_decoder.h>
  3. #include <lib/toolbox/manchester_encoder.h>
  4. #include "../blocks/const.h"
  5. #include "../blocks/decoder.h"
  6. #include "../blocks/encoder.h"
  7. #include "../blocks/generic.h"
  8. #include "../blocks/math.h"
  9. /*
  10. * Help
  11. * https://phreakerclub.com/forum/showthread.php?t=635&highlight=came+twin
  12. *
  13. */
  14. #define TAG "SubGhzProtocolCAME_Twee"
  15. #define DIP_PATTERN "%c%c%c%c%c%c%c%c%c%c"
  16. #define CNT_TO_DIP(dip) \
  17. (dip & 0x0200 ? '1' : '0'), (dip & 0x0100 ? '1' : '0'), (dip & 0x0080 ? '1' : '0'), \
  18. (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'), (dip & 0x0010 ? '1' : '0'), \
  19. (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), (dip & 0x0002 ? '1' : '0'), \
  20. (dip & 0x0001 ? '1' : '0')
  21. static const uint32_t came_twee_magic_numbers_xor[15] = {
  22. 0x0E0E0E00,
  23. 0x1D1D1D11,
  24. 0x2C2C2C22,
  25. 0x3B3B3B33,
  26. 0x4A4A4A44,
  27. 0x59595955,
  28. 0x68686866,
  29. 0x77777777,
  30. 0x86868688,
  31. 0x95959599,
  32. 0xA4A4A4AA,
  33. 0xB3B3B3BB,
  34. 0xC2C2C2CC,
  35. 0xD1D1D1DD,
  36. 0xE0E0E0EE,
  37. };
  38. static const SubGhzBlockConst subghz_protocol_came_twee_const = {
  39. .te_short = 500,
  40. .te_long = 1000,
  41. .te_delta = 250,
  42. .min_count_bit_for_found = 54,
  43. };
  44. struct SubGhzProtocolDecoderCameTwee {
  45. SubGhzProtocolDecoderBase base;
  46. SubGhzBlockDecoder decoder;
  47. SubGhzBlockGeneric generic;
  48. ManchesterState manchester_saved_state;
  49. };
  50. struct SubGhzProtocolEncoderCameTwee {
  51. SubGhzProtocolEncoderBase base;
  52. SubGhzProtocolBlockEncoder encoder;
  53. SubGhzBlockGeneric generic;
  54. };
  55. typedef enum {
  56. CameTweeDecoderStepReset = 0,
  57. CameTweeDecoderStepDecoderData,
  58. } CameTweeDecoderStep;
  59. const SubGhzProtocolDecoder subghz_protocol_came_twee_decoder = {
  60. .alloc = subghz_protocol_decoder_came_twee_alloc,
  61. .free = subghz_protocol_decoder_came_twee_free,
  62. .feed = subghz_protocol_decoder_came_twee_feed,
  63. .reset = subghz_protocol_decoder_came_twee_reset,
  64. .get_hash_data = subghz_protocol_decoder_came_twee_get_hash_data,
  65. .serialize = subghz_protocol_decoder_came_twee_serialize,
  66. .deserialize = subghz_protocol_decoder_came_twee_deserialize,
  67. .get_string = subghz_protocol_decoder_came_twee_get_string,
  68. };
  69. const SubGhzProtocolEncoder subghz_protocol_came_twee_encoder = {
  70. .alloc = subghz_protocol_encoder_came_twee_alloc,
  71. .free = subghz_protocol_encoder_came_twee_free,
  72. .deserialize = subghz_protocol_encoder_came_twee_deserialize,
  73. .stop = subghz_protocol_encoder_came_twee_stop,
  74. .yield = subghz_protocol_encoder_came_twee_yield,
  75. };
  76. const SubGhzProtocol subghz_protocol_came_twee = {
  77. .name = SUBGHZ_PROTOCOL_CAME_TWEE_NAME,
  78. .type = SubGhzProtocolTypeStatic,
  79. .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
  80. SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
  81. .decoder = &subghz_protocol_came_twee_decoder,
  82. .encoder = &subghz_protocol_came_twee_encoder,
  83. };
  84. void* subghz_protocol_encoder_came_twee_alloc(SubGhzEnvironment* environment) {
  85. SubGhzProtocolEncoderCameTwee* instance = malloc(sizeof(SubGhzProtocolEncoderCameTwee));
  86. instance->base.protocol = &subghz_protocol_came_twee;
  87. instance->generic.protocol_name = instance->base.protocol->name;
  88. instance->encoder.repeat = 10;
  89. instance->encoder.size_upload = 1536; //max upload 92*14 = 1288 !!!!
  90. instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
  91. instance->encoder.is_runing = false;
  92. return instance;
  93. }
  94. void subghz_protocol_encoder_came_twee_free(void* context) {
  95. furi_assert(context);
  96. SubGhzProtocolEncoderCameTwee* instance = context;
  97. free(instance->encoder.upload);
  98. free(instance);
  99. }
  100. static LevelDuration
  101. subghz_protocol_encoder_came_twee_add_duration_to_upload(ManchesterEncoderResult result) {
  102. LevelDuration data = {.duration = 0, .level = 0};
  103. switch(result) {
  104. case ManchesterEncoderResultShortLow:
  105. data.duration = subghz_protocol_came_twee_const.te_short;
  106. data.level = false;
  107. break;
  108. case ManchesterEncoderResultLongLow:
  109. data.duration = subghz_protocol_came_twee_const.te_long;
  110. data.level = false;
  111. break;
  112. case ManchesterEncoderResultLongHigh:
  113. data.duration = subghz_protocol_came_twee_const.te_long;
  114. data.level = true;
  115. break;
  116. case ManchesterEncoderResultShortHigh:
  117. data.duration = subghz_protocol_came_twee_const.te_short;
  118. data.level = true;
  119. break;
  120. default:
  121. FURI_LOG_E(TAG, "DO CRASH HERE.");
  122. furi_crash(NULL);
  123. break;
  124. }
  125. return level_duration_make(data.level, data.duration);
  126. }
  127. static void subghz_protocol_encoder_came_twee_get_upload(SubGhzProtocolEncoderCameTwee* instance) {
  128. furi_assert(instance);
  129. size_t index = 0;
  130. ManchesterEncoderState enc_state;
  131. manchester_encoder_reset(&enc_state);
  132. ManchesterEncoderResult result;
  133. uint64_t temp_parcel = 0x003FFF7200000000; //parcel mask
  134. for(int i = 14; i >= 0; i--) {
  135. temp_parcel = (temp_parcel & 0xFFFFFFFF00000000) |
  136. (instance->generic.serial ^ came_twee_magic_numbers_xor[i]);
  137. for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
  138. if(!manchester_encoder_advance(&enc_state, !bit_read(temp_parcel, i - 1), &result)) {
  139. instance->encoder.upload[index++] =
  140. subghz_protocol_encoder_came_twee_add_duration_to_upload(result);
  141. manchester_encoder_advance(&enc_state, !bit_read(temp_parcel, i - 1), &result);
  142. }
  143. instance->encoder.upload[index++] =
  144. subghz_protocol_encoder_came_twee_add_duration_to_upload(result);
  145. }
  146. instance->encoder.upload[index] = subghz_protocol_encoder_came_twee_add_duration_to_upload(
  147. manchester_encoder_finish(&enc_state));
  148. if(level_duration_get_level(instance->encoder.upload[index])) {
  149. index++;
  150. }
  151. instance->encoder.upload[index++] =
  152. level_duration_make(false, (uint32_t)subghz_protocol_came_twee_const.te_long * 51);
  153. }
  154. instance->encoder.size_upload = index;
  155. }
  156. /** Analysis of received data
  157. *
  158. * @param instance SubGhzProtocolCameTwee instance
  159. */
  160. static void subghz_protocol_came_twee_remote_controller(SubGhzBlockGeneric* instance) {
  161. /* Came Twee 54 bit, rolling code 15 parcels with
  162. * a decreasing counter from 0xE to 0x0
  163. * with originally coded dip switches on the console 10 bit code
  164. *
  165. * 0x003FFF72E04A6FEE
  166. * 0x003FFF72D17B5EDD
  167. * 0x003FFF72C2684DCC
  168. * 0x003FFF72B3193CBB
  169. * 0x003FFF72A40E2BAA
  170. * 0x003FFF72953F1A99
  171. * 0x003FFF72862C0988
  172. * 0x003FFF7277DDF877
  173. * 0x003FFF7268C2E766
  174. * 0x003FFF7259F3D655
  175. * 0x003FFF724AE0C544
  176. * 0x003FFF723B91B433
  177. * 0x003FFF722C86A322
  178. * 0x003FFF721DB79211
  179. * 0x003FFF720EA48100
  180. *
  181. * decryption
  182. * the last 32 bits, do XOR by the desired number, divide the result by 4,
  183. * convert the first 16 bits of the resulting 32-bit number to bin and do
  184. * bit-by-bit mirroring, adding up to 10 bits
  185. *
  186. * Example
  187. * Step 1. 0x003FFF721DB79211 => 0x1DB79211
  188. * Step 4. 0x1DB79211 xor 0x1D1D1D11 => 0x00AA8F00
  189. * Step 4. 0x00AA8F00 / 4 => 0x002AA3C0
  190. * Step 5. 0x002AA3C0 => 0x002A
  191. * Step 6. 0x002A bin => b101010
  192. * Step 7. b101010 => b0101010000
  193. * Step 8. b0101010000 => (Dip) Off ON Off ON Off ON Off Off Off Off
  194. */
  195. uint8_t cnt_parcel = (uint8_t)(instance->data & 0xF);
  196. uint32_t data = (uint32_t)(instance->data & 0x0FFFFFFFF);
  197. data = (data ^ came_twee_magic_numbers_xor[cnt_parcel]);
  198. instance->serial = data;
  199. data /= 4;
  200. instance->btn = (data >> 4) & 0x0F;
  201. data >>= 16;
  202. data = (uint16_t)subghz_protocol_blocks_reverse_key(data, 16);
  203. instance->cnt = data >> 6;
  204. }
  205. bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) {
  206. furi_assert(context);
  207. SubGhzProtocolEncoderCameTwee* instance = context;
  208. bool res = false;
  209. do {
  210. if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
  211. FURI_LOG_E(TAG, "Deserialize error");
  212. break;
  213. }
  214. //optional parameter parameter
  215. flipper_format_read_uint32(
  216. flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
  217. subghz_protocol_came_twee_remote_controller(&instance->generic);
  218. subghz_protocol_encoder_came_twee_get_upload(instance);
  219. instance->encoder.is_runing = true;
  220. res = true;
  221. } while(false);
  222. return res;
  223. }
  224. void subghz_protocol_encoder_came_twee_stop(void* context) {
  225. SubGhzProtocolEncoderCameTwee* instance = context;
  226. instance->encoder.is_runing = false;
  227. }
  228. LevelDuration subghz_protocol_encoder_came_twee_yield(void* context) {
  229. SubGhzProtocolEncoderCameTwee* instance = context;
  230. if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) {
  231. instance->encoder.is_runing = false;
  232. return level_duration_reset();
  233. }
  234. LevelDuration ret = instance->encoder.upload[instance->encoder.front];
  235. if(++instance->encoder.front == instance->encoder.size_upload) {
  236. instance->encoder.repeat--;
  237. instance->encoder.front = 0;
  238. }
  239. return ret;
  240. }
  241. void* subghz_protocol_decoder_came_twee_alloc(SubGhzEnvironment* environment) {
  242. SubGhzProtocolDecoderCameTwee* instance = malloc(sizeof(SubGhzProtocolDecoderCameTwee));
  243. instance->base.protocol = &subghz_protocol_came_twee;
  244. instance->generic.protocol_name = instance->base.protocol->name;
  245. return instance;
  246. }
  247. void subghz_protocol_decoder_came_twee_free(void* context) {
  248. furi_assert(context);
  249. SubGhzProtocolDecoderCameTwee* instance = context;
  250. free(instance);
  251. }
  252. void subghz_protocol_decoder_came_twee_reset(void* context) {
  253. furi_assert(context);
  254. SubGhzProtocolDecoderCameTwee* instance = context;
  255. instance->decoder.parser_step = CameTweeDecoderStepReset;
  256. manchester_advance(
  257. instance->manchester_saved_state,
  258. ManchesterEventReset,
  259. &instance->manchester_saved_state,
  260. NULL);
  261. }
  262. void subghz_protocol_decoder_came_twee_feed(void* context, bool level, uint32_t duration) {
  263. furi_assert(context);
  264. SubGhzProtocolDecoderCameTwee* instance = context;
  265. ManchesterEvent event = ManchesterEventReset;
  266. switch(instance->decoder.parser_step) {
  267. case CameTweeDecoderStepReset:
  268. if((!level) && (DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long * 51) <
  269. subghz_protocol_came_twee_const.te_delta * 20)) {
  270. //Found header CAME
  271. instance->decoder.parser_step = CameTweeDecoderStepDecoderData;
  272. instance->decoder.decode_data = 0;
  273. instance->decoder.decode_count_bit = 0;
  274. manchester_advance(
  275. instance->manchester_saved_state,
  276. ManchesterEventLongLow,
  277. &instance->manchester_saved_state,
  278. NULL);
  279. manchester_advance(
  280. instance->manchester_saved_state,
  281. ManchesterEventLongHigh,
  282. &instance->manchester_saved_state,
  283. NULL);
  284. manchester_advance(
  285. instance->manchester_saved_state,
  286. ManchesterEventShortLow,
  287. &instance->manchester_saved_state,
  288. NULL);
  289. }
  290. break;
  291. case CameTweeDecoderStepDecoderData:
  292. if(!level) {
  293. if(DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_short) <
  294. subghz_protocol_came_twee_const.te_delta) {
  295. event = ManchesterEventShortLow;
  296. } else if(
  297. DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long) <
  298. subghz_protocol_came_twee_const.te_delta) {
  299. event = ManchesterEventLongLow;
  300. } else if(
  301. duration >= (subghz_protocol_came_twee_const.te_long * 2 +
  302. subghz_protocol_came_twee_const.te_delta)) {
  303. if(instance->decoder.decode_count_bit >=
  304. subghz_protocol_came_twee_const.min_count_bit_for_found) {
  305. instance->generic.data = instance->decoder.decode_data;
  306. instance->generic.data_count_bit = instance->decoder.decode_count_bit;
  307. if(instance->base.callback)
  308. instance->base.callback(&instance->base, instance->base.context);
  309. }
  310. instance->decoder.decode_data = 0;
  311. instance->decoder.decode_count_bit = 0;
  312. manchester_advance(
  313. instance->manchester_saved_state,
  314. ManchesterEventLongLow,
  315. &instance->manchester_saved_state,
  316. NULL);
  317. manchester_advance(
  318. instance->manchester_saved_state,
  319. ManchesterEventLongHigh,
  320. &instance->manchester_saved_state,
  321. NULL);
  322. manchester_advance(
  323. instance->manchester_saved_state,
  324. ManchesterEventShortLow,
  325. &instance->manchester_saved_state,
  326. NULL);
  327. } else {
  328. instance->decoder.parser_step = CameTweeDecoderStepReset;
  329. }
  330. } else {
  331. if(DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_short) <
  332. subghz_protocol_came_twee_const.te_delta) {
  333. event = ManchesterEventShortHigh;
  334. } else if(
  335. DURATION_DIFF(duration, subghz_protocol_came_twee_const.te_long) <
  336. subghz_protocol_came_twee_const.te_delta) {
  337. event = ManchesterEventLongHigh;
  338. } else {
  339. instance->decoder.parser_step = CameTweeDecoderStepReset;
  340. }
  341. }
  342. if(event != ManchesterEventReset) {
  343. bool data;
  344. bool data_ok = manchester_advance(
  345. instance->manchester_saved_state, event, &instance->manchester_saved_state, &data);
  346. if(data_ok) {
  347. instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data;
  348. instance->decoder.decode_count_bit++;
  349. }
  350. }
  351. break;
  352. }
  353. }
  354. uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context) {
  355. furi_assert(context);
  356. SubGhzProtocolDecoderCameTwee* instance = context;
  357. return subghz_protocol_blocks_get_hash_data(
  358. &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
  359. }
  360. bool subghz_protocol_decoder_came_twee_serialize(
  361. void* context,
  362. FlipperFormat* flipper_format,
  363. uint32_t frequency,
  364. FuriHalSubGhzPreset preset) {
  365. furi_assert(context);
  366. SubGhzProtocolDecoderCameTwee* instance = context;
  367. return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
  368. }
  369. bool subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) {
  370. furi_assert(context);
  371. SubGhzProtocolDecoderCameTwee* instance = context;
  372. return subghz_block_generic_deserialize(&instance->generic, flipper_format);
  373. }
  374. void subghz_protocol_decoder_came_twee_get_string(void* context, string_t output) {
  375. furi_assert(context);
  376. SubGhzProtocolDecoderCameTwee* instance = context;
  377. subghz_protocol_came_twee_remote_controller(&instance->generic);
  378. uint32_t code_found_hi = instance->generic.data >> 32;
  379. uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff;
  380. string_cat_printf(
  381. output,
  382. "%s %dbit\r\n"
  383. "Key:0x%lX%08lX\r\n"
  384. "Btn:%lX\r\n"
  385. "DIP:" DIP_PATTERN "\r\n",
  386. instance->generic.protocol_name,
  387. instance->generic.data_count_bit,
  388. code_found_hi,
  389. code_found_lo,
  390. instance->generic.btn,
  391. CNT_TO_DIP(instance->generic.cnt));
  392. }