Explorar o código

[FL-2927] SubGhz: add RAW Read threshold rssi (#1911)

* SubGhz: add RAW Read threshold rssi
* SubGhz: update indicator RSSI
* SubGhz: fix record file

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Skorpionm %!s(int64=3) %!d(string=hai) anos
pai
achega
5c8df66b7c

+ 44 - 6
applications/main/subghz/scenes/subghz_scene_read_raw.c

@@ -6,6 +6,7 @@
 
 #define RAW_FILE_NAME "Raw_signal_"
 #define TAG "SubGhzSceneReadRAW"
+#define RAW_THRESHOLD_RSSI_LOW_COUNT 10
 
 bool subghz_scene_read_raw_update_filename(SubGhz* subghz) {
     bool ret = false;
@@ -72,24 +73,33 @@ void subghz_scene_read_raw_on_enter(void* context) {
 
     switch(subghz->txrx->rx_key_state) {
     case SubGhzRxKeyStateBack:
-        subghz_read_raw_set_status(subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, "");
+        subghz_read_raw_set_status(
+            subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, "", subghz->txrx->raw_threshold_rssi);
         break;
     case SubGhzRxKeyStateRAWLoad:
         path_extract_filename(subghz->file_path, file_name, true);
         subghz_read_raw_set_status(
             subghz->subghz_read_raw,
             SubGhzReadRAWStatusLoadKeyTX,
-            furi_string_get_cstr(file_name));
+            furi_string_get_cstr(file_name),
+            subghz->txrx->raw_threshold_rssi);
         subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
         break;
     case SubGhzRxKeyStateRAWSave:
         path_extract_filename(subghz->file_path, file_name, true);
         subghz_read_raw_set_status(
-            subghz->subghz_read_raw, SubGhzReadRAWStatusSaveKey, furi_string_get_cstr(file_name));
+            subghz->subghz_read_raw,
+            SubGhzReadRAWStatusSaveKey,
+            furi_string_get_cstr(file_name),
+            subghz->txrx->raw_threshold_rssi);
         subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
         break;
     default:
-        subghz_read_raw_set_status(subghz->subghz_read_raw, SubGhzReadRAWStatusStart, "");
+        subghz_read_raw_set_status(
+            subghz->subghz_read_raw,
+            SubGhzReadRAWStatusStart,
+            "",
+            subghz->txrx->raw_threshold_rssi);
         subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
         break;
     }
@@ -273,7 +283,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
             if(subghz->txrx->rx_key_state != SubGhzRxKeyStateIDLE) {
                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
             } else {
-                //subghz_get_preset_name(subghz, subghz->error_str);
+                subghz->txrx->raw_threshold_rssi_low_count = RAW_THRESHOLD_RSSI_LOW_COUNT;
                 if(subghz_protocol_raw_save_to_file_init(
                        (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result,
                        RAW_FILE_NAME,
@@ -319,7 +329,35 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
                 subghz->subghz_read_raw,
                 subghz_protocol_raw_get_sample_write(
                     (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result));
-            subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, furi_hal_subghz_get_rssi());
+
+            float rssi = furi_hal_subghz_get_rssi();
+
+            if(subghz->txrx->raw_threshold_rssi == SUBGHZ_RAW_TRESHOLD_MIN) {
+                subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, true);
+                subghz_protocol_raw_save_to_file_pause(
+                    (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, false);
+            } else {
+                if(rssi < subghz->txrx->raw_threshold_rssi) {
+                    subghz->txrx->raw_threshold_rssi_low_count++;
+                    if(subghz->txrx->raw_threshold_rssi_low_count > RAW_THRESHOLD_RSSI_LOW_COUNT) {
+                        subghz->txrx->raw_threshold_rssi_low_count = RAW_THRESHOLD_RSSI_LOW_COUNT;
+                    }
+                    subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, false);
+                } else {
+                    subghz->txrx->raw_threshold_rssi_low_count = 0;
+                }
+
+                if(subghz->txrx->raw_threshold_rssi_low_count == RAW_THRESHOLD_RSSI_LOW_COUNT) {
+                    subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, false);
+                    subghz_protocol_raw_save_to_file_pause(
+                        (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, true);
+                } else {
+                    subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, true);
+                    subghz_protocol_raw_save_to_file_pause(
+                        (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, false);
+                }
+            }
+
             break;
         case SubGhzNotificationStateTx:
             notification_message(subghz->notifications, &sequence_blink_magenta_10);

+ 52 - 0
applications/main/subghz/scenes/subghz_scene_receiver_config.c

@@ -1,10 +1,41 @@
 #include "../subghz_i.h"
+#include <lib/toolbox/value_index.h>
 
 enum SubGhzSettingIndex {
     SubGhzSettingIndexFrequency,
     SubGhzSettingIndexHopping,
     SubGhzSettingIndexModulation,
     SubGhzSettingIndexLock,
+    SubGhzSettingIndexRAWThesholdRSSI,
+};
+
+#define RAW_THRESHOLD_RSSI_COUNT 11
+const char* const raw_theshold_rssi_text[RAW_THRESHOLD_RSSI_COUNT] = {
+    "-----",
+    "-85.0",
+    "-80.0",
+    "-75.0",
+    "-70.0",
+    "-65.0",
+    "-60.0",
+    "-55.0",
+    "-50.0",
+    "-45.0",
+    "-40.0",
+
+};
+const float raw_theshold_rssi_value[RAW_THRESHOLD_RSSI_COUNT] = {
+    -90.0f,
+    -85.0f,
+    -80.0f,
+    -75.0f,
+    -70.0f,
+    -65.0f,
+    -60.0f,
+    -55.0f,
+    -50.0f,
+    -45.0f,
+    -40.0f,
 };
 
 #define HOPPING_COUNT 2
@@ -136,6 +167,14 @@ static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item)
     subghz->txrx->hopper_state = hopping_value[index];
 }
 
+static void subghz_scene_receiver_config_set_raw_threshold_rssi(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, raw_theshold_rssi_text[index]);
+    subghz->txrx->raw_threshold_rssi = raw_theshold_rssi_value[index];
+}
+
 static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) {
     furi_assert(context);
     SubGhz* subghz = context;
@@ -204,6 +243,19 @@ void subghz_scene_receiver_config_on_enter(void* context) {
             subghz_scene_receiver_config_var_list_enter_callback,
             subghz);
     }
