Просмотр исходного кода

[FL-2669] SubGhz: add support for loading custom presets (#1398)

* SubGhz: load custom -preset
* SubGhz: fix error prt=0
* SubGhz: load custom preset
* SubGhz: code refactoring to support custom preset
* SubGhz: add custom presert refactoring
* SubGhz: fix alloc history alloc preset
* SubGhz: fix error load file
* SubGhz: fix start custom preset
* SubGhz: fix delete custom preset
* SubGhz: add description Custom_preset_data for CC1101
* SubGhz: debug logging and buffer size rounding

Co-authored-by: あく <alleteam@gmail.com>
Co-authored-by: Aleksandr Kutuzov <aku@plooks.com>
Skorpionm 3 лет назад
Родитель
Сommit
ec19c11dbe
75 измененных файлов с 681 добавлено и 454 удалено
  1. 13 0
      applications/subghz/helpers/subghz_types.h
  2. 6 2
      applications/subghz/scenes/subghz_scene_need_saving.c
  3. 11 5
      applications/subghz/scenes/subghz_scene_read_raw.c
  4. 14 8
      applications/subghz/scenes/subghz_scene_receiver.c
  5. 28 36
      applications/subghz/scenes/subghz_scene_receiver_config.c
  6. 15 6
      applications/subghz/scenes/subghz_scene_receiver_info.c
  7. 24 62
      applications/subghz/scenes/subghz_scene_set_type.c
  8. 7 2
      applications/subghz/subghz.c
  9. 21 9
      applications/subghz/subghz_history.c
  10. 7 6
      applications/subghz/subghz_history.h
  11. 63 28
      applications/subghz/subghz_i.c
  12. 10 5
      applications/subghz/subghz_i.h
  13. 197 5
      applications/subghz/subghz_setting.c
  14. 22 0
      applications/subghz/subghz_setting.h
  15. 19 8
      assets/resources/subghz/assets/setting_user
  16. 43 10
      firmware/targets/f7/furi_hal/furi_hal_subghz.c
  17. 9 2
      firmware/targets/furi_hal_include/furi_hal_subghz.h
  18. 29 28
      lib/subghz/blocks/generic.c
  19. 7 9
      lib/subghz/blocks/generic.h
  20. 2 4
      lib/subghz/protocols/base.c
  21. 2 4
      lib/subghz/protocols/base.h
  22. 2 3
      lib/subghz/protocols/came.c
  23. 2 4
      lib/subghz/protocols/came.h
  24. 2 3
      lib/subghz/protocols/came_atomo.c
  25. 2 4
      lib/subghz/protocols/came_atomo.h
  26. 2 3
      lib/subghz/protocols/came_twee.c
  27. 2 4
      lib/subghz/protocols/came_twee.h
  28. 2 3
      lib/subghz/protocols/chamberlain_code.c
  29. 2 4
      lib/subghz/protocols/chamberlain_code.h
  30. 2 3
      lib/subghz/protocols/faac_slh.c
  31. 2 4
      lib/subghz/protocols/faac_slh.h
  32. 2 3
      lib/subghz/protocols/gate_tx.c
  33. 2 4
      lib/subghz/protocols/gate_tx.h
  34. 2 3
      lib/subghz/protocols/holtek.c
  35. 2 4
      lib/subghz/protocols/holtek.h
  36. 2 3
      lib/subghz/protocols/hormann.c
  37. 2 4
      lib/subghz/protocols/hormann.h
  38. 2 3
      lib/subghz/protocols/ido.c
  39. 2 4
      lib/subghz/protocols/ido.h
  40. 4 8
      lib/subghz/protocols/keeloq.c
  41. 4 8
      lib/subghz/protocols/keeloq.h
  42. 2 3
      lib/subghz/protocols/kia.c
  43. 2 4
      lib/subghz/protocols/kia.h
  44. 2 3
      lib/subghz/protocols/linear.c
  45. 2 4
      lib/subghz/protocols/linear.h
  46. 2 3
      lib/subghz/protocols/megacode.c
  47. 2 4
      lib/subghz/protocols/megacode.h
  48. 2 3
      lib/subghz/protocols/nero_radio.c
  49. 2 4
      lib/subghz/protocols/nero_radio.h
  50. 2 3
      lib/subghz/protocols/nero_sketch.c
  51. 2 4
      lib/subghz/protocols/nero_sketch.h
  52. 2 3
      lib/subghz/protocols/nice_flo.c
  53. 2 4
      lib/subghz/protocols/nice_flo.h
  54. 2 3
      lib/subghz/protocols/nice_flor_s.c
  55. 2 4
      lib/subghz/protocols/nice_flor_s.h
  56. 2 3
      lib/subghz/protocols/power_smart.c
  57. 2 4
      lib/subghz/protocols/power_smart.h
  58. 2 4
      lib/subghz/protocols/princeton.c
  59. 2 4
      lib/subghz/protocols/princeton.h
  60. 17 7
      lib/subghz/protocols/raw.c
  61. 2 4
      lib/subghz/protocols/raw.h
  62. 2 3
      lib/subghz/protocols/scher_khan.c
  63. 2 4
      lib/subghz/protocols/scher_khan.h
  64. 2 3
      lib/subghz/protocols/secplus_v1.c
  65. 2 4
      lib/subghz/protocols/secplus_v1.h
  66. 4 8
      lib/subghz/protocols/secplus_v2.c
  67. 4 8
      lib/subghz/protocols/secplus_v2.h
  68. 2 4
      lib/subghz/protocols/somfy_keytis.c
  69. 2 4
      lib/subghz/protocols/somfy_keytis.h
  70. 2 3
      lib/subghz/protocols/somfy_telis.c
  71. 2 4
      lib/subghz/protocols/somfy_telis.h
  72. 2 4
      lib/subghz/protocols/star_line.c
  73. 2 4
      lib/subghz/protocols/star_line.h
  74. 2 3
      lib/subghz/subghz_worker.c
  75. 3 5
      lib/subghz/types.h

+ 13 - 0
applications/subghz/helpers/subghz_types.h

@@ -1,5 +1,9 @@
 #pragma once
 
+#include "m-string.h"
+#include <furi.h>
+#include <furi_hal.h>
+
 /** SubGhzNotification state */
 typedef enum {
     SubGhzNotificationStateStarting,
@@ -67,3 +71,12 @@ typedef enum {
     SubGhzViewIdTestCarrier,
     SubGhzViewIdTestPacket,
 } SubGhzViewId;
+
+struct SubGhzPesetDefinition {
+    string_t name;
+    uint32_t frequency;
+    uint8_t* data;
+    size_t data_size;
+};
+
+typedef struct SubGhzPesetDefinition SubGhzPesetDefinition;

+ 6 - 2
applications/subghz/scenes/subghz_scene_need_saving.c

@@ -48,8 +48,12 @@ bool subghz_scene_need_saving_on_event(void* context, SceneManagerEvent event) {
         } else if(event.event == SubGhzCustomEventSceneExit) {
             if(subghz->txrx->rx_key_state == SubGhzRxKeyStateExit) {
                 subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
-                subghz->txrx->frequency = subghz_setting_get_default_frequency(subghz->setting);
-                subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
+                subghz_preset_init(
+                    subghz,
+                    "AM650",
+                    subghz_setting_get_default_frequency(subghz->setting),
+                    NULL,
+                    0);
                 scene_manager_search_and_switch_to_previous_scene(
                     subghz->scene_manager, SubGhzSceneStart);
             } else {

+ 11 - 5
applications/subghz/scenes/subghz_scene_read_raw.c

@@ -131,8 +131,12 @@ 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_setting_get_default_frequency(subghz->setting);
-                subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
+                subghz_preset_init(
+                    subghz,
+                    "AM650",
+                    subghz_setting_get_default_frequency(subghz->setting),
+                    NULL,
+                    0);
                 if(!scene_manager_search_and_switch_to_previous_scene(
                        subghz->scene_manager, SubGhzSceneSaved)) {
                     if(!scene_manager_search_and_switch_to_previous_scene(
@@ -268,13 +272,15 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
                 if(subghz_protocol_raw_save_to_file_init(
                        (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result,
                        RAW_FILE_NAME,
-                       subghz->txrx->frequency,
                        subghz->txrx->preset)) {
                     DOLPHIN_DEED(DolphinDeedSubGhzRawRec);
                     if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) ||
                        (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) {
-                        subghz_begin(subghz, subghz->txrx->preset);
-                        subghz_rx(subghz, subghz->txrx->frequency);
+                        subghz_begin(
+                            subghz,
+                            subghz_setting_get_preset_data_by_name(
+                                subghz->setting, string_get_cstr(subghz->txrx->preset->name)));
+                        subghz_rx(subghz, subghz->txrx->preset->frequency);
                     }
                     subghz->state_notifications = SubGhzNotificationStateRx;
                     subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey;

+ 14 - 8
applications/subghz/scenes/subghz_scene_receiver.c

@@ -75,8 +75,7 @@ static void subghz_scene_add_to_history_callback(
     string_t str_buff;
     string_init(str_buff);
 
-    if(subghz_history_add_to_history(
-           subghz->txrx->history, decoder_base, subghz->txrx->frequency, subghz->txrx->preset)) {
+    if(subghz_history_add_to_history(subghz->txrx->history, decoder_base, subghz->txrx->preset)) {
         string_reset(str_buff);
 
         subghz->state_notifications = SubGhzNotificationStateRxDone;
@@ -103,8 +102,8 @@ void subghz_scene_receiver_on_enter(void* context) {
     string_init(str_buff);
 
     if(subghz->txrx->rx_key_state == SubGhzRxKeyStateIDLE) {
-        subghz->txrx->frequency = subghz_setting_get_default_frequency(subghz->setting);
-        subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
+        subghz_preset_init(
+            subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
         subghz_history_reset(subghz->txrx->history);
         subghz->txrx->rx_key_state = SubGhzRxKeyStateStart;
     }
@@ -135,8 +134,11 @@ void subghz_scene_receiver_on_enter(void* context) {
     };
     if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) ||
        (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) {
-        subghz_begin(subghz, subghz->txrx->preset);
-        subghz_rx(subghz, subghz->txrx->frequency);
+        subghz_begin(
+            subghz,
+            subghz_setting_get_preset_data_by_name(
+                subghz->setting, string_get_cstr(subghz->txrx->preset->name)));
+        subghz_rx(subghz, subghz->txrx->preset->frequency);
     }
     subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen);
 
@@ -164,8 +166,12 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
             } else {
                 subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
-                subghz->txrx->frequency = subghz_setting_get_default_frequency(subghz->setting);
-                subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
+                subghz_preset_init(
+                    subghz,
+                    "AM650",
+                    subghz_setting_get_default_frequency(subghz->setting),
+                    NULL,
+                    0);
                 scene_manager_search_and_switch_to_previous_scene(
                     subghz->scene_manager, SubGhzSceneStart);
             }

+ 28 - 36
applications/subghz/scenes/subghz_scene_receiver_config.c

@@ -7,20 +7,6 @@ enum SubGhzSettingIndex {
     SubGhzSettingIndexLock,
 };
 
-#define PRESET_COUNT 4
-const char* const preset_text[PRESET_COUNT] = {
-    "AM270",
-    "AM650",
-    "FM238",
-    "FM476",
-};
-const uint32_t preset_value[PRESET_COUNT] = {
-    FuriHalSubGhzPresetOok270Async, /** OOK, bandwidth 270kHz, asynchronous */
-    FuriHalSubGhzPresetOok650Async, /** OOK, bandwidth 650kHz, asynchronous */
-    FuriHalSubGhzPreset2FSKDev238Async, /** FM, deviation 2.380371 kHz, asynchronous */
-    FuriHalSubGhzPreset2FSKDev476Async, /** FM, deviation 4.760742 kHz, asynchronous */
-};
-
 #define HOPPING_COUNT 2
 const char* const hopping_text[HOPPING_COUNT] = {
     "OFF",
@@ -31,32 +17,31 @@ const uint32_t hopping_value[HOPPING_COUNT] = {
     SubGhzHopperStateRunnig,
 };
 
-uint8_t subghz_scene_receiver_config_uint32_value_index(
-    const uint32_t value,
-    const uint32_t values[],
-    uint8_t values_count) {
-    int64_t last_value = INT64_MIN;
+uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
+    furi_assert(context);
+    SubGhz* subghz = context;
     uint8_t index = 0;
-    for(uint8_t i = 0; i < values_count; i++) {
-        if((value >= last_value) && (value <= values[i])) {
+    for(uint8_t i = 0; i < subghz_setting_get_frequency_count(subghz->setting); i++) {
+        if(value == subghz_setting_get_frequency(subghz->setting, i)) {
             index = i;
             break;
+        } else {
+            index = subghz_setting_get_frequency_default_index(subghz->setting);
         }
-        last_value = values[i];
     }
     return index;
 }
 
-uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
+uint8_t subghz_scene_receiver_config_next_preset(const char* preset_name, void* context) {
     furi_assert(context);
     SubGhz* subghz = context;
     uint8_t index = 0;
-    for(uint8_t i = 0; i < subghz_setting_get_frequency_count(subghz->setting); i++) {
-        if(value == subghz_setting_get_frequency(subghz->setting, i)) {
+    for(uint8_t i = 0; i < subghz_setting_get_preset_count(subghz->setting); i++) {
+        if(!strcmp(subghz_setting_get_preset_name(subghz->setting, i), preset_name)) {
             index = i;
             break;
         } else {
-            index = subghz_setting_get_frequency_default_index(subghz->setting);
+            //  index = subghz_setting_get_frequency_default_index(subghz->setting);
         }
     }
     return index;
@@ -94,7 +79,7 @@ static void subghz_scene_receiver_config_set_frequency(VariableItem* item) {
             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);
+        subghz->txrx->preset->frequency = subghz_setting_get_frequency(subghz->setting, index);
     } else {
         variable_item_set_current_value_index(
             item, subghz_setting_get_frequency_default_index(subghz->setting));
@@ -104,9 +89,14 @@ static void subghz_scene_receiver_config_set_frequency(VariableItem* item) {
 static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
     SubGhz* subghz = variable_item_get_context(item);
     uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, preset_text[index]);
-    subghz->txrx->preset = preset_value[index];
+    variable_item_set_current_value_text(
+        item, subghz_setting_get_preset_name(subghz->setting, index));
+    subghz_preset_init(
+        subghz,
+        subghz_setting_get_preset_name(subghz->setting, index),
+        subghz->txrx->preset->frequency,
+        subghz_setting_get_preset_data(subghz->setting, index),
+        subghz_setting_get_preset_data_size(subghz->setting, index));
 }
 
 static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item) {
@@ -125,7 +115,7 @@ static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item)
             (VariableItem*)scene_manager_get_scene_state(
                 subghz->scene_manager, SubGhzSceneReceiverConfig),
             text_buf);
-        subghz->txrx->frequency = subghz_setting_get_default_frequency(subghz->setting);
+        subghz->txrx->preset->frequency = subghz_setting_get_default_frequency(subghz->setting);
         variable_item_set_current_value_index(
             (VariableItem*)scene_manager_get_scene_state(
                 subghz->scene_manager, SubGhzSceneReceiverConfig),
@@ -164,7 +154,8 @@ void subghz_scene_receiver_config_on_enter(void* context) {
         subghz_setting_get_frequency_count(subghz->setting),
         subghz_scene_receiver_config_set_frequency,
         subghz);
-    value_index = subghz_scene_receiver_config_next_frequency(subghz->txrx->frequency, subghz);
+    value_index =
+        subghz_scene_receiver_config_next_frequency(subghz->txrx->preset->frequency, subghz);
     scene_manager_set_scene_state(
         subghz->scene_manager, SubGhzSceneReceiverConfig, (uint32_t)item);
     variable_item_set_current_value_index(item, value_index);
@@ -193,13 +184,14 @@ void subghz_scene_receiver_config_on_enter(void* context) {
     item = variable_item_list_add(
         subghz->variable_item_list,
         "Modulation:",
-        PRESET_COUNT,
+        subghz_setting_get_preset_count(subghz->setting),
         subghz_scene_receiver_config_set_preset,
         subghz);
-    value_index = subghz_scene_receiver_config_uint32_value_index(
-        subghz->txrx->preset, preset_value, PRESET_COUNT);
+    value_index = subghz_scene_receiver_config_next_preset(
+        string_get_cstr(subghz->txrx->preset->name), subghz);
     variable_item_set_current_value_index(item, value_index);
-    variable_item_set_current_value_text(item, preset_text[value_index]);
+    variable_item_set_current_value_text(
+        item, subghz_setting_get_preset_name(subghz->setting, value_index));
 
     if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
        SubGhzCustomEventManagerSet) {

+ 15 - 6
applications/subghz/scenes/subghz_scene_receiver_info.c

@@ -27,10 +27,16 @@ static bool subghz_scene_receiver_info_update_parser(void* context) {
         subghz_protocol_decoder_base_deserialize(
             subghz->txrx->decoder_result,
             subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen));
-        subghz->txrx->frequency =
-            subghz_history_get_frequency(subghz->txrx->history, subghz->txrx->idx_menu_chosen);
-        subghz->txrx->preset =
-            subghz_history_get_preset(subghz->txrx->history, subghz->txrx->idx_menu_chosen);
+
+        SubGhzPesetDefinition* preset =
+            subghz_history_get_presset(subghz->txrx->history, subghz->txrx->idx_menu_chosen);
+        subghz_preset_init(
+            subghz,
+            string_get_cstr(preset->name),
+            preset->frequency,
+            preset->data,
+            preset->data_size);
+
         return true;
     }
     return false;
@@ -137,8 +143,11 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
                 subghz_tx_stop(subghz);
             }
             if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) {
-                subghz_begin(subghz, subghz->txrx->preset);
-                subghz_rx(subghz, subghz->txrx->frequency);
+                subghz_begin(
+                    subghz,
+                    subghz_setting_get_preset_data_by_name(
+                        subghz->setting, string_get_cstr(subghz->txrx->preset->name)));
+                subghz_rx(subghz, subghz->txrx->preset->frequency);
             }
             if(subghz->txrx->hopper_state == SubGhzHopperStatePause) {
                 subghz->txrx->hopper_state = SubGhzHopperStateRunnig;

+ 24 - 62
applications/subghz/scenes/subghz_scene_set_type.c

@@ -16,12 +16,13 @@ bool subghz_scene_set_type_submenu_gen_data_protocol(
     uint64_t key,
     uint32_t bit,
     uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    const char* preset_name) {
     furi_assert(context);
     SubGhz* subghz = context;
 
     bool res = false;
 
+    subghz_preset_init(subghz, preset_name, frequency, NULL, 0);
     subghz->txrx->decoder_result =
         subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, protocol_name);
 
@@ -35,7 +36,7 @@ bool subghz_scene_set_type_submenu_gen_data_protocol(
         Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data);
         stream_clean(fff_data_stream);
         if(!subghz_protocol_decoder_base_serialize(
-               subghz->txrx->decoder_result, subghz->txrx->fff_data, frequency, preset)) {
+               subghz->txrx->decoder_result, subghz->txrx->fff_data, subghz->txrx->preset)) {
             FURI_LOG_E(TAG, "Unable to serialize");
             break;
         }
@@ -177,12 +178,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
         case SubmenuIndexPricenton:
             key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
             if(subghz_scene_set_type_submenu_gen_data_protocol(
-                   subghz,
-                   SUBGHZ_PROTOCOL_PRINCETON_NAME,
-                   key,
-                   24,
-                   433920000,
-                   FuriHalSubGhzPresetOok650Async)) {
+                   subghz, SUBGHZ_PROTOCOL_PRINCETON_NAME, key, 24, 433920000, "AM650")) {
                 uint32_t te = 400;
                 flipper_format_update_uint32(subghz->txrx->fff_data, "TE", (uint32_t*)&te, 1);
                 generated_protocol = true;
@@ -191,60 +187,35 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
         case SubmenuIndexNiceFlo12bit:
             key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4
             if(subghz_scene_set_type_submenu_gen_data_protocol(
-                   subghz,
-                   SUBGHZ_PROTOCOL_NICE_FLO_NAME,
-                   key,
-                   12,
-                   433920000,
-                   FuriHalSubGhzPresetOok650Async)) {
+                   subghz, SUBGHZ_PROTOCOL_NICE_FLO_NAME, key, 12, 433920000, "AM650")) {
                 generated_protocol = true;
             }
             break;
         case SubmenuIndexNiceFlo24bit:
             key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
             if(subghz_scene_set_type_submenu_gen_data_protocol(
-                   subghz,
-                   SUBGHZ_PROTOCOL_NICE_FLO_NAME,
-                   key,
-                   24,
-                   433920000,
-                   FuriHalSubGhzPresetOok650Async)) {
+                   subghz, SUBGHZ_PROTOCOL_NICE_FLO_NAME, key, 24, 433920000, "AM650")) {
                 generated_protocol = true;
             }
             break;
         case SubmenuIndexCAME12bit:
             key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4
             if(subghz_scene_set_type_submenu_gen_data_protocol(
-                   subghz,
-                   SUBGHZ_PROTOCOL_CAME_NAME,
-                   key,
-                   12,
-                   433920000,
-                   FuriHalSubGhzPresetOok650Async)) {
+                   subghz, SUBGHZ_PROTOCOL_CAME_NAME, key, 12, 433920000, "AM650")) {
                 generated_protocol = true;
             }
             break;
         case SubmenuIndexCAME24bit:
             key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
             if(subghz_scene_set_type_submenu_gen_data_protocol(
-                   subghz,
-                   SUBGHZ_PROTOCOL_CAME_NAME,
-                   key,
-                   24,
-                   433920000,
-                   FuriHalSubGhzPresetOok650Async)) {
+                   subghz, SUBGHZ_PROTOCOL_CAME_NAME, key, 24, 433920000, "AM650")) {
                 generated_protocol = true;
             }
             break;
         case SubmenuIndexLinear_300_00:
             key = (key & 0x3FF);
             if(subghz_scene_set_type_submenu_gen_data_protocol(
-                   subghz,
-                   SUBGHZ_PROTOCOL_LINEAR_NAME,
-                   key,
-                   10,
-                   300000000,
-                   FuriHalSubGhzPresetOok650Async)) {
+                   subghz, SUBGHZ_PROTOCOL_LINEAR_NAME, key, 10, 300000000, "AM650")) {
                 generated_protocol = true;
             }
             break;
@@ -252,12 +223,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
             key = (key & 0x0FFFFFF0);
             key = 0x003FFF7200000000 | (key ^ 0xE0E0E0EE);
             if(subghz_scene_set_type_submenu_gen_data_protocol(
-                   subghz,
-                   SUBGHZ_PROTOCOL_CAME_TWEE_NAME,
-                   key,
-                   54,
-                   433920000,
-                   FuriHalSubGhzPresetOok650Async)) {
+                   subghz, SUBGHZ_PROTOCOL_CAME_TWEE_NAME, key, 54, 433920000, "AM650")) {
                 generated_protocol = true;
             }
             break;
@@ -271,18 +237,15 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
             key = (key & 0x00F0FF00) | 0xF << 16 | 0x40; //btn 0xF, 0xC, 0xA, 0x6 (?)
             uint64_t rev_key = subghz_protocol_blocks_reverse_key(key, 24);
             if(subghz_scene_set_type_submenu_gen_data_protocol(
-                   subghz,
-                   SUBGHZ_PROTOCOL_GATE_TX_NAME,
-                   rev_key,
-                   24,
-                   433920000,
-                   FuriHalSubGhzPresetOok650Async)) {
+                   subghz, SUBGHZ_PROTOCOL_GATE_TX_NAME, rev_key, 24, 433920000, "AM650")) {
                 generated_protocol = true;
             }
             break;
         case SubmenuIndexDoorHan_433_92:
             subghz->txrx->transmitter = subghz_transmitter_alloc_init(
                 subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME);
+            subghz_preset_init(
+                subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
             if(subghz->txrx->transmitter) {
                 subghz_protocol_keeloq_create_data(
                     subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
@@ -291,8 +254,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
                     0x2,
                     0x0003,
                     "DoorHan",
-                    subghz_setting_get_default_frequency(subghz->setting),
-                    FuriHalSubGhzPresetOok650Async);
+                    subghz->txrx->preset);
                 generated_protocol = true;
             } else {
                 generated_protocol = false;
@@ -307,6 +269,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
         case SubmenuIndexDoorHan_315_00:
             subghz->txrx->transmitter = subghz_transmitter_alloc_init(
                 subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME);
+            subghz_preset_init(subghz, "AM650", 315000000, NULL, 0);
             if(subghz->txrx->transmitter) {
                 subghz_protocol_keeloq_create_data(
                     subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
@@ -315,8 +278,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
                     0x2,
                     0x0003,
                     "DoorHan",
-                    315000000,
-                    FuriHalSubGhzPresetOok650Async);
+                    subghz->txrx->preset);
                 generated_protocol = true;
             } else {
                 generated_protocol = false;
@@ -338,7 +300,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
                    (uint64_t)key << 32 | 0xE6000000,
                    42,
                    315000000,
-                   FuriHalSubGhzPresetOok650Async)) {
+                   "AM650")) {
                 generated_protocol = true;
             }
             break;
@@ -352,13 +314,14 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
                    (uint64_t)key << 32 | 0xE6000000,
                    42,
                    390000000,
-                   FuriHalSubGhzPresetOok650Async)) {
+                   "AM650")) {
                 generated_protocol = true;
             }
             break;
         case SubmenuIndexSecPlus_v2_310_00:
             subghz->txrx->transmitter = subghz_transmitter_alloc_init(
                 subghz->txrx->environment, SUBGHZ_PROTOCOL_SECPLUS_V2_NAME);
