diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 7392221dc..3eac03dec 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -341,5 +341,5 @@ void subghz_scene_read_raw_on_exit(void* context) { notification_message(subghz->notifications, &sequence_reset_rgb); //filter restoration - subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); + subghz_last_settings_set_detect_raw_values(subghz); } \ No newline at end of file diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index 0175cd0fd..b782f5a31 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -29,11 +29,6 @@ const char* const detect_raw_text[DETECT_RAW_COUNT] = { "ON", }; -const SubGhzProtocolFlag detect_raw_value[DETECT_RAW_COUNT] = { - SubGhzProtocolFlag_Decodable, - SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW, -}; - #define RSSI_THRESHOLD_COUNT 7 const char* const rssi_threshold_text[RSSI_THRESHOLD_COUNT] = { "-72db", @@ -105,20 +100,6 @@ uint8_t subghz_scene_receiver_config_hopper_value_index( } } -uint8_t subghz_scene_receiver_config_detect_raw_value_index( - const SubGhzProtocolFlag value, - const SubGhzProtocolFlag values[], - uint8_t values_count) { - uint8_t index = 0; - for(uint8_t i = 0; i < values_count; i++) { - if(value == values[i]) { - index = i; - break; - } - } - return index; -} - uint8_t subghz_scene_receiver_config_rssi_threshold_value_index( const int value, const int values[], @@ -186,12 +167,9 @@ static void subghz_scene_receiver_config_set_detect_raw(VariableItem* item) { uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, detect_raw_text[index]); - subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]); + subghz->last_settings->detect_raw = index; - subghz_protocol_decoder_raw_set_auto_mode( - subghz_receiver_search_decoder_base_by_name( - subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME), - (index == 1)); + subghz_last_settings_set_detect_raw_values(subghz); } static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) { @@ -304,10 +282,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { DETECT_RAW_COUNT, subghz_scene_receiver_config_set_detect_raw, subghz); - value_index = subghz_scene_receiver_config_detect_raw_value_index( - subghz_receiver_get_filter(subghz->txrx->receiver), - detect_raw_value, - DETECT_RAW_COUNT); + value_index = subghz->last_settings->detect_raw; variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, detect_raw_text[value_index]); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index 5621bb847..be171f421 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_info.c @@ -26,6 +26,7 @@ static bool subghz_scene_receiver_info_update_parser(void* context) { subghz->txrx->receiver, subghz_history_get_protocol_name(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); if(subghz->txrx->decoder_result) { + // In this case flipper format was changed to short file content subghz_protocol_decoder_base_deserialize( subghz->txrx->decoder_result, subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); diff --git a/applications/main/subghz/scenes/subghz_scene_start.c b/applications/main/subghz/scenes/subghz_scene_start.c index 35c7ecb9c..f64e29e0c 100644 --- a/applications/main/subghz/scenes/subghz_scene_start.c +++ b/applications/main/subghz/scenes/subghz_scene_start.c @@ -21,11 +21,7 @@ void subghz_scene_start_on_enter(void* context) { if(subghz->state_notifications == SubGhzNotificationStateStarting) { subghz->state_notifications = SubGhzNotificationStateIDLE; } - subghz_protocol_decoder_raw_set_auto_mode( - subghz_receiver_search_decoder_base_by_name( - subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME), - false); - subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); + subghz_last_settings_set_detect_raw_values(subghz); submenu_add_item( subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz); diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 8b9dd399f..4b7c9077c 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -183,9 +183,10 @@ SubGhz* subghz_alloc() { #if FURI_DEBUG FURI_LOG_D( TAG, - "last frequency: %d, preset: %d", + "last frequency: %d, preset: %d, detect_raw: %d", subghz->last_settings->frequency, - subghz->last_settings->preset); + subghz->last_settings->preset, + subghz->last_settings->detect_raw); #endif subghz_setting_set_default_frequency(subghz->setting, subghz->last_settings->frequency); @@ -215,7 +216,7 @@ SubGhz* subghz_alloc() { subghz_environment_set_nice_flor_s_rainbow_table_file_name( subghz->txrx->environment, EXT_PATH("subghz/assets/nice_flor_s")); subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment); - subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); + subghz_last_settings_set_detect_raw_values(subghz); subghz_worker_set_overrun_callback( subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index 0af8c0a15..29e1655f5 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -1,14 +1,18 @@ #include "subghz_history.h" #include -#include -#include +#include #define SUBGHZ_HISTORY_MAX 65 +#define SUBGHZ_HISTORY_TMP_DIR EXT_PATH("subghz/tmp_history") +#define SUBGHZ_HISTORY_TMP_EXTENSION ".tmp" +#define SUBGHZ_HISTORY_TMP_FILE_KEY "Filename" #define TAG "SubGhzHistory" typedef struct { string_t item_str; FlipperFormat* flipper_string; + string_t protocol_name; + bool is_file; uint8_t type; SubGhzPresetDefinition* preset; } SubGhzHistoryItem; @@ -26,30 +30,134 @@ struct SubGhzHistory { uint16_t last_index_write; uint8_t code_last_hash_data; string_t tmp_string; + bool write_tmp_files; + Storage* storage; SubGhzHistoryStruct* history; }; +#if FURI_DEBUG +#define LOG_DELAY 1 +#endif + +/** + * @brief Generate filename like 000.tmp + * + * @param filename + * @param index - index of file, timestamp doesn't accepted! + */ +void subghz_history_generate_temp_filename(string_t filename, uint32_t index) { + FuriHalRtcDateTime datetime = {0}; + furi_hal_rtc_get_datetime(&datetime); + string_init_printf(filename, "%03d%s", index, SUBGHZ_HISTORY_TMP_EXTENSION); +} + +/** + * @brief Check SD card, recursive delete dir and files and create new dir + * + * @param instance + * @param only_remove_dir + * @return true - if all ok + * @return false - if something failed + */ +bool subghz_history_clear_dir_or_create(SubGhzHistory* instance, bool only_remove_dir) { +#if FURI_DEBUG + FURI_LOG_D(TAG, "subghz_history_clear_dir_or_create: %s", only_remove_dir ? "true" : "false"); + furi_delay_ms(LOG_DELAY); +#endif + + // Stage 0 - SD installed? + FS_Error status = storage_sd_status(instance->storage); + if(status != FSE_OK) { + FURI_LOG_W(TAG, "SD storage not installed! Status: %d", status); + return false; + } + + // Stage 1 - delete all content if exists + FileInfo fileinfo; + storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &fileinfo); + + // This is temp + bool res = instance->write_tmp_files = true; + + // Uncomment it + // if(fileinfo.flags & FSF_DIRECTORY) { + // res = storage_simply_remove_recursive(instance->storage, SUBGHZ_HISTORY_TMP_DIR); + // } else { + // res = (storage_common_remove(instance->storage, SUBGHZ_HISTORY_TMP_DIR) == FSE_OK); + // } + +#if FURI_DEBUG + FURI_LOG_D(TAG, "storage_common_remove done: %s", res ? "true" : "false"); + furi_delay_ms(LOG_DELAY); +#endif + + // Uncomment it + // Stage 2 - create dir + // if(!only_remove_dir && res) { + // res = storage_simply_mkdir(instance->storage, SUBGHZ_HISTORY_TMP_DIR); + // #if FURI_DEBUG + // FURI_LOG_D(TAG, "storage_simply_mkdir done: %s", res ? "true" : "false"); + // furi_delay_ms(LOG_DELAY); + // #endif + // } + + return res; +} + SubGhzHistory* subghz_history_alloc(void) { SubGhzHistory* instance = malloc(sizeof(SubGhzHistory)); string_init(instance->tmp_string); instance->history = malloc(sizeof(SubGhzHistoryStruct)); SubGhzHistoryItemArray_init(instance->history->data); + instance->storage = furi_record_open(RECORD_STORAGE); + instance->write_tmp_files = false; + +#if FURI_DEBUG + FURI_LOG_D(TAG, "BEFORE subghz_history_clear_dir_or_create"); + furi_delay_ms(LOG_DELAY); +#endif + // Check if we can write files on SD + instance->write_tmp_files = subghz_history_clear_dir_or_create(instance, false); + return instance; } +/** + * @brief free all items in array + * + * @param instance + */ +void subghz_history_clean_item_array(SubGhzHistory* instance) { + for + M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) { + string_clear(item->item_str); + string_clear(item->preset->name); + string_clear(item->protocol_name); + + free(item->preset); + item->type = 0; + item->is_file = false; + + if(item->flipper_string != NULL) { + flipper_format_free(item->flipper_string); + } + } +} + void subghz_history_free(SubGhzHistory* instance) { furi_assert(instance); string_clear(instance->tmp_string); - for - M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) { - string_clear(item->item_str); - string_clear(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } + + subghz_history_clean_item_array(instance); SubGhzHistoryItemArray_clear(instance->history->data); free(instance->history); + + if(instance->write_tmp_files) { + instance->write_tmp_files = subghz_history_clear_dir_or_create(instance, true); + } + + furi_record_close(RECORD_STORAGE); + free(instance); } @@ -74,17 +182,16 @@ const char* subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx) { void subghz_history_reset(SubGhzHistory* instance) { furi_assert(instance); string_reset(instance->tmp_string); - for - M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) { - string_clear(item->item_str); - string_clear(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - } + + subghz_history_clean_item_array(instance); + SubGhzHistoryItemArray_reset(instance->history->data); instance->last_index_write = 0; instance->code_last_hash_data = 0; + + if(instance->write_tmp_files) { + instance->write_tmp_files = subghz_history_clear_dir_or_create(instance, false); + } } uint16_t subghz_history_get_item(SubGhzHistory* instance) { @@ -101,12 +208,8 @@ uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx) const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t idx) { furi_assert(instance); SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx); - flipper_format_rewind(item->flipper_string); - if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { - FURI_LOG_E(TAG, "Missing Protocol"); - string_reset(instance->tmp_string); - } - return string_get_cstr(instance->tmp_string); + + return string_get_cstr(item->protocol_name); } FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx) { @@ -115,17 +218,73 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx if(item->flipper_string) { return item->flipper_string; } else { - return NULL; + bool result_ok = false; + if(instance->write_tmp_files && item->is_file) { + // We have files! +#if FURI_DEBUG + FURI_LOG_D(TAG, "We have files!"); + furi_delay_ms(LOG_DELAY); +#endif + string_t filename; + string_t dir_path; + string_init(filename); + string_init(dir_path); + subghz_history_generate_temp_filename(filename, idx); + string_cat_printf( + dir_path, "%s/%s", SUBGHZ_HISTORY_TMP_DIR, string_get_cstr(filename)); + // string_init_printf( + // dir_path, "%s/%s", SUBGHZ_HISTORY_TMP_DIR, string_get_cstr(filename)); + + if(storage_file_exists(instance->storage, string_get_cstr(dir_path))) { +#if FURI_DEBUG + FURI_LOG_D(TAG, "Exist: %s", dir_path); + furi_delay_ms(LOG_DELAY); +#endif + // Set to current anyway it has NULL value + item->flipper_string = flipper_format_string_alloc(); + Stream* dst_stream = flipper_format_get_raw_stream(item->flipper_string); + stream_clean(dst_stream); + + size_t size = stream_load_from_file( + dst_stream, instance->storage, string_get_cstr(dir_path)); + if(size > 0) { +#if FURI_DEBUG + FURI_LOG_I(TAG, "Save ok!"); + furi_delay_ms(LOG_DELAY); +#endif + // We changed contents of file, so we no needed to load + // content from disk for the next time + item->is_file = false; + result_ok = true; + } else { + FURI_LOG_E(TAG, "Stream copy failed!"); + flipper_format_free(item->flipper_string); + } + } else { + FURI_LOG_E(TAG, "Can't convert filename to file"); + } + + string_clear(filename); + string_clear(dir_path); + } else { +#if FURI_DEBUG + FURI_LOG_W(TAG, "Write TMP files failed!"); + furi_delay_ms(LOG_DELAY); +#endif + } + return result_ok ? item->flipper_string : NULL; } } + bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output) { furi_assert(instance); if(instance->last_index_write == SUBGHZ_HISTORY_MAX) { if(output != NULL) string_printf(output, "Memory is FULL"); return true; } - if(output != NULL) + if(output != NULL) { string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX); + } return false; } @@ -141,7 +300,9 @@ bool subghz_history_add_to_history( furi_assert(instance); furi_assert(context); - if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false; + if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) { + return false; + } SubGhzProtocolDecoderBase* decoder_base = context; if((instance->code_last_hash_data == @@ -166,6 +327,9 @@ bool subghz_history_add_to_history( item->preset->data_size = preset->data_size; string_init(item->item_str); + string_init(item->protocol_name); + + // At this point file mapped to memory otherwise file cannot decoded item->flipper_string = flipper_format_string_alloc(); subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset); @@ -177,6 +341,11 @@ bool subghz_history_add_to_history( if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) { FURI_LOG_E(TAG, "Missing Protocol"); break; + } else { + string_init_printf(item->protocol_name, "%s", string_get_cstr(instance->tmp_string)); +#if FURI_DEBUG + FURI_LOG_I(TAG, "File protocol: %s", string_get_cstr(item->protocol_name)); +#endif } if(!strcmp(string_get_cstr(instance->tmp_string), "RAW")) { string_printf( @@ -234,7 +403,62 @@ bool subghz_history_add_to_history( } } while(false); + // Copy streams + // Thinking that some data may be saved + // Stream* src = flipper_format_get_raw_stream(flipper_string); + // stream_seek(src, 0, StreamOffsetFromStart); + + // Stream* dst = string_stream_alloc(); + // stream_clean(dst); + // stream_copy_full(src, dst); + + // If we can write to files + //bool no_close = false; + if(instance->write_tmp_files) { + string_t filename; + string_t dir_path; + string_init(filename); + string_init(dir_path); + + subghz_history_generate_temp_filename(filename, instance->last_index_write); + string_cat_printf(dir_path, "%s/%s", SUBGHZ_HISTORY_TMP_DIR, string_get_cstr(filename)); +#if FURI_DEBUG + FURI_LOG_I(TAG, "Let's do some hack. Create file %s", string_get_cstr(dir_path)); +#endif + Stream* dst = flipper_format_get_raw_stream(item->flipper_string); + stream_rewind(dst); + // stream_seek(dst, 0, StreamOffsetFromStart); + if(stream_save_to_file( + dst, instance->storage, string_get_cstr(dir_path), FSOM_CREATE_ALWAYS) > 0) { + // Free flipper_format + //flipper_format_free(flipper_string); + //flipper_string = NULL; + //stream_free(dst); + flipper_format_free(item->flipper_string); + item->flipper_string = NULL; +#if FURI_DEBUG + FURI_LOG_I(TAG, "Save done!"); +#endif + // This item contains fake data to load from SD + item->is_file = true; + } else { + FURI_LOG_E(TAG, "Stream copy failed!"); + } + string_clear(filename); + string_clear(dir_path); + + /* }*/ + } else { +#if FURI_DEBUG + FURI_LOG_I(TAG, "Old fashion way"); +#endif + // Old fashion way + //item->flipper_string = dst; + } + //flipper_format_free(flipper_string); + string_clear(text); + instance->last_index_write++; return true; } diff --git a/applications/main/subghz/subghz_last_settings.c b/applications/main/subghz/subghz_last_settings.c index b24273cf3..8dd2c165a 100644 --- a/applications/main/subghz/subghz_last_settings.c +++ b/applications/main/subghz/subghz_last_settings.c @@ -1,5 +1,6 @@ #include "subghz_last_settings.h" -#include +#include "subghz_i.h" +#include #define TAG "SubGhzLastSettings" @@ -10,6 +11,11 @@ // "AM270", "AM650", "FM238", "FM476", #define SUBGHZ_LAST_SETTING_DEFAULT_PRESET 1 #define SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY 433920000 +#define SUBGHZ_LAST_SETTING_DEFAULT_READ_RAW 0 + +#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY "Frequency" +#define SUBGHZ_LAST_SETTING_FIELD_PRESET "Preset" +#define SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW "DetectRaw" SubGhzLastSettings* subghz_last_settings_alloc(void) { SubGhzLastSettings* instance = malloc(sizeof(SubGhzLastSettings)); @@ -32,11 +38,16 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count uint32_t temp_frequency = 0; int32_t temp_preset = 0; + uint32_t temp_read_raw = 0; if(FSE_OK == storage_sd_status(storage) && SUBGHZ_LAST_SETTINGS_PATH && flipper_format_file_open_existing(fff_data_file, SUBGHZ_LAST_SETTINGS_PATH)) { - flipper_format_read_int32(fff_data_file, "Preset", (int32_t*)&temp_preset, 1); - flipper_format_read_uint32(fff_data_file, "Frequency", (uint32_t*)&temp_frequency, 1); + flipper_format_read_int32( + fff_data_file, SUBGHZ_LAST_SETTING_FIELD_PRESET, (int32_t*)&temp_preset, 1); + flipper_format_read_uint32( + fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY, (uint32_t*)&temp_frequency, 1); + flipper_format_read_uint32( + fff_data_file, SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW, (uint32_t*)&temp_read_raw, 1); } else { FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH); } @@ -45,8 +56,10 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count FURI_LOG_W(TAG, "Last used frequency not found or can't be used!"); instance->frequency = SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY; instance->preset = SUBGHZ_LAST_SETTING_DEFAULT_PRESET; + instance->detect_raw = SUBGHZ_LAST_SETTING_DEFAULT_READ_RAW; } else { instance->frequency = temp_frequency; + instance->detect_raw = temp_read_raw; if(temp_preset > (int32_t)preset_count - 1 || temp_preset < 0) { FURI_LOG_W(TAG, "Last used preset no found"); @@ -84,10 +97,16 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) { file, SUBGHZ_LAST_SETTING_FILE_TYPE, SUBGHZ_LAST_SETTING_FILE_VERSION)) break; - if(!flipper_format_insert_or_update_int32(file, "Preset", &instance->preset, 1)) { + if(!flipper_format_insert_or_update_int32( + file, SUBGHZ_LAST_SETTING_FIELD_PRESET, &instance->preset, 1)) { break; } - if(!flipper_format_insert_or_update_uint32(file, "Frequency", &instance->frequency, 1)) { + if(!flipper_format_insert_or_update_uint32( + file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY, &instance->frequency, 1)) { + break; + } + if(!flipper_format_insert_or_update_uint32( + file, SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW, &instance->detect_raw, 1)) { break; } saved = true; @@ -102,4 +121,16 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) { furi_record_close(RECORD_STORAGE); return saved; +} + +void subghz_last_settings_set_detect_raw_values(void* context) { + furi_assert(context); + SubGhz* instance = (SubGhz*)context; + bool is_detect_raw = instance->last_settings->detect_raw > 0; + subghz_receiver_set_filter( + instance->txrx->receiver, is_detect_raw ? DETECT_RAW_TRUE : DETECT_RAW_FALSE); + subghz_protocol_decoder_raw_set_auto_mode( + subghz_receiver_search_decoder_base_by_name( + instance->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME), + is_detect_raw); } \ No newline at end of file diff --git a/applications/main/subghz/subghz_last_settings.h b/applications/main/subghz/subghz_last_settings.h index 8067bb66a..5efc7ebb0 100644 --- a/applications/main/subghz/subghz_last_settings.h +++ b/applications/main/subghz/subghz_last_settings.h @@ -4,9 +4,14 @@ #include #include #include +#include + +#define DETECT_RAW_FALSE SubGhzProtocolFlag_Decodable +#define DETECT_RAW_TRUE SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW typedef struct { uint32_t frequency; + uint32_t detect_raw; int32_t preset; } SubGhzLastSettings; @@ -16,4 +21,6 @@ void subghz_last_settings_free(SubGhzLastSettings* instance); void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count); -bool subghz_last_settings_save(SubGhzLastSettings* instance); \ No newline at end of file +bool subghz_last_settings_save(SubGhzLastSettings* instance); + +void subghz_last_settings_set_detect_raw_values(void* context); \ No newline at end of file