SubGhz: support for custom frequencies for SubGhz (#1108)
* SubGhz: add load setting * SubGhz: add support file upload with custom frequencies * SubGhz: add load region setting * SubGhz: fix syntax * SubGhz: fix furi_halt error * Desktop: hide dolphin controls in production build * Notification: fix crash on NotificationMessageTypeLedDisplayUnlock message Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		| @@ -29,6 +29,7 @@ struct SubGhzFrequencyAnalyzerWorker { | ||||
|     volatile bool worker_running; | ||||
|     uint8_t count_repet; | ||||
|     FrequencyRSSI frequency_rssi_buf; | ||||
|     SubGhzSetting* setting; | ||||
|  | ||||
|     float filVal; | ||||
|  | ||||
| @@ -77,10 +78,12 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { | ||||
|         frequency_rssi.rssi = -127.0f; | ||||
|         furi_hal_subghz_idle(); | ||||
|         furi_hal_subghz_load_registers(subghz_preset_ook_650khz); | ||||
|         for(size_t i = 0; i < subghz_frequencies_count; i++) { | ||||
|             if(furi_hal_subghz_is_frequency_valid(subghz_frequencies[i])) { | ||||
|         for(size_t i = 0; i < subghz_setting_get_frequency_count(instance->setting); i++) { | ||||
|             if(furi_hal_subghz_is_frequency_valid( | ||||
|                    subghz_setting_get_frequency(instance->setting, i))) { | ||||
|                 furi_hal_subghz_idle(); | ||||
|                 frequency = furi_hal_subghz_set_frequency(subghz_frequencies[i]); | ||||
|                 frequency = furi_hal_subghz_set_frequency( | ||||
|                     subghz_setting_get_frequency(instance->setting, i)); | ||||
|                 furi_hal_subghz_rx(); | ||||
|                 osDelay(3); | ||||
|                 rssi = furi_hal_subghz_get_rssi(); | ||||
| @@ -150,6 +153,8 @@ SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc() { | ||||
|     furi_thread_set_context(instance->thread, instance); | ||||
|     furi_thread_set_callback(instance->thread, subghz_frequency_analyzer_worker_thread); | ||||
|  | ||||
|     instance->setting = subghz_setting_alloc(); | ||||
|     subghz_setting_load(instance->setting, "/ext/subghz/assets/setting_frequency_analyzer_user"); | ||||
|     return instance; | ||||
| } | ||||
|  | ||||
| @@ -157,7 +162,7 @@ void subghz_frequency_analyzer_worker_free(SubGhzFrequencyAnalyzerWorker* instan | ||||
|     furi_assert(instance); | ||||
|  | ||||
|     furi_thread_free(instance->thread); | ||||
|  | ||||
|     subghz_setting_free(instance->setting); | ||||
|     free(instance); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -127,7 +127,8 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { | ||||
|                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving); | ||||
|             } else { | ||||
|                 //Restore default setting | ||||
|                 subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; | ||||
|                 subghz->txrx->frequency = subghz_setting_get_frequency( | ||||
|                     subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting)); | ||||
|                 subghz->txrx->preset = FuriHalSubGhzPresetOok650Async; | ||||
|                 if(!scene_manager_search_and_switch_to_previous_scene( | ||||
|                        subghz->scene_manager, SubGhzSceneSaved)) { | ||||
|   | ||||
| @@ -120,7 +120,8 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { | ||||
|                 subghz_sleep(subghz); | ||||
|             }; | ||||
|             subghz->txrx->hopper_state = SubGhzHopperStateOFF; | ||||
|             subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; | ||||
|             subghz->txrx->frequency = subghz_setting_get_frequency( | ||||
|                 subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting)); | ||||
|             subghz->txrx->preset = FuriHalSubGhzPresetOok650Async; | ||||
|             subghz->txrx->idx_menu_chosen = 0; | ||||
|             subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz); | ||||
|   | ||||
| @@ -40,6 +40,21 @@ uint8_t subghz_scene_receiver_config_uint32_value_index( | ||||
|     return index; | ||||
| } | ||||
|  | ||||
| uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) { | ||||
|     furi_assert(context); | ||||
|     SubGhz* subghz = context; | ||||
|     int64_t last_value = INT64_MIN; | ||||
|     uint8_t index = 0; | ||||
|     for(uint8_t i = 0; i < subghz_setting_get_frequency_count(subghz->setting); i++) { | ||||
|         if((value >= last_value) && (value <= subghz_setting_get_frequency(subghz->setting, i))) { | ||||
|             index = i; | ||||
|             break; | ||||
|         } | ||||
|         last_value = subghz_setting_get_frequency(subghz->setting, i); | ||||
|     } | ||||
|     return index; | ||||
| } | ||||
|  | ||||
| uint8_t subghz_scene_receiver_config_hopper_value_index( | ||||
|     const uint32_t value, | ||||
|     const uint32_t values[], | ||||
| @@ -64,10 +79,17 @@ static void subghz_scene_receiver_config_set_frequency(VariableItem* item) { | ||||
|     uint8_t index = variable_item_get_current_value_index(item); | ||||
|  | ||||
|     if(subghz->txrx->hopper_state == SubGhzHopperStateOFF) { | ||||
|         variable_item_set_current_value_text(item, subghz_frequencies_text[index]); | ||||
|         subghz->txrx->frequency = subghz_frequencies[index]; | ||||
|         char text_buf[10] = {0}; | ||||
|         sprintf( | ||||
|             text_buf, | ||||
|             "%lu.%02lu", | ||||
|             subghz_setting_get_frequency(subghz->setting, index) / 1000000, | ||||
|             (subghz_setting_get_frequency(subghz->setting, index) % 1000000) / 10000); | ||||
|         variable_item_set_current_value_text(item, text_buf); | ||||
|         subghz->txrx->frequency = subghz_setting_get_frequency(subghz->setting, index); | ||||
|     } else { | ||||
|         variable_item_set_current_value_index(item, subghz_frequencies_433_92); | ||||
|         variable_item_set_current_value_index( | ||||
|             item, subghz_setting_get_frequency_default_index(subghz->setting)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -85,15 +107,27 @@ static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item) | ||||
|  | ||||
|     variable_item_set_current_value_text(item, hopping_text[index]); | ||||
|     if(hopping_value[index] == SubGhzHopperStateOFF) { | ||||
|         char text_buf[10] = {0}; | ||||
|         sprintf( | ||||
|             text_buf, | ||||
|             "%lu.%02lu", | ||||
|             subghz_setting_get_frequency( | ||||
|                 subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting)) / | ||||
|                 1000000, | ||||
|             (subghz_setting_get_frequency( | ||||
|                  subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting)) % | ||||
|              1000000) / | ||||
|                 10000); | ||||
|         variable_item_set_current_value_text( | ||||
|             (VariableItem*)scene_manager_get_scene_state( | ||||
|                 subghz->scene_manager, SubGhzSceneReceiverConfig), | ||||
|             subghz_frequencies_text[subghz_frequencies_433_92]); | ||||
|         subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; | ||||
|             text_buf); | ||||
|         subghz->txrx->frequency = subghz_setting_get_frequency( | ||||
|             subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting)); | ||||
|         variable_item_set_current_value_index( | ||||
|             (VariableItem*)scene_manager_get_scene_state( | ||||
|                 subghz->scene_manager, SubGhzSceneReceiverConfig), | ||||
|             subghz_frequencies_433_92); | ||||
|             subghz_setting_get_frequency_default_index(subghz->setting)); | ||||
|     } else { | ||||
|         variable_item_set_current_value_text( | ||||
|             (VariableItem*)scene_manager_get_scene_state( | ||||
| @@ -102,7 +136,7 @@ static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item) | ||||
|         variable_item_set_current_value_index( | ||||
|             (VariableItem*)scene_manager_get_scene_state( | ||||
|                 subghz->scene_manager, SubGhzSceneReceiverConfig), | ||||
|             subghz_frequencies_433_92); | ||||
|             subghz_setting_get_frequency_default_index(subghz->setting)); | ||||
|     } | ||||
|  | ||||
|     subghz->txrx->hopper_state = hopping_value[index]; | ||||
| @@ -116,15 +150,20 @@ void subghz_scene_receiver_config_on_enter(void* context) { | ||||
|     item = variable_item_list_add( | ||||
|         subghz->variable_item_list, | ||||
|         "Frequency:", | ||||
|         subghz_frequencies_count, | ||||
|         subghz_setting_get_frequency_count(subghz->setting), | ||||
|         subghz_scene_receiver_config_set_frequency, | ||||
|         subghz); | ||||
|     value_index = subghz_scene_receiver_config_uint32_value_index( | ||||
|         subghz->txrx->frequency, subghz_frequencies, subghz_frequencies_count); | ||||
|     value_index = subghz_scene_receiver_config_next_frequency(subghz->txrx->frequency, subghz); | ||||
|     scene_manager_set_scene_state( | ||||
|         subghz->scene_manager, SubGhzSceneReceiverConfig, (uint32_t)item); | ||||
|     variable_item_set_current_value_index(item, value_index); | ||||
|     variable_item_set_current_value_text(item, subghz_frequencies_text[value_index]); | ||||
|     char text_buf[10] = {0}; | ||||
|     sprintf( | ||||
|         text_buf, | ||||
|         "%lu.%02lu", | ||||
|         subghz_setting_get_frequency(subghz->setting, value_index) / 1000000, | ||||
|         (subghz_setting_get_frequency(subghz->setting, value_index) % 1000000) / 10000); | ||||
|     variable_item_set_current_value_text(item, text_buf); | ||||
|  | ||||
|     if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != | ||||
|        SubGhzCustomEventManagerSet) { | ||||
|   | ||||
| @@ -46,7 +46,7 @@ bool subghz_scene_set_type_submenu_gen_data_protocol( | ||||
|         if(!subghz_protocol_decoder_base_serialize( | ||||
|                subghz->txrx->decoder_result, | ||||
|                subghz->txrx->fff_data, | ||||
|                subghz_frequencies[subghz_frequencies_433_92], | ||||
|                subghz_setting_get_frequency_default_index(subghz->setting), | ||||
|                FuriHalSubGhzPresetOok650Async)) { | ||||
|             FURI_LOG_E(TAG, "Unable to serialize"); | ||||
|             break; | ||||
| @@ -213,7 +213,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { | ||||
|                     0x2, | ||||
|                     0x0003, | ||||
|                     "DoorHan", | ||||
|                     subghz_frequencies[subghz_frequencies_433_92], | ||||
|                     subghz_setting_get_frequency_default_index(subghz->setting), | ||||
|                     FuriHalSubGhzPresetOok650Async); | ||||
|                 generated_protocol = true; | ||||
|             } else { | ||||
| @@ -237,7 +237,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { | ||||
|                     0x2, | ||||
|                     0x0003, | ||||
|                     "DoorHan", | ||||
|                     subghz_frequencies[subghz_frequencies_315_00], | ||||
|                     315000000, | ||||
|                     FuriHalSubGhzPresetOok650Async); | ||||
|                 generated_protocol = true; | ||||
|             } else { | ||||
|   | ||||
| @@ -3,68 +3,6 @@ | ||||
| #include "subghz_i.h" | ||||
| #include <lib/toolbox/path.h> | ||||
|  | ||||
| const char* const subghz_frequencies_text[] = { | ||||
|  | ||||
|     "300.00", | ||||
|     "303.88", | ||||
|     "304.25", | ||||
|     "315.00", | ||||
|     "318.00", | ||||
|  | ||||
|     "390.00", | ||||
|     "418.00", | ||||
|     "433.08", | ||||
|     "433.42", | ||||
|     "433.92", | ||||
|     "434.42", | ||||
|     "434.78", | ||||
|     "438.90", | ||||
|  | ||||
|     "868.35", | ||||
|     "915.00", | ||||
|     "925.00", | ||||
| }; | ||||
|  | ||||
| const uint32_t subghz_frequencies[] = { | ||||
|  | ||||
|     /* 300 - 348 */ | ||||
|     300000000, | ||||
|     303875000, | ||||
|     304250000, | ||||
|     315000000, | ||||
|     318000000, | ||||
|  | ||||
|     /* 387 - 464 */ | ||||
|     390000000, | ||||
|     418000000, | ||||
|     433075000, /* LPD433 first */ | ||||
|     433420000, | ||||
|     433920000, /* LPD433 mid */ | ||||
|     434420000, | ||||
|     434775000, /* LPD433 last channels */ | ||||
|     438900000, | ||||
|  | ||||
|     /* 779 - 928 */ | ||||
|     868350000, | ||||
|     915000000, | ||||
|     925000000, | ||||
|  | ||||
| }; | ||||
|  | ||||
| const uint32_t subghz_hopper_frequencies[] = { | ||||
|     315000000, | ||||
|     318000000, | ||||
|     390000000, | ||||
|     433920000, | ||||
|     868350000, | ||||
| }; | ||||
|  | ||||
| const uint32_t subghz_frequencies_count = sizeof(subghz_frequencies) / sizeof(uint32_t); | ||||
| const uint32_t subghz_hopper_frequencies_count = | ||||
|     sizeof(subghz_hopper_frequencies) / sizeof(uint32_t); | ||||
| const uint32_t subghz_frequencies_433_92 = 9; | ||||
| const uint32_t subghz_frequencies_315_00 = 3; | ||||
|  | ||||
| bool subghz_custom_event_callback(void* context, uint32_t event) { | ||||
|     furi_assert(context); | ||||
|     SubGhz* subghz = context; | ||||
| @@ -186,9 +124,14 @@ SubGhz* subghz_alloc() { | ||||
|         SubGhzViewIdStatic, | ||||
|         subghz_test_static_get_view(subghz->subghz_test_static)); | ||||
|  | ||||
|     //init setting | ||||
|     subghz->setting = subghz_setting_alloc(); | ||||
|     subghz_setting_load(subghz->setting, "/ext/subghz/assets/setting_user"); | ||||
|  | ||||
|     //init Worker & Protocol & History | ||||
|     subghz->txrx = malloc(sizeof(SubGhzTxRx)); | ||||
|     subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; | ||||
|     subghz->txrx->frequency = subghz_setting_get_frequency( | ||||
|         subghz->setting, subghz_setting_get_frequency_default_index(subghz->setting)); | ||||
|     subghz->txrx->preset = FuriHalSubGhzPresetOok650Async; | ||||
|     subghz->txrx->txrx_state = SubGhzTxRxStateSleep; | ||||
|     subghz->txrx->hopper_state = SubGhzHopperStateOFF; | ||||
| @@ -281,6 +224,9 @@ void subghz_free(SubGhz* subghz) { | ||||
|     furi_record_close("gui"); | ||||
|     subghz->gui = NULL; | ||||
|  | ||||
|     //setting | ||||
|     subghz_setting_free(subghz->setting); | ||||
|  | ||||
|     //Worker & Protocol & History | ||||
|     subghz_receiver_free(subghz->txrx->receiver); | ||||
|     subghz_environment_free(subghz->txrx->environment); | ||||
|   | ||||
| @@ -514,9 +514,9 @@ void subghz_hopper_update(SubGhz* subghz) { | ||||
|     } else { | ||||
|         subghz->txrx->hopper_state = SubGhzHopperStateRunnig; | ||||
|     } | ||||
|  | ||||
|     // Select next frequency | ||||
|     if(subghz->txrx->hopper_idx_frequency < subghz_hopper_frequencies_count - 1) { | ||||
|     if(subghz->txrx->hopper_idx_frequency < | ||||
|        subghz_setting_get_hopper_frequency_count(subghz->setting) - 1) { | ||||
|         subghz->txrx->hopper_idx_frequency++; | ||||
|     } else { | ||||
|         subghz->txrx->hopper_idx_frequency = 0; | ||||
| @@ -527,7 +527,8 @@ void subghz_hopper_update(SubGhz* subghz) { | ||||
|     }; | ||||
|     if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) { | ||||
|         subghz_receiver_reset(subghz->txrx->receiver); | ||||
|         subghz->txrx->frequency = subghz_hopper_frequencies[subghz->txrx->hopper_idx_frequency]; | ||||
|         subghz->txrx->frequency = subghz_setting_get_hopper_frequency( | ||||
|             subghz->setting, subghz->txrx->hopper_idx_frequency); | ||||
|         subghz_rx(subghz, subghz->txrx->frequency); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -30,19 +30,12 @@ | ||||
| #include <lib/subghz/transmitter.h> | ||||
|  | ||||
| #include "subghz_history.h" | ||||
| #include "subghz_setting.h" | ||||
|  | ||||
| #include <gui/modules/variable_item_list.h> | ||||
|  | ||||
| #define SUBGHZ_MAX_LEN_NAME 40 | ||||
|  | ||||
| extern const char* const subghz_frequencies_text[]; | ||||
| extern const uint32_t subghz_frequencies[]; | ||||
| extern const uint32_t subghz_hopper_frequencies[]; | ||||
| extern const uint32_t subghz_frequencies_count; | ||||
| extern const uint32_t subghz_hopper_frequencies_count; | ||||
| extern const uint32_t subghz_frequencies_433_92; | ||||
| extern const uint32_t subghz_frequencies_315_00; | ||||
|  | ||||
| /** SubGhzNotification state */ | ||||
| typedef enum { | ||||
|     SubGhzNotificationStateStarting, | ||||
| @@ -137,6 +130,7 @@ struct SubGhz { | ||||
|     SubGhzTestCarrier* subghz_test_carrier; | ||||
|     SubGhzTestPacket* subghz_test_packet; | ||||
|     string_t error_str; | ||||
|     SubGhzSetting* setting; | ||||
| }; | ||||
|  | ||||
| typedef enum { | ||||
|   | ||||
							
								
								
									
										361
									
								
								applications/subghz/subghz_setting.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										361
									
								
								applications/subghz/subghz_setting.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,361 @@ | ||||
| #include "subghz_setting.h" | ||||
| #include "subghz_i.h" | ||||
|  | ||||
| #include <furi.h> | ||||
| #include <m-list.h> | ||||
| #include <lib/flipper_format/flipper_format.h> | ||||
|  | ||||
| #define TAG "SubGhzSetting" | ||||
|  | ||||
| #define SUBGHZ_SETTING_FILE_VERSION 1 | ||||
| #define SUBGHZ_SETTING_FILE_TYPE "Flipper SubGhz Setting File" | ||||
|  | ||||
| typedef enum { | ||||
|     SubGhzSettingStateNoLoad = 0, | ||||
|     SubGhzSettingStateLoadFrequencyDefault, | ||||
|     SubGhzSettingStateOkLoad, | ||||
| } SubGhzSettingState; | ||||
|  | ||||
| static const uint32_t subghz_frequencies[] = { | ||||
|     /* 300 - 348 */ | ||||
|     300000000, | ||||
|     303875000, | ||||
|     304250000, | ||||
|     315000000, | ||||
|     318000000, | ||||
|  | ||||
|     /* 387 - 464 */ | ||||
|     390000000, | ||||
|     418000000, | ||||
|     433075000, /* LPD433 first */ | ||||
|     433420000, | ||||
|     433920000, /* LPD433 mid */ | ||||
|     434420000, | ||||
|     434775000, /* LPD433 last channels */ | ||||
|     438900000, | ||||
|  | ||||
|     /* 779 - 928 */ | ||||
|     868350000, | ||||
|     915000000, | ||||
|     925000000, | ||||
|     0, | ||||
| }; | ||||
| static const uint32_t subghz_hopper_frequencies[] = { | ||||
|     315000000, | ||||
|     318000000, | ||||
|     390000000, | ||||
|     433920000, | ||||
|     868350000, | ||||
|     0, | ||||
| }; | ||||
| static const uint32_t subghz_frequency_default_index = 9; | ||||
|  | ||||
| static const uint32_t subghz_frequencies_region_eu_ru[] = { | ||||
|     /* 300 - 348 */ | ||||
|     300000000, | ||||
|     303875000, | ||||
|     304250000, | ||||
|     315000000, | ||||
|     318000000, | ||||
|  | ||||
|     /* 387 - 464 */ | ||||
|     390000000, | ||||
|     418000000, | ||||
|     433075000, /* LPD433 first */ | ||||
|     433420000, | ||||
|     433920000, /* LPD433 mid */ | ||||
|     434420000, | ||||
|     434775000, /* LPD433 last channels */ | ||||
|     438900000, | ||||
|  | ||||
|     /* 779 - 928 */ | ||||
|     868350000, | ||||
|     915000000, | ||||
|     925000000, | ||||
|     0, | ||||
| }; | ||||
| static const uint32_t subghz_hopper_frequencies_region_eu_ru[] = { | ||||
|     315000000, | ||||
|     318000000, | ||||
|     390000000, | ||||
|     433920000, | ||||
|     868350000, | ||||
|     0, | ||||
| }; | ||||
| static const uint32_t subghz_frequency_default_index_region_eu_ru = 9; | ||||
|  | ||||
| static const uint32_t subghz_frequencies_region_us_ca_au[] = { | ||||
|     /* 300 - 348 */ | ||||
|     300000000, | ||||
|     303875000, | ||||
|     304250000, | ||||
|     315000000, | ||||
|     318000000, | ||||
|  | ||||
|     /* 387 - 464 */ | ||||
|     390000000, | ||||
|     418000000, | ||||
|     433075000, /* LPD433 first */ | ||||
|     433420000, | ||||
|     433920000, /* LPD433 mid */ | ||||
|     434420000, | ||||
|     434775000, /* LPD433 last channels */ | ||||
|     438900000, | ||||
|  | ||||
|     /* 779 - 928 */ | ||||
|     868350000, | ||||
|     915000000, | ||||
|     925000000, | ||||
|     0, | ||||
| }; | ||||
| static const uint32_t subghz_hopper_frequencies_region_us_ca_au[] = { | ||||
|     315000000, | ||||
|     318000000, | ||||
|     390000000, | ||||
|     433920000, | ||||
|     868350000, | ||||
|     0, | ||||
| }; | ||||
| static const uint32_t subghz_frequency_default_index_region_us_ca_au = 9; | ||||
|  | ||||
| static const uint32_t subghz_frequencies_region_jp[] = { | ||||
|     /* 300 - 348 */ | ||||
|     300000000, | ||||
|     303875000, | ||||
|     304250000, | ||||
|     315000000, | ||||
|     318000000, | ||||
|  | ||||
|     /* 387 - 464 */ | ||||
|     390000000, | ||||
|     418000000, | ||||
|     433075000, /* LPD433 first */ | ||||
|     433420000, | ||||
|     433920000, /* LPD433 mid */ | ||||
|     434420000, | ||||
|     434775000, /* LPD433 last channels */ | ||||
|     438900000, | ||||
|  | ||||
|     /* 779 - 928 */ | ||||
|     868350000, | ||||
|     915000000, | ||||
|     925000000, | ||||
|     0, | ||||
| }; | ||||
| static const uint32_t subghz_hopper_frequencies_region_jp[] = { | ||||
|     315000000, | ||||
|     318000000, | ||||
|     390000000, | ||||
|     433920000, | ||||
|     868350000, | ||||
|     0, | ||||
| }; | ||||
| static const uint32_t subghz_frequency_default_index_region_jp = 9; | ||||
|  | ||||
| LIST_DEF(frequencies_list, uint32_t) | ||||
| LIST_DEF(hopper_frequencies_list, uint32_t) | ||||
|  | ||||
| struct SubGhzSetting { | ||||
|     frequencies_list_t frequencies; | ||||
|     hopper_frequencies_list_t hopper_frequencies; | ||||
|     size_t frequencies_count; | ||||
|     size_t hopper_frequencies_count; | ||||
|     uint32_t frequency_default_index; | ||||
| }; | ||||
|  | ||||
| SubGhzSetting* subghz_setting_alloc(void) { | ||||
|     SubGhzSetting* instance = malloc(sizeof(SubGhzSetting)); | ||||
|     frequencies_list_init(instance->frequencies); | ||||
|     hopper_frequencies_list_init(instance->hopper_frequencies); | ||||
|     return instance; | ||||
| } | ||||
|  | ||||
| void subghz_setting_free(SubGhzSetting* instance) { | ||||
|     furi_assert(instance); | ||||
|     frequencies_list_clear(instance->frequencies); | ||||
|     hopper_frequencies_list_clear(instance->hopper_frequencies); | ||||
|     free(instance); | ||||
| } | ||||
|  | ||||
| void subghz_setting_load_default( | ||||
|     SubGhzSetting* instance, | ||||
|     const uint32_t frequencies[], | ||||
|     const uint32_t hopper_frequencies[], | ||||
|     const uint32_t frequency_default_index) { | ||||
|     furi_assert(instance); | ||||
|     size_t i = 0; | ||||
|     frequencies_list_clear(instance->frequencies); | ||||
|     hopper_frequencies_list_clear(instance->hopper_frequencies); | ||||
|     i = 0; | ||||
|     while(frequencies[i]) { | ||||
|         frequencies_list_push_back(instance->frequencies, frequencies[i]); | ||||
|         i++; | ||||
|     } | ||||
|     instance->frequencies_count = i; | ||||
|  | ||||
|     i = 0; | ||||
|     while(hopper_frequencies[i]) { | ||||
|         hopper_frequencies_list_push_back(instance->hopper_frequencies, hopper_frequencies[i]); | ||||
|         i++; | ||||
|     } | ||||
|     instance->hopper_frequencies_count = i; | ||||
|  | ||||
|     instance->frequency_default_index = frequency_default_index; | ||||
| } | ||||
|  | ||||
| void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { | ||||
|     furi_assert(instance); | ||||
|  | ||||
|     frequencies_list_clear(instance->frequencies); | ||||
|     hopper_frequencies_list_clear(instance->hopper_frequencies); | ||||
|  | ||||
|     Storage* storage = furi_record_open("storage"); | ||||
|     FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); | ||||
|  | ||||
|     string_t temp_str; | ||||
|     string_init(temp_str); | ||||
|     uint32_t temp_data32; | ||||
|     SubGhzSettingState loading = SubGhzSettingStateNoLoad; | ||||
|     uint16_t i = 0; | ||||
|  | ||||
|     if(file_path) { | ||||
|         do { | ||||
|             if(!flipper_format_file_open_existing(fff_data_file, file_path)) { | ||||
|                 FURI_LOG_E(TAG, "Error open file %s", file_path); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { | ||||
|                 FURI_LOG_E(TAG, "Missing or incorrect header"); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             if((!strcmp(string_get_cstr(temp_str), SUBGHZ_SETTING_FILE_TYPE)) && | ||||
|                temp_data32 == SUBGHZ_SETTING_FILE_VERSION) { | ||||
|             } else { | ||||
|                 FURI_LOG_E(TAG, "Type or version mismatch"); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             if(!flipper_format_rewind(fff_data_file)) { | ||||
|                 FURI_LOG_E(TAG, "Rewind error"); | ||||
|                 break; | ||||
|             } | ||||
|             i = 0; | ||||
|             while(flipper_format_read_uint32( | ||||
|                 fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) { | ||||
|                 if(furi_hal_subghz_is_frequency_valid(temp_data32)) { | ||||
|                     FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32); | ||||
|                     frequencies_list_push_back(instance->frequencies, temp_data32); | ||||
|                     i++; | ||||
|                 } else { | ||||
|                     FURI_LOG_E(TAG, "Frequency not supported %lu", temp_data32); | ||||
|                 } | ||||
|             } | ||||
|             instance->frequencies_count = i; | ||||
|  | ||||
|             if(!flipper_format_rewind(fff_data_file)) { | ||||
|                 FURI_LOG_E(TAG, "Rewind error"); | ||||
|                 break; | ||||
|             } | ||||
|             i = 0; | ||||
|             while(flipper_format_read_uint32( | ||||
|                 fff_data_file, "Hopper_frequency", (uint32_t*)&temp_data32, 1)) { | ||||
|                 if(furi_hal_subghz_is_frequency_valid(temp_data32)) { | ||||
|                     FURI_LOG_I(TAG, "Hopper frequency loaded %lu", temp_data32); | ||||
|                     hopper_frequencies_list_push_back(instance->hopper_frequencies, temp_data32); | ||||
|                     i++; | ||||
|                 } else { | ||||
|                     FURI_LOG_E(TAG, "Hopper frequency not supported %lu", temp_data32); | ||||
|                 } | ||||
|             } | ||||
|             instance->hopper_frequencies_count = i; | ||||
|  | ||||
|             if(!flipper_format_rewind(fff_data_file)) { | ||||
|                 FURI_LOG_E(TAG, "Rewind error"); | ||||
|                 break; | ||||
|             } | ||||
|             if(!flipper_format_read_uint32( | ||||
|                    fff_data_file, "Frequency_default", (uint32_t*)&temp_data32, 1)) { | ||||
|                 FURI_LOG_E(TAG, "Frequency default missing"); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             for(i = 0; i < instance->frequencies_count; i++) { | ||||
|                 if(subghz_setting_get_frequency(instance, i) == temp_data32) { | ||||
|                     instance->frequency_default_index = i; | ||||
|                     FURI_LOG_I(TAG, "Frequency default index %lu", i); | ||||
|                     loading = SubGhzSettingStateLoadFrequencyDefault; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if(loading == SubGhzSettingStateLoadFrequencyDefault) { | ||||
|                 loading = SubGhzSettingStateOkLoad; | ||||
|             } else { | ||||
|                 FURI_LOG_E(TAG, "Frequency default index missing"); | ||||
|             } | ||||
|         } while(false); | ||||
|     } | ||||
|     flipper_format_free(fff_data_file); | ||||
|     furi_record_close("storage"); | ||||
|  | ||||
|     if(loading != SubGhzSettingStateOkLoad) { | ||||
|         switch(furi_hal_version_get_hw_region()) { | ||||
|         case FuriHalVersionRegionEuRu: | ||||
|             subghz_setting_load_default( | ||||
|                 instance, | ||||
|                 subghz_frequencies_region_eu_ru, | ||||
|                 subghz_hopper_frequencies_region_eu_ru, | ||||
|                 subghz_frequency_default_index_region_eu_ru); | ||||
|             break; | ||||
|         case FuriHalVersionRegionUsCaAu: | ||||
|             subghz_setting_load_default( | ||||
|                 instance, | ||||
|                 subghz_frequencies_region_us_ca_au, | ||||
|                 subghz_hopper_frequencies_region_us_ca_au, | ||||
|                 subghz_frequency_default_index_region_us_ca_au); | ||||
|             break; | ||||
|         case FuriHalVersionRegionJp: | ||||
|             subghz_setting_load_default( | ||||
|                 instance, | ||||
|                 subghz_frequencies_region_jp, | ||||
|                 subghz_hopper_frequencies_region_jp, | ||||
|                 subghz_frequency_default_index_region_jp); | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             subghz_setting_load_default( | ||||
|                 instance, | ||||
|                 subghz_frequencies, | ||||
|                 subghz_hopper_frequencies, | ||||
|                 subghz_frequency_default_index); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| size_t subghz_setting_get_frequency_count(SubGhzSetting* instance) { | ||||
|     furi_assert(instance); | ||||
|     return instance->frequencies_count; | ||||
| } | ||||
|  | ||||
| size_t subghz_setting_get_hopper_frequency_count(SubGhzSetting* instance) { | ||||
|     furi_assert(instance); | ||||
|     return instance->hopper_frequencies_count; | ||||
| } | ||||
|  | ||||
| uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx) { | ||||
|     furi_assert(instance); | ||||
|     return *frequencies_list_get(instance->frequencies, idx); | ||||
| } | ||||
|  | ||||
| uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx) { | ||||
|     furi_assert(instance); | ||||
|     return *hopper_frequencies_list_get(instance->hopper_frequencies, idx); | ||||
| } | ||||
|  | ||||
| uint32_t subghz_setting_get_frequency_default_index(SubGhzSetting* instance) { | ||||
|     furi_assert(instance); | ||||
|     return instance->frequency_default_index; | ||||
| } | ||||
							
								
								
									
										17
									
								
								applications/subghz/subghz_setting.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								applications/subghz/subghz_setting.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <math.h> | ||||
| #include <furi.h> | ||||
| #include <furi_hal.h> | ||||
|  | ||||
| typedef struct SubGhzSetting SubGhzSetting; | ||||
|  | ||||
| SubGhzSetting* subghz_setting_alloc(void); | ||||
| void subghz_setting_free(SubGhzSetting* instance); | ||||
| void subghz_setting_load(SubGhzSetting* instance, const char* file_path); | ||||
| size_t subghz_setting_get_frequency_count(SubGhzSetting* instance); | ||||
| size_t subghz_setting_get_hopper_frequency_count(SubGhzSetting* instance); | ||||
| uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx); | ||||
| uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx); | ||||
| uint32_t subghz_setting_get_frequency_default_index(SubGhzSetting* instance); | ||||
		Reference in New Issue
	
	Block a user