+            subghz_preset_init(subghz, "AM650", 310000000, NULL, 0);
             if(subghz->txrx->transmitter) {
                 subghz_protocol_secplus_v2_create_data(
                     subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
@@ -366,8 +329,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
                     key,
                     0x68,
                     0xE500000,
-                    310000000,
-                    FuriHalSubGhzPresetOok650Async);
+                    subghz->txrx->preset);
                 generated_protocol = true;
             } else {
                 generated_protocol = false;
@@ -377,6 +339,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
         case SubmenuIndexSecPlus_v2_315_00:
             subghz->txrx->transmitter = subghz_transmitter_alloc_init(
                 subghz->txrx->environment, SUBGHZ_PROTOCOL_SECPLUS_V2_NAME);
+            subghz_preset_init(subghz, "AM650", 315000000, NULL, 0);
             if(subghz->txrx->transmitter) {
                 subghz_protocol_secplus_v2_create_data(
                     subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
@@ -384,8 +347,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
                     key,
                     0x68,
                     0xE500000,
-                    315000000,
-                    FuriHalSubGhzPresetOok650Async);
+                    subghz->txrx->preset);
                 generated_protocol = true;
             } else {
                 generated_protocol = false;
@@ -395,6 +357,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
         case SubmenuIndexSecPlus_v2_390_00:
             subghz->txrx->transmitter = subghz_transmitter_alloc_init(
                 subghz->txrx->environment, SUBGHZ_PROTOCOL_SECPLUS_V2_NAME);
+            subghz_preset_init(subghz, "AM650", 390000000, NULL, 0);
             if(subghz->txrx->transmitter) {
                 subghz_protocol_secplus_v2_create_data(
                     subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
@@ -402,8 +365,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
                     key,
                     0x68,
                     0xE500000,
-                    390000000,
-                    FuriHalSubGhzPresetOok650Async);
+                    subghz->txrx->preset);
                 generated_protocol = true;
             } else {
                 generated_protocol = false;

+ 7 - 2
applications/subghz/subghz.c

@@ -199,8 +199,11 @@ SubGhz* subghz_alloc() {
     //init Worker & Protocol & History & KeyBoard
     subghz->lock = SubGhzLockOff;
     subghz->txrx = malloc(sizeof(SubGhzTxRx));
-    subghz->txrx->frequency = subghz_setting_get_default_frequency(subghz->setting);
-    subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
+    subghz->txrx->preset = malloc(sizeof(SubGhzPesetDefinition));
+    string_init(subghz->txrx->preset->name);
+    subghz_preset_init(
+        subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
+
     subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
     subghz->txrx->hopper_state = SubGhzHopperStateOFF;
     subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
@@ -308,6 +311,8 @@ void subghz_free(SubGhz* subghz) {
     subghz_worker_free(subghz->txrx->worker);
     flipper_format_free(subghz->txrx->fff_data);
     subghz_history_free(subghz->txrx->history);
+    string_clear(subghz->txrx->preset->name);
+    free(subghz->txrx->preset);
     free(subghz->txrx);
 
     //Error string

+ 21 - 9
applications/subghz/subghz_history.c

@@ -12,8 +12,7 @@ typedef struct {
     string_t item_str;
     FlipperFormat* flipper_string;
     uint8_t type;
-    FuriHalSubGhzPreset preset;
-    uint32_t frequency;
+    SubGhzPesetDefinition* preset;
 } SubGhzHistoryItem;
 
 ARRAY_DEF(SubGhzHistoryItemArray, SubGhzHistoryItem, M_POD_OPLIST)
@@ -46,6 +45,8 @@ void subghz_history_free(SubGhzHistory* instance) {
     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;
         }
@@ -57,21 +58,29 @@ void subghz_history_free(SubGhzHistory* instance) {
 uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx) {
     furi_assert(instance);
     SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
-    return item->frequency;
+    return item->preset->frequency;
 }
 
-FuriHalSubGhzPreset subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx) {
+SubGhzPesetDefinition* subghz_history_get_presset(SubGhzHistory* instance, uint16_t idx) {
     furi_assert(instance);
     SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
     return item->preset;
 }
 
+const char* subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx) {
+    furi_assert(instance);
+    SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
+    return string_get_cstr(item->preset->name);
+}
+
 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;
         }
@@ -130,8 +139,7 @@ void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output,
 bool subghz_history_add_to_history(
     SubGhzHistory* instance,
     void* context,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(instance);
     furi_assert(context);
 
@@ -151,13 +159,17 @@ bool subghz_history_add_to_history(
     string_t text;
     string_init(text);
     SubGhzHistoryItem* item = SubGhzHistoryItemArray_push_raw(instance->history->data);
+    item->preset = malloc(sizeof(SubGhzPesetDefinition));
     item->type = decoder_base->protocol->type;
-    item->frequency = frequency;
-    item->preset = preset;
+    item->preset->frequency = preset->frequency;
+    string_init(item->preset->name);
+    string_set(item->preset->name, preset->name);
+    item->preset->data = preset->data;
+    item->preset->data_size = preset->data_size;
 
     string_init(item->item_str);
     item->flipper_string = flipper_format_string_alloc();
-    subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, frequency, preset);
+    subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset);
 
     do {
         if(!flipper_format_rewind(item->flipper_string)) {

+ 7 - 6
applications/subghz/subghz_history.h

@@ -5,6 +5,7 @@
 #include <furi.h>
 #include <furi_hal.h>
 #include <lib/flipper_format/flipper_format.h>
+#include "helpers/subghz_types.h"
 
 typedef struct SubGhzHistory SubGhzHistory;
 
@@ -34,13 +35,15 @@ void subghz_history_reset(SubGhzHistory* instance);
  */
 uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx);
 
+SubGhzPesetDefinition* subghz_history_get_presset(SubGhzHistory* instance, uint16_t idx);
+
 /** Get preset to history[idx]
  * 
  * @param instance  - SubGhzHistory instance
  * @param idx       - record index  
- * @return preset    - FuriHalSubGhzPreset preset
+ * @return preset   - preset name
  */
-FuriHalSubGhzPreset subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx);
+const char* subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx);
 
 /** Get history index write 
  * 
@@ -85,15 +88,13 @@ bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output
  * 
  * @param instance  - SubGhzHistory instance
  * @param context    - SubGhzProtocolCommon context
- * @param frequency - frequency Hz
- * @param preset    - FuriHalSubGhzPreset preset
+ * @param preset    - SubGhzPesetDefinition preset
  * @return bool;
  */
 bool subghz_history_add_to_history(
     SubGhzHistory* instance,
     void* context,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data
  * 

+ 63 - 28
applications/subghz/subghz_i.c

@@ -1,7 +1,6 @@
 #include "subghz_i.h"
 
 #include "assets_icons.h"
-#include "m-string.h"
 #include "subghz/types.h"
 #include <math.h>
 #include <furi.h>
@@ -19,15 +18,31 @@
 
 #define TAG "SubGhz"
 
+void subghz_preset_init(
+    void* context,
+    const char* preset_name,
+    uint32_t frequency,
+    uint8_t* preset_data,
+    size_t preset_data_size) {
+    furi_assert(context);
+    SubGhz* subghz = context;
+    string_set(subghz->txrx->preset->name, preset_name);
+    subghz->txrx->preset->frequency = frequency;
+    subghz->txrx->preset->data = preset_data;
+    subghz->txrx->preset->data_size = preset_data_size;
+}
+
 bool subghz_set_preset(SubGhz* subghz, const char* preset) {
     if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) {
-        subghz->txrx->preset = FuriHalSubGhzPresetOok270Async;
+        string_set(subghz->txrx->preset->name, "AM270");
     } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) {
-        subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
+        string_set(subghz->txrx->preset->name, "AM650");
     } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) {
-        subghz->txrx->preset = FuriHalSubGhzPreset2FSKDev238Async;
+        string_set(subghz->txrx->preset->name, "FM238");
     } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) {
-        subghz->txrx->preset = FuriHalSubGhzPreset2FSKDev476Async;
+        string_set(subghz->txrx->preset->name, "FM476");
+    } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) {
+        string_set(subghz->txrx->preset->name, "CUSTOM");
     } else {
         FURI_LOG_E(TAG, "Unknown preset");
         return false;
@@ -41,29 +56,19 @@ void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_
         string_printf(
             frequency,
             "%03ld.%02ld",
-            subghz->txrx->frequency / 1000000 % 1000,
-            subghz->txrx->frequency / 10000 % 100);
+            subghz->txrx->preset->frequency / 1000000 % 1000,
+            subghz->txrx->preset->frequency / 10000 % 100);
     }
