diff --git a/applications/main/subghz/scenes/subghz_scene_delete_success.c b/applications/main/subghz/scenes/subghz_scene_delete_success.c index 8a254624..4d9f33e3 100644 --- a/applications/main/subghz/scenes/subghz_scene_delete_success.c +++ b/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); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index c0f90157..4733b0e1 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/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; } diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 536cb535..9271443a 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/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", "", 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 \t - Chat with other Flippers\r\n"); printf( "\ttx <3 byte Key: in hex> \t - Transmitting key\r\n"); - printf("\trx \t - Reception key\r\n"); + printf("\trx \t - Receive\r\n"); + printf("\trx_raw \t - Receive RAW\r\n"); printf("\tdecode_raw \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; diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 6456555d..65ab375e 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/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* diff --git a/firmware/targets/f7/furi_hal/furi_hal_interrupt.c b/firmware/targets/f7/furi_hal/furi_hal_interrupt.c index 1b1132d0..b5639d23 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_interrupt.c +++ b/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 diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index a6d27530..59646461 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/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() { diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index b639c93b..ac3492e7 100644 --- a/lib/subghz/protocols/raw.c +++ b/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); diff --git a/lib/subghz/subghz_worker.c b/lib/subghz/subghz_worker.c index 35e39988..50b5aba5 100644 --- a/lib/subghz/subghz_worker.c +++ b/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; + 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 { + } 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; +} \ No newline at end of file diff --git a/lib/subghz/subghz_worker.h b/lib/subghz/subghz_worker.h index f85b1fdc..657278f5 100644 --- a/lib/subghz/subghz_worker.h +++ b/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