subghz_txrx.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. #include "subghz_txrx_i.h"
  2. #include <lib/subghz/protocols/protocol_items.h>
  3. #define TAG "SubGhz"
  4. SubGhzTxRx* subghz_txrx_alloc() {
  5. SubGhzTxRx* instance = malloc(sizeof(SubGhzTxRx));
  6. instance->setting = subghz_setting_alloc();
  7. subghz_setting_load(instance->setting, EXT_PATH("subghz/assets/setting_user"));
  8. instance->preset = malloc(sizeof(SubGhzRadioPreset));
  9. instance->preset->name = furi_string_alloc();
  10. subghz_txrx_set_preset(
  11. instance, "AM650", subghz_setting_get_default_frequency(instance->setting), NULL, 0);
  12. instance->txrx_state = SubGhzTxRxStateSleep;
  13. subghz_txrx_hopper_set_state(instance, SubGhzHopperStateOFF);
  14. subghz_txrx_speaker_set_state(instance, SubGhzSpeakerStateDisable);
  15. instance->worker = subghz_worker_alloc();
  16. instance->fff_data = flipper_format_string_alloc();
  17. instance->environment = subghz_environment_alloc();
  18. instance->is_database_loaded = subghz_environment_load_keystore(
  19. instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes"));
  20. subghz_environment_load_keystore(
  21. instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user"));
  22. subghz_environment_set_came_atomo_rainbow_table_file_name(
  23. instance->environment, EXT_PATH("subghz/assets/came_atomo"));
  24. subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
  25. instance->environment, EXT_PATH("subghz/assets/alutech_at_4n"));
  26. subghz_environment_set_nice_flor_s_rainbow_table_file_name(
  27. instance->environment, EXT_PATH("subghz/assets/nice_flor_s"));
  28. subghz_environment_set_protocol_registry(
  29. instance->environment, (void*)&subghz_protocol_registry);
  30. instance->receiver = subghz_receiver_alloc_init(instance->environment);
  31. subghz_worker_set_overrun_callback(
  32. instance->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset);
  33. subghz_worker_set_pair_callback(
  34. instance->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode);
  35. subghz_worker_set_context(instance->worker, instance->receiver);
  36. return instance;
  37. }
  38. void subghz_txrx_free(SubGhzTxRx* instance) {
  39. furi_assert(instance);
  40. subghz_worker_free(instance->worker);
  41. subghz_receiver_free(instance->receiver);
  42. subghz_environment_free(instance->environment);
  43. flipper_format_free(instance->fff_data);
  44. furi_string_free(instance->preset->name);
  45. subghz_setting_free(instance->setting);
  46. free(instance->preset);
  47. free(instance);
  48. }
  49. bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance) {
  50. furi_assert(instance);
  51. return instance->is_database_loaded;
  52. }
  53. void subghz_txrx_set_preset(
  54. SubGhzTxRx* instance,
  55. const char* preset_name,
  56. uint32_t frequency,
  57. uint8_t* preset_data,
  58. size_t preset_data_size) {
  59. furi_assert(instance);
  60. furi_string_set(instance->preset->name, preset_name);
  61. SubGhzRadioPreset* preset = instance->preset;
  62. preset->frequency = frequency;
  63. preset->data = preset_data;
  64. preset->data_size = preset_data_size;
  65. }
  66. const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset) {
  67. UNUSED(instance);
  68. const char* preset_name = "";
  69. if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) {
  70. preset_name = "AM270";
  71. } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) {
  72. preset_name = "AM650";
  73. } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) {
  74. preset_name = "FM238";
  75. } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) {
  76. preset_name = "FM476";
  77. } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) {
  78. preset_name = "CUSTOM";
  79. } else {
  80. FURI_LOG_E(TAG, "Unknown preset");
  81. }
  82. return preset_name;
  83. }
  84. SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance) {
  85. furi_assert(instance);
  86. return *instance->preset;
  87. }
  88. void subghz_txrx_get_frequency_and_modulation(
  89. SubGhzTxRx* instance,
  90. FuriString* frequency,
  91. FuriString* modulation) {
  92. furi_assert(instance);
  93. SubGhzRadioPreset* preset = instance->preset;
  94. if(frequency != NULL) {
  95. furi_string_printf(
  96. frequency,
  97. "%03ld.%02ld",
  98. preset->frequency / 1000000 % 1000,
  99. preset->frequency / 10000 % 100);
  100. }
  101. if(modulation != NULL) {
  102. furi_string_printf(modulation, "%.2s", furi_string_get_cstr(preset->name));
  103. }
  104. }
  105. static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) {
  106. furi_assert(instance);
  107. furi_hal_subghz_reset();
  108. furi_hal_subghz_idle();
  109. furi_hal_subghz_load_custom_preset(preset_data);
  110. furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
  111. instance->txrx_state = SubGhzTxRxStateIDLE;
  112. }
  113. static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) {
  114. furi_assert(instance);
  115. if(!furi_hal_subghz_is_frequency_valid(frequency)) {
  116. furi_crash("SubGhz: Incorrect RX frequency.");
  117. }
  118. furi_assert(
  119. instance->txrx_state != SubGhzTxRxStateRx && instance->txrx_state != SubGhzTxRxStateSleep);
  120. furi_hal_subghz_idle();
  121. uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
  122. furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
  123. furi_hal_subghz_flush_rx();
  124. subghz_txrx_speaker_on(instance);
  125. furi_hal_subghz_rx();
  126. furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, instance->worker);
  127. subghz_worker_start(instance->worker);
  128. instance->txrx_state = SubGhzTxRxStateRx;
  129. return value;
  130. }
  131. static void subghz_txrx_idle(SubGhzTxRx* instance) {
  132. furi_assert(instance);
  133. furi_assert(instance->txrx_state != SubGhzTxRxStateSleep);
  134. furi_hal_subghz_idle();
  135. subghz_txrx_speaker_off(instance);
  136. instance->txrx_state = SubGhzTxRxStateIDLE;
  137. }
  138. static void subghz_txrx_rx_end(SubGhzTxRx* instance) {
  139. furi_assert(instance);
  140. furi_assert(instance->txrx_state == SubGhzTxRxStateRx);
  141. if(subghz_worker_is_running(instance->worker)) {
  142. subghz_worker_stop(instance->worker);
  143. furi_hal_subghz_stop_async_rx();
  144. }
  145. furi_hal_subghz_idle();
  146. subghz_txrx_speaker_off(instance);
  147. instance->txrx_state = SubGhzTxRxStateIDLE;
  148. }
  149. void subghz_txrx_sleep(SubGhzTxRx* instance) {
  150. furi_assert(instance);
  151. furi_hal_subghz_sleep();
  152. instance->txrx_state = SubGhzTxRxStateSleep;
  153. }
  154. static bool subghz_txrx_tx(SubGhzTxRx* instance, uint32_t frequency) {
  155. furi_assert(instance);
  156. if(!furi_hal_subghz_is_frequency_valid(frequency)) {
  157. furi_crash("SubGhz: Incorrect TX frequency.");
  158. }
  159. furi_assert(instance->txrx_state != SubGhzTxRxStateSleep);
  160. furi_hal_subghz_idle();
  161. furi_hal_subghz_set_frequency_and_path(frequency);
  162. furi_hal_gpio_write(&gpio_cc1101_g0, false);
  163. furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  164. bool ret = furi_hal_subghz_tx();
  165. if(ret) {
  166. subghz_txrx_speaker_on(instance);
  167. instance->txrx_state = SubGhzTxRxStateTx;
  168. }
  169. return ret;
  170. }
  171. SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format) {
  172. furi_assert(instance);
  173. furi_assert(flipper_format);
  174. subghz_txrx_stop(instance);
  175. SubGhzTxRxStartTxState ret = SubGhzTxRxStartTxStateErrorParserOthers;
  176. FuriString* temp_str = furi_string_alloc();
  177. uint32_t repeat = 200;
  178. do {
  179. if(!flipper_format_rewind(flipper_format)) {
  180. FURI_LOG_E(TAG, "Rewind error");
  181. break;
  182. }
  183. if(!flipper_format_read_string(flipper_format, "Protocol", temp_str)) {
  184. FURI_LOG_E(TAG, "Missing Protocol");
  185. break;
  186. }
  187. if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) {
  188. FURI_LOG_E(TAG, "Unable Repeat");
  189. break;
  190. }
  191. ret = SubGhzTxRxStartTxStateOk;
  192. SubGhzRadioPreset* preset = instance->preset;
  193. instance->transmitter =
  194. subghz_transmitter_alloc_init(instance->environment, furi_string_get_cstr(temp_str));
  195. if(instance->transmitter) {
  196. if(subghz_transmitter_deserialize(instance->transmitter, flipper_format) ==
  197. SubGhzProtocolStatusOk) {
  198. if(strcmp(furi_string_get_cstr(preset->name), "") != 0) {
  199. subghz_txrx_begin(
  200. instance,
  201. subghz_setting_get_preset_data_by_name(
  202. instance->setting, furi_string_get_cstr(preset->name)));
  203. if(preset->frequency) {
  204. if(!subghz_txrx_tx(instance, preset->frequency)) {
  205. FURI_LOG_E(TAG, "Only Rx");
  206. ret = SubGhzTxRxStartTxStateErrorOnlyRx;
  207. }
  208. } else {
  209. ret = SubGhzTxRxStartTxStateErrorParserOthers;
  210. }
  211. } else {
  212. FURI_LOG_E(
  213. TAG, "Unknown name preset \" %s \"", furi_string_get_cstr(preset->name));
  214. ret = SubGhzTxRxStartTxStateErrorParserOthers;
  215. }
  216. if(ret == SubGhzTxRxStartTxStateOk) {
  217. //Start TX
  218. furi_hal_subghz_start_async_tx(
  219. subghz_transmitter_yield, instance->transmitter);
  220. }
  221. } else {
  222. ret = SubGhzTxRxStartTxStateErrorParserOthers;
  223. }
  224. } else {
  225. ret = SubGhzTxRxStartTxStateErrorParserOthers;
  226. }
  227. if(ret != SubGhzTxRxStartTxStateOk) {
  228. subghz_transmitter_free(instance->transmitter);
  229. if(instance->txrx_state != SubGhzTxRxStateIDLE) {
  230. subghz_txrx_idle(instance);
  231. }
  232. }
  233. } while(false);
  234. furi_string_free(temp_str);
  235. return ret;
  236. }
  237. void subghz_txrx_rx_start(SubGhzTxRx* instance) {
  238. furi_assert(instance);
  239. subghz_txrx_stop(instance);
  240. subghz_txrx_begin(
  241. instance,
  242. subghz_setting_get_preset_data_by_name(
  243. subghz_txrx_get_setting(instance), furi_string_get_cstr(instance->preset->name)));
  244. subghz_txrx_rx(instance, instance->preset->frequency);
  245. }
  246. void subghz_txrx_set_need_save_callback(
  247. SubGhzTxRx* instance,
  248. SubGhzTxRxNeedSaveCallback callback,
  249. void* context) {
  250. furi_assert(instance);
  251. instance->need_save_callback = callback;
  252. instance->need_save_context = context;
  253. }
  254. static void subghz_txrx_tx_stop(SubGhzTxRx* instance) {
  255. furi_assert(instance);
  256. furi_assert(instance->txrx_state == SubGhzTxRxStateTx);
  257. //Stop TX
  258. furi_hal_subghz_stop_async_tx();
  259. subghz_transmitter_stop(instance->transmitter);
  260. subghz_transmitter_free(instance->transmitter);
  261. //if protocol dynamic then we save the last upload
  262. if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) {
  263. if(instance->need_save_callback) {
  264. instance->need_save_callback(instance->need_save_context);
  265. }
  266. }
  267. subghz_txrx_idle(instance);
  268. subghz_txrx_speaker_off(instance);
  269. //Todo: Show message
  270. // notification_message(notifications, &sequence_reset_red);
  271. }
  272. FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) {
  273. furi_assert(instance);
  274. return instance->fff_data;
  275. }
  276. SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance) {
  277. furi_assert(instance);
  278. return instance->setting;
  279. }
  280. void subghz_txrx_stop(SubGhzTxRx* instance) {
  281. furi_assert(instance);
  282. switch(instance->txrx_state) {
  283. case SubGhzTxRxStateTx:
  284. subghz_txrx_tx_stop(instance);
  285. subghz_txrx_speaker_unmute(instance);
  286. break;
  287. case SubGhzTxRxStateRx:
  288. subghz_txrx_rx_end(instance);
  289. subghz_txrx_speaker_mute(instance);
  290. break;
  291. default:
  292. break;
  293. }
  294. }
  295. void subghz_txrx_hopper_update(SubGhzTxRx* instance) {
  296. furi_assert(instance);
  297. switch(instance->hopper_state) {
  298. case SubGhzHopperStateOFF:
  299. case SubGhzHopperStatePause:
  300. return;
  301. case SubGhzHopperStateRSSITimeOut:
  302. if(instance->hopper_timeout != 0) {
  303. instance->hopper_timeout--;
  304. return;
  305. }
  306. break;
  307. default:
  308. break;
  309. }
  310. float rssi = -127.0f;
  311. if(instance->hopper_state != SubGhzHopperStateRSSITimeOut) {
  312. // See RSSI Calculation timings in CC1101 17.3 RSSI
  313. rssi = furi_hal_subghz_get_rssi();
  314. // Stay if RSSI is high enough
  315. if(rssi > -90.0f) {
  316. instance->hopper_timeout = 10;
  317. instance->hopper_state = SubGhzHopperStateRSSITimeOut;
  318. return;
  319. }
  320. } else {
  321. instance->hopper_state = SubGhzHopperStateRunnig;
  322. }
  323. // Select next frequency
  324. if(instance->hopper_idx_frequency <
  325. subghz_setting_get_hopper_frequency_count(instance->setting) - 1) {
  326. instance->hopper_idx_frequency++;
  327. } else {
  328. instance->hopper_idx_frequency = 0;
  329. }
  330. if(instance->txrx_state == SubGhzTxRxStateRx) {
  331. subghz_txrx_rx_end(instance);
  332. };
  333. if(instance->txrx_state == SubGhzTxRxStateIDLE) {
  334. subghz_receiver_reset(instance->receiver);
  335. instance->preset->frequency =
  336. subghz_setting_get_hopper_frequency(instance->setting, instance->hopper_idx_frequency);
  337. subghz_txrx_rx(instance, instance->preset->frequency);
  338. }
  339. }
  340. SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance) {
  341. furi_assert(instance);
  342. return instance->hopper_state;
  343. }
  344. void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state) {
  345. furi_assert(instance);
  346. instance->hopper_state = state;
  347. }
  348. void subghz_txrx_hopper_unpause(SubGhzTxRx* instance) {
  349. furi_assert(instance);
  350. if(instance->hopper_state == SubGhzHopperStatePause) {
  351. instance->hopper_state = SubGhzHopperStateRunnig;
  352. }
  353. }
  354. void subghz_txrx_hopper_pause(SubGhzTxRx* instance) {
  355. furi_assert(instance);
  356. if(instance->hopper_state == SubGhzHopperStateRunnig) {
  357. instance->hopper_state = SubGhzHopperStatePause;
  358. }
  359. }
  360. void subghz_txrx_speaker_on(SubGhzTxRx* instance) {
  361. furi_assert(instance);
  362. if(instance->speaker_state == SubGhzSpeakerStateEnable) {
  363. if(furi_hal_speaker_acquire(30)) {
  364. furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
  365. } else {
  366. instance->speaker_state = SubGhzSpeakerStateDisable;
  367. }
  368. }
  369. }
  370. void subghz_txrx_speaker_off(SubGhzTxRx* instance) {
  371. furi_assert(instance);
  372. if(instance->speaker_state != SubGhzSpeakerStateDisable) {
  373. if(furi_hal_speaker_is_mine()) {
  374. furi_hal_subghz_set_async_mirror_pin(NULL);
  375. furi_hal_speaker_release();
  376. if(instance->speaker_state == SubGhzSpeakerStateShutdown)
  377. instance->speaker_state = SubGhzSpeakerStateDisable;
  378. }
  379. }
  380. }
  381. void subghz_txrx_speaker_mute(SubGhzTxRx* instance) {
  382. furi_assert(instance);
  383. if(instance->speaker_state == SubGhzSpeakerStateEnable) {
  384. if(furi_hal_speaker_is_mine()) {
  385. furi_hal_subghz_set_async_mirror_pin(NULL);
  386. }
  387. }
  388. }
  389. void subghz_txrx_speaker_unmute(SubGhzTxRx* instance) {
  390. furi_assert(instance);
  391. if(instance->speaker_state == SubGhzSpeakerStateEnable) {
  392. if(furi_hal_speaker_is_mine()) {
  393. furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
  394. }
  395. }
  396. }
  397. void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state) {
  398. furi_assert(instance);
  399. instance->speaker_state = state;
  400. }
  401. SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance) {
  402. furi_assert(instance);
  403. return instance->speaker_state;
  404. }
  405. bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol) {
  406. furi_assert(instance);
  407. furi_assert(name_protocol);
  408. bool res = false;
  409. instance->decoder_result =
  410. subghz_receiver_search_decoder_base_by_name(instance->receiver, name_protocol);
  411. if(instance->decoder_result) {
  412. res = true;
  413. }
  414. return res;
  415. }
  416. SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance) {
  417. furi_assert(instance);
  418. return instance->decoder_result;
  419. }
  420. bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance) {
  421. furi_assert(instance);
  422. return (
  423. (instance->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) ==
  424. SubGhzProtocolFlag_Save);
  425. }
  426. bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type) {
  427. furi_assert(instance);
  428. const SubGhzProtocol* protocol = instance->decoder_result->protocol;
  429. if(check_type) {
  430. return (
  431. ((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) &&
  432. protocol->encoder->deserialize && protocol->type == SubGhzProtocolTypeStatic);
  433. }
  434. return (
  435. ((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) &&
  436. protocol->encoder->deserialize);
  437. }
  438. void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter) {
  439. furi_assert(instance);
  440. subghz_receiver_set_filter(instance->receiver, filter);
  441. }
  442. void subghz_txrx_set_rx_calback(
  443. SubGhzTxRx* instance,
  444. SubGhzReceiverCallback callback,
  445. void* context) {
  446. subghz_receiver_set_rx_callback(instance->receiver, callback, context);
  447. }
  448. void subghz_txrx_set_raw_file_encoder_worker_callback_end(
  449. SubGhzTxRx* instance,
  450. SubGhzProtocolEncoderRAWCallbackEnd callback,
  451. void* context) {
  452. subghz_protocol_raw_file_encoder_worker_set_callback_end(
  453. (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance(instance->transmitter),
  454. callback,
  455. context);
  456. }