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

[FL-3093, FL-3087] SubGhz: Fix Raw write, add short duration filter setting (#2300)

* SubGhz: Fix recording RAW files, sometimes could not start at a high level
* SubGhz:  subghz_worker, add short duration filter setting
* SubGhz: capture raw timings in cli. Furi: clear pending interrupts on ISR set/reset
* SubGhz: fix start  duration in furi_hal_subghz_start_async_rx
* [FL-3093] SubGhz: hopping issue in some regions
* [FL-3087] SubGhz: fix delete-ok issue
* SubGhz: remove copypasta from rx_raw cli command

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Skorpionm 2 лет назад
Родитель
Сommit
99253a0e28

+ 0 - 5
applications/main/subghz/scenes/subghz_scene_delete_success.c

@@ -28,13 +28,8 @@ bool subghz_scene_delete_success_on_event(void* context, SceneManagerEvent event
         if(event.event == SubGhzCustomEventSceneDeleteSuccess) {
             if(scene_manager_search_and_switch_to_previous_scene(
                    subghz->scene_manager, SubGhzSceneReadRAW)) {
-                scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW);
             } else if(scene_manager_search_and_switch_to_previous_scene(
                           subghz->scene_manager, SubGhzSceneSaved)) {
-                // Commented so that the user doesn't have to press
-                // back twice to get to the main SubGhz menu after
-                // deleting a file.
-                //scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved);
             } else {
                 scene_manager_search_and_switch_to_previous_scene(
                     subghz->scene_manager, SubGhzSceneStart);

+ 15 - 0
applications/main/subghz/scenes/subghz_scene_receiver_info.c

@@ -129,6 +129,21 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
                        subghz_history_get_raw_data(
                            subghz->txrx->history, subghz->txrx->idx_menu_chosen))) {
                     scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx);
+                    if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
+                        subghz_tx_stop(subghz);
+                    }
+                    if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) {
+                        subghz_begin(
+                            subghz,
+                            subghz_setting_get_preset_data_by_name(
+                                subghz->setting,
+                                furi_string_get_cstr(subghz->txrx->preset->name)));
+                        subghz_rx(subghz, subghz->txrx->preset->frequency);
+                    }
+                    if(subghz->txrx->hopper_state == SubGhzHopperStatePause) {
+                        subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
+                    }
+                    subghz->state_notifications = SubGhzNotificationStateRx;
                 } else {
                     subghz->state_notifications = SubGhzNotificationStateTx;
                 }

+ 82 - 1
applications/main/subghz/subghz_cli.c

@@ -309,6 +309,81 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
     free(instance);
 }
 