+    if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
+       SubGhzCustomEventManagerSet) {
+        item = variable_item_list_add(
+            subghz->variable_item_list,
+            "RSSI Threshold:",
+            RAW_THRESHOLD_RSSI_COUNT,
+            subghz_scene_receiver_config_set_raw_threshold_rssi,
+            subghz);
+        value_index = value_index_float(
+            subghz->txrx->raw_threshold_rssi, raw_theshold_rssi_value, RAW_THRESHOLD_RSSI_COUNT);
+        variable_item_set_current_value_index(item, value_index);
+        variable_item_set_current_value_text(item, raw_theshold_rssi_text[value_index]);
+    }
     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
 }
 

+ 1 - 0
applications/main/subghz/subghz.c

@@ -178,6 +178,7 @@ SubGhz* subghz_alloc() {
     subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
     subghz->txrx->hopper_state = SubGhzHopperStateOFF;
     subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
+    subghz->txrx->raw_threshold_rssi = SUBGHZ_RAW_TRESHOLD_MIN;
     subghz->txrx->history = subghz_history_alloc();
     subghz->txrx->worker = subghz_worker_alloc();
     subghz->txrx->fff_data = flipper_format_string_alloc();

+ 3 - 0
applications/main/subghz/subghz_i.h

@@ -54,6 +54,9 @@ struct SubGhzTxRx {
     uint8_t hopper_timeout;
     uint8_t hopper_idx_frequency;
     SubGhzRxKeyState rx_key_state;
+
+    float raw_threshold_rssi;
+    uint8_t raw_threshold_rssi_low_count;
 };
 
 typedef struct SubGhzTxRx SubGhzTxRx;

+ 68 - 9
applications/main/subghz/views/subghz_read_raw.c

@@ -23,10 +23,12 @@ typedef struct {
     FuriString* sample_write;
     FuriString* file_name;
     uint8_t* rssi_history;
+    uint8_t rssi_curret;
     bool rssi_history_end;
     uint8_t ind_write;
     uint8_t ind_sin;
     SubGhzReadRAWStatus status;
+    float raw_threshold_rssi;
 } SubGhzReadRAWModel;
 
 void subghz_read_raw_set_callback(
@@ -54,21 +56,27 @@ void subghz_read_raw_add_data_statusbar(
         true);
 }
 
-void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi) {
+void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi, bool trace) {
     furi_assert(instance);
     uint8_t u_rssi = 0;
 
-    if(rssi < -90) {
+    if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) {
         u_rssi = 0;
     } else {
-        u_rssi = (uint8_t)((rssi + 90) / 2.7);
+        u_rssi = (uint8_t)((rssi - SUBGHZ_RAW_TRESHOLD_MIN) / 2.7);
     }
 
     with_view_model(
         instance->view,
         SubGhzReadRAWModel * model,
         {
-            model->rssi_history[model->ind_write++] = u_rssi;
+            model->rssi_curret = u_rssi;
+            if(trace) {
+                model->rssi_history[model->ind_write++] = u_rssi;
+            } else {
+                model->rssi_history[model->ind_write] = u_rssi;
+            }
+
             if(model->ind_write > SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE) {
                 model->rssi_history_end = true;
                 model->ind_write = 0;
@@ -187,24 +195,53 @@ void subghz_read_raw_draw_scale(Canvas* canvas, SubGhzReadRAWModel* model) {
 void subghz_read_raw_draw_rssi(Canvas* canvas, SubGhzReadRAWModel* model) {
     int ind = 0;
     int base = 0;
+    uint8_t width = 2;
     if(model->rssi_history_end == false) {
         for(int i = model->ind_write; i >= 0; i--) {
             canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[i]);
         }
+        canvas_draw_line(
+            canvas, model->ind_write + 1, 47, model->ind_write + 1, 47 - model->rssi_curret);
         if(model->ind_write > 3) {
-            canvas_draw_line(canvas, model->ind_write, 47, model->ind_write, 13);
+            canvas_draw_line(
+                canvas, model->ind_write - 1, 47, model->ind_write - 1, 47 - model->rssi_curret);
+
+            for(uint8_t i = 13; i < 47; i += width * 2) {
+                canvas_draw_line(canvas, model->ind_write, i, model->ind_write, i + width);
+            }
             canvas_draw_line(canvas, model->ind_write - 2, 12, model->ind_write + 2, 12);
             canvas_draw_line(canvas, model->ind_write - 1, 13, model->ind_write + 1, 13);
         }
     } else {
+        int i = 0;
         base = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - model->ind_write;
-        for(int i = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE; i >= 0; i--) {
+        for(i = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE; i > 0; i--) {
             ind = i - base;
             if(ind < 0) ind += SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE;
             canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[ind]);
         }
+
         canvas_draw_line(
-            canvas, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, 47, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, 13);
+            canvas,
+            SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 1,
+            47,
+            SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 1,
+            47 - model->rssi_curret);
+        canvas_draw_line(
+            canvas,
+            SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE + 1,
+            47,
+            SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE + 1,
+            47 - model->rssi_curret);
+
+        for(uint8_t i = 13; i < 47; i += width * 2) {
+            canvas_draw_line(
+                canvas,
+                SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE,
+                i,
+                SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE,
+                i + width);
+        }
         canvas_draw_line(
             canvas,
             SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 2,
@@ -220,6 +257,24 @@ void subghz_read_raw_draw_rssi(Canvas* canvas, SubGhzReadRAWModel* model) {
     }
 }
 
+void subghz_read_raw_draw_threshold_rssi(Canvas* canvas, SubGhzReadRAWModel* model) {
+    uint8_t x = 118;
+    uint8_t y = 48;
+
+    if(model->raw_threshold_rssi > SUBGHZ_RAW_TRESHOLD_MIN) {
+        uint8_t x = 118;
+        y -= (uint8_t)((model->raw_threshold_rssi - SUBGHZ_RAW_TRESHOLD_MIN) / 2.7);
+
+        uint8_t width = 3;
+        for(uint8_t i = 0; i < x; i += width * 2) {
+            canvas_draw_line(canvas, i, y, i + width, y);
+        }
+    }
+    canvas_draw_line(canvas, x, y - 2, x, y + 2);
+    canvas_draw_line(canvas, x - 1, y - 1, x - 1, y + 1);
+    canvas_draw_dot(canvas, x - 2, y);
+}
+
 void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) {
     uint8_t graphics_mode = 1;
     canvas_set_color(canvas, ColorBlack);
@@ -278,8 +333,9 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) {
     } else {
         subghz_read_raw_draw_rssi(canvas, model);
         subghz_read_raw_draw_scale(canvas, model);
+        subghz_read_raw_draw_threshold_rssi(canvas, model);
         canvas_set_font_direction(canvas, CanvasDirectionBottomToTop);
-        canvas_draw_str(canvas, 126, 40, "RSSI");
+        canvas_draw_str(canvas, 128, 40, "RSSI");
         canvas_set_font_direction(canvas, CanvasDirectionLeftToRight);
     }
 }
@@ -433,7 +489,8 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
 void subghz_read_raw_set_status(
     SubGhzReadRAW* instance,
     SubGhzReadRAWStatus status,
-    const char* file_name) {
+    const char* file_name,
+    float raw_threshold_rssi) {
     furi_assert(instance);
 
     switch(status) {
@@ -447,6 +504,7 @@ void subghz_read_raw_set_status(
                 model->ind_write = 0;
                 furi_string_reset(model->file_name);
                 furi_string_set(model->sample_write, "0 spl.");
+                model->raw_threshold_rssi = raw_threshold_rssi;
             },
             true);
         break;
@@ -536,6 +594,7 @@ SubGhzReadRAW* subghz_read_raw_alloc() {
             model->sample_write = furi_string_alloc();
             model->file_name = furi_string_alloc();
             model->rssi_history = malloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t));
+            model->raw_threshold_rssi = -127.0f;
         },
         true);
 

+ 5 - 2
applications/main/subghz/views/subghz_read_raw.h

@@ -3,6 +3,8 @@
 #include <gui/view.h>
 #include "../helpers/subghz_custom_event.h"
 
+#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f
+
 typedef struct SubGhzReadRAW SubGhzReadRAW;
 
 typedef void (*SubGhzReadRAWCallback)(SubGhzCustomEvent event, void* context);
@@ -40,11 +42,12 @@ void subghz_read_raw_stop_send(SubGhzReadRAW* instance);
 
 void subghz_read_raw_update_sin(SubGhzReadRAW* instance);
 
-void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi);
+void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi, bool trace);
 
 void subghz_read_raw_set_status(
     SubGhzReadRAW* instance,
     SubGhzReadRAWStatus status,
-    const char* file_name);
+    const char* file_name,
+    float raw_threshold_rssi);
 
 View* subghz_read_raw_get_view(SubGhzReadRAW* subghz_static);