-
     if(modulation != NULL) {
-        if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async ||
-           subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) {
-            string_set_str(modulation, "AM");
-        } else if(
-            subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async ||
-            subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) {
-            string_set_str(modulation, "FM");
-        } else {
-            furi_crash("SubGhz: Modulation is incorrect.");
-        }
+        string_printf(modulation, "%0.2s", string_get_cstr(subghz->txrx->preset->name));
     }
 }
 
-void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset) {
+void subghz_begin(SubGhz* subghz, uint8_t* preset_data) {
     furi_assert(subghz);
     furi_hal_subghz_reset();
     furi_hal_subghz_idle();
-    furi_hal_subghz_load_preset(preset);
+    furi_hal_subghz_load_custom_preset(preset_data);
     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
     subghz->txrx->txrx_state = SubGhzTxRxStateIDLE;
 }
@@ -155,13 +160,21 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) {
 
         if(subghz->txrx->transmitter) {
             if(subghz_transmitter_deserialize(subghz->txrx->transmitter, flipper_format)) {
-                if(subghz->txrx->preset) {
-                    subghz_begin(subghz, subghz->txrx->preset);
+                if(strcmp(string_get_cstr(subghz->txrx->preset->name), "")) {
+                    subghz_begin(
+                        subghz,
+                        subghz_setting_get_preset_data_by_name(
+                            subghz->setting, string_get_cstr(subghz->txrx->preset->name)));
                 } else {
-                    subghz_begin(subghz, FuriHalSubGhzPresetOok270Async);
+                    FURI_LOG_E(
+                        TAG,
+                        "Unknown name preset \" %s \"",
+                        string_get_cstr(subghz->txrx->preset->name));
+                    subghz_begin(
+                        subghz, subghz_setting_get_preset_data_by_name(subghz->setting, "AM650"));
                 }
-                if(subghz->txrx->frequency) {
-                    ret = subghz_tx(subghz, subghz->txrx->frequency);
+                if(subghz->txrx->preset->frequency) {
+                    ret = subghz_tx(subghz, subghz->txrx->preset->frequency);
                 } else {
                     ret = subghz_tx(subghz, 433920000);
                 }
@@ -270,16 +283,38 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) {
             load_key_state = SubGhzLoadKeyStateOnlyRx;
             break;
         }
-        subghz->txrx->frequency = temp_data32;
+        subghz->txrx->preset->frequency = temp_data32;
 
         if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
             FURI_LOG_E(TAG, "Missing Preset");
             break;
         }
+
         if(!subghz_set_preset(subghz, string_get_cstr(temp_str))) {
             break;
         }
 
+        if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
+            //Todo add Custom_preset_module
+            //delete peset if it already exists
+            subghz_setting_delete_custom_preset(
+                subghz->setting, string_get_cstr(subghz->txrx->preset->name));
+            //load custom preset from file
+            if(!subghz_setting_load_custom_preset(
+                   subghz->setting, string_get_cstr(subghz->txrx->preset->name), fff_data_file)) {
+                FURI_LOG_E(TAG, "Missing Custom preset");
+                break;
+            }
+        }
+        size_t preset_index = subghz_setting_get_inx_preset_by_name(
+            subghz->setting, string_get_cstr(subghz->txrx->preset->name));
+        subghz_preset_init(
+            subghz,
+            string_get_cstr(subghz->txrx->preset->name),
+            subghz->txrx->preset->frequency,
+            subghz_setting_get_preset_data(subghz->setting, preset_index),
+            subghz_setting_get_preset_data_size(subghz->setting, preset_index));
+
         if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
             FURI_LOG_E(TAG, "Missing Protocol");
             break;
@@ -541,8 +576,8 @@ void subghz_hopper_update(SubGhz* subghz) {
     };
     if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) {
         subghz_receiver_reset(subghz->txrx->receiver);
-        subghz->txrx->frequency = subghz_setting_get_hopper_frequency(
+        subghz->txrx->preset->frequency = subghz_setting_get_hopper_frequency(
             subghz->setting, subghz->txrx->hopper_idx_frequency);
-        subghz_rx(subghz, subghz->txrx->frequency);
+        subghz_rx(subghz, subghz->txrx->preset->frequency);
     }
 }

+ 10 - 5
applications/subghz/subghz_i.h

@@ -11,8 +11,8 @@
 #include "views/subghz_test_carrier.h"
 #include "views/subghz_test_packet.h"
 
-#include <furi.h>
-#include <furi_hal.h>
+// #include <furi.h>
+// #include <furi_hal.h>
 #include <gui/gui.h>
 #include <dialogs/dialogs.h>
 #include <gui/scene_manager.h>
@@ -49,8 +49,7 @@ struct SubGhzTxRx {
     SubGhzProtocolDecoderBase* decoder_result;
     FlipperFormat* fff_data;
 
-    uint32_t frequency;
-    FuriHalSubGhzPreset preset;
+    SubGhzPesetDefinition* preset;
     SubGhzHistory* history;
     uint16_t idx_menu_chosen;
     SubGhzTxRxState txrx_state;
@@ -97,9 +96,15 @@ struct SubGhz {
     void* rpc_ctx;
 };
 
+void subghz_preset_init(
+    void* context,
+    const char* preset_name,
+    uint32_t frequency,
+    uint8_t* preset_data,
+    size_t preset_data_size);
 bool subghz_set_preset(SubGhz* subghz, const char* preset);
 void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_t modulation);
-void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset);
+void subghz_begin(SubGhz* subghz, uint8_t* preset_data);
 uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency);
 void subghz_rx_end(SubGhz* subghz);
 void subghz_sleep(SubGhz* subghz);