+void subghz_cli_command_rx_raw(Cli* cli, FuriString* args, void* context) {
+    UNUSED(context);
+    uint32_t frequency = 433920000;
+
+    if(furi_string_size(args)) {
+        int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency);
+        if(ret != 1) {
+            printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency);
+            cli_print_usage("subghz rx", "<Frequency: in Hz>", furi_string_get_cstr(args));
+            return;
+        }
+        if(!furi_hal_subghz_is_frequency_valid(frequency)) {
+            printf(
+                "Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n",
+                frequency);
+            return;
+        }
+    }
+
+    // Allocate context and buffers
+    SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx));
+    instance->stream =
+        furi_stream_buffer_alloc(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
+    furi_check(instance->stream);
+
+    // Configure radio
+    furi_hal_subghz_reset();
+    furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok270Async);
+    frequency = furi_hal_subghz_set_frequency_and_path(frequency);
+    furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
+
+    furi_hal_power_suppress_charge_enter();
+
+    // Prepare and start RX
+    furi_hal_subghz_start_async_rx(subghz_cli_command_rx_capture_callback, instance);
+
+    // Wait for packets to arrive
+    printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
+    LevelDuration level_duration;
+    size_t counter = 0;
+    while(!cli_cmd_interrupt_received(cli)) {
+        int ret = furi_stream_buffer_receive(
+            instance->stream, &level_duration, sizeof(LevelDuration), 10);
+        if(ret == 0) {
+            continue;
+        }
+        if(ret != sizeof(LevelDuration)) {
+            puts("stream corrupt");
+            break;
+        }
+        if(level_duration_is_reset(level_duration)) {
+            puts(". ");
+        } else {
+            bool level = level_duration_get_level(level_duration);
+            uint32_t duration = level_duration_get_duration(level_duration);
+            printf("%c%lu ", level ? '+' : '-', duration);
+        }
+        furi_thread_stdout_flush();
+        counter++;
+        if(counter > 255) {
+            puts("\r\n");
+            counter = 0;
+        }
+    }
+
+    // Shutdown radio
+    furi_hal_subghz_stop_async_rx();
+    furi_hal_subghz_sleep();
+
+    furi_hal_power_suppress_charge_exit();
+
+    // Cleanup
+    furi_stream_buffer_free(instance->stream);
+    free(instance);
+}
 void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) {
     UNUSED(context);
     FuriString* file_name;
@@ -431,7 +506,8 @@ static void subghz_cli_command_print_usage() {
     printf("\tchat <frequency:in Hz>\t - Chat with other Flippers\r\n");
     printf(
         "\ttx <3 byte Key: in hex> <frequency: in Hz> <te: us> <repeat: count>\t - Transmitting key\r\n");
-    printf("\trx <frequency:in Hz>\t - Reception key\r\n");
+    printf("\trx <frequency:in Hz>\t - Receive\r\n");
+    printf("\trx_raw <frequency:in Hz>\t - Receive RAW\r\n");
     printf("\tdecode_raw <file_name: path_RAW_file>\t - Testing\r\n");
 
     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
@@ -733,6 +809,11 @@ static void subghz_cli_command(Cli* cli, FuriString* args, void* context) {
             break;
         }
 
+        if(furi_string_cmp_str(cmd, "rx_raw") == 0) {
+            subghz_cli_command_rx_raw(cli, args, context);
+            break;
+        }
+
         if(furi_string_cmp_str(cmd, "decode_raw") == 0) {
             subghz_cli_command_decode_raw(cli, args, context);
             break;

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

@@ -1,5 +1,5 @@
 entry,status,name,type,params
-Version,+,13.0,,
+Version,+,13.1,,
 Header,+,applications/services/bt/bt_service/bt.h,,
 Header,+,applications/services/cli/cli.h,,
 Header,+,applications/services/cli/cli_vcp.h,,
@@ -2675,6 +2675,7 @@ Function,+,subghz_worker_free,void,SubGhzWorker*
 Function,+,subghz_worker_is_running,_Bool,SubGhzWorker*
 Function,+,subghz_worker_rx_callback,void,"_Bool, uint32_t, void*"
 Function,+,subghz_worker_set_context,void,"SubGhzWorker*, void*"
+Function,+,subghz_worker_set_filter,void,"SubGhzWorker*, uint16_t"
 Function,+,subghz_worker_set_overrun_callback,void,"SubGhzWorker*, SubGhzWorkerOverrunCallback"
 Function,+,subghz_worker_set_pair_callback,void,"SubGhzWorker*, SubGhzWorkerPairCallback"
 Function,+,subghz_worker_start,void,SubGhzWorker*

+ 17 - 0
firmware/targets/f7/furi_hal/furi_hal_interrupt.c

@@ -74,6 +74,21 @@ __attribute__((always_inline)) static inline void
     NVIC_EnableIRQ(furi_hal_interrupt_irqn[index]);
 }
 
+__attribute__((always_inline)) static inline void
+    furi_hal_interrupt_clear_pending(FuriHalInterruptId index) {
+    NVIC_ClearPendingIRQ(furi_hal_interrupt_irqn[index]);
+}
+
+__attribute__((always_inline)) static inline void
+    furi_hal_interrupt_get_pending(FuriHalInterruptId index) {
+    NVIC_GetPendingIRQ(furi_hal_interrupt_irqn[index]);
+}
+
+__attribute__((always_inline)) static inline void
+    furi_hal_interrupt_set_pending(FuriHalInterruptId index) {
+    NVIC_SetPendingIRQ(furi_hal_interrupt_irqn[index]);
+}
+
 __attribute__((always_inline)) static inline void
     furi_hal_interrupt_disable(FuriHalInterruptId index) {
     NVIC_DisableIRQ(furi_hal_interrupt_irqn[index]);
@@ -123,6 +138,7 @@ void furi_hal_interrupt_set_isr_ex(
         // Pre ISR clear
         furi_assert(furi_hal_interrupt_isr[index].isr != NULL);
         furi_hal_interrupt_disable(index);
+        furi_hal_interrupt_clear_pending(index);
     }
 
     furi_hal_interrupt_isr[index].isr = isr;
@@ -131,6 +147,7 @@ void furi_hal_interrupt_set_isr_ex(
 
     if(isr) {
         // Post ISR set
+        furi_hal_interrupt_clear_pending(index);
         furi_hal_interrupt_enable(index, priority);
     } else {
         // Post ISR clear

+ 8 - 3
firmware/targets/f7/furi_hal/furi_hal_subghz.c

@@ -438,7 +438,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
     TIM_InitStruct.Prescaler = 64 - 1;
     TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
     TIM_InitStruct.Autoreload = 0x7FFFFFFE;
-    TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4;
+    TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4; // Clock division for capture filter
     LL_TIM_Init(TIM2, &TIM_InitStruct);
 
     // Timer: advanced
@@ -455,13 +455,15 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
     LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_INDIRECTTI);
     LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
     LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_FALLING);
-    LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1);
 
     // Timer: channel 2 direct
     LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI);
     LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
     LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING);
