Explorar el Código

Skorp subghz capture refactoring (#569)

* SubGhz: changing the operation of the capture timer, and the logic of the work of parsers
* Add toolbox lib. Move levels to toolbox. Subghz switch to levels.
* Subghz: update worker signatures
* SubGhz: pluggable level duration implementations.
* SubGhz : test drawing pictures in Gui
* SubGhz: Added a callback with the parser structure as argument
* SubGhz: copy protocol data to model
* SubGhz: refactoing code
* SubGhz: cleanup and format sources
* SubGhz: remove comments

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
Skorpionm hace 4 años
padre
commit
4ce41a3e6f

+ 15 - 16
applications/subghz/subghz_cli.c

@@ -216,19 +216,16 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) {
 
 
 volatile bool subghz_cli_overrun = false;
 volatile bool subghz_cli_overrun = false;
 
 
-void subghz_cli_command_rx_callback(
-    ApiHalSubGhzCaptureLevel level,
-    uint32_t duration,
-    void* context) {
+void subghz_cli_command_rx_callback(bool level, uint32_t duration, void* context) {
     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-    LevelPair pair = {.level = level, .duration = duration};
+    LevelDuration level_duration = level_duration_make(level, duration);
     if(subghz_cli_overrun) {
     if(subghz_cli_overrun) {
         subghz_cli_overrun = false;
         subghz_cli_overrun = false;
-        pair.level = ApiHalSubGhzCaptureLevelOverrun;
+        level_duration = level_duration_reset();
     }
     }
-    size_t ret =
-        xStreamBufferSendFromISR(context, &pair, sizeof(LevelPair), &xHigherPriorityTaskWoken);
-    if(sizeof(LevelPair) != ret) subghz_cli_overrun = true;
+    size_t ret = xStreamBufferSendFromISR(
+        context, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken);
+    if(sizeof(LevelDuration) != ret) subghz_cli_overrun = true;
     portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
     portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
 }
 }
 
 
@@ -257,13 +254,13 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
     SubGhzProtocol* protocol = subghz_protocol_alloc();
     SubGhzProtocol* protocol = subghz_protocol_alloc();
     subghz_protocol_load_keeloq_file(protocol, "/assets/subghz/keeloq_mfcodes");
     subghz_protocol_load_keeloq_file(protocol, "/assets/subghz/keeloq_mfcodes");
     subghz_protocol_load_nice_flor_s_file(protocol, "/assets/subghz/nice_floor_s_rx");
     subghz_protocol_load_nice_flor_s_file(protocol, "/assets/subghz/nice_floor_s_rx");
-    subghz_protocol_enable_dump(protocol, NULL, NULL);
+    subghz_protocol_enable_dump_text(protocol, NULL, NULL);
 
 
     frequency = api_hal_subghz_set_frequency_and_path(frequency);
     frequency = api_hal_subghz_set_frequency_and_path(frequency);
     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
 
 
     StreamBufferHandle_t rx_stream =
     StreamBufferHandle_t rx_stream =
-        xStreamBufferCreate(sizeof(LevelPair) * 1024, sizeof(LevelPair));
+        xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
 
 
     api_hal_subghz_set_capture_callback(subghz_cli_command_rx_callback, rx_stream);
     api_hal_subghz_set_capture_callback(subghz_cli_command_rx_callback, rx_stream);
     api_hal_subghz_enable_capture();
     api_hal_subghz_enable_capture();
@@ -272,15 +269,17 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
     api_hal_subghz_rx();
     api_hal_subghz_rx();
 
 
     printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
     printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
-    LevelPair pair;
+    LevelDuration level_duration;
     while(!cli_cmd_interrupt_received(cli)) {
     while(!cli_cmd_interrupt_received(cli)) {
-        int ret = xStreamBufferReceive(rx_stream, &pair, sizeof(LevelPair), 10);
-        if(ret == sizeof(LevelPair)) {
-            if(pair.level == ApiHalSubGhzCaptureLevelOverrun) {
+        int ret = xStreamBufferReceive(rx_stream, &level_duration, sizeof(LevelDuration), 10);
+        if(ret == sizeof(LevelDuration)) {
+            if(level_duration_is_reset(level_duration)) {
                 printf(".");
                 printf(".");
                 subghz_protocol_reset(protocol);
                 subghz_protocol_reset(protocol);
             } else {
             } else {
-                subghz_protocol_parse(protocol, pair);
+                bool level = level_duration_get_level(level_duration);
+                uint32_t duration = level_duration_get_duration(level_duration);
+                subghz_protocol_parse(protocol, level, duration);
             }
             }
         }
         }
     }
     }

+ 50 - 3
applications/subghz/views/subghz_capture.c

@@ -11,6 +11,8 @@
 #include <fl_subghz/subghz_worker.h>
 #include <fl_subghz/subghz_worker.h>
 #include <fl_subghz/protocols/subghz_protocol.h>
 #include <fl_subghz/protocols/subghz_protocol.h>
 
 
+#include <assets_icons.h>
+
 struct SubghzCapture {
 struct SubghzCapture {
     View* view;
     View* view;
     SubGhzWorker* worker;
     SubGhzWorker* worker;
@@ -22,6 +24,8 @@ typedef struct {
     uint32_t real_frequency;
     uint32_t real_frequency;
     uint32_t counter;
     uint32_t counter;
     string_t text;
     string_t text;
+    uint16_t scene;
+    SubGhzProtocolCommon parser;
 } SubghzCaptureModel;
 } SubghzCaptureModel;
 
 
 static const char subghz_symbols[] = {'-', '\\', '|', '/'};
 static const char subghz_symbols[] = {'-', '\\', '|', '/'};
@@ -41,8 +45,22 @@ void subghz_capture_draw(Canvas* canvas, SubghzCaptureModel* model) {
         subghz_symbols[model->counter % 4]);
         subghz_symbols[model->counter % 4]);
     canvas_draw_str(canvas, 0, 8, buffer);
     canvas_draw_str(canvas, 0, 8, buffer);
 
 
-    canvas_set_font(canvas, FontSecondary);
-    elements_multiline_text(canvas, 0, 20, string_get_cstr(model->text));
+    switch(model->scene) {
+    case 1:
+        canvas_draw_icon(canvas, 0, 10, &I_RFIDDolphinReceive_97x61);
+        canvas_invert_color(canvas);
+        canvas_draw_box(canvas, 80, 12, 20, 20);
+        canvas_invert_color(canvas);
+        canvas_draw_icon(canvas, 75, 18, &I_sub1_10px);
+        elements_multiline_text_aligned(
+            canvas, 90, 38, AlignCenter, AlignTop, "Detecting\r\nSubGhz");
+        break;
+
+    default:
+        canvas_set_font(canvas, FontSecondary);
+        elements_multiline_text(canvas, 0, 20, string_get_cstr(model->text));
+        break;
+    }
 }
 }
 
 
 bool subghz_capture_input(InputEvent* event, void* context) {
 bool subghz_capture_input(InputEvent* event, void* context) {
@@ -87,6 +105,34 @@ void subghz_capture_text_callback(string_t text, void* context) {
         subghz_capture->view, (SubghzCaptureModel * model) {
         subghz_capture->view, (SubghzCaptureModel * model) {
             model->counter++;
             model->counter++;
             string_set(model->text, text);
             string_set(model->text, text);
+            model->scene = 0;
+            return true;
+        });
+}
+
+void subghz_capture_protocol_callback(SubGhzProtocolCommon* parser, void* context) {
+    furi_assert(context);
+    SubghzCapture* subghz_capture = context;
+    char buffer[64];
+    snprintf(
+        buffer,
+        sizeof(buffer),
+        "%s\r\n"
+        "K:%lX%lX\r\n"
+        "SN:%lX\r\n"
+        "BTN:%X",
+        parser->name,
+        (uint32_t)(parser->code_found >> 32),
+        (uint32_t)(parser->code_found & 0x00000000FFFFFFFF),
+        parser->serial,
+        parser->btn);
+
+    with_view_model(
+        subghz_capture->view, (SubghzCaptureModel * model) {
+            model->counter++;
+            model->parser = *parser;
+            string_set(model->text, buffer);
+            model->scene = 0;
             return true;
             return true;
         });
         });
 }
 }