+ 197 - 5
applications/subghz/subghz_setting.c

@@ -3,7 +3,7 @@
 
 #include <furi.h>
 #include <m-list.h>
-#include <lib/flipper_format/flipper_format.h>
+#include "furi_hal_subghz_configs.h"
 
 #define TAG "SubGhzSetting"
 
@@ -157,29 +157,89 @@ static const uint32_t subghz_hopper_frequency_list_region_jp[] = {
     0,
 };
 
+typedef struct {
+    string_t custom_preset_name;
+    uint8_t* custom_preset_data;
+    size_t custom_preset_data_size;
+} SubGhzSettingCustomPresetItem;
+
+ARRAY_DEF(SubGhzSettingCustomPresetItemArray, SubGhzSettingCustomPresetItem, M_POD_OPLIST)
+
+#define M_OPL_SubGhzSettingCustomPresetItemArray_t() \
+    ARRAY_OPLIST(SubGhzSettingCustomPresetItemArray, M_POD_OPLIST)
+
 LIST_DEF(FrequencyList, uint32_t)
 
 #define M_OPL_FrequencyList_t() LIST_OPLIST(FrequencyList)
 
+typedef struct {
+    SubGhzSettingCustomPresetItemArray_t data;
+} SubGhzSettingCustomPresetStruct;
+
 struct SubGhzSetting {
     FrequencyList_t frequencies;
     FrequencyList_t hopper_frequencies;
+    SubGhzSettingCustomPresetStruct* preset;
 };
 
 SubGhzSetting* subghz_setting_alloc(void) {
     SubGhzSetting* instance = malloc(sizeof(SubGhzSetting));
     FrequencyList_init(instance->frequencies);
     FrequencyList_init(instance->hopper_frequencies);
+    instance->preset = malloc(sizeof(SubGhzSettingCustomPresetStruct));
+    SubGhzSettingCustomPresetItemArray_init(instance->preset->data);
     return instance;
 }
 
+static void subghz_setting_preset_reset(SubGhzSetting* instance) {
+    for
+        M_EACH(item, instance->preset->data, SubGhzSettingCustomPresetItemArray_t) {
+            string_clear(item->custom_preset_name);
+            free(item->custom_preset_data);
+        }
+    SubGhzSettingCustomPresetItemArray_reset(instance->preset->data);
+}
+
 void subghz_setting_free(SubGhzSetting* instance) {
     furi_assert(instance);
     FrequencyList_clear(instance->frequencies);
     FrequencyList_clear(instance->hopper_frequencies);
+    for
+        M_EACH(item, instance->preset->data, SubGhzSettingCustomPresetItemArray_t) {
+            string_clear(item->custom_preset_name);
+            free(item->custom_preset_data);
+        }
+    SubGhzSettingCustomPresetItemArray_clear(instance->preset->data);
+    free(instance->preset);
     free(instance);
 }
 