-    LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV32_N8);
+    LL_TIM_IC_SetFilter(
+        TIM2,
+        LL_TIM_CHANNEL_CH2,
+        LL_TIM_IC_FILTER_FDIV32_N8); // Capture filter: 1/(64000000/64/4/32*8) = 16us
 
     // ISR setup
     furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_subghz_capture_ISR, NULL);
@@ -481,6 +483,9 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
 
     // Switch to RX
     furi_hal_subghz_rx();
+
+    //Clear the variable after the end of the session
+    furi_hal_subghz_capture_delta_duration = 0;
 }
 
 void furi_hal_subghz_stop_async_rx() {

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

@@ -159,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->last_level = false;
         instance->pause = false;
         init = true;
     } while(0);

+ 18 - 20
lib/subghz/subghz_worker.c

@@ -12,7 +12,6 @@ struct SubGhzWorker {
     volatile bool overrun;
 
     LevelDuration filter_level_duration;
-    bool filter_running;
     uint16_t filter_duration;
 
     SubGhzWorkerOverrunCallback overrun_callback;
@@ -59,24 +58,19 @@ static int32_t subghz_worker_thread_callback(void* context) {
                 bool level = level_duration_get_level(level_duration);
                 uint32_t duration = level_duration_get_duration(level_duration);
 
-                if(instance->filter_running) {
-                    if((duration < instance->filter_duration) ||
-                       (instance->filter_level_duration.level == level)) {
-                        instance->filter_level_duration.duration += duration;
-
-                    } else if(instance->filter_level_duration.level != level) {
-                        if(instance->pair_callback)
-                            instance->pair_callback(
-                                instance->context,
-                                instance->filter_level_duration.level,
-                                instance->filter_level_duration.duration);
-
-                        instance->filter_level_duration.duration = duration;
-                        instance->filter_level_duration.level = level;
-                    }
-                } else {
+                if((duration < instance->filter_duration) ||
+                   (instance->filter_level_duration.level == level)) {
+                    instance->filter_level_duration.duration += duration;
+
+                } else if(instance->filter_level_duration.level != level) {
                     if(instance->pair_callback)
-                        instance->pair_callback(instance->context, level, duration);
+                        instance->pair_callback(
+                            instance->context,
+                            instance->filter_level_duration.level,
+                            instance->filter_level_duration.duration);
+
+                    instance->filter_level_duration.duration = duration;
+                    instance->filter_level_duration.level = level;
                 }
             }
         }
@@ -94,8 +88,7 @@ SubGhzWorker* subghz_worker_alloc() {
     instance->stream =
         furi_stream_buffer_alloc(sizeof(LevelDuration) * 4096, sizeof(LevelDuration));
 
-    //setting filter
-    instance->filter_running = true;
+    //setting default filter in us
     instance->filter_duration = 30;
 
     return instance;
@@ -149,3 +142,8 @@ bool subghz_worker_is_running(SubGhzWorker* instance) {
     furi_assert(instance);
     return instance->running;
 }
+
+void subghz_worker_set_filter(SubGhzWorker* instance, uint16_t timeout) {
+    furi_assert(instance);
+    instance->filter_duration = timeout;
+}

+ 8 - 0
lib/subghz/subghz_worker.h

@@ -67,6 +67,14 @@ void subghz_worker_stop(SubGhzWorker* instance);
  */
 bool subghz_worker_is_running(SubGhzWorker* instance);
 
+/** 
+ * Short duration filter setting.
+ * glues short durations into 1. The default setting is 30 us, if set to 0 the filter will be disabled
+ * @param instance Pointer to a SubGhzWorker instance
+ * @param timeout time in us
+ */
+void subghz_worker_set_filter(SubGhzWorker* instance, uint16_t timeout);
+
 #ifdef __cplusplus
 }
 #endif