@@ -104,6 +150,7 @@ void subghz_capture_enter(void* context) {
             model->frequency = subghz_frequencies_433_92;
             model->frequency = subghz_frequencies_433_92;
             model->real_frequency =
             model->real_frequency =
                 api_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
                 api_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
+            model->scene = 1;
             return true;
             return true;
         });
         });
 
 
@@ -163,7 +210,7 @@ SubghzCapture* subghz_capture_alloc() {
     subghz_protocol_load_keeloq_file(subghz_capture->protocol, "/assets/subghz/keeloq_mfcodes");
     subghz_protocol_load_keeloq_file(subghz_capture->protocol, "/assets/subghz/keeloq_mfcodes");
     subghz_protocol_load_nice_flor_s_file(
     subghz_protocol_load_nice_flor_s_file(
         subghz_capture->protocol, "/assets/subghz/nice_floor_s_rx");
         subghz_capture->protocol, "/assets/subghz/nice_floor_s_rx");
-    subghz_protocol_enable_dump(
+    subghz_protocol_enable_dump_text(
         subghz_capture->protocol, subghz_capture_text_callback, subghz_capture);
         subghz_capture->protocol, subghz_capture_text_callback, subghz_capture);
 
 
     return subghz_capture;
     return subghz_capture;

+ 2 - 14
firmware/targets/api-hal-include/api-hal-subghz.h

@@ -2,6 +2,7 @@
 
 
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
+#include <toolbox/level_duration.h>
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
@@ -107,21 +108,8 @@ uint32_t api_hal_subghz_set_frequency(uint32_t value);
  */
  */
 void api_hal_subghz_set_path(ApiHalSubGhzPath path);
 void api_hal_subghz_set_path(ApiHalSubGhzPath path);
 
 
-/** Front Definition for capture callback */
-typedef enum {
-    ApiHalSubGhzCaptureLevelHigh,
-    ApiHalSubGhzCaptureLevelLow,
-    ApiHalSubGhzCaptureLevelOverrun,
-    ApiHalSubGhzCaptureLevelUnderrun,
-} ApiHalSubGhzCaptureLevel;
-
-typedef struct {
-    ApiHalSubGhzCaptureLevel level;
-    uint32_t duration;
-} LevelPair;
-
 /** Signal Timings Capture callback */
 /** Signal Timings Capture callback */
-typedef void (*ApiHalSubGhzCaptureCallback)(ApiHalSubGhzCaptureLevel level, uint32_t time, void* context);
+typedef void (*ApiHalSubGhzCaptureCallback)(bool level, uint32_t duration, void* context);
 
 
 /** Set signal timings capture callback
 /** Set signal timings capture callback
  * @param callback - your callback for front capture
  * @param callback - your callback for front capture

+ 3 - 7
firmware/targets/f6/api-hal/api-hal-subghz.c

@@ -292,9 +292,7 @@ static void api_hal_subghz_capture_ISR() {
         LL_TIM_ClearFlag_CC1(TIM2);
         LL_TIM_ClearFlag_CC1(TIM2);
         api_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
         api_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
         if (api_hal_subghz_capture_callback) {
         if (api_hal_subghz_capture_callback) {
-            api_hal_subghz_capture_callback(
-                ApiHalSubGhzCaptureLevelHigh,
-                api_hal_subghz_capture_delta_duration,
+            api_hal_subghz_capture_callback(true, api_hal_subghz_capture_delta_duration,
                 (void*)api_hal_subghz_capture_callback_context
                 (void*)api_hal_subghz_capture_callback_context
             );
             );
         }
         }
@@ -303,9 +301,7 @@ static void api_hal_subghz_capture_ISR() {
     if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
     if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
         LL_TIM_ClearFlag_CC2(TIM2);
         LL_TIM_ClearFlag_CC2(TIM2);
         if (api_hal_subghz_capture_callback) {
         if (api_hal_subghz_capture_callback) {
-            api_hal_subghz_capture_callback(
-                ApiHalSubGhzCaptureLevelLow,
-                LL_TIM_IC_GetCaptureCH2(TIM2) - api_hal_subghz_capture_delta_duration,
+            api_hal_subghz_capture_callback(false, LL_TIM_IC_GetCaptureCH2(TIM2) - api_hal_subghz_capture_delta_duration,
                 (void*)api_hal_subghz_capture_callback_context
                 (void*)api_hal_subghz_capture_callback_context
             );
             );
         }
         }
@@ -323,7 +319,7 @@ void api_hal_subghz_enable_capture() {
     LL_TIM_InitTypeDef TIM_InitStruct = {0};
     LL_TIM_InitTypeDef TIM_InitStruct = {0};
     TIM_InitStruct.Prescaler = 64-1; 
     TIM_InitStruct.Prescaler = 64-1; 
     TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
     TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
-    TIM_InitStruct.Autoreload = 0xFFFFFFFF;
+    TIM_InitStruct.Autoreload = 0x7FFFFFFE;
     TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
     TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
     LL_TIM_Init(TIM2, &TIM_InitStruct);
     LL_TIM_Init(TIM2, &TIM_InitStruct);
 
 

+ 39 - 13
lib/fl_subghz/protocols/subghz_protocol.c

@@ -22,9 +22,11 @@ struct SubGhzProtocol {
 
 
     SubGhzProtocolTextCallback text_callback;
     SubGhzProtocolTextCallback text_callback;
     void* text_callback_context;
     void* text_callback_context;
+    SubGhzProtocolCommonCallbackDump parser_callback;
+    void* parser_callback_context;
 };
 };
 
 
-static void subghz_protocol_came_rx_callback(SubGhzProtocolCommon* parser, void* context) {
+static void subghz_protocol_text_rx_callback(SubGhzProtocolCommon* parser, void* context) {
     SubGhzProtocol* instance = context;
     SubGhzProtocol* instance = context;
 
 
     string_t output;
     string_t output;
@@ -38,6 +40,13 @@ static void subghz_protocol_came_rx_callback(SubGhzProtocolCommon* parser, void*
     string_clear(output);
     string_clear(output);
 }
 }
 
 
+static void subghz_protocol_parser_rx_callback(SubGhzProtocolCommon* parser, void* context) {
+    SubGhzProtocol* instance = context;
+    if (instance->parser_callback) {
+        instance->parser_callback(parser, instance->parser_callback_context);
+    } 
+}
+
 SubGhzProtocol* subghz_protocol_alloc() {
 SubGhzProtocol* subghz_protocol_alloc() {
     SubGhzProtocol* instance = furi_alloc(sizeof(SubGhzProtocol));
     SubGhzProtocol* instance = furi_alloc(sizeof(SubGhzProtocol));
 
 
@@ -62,19 +71,31 @@ void subghz_protocol_free(SubGhzProtocol* instance) {
     free(instance);
     free(instance);
 }
 }
 
 
-void subghz_protocol_enable_dump(SubGhzProtocol* instance, SubGhzProtocolTextCallback callback, void* context) {
+void subghz_protocol_enable_dump_text(SubGhzProtocol* instance, SubGhzProtocolTextCallback callback, void* context) {
     furi_assert(instance);
     furi_assert(instance);
 
 
-    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->came, subghz_protocol_came_rx_callback, instance);
-    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->keeloq, subghz_protocol_came_rx_callback, instance);
-    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->princeton, subghz_protocol_came_rx_callback, instance);
-    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flo, subghz_protocol_came_rx_callback, instance);
-    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flor_s, subghz_protocol_came_rx_callback, instance);
+    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->came, subghz_protocol_text_rx_callback, instance);
+    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->keeloq, subghz_protocol_text_rx_callback, instance);
+    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->princeton, subghz_protocol_text_rx_callback, instance);
+    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flo, subghz_protocol_text_rx_callback, instance);
+    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flor_s, subghz_protocol_text_rx_callback, instance);
 
 
     instance->text_callback = callback;
     instance->text_callback = callback;
     instance->text_callback_context = context;
     instance->text_callback_context = context;
 }
 }
 
 
+void subghz_protocol_enable_dump(SubGhzProtocol* instance, SubGhzProtocolCommonCallbackDump callback, void* context) {
+    furi_assert(instance);
+
+    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->came, subghz_protocol_parser_rx_callback, instance);
+    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->keeloq, subghz_protocol_parser_rx_callback, instance);
+    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->princeton, subghz_protocol_parser_rx_callback, instance);
+    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flo, subghz_protocol_parser_rx_callback, instance);
+    subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flor_s, subghz_protocol_parser_rx_callback, instance);
+    instance->parser_callback = callback;
+    instance->parser_callback_context = context;
+}
+
 static void subghz_protocol_load_keeloq_file_process_line(SubGhzProtocol* instance, string_t line) {
 static void subghz_protocol_load_keeloq_file_process_line(SubGhzProtocol* instance, string_t line) {
     uint64_t key = 0;
     uint64_t key = 0;
     uint16_t type = 0;
     uint16_t type = 0;
@@ -123,12 +144,17 @@ void subghz_protocol_load_keeloq_file(SubGhzProtocol* instance, const char* file
 }
 }
 
 
 void subghz_protocol_reset(SubGhzProtocol* instance) {
 void subghz_protocol_reset(SubGhzProtocol* instance) {
+    subghz_protocol_came_reset(instance->came);
+    subghz_protocol_keeloq_reset(instance->keeloq);
+    subghz_protocol_princeton_reset(instance->princeton);
+    subghz_protocol_nice_flo_reset(instance->nice_flo);
+    subghz_protocol_nice_flor_s_reset(instance->nice_flor_s);
 }
 }
 
 
-void subghz_protocol_parse(SubGhzProtocol* instance, LevelPair data) {
-    subghz_protocol_came_parse(instance->came, data);
-    subghz_protocol_keeloq_parse(instance->keeloq, data);
-    subghz_protocol_princeton_parse(instance->princeton, data);
-    subghz_protocol_nice_flo_parse(instance->nice_flo, data);
-    subghz_protocol_nice_flor_s_parse(instance->nice_flor_s, data);
+void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration) {
+    subghz_protocol_came_parse(instance->came, level, duration);
+    subghz_protocol_keeloq_parse(instance->keeloq, level, duration);
+    subghz_protocol_princeton_parse(instance->princeton, level, duration);
+    subghz_protocol_nice_flo_parse(instance->nice_flo, level, duration);
+    subghz_protocol_nice_flor_s_parse(instance->nice_flor_s, level, duration);
 }
 }

+ 14 - 7
lib/fl_subghz/protocols/subghz_protocol.h

@@ -3,6 +3,7 @@
 #include "subghz_protocol_common.h"
 #include "subghz_protocol_common.h"
 
 
 typedef void (*SubGhzProtocolTextCallback)(string_t text, void* context);
 typedef void (*SubGhzProtocolTextCallback)(string_t text, void* context);
+typedef void (*SubGhzProtocolCommonCallbackDump)(SubGhzProtocolCommon *parser, void* context);
 
 
 typedef struct SubGhzProtocol SubGhzProtocol;
 typedef struct SubGhzProtocol SubGhzProtocol;
 
 
@@ -18,16 +19,21 @@ SubGhzProtocol* subghz_protocol_alloc();
  */
  */
 void subghz_protocol_free(SubGhzProtocol* instance);
 void subghz_protocol_free(SubGhzProtocol* instance);
 
 
-/** Outputting data from all parsers
+/** Outputting data text from all parsers
  * 
  * 
  * @param instance - SubGhzProtocol instance
  * @param instance - SubGhzProtocol instance
  * @param callback - SubGhzProtocolTextCallback callback
  * @param callback - SubGhzProtocolTextCallback callback
  * @param context
  * @param context
  */
  */
-void subghz_protocol_enable_dump(
-    SubGhzProtocol* instance,
-    SubGhzProtocolTextCallback callback,
-    void* context);
+void subghz_protocol_enable_dump_text(SubGhzProtocol* instance,SubGhzProtocolTextCallback callback,void* context);
+
+/** Outputting data SubGhzProtocol from all parsers
+ * 
+ * @param instance - SubGhzProtocol instance
+ * @param callback - SubGhzProtocolTextCallback callback
+ * @param context
+ */
+void subghz_protocol_enable_dump( SubGhzProtocol* instance, SubGhzProtocolCommonCallbackDump callback, void* context);
 
 
 /** File name rainbow table Nice Flor-S
 /** File name rainbow table Nice Flor-S
  * 
  * 
@@ -52,6 +58,7 @@ void subghz_protocol_reset(SubGhzProtocol* instance);
 /** Loading data into all parsers
 /** Loading data into all parsers
  * 
  * 
  * @param instance - SubGhzProtocol instance
  * @param instance - SubGhzProtocol instance
- * @param data - LevelPair data
+ * @param level - true is high, false if low
+ * @param duration - level duration in microseconds
  */
  */
-void subghz_protocol_parse(SubGhzProtocol* instance, LevelPair data);
+void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration);