+static void subghz_setting_load_default_preset(
+    SubGhzSetting* instance,
+    const char* preset_name,
+    const uint8_t* preset_data,
+    const uint8_t preset_pa_table[8]) {
+    furi_assert(instance);
+    furi_assert(preset_data);
+    uint32_t preset_data_count = 0;
+    SubGhzSettingCustomPresetItem* item =
+        SubGhzSettingCustomPresetItemArray_push_raw(instance->preset->data);
+
+    string_init(item->custom_preset_name);
+    string_set(item->custom_preset_name, preset_name);
+
+    while(preset_data[preset_data_count]) {
+        preset_data_count += 2;
+    }
+    preset_data_count += 2;
+    item->custom_preset_data_size = sizeof(uint8_t) * preset_data_count + sizeof(uint8_t) * 8;
+    item->custom_preset_data = malloc(item->custom_preset_data_size);
+    //load preset register
+    memcpy(&item->custom_preset_data[0], &preset_data[0], preset_data_count);
+    //load pa table
+    memcpy(&item->custom_preset_data[preset_data_count], &preset_pa_table[0], 8);
+}
+
 static void subghz_setting_load_default_region(
     SubGhzSetting* instance,
     const uint32_t frequencies[],
@@ -188,6 +248,7 @@ static void subghz_setting_load_default_region(
 
     FrequencyList_reset(instance->frequencies);
     FrequencyList_reset(instance->hopper_frequencies);
+    subghz_setting_preset_reset(instance);
 
     while(*frequencies) {
         FrequencyList_push_back(instance->frequencies, *frequencies);
@@ -198,6 +259,27 @@ static void subghz_setting_load_default_region(
         FrequencyList_push_back(instance->hopper_frequencies, *hopper_frequencies);
         hopper_frequencies++;
     }
+
+    subghz_setting_load_default_preset(
+        instance,
+        "AM270",
+        (uint8_t*)furi_hal_subghz_preset_ook_270khz_async_regs,
+        furi_hal_subghz_preset_ook_async_patable);
+    subghz_setting_load_default_preset(
+        instance,
+        "AM650",
+        (uint8_t*)furi_hal_subghz_preset_ook_650khz_async_regs,
+        furi_hal_subghz_preset_ook_async_patable);
+    subghz_setting_load_default_preset(
+        instance,
+        "FM238",
+        (uint8_t*)furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs,
+        furi_hal_subghz_preset_2fsk_async_patable);
+    subghz_setting_load_default_preset(
+        instance,
+        "FM476",
+        (uint8_t*)furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs,
+        furi_hal_subghz_preset_2fsk_async_patable);
 }
 
 void subghz_setting_load_default(SubGhzSetting* instance) {
@@ -260,7 +342,7 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
 
             // Standard frequencies (optional)
             temp_bool = true;
-            flipper_format_read_bool(fff_data_file, "add_standard_frequencies", &temp_bool, 1);
+            flipper_format_read_bool(fff_data_file, "Add_standard_frequencies", &temp_bool, 1);
             if(!temp_bool) {
                 FURI_LOG_I(TAG, "Removing standard frequencies");
                 FrequencyList_reset(instance->frequencies);
@@ -275,7 +357,7 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
                 break;
             }
             while(flipper_format_read_uint32(
-                fff_data_file, "frequency", (uint32_t*)&temp_data32, 1)) {
+                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);
                     FrequencyList_push_back(instance->frequencies, temp_data32);
@@ -290,7 +372,7 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
                 break;
             }
             while(flipper_format_read_uint32(
-                fff_data_file, "hopper_frequency", (uint32_t*)&temp_data32, 1)) {
+                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);
                     FrequencyList_push_back(instance->hopper_frequencies, temp_data32);
@@ -304,7 +386,7 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
                 FURI_LOG_E(TAG, "Rewind error");
                 break;
             }
-            if(flipper_format_read_uint32(fff_data_file, "default_frequency", &temp_data32, 1)) {
+            if(flipper_format_read_uint32(fff_data_file, "Default_frequency", &temp_data32, 1)) {
                 for
                     M_EACH(frequency, instance->frequencies, FrequencyList_t) {
                         *frequency &= FREQUENCY_MASK;
@@ -313,6 +395,18 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) {
                         }
                     }
             }
+
+            // custom preset (optional)
+            if(!flipper_format_rewind(fff_data_file)) {
+                FURI_LOG_E(TAG, "Rewind error");
+                break;
+            }
+            while(flipper_format_read_string(fff_data_file, "Custom_preset_name", temp_str)) {
+                FURI_LOG_I(TAG, "Custom preset loaded %s", string_get_cstr(temp_str));
+                subghz_setting_load_custom_preset(
+                    instance, string_get_cstr(temp_str), fff_data_file);
+            }
+
         } while(false);
     }
 
@@ -337,6 +431,104 @@ size_t subghz_setting_get_hopper_frequency_count(SubGhzSetting* instance) {
     return FrequencyList_size(instance->hopper_frequencies);
 }
 
+size_t subghz_setting_get_preset_count(SubGhzSetting* instance) {
+    furi_assert(instance);
+    return SubGhzSettingCustomPresetItemArray_size(instance->preset->data);
+}
+
+const char* subghz_setting_get_preset_name(SubGhzSetting* instance, size_t idx) {
+    furi_assert(instance);
+    SubGhzSettingCustomPresetItem* item =
+        SubGhzSettingCustomPresetItemArray_get(instance->preset->data, idx);
+    return string_get_cstr(item->custom_preset_name);
+}
+
+int subghz_setting_get_inx_preset_by_name(SubGhzSetting* instance, const char* preset_name) {
+    furi_assert(instance);
+    size_t idx = 0;
+     for
+         M_EACH(item, instance->preset->data, SubGhzSettingCustomPresetItemArray_t) {
+             if(strcmp(string_get_cstr(item->custom_preset_name), preset_name) == 0) {
+                 return idx;
+             }
+             idx++;
+         }
+     furi_crash("SubGhz: No name preset.");
+     return -1;
+}
+
+bool subghz_setting_load_custom_preset(
+    SubGhzSetting* instance,
+    const char* preset_name,
+    FlipperFormat* fff_data_file) {
+    furi_assert(instance);
+    furi_assert(preset_name);
+    uint32_t temp_data32;
+    SubGhzSettingCustomPresetItem* item =
+        SubGhzSettingCustomPresetItemArray_push_raw(instance->preset->data);
+    string_init(item->custom_preset_name);
+    string_set(item->custom_preset_name, preset_name);
+    do {
+        if(!flipper_format_get_value_count(fff_data_file, "Custom_preset_data", &temp_data32))
+            break;
+        if(!temp_data32 || (temp_data32 % 2)) {
+            FURI_LOG_E(TAG, "Integrity error Custom_preset_data");
+            break;
+        }
+        item->custom_preset_data_size = sizeof(uint8_t) * temp_data32;
+        item->custom_preset_data = malloc(item->custom_preset_data_size);
+        if(!flipper_format_read_hex(
+               fff_data_file,
+               "Custom_preset_data",
+               item->custom_preset_data,
+               item->custom_preset_data_size)) {
+            FURI_LOG_E(TAG, "Missing Custom_preset_data");
+            break;
+        }
+        return true;
+    } while(true);
+    return false;
+}
+
+bool subghz_setting_delete_custom_preset(SubGhzSetting* instance, const char* preset_name) {
+    furi_assert(instance);
+    furi_assert(preset_name);
+    SubGhzSettingCustomPresetItemArray_it_t it;
+    SubGhzSettingCustomPresetItemArray_it_last(it, instance->preset->data);
+    while(!SubGhzSettingCustomPresetItemArray_end_p(it)) {
+        SubGhzSettingCustomPresetItem* item = SubGhzSettingCustomPresetItemArray_ref(it);
+        if(strcmp(string_get_cstr(item->custom_preset_name), preset_name) == 0) {
+            string_clear(item->custom_preset_name);
+            free(item->custom_preset_data);
+            SubGhzSettingCustomPresetItemArray_remove(instance->preset->data, it);
+            return true;
+        }
+        SubGhzSettingCustomPresetItemArray_previous(it);
+    }
+    return false;
+}
+
+uint8_t* subghz_setting_get_preset_data(SubGhzSetting* instance, size_t idx) {
+    furi_assert(instance);
+    SubGhzSettingCustomPresetItem* item =
+        SubGhzSettingCustomPresetItemArray_get(instance->preset->data, idx);
+    return item->custom_preset_data;
+}
+
+size_t subghz_setting_get_preset_data_size(SubGhzSetting* instance, size_t idx) {
+    furi_assert(instance);
+    SubGhzSettingCustomPresetItem* item =
+        SubGhzSettingCustomPresetItemArray_get(instance->preset->data, idx);
+    return item->custom_preset_data_size;
+}
+
+uint8_t* subghz_setting_get_preset_data_by_name(SubGhzSetting* instance, const char* preset_name) {
+    furi_assert(instance);
+    SubGhzSettingCustomPresetItem* item = SubGhzSettingCustomPresetItemArray_get(
+        instance->preset->data, subghz_setting_get_inx_preset_by_name(instance, preset_name));
+    return item->custom_preset_data;
+}
+
 uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx) {
     furi_assert(instance);
     uint32_t* ret = FrequencyList_get(instance->frequencies, idx);

+ 22 - 0
applications/subghz/subghz_setting.h

@@ -4,6 +4,9 @@
 #include <math.h>
 #include <furi.h>
 #include <furi_hal.h>
+#include <lib/flipper_format/flipper_format.h>
+
+#define SUBGHZ_SETTING_DEFAULT_PRESET_COUNT 4
 
 typedef struct SubGhzSetting SubGhzSetting;
 
@@ -17,6 +20,25 @@ size_t subghz_setting_get_frequency_count(SubGhzSetting* instance);
 
 size_t subghz_setting_get_hopper_frequency_count(SubGhzSetting* instance);
 
+size_t subghz_setting_get_preset_count(SubGhzSetting* instance);
+
+const char* subghz_setting_get_preset_name(SubGhzSetting* instance, size_t idx);
+
+int subghz_setting_get_inx_preset_by_name(SubGhzSetting* instance, const char* preset_name);
+
+uint8_t* subghz_setting_get_preset_data(SubGhzSetting* instance, size_t idx);
+
+size_t subghz_setting_get_preset_data_size(SubGhzSetting* instance, size_t idx);
+
+uint8_t* subghz_setting_get_preset_data_by_name(SubGhzSetting* instance, const char* preset_name);
+
+bool subghz_setting_load_custom_preset(
+    SubGhzSetting* instance,
+    const char* preset_name,
+    FlipperFormat* fff_data_file);
+
+bool subghz_setting_delete_custom_preset(SubGhzSetting* instance, const char* preset_name);
+
 uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx);
 
 uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx);

+ 19 - 8
assets/resources/subghz/assets/setting_user

@@ -2,17 +2,28 @@ Filetype: Flipper SubGhz Setting File
 Version: 1
 
 # Add Standard frequencies for your region
-#add_standard_frequencies: true
+#Add_standard_frequencies: true
 
 # Default Frequency: used as default for "Read" and "Read Raw"
