Преглед изворни кода

SubGhz: frequency hopping mode (#671)

* SubGhz: fix assert on worker double stop.
* SubGhz: add hopping mode (315.00, 433.92, 868.00)
* SubGhz: add support for new alarms on the keelog protocol
* SubGhz: update te in princeton protocol
* SubGhz: move static to tests, rename sniffer to hopper/auto, remove delay from timer thread, optimize locking strategy.

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Skorpionm пре 4 година
родитељ
комит
663dbbfe9f

+ 1 - 1
applications/subghz/scenes/subghz_scene_config.h

@@ -5,8 +5,8 @@ ADD_SCENE(subghz, save_name, SaveName)
 ADD_SCENE(subghz, save_success, SaveSuccess)
 ADD_SCENE(subghz, saved, Saved)
 ADD_SCENE(subghz, transmitter, Transmitter)
-ADD_SCENE(subghz, static, Static)
 ADD_SCENE(subghz, test, Test)
+ADD_SCENE(subghz, test_static, TestStatic)
 ADD_SCENE(subghz, test_carrier, TestCarrier)
 ADD_SCENE(subghz, test_packet, TestPacket)
 ADD_SCENE(subghz, set_type, SetType)

+ 0 - 11
applications/subghz/scenes/subghz_scene_start.c

@@ -4,7 +4,6 @@ enum SubmenuIndex {
     SubmenuIndexAnalyze,
     SubmenuIndexRead,
     SubmenuIndexSaved,
-    SubmenuIndexStatic,
     SubmenuIndexTest,
     SubmenuIndexAddManualy,
 };
@@ -35,8 +34,6 @@ const void subghz_scene_start_on_enter(void* context) {
         SubmenuIndexAddManualy,
         subghz_scene_start_submenu_callback,
         subghz);
-    submenu_add_item(
-        subghz->submenu, "Static", SubmenuIndexStatic, subghz_scene_start_submenu_callback, subghz);
     submenu_add_item(
         subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz);
 
@@ -56,9 +53,6 @@ const bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneAnalyze);
             return true;
         } else if(event.event == SubmenuIndexRead) {
-            // scene_manager_set_scene_state(
-            //     subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead);
-            // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneRead);
             scene_manager_set_scene_state(
                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
@@ -73,11 +67,6 @@ const bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAddManualy);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetType);
             return true;
-        } else if(event.event == SubmenuIndexStatic) {
-            scene_manager_set_scene_state(
-                subghz->scene_manager, SubGhzSceneStart, SubmenuIndexStatic);
-            scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStatic);
-            return true;
         } else if(event.event == SubmenuIndexTest) {
             scene_manager_set_scene_state(
                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest);

+ 8 - 0
applications/subghz/scenes/subghz_scene_test.c

@@ -3,6 +3,7 @@
 enum SubmenuIndex {
     SubmenuIndexCarrier,
     SubmenuIndexPacket,
+    SubmenuIndexStatic,
 };
 
 void subghz_scene_test_submenu_callback(void* context, uint32_t index) {
@@ -21,6 +22,8 @@ const void subghz_scene_test_on_enter(void* context) {
         subghz);
     submenu_add_item(
         subghz->submenu, "Packet", SubmenuIndexPacket, subghz_scene_test_submenu_callback, subghz);
+    submenu_add_item(
+        subghz->submenu, "Static", SubmenuIndexStatic, subghz_scene_test_submenu_callback, subghz);
 
     submenu_set_selected_item(
         subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneTest));
@@ -42,6 +45,11 @@ const bool subghz_scene_test_on_event(void* context, SceneManagerEvent event) {
                 subghz->scene_manager, SubGhzSceneTest, SubmenuIndexPacket);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestPacket);
             return true;
+        } else if(event.event == SubmenuIndexStatic) {
+            scene_manager_set_scene_state(
+                subghz->scene_manager, SubGhzSceneTest, SubmenuIndexStatic);
+            scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestStatic);
+            return true;
         }
     }
     return false;

+ 3 - 3
applications/subghz/scenes/subghz_scene_static.c → applications/subghz/scenes/subghz_scene_test_static.c

@@ -1,15 +1,15 @@
 #include "../subghz_i.h"
 
-const void subghz_scene_static_on_enter(void* context) {
+const void subghz_scene_test_static_on_enter(void* context) {
     SubGhz* subghz = context;
     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewStatic);
 }
 