+ 17 - 12
lib/fl_subghz/protocols/subghz_protocol_came.c

@@ -63,11 +63,15 @@ void subghz_protocol_came_send_key(SubGhzProtocolCame* instance, uint64_t key, u
     }
     }
 }
 }
 
 
-void subghz_protocol_came_parse(SubGhzProtocolCame* instance, LevelPair data) {
+void subghz_protocol_came_reset(SubGhzProtocolCame* instance) {
+    instance->common.parser_step = 0;
+}
+
+void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32_t duration) {
     switch (instance->common.parser_step) {
     switch (instance->common.parser_step) {
     case 0:
     case 0:
-        if ((data.level == ApiHalSubGhzCaptureLevelLow)
-                && (DURATION_DIFF(data.duration,instance->common.te_shot * 51)< instance->common.te_delta * 51)) { //Need protocol 36 te_shot
+        if ((!level)
+                && (DURATION_DIFF(duration, instance->common.te_shot * 51)< instance->common.te_delta * 51)) { //Need protocol 36 te_shot
             //Found header CAME
             //Found header CAME
             instance->common.parser_step = 1;
             instance->common.parser_step = 1;
         } else {
         } else {
@@ -75,9 +79,9 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, LevelPair data) {
         }
         }
         break;
         break;
     case 1:
     case 1:
-        if (data.level == ApiHalSubGhzCaptureLevelLow) {
+        if (!level) {
             break;
             break;
-        } else if (DURATION_DIFF(data.duration,instance->common.te_shot)< instance->common.te_delta) {
+        } else if (DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta) {
             //Found start bit CAME
             //Found start bit CAME
             instance->common.parser_step = 2;
             instance->common.parser_step = 2;
             instance->common.code_found = 0;
             instance->common.code_found = 0;
@@ -87,33 +91,34 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, LevelPair data) {
         }
         }
         break;
         break;
     case 2:
     case 2:
-        if (data.level == ApiHalSubGhzCaptureLevelLow) { //save interval
-            if (data.duration >= (instance->common.te_shot * 4)) {
+        if (!level) { //save interval
+            if (duration >= (instance->common.te_shot * 4)) {
                 instance->common.parser_step = 1;
                 instance->common.parser_step = 1;
                 if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
                 if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
 
 
-                    //ToDo out data display
+
                     instance->common.serial = 0x0;
                     instance->common.serial = 0x0;
                     instance->common.btn = 0x0;
                     instance->common.btn = 0x0;
                     if (instance->common.callback)
                     if (instance->common.callback)
                         instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
                         instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
+                
                 }
                 }
                 break;
                 break;
             }
             }
-            instance->common.te_last = data.duration;
+            instance->common.te_last = duration;
             instance->common.parser_step = 3;
             instance->common.parser_step = 3;
         } else {
         } else {
             instance->common.parser_step = 0;
             instance->common.parser_step = 0;
         }
         }
         break;
         break;
     case 3:
     case 3:
-        if (data.level == ApiHalSubGhzCaptureLevelHigh) {
+        if (level) {
             if ((DURATION_DIFF(instance->common.te_last,instance->common.te_shot) < instance->common.te_delta)
             if ((DURATION_DIFF(instance->common.te_last,instance->common.te_shot) < instance->common.te_delta)
-                    && (DURATION_DIFF(data.duration,instance->common.te_long)< instance->common.te_delta)) {
+                    && (DURATION_DIFF(duration, instance->common.te_long)< instance->common.te_delta)) {
                 subghz_protocol_common_add_bit(&instance->common, 0);
                 subghz_protocol_common_add_bit(&instance->common, 0);
                 instance->common.parser_step = 2;
                 instance->common.parser_step = 2;
             } else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta)
             } else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta)
-                    && (DURATION_DIFF(data.duration,instance->common.te_shot)< instance->common.te_delta)) {
+                    && (DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta)) {
                 subghz_protocol_common_add_bit(&instance->common, 1);
                 subghz_protocol_common_add_bit(&instance->common, 1);
                 instance->common.parser_step = 2;
                 instance->common.parser_step = 2;
             } else
             } else

