From a5cc3453c815ca01fa46ae9d3873a72d0ef52d65 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Thu, 14 Apr 2022 18:05:40 +0400 Subject: [PATCH] SubGhz: support for custom frequencies for SubGhz (#1108) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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: あく --- .../desktop/views/desktop_view_debug.c | 10 +- applications/notification/notification_app.c | 13 +- applications/notification/notification_app.h | 1 + .../subghz_frequency_analyzer_worker.c | 13 +- .../subghz/scenes/subghz_scene_read_raw.c | 3 +- .../subghz/scenes/subghz_scene_receiver.c | 3 +- .../scenes/subghz_scene_receiver_config.c | 61 ++- .../subghz/scenes/subghz_scene_set_type.c | 6 +- applications/subghz/subghz.c | 72 +--- applications/subghz/subghz_i.c | 7 +- applications/subghz/subghz_i.h | 10 +- applications/subghz/subghz_setting.c | 361 ++++++++++++++++++ applications/subghz/subghz_setting.h | 17 + .../assets/setting_frequency_analyzer_user | 19 + assets/resources/subghz/assets/setting_user | 24 ++ 15 files changed, 511 insertions(+), 109 deletions(-) create mode 100644 applications/subghz/subghz_setting.c create mode 100644 applications/subghz/subghz_setting.h create mode 100644 assets/resources/subghz/assets/setting_frequency_analyzer_user create mode 100644 assets/resources/subghz/assets/setting_user diff --git a/applications/desktop/views/desktop_view_debug.c b/applications/desktop/views/desktop_view_debug.c index 0aed2adf..98cf57ce 100644 --- a/applications/desktop/views/desktop_view_debug.c +++ b/applications/desktop/views/desktop_view_debug.c @@ -114,14 +114,8 @@ bool desktop_debug_input(InputEvent* event, void* context) { DesktopViewStatsScreens current = 0; with_view_model( debug_view->view, (DesktopDebugViewModel * model) { -#if SRV_DOLPHIN_STATE_DEBUG == 1 - if(event->key == InputKeyDown) { - model->screen = (model->screen + 1) % DesktopViewStatsTotalCount; - } else if(event->key == InputKeyUp) { - model->screen = ((model->screen - 1) + DesktopViewStatsTotalCount) % - DesktopViewStatsTotalCount; - } -#else + +#ifdef SRV_DOLPHIN_STATE_DEBUG if((event->key == InputKeyDown) || (event->key == InputKeyUp)) { model->screen = !model->screen; } diff --git a/applications/notification/notification_app.c b/applications/notification/notification_app.c index 00136ec5..447bf903 100644 --- a/applications/notification/notification_app.c +++ b/applications/notification/notification_app.c @@ -164,7 +164,6 @@ void notification_process_notification_message( notification_message = (*message->sequence)[notification_message_index]; bool led_active = false; - uint8_t display_led_lock = 0; uint8_t led_values[NOTIFICATION_LED_COUNT] = {0x00, 0x00, 0x00}; bool reset_notifications = true; float speaker_volume_setting = app->settings.speaker_volume; @@ -192,18 +191,18 @@ void notification_process_notification_message( reset_mask |= reset_display_mask; break; case NotificationMessageTypeLedDisplayLock: - furi_assert(display_led_lock < UINT8_MAX); - display_led_lock++; - if(display_led_lock == 1) { + furi_assert(app->display_led_lock < UINT8_MAX); + app->display_led_lock++; + if(app->display_led_lock == 1) { notification_apply_internal_led_layer( &app->display, notification_message->data.led.value * display_brightness_setting); } break; case NotificationMessageTypeLedDisplayUnlock: - furi_assert(display_led_lock > 0); - display_led_lock--; - if(display_led_lock == 0) { + furi_assert(app->display_led_lock > 0); + app->display_led_lock--; + if(app->display_led_lock == 0) { notification_apply_internal_led_layer( &app->display, notification_message->data.led.value * display_brightness_setting); diff --git a/applications/notification/notification_app.h b/applications/notification/notification_app.h index 5b7546aa..2c41bc82 100644 --- a/applications/notification/notification_app.h +++ b/applications/notification/notification_app.h @@ -49,6 +49,7 @@ struct NotificationApp { NotificationLedLayer display; NotificationLedLayer led[NOTIFICATION_LED_COUNT]; + uint8_t display_led_lock; NotificationSettings settings; }; diff --git a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c index 54b3191d..b6b3a1ed 100644 --- a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c +++ b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c @@ -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); } diff --git a/applications/subghz/scenes/subghz_scene_read_raw.c b/applications/subghz/scenes/subghz_scene_read_raw.c index e63014f7..cbd64f8f 100644 --- a/applications/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/subghz/scenes/subghz_scene_read_raw.c @@ -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)) { diff --git a/applications/subghz/scenes/subghz_scene_receiver.c b/applications/subghz/scenes/subghz_scene_receiver.c index dc6b9968..8a5ee921 100644 --- a/applications/subghz/scenes/subghz_scene_receiver.c +++ b/applications/subghz/scenes/subghz_scene_receiver.c @@ -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); diff --git a/applications/subghz/scenes/subghz_scene_receiver_config.c b/applications/subghz/scenes/subghz_scene_receiver_config.c index 98fce89a..f2ae749f 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/subghz/scenes/subghz_scene_receiver_config.c @@ -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) { diff --git a/applications/subghz/scenes/subghz_scene_set_type.c b/applications/subghz/scenes/subghz_scene_set_type.c index 32aecc14..4fb36467 100644 --- a/applications/subghz/scenes/subghz_scene_set_type.c +++ b/applications/subghz/scenes/subghz_scene_set_type.c @@ -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 { diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 3320db48..80c69734 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -3,68 +3,6 @@ #include "subghz_i.h" #include -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); diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index ea6fa80e..5740ea9d 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -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); } } diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h index 9ef1ee54..b2ce806c 100644 --- a/applications/subghz/subghz_i.h +++ b/applications/subghz/subghz_i.h @@ -30,19 +30,12 @@ #include #include "subghz_history.h" +#include "subghz_setting.h" #include #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 { diff --git a/applications/subghz/subghz_setting.c b/applications/subghz/subghz_setting.c new file mode 100644 index 00000000..98a8a16e --- /dev/null +++ b/applications/subghz/subghz_setting.c @@ -0,0 +1,361 @@ +#include "subghz_setting.h" +#include "subghz_i.h" + +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/applications/subghz/subghz_setting.h b/applications/subghz/subghz_setting.h new file mode 100644 index 00000000..cdf60797 --- /dev/null +++ b/applications/subghz/subghz_setting.h @@ -0,0 +1,17 @@ + +#pragma once + +#include +#include +#include + +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); diff --git a/assets/resources/subghz/assets/setting_frequency_analyzer_user b/assets/resources/subghz/assets/setting_frequency_analyzer_user new file mode 100644 index 00000000..2c03a402 --- /dev/null +++ b/assets/resources/subghz/assets/setting_frequency_analyzer_user @@ -0,0 +1,19 @@ +Filetype: Flipper SubGhz Setting File +Version: 1 +Frequency_default: 433920000 +Frequency: 300000000 +Frequency: 303875000 +Frequency: 304250000 +Frequency: 315000000 +Frequency: 318000000 +Frequency: 390000000 +Frequency: 418000000 +Frequency: 433075000 +Frequency: 433420000 +Frequency: 433920000 +Frequency: 434420000 +Frequency: 434775000 +Frequency: 438900000 +Frequency: 868350000 +Frequency: 915000000 +Frequency: 925000000 diff --git a/assets/resources/subghz/assets/setting_user b/assets/resources/subghz/assets/setting_user new file mode 100644 index 00000000..11bd984d --- /dev/null +++ b/assets/resources/subghz/assets/setting_user @@ -0,0 +1,24 @@ +Filetype: Flipper SubGhz Setting File +Version: 1 +Frequency_default: 433920000 +Frequency: 300000000 +Frequency: 303875000 +Frequency: 304250000 +Frequency: 315000000 +Frequency: 318000000 +Frequency: 390000000 +Frequency: 418000000 +Frequency: 433075000 +Frequency: 433420000 +Frequency: 433920000 +Frequency: 434420000 +Frequency: 434775000 +Frequency: 438900000 +Frequency: 868350000 +Frequency: 915000000 +Frequency: 925000000 +Hopper_frequency: 315000000 +Hopper_frequency: 318000000 +Hopper_frequency: 390000000 +Hopper_frequency: 433920000 +Hopper_frequency: 868350000