-const bool subghz_scene_static_on_event(void* context, SceneManagerEvent event) {
+const bool subghz_scene_test_static_on_event(void* context, SceneManagerEvent event) {
     // SubGhz* subghz = context;
     return false;
 }
 
-const void subghz_scene_static_on_exit(void* context) {
+const void subghz_scene_test_static_on_exit(void* context) {
     // SubGhz* subghz = context;
 }

+ 5 - 3
applications/subghz/subghz.c

@@ -121,9 +121,11 @@ SubGhz* subghz_alloc() {
         subghz_test_packet_get_view(subghz->subghz_test_packet));
 
     // Static send
-    subghz->subghz_static = subghz_static_alloc();
+    subghz->subghz_test_static = subghz_test_static_alloc();
     view_dispatcher_add_view(
-        subghz->view_dispatcher, SubGhzViewStatic, subghz_static_get_view(subghz->subghz_static));
+        subghz->view_dispatcher,
+        SubGhzViewStatic,
+        subghz_test_static_get_view(subghz->subghz_test_static));
 
     //init Worker & Protocol
     subghz->worker = subghz_worker_alloc();
@@ -155,7 +157,7 @@ void subghz_free(SubGhz* subghz) {
 
     // Static
     view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewStatic);
-    subghz_static_free(subghz->subghz_static);
+    subghz_test_static_free(subghz->subghz_test_static);
 
     // Analyze
     view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewAnalyze);

+ 2 - 2
applications/subghz/subghz_i.h

@@ -4,8 +4,8 @@
 #include "views/subghz_analyze.h"
 #include "views/subghz_receiver.h"
 #include "views/subghz_transmitter.h"
-#include "views/subghz_static.h"
 
+#include "views/subghz_test_static.h"
 #include "views/subghz_test_carrier.h"
 #include "views/subghz_test_packet.h"
 
@@ -62,8 +62,8 @@ struct SubGhz {
     SubghzAnalyze* subghz_analyze;
     SubghzReceiver* subghz_receiver;
     SubghzTransmitter* subghz_transmitter;
-    SubghzStatic* subghz_static;
 
+    SubghzTestStatic* subghz_test_static;
     SubghzTestCarrier* subghz_test_carrier;
     SubghzTestPacket* subghz_test_packet;
 };

+ 99 - 12
applications/subghz/views/subghz_receiver.c

@@ -14,6 +14,16 @@
 #define MAX_LEN_PX 100
 #define MENU_ITEMS 4
 
+#define COUNT_FREQUNCY_SCANER 3
+const uint32_t subghz_frequencies_scanner[] = {
+    /* 300 - 348 */
+    315000000,
+    /* 387 - 464 */
+    433920000, /* LPD433 mid */
+    /* 779 - 928 */
+    868350000,
+};
+
 typedef enum {
     ReceiverSceneStart,
     ReceiverSceneMain,
@@ -21,6 +31,12 @@ typedef enum {
     ReceiverSceneInfo,
 } SubghzReceiverScene;
 
+typedef enum {
+    SubGhzHopperStateOFF,
+    SubGhzHopperStatePause,
+    SubGhzHopperStateRunnig,
+} SubGhzHopperState;
+
 static const Icon* ReceiverItemIcons[] = {
     [TYPE_PROTOCOL_UNKNOWN] = &I_quest_7x8,
     [TYPE_PROTOCOL_STATIC] = &I_unlock_7x8,
@@ -33,6 +49,8 @@ struct SubghzReceiver {
     void* context;
     SubGhzWorker* worker;
     SubGhzProtocol* protocol;
+    osTimerId timer;
+    SubGhzHopperState hopper_state;
 };
 
 typedef struct {
@@ -188,13 +206,18 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
         break;
 
     case ReceiverSceneConfig:
-        snprintf(
-            buffer,
-            sizeof(buffer),
-            "Frequency:  < %03ld.%03ldMHz >",
-            model->real_frequency / 1000000 % 1000,
-            model->real_frequency / 1000 % 1000);
-        canvas_draw_str(canvas, 0, 8, buffer);
+        if(model->frequency < subghz_frequencies_count) {
+            snprintf(
+                buffer,
+                sizeof(buffer),
+                "Frequency:  < %03ld.%03ldMHz >",
+                model->real_frequency / 1000000 % 1000,
+                model->real_frequency / 1000 % 1000);
+            canvas_draw_str(canvas, 0, 8, buffer);
+        } else {
+            canvas_draw_str(canvas, 0, 8, "Frequency: <auto>");
+        }
+
         elements_button_center(canvas, "Save");
         break;
 
@@ -255,6 +278,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
                     return true;
                 });
         } else if(event->key == InputKeyLeft) {
+            subghz_receiver->hopper_state = SubGhzHopperStatePause;
             with_view_model(
                 subghz_receiver->view, (SubghzReceiverModel * model) {
                     model->scene = ReceiverSceneConfig;
@@ -295,6 +319,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
                     subghz_rx_end(subghz_receiver->worker);
                     model->real_frequency =
                         subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]);
+                    subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
                     model->scene = ReceiverSceneMain;
                     return true;
                 });