+ 7 - 2
lib/fl_subghz/protocols/subghz_protocol_came.h

@@ -25,9 +25,14 @@ void subghz_protocol_came_free(SubGhzProtocolCame* instance);
  */
  */
 void subghz_protocol_came_send_key(SubGhzProtocolCame* instance, uint64_t key, uint8_t bit, uint8_t repeat);
 void subghz_protocol_came_send_key(SubGhzProtocolCame* instance, uint64_t key, uint8_t bit, uint8_t repeat);
 
 
+/** Reset internal state
+ * @param instance - SubGhzProtocolCame instance
+ */
+void subghz_protocol_came_reset(SubGhzProtocolCame* instance);
+
 /** Parse accepted duration
 /** Parse accepted duration
  * 
  * 
  * @param instance - SubGhzProtocolCame instance
  * @param instance - SubGhzProtocolCame instance
- * @param data - LevelPair data
+ * @param data - LevelDuration level_duration
  */
  */
-void subghz_protocol_came_parse(SubGhzProtocolCame* instance, LevelPair data);
+void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32_t duration);;

+ 1 - 0
lib/fl_subghz/protocols/subghz_protocol_common.c

@@ -27,6 +27,7 @@ void subghz_protocol_common_set_callback(SubGhzProtocolCommon* common, SubGhzPro
     common->context = context;
     common->context = context;
 }
 }
 
 
+
 void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output) {
 void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output) {
     if (instance->to_string) {
     if (instance->to_string) {
         instance->to_string(instance, output);
         instance->to_string(instance, output);

+ 2 - 2
lib/fl_subghz/protocols/subghz_protocol_common.h

@@ -11,7 +11,7 @@
 
 
 #define SUBGHZ_TX_PIN_HIGTH() 
 #define SUBGHZ_TX_PIN_HIGTH() 
 #define SUBGHZ_TX_PIN_LOW() 
 #define SUBGHZ_TX_PIN_LOW() 
-#define DURATION_DIFF(x,y) ((x < y) ? (y - x) : (x - y))
+#define DURATION_DIFF(x, y) ((x < y) ? (y - x) : (x - y))
 
 
 typedef struct SubGhzProtocolCommon SubGhzProtocolCommon;
 typedef struct SubGhzProtocolCommon SubGhzProtocolCommon;
 
 
@@ -29,7 +29,7 @@ struct SubGhzProtocolCommon {
     uint8_t     code_count_bit;
     uint8_t     code_count_bit;
     uint8_t     code_min_count_bit_for_found;
     uint8_t     code_min_count_bit_for_found;
     uint8_t     parser_step;
     uint8_t     parser_step;
-    uint16_t    te_last;
+    uint32_t    te_last;
     uint8_t     header_count;
     uint8_t     header_count;
     uint16_t    cnt;
     uint16_t    cnt;
     uint32_t    serial;
     uint32_t    serial;

+ 14 - 12
lib/fl_subghz/protocols/subghz_protocol_keeloq.c

@@ -271,10 +271,14 @@ void subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, uint64_t ke
     }
     }
 }
 }
 
 