-#default_frequency: 433920000
+#Default_frequency: 433920000
 
 # Frequencies used for "Read", "Read Raw" and "Frequency Analyzer"
-#frequency: 300000000
-#frequency: 310000000
-#frequency: 320000000
+#Frequency: 300000000
+#Frequency: 310000000
+#Frequency: 320000000
 
 # Frequencies used for hopping mode (keep this list small or flipper will miss signal)
-#hopper_frequency: 300000000
-#hopper_frequency: 310000000
-#hopper_frequency: 310000000
+#Hopper_frequency: 300000000
+#Hopper_frequency: 310000000
+#Hopper_frequency: 310000000
+
+# Custom preset
+# format for CC1101 "Custom_preset_data:" XX YY XX YY .. 00 00 ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ, where: XX-register, YY - register data, 00 00 - end load register, ZZ - 8 byte Pa table register
+
+#Custom_preset_name: AM_1
+#Custom_preset_module: CC1101
+#Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00
+
+#Custom_preset_name: AM_2
+#Custom_preset_module: CC1101
+#Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00

+ 43 - 10
firmware/targets/f7/furi_hal/furi_hal_subghz.c

@@ -100,22 +100,24 @@ void furi_hal_subghz_dump_state() {
 
 void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
     if(preset == FuriHalSubGhzPresetOok650Async) {
-        furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_650khz_async_regs);
+        furi_hal_subghz_load_registers((uint8_t*)furi_hal_subghz_preset_ook_650khz_async_regs);
         furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable);
     } else if(preset == FuriHalSubGhzPresetOok270Async) {
-        furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_270khz_async_regs);
+        furi_hal_subghz_load_registers((uint8_t*)furi_hal_subghz_preset_ook_270khz_async_regs);
         furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable);
     } else if(preset == FuriHalSubGhzPreset2FSKDev238Async) {
-        furi_hal_subghz_load_registers(furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs);
+        furi_hal_subghz_load_registers(
+            (uint8_t*)furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs);
         furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable);
     } else if(preset == FuriHalSubGhzPreset2FSKDev476Async) {
-        furi_hal_subghz_load_registers(furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs);
+        furi_hal_subghz_load_registers(
+            (uint8_t*)furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs);
         furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable);
     } else if(preset == FuriHalSubGhzPresetMSK99_97KbAsync) {
-        furi_hal_subghz_load_registers(furi_hal_subghz_preset_msk_99_97kb_async_regs);
+        furi_hal_subghz_load_registers((uint8_t*)furi_hal_subghz_preset_msk_99_97kb_async_regs);
         furi_hal_subghz_load_patable(furi_hal_subghz_preset_msk_async_patable);
     } else if(preset == FuriHalSubGhzPresetGFSK9_99KbAsync) {
-        furi_hal_subghz_load_registers(furi_hal_subghz_preset_gfsk_9_99kb_async_regs);
+        furi_hal_subghz_load_registers((uint8_t*)furi_hal_subghz_preset_gfsk_9_99kb_async_regs);
         furi_hal_subghz_load_patable(furi_hal_subghz_preset_gfsk_async_patable);
     } else {
         furi_crash("SubGhz: Missing config.");
@@ -123,13 +125,44 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
     furi_hal_subghz.preset = preset;
 }
 
-void furi_hal_subghz_load_registers(const uint8_t data[][2]) {
+void furi_hal_subghz_load_custom_preset(uint8_t* preset_data) {
+    //load config
     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
     cc1101_reset(&furi_hal_spi_bus_handle_subghz);
     uint32_t i = 0;
-    while(data[i][0]) {
-        cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i][0], data[i][1]);
-        i++;
+    uint8_t pa[8] = {0};
+    while(preset_data[i]) {
+        cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, preset_data[i], preset_data[i + 1]);
+        i += 2;
+    }
+    furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
+
+    //load pa table
+    memcpy(&pa[0], &preset_data[i + 2], 8);
+    furi_hal_subghz_load_patable(pa);
+    furi_hal_subghz.preset = FuriHalSubGhzPresetCustom;
+
+    //show debug
+    if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
+        i = 0;
+        FURI_LOG_D(TAG, "Loading custom preset");
+        while(preset_data[i]) {
+            FURI_LOG_D(TAG, "Reg[%lu]: %02X=%02X", i, preset_data[i], preset_data[i + 1]);
+            i += 2;
+        }
+        for(uint8_t y = i; y < i + 10; y++) {
+            FURI_LOG_D(TAG, "PA[%lu]:  %02X", y, preset_data[y]);
+        }
+    }
+}
+
+void furi_hal_subghz_load_registers(uint8_t* data) {
+    furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
+    cc1101_reset(&furi_hal_spi_bus_handle_subghz);
+    uint32_t i = 0;
+    while(data[i]) {
+        cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i], data[i + 1]);
+        i += 2;
     }
     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
 }

+ 9 - 2
firmware/targets/furi_hal_include/furi_hal_subghz.h

@@ -22,7 +22,8 @@ typedef enum {
     FuriHalSubGhzPreset2FSKDev238Async, /**< FM, deviation 2.380371 kHz, asynchronous */
     FuriHalSubGhzPreset2FSKDev476Async, /**< FM, deviation 47.60742 kHz, asynchronous */
     FuriHalSubGhzPresetMSK99_97KbAsync, /**< MSK, deviation 47.60742 kHz, 99.97Kb/s, asynchronous */
-    FuriHalSubGhzPresetGFSK9_99KbAsync /**< GFSK, deviation 19.042969 kHz, 9.996Kb/s, asynchronous */
+    FuriHalSubGhzPresetGFSK9_99KbAsync, /**< GFSK, deviation 19.042969 kHz, 9.996Kb/s, asynchronous */
+    FuriHalSubGhzPresetCustom, /**Custom Preset*/
 } FuriHalSubGhzPreset;
 
 /** Switchable Radio Paths */
@@ -74,11 +75,17 @@ void furi_hal_subghz_dump_state();
  */
 void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset);
 
+/** Load custom registers from preset
+ *
+ * @param      preset_data   registers to load
+ */
+void furi_hal_subghz_load_custom_preset(uint8_t* preset_data);
+
 /** Load registers
  *
  * @param      data  Registers data
  */
-void furi_hal_subghz_load_registers(const uint8_t data[][2]);
+void furi_hal_subghz_load_registers(uint8_t* data);
 
 /** Load PATABLE
  *

+ 29 - 28
lib/subghz/blocks/generic.c

@@ -1,39 +1,29 @@
 #include "generic.h"
-#include "../types.h"
 #include <lib/toolbox/stream/stream.h>
 #include <lib/flipper_format/flipper_format_i.h>
 
 #define TAG "SubGhzBlockGeneric"
 
-bool subghz_block_generic_get_preset_name(FuriHalSubGhzPreset preset, string_t preset_str) {
-    const char* preset_name;
-    switch(preset) {
-    case FuriHalSubGhzPresetOok270Async:
-        preset_name = "FuriHalSubGhzPresetOok270Async";
-        break;
-    case FuriHalSubGhzPresetOok650Async:
-        preset_name = "FuriHalSubGhzPresetOok650Async";
-        break;
-    case FuriHalSubGhzPreset2FSKDev238Async:
-        preset_name = "FuriHalSubGhzPreset2FSKDev238Async";
-        break;
-    case FuriHalSubGhzPreset2FSKDev476Async:
-        preset_name = "FuriHalSubGhzPreset2FSKDev476Async";
-        break;
-    default:
-        FURI_LOG_E(TAG, "Unknown preset");
-        return false;
-        break;
+void subghz_block_generic_get_preset_name(const char* preset_name, string_t preset_str) {
+    const char* preset_name_temp;
+    if(!strcmp(preset_name, "AM270")) {
+        preset_name_temp = "FuriHalSubGhzPresetOok270Async";
+    } else if(!strcmp(preset_name, "AM650")) {
+        preset_name_temp = "FuriHalSubGhzPresetOok650Async";
+    } else if(!strcmp(preset_name, "FM238")) {
+        preset_name_temp = "FuriHalSubGhzPreset2FSKDev238Async";
+    } else if(!strcmp(preset_name, "FM476")) {
+        preset_name_temp = "FuriHalSubGhzPreset2FSKDev476Async";
+    } else {
+        preset_name_temp = "FuriHalSubGhzPresetCustom";
     }
-    string_set(preset_str, preset_name);
-    return true;
+    string_set(preset_str, preset_name_temp);
 }
 
 bool subghz_block_generic_serialize(
     SubGhzBlockGeneric* instance,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(instance);
     bool res = false;
     string_t temp_str;
@@ -46,17 +36,28 @@ bool subghz_block_generic_serialize(
             break;
         }
 
-        if(!flipper_format_write_uint32(flipper_format, "Frequency", &frequency, 1)) {
+        if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) {
             FURI_LOG_E(TAG, "Unable to add Frequency");
             break;
         }
-        if(!subghz_block_generic_get_preset_name(preset, temp_str)) {
-            break;
-        }
+
+        subghz_block_generic_get_preset_name(string_get_cstr(preset->name), temp_str);
         if(!flipper_format_write_string_cstr(flipper_format, "Preset", string_get_cstr(temp_str))) {
             FURI_LOG_E(TAG, "Unable to add Preset");
             break;
         }
+        if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
+            if(!flipper_format_write_string_cstr(
+                   flipper_format, "Custom_preset_module", "CC1101")) {
+                FURI_LOG_E(TAG, "Unable to add Custom_preset_module");
+                break;
+            }
+            if(!flipper_format_write_hex(
+                   flipper_format, "Custom_preset_data", preset->data, preset->data_size)) {
+                FURI_LOG_E(TAG, "Unable to add Custom_preset_data");
+                break;
+            }
+        }
         if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->protocol_name)) {
             FURI_LOG_E(TAG, "Unable to add Protocol");
             break;

+ 7 - 9
lib/subghz/blocks/generic.h

@@ -7,6 +7,7 @@
 #include <lib/flipper_format/flipper_format.h>
 #include "furi.h"
 #include "furi_hal.h"
+#include "../types.h"
 
 typedef struct SubGhzBlockGeneric SubGhzBlockGeneric;
 
@@ -20,26 +21,23 @@ struct SubGhzBlockGeneric {
 };
 
 /**
- * Get modulation name.
- * @param preset modulation,FuriHalSubGhzPreset 
- * @param preset_str Output modulation name 
- * @return true On success
+ * Get name preset.
+ * @param preset_name name preset
+ * @param preset_str Output name preset
  */
