subghz_setting.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. #include "subghz_setting.h"
  2. #include "subghz_i.h"
  3. #include <furi.h>
  4. #include <m-list.h>
  5. #include "furi_hal_subghz_configs.h"
  6. #define TAG "SubGhzSetting"
  7. #define SUBGHZ_SETTING_FILE_TYPE "Flipper SubGhz Setting File"
  8. #define SUBGHZ_SETTING_FILE_VERSION 1
  9. #define FREQUENCY_FLAG_DEFAULT (1 << 31)
  10. #define FREQUENCY_MASK (0xFFFFFFFF ^ FREQUENCY_FLAG_DEFAULT)
  11. /* Default */
  12. static const uint32_t subghz_frequency_list[] = {
  13. /* 300 - 348 */
  14. 300000000,
  15. 303875000,
  16. 304250000,
  17. 310000000,
  18. 315000000,
  19. 318000000,
  20. /* 387 - 464 */
  21. 390000000,
  22. 418000000,
  23. 433075000, /* LPD433 first */
  24. 433420000,
  25. 433920000 | FREQUENCY_FLAG_DEFAULT, /* LPD433 mid */
  26. 434420000,
  27. 434775000, /* LPD433 last channels */
  28. 438900000,
  29. /* 779 - 928 */
  30. 868350000,
  31. 915000000,
  32. 925000000,
  33. 0,
  34. };
  35. static const uint32_t subghz_hopper_frequency_list[] = {
  36. 310000000,
  37. 315000000,
  38. 318000000,
  39. 390000000,
  40. 433920000,
  41. 868350000,
  42. 0,
  43. };
  44. /* Europe and Russia */
  45. static const uint32_t subghz_frequency_list_region_eu_ru[] = {
  46. /* 300 - 348 */
  47. 300000000,
  48. 303875000,
  49. 304250000,
  50. 310000000,
  51. 315000000,
  52. 318000000,
  53. /* 387 - 464 */
  54. 390000000,
  55. 418000000,
  56. 433075000, /* LPD433 first */
  57. 433420000,
  58. 433920000 | FREQUENCY_FLAG_DEFAULT, /* LPD433 mid */
  59. 434420000,
  60. 434775000, /* LPD433 last channels */
  61. 438900000,
  62. /* 779 - 928 */
  63. 868350000,
  64. 915000000,
  65. 925000000,
  66. 0,
  67. };
  68. static const uint32_t subghz_hopper_frequency_list_region_eu_ru[] = {
  69. 310000000,
  70. 315000000,
  71. 318000000,
  72. 390000000,
  73. 433920000,
  74. 868350000,
  75. 0,
  76. };
  77. /* Region 0 */
  78. static const uint32_t subghz_frequency_list_region_us_ca_au[] = {
  79. /* 300 - 348 */
  80. 300000000,
  81. 303875000,
  82. 304250000,
  83. 310000000,
  84. 315000000,
  85. 318000000,
  86. /* 387 - 464 */
  87. 390000000,
  88. 418000000,
  89. 433075000, /* LPD433 first */
  90. 433420000,
  91. 433920000 | FREQUENCY_FLAG_DEFAULT, /* LPD433 mid */
  92. 434420000,
  93. 434775000, /* LPD433 last channels */
  94. 438900000,
  95. /* 779 - 928 */
  96. 868350000,
  97. 915000000,
  98. 925000000,
  99. 0,
  100. };
  101. static const uint32_t subghz_hopper_frequency_list_region_us_ca_au[] = {
  102. 310000000,
  103. 315000000,
  104. 318000000,
  105. 390000000,
  106. 433920000,
  107. 868350000,
  108. 0,
  109. };
  110. static const uint32_t subghz_frequency_list_region_jp[] = {
  111. /* 300 - 348 */
  112. 300000000,
  113. 303875000,
  114. 304250000,
  115. 310000000,
  116. 315000000,
  117. 318000000,
  118. /* 387 - 464 */
  119. 390000000,
  120. 418000000,
  121. 433075000, /* LPD433 first */
  122. 433420000,
  123. 433920000 | FREQUENCY_FLAG_DEFAULT, /* LPD433 mid */
  124. 434420000,
  125. 434775000, /* LPD433 last channels */
  126. 438900000,
  127. /* 779 - 928 */
  128. 868350000,
  129. 915000000,
  130. 925000000,
  131. 0,
  132. };
  133. static const uint32_t subghz_hopper_frequency_list_region_jp[] = {
  134. 310000000,
  135. 315000000,
  136. 318000000,
  137. 390000000,
  138. 433920000,
  139. 868350000,
  140. 0,
  141. };
  142. typedef struct {
  143. string_t custom_preset_name;
  144. uint8_t* custom_preset_data;
  145. size_t custom_preset_data_size;
  146. } SubGhzSettingCustomPresetItem;
  147. ARRAY_DEF(SubGhzSettingCustomPresetItemArray, SubGhzSettingCustomPresetItem, M_POD_OPLIST)
  148. #define M_OPL_SubGhzSettingCustomPresetItemArray_t() \
  149. ARRAY_OPLIST(SubGhzSettingCustomPresetItemArray, M_POD_OPLIST)
  150. LIST_DEF(FrequencyList, uint32_t)
  151. #define M_OPL_FrequencyList_t() LIST_OPLIST(FrequencyList)
  152. typedef struct {
  153. SubGhzSettingCustomPresetItemArray_t data;
  154. } SubGhzSettingCustomPresetStruct;
  155. struct SubGhzSetting {
  156. FrequencyList_t frequencies;
  157. FrequencyList_t hopper_frequencies;
  158. SubGhzSettingCustomPresetStruct* preset;
  159. };
  160. SubGhzSetting* subghz_setting_alloc(void) {
  161. SubGhzSetting* instance = malloc(sizeof(SubGhzSetting));
  162. FrequencyList_init(instance->frequencies);
  163. FrequencyList_init(instance->hopper_frequencies);
  164. instance->preset = malloc(sizeof(SubGhzSettingCustomPresetStruct));
  165. SubGhzSettingCustomPresetItemArray_init(instance->preset->data);
  166. return instance;
  167. }
  168. static void subghz_setting_preset_reset(SubGhzSetting* instance) {
  169. for
  170. M_EACH(item, instance->preset->data, SubGhzSettingCustomPresetItemArray_t) {
  171. string_clear(item->custom_preset_name);
  172. free(item->custom_preset_data);
  173. }
  174. SubGhzSettingCustomPresetItemArray_reset(instance->preset->data);
  175. }
  176. void subghz_setting_free(SubGhzSetting* instance) {
  177. furi_assert(instance);
  178. FrequencyList_clear(instance->frequencies);
  179. FrequencyList_clear(instance->hopper_frequencies);
  180. for
  181. M_EACH(item, instance->preset->data, SubGhzSettingCustomPresetItemArray_t) {
  182. string_clear(item->custom_preset_name);
  183. free(item->custom_preset_data);
  184. }
  185. SubGhzSettingCustomPresetItemArray_clear(instance->preset->data);
  186. free(instance->preset);
  187. free(instance);
  188. }
  189. static void subghz_setting_load_default_preset(
  190. SubGhzSetting* instance,
  191. const char* preset_name,
  192. const uint8_t* preset_data,
  193. const uint8_t preset_pa_table[8]) {
  194. furi_assert(instance);
  195. furi_assert(preset_data);
  196. uint32_t preset_data_count = 0;
  197. SubGhzSettingCustomPresetItem* item =
  198. SubGhzSettingCustomPresetItemArray_push_raw(instance->preset->data);
  199. string_init(item->custom_preset_name);
  200. string_set(item->custom_preset_name, preset_name);
  201. while(preset_data[preset_data_count]) {
  202. preset_data_count += 2;
  203. }
  204. preset_data_count += 2;
  205. item->custom_preset_data_size = sizeof(uint8_t) * preset_data_count + sizeof(uint8_t) * 8;
  206. item->custom_preset_data = malloc(item->custom_preset_data_size);
  207. //load preset register
  208. memcpy(&item->custom_preset_data[0], &preset_data[0], preset_data_count);
  209. //load pa table
  210. memcpy(&item->custom_preset_data[preset_data_count], &preset_pa_table[0], 8);
  211. }
  212. static void subghz_setting_load_default_region(
  213. SubGhzSetting* instance,
  214. const uint32_t frequencies[],
  215. const uint32_t hopper_frequencies[]) {
  216. furi_assert(instance);
  217. FrequencyList_reset(instance->frequencies);
  218. FrequencyList_reset(instance->hopper_frequencies);
  219. subghz_setting_preset_reset(instance);
  220. while(*frequencies) {
  221. FrequencyList_push_back(instance->frequencies, *frequencies);
  222. frequencies++;
  223. }
  224. while(*hopper_frequencies) {
  225. FrequencyList_push_back(instance->hopper_frequencies, *hopper_frequencies);
  226. hopper_frequencies++;
  227. }
  228. subghz_setting_load_default_preset(
  229. instance,
  230. "AM270",
  231. (uint8_t*)furi_hal_subghz_preset_ook_270khz_async_regs,
  232. furi_hal_subghz_preset_ook_async_patable);
  233. subghz_setting_load_default_preset(
  234. instance,
  235. "AM650",
  236. (uint8_t*)furi_hal_subghz_preset_ook_650khz_async_regs,
  237. furi_hal_subghz_preset_ook_async_patable);
  238. subghz_setting_load_default_preset(
  239. instance,
  240. "FM238",
  241. (uint8_t*)furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs,
  242. furi_hal_subghz_preset_2fsk_async_patable);
  243. subghz_setting_load_default_preset(
  244. instance,
  245. "FM476",
  246. (uint8_t*)furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs,
  247. furi_hal_subghz_preset_2fsk_async_patable);
  248. }
  249. void subghz_setting_load_default(SubGhzSetting* instance) {
  250. switch(furi_hal_version_get_hw_region()) {
  251. case FuriHalVersionRegionEuRu:
  252. subghz_setting_load_default_region(
  253. instance,
  254. subghz_frequency_list_region_eu_ru,
  255. subghz_hopper_frequency_list_region_eu_ru);
  256. break;
  257. case FuriHalVersionRegionUsCaAu:
  258. subghz_setting_load_default_region(
  259. instance,
  260. subghz_frequency_list_region_us_ca_au,
  261. subghz_hopper_frequency_list_region_us_ca_au);
  262. break;
  263. case FuriHalVersionRegionJp:
  264. subghz_setting_load_default_region(
  265. instance, subghz_frequency_list_region_jp, subghz_hopper_frequency_list_region_jp);
  266. break;
  267. default:
  268. subghz_setting_load_default_region(
  269. instance, subghz_frequency_list, subghz_hopper_frequency_list);
  270. break;
  271. }
  272. }
  273. void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
  274. furi_assert(instance);
  275. Storage* storage = furi_record_open(RECORD_STORAGE);
  276. FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
  277. string_t temp_str;
  278. string_init(temp_str);
  279. uint32_t temp_data32;
  280. bool temp_bool;
  281. subghz_setting_load_default(instance);
  282. if(file_path) {
  283. do {
  284. if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
  285. FURI_LOG_E(TAG, "Error open file %s", file_path);
  286. break;
  287. }
  288. if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
  289. FURI_LOG_E(TAG, "Missing or incorrect header");
  290. break;
  291. }
  292. if((!strcmp(string_get_cstr(temp_str), SUBGHZ_SETTING_FILE_TYPE)) &&
  293. temp_data32 == SUBGHZ_SETTING_FILE_VERSION) {
  294. } else {
  295. FURI_LOG_E(TAG, "Type or version mismatch");
  296. break;
  297. }
  298. // Standard frequencies (optional)
  299. temp_bool = true;
  300. flipper_format_read_bool(fff_data_file, "Add_standard_frequencies", &temp_bool, 1);
  301. if(!temp_bool) {
  302. FURI_LOG_I(TAG, "Removing standard frequencies");
  303. FrequencyList_reset(instance->frequencies);
  304. FrequencyList_reset(instance->hopper_frequencies);
  305. } else {
  306. FURI_LOG_I(TAG, "Keeping standard frequencies");
  307. }
  308. // Load frequencies
  309. if(!flipper_format_rewind(fff_data_file)) {
  310. FURI_LOG_E(TAG, "Rewind error");
  311. break;
  312. }
  313. while(flipper_format_read_uint32(
  314. fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) {
  315. if(furi_hal_subghz_is_frequency_valid(temp_data32)) {
  316. FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32);
  317. FrequencyList_push_back(instance->frequencies, temp_data32);
  318. } else {
  319. FURI_LOG_E(TAG, "Frequency not supported %lu", temp_data32);
  320. }
  321. }
  322. // Load hopper frequencies
  323. if(!flipper_format_rewind(fff_data_file)) {
  324. FURI_LOG_E(TAG, "Rewind error");
  325. break;
  326. }
  327. while(flipper_format_read_uint32(
  328. fff_data_file, "Hopper_frequency", (uint32_t*)&temp_data32, 1)) {
  329. if(furi_hal_subghz_is_frequency_valid(temp_data32)) {
  330. FURI_LOG_I(TAG, "Hopper frequency loaded %lu", temp_data32);
  331. FrequencyList_push_back(instance->hopper_frequencies, temp_data32);
  332. } else {
  333. FURI_LOG_E(TAG, "Hopper frequency not supported %lu", temp_data32);
  334. }
  335. }
  336. // Default frequency (optional)
  337. if(!flipper_format_rewind(fff_data_file)) {
  338. FURI_LOG_E(TAG, "Rewind error");
  339. break;
  340. }
  341. if(flipper_format_read_uint32(fff_data_file, "Default_frequency", &temp_data32, 1)) {
  342. for
  343. M_EACH(frequency, instance->frequencies, FrequencyList_t) {
  344. *frequency &= FREQUENCY_MASK;
  345. if(*frequency == temp_data32) {
  346. *frequency |= FREQUENCY_FLAG_DEFAULT;
  347. }
  348. }
  349. }
  350. // custom preset (optional)
  351. if(!flipper_format_rewind(fff_data_file)) {
  352. FURI_LOG_E(TAG, "Rewind error");
  353. break;
  354. }
  355. while(flipper_format_read_string(fff_data_file, "Custom_preset_name", temp_str)) {
  356. FURI_LOG_I(TAG, "Custom preset loaded %s", string_get_cstr(temp_str));
  357. subghz_setting_load_custom_preset(
  358. instance, string_get_cstr(temp_str), fff_data_file);
  359. }
  360. } while(false);
  361. }
  362. string_clear(temp_str);
  363. flipper_format_free(fff_data_file);
  364. furi_record_close(RECORD_STORAGE);
  365. if(!FrequencyList_size(instance->frequencies) ||
  366. !FrequencyList_size(instance->hopper_frequencies)) {
  367. FURI_LOG_E(TAG, "Error loading user settings, loading default settings");
  368. subghz_setting_load_default(instance);
  369. }
  370. }
  371. size_t subghz_setting_get_frequency_count(SubGhzSetting* instance) {
  372. furi_assert(instance);
  373. return FrequencyList_size(instance->frequencies);
  374. }
  375. size_t subghz_setting_get_hopper_frequency_count(SubGhzSetting* instance) {
  376. furi_assert(instance);
  377. return FrequencyList_size(instance->hopper_frequencies);
  378. }
  379. size_t subghz_setting_get_preset_count(SubGhzSetting* instance) {
  380. furi_assert(instance);
  381. return SubGhzSettingCustomPresetItemArray_size(instance->preset->data);
  382. }
  383. const char* subghz_setting_get_preset_name(SubGhzSetting* instance, size_t idx) {
  384. furi_assert(instance);
  385. SubGhzSettingCustomPresetItem* item =
  386. SubGhzSettingCustomPresetItemArray_get(instance->preset->data, idx);
  387. return string_get_cstr(item->custom_preset_name);
  388. }
  389. int subghz_setting_get_inx_preset_by_name(SubGhzSetting* instance, const char* preset_name) {
  390. furi_assert(instance);
  391. size_t idx = 0;
  392. for
  393. M_EACH(item, instance->preset->data, SubGhzSettingCustomPresetItemArray_t) {
  394. if(strcmp(string_get_cstr(item->custom_preset_name), preset_name) == 0) {
  395. return idx;
  396. }
  397. idx++;
  398. }
  399. furi_crash("SubGhz: No name preset.");
  400. return -1;
  401. }
  402. bool subghz_setting_load_custom_preset(
  403. SubGhzSetting* instance,
  404. const char* preset_name,
  405. FlipperFormat* fff_data_file) {
  406. furi_assert(instance);
  407. furi_assert(preset_name);
  408. uint32_t temp_data32;
  409. SubGhzSettingCustomPresetItem* item =
  410. SubGhzSettingCustomPresetItemArray_push_raw(instance->preset->data);
  411. string_init(item->custom_preset_name);
  412. string_set(item->custom_preset_name, preset_name);
  413. do {
  414. if(!flipper_format_get_value_count(fff_data_file, "Custom_preset_data", &temp_data32))
  415. break;
  416. if(!temp_data32 || (temp_data32 % 2)) {
  417. FURI_LOG_E(TAG, "Integrity error Custom_preset_data");
  418. break;
  419. }
  420. item->custom_preset_data_size = sizeof(uint8_t) * temp_data32;
  421. item->custom_preset_data = malloc(item->custom_preset_data_size);
  422. if(!flipper_format_read_hex(
  423. fff_data_file,
  424. "Custom_preset_data",
  425. item->custom_preset_data,
  426. item->custom_preset_data_size)) {
  427. FURI_LOG_E(TAG, "Missing Custom_preset_data");
  428. break;
  429. }
  430. return true;
  431. } while(true);
  432. return false;
  433. }
  434. bool subghz_setting_delete_custom_preset(SubGhzSetting* instance, const char* preset_name) {
  435. furi_assert(instance);
  436. furi_assert(preset_name);
  437. SubGhzSettingCustomPresetItemArray_it_t it;
  438. SubGhzSettingCustomPresetItemArray_it_last(it, instance->preset->data);
  439. while(!SubGhzSettingCustomPresetItemArray_end_p(it)) {
  440. SubGhzSettingCustomPresetItem* item = SubGhzSettingCustomPresetItemArray_ref(it);
  441. if(strcmp(string_get_cstr(item->custom_preset_name), preset_name) == 0) {
  442. string_clear(item->custom_preset_name);
  443. free(item->custom_preset_data);
  444. SubGhzSettingCustomPresetItemArray_remove(instance->preset->data, it);
  445. return true;
  446. }
  447. SubGhzSettingCustomPresetItemArray_previous(it);
  448. }
  449. return false;
  450. }
  451. uint8_t* subghz_setting_get_preset_data(SubGhzSetting* instance, size_t idx) {
  452. furi_assert(instance);
  453. SubGhzSettingCustomPresetItem* item =
  454. SubGhzSettingCustomPresetItemArray_get(instance->preset->data, idx);
  455. return item->custom_preset_data;
  456. }
  457. size_t subghz_setting_get_preset_data_size(SubGhzSetting* instance, size_t idx) {
  458. furi_assert(instance);
  459. SubGhzSettingCustomPresetItem* item =
  460. SubGhzSettingCustomPresetItemArray_get(instance->preset->data, idx);
  461. return item->custom_preset_data_size;
  462. }
  463. uint8_t* subghz_setting_get_preset_data_by_name(SubGhzSetting* instance, const char* preset_name) {
  464. furi_assert(instance);
  465. SubGhzSettingCustomPresetItem* item = SubGhzSettingCustomPresetItemArray_get(
  466. instance->preset->data, subghz_setting_get_inx_preset_by_name(instance, preset_name));
  467. return item->custom_preset_data;
  468. }
  469. uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx) {
  470. furi_assert(instance);
  471. uint32_t* ret = FrequencyList_get(instance->frequencies, idx);
  472. if(ret) {
  473. return (*ret) & FREQUENCY_MASK;
  474. } else {
  475. return 0;
  476. }
  477. }
  478. uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx) {
  479. furi_assert(instance);
  480. uint32_t* ret = FrequencyList_get(instance->hopper_frequencies, idx);
  481. if(ret) {
  482. return *ret;
  483. } else {
  484. return 0;
  485. }
  486. }
  487. uint32_t subghz_setting_get_frequency_default_index(SubGhzSetting* instance) {
  488. furi_assert(instance);
  489. for(size_t i = 0; i < FrequencyList_size(instance->frequencies); i++) {
  490. uint32_t frequency = *FrequencyList_get(instance->frequencies, i);
  491. if(frequency & FREQUENCY_FLAG_DEFAULT) {
  492. return i;
  493. }
  494. }
  495. return 0;
  496. }
  497. uint32_t subghz_setting_get_default_frequency(SubGhzSetting* instance) {
  498. furi_assert(instance);
  499. return subghz_setting_get_frequency(
  500. instance, subghz_setting_get_frequency_default_index(instance));
  501. }