-void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, LevelPair data) {
+void subghz_protocol_keeloq_reset(SubGhzProtocolKeeloq* instance) {
+    instance->common.parser_step = 0;
+}
+
+void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, uint32_t duration) {
     switch (instance->common.parser_step) {
     switch (instance->common.parser_step) {
     case 0:
     case 0:
-        if ((data.level == ApiHalSubGhzCaptureLevelHigh) && DURATION_DIFF(data.duration, instance->common.te_shot)< instance->common.te_delta) {
+        if ((level) && DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta) {
             instance->common.parser_step = 1;
             instance->common.parser_step = 1;
             instance->common.header_count++;
             instance->common.header_count++;
         } else {
         } else {
@@ -283,11 +287,11 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, LevelPair data
 
 
         break;
         break;
     case 1:
     case 1:
-        if ((data.level == ApiHalSubGhzCaptureLevelLow) && (DURATION_DIFF(data.duration, instance->common.te_shot ) < instance->common.te_delta)) {
+        if ((!level) && (DURATION_DIFF(duration, instance->common.te_shot ) < instance->common.te_delta)) {
             instance->common.parser_step = 0;
             instance->common.parser_step = 0;
             break;
             break;
         }
         }
-        if ((instance->common.header_count > 2) && ( DURATION_DIFF(data.duration, instance->common.te_shot * 10)< instance->common.te_delta * 10)) {
+        if ((instance->common.header_count > 2) && ( DURATION_DIFF(duration, instance->common.te_shot * 10)< instance->common.te_delta * 10)) {
             // Found header
             // Found header
             instance->common.parser_step = 2;
             instance->common.parser_step = 2;
             instance->common.code_found = 0;
             instance->common.code_found = 0;
@@ -298,21 +302,19 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, LevelPair data
         }
         }
         break;
         break;
     case 2:
     case 2:
-        if (data.level == ApiHalSubGhzCaptureLevelHigh) {
-            instance->common.te_last = data.duration;
+        if (level) {
+            instance->common.te_last = duration;
             instance->common.parser_step = 3;
             instance->common.parser_step = 3;
         }
         }
         break;
         break;
     case 3:
     case 3:
-        if (data.level == ApiHalSubGhzCaptureLevelLow) {
-            if (data.duration >= (instance->common.te_shot * 2 + instance->common.te_delta)) {
+        if (!level) {
+            if (duration >= (instance->common.te_shot * 2 + instance->common.te_delta)) {
                 // Found end TX
                 // Found end TX
                 instance->common.parser_step = 0;
                 instance->common.parser_step = 0;
                 if (instance->common.code_count_bit >= instance->common.code_min_count_bit_for_found) {
                 if (instance->common.code_count_bit >= instance->common.code_min_count_bit_for_found) {
-                    //&& (instance->common.code_last_found != instance->common.code_found )) {
                     instance->common.code_last_found = instance->common.code_found;
                     instance->common.code_last_found = instance->common.code_found;
 
 
-                    //ToDo out data display
                     subghz_protocol_keeloq_check_remote_controller(instance);
                     subghz_protocol_keeloq_check_remote_controller(instance);
 
 
                     instance->common.code_found = 0;
                     instance->common.code_found = 0;
@@ -321,13 +323,13 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, LevelPair data
                 }
                 }
                 break;
                 break;
             } else if ((DURATION_DIFF(instance->common.te_last, instance->common.te_shot) < instance->common.te_delta)
             } else if ((DURATION_DIFF(instance->common.te_last, instance->common.te_shot) < instance->common.te_delta)
-                    && (DURATION_DIFF(data.duration, instance->common.te_long) < instance->common.te_delta)) {
+                    && (DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
                 if (instance->common.code_count_bit < instance->common.code_min_count_bit_for_found) {
                 if (instance->common.code_count_bit < instance->common.code_min_count_bit_for_found) {
                     subghz_protocol_common_add_bit(&instance->common, 1);
                     subghz_protocol_common_add_bit(&instance->common, 1);
                 }
                 }
                 instance->common.parser_step = 2;
                 instance->common.parser_step = 2;
             } else if ((DURATION_DIFF(instance->common.te_last, instance->common.te_long) < instance->common.te_delta)
             } else if ((DURATION_DIFF(instance->common.te_last, instance->common.te_long) < instance->common.te_delta)
-                    && (DURATION_DIFF(data.duration, instance->common.te_shot) < instance->common.te_delta)) {
+                    && (DURATION_DIFF(duration, instance->common.te_shot) < instance->common.te_delta)) {
                 if (instance->common.code_count_bit < instance->common.code_min_count_bit_for_found) {
                 if (instance->common.code_count_bit < instance->common.code_min_count_bit_for_found) {
                     subghz_protocol_common_add_bit(&instance->common, 0);
                     subghz_protocol_common_add_bit(&instance->common, 0);
                 }
                 }

+ 7 - 2
lib/fl_subghz/protocols/subghz_protocol_keeloq.h

@@ -34,12 +34,17 @@ void subghz_protocol_keeloq_add_manafacture_key(SubGhzProtocolKeeloq* instance,
  */
  */
 void subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, uint64_t key, uint8_t bit, uint8_t repeat);
 void subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, uint64_t key, uint8_t bit, uint8_t repeat);
 
 
+/** Reset internal state
+ * @param instance - SubGhzProtocolKeeloq instance
+ */
+void subghz_protocol_keeloq_reset(SubGhzProtocolKeeloq* instance);
+
 /** Parse accepted duration
 /** Parse accepted duration
  * 
  * 
  * @param instance - SubGhzProtocolKeeloq instance
  * @param instance - SubGhzProtocolKeeloq instance
- * @param data - LevelPair data
+ * @param data - LevelDuration level_duration
  */
  */
-void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, LevelPair data);
+void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, uint32_t duration);;
 
 
 /** Outputting information from the parser
 /** Outputting information from the parser
  * 
  * 

+ 16 - 13
lib/fl_subghz/protocols/subghz_protocol_nice_flo.c

@@ -62,11 +62,15 @@ void subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, uint64_t
     }
     }
 }
 }
 
 
-void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, LevelPair data) {
+void subghz_protocol_nice_flo_reset(SubGhzProtocolNiceFlo* instance) {
+    instance->common.parser_step = 0;
+}
+
+void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, uint32_t duration) {
     switch (instance->common.parser_step) {
     switch (instance->common.parser_step) {
     case 0:
     case 0:
-        if ((data.level == ApiHalSubGhzCaptureLevelLow)
-                && (DURATION_DIFF(data.duration,instance->common.te_shot * 36)< instance->common.te_delta * 36)) {
+        if ((!level)
+                && (DURATION_DIFF(duration, instance->common.te_shot * 36)< instance->common.te_delta * 36)) {
             //Found header Nice Flo
             //Found header Nice Flo
             instance->common.parser_step = 1;
             instance->common.parser_step = 1;
         } else {
         } else {
@@ -74,9 +78,9 @@ void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, LevelPair d
         }
         }
         break;
         break;
     case 1:
     case 1:
-        if (data.level == ApiHalSubGhzCaptureLevelLow) {
+        if (!level) {
             break;
             break;
-        } else if (DURATION_DIFF(data.duration,instance->common.te_shot)< instance->common.te_delta) {
+        } else if (DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta) {
             //Found start bit Nice Flo
             //Found start bit Nice Flo
             instance->common.parser_step = 2;
             instance->common.parser_step = 2;
             instance->common.code_found = 0;
             instance->common.code_found = 0;
@@ -86,31 +90,30 @@ void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, LevelPair d
         }
         }
         break;
         break;
     case 2:
     case 2:
-        if (data.level == ApiHalSubGhzCaptureLevelLow) { //save interval
-            if (data.duration >= (instance->common.te_shot * 4)) {
+        if (!level) { //save interval
+            if (duration >= (instance->common.te_shot * 4)) {
                 instance->common.parser_step = 1;
                 instance->common.parser_step = 1;
                 if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
                 if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
 
 
-                    //ToDo out data display
-                    //instance->common.serial = 0x12345;
                     if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
                     if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
+
                 }
                 }
                 break;
                 break;
             }
             }
-            instance->common.te_last = data.duration;
+            instance->common.te_last = duration;
             instance->common.parser_step = 3;
             instance->common.parser_step = 3;
         } else {
         } else {
             instance->common.parser_step = 0;
             instance->common.parser_step = 0;
         }
         }
         break;
         break;
     case 3:
     case 3:
-        if (data.level == ApiHalSubGhzCaptureLevelHigh) {
+        if (level) {
             if ((DURATION_DIFF(instance->common.te_last,instance->common.te_shot) < instance->common.te_delta)
             if ((DURATION_DIFF(instance->common.te_last,instance->common.te_shot) < instance->common.te_delta)
-                    && (DURATION_DIFF(data.duration,instance->common.te_long)< instance->common.te_delta)) {
+                    && (DURATION_DIFF(duration, instance->common.te_long)< instance->common.te_delta)) {
                 subghz_protocol_common_add_bit(&instance->common, 0);
                 subghz_protocol_common_add_bit(&instance->common, 0);
                 instance->common.parser_step = 2;
                 instance->common.parser_step = 2;
             } else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta)
             } else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta)
-                    && (DURATION_DIFF(data.duration,instance->common.te_shot)< instance->common.te_delta)) {
+                    && (DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta)) {
                 subghz_protocol_common_add_bit(&instance->common, 1);
                 subghz_protocol_common_add_bit(&instance->common, 1);
                 instance->common.parser_step = 2;
                 instance->common.parser_step = 2;
             } else
             } else

+ 7 - 2
lib/fl_subghz/protocols/subghz_protocol_nice_flo.h

@@ -25,9 +25,14 @@ void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance);
  */
  */
 void subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, uint64_t key, uint8_t bit, uint8_t repeat);
 void subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, uint64_t key, uint8_t bit, uint8_t repeat);
 
 
+/** Reset internal state
+ * @param instance - SubGhzProtocolNiceFlo instance
+ */
+void subghz_protocol_nice_flo_reset(SubGhzProtocolNiceFlo* instance);
+
 /** Parse accepted duration
 /** Parse accepted duration
  * 
  * 
  * @param instance - SubGhzProtocolNiceFlo instance
  * @param instance - SubGhzProtocolNiceFlo instance
- * @param data - LevelPair data
+ * @param data - LevelDuration level_duration
  */
  */
-void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, LevelPair data);
+void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, uint32_t duration);;

+ 19 - 14
lib/fl_subghz/protocols/subghz_protocol_nice_flor_s.c

@@ -144,11 +144,15 @@ void subghz_nice_flor_s_decoder_decrypt(SubGhzProtocolNiceFlorS* instance) {
     if(instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
     if(instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
 }
 }
 
 
-void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, LevelPair data) {
+void subghz_protocol_nice_flor_s_reset(SubGhzProtocolNiceFlorS* instance) {
+    instance->common.parser_step = 0;
+}
+
+void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, bool level, uint32_t duration) {
     switch(instance->common.parser_step) {
     switch(instance->common.parser_step) {
     case 0:
     case 0:
-        if((data.level == ApiHalSubGhzCaptureLevelLow) 
-            && (DURATION_DIFF(data.duration, instance->common.te_shot * 38) < instance->common.te_delta * 38)) {
+        if((!level) 
+            && (DURATION_DIFF(duration, instance->common.te_shot * 38) < instance->common.te_delta * 38)) {
             //Found start header Nice Flor-S
             //Found start header Nice Flor-S
             instance->common.parser_step = 1;
             instance->common.parser_step = 1;
         } else {
         } else {
@@ -156,8 +160,8 @@ void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, LevelP
         }
         }
         break;
         break;
     case 1:
     case 1:
-        if((data.level == ApiHalSubGhzCaptureLevelHigh) 
-            && (DURATION_DIFF(data.duration, instance->common.te_shot * 3) < instance->common.te_delta * 3)) {
+        if((level) 
+            && (DURATION_DIFF(duration, instance->common.te_shot * 3) < instance->common.te_delta * 3)) {
             //Found next header Nice Flor-S
             //Found next header Nice Flor-S
             instance->common.parser_step = 2;
             instance->common.parser_step = 2;
         } else {
         } else {
@@ -165,8 +169,8 @@ void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, LevelP
         }
         }
         break;
         break;
     case 2:
     case 2:
-        if((data.level == ApiHalSubGhzCaptureLevelLow) 
-            && (DURATION_DIFF(data.duration, instance->common.te_shot * 3) < instance->common.te_delta * 3)) {
+        if((!level) 
+            && (DURATION_DIFF(duration, instance->common.te_shot * 3) < instance->common.te_delta * 3)) {
             //Found header Nice Flor-S
             //Found header Nice Flor-S
             instance->common.parser_step = 3;
             instance->common.parser_step = 3;
             instance->common.code_found = 0;
             instance->common.code_found = 0;
@@ -176,31 +180,32 @@ void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, LevelP
         }
         }
         break;
         break;
     case 3:
     case 3:
-        if(data.level == ApiHalSubGhzCaptureLevelHigh) {
-            if(DURATION_DIFF(data.duration, instance->common.te_shot * 3) < instance->common.te_delta) {
+        if(level) {
+            if(DURATION_DIFF(duration, instance->common.te_shot * 3) < instance->common.te_delta) {
                 //Found STOP bit
                 //Found STOP bit
                 instance->common.parser_step = 0;
                 instance->common.parser_step = 0;
                 if(instance->common.code_count_bit >=instance->common.code_min_count_bit_for_found) {
                 if(instance->common.code_count_bit >=instance->common.code_min_count_bit_for_found) {
-                    //ToDo out data display
+
                     subghz_nice_flor_s_decoder_decrypt(instance);
                     subghz_nice_flor_s_decoder_decrypt(instance);
+                    
                 }
                 }
                 break;
                 break;
             } else {
             } else {
                 //save interval
                 //save interval
-                instance->common.te_last = data.duration;
+                instance->common.te_last = duration;
                 instance->common.parser_step = 4;
                 instance->common.parser_step = 4;
             }
             }
         }
         }
         break;
         break;
     case 4:
     case 4:
-        if(data.level == ApiHalSubGhzCaptureLevelLow) {
+        if(!level) {
             if((DURATION_DIFF(instance->common.te_last, instance->common.te_shot) < instance->common.te_delta) 
             if((DURATION_DIFF(instance->common.te_last, instance->common.te_shot) < instance->common.te_delta) 
-                &&(DURATION_DIFF(data.duration, instance->common.te_long) < instance->common.te_delta)) {
+                &&(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
                 subghz_protocol_common_add_bit(&instance->common, 0);
                 subghz_protocol_common_add_bit(&instance->common, 0);
                 instance->common.parser_step = 3;
                 instance->common.parser_step = 3;
             } else if(
             } else if(
                 (DURATION_DIFF(instance->common.te_last, instance->common.te_long) < instance->common.te_delta) 
                 (DURATION_DIFF(instance->common.te_last, instance->common.te_long) < instance->common.te_delta) 
-                    &&(DURATION_DIFF(data.duration, instance->common.te_shot) < instance->common.te_delta)) {
+                    &&(DURATION_DIFF(duration, instance->common.te_shot) < instance->common.te_delta)) {
                 subghz_protocol_common_add_bit(&instance->common, 1);
                 subghz_protocol_common_add_bit(&instance->common, 1);
                 instance->common.parser_step = 3;
                 instance->common.parser_step = 3;
             } else
             } else

+ 7 - 2
lib/fl_subghz/protocols/subghz_protocol_nice_flor_s.h

@@ -32,12 +32,17 @@ void subghz_protocol_nice_flor_s_name_file(SubGhzProtocolNiceFlorS* instance, co
  */
  */
 void subghz_protocol_nice_flor_s_send_key(SubGhzProtocolNiceFlorS* instance, uint64_t key, uint8_t bit, uint8_t repeat);
 void subghz_protocol_nice_flor_s_send_key(SubGhzProtocolNiceFlorS* instance, uint64_t key, uint8_t bit, uint8_t repeat);
 
 
+/** Reset internal state
+ * @param instance - SubGhzProtocolNiceFlorS instance
+ */
+void subghz_protocol_nice_flor_s_reset(SubGhzProtocolNiceFlorS* instance);
+
 /** Parse accepted duration
 /** Parse accepted duration
  * 
  * 
  * @param instance - SubGhzProtocolNiceFlorS instance
  * @param instance - SubGhzProtocolNiceFlorS instance
- * @param data - LevelPair data
+ * @param data - LevelDuration level_duration
  */
  */
-void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, LevelPair data);
+void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, bool level, uint32_t duration);;
 
 
 /** Outputting information from the parser
 /** Outputting information from the parser
  * 
  * 

+ 15 - 10
lib/fl_subghz/protocols/subghz_protocol_princeton.c

@@ -62,11 +62,15 @@ void subghz_protocol_princeton_send_key(SubGhzProtocolPrinceton* instance, uint6
     }
     }
 }
 }
 
 
-void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, LevelPair data) {
+void subghz_protocol_princeton_reset(SubGhzProtocolPrinceton* instance) {
+    instance->common.parser_step = 0;
+}
+
+void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, bool level, uint32_t duration) {
     switch (instance->common.parser_step) {
     switch (instance->common.parser_step) {
     case 0:
     case 0:
-        if ((data.level == ApiHalSubGhzCaptureLevelLow)
-                && (DURATION_DIFF(data.duration,instance->common.te_shot * 36)< instance->common.te_delta * 36)) {
+        if ((!level)
+                && (DURATION_DIFF(duration,instance->common.te_shot * 36)< instance->common.te_delta * 36)) {
             //Found Preambula
             //Found Preambula
             instance->common.parser_step = 1;
             instance->common.parser_step = 1;
             instance->common.code_found = 0;
             instance->common.code_found = 0;
@@ -77,20 +81,21 @@ void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, LevelPai
         break;
         break;
     case 1:
     case 1:
         //save duration
         //save duration
-        if (data.level == ApiHalSubGhzCaptureLevelHigh) {
-            instance->common.te_last = data.duration;
+        if (level) {
+            instance->common.te_last = duration;
             instance->common.parser_step = 2;
             instance->common.parser_step = 2;
         }
         }
         break;
         break;
     case 2:
     case 2:
-        if (data.level == ApiHalSubGhzCaptureLevelLow) {
-            if (data.duration>= (instance->common.te_shot * 10+ instance->common.te_delta)) {
+        if (!level) {
+            if (duration >= (instance->common.te_shot * 10 + instance->common.te_delta)) {
                 instance->common.parser_step = 1;
                 instance->common.parser_step = 1;
                 if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
                 if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
-                    //ToDo out data display
+
                     instance->common.serial = instance->common.code_found >> 4;
                     instance->common.serial = instance->common.code_found >> 4;
                     instance->common.btn = (uint8_t)instance->common.code_found & 0x00000F;
                     instance->common.btn = (uint8_t)instance->common.code_found & 0x00000F;
                     if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
                     if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
+
                 }
                 }
                 instance->common.code_found = 0;
                 instance->common.code_found = 0;
                 instance->common.code_count_bit = 0;
                 instance->common.code_count_bit = 0;
@@ -98,11 +103,11 @@ void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, LevelPai
             }
             }
 
 
             if ((DURATION_DIFF(instance->common.te_last,instance->common.te_shot)< instance->common.te_delta)
             if ((DURATION_DIFF(instance->common.te_last,instance->common.te_shot)< instance->common.te_delta)
-                    && (DURATION_DIFF(data.duration,instance->common.te_long)< instance->common.te_delta*3)) {
+                    && (DURATION_DIFF(duration,instance->common.te_long)< instance->common.te_delta*3)) {
                 subghz_protocol_common_add_bit(&instance->common, 0);
                 subghz_protocol_common_add_bit(&instance->common, 0);
                 instance->common.parser_step = 1;
                 instance->common.parser_step = 1;
             } else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta*3)
             } else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta*3)
-                    && (DURATION_DIFF(data.duration,instance->common.te_shot)< instance->common.te_delta)) {
+                    && (DURATION_DIFF(duration,instance->common.te_shot)< instance->common.te_delta)) {
                 subghz_protocol_common_add_bit(&instance->common, 1);
                 subghz_protocol_common_add_bit(&instance->common, 1);
                 instance->common.parser_step = 1;
                 instance->common.parser_step = 1;
             } else {
             } else {

+ 7 - 2
lib/fl_subghz/protocols/subghz_protocol_princeton.h

@@ -25,12 +25,17 @@ void subghz_protocol_princeton_free(SubGhzProtocolPrinceton* instance);
  */
  */
 void subghz_protocol_princeton_send_key(SubGhzProtocolPrinceton* instance, uint64_t key, uint8_t bit, uint8_t repeat);
 void subghz_protocol_princeton_send_key(SubGhzProtocolPrinceton* instance, uint64_t key, uint8_t bit, uint8_t repeat);
 
 
+/** Reset internal state
+ * @param instance - SubGhzProtocolPrinceton instance
+ */
+void subghz_protocol_princeton_reset(SubGhzProtocolPrinceton* instance);
+
 /** Parse accepted duration
 /** Parse accepted duration
  * 
  * 
  * @param instance - SubGhzProtocolPrinceton instance
  * @param instance - SubGhzProtocolPrinceton instance
- * @param data - LevelPair data
+ * @param data - LevelDuration level_duration
  */
  */
-void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, LevelPair data);
+void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, bool level, uint32_t duration);;
 
 
 /** Outputting information from the parser
 /** Outputting information from the parser
  * 
  * 

+ 13 - 15
lib/fl_subghz/subghz_worker.c

@@ -21,22 +21,18 @@ struct SubGhzWorker {
  * @param duration received signal duration
  * @param duration received signal duration
  * @param context 
  * @param context 
  */
  */
-void subghz_worker_rx_callback(
-    ApiHalSubGhzCaptureLevel level,
-    uint32_t duration,
-    void* context) {
-
+void subghz_worker_rx_callback(bool level, uint32_t duration, void* context) {
     SubGhzWorker* instance = context;
     SubGhzWorker* instance = context;
 
 
     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-    LevelPair pair = {.level = level, .duration = duration};
+    LevelDuration level_duration = level_duration_make(level, duration);
     if(instance->overrun) {
     if(instance->overrun) {
         instance->overrun = false;
         instance->overrun = false;
-        pair.level = ApiHalSubGhzCaptureLevelOverrun;
+        level_duration = level_duration_reset();
     }
     }
     size_t ret =
     size_t ret =
-        xStreamBufferSendFromISR(instance->stream, &pair, sizeof(LevelPair), &xHigherPriorityTaskWoken);
-    if(sizeof(LevelPair) != ret) instance->overrun = true;
+        xStreamBufferSendFromISR(instance->stream, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken);
+    if(sizeof(LevelDuration) != ret) instance->overrun = true;
     portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
     portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
 }
 }
 
 
@@ -48,15 +44,17 @@ void subghz_worker_rx_callback(
 static int32_t subghz_worker_thread_callback(void* context) {
 static int32_t subghz_worker_thread_callback(void* context) {
     SubGhzWorker* instance = context;
     SubGhzWorker* instance = context;
 
 
-    LevelPair pair;
+    LevelDuration level_duration;
     while(instance->running) {
     while(instance->running) {
-        int ret = xStreamBufferReceive(instance->stream, &pair, sizeof(LevelPair), 10);
-        if(ret == sizeof(LevelPair)) {
-            if(pair.level == ApiHalSubGhzCaptureLevelOverrun) {
+        int ret = xStreamBufferReceive(instance->stream, &level_duration, sizeof(LevelDuration), 10);
+        if(ret == sizeof(LevelDuration)) {
+            if(level_duration_is_reset(level_duration)) {
                 printf(".");
                 printf(".");
                 if (instance->overrun_callback) instance->overrun_callback(instance->context);
                 if (instance->overrun_callback) instance->overrun_callback(instance->context);
             } else {
             } else {
-                if (instance->pair_callback) instance->pair_callback(instance->context, pair);
+                bool level = level_duration_get_level(level_duration);
+                uint32_t duration = level_duration_get_duration(level_duration);
+                if (instance->pair_callback) instance->pair_callback(instance->context, level, duration);
             }
             }
         }
         }
     }
     }
@@ -73,7 +71,7 @@ SubGhzWorker* subghz_worker_alloc() {
     furi_thread_set_context(instance->thread, instance);
     furi_thread_set_context(instance->thread, instance);
     furi_thread_set_callback(instance->thread, subghz_worker_thread_callback);
     furi_thread_set_callback(instance->thread, subghz_worker_thread_callback);
     
     
-    instance->stream = xStreamBufferCreate(sizeof(LevelPair) * 1024, sizeof(LevelPair));
+    instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
 
 
     return instance;
     return instance;
 }
 }

+ 2 - 2
lib/fl_subghz/subghz_worker.h

@@ -6,9 +6,9 @@ typedef struct SubGhzWorker SubGhzWorker;
 
 
 typedef void (*SubGhzWorkerOverrunCallback)(void* context);
 typedef void (*SubGhzWorkerOverrunCallback)(void* context);
 
 
-typedef void (*SubGhzWorkerPairCallback)(void* context, LevelPair pair);
+typedef void (*SubGhzWorkerPairCallback)(void* context, bool level, uint32_t duration);
 
 
-void subghz_worker_rx_callback(ApiHalSubGhzCaptureLevel level, uint32_t duration, void* context);
+void subghz_worker_rx_callback(bool level, uint32_t duration, void* context);
 
 
 /** Allocate SubGhzWorker
 /** Allocate SubGhzWorker
  * 
  * 

+ 71 - 0
lib/toolbox/level_duration.h

@@ -0,0 +1,71 @@
+#pragma once
+
+#include <stdint.h>
+
+#define LEVEL_DURATION_BIG
+
+#ifdef LEVEL_DURATION_BIG
+
+#define LEVEL_DURATION_RESET 0U
+#define LEVEL_DURATION_LEVEL_LOW 1U
+#define LEVEL_DURATION_LEVEL_HIGH 2U
+#define LEVEL_DURATION_RESERVED 0x800000U
+
+typedef struct {
+    uint32_t level;
+    uint32_t duration;
+} LevelDuration;
+
+static inline LevelDuration level_duration_make(bool level, uint32_t duration) {
+    LevelDuration level_duration;
+    level_duration.level = level ? LEVEL_DURATION_LEVEL_HIGH : LEVEL_DURATION_LEVEL_LOW;
+    level_duration.duration = duration;
+    return level_duration;
+}
+
+static inline LevelDuration level_duration_reset() {
+    LevelDuration level_duration;
+    level_duration.level = LEVEL_DURATION_RESET;
+    return level_duration;
+}
+
+static inline bool level_duration_is_reset(LevelDuration level_duration) {
+    return level_duration.level == LEVEL_DURATION_RESET;
+}
+
+static inline bool level_duration_get_level(LevelDuration level_duration) {
+    return level_duration.level == LEVEL_DURATION_LEVEL_HIGH;
+}
+
+static inline uint32_t level_duration_get_duration(LevelDuration level_duration) {
+    return level_duration.duration;
+}
+
+#else
+
+#define LEVEL_DURATION_RESET 0U
+#define LEVEL_DURATION_RESERVED 0x800000U
+
+typedef int32_t LevelDuration;
+
+static inline LevelDuration level_duration(bool level, uint32_t duration) {
+    return level ? duration : -(int32_t)duration;
+}
+
+static inline LevelDuration level_duration_reset() {
+    return LEVEL_DURATION_RESET;
+}
+
+static inline bool level_duration_is_reset(LevelDuration level_duration) {
+    return (level_duration == LEVEL_DURATION_RESET);
+}
+
+static inline bool level_duration_get_level(LevelDuration level_duration) {
+    return (level_duration > 0);
+}
+
+static inline uint32_t level_duration_get_duration(LevelDuration level_duration) {
+    return (level_duration >= 0) ? level_duration : -level_duration;
+}
+
+#endif