-bool subghz_block_generic_get_preset_name(FuriHalSubGhzPreset preset, string_t preset_str);
+void subghz_block_generic_get_preset_name(const char* preset_name, string_t preset_str);
 
 /**
  * Serialize data SubGhzBlockGeneric.
  * @param instance Pointer to a SubGhzBlockGeneric instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_block_generic_serialize(
     SubGhzBlockGeneric* instance,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzBlockGeneric.

+ 2 - 4
lib/subghz/protocols/base.c

@@ -26,14 +26,12 @@ bool subghz_protocol_decoder_base_get_string(
 bool subghz_protocol_decoder_base_serialize(
     SubGhzProtocolDecoderBase* decoder_base,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     bool status = false;
 
     if(decoder_base->protocol && decoder_base->protocol->decoder &&
        decoder_base->protocol->decoder->serialize) {
-        status = decoder_base->protocol->decoder->serialize(
-            decoder_base, flipper_format, frequency, preset);
+        status = decoder_base->protocol->decoder->serialize(decoder_base, flipper_format, preset);
     }
 
     return status;

+ 2 - 4
lib/subghz/protocols/base.h

@@ -43,15 +43,13 @@ bool subghz_protocol_decoder_base_get_string(
  * Serialize data SubGhzProtocolDecoderBase.
  * @param decoder_base Pointer to a SubGhzProtocolDecoderBase instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_base_serialize(
     SubGhzProtocolDecoderBase* decoder_base,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderBase.

+ 2 - 3
lib/subghz/protocols/came.c

@@ -284,11 +284,10 @@ uint8_t subghz_protocol_decoder_came_get_hash_data(void* context) {
 bool subghz_protocol_decoder_came_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderCame* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_came_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/came.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_came_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderCame.
  * @param context Pointer to a SubGhzProtocolDecoderCame instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_came_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderCame.

+ 2 - 3
lib/subghz/protocols/came_atomo.c

@@ -301,11 +301,10 @@ uint8_t subghz_protocol_decoder_came_atomo_get_hash_data(void* context) {
 bool subghz_protocol_decoder_came_atomo_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderCameAtomo* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_came_atomo_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/came_atomo.h

@@ -48,15 +48,13 @@ uint8_t subghz_protocol_decoder_came_atomo_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderCameAtomo.
  * @param context Pointer to a SubGhzProtocolDecoderCameAtomo instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_came_atomo_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderCameAtomo.

+ 2 - 3
lib/subghz/protocols/came_twee.c

@@ -418,11 +418,10 @@ uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context) {
 bool subghz_protocol_decoder_came_twee_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderCameTwee* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/came_twee.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderCameTwee.
  * @param context Pointer to a SubGhzProtocolDecoderCameTwee instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_came_twee_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderCameTwee.

+ 2 - 3
lib/subghz/protocols/chamberlain_code.c

@@ -423,11 +423,10 @@ uint8_t subghz_protocol_decoder_chamb_code_get_hash_data(void* context) {
 bool subghz_protocol_decoder_chamb_code_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderChamb_Code* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/chamberlain_code.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_chamb_code_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderChamb_Code.
  * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_chamb_code_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderChamb_Code.

+ 2 - 3
lib/subghz/protocols/faac_slh.c

@@ -183,11 +183,10 @@ uint8_t subghz_protocol_decoder_faac_slh_get_hash_data(void* context) {
 bool subghz_protocol_decoder_faac_slh_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderFaacSLH* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/faac_slh.h

@@ -49,15 +49,13 @@ uint8_t subghz_protocol_decoder_faac_slh_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderFaacSLH.
  * @param context Pointer to a SubGhzProtocolDecoderFaacSLH instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_faac_slh_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderFaacSLH.

+ 2 - 3
lib/subghz/protocols/gate_tx.c

@@ -289,11 +289,10 @@ uint8_t subghz_protocol_decoder_gate_tx_get_hash_data(void* context) {
 bool subghz_protocol_decoder_gate_tx_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderGateTx* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_gate_tx_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/gate_tx.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_gate_tx_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderGateTx.
  * @param context Pointer to a SubGhzProtocolDecoderGateTx instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_gate_tx_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderGateTx.

+ 2 - 3
lib/subghz/protocols/holtek.c

@@ -322,11 +322,10 @@ uint8_t subghz_protocol_decoder_holtek_get_hash_data(void* context) {
 bool subghz_protocol_decoder_holtek_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderHoltek* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_holtek_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/holtek.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_holtek_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderHoltek.
  * @param context Pointer to a SubGhzProtocolDecoderHoltek instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_holtek_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderHoltek.

+ 2 - 3
lib/subghz/protocols/hormann.c

@@ -310,11 +310,10 @@ uint8_t subghz_protocol_decoder_hormann_get_hash_data(void* context) {
 bool subghz_protocol_decoder_hormann_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderHormann* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_hormann_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/hormann.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_hormann_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderHormann.
  * @param context Pointer to a SubGhzProtocolDecoderHormann instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_hormann_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderHormann.

+ 2 - 3
lib/subghz/protocols/ido.c

@@ -182,11 +182,10 @@ uint8_t subghz_protocol_decoder_ido_get_hash_data(void* context) {
 bool subghz_protocol_decoder_ido_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderIDo* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_ido_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/ido.h

@@ -49,15 +49,13 @@ uint8_t subghz_protocol_decoder_ido_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderIDo.
  * @param context Pointer to a SubGhzProtocolDecoderIDo instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_ido_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderIDo.

+ 4 - 8
lib/subghz/protocols/keeloq.c

@@ -174,8 +174,7 @@ bool subghz_protocol_keeloq_create_data(
     uint8_t btn,
     uint16_t cnt,
     const char* manufacture_name,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolEncoderKeeloq* instance = context;
     instance->generic.serial = serial;
@@ -184,8 +183,7 @@ bool subghz_protocol_keeloq_create_data(
     instance->generic.data_count_bit = 64;
     bool res = subghz_protocol_keeloq_gen_data(instance, btn);
     if(res) {
-        res =
-            subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+        res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
     }
     return res;
 }
@@ -633,15 +631,13 @@ uint8_t subghz_protocol_decoder_keeloq_get_hash_data(void* context) {
 bool subghz_protocol_decoder_keeloq_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderKeeloq* instance = context;
     subghz_protocol_keeloq_check_remote_controller(
         &instance->generic, instance->keystore, &instance->manufacture_name);
 
-    bool res =
-        subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 
     if(res && !flipper_format_write_string_cstr(
                   flipper_format, "Manufacture", instance->manufacture_name)) {

+ 4 - 8
lib/subghz/protocols/keeloq.h

@@ -32,8 +32,7 @@ void subghz_protocol_encoder_keeloq_free(void* context);
  * @param btn Button number, 4 bit
  * @param cnt Container value, 16 bit
  * @param manufacture_name Name of manufacturer's key
- * @param frequency Transmission frequency, Hz
- * @param preset Modulation, FuriHalSubGhzPreset
+ * @param preset Modulation, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_keeloq_create_data(
@@ -43,8 +42,7 @@ bool subghz_protocol_keeloq_create_data(
     uint8_t btn,
     uint16_t cnt,
     const char* manufacture_name,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize and generating an upload to send.
@@ -105,15 +103,13 @@ uint8_t subghz_protocol_decoder_keeloq_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderKeeloq.
  * @param context Pointer to a SubGhzProtocolDecoderKeeloq instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_keeloq_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderKeeloq.

+ 2 - 3
lib/subghz/protocols/kia.c

@@ -233,11 +233,10 @@ uint8_t subghz_protocol_decoder_kia_get_hash_data(void* context) {
 bool subghz_protocol_decoder_kia_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderKIA* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_kia_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/kia.h

@@ -49,15 +49,13 @@ uint8_t subghz_protocol_decoder_kia_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderKIA.
  * @param context Pointer to a SubGhzProtocolDecoderKIA instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_kia_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderKIA.

+ 2 - 3
lib/subghz/protocols/linear.c

@@ -299,11 +299,10 @@ uint8_t subghz_protocol_decoder_linear_get_hash_data(void* context) {
 bool subghz_protocol_decoder_linear_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderLinear* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_linear_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/linear.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_linear_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderLinear.
  * @param context Pointer to a SubGhzProtocolDecoderLinear instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_linear_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderLinear.

+ 2 - 3
lib/subghz/protocols/megacode.c

@@ -380,11 +380,10 @@ uint8_t subghz_protocol_decoder_megacode_get_hash_data(void* context) {
 bool subghz_protocol_decoder_megacode_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderMegaCode* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_megacode_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/megacode.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_megacode_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderMegaCode.
  * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_megacode_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderMegaCode.

+ 2 - 3
lib/subghz/protocols/nero_radio.c

@@ -342,11 +342,10 @@ uint8_t subghz_protocol_decoder_nero_radio_get_hash_data(void* context) {
 bool subghz_protocol_decoder_nero_radio_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderNeroRadio* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/nero_radio.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_nero_radio_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderNeroRadio.
  * @param context Pointer to a SubGhzProtocolDecoderNeroRadio instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_nero_radio_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderNeroRadio.

+ 2 - 3
lib/subghz/protocols/nero_sketch.c

@@ -327,11 +327,10 @@ uint8_t subghz_protocol_decoder_nero_sketch_get_hash_data(void* context) {
 bool subghz_protocol_decoder_nero_sketch_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderNeroSketch* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_nero_sketch_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/nero_sketch.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_nero_sketch_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderNeroSketch.
  * @param context Pointer to a SubGhzProtocolDecoderNeroSketch instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_nero_sketch_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderNeroSketch.

+ 2 - 3
lib/subghz/protocols/nice_flo.c

@@ -277,11 +277,10 @@ uint8_t subghz_protocol_decoder_nice_flo_get_hash_data(void* context) {
 bool subghz_protocol_decoder_nice_flo_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderNiceFlo* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/nice_flo.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_nice_flo_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderNiceFlo.
  * @param context Pointer to a SubGhzProtocolDecoderNiceFlo instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_nice_flo_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderNiceFlo.

+ 2 - 3
lib/subghz/protocols/nice_flor_s.c

@@ -330,11 +330,10 @@ uint8_t subghz_protocol_decoder_nice_flor_s_get_hash_data(void* context) {
 bool subghz_protocol_decoder_nice_flor_s_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderNiceFlorS* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/nice_flor_s.h

@@ -49,15 +49,13 @@ uint8_t subghz_protocol_decoder_nice_flor_s_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderNiceFlorS.
  * @param context Pointer to a SubGhzProtocolDecoderNiceFlorS instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_nice_flor_s_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderNiceFlorS.

+ 2 - 3
lib/subghz/protocols/power_smart.c

@@ -345,11 +345,10 @@ uint8_t subghz_protocol_decoder_power_smart_get_hash_data(void* context) {
 bool subghz_protocol_decoder_power_smart_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderPowerSmart* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/power_smart.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_power_smart_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderPowerSmart.
  * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_power_smart_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderPowerSmart.

+ 2 - 4
lib/subghz/protocols/princeton.c

@@ -300,12 +300,10 @@ uint8_t subghz_protocol_decoder_princeton_get_hash_data(void* context) {
 bool subghz_protocol_decoder_princeton_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderPrinceton* instance = context;
-    bool res =
-        subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
     if(res && !flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) {
         FURI_LOG_E(TAG, "Unable to add TE");
         res = false;

+ 2 - 4
lib/subghz/protocols/princeton.h

@@ -83,15 +83,13 @@ uint8_t subghz_protocol_decoder_princeton_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderPrinceton.
  * @param context Pointer to a SubGhzProtocolDecoderPrinceton instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_princeton_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderPrinceton.

+ 17 - 7
lib/subghz/protocols/raw.c

@@ -83,8 +83,7 @@ const SubGhzProtocol subghz_protocol_raw = {
 bool subghz_protocol_raw_save_to_file_init(
     SubGhzProtocolDecoderRAW* instance,
     const char* dev_name,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(instance);
 
     instance->storage = furi_record_open(RECORD_STORAGE);
@@ -124,19 +123,30 @@ bool subghz_protocol_raw_save_to_file_init(
             break;
         }
 
-        if(!flipper_format_write_uint32(instance->flipper_file, "Frequency", &frequency, 1)) {
+        if(!flipper_format_write_uint32(
+               instance->flipper_file, "Frequency", &preset->frequency, 1)) {
             FURI_LOG_E(TAG, "Unable to add Frequency");
             break;
         }
-        if(!subghz_block_generic_get_preset_name(preset, temp_str)) {
-            break;
-        }
+
+        subghz_block_generic_get_preset_name(string_get_cstr(preset->name), temp_str);
         if(!flipper_format_write_string_cstr(
                instance->flipper_file, "Preset", string_get_cstr(temp_str))) {
             FURI_LOG_E(TAG, "Unable to add Preset");
             break;
         }
-
+        if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
+            if(!flipper_format_write_string_cstr(
+                   instance->flipper_file, "Custom_preset_module", "CC1101")) {
+                FURI_LOG_E(TAG, "Unable to add Custom_preset_module");
+                break;
+            }
+            if(!flipper_format_write_hex(
+                   instance->flipper_file, "Custom_preset_data", preset->data, preset->data_size)) {
+                FURI_LOG_E(TAG, "Unable to add Custom_preset_data");
+                break;
+            }
+        }
         if(!flipper_format_write_string_cstr(
                instance->flipper_file, "Protocol", instance->base.protocol->name)) {
             FURI_LOG_E(TAG, "Unable to add Protocol");

+ 2 - 4
lib/subghz/protocols/raw.h

@@ -17,15 +17,13 @@ extern const SubGhzProtocol subghz_protocol_raw;
  * Open file for writing
  * @param instance Pointer to a SubGhzProtocolDecoderRAW instance
  * @param dev_name  File name
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_raw_save_to_file_init(
     SubGhzProtocolDecoderRAW* instance,
     const char* dev_name,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Stop writing file to flash

+ 2 - 3
lib/subghz/protocols/scher_khan.c

@@ -251,11 +251,10 @@ uint8_t subghz_protocol_decoder_scher_khan_get_hash_data(void* context) {
 bool subghz_protocol_decoder_scher_khan_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderScherKhan* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_scher_khan_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/scher_khan.h

@@ -49,15 +49,13 @@ uint8_t subghz_protocol_decoder_scher_khan_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderScherKhan.
  * @param context Pointer to a SubGhzProtocolDecoderScherKhan instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_scher_khan_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderScherKhan.

+ 2 - 3
lib/subghz/protocols/secplus_v1.c

@@ -515,11 +515,10 @@ uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context) {
 bool subghz_protocol_decoder_secplus_v1_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderSecPlus_v1* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/secplus_v1.h

@@ -82,15 +82,13 @@ uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderSecPlus_v1.
  * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_secplus_v1_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderSecPlus_v1.

+ 4 - 8
lib/subghz/protocols/secplus_v2.c

@@ -588,8 +588,7 @@ bool subghz_protocol_secplus_v2_create_data(
     uint32_t serial,
     uint8_t btn,
     uint32_t cnt,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolEncoderSecPlus_v2* instance = context;
     instance->generic.serial = serial;
@@ -598,8 +597,7 @@ bool subghz_protocol_secplus_v2_create_data(
     instance->generic.data_count_bit =
         (uint8_t)subghz_protocol_secplus_v2_const.min_count_bit_for_found;
     subghz_protocol_secplus_v2_encode(instance);
-    bool res =
-        subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 
     uint8_t key_data[sizeof(uint64_t)] = {0};
     for(size_t i = 0; i < sizeof(uint64_t); i++) {
@@ -757,12 +755,10 @@ uint8_t subghz_protocol_decoder_secplus_v2_get_hash_data(void* context) {
 bool subghz_protocol_decoder_secplus_v2_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderSecPlus_v2* instance = context;
-    bool res =
-        subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 
     uint8_t key_data[sizeof(uint64_t)] = {0};
     for(size_t i = 0; i < sizeof(uint64_t); i++) {

+ 4 - 8
lib/subghz/protocols/secplus_v2.h

@@ -52,8 +52,7 @@ LevelDuration subghz_protocol_encoder_secplus_v2_yield(void* context);
  * @param btn Button number, 8 bit
  * @param cnt Container value, 28 bit
  * @param manufacture_name Name of manufacturer's key
- * @param frequency Transmission frequency, Hz
- * @param preset Modulation, FuriHalSubGhzPreset
+ * @param preset Modulation, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_secplus_v2_create_data(
@@ -62,8 +61,7 @@ bool subghz_protocol_secplus_v2_create_data(
     uint32_t serial,
     uint8_t btn,
     uint32_t cnt,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Allocate SubGhzProtocolDecoderSecPlus_v2.
@@ -103,15 +101,13 @@ uint8_t subghz_protocol_decoder_secplus_v2_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderSecPlus_v2.
  * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_secplus_v2_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderSecPlus_v2.

+ 2 - 4
lib/subghz/protocols/somfy_keytis.c

@@ -382,12 +382,10 @@ uint8_t subghz_protocol_decoder_somfy_keytis_get_hash_data(void* context) {
 bool subghz_protocol_decoder_somfy_keytis_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderSomfyKeytis* instance = context;
-    bool res =
-        subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
     if(res && !flipper_format_write_uint32(
                   flipper_format, "Duration_Counter", &instance->press_duration_counter, 1)) {
         FURI_LOG_E(TAG, "Unable to add Duration_Counter");

+ 2 - 4
lib/subghz/protocols/somfy_keytis.h

@@ -49,15 +49,13 @@ uint8_t subghz_protocol_decoder_somfy_keytis_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderSomfyKeytis.
  * @param context Pointer to a SubGhzProtocolDecoderSomfyKeytis instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_somfy_keytis_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderSomfyKeytis.

+ 2 - 3
lib/subghz/protocols/somfy_telis.c

@@ -339,11 +339,10 @@ uint8_t subghz_protocol_decoder_somfy_telis_get_hash_data(void* context) {
 bool subghz_protocol_decoder_somfy_telis_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderSomfyTelis* instance = context;
-    return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 }
 
 bool subghz_protocol_decoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format) {

+ 2 - 4
lib/subghz/protocols/somfy_telis.h

@@ -49,15 +49,13 @@ uint8_t subghz_protocol_decoder_somfy_telis_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderSomfyTelis.
  * @param context Pointer to a SubGhzProtocolDecoderSomfyTelis instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_somfy_telis_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderSomfyTelis.

+ 2 - 4
lib/subghz/protocols/star_line.c

@@ -320,14 +320,12 @@ uint8_t subghz_protocol_decoder_star_line_get_hash_data(void* context) {
 bool subghz_protocol_decoder_star_line_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset) {
+    SubGhzPesetDefinition* preset) {
     furi_assert(context);
     SubGhzProtocolDecoderStarLine* instance = context;
     subghz_protocol_star_line_check_remote_controller(
         &instance->generic, instance->keystore, &instance->manufacture_name);
-    bool res =
-        subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
+    bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
 
     if(res && !flipper_format_write_string_cstr(
                   flipper_format, "Manufacture", instance->manufacture_name)) {

+ 2 - 4
lib/subghz/protocols/star_line.h

@@ -49,15 +49,13 @@ uint8_t subghz_protocol_decoder_star_line_get_hash_data(void* context);
  * Serialize data SubGhzProtocolDecoderStarLine.
  * @param context Pointer to a SubGhzProtocolDecoderStarLine instance
  * @param flipper_format Pointer to a FlipperFormat instance
- * @param frequency The frequency at which the signal was received, Hz
- * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
+ * @param preset The modulation on which the signal was received, SubGhzPesetDefinition
  * @return true On success
  */
 bool subghz_protocol_decoder_star_line_serialize(
     void* context,
     FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+    SubGhzPesetDefinition* preset);
 
 /**
  * Deserialize data SubGhzProtocolDecoderStarLine.

+ 2 - 3
lib/subghz/subghz_worker.c

@@ -57,7 +57,6 @@ static int32_t subghz_worker_thread_callback(void* context) {
         if(ret == sizeof(LevelDuration)) {
             if(level_duration_is_reset(level_duration)) {
                 FURI_LOG_E(TAG, "Overrun buffer");
-                ;
                 if(instance->overrun_callback) instance->overrun_callback(instance->context);
             } else {
                 bool level = level_duration_get_level(level_duration);
@@ -98,11 +97,11 @@ SubGhzWorker* subghz_worker_alloc() {
     furi_thread_set_context(instance->thread, instance);
     furi_thread_set_callback(instance->thread, subghz_worker_thread_callback);
 
-    instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 2048, sizeof(LevelDuration));
+    instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 4096, sizeof(LevelDuration));
 
     //setting filter
     instance->filter_running = true;
-    instance->filter_duration = 20;
+    instance->filter_duration = 30;
 
     return instance;
 }

+ 3 - 5
lib/subghz/types.h

@@ -10,6 +10,7 @@
 #include "environment.h"
 #include <furi.h>
 #include <furi_hal.h>
+#include <subghz/helpers/subghz_types.h>
 
 #define SUBGHZ_APP_FOLDER ANY_PATH("subghz")
 #define SUBGHZ_RAW_FOLDER EXT_PATH("subghz")
@@ -30,11 +31,8 @@ typedef void* (*SubGhzAlloc)(SubGhzEnvironment* environment);
 typedef void (*SubGhzFree)(void* context);
 
 // Serialize and Deserialize
-typedef bool (*SubGhzSerialize)(
-    void* context,
-    FlipperFormat* flipper_format,
-    uint32_t frequency,
-    FuriHalSubGhzPreset preset);
+typedef bool (
+    *SubGhzSerialize)(void* context, FlipperFormat* flipper_format, SubGhzPesetDefinition* preset);
 typedef bool (*SubGhzDeserialize)(void* context, FlipperFormat* flipper_format);
 
 // Decoder specific