@@ -303,6 +328,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
             subghz_receiver->callback(SubghzReceverEventSave, subghz_receiver->context);
             return false;
         } else if(can_be_saved && event->key == InputKeyOk && event->type == InputTypePress) {
+            subghz_receiver->hopper_state = SubGhzHopperStatePause;
             subghz_rx_end(subghz_receiver->worker);
             subghz_receiver->callback(SubghzReceverEventSendStart, subghz_receiver->context);
             return true;
@@ -318,6 +344,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
                 subghz_receiver->view, (SubghzReceiverModel * model) {
                     model->frequency = model->temp_frequency;
                     model->real_frequency = subghz_frequencies[model->frequency];
+                    subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
                     if(subghz_history_get_item(model->history) == 0) {
                         model->scene = ReceiverSceneStart;
                     } else {
@@ -329,9 +356,16 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
         } else if(event->key == InputKeyOk) {
             with_view_model(
                 subghz_receiver->view, (SubghzReceiverModel * model) {
-                    subghz_rx_end(subghz_receiver->worker);
-                    model->real_frequency =
-                        subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]);
+                    if(model->frequency < subghz_frequencies_count) {
+                        subghz_rx_end(subghz_receiver->worker);
+                        model->real_frequency = subghz_rx(
+                            subghz_receiver->worker, subghz_frequencies[model->frequency]);
+                        subghz_receiver->hopper_state = SubGhzHopperStateOFF;
+                    } else {
+                        osTimerStart(subghz_receiver->timer, 1024 / 10);
+                        subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
+                    }
+
                     if(subghz_history_get_item(model->history) == 0) {
                         model->scene = ReceiverSceneStart;
                     } else {
@@ -349,7 +383,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
                         if(model->frequency > 0) model->frequency--;
                         model_updated = true;
                     } else if(event->key == InputKeyRight) {
-                        if(model->frequency < subghz_frequencies_count - 1) model->frequency++;
+                        if(model->frequency < subghz_frequencies_count) model->frequency++;
                         model_updated = true;
                     }
                     if(model_updated) {
@@ -364,6 +398,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
         if(event->key == InputKeyBack) {
             return false;
         } else if(event->key == InputKeyLeft) {
+            subghz_receiver->hopper_state = SubGhzHopperStatePause;
             with_view_model(
                 subghz_receiver->view, (SubghzReceiverModel * model) {
                     model->temp_frequency = model->frequency;
@@ -416,6 +451,52 @@ void subghz_receiver_protocol_callback(SubGhzProtocolCommon* parser, void* conte
     subghz_receiver_update_offset(subghz_receiver);
 }
 
+static void subghz_receiver_timer_callback(void* context) {
+    furi_assert(context);
+    SubghzReceiver* subghz_receiver = context;
+
+    switch(subghz_receiver->hopper_state) {
+    case SubGhzHopperStateOFF:
+        return;
+        break;
+    case SubGhzHopperStatePause:
+        osTimerStart(subghz_receiver->timer, 1024 / 10);
+        return;
+        break;
+    default:
+        break;
+    }
+    float rssi = -127.0f;
+    with_view_model(
+        subghz_receiver->view, (SubghzReceiverModel * model) {
+            // See RSSI Calculation timings in CC1101 17.3 RSSI
+            rssi = furi_hal_subghz_get_rssi();
+
+            // Stay if RSSI is high enough
+            if(rssi > -90.0f) {
+                osTimerStart(subghz_receiver->timer, 1024 / 4);
+                return false;
+            } else {
+                osTimerStart(subghz_receiver->timer, 1024 / 10);
+            }
+
+            // Select next frequency
+            if(model->frequency < COUNT_FREQUNCY_SCANER - 1) {
+                model->frequency++;
+            } else {
+                model->frequency = 0;
+            }
+
+            // Restart radio
+            subghz_rx_end(subghz_receiver->worker);
+            subghz_protocol_reset(subghz_receiver->protocol);
+            model->real_frequency =
+                subghz_rx(subghz_receiver->worker, subghz_frequencies_scanner[model->frequency]);
+
+            return true;
+        });
+}
+
 void subghz_receiver_enter(void* context) {
     furi_assert(context);
     SubghzReceiver* subghz_receiver = context;
@@ -441,6 +522,7 @@ void subghz_receiver_enter(void* context) {
 void subghz_receiver_exit(void* context) {
     furi_assert(context);
     SubghzReceiver* subghz_receiver = context;
+    osTimerStop(subghz_receiver->timer);
     with_view_model(
         subghz_receiver->view, (SubghzReceiverModel * model) {
             string_clean(model->text);
@@ -469,6 +551,10 @@ SubghzReceiver* subghz_receiver_alloc() {
             model->history = subghz_history_alloc();
             return true;
         });
+
+    subghz_receiver->timer =
+        osTimerNew(subghz_receiver_timer_callback, osTimerOnce, subghz_receiver, NULL);
+    subghz_receiver->hopper_state = SubGhzHopperStateOFF;
     return subghz_receiver;
 }
 
@@ -481,6 +567,7 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver) {
             subghz_history_free(model->history);
             return false;
         });
+    osTimerDelete(subghz_receiver->timer);
     view_free(subghz_receiver->view);
     free(subghz_receiver);
 }
@@ -529,4 +616,4 @@ void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, st
         "Preset: %d\n",
         (int)frequency,
         (int)preset);
-}
+}

+ 5 - 0
applications/subghz/views/subghz_receiver.h

@@ -36,8 +36,13 @@ void subghz_receiver_set_protocol(
     SubghzReceiver* subghz_receiver,
     SubGhzProtocolCommon* protocol_result,
     SubGhzProtocol* protocol);
+
 SubGhzProtocolCommon* subghz_receiver_get_protocol(SubghzReceiver* subghz_receiver);
+
 void subghz_receiver_set_worker(SubghzReceiver* subghz_receiver, SubGhzWorker* worker);
+
 uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver);
+
 FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver);
+
 void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output);

+ 0 - 11
applications/subghz/views/subghz_static.h

@@ -1,11 +0,0 @@
-#pragma once
-
-#include <gui/view.h>
-
-typedef struct SubghzStatic SubghzStatic;
-
-SubghzStatic* subghz_static_alloc();
-
-void subghz_static_free(SubghzStatic* subghz_static);
-
-View* subghz_static_get_view(SubghzStatic* subghz_static);

+ 36 - 41
applications/subghz/views/subghz_static.c → applications/subghz/views/subghz_test_static.c

@@ -1,4 +1,4 @@
-#include "subghz_static.h"
+#include "subghz_test_static.h"
 #include "../subghz_i.h"
 
 #include <math.h>
@@ -8,30 +8,30 @@
 #include <notification/notification-messages.h>
 #include <lib/subghz/protocols/subghz_protocol_princeton.h>
 
-static const uint32_t subghz_static_keys[] = {
+static const uint32_t subghz_test_static_keys[] = {
     0x0074BADE,
     0x0074BADD,
     0x0074BADB,
     0x00E34A4E,
 };
 
-struct SubghzStatic {
+struct SubghzTestStatic {
     View* view;
     SubGhzEncoderPrinceton* encoder;
 };
 
 typedef enum {
-    SubghzStaticStatusRx,
-    SubghzStaticStatusTx,
-} SubghzStaticStatus;
+    SubghzTestStaticStatusRx,
+    SubghzTestStaticStatusTx,
+} SubghzTestStaticStatus;
 
 typedef struct {
     uint8_t frequency;
     uint32_t real_frequency;
     uint8_t button;
-} SubghzStaticModel;
+} SubghzTestStaticModel;
 
-void subghz_static_draw(Canvas* canvas, SubghzStaticModel* model) {
+void subghz_test_static_draw(Canvas* canvas, SubghzTestStaticModel* model) {
     char buffer[64];
 
     canvas_set_color(canvas, ColorBlack);
@@ -52,24 +52,21 @@ void subghz_static_draw(Canvas* canvas, SubghzStaticModel* model) {
     canvas_draw_str(canvas, 0, 31, buffer);
 }
 
-bool subghz_static_input(InputEvent* event, void* context) {
+bool subghz_test_static_input(InputEvent* event, void* context) {
     furi_assert(context);
-    SubghzStatic* instance = context;
+    SubghzTestStatic* instance = context;
 
     if(event->key == InputKeyBack) {
         return false;
     }
 
     with_view_model(
-        instance->view, (SubghzStaticModel * model) {
-            bool reconfigure = false;
+        instance->view, (SubghzTestStaticModel * model) {
             if(event->type == InputTypeShort) {
                 if(event->key == InputKeyLeft) {
                     if(model->frequency > 0) model->frequency--;
-                    reconfigure = true;
                 } else if(event->key == InputKeyRight) {
                     if(model->frequency < subghz_frequencies_count - 1) model->frequency++;
-                    reconfigure = true;
                 } else if(event->key == InputKeyDown) {
                     if(model->button > 0) model->button--;
                 } else if(event->key == InputKeyUp) {
@@ -77,28 +74,29 @@ bool subghz_static_input(InputEvent* event, void* context) {
                 }
             }
 
-            if(reconfigure) {
-                furi_hal_subghz_idle();
-                model->real_frequency =
-                    furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
-                furi_hal_subghz_tx();
-            }
+            model->real_frequency = subghz_frequencies[model->frequency];
 
             if(event->key == InputKeyOk) {
+                NotificationApp* notification = furi_record_open("notification");
                 if(event->type == InputTypePress) {
-                    NotificationApp* notification = furi_record_open("notification");
                     notification_message_block(notification, &sequence_set_red_255);
 
+                    FURI_LOG_I("SubghzTestStatic", "TX Start");
+                    furi_hal_subghz_idle();
+                    furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
+
                     subghz_encoder_princeton_set(
-                        instance->encoder, subghz_static_keys[model->button], 20);
+                        instance->encoder, subghz_test_static_keys[model->button], 10000);
+
                     furi_hal_subghz_start_async_tx(
                         subghz_encoder_princeton_yield, instance->encoder);
-                    while(!furi_hal_subghz_is_async_tx_complete()) osDelay(33);
+                } else if(event->type == InputTypeRelease) {
+                    FURI_LOG_I("SubghzTestStatic", "TX Stop");
                     furi_hal_subghz_stop_async_tx();
 
                     notification_message(notification, &sequence_reset_red);
-                    furi_record_close("notification");
                 }
+                furi_record_close("notification");
             }
 
             return true;
@@ -107,9 +105,9 @@ bool subghz_static_input(InputEvent* event, void* context) {
     return true;
 }
 
-void subghz_static_enter(void* context) {
+void subghz_test_static_enter(void* context) {
     furi_assert(context);
-    SubghzStatic* instance = context;
+    SubghzTestStatic* instance = context;
 
     furi_hal_subghz_reset();
     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
@@ -118,47 +116,44 @@ void subghz_static_enter(void* context) {
     hal_gpio_write(&gpio_cc1101_g0, false);
 
     with_view_model(
-        instance->view, (SubghzStaticModel * model) {
+        instance->view, (SubghzTestStaticModel * model) {
             model->frequency = subghz_frequencies_433_92;
-            model->real_frequency =
-                furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
+            model->real_frequency = subghz_frequencies[model->frequency];
             model->button = 0;
             return true;
         });
-
-    furi_hal_subghz_tx();
 }
 
-void subghz_static_exit(void* context) {
+void subghz_test_static_exit(void* context) {
     furi_assert(context);
     furi_hal_subghz_sleep();
 }
 
-SubghzStatic* subghz_static_alloc() {
-    SubghzStatic* instance = furi_alloc(sizeof(SubghzStatic));
+SubghzTestStatic* subghz_test_static_alloc() {
+    SubghzTestStatic* instance = furi_alloc(sizeof(SubghzTestStatic));
 
     // View allocation and configuration
     instance->view = view_alloc();
-    view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubghzStaticModel));
+    view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubghzTestStaticModel));
     view_set_context(instance->view, instance);
-    view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_static_draw);
-    view_set_input_callback(instance->view, subghz_static_input);
-    view_set_enter_callback(instance->view, subghz_static_enter);
-    view_set_exit_callback(instance->view, subghz_static_exit);
+    view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_test_static_draw);
+    view_set_input_callback(instance->view, subghz_test_static_input);
+    view_set_enter_callback(instance->view, subghz_test_static_enter);
+    view_set_exit_callback(instance->view, subghz_test_static_exit);
 
     instance->encoder = subghz_encoder_princeton_alloc();
 
     return instance;
 }
 
-void subghz_static_free(SubghzStatic* instance) {
+void subghz_test_static_free(SubghzTestStatic* instance) {
     furi_assert(instance);
     subghz_encoder_princeton_free(instance->encoder);
     view_free(instance->view);
     free(instance);
 }
 
-View* subghz_static_get_view(SubghzStatic* instance) {
+View* subghz_test_static_get_view(SubghzTestStatic* instance) {
     furi_assert(instance);
     return instance->view;
 }

+ 11 - 0
applications/subghz/views/subghz_test_static.h

@@ -0,0 +1,11 @@
+#pragma once
+
+#include <gui/view.h>
+
+typedef struct SubghzTestStatic SubghzTestStatic;
+
+SubghzTestStatic* subghz_test_static_alloc();
+
+void subghz_test_static_free(SubghzTestStatic* subghz_static);
+
+View* subghz_test_static_get_view(SubghzTestStatic* subghz_static);

+ 13 - 7
lib/subghz/protocols/subghz_protocol_keeloq.c

@@ -65,7 +65,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
                 //Simple Learning
                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
                 if((decrypt >> 28 == btn) &&
-                   ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
+                   (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
+                    ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
                     instance->manufacture_name = string_get_cstr(manufacture_code->name);
                     instance->common.cnt = decrypt & 0x0000FFFF;
                     return 1;
@@ -78,7 +79,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
                     subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
                 if((decrypt >> 28 == btn) &&
-                   ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
+                   (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
+                    ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
                     instance->manufacture_name = string_get_cstr(manufacture_code->name);
                     instance->common.cnt = decrypt & 0x0000FFFF;
                     return 1;
@@ -88,7 +90,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
                 // Simple Learning
                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
                 if((decrypt >> 28 == btn) &&
-                   ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
+                   (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
+                    ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
                     instance->manufacture_name = string_get_cstr(manufacture_code->name);
                     instance->common.cnt = decrypt & 0x0000FFFF;
                     return 1;
@@ -102,7 +105,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
                 }
                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev);
                 if((decrypt >> 28 == btn) &&
-                   ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
+                   (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
+                    ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
                     instance->manufacture_name = string_get_cstr(manufacture_code->name);
                     instance->common.cnt = decrypt & 0x0000FFFF;
                     return 1;
@@ -114,7 +118,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
                     subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
                 if((decrypt >> 28 == btn) &&
-                   ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
+                   (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
+                    ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
                     instance->manufacture_name = string_get_cstr(manufacture_code->name);
                     instance->common.cnt = decrypt & 0x0000FFFF;
                     return 1;
@@ -129,7 +134,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
                 man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
                 decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
                 if((decrypt >> 28 == btn) &&
-                   ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) {
+                   (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
+                    ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
                     instance->manufacture_name = string_get_cstr(manufacture_code->name);
                     instance->common.cnt = decrypt & 0x0000FFFF;
                     return 1;
@@ -453,4 +459,4 @@ void subghz_decoder_keeloq_to_load_protocol(
     instance->common.code_last_found = data->code_found;
     instance->common.code_last_count_bit = data->code_count_bit;
     subghz_protocol_keeloq_check_remote_controller(instance);
-}
+}

+ 2 - 2
lib/subghz/protocols/subghz_protocol_princeton.c

@@ -5,7 +5,7 @@
  *
  */
 
-#define SUBGHZ_PT_SHORT 450
+#define SUBGHZ_PT_SHORT 400
 #define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3)
 #define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30)
 
@@ -86,7 +86,7 @@ SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc(void) {
     instance->common.code_min_count_bit_for_found = 24;
     instance->common.te_short = SUBGHZ_PT_SHORT; //150;
     instance->common.te_long = SUBGHZ_PT_LONG; //450;
-    instance->common.te_delta = 200; //50;
+    instance->common.te_delta = 250; //50;
     instance->common.type_protocol = TYPE_PROTOCOL_STATIC;
     instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_decoder_princeton_to_str;
     instance->common.to_save_string =