+ 1 - 0
firmware/targets/f7/api_symbols.csv

@@ -2310,6 +2310,7 @@ Function,+,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhz
 Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*"
 Function,+,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW*
 Function,+,subghz_protocol_raw_save_to_file_init,_Bool,"SubGhzProtocolDecoderRAW*, const char*, SubGhzRadioPreset*"
+Function,+,subghz_protocol_raw_save_to_file_pause,void,"SubGhzProtocolDecoderRAW*, _Bool"
 Function,+,subghz_protocol_raw_save_to_file_stop,void,SubGhzProtocolDecoderRAW*
 Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment*
 Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t"

+ 11 - 1
lib/subghz/protocols/raw.c

@@ -32,6 +32,7 @@ struct SubGhzProtocolDecoderRAW {
     FuriString* file_name;
     size_t sample_write;
     bool last_level;
+    bool pause;
 };
 
 struct SubGhzProtocolEncoderRAW {
@@ -158,6 +159,7 @@ bool subghz_protocol_raw_save_to_file_init(
         instance->upload_raw = malloc(SUBGHZ_DOWNLOAD_MAX_SIZE * sizeof(int32_t));
         instance->file_is_open = RAWFileIsOpenWrite;
         instance->sample_write = 0;
+        instance->pause = false;
         init = true;
     } while(0);
 
@@ -199,6 +201,14 @@ void subghz_protocol_raw_save_to_file_stop(SubGhzProtocolDecoderRAW* instance) {
     instance->file_is_open = RAWFileIsOpenClose;
 }
 
+void subghz_protocol_raw_save_to_file_pause(SubGhzProtocolDecoderRAW* instance, bool pause) {
+    furi_assert(instance);
+
+    if(instance->pause != pause) {
+        instance->pause = pause;
+    }
+}
+
 size_t subghz_protocol_raw_get_sample_write(SubGhzProtocolDecoderRAW* instance) {
     return instance->sample_write + instance->ind_write;
 }
@@ -234,7 +244,7 @@ void subghz_protocol_decoder_raw_feed(void* context, bool level, uint32_t durati
     furi_assert(context);
     SubGhzProtocolDecoderRAW* instance = context;
 
-    if(instance->upload_raw != NULL) {
+    if(!instance->pause && (instance->upload_raw != NULL)) {
         if(duration > subghz_protocol_raw_const.te_short) {
             if(instance->last_level != level) {
                 instance->last_level = (level ? true : false);

+ 7 - 0
lib/subghz/protocols/raw.h

@@ -103,6 +103,13 @@ void subghz_protocol_encoder_raw_free(void* context);
  */
 void subghz_protocol_encoder_raw_stop(void* context);
 
+/**
+ * pause writing to flash.
+ * @param context Pointer to a SubGhzProtocolEncoderRAW instance
+ * @param pause pause writing
+ */
+void subghz_protocol_raw_save_to_file_pause(SubGhzProtocolDecoderRAW* instance, bool pause);
+
 /**
  * Set callback on completion of file transfer.
  * @param instance Pointer to a SubGhzProtocolEncoderRAW instance