diff --git a/applications/main/subghz/scenes/subghz_scene_ext_module_settings.c b/applications/main/subghz/scenes/subghz_scene_ext_module_settings.c index 3242bafdc..7d7a505cb 100644 --- a/applications/main/subghz/scenes/subghz_scene_ext_module_settings.c +++ b/applications/main/subghz/scenes/subghz_scene_ext_module_settings.c @@ -34,24 +34,6 @@ static void subghz_scene_receiver_config_set_debug_pin(VariableItem* item) { variable_item_set_current_value_text(item, debug_pin_text[index]); - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if(value_index2 == 1) { - furi_hal_subghz_set_async_mirror_pin(&gpio_ext_pa7); - if(furi_hal_subghz.async_mirror_pin != NULL) { - furi_hal_gpio_init( - furi_hal_subghz.async_mirror_pin, - GpioModeOutputPushPull, - GpioPullNo, - GpioSpeedVeryHigh); - } - } else { - if(furi_hal_subghz.async_mirror_pin != NULL) { - furi_hal_gpio_init( - furi_hal_subghz.async_mirror_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - } - furi_hal_subghz_set_async_mirror_pin(NULL); - } - } subghz->txrx->debug_pin_state = index == 1; } @@ -90,13 +72,6 @@ bool subghz_scene_ext_module_settings_on_event(void* context, SceneManagerEvent UNUSED(subghz); UNUSED(event); - return false; -} - -void subghz_scene_ext_module_settings_on_exit(void* context) { - SubGhz* subghz = context; - variable_item_list_reset(subghz->variable_item_list); - // Set selected radio module furi_hal_subghz_set_radio_type(value_index); @@ -107,4 +82,11 @@ void subghz_scene_ext_module_settings_on_exit(void* context) { furi_string_set(subghz->error_str, "Please connect\nexternal radio"); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub); } + + return false; +} + +void subghz_scene_ext_module_settings_on_exit(void* context) { + SubGhz* subghz = context; + variable_item_list_reset(subghz->variable_item_list); } diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index b572a6f43..1fbe662ed 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -597,6 +597,10 @@ void subghz_hopper_update(SubGhz* subghz) { } void subghz_speaker_on(SubGhz* subghz) { + if(subghz->txrx->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_ext_pa7); + } + if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) { if(furi_hal_speaker_acquire(30)) { if(!subghz->txrx->debug_pin_state) { @@ -609,6 +613,9 @@ void subghz_speaker_on(SubGhz* subghz) { } void subghz_speaker_off(SubGhz* subghz) { + if(subghz->txrx->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } if(subghz->txrx->speaker_state != SubGhzSpeakerStateDisable) { if(furi_hal_speaker_is_mine()) { if(!subghz->txrx->debug_pin_state) { @@ -622,6 +629,9 @@ void subghz_speaker_off(SubGhz* subghz) { } void subghz_speaker_mute(SubGhz* subghz) { + if(subghz->txrx->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) { if(furi_hal_speaker_is_mine()) { if(!subghz->txrx->debug_pin_state) { @@ -632,6 +642,9 @@ void subghz_speaker_mute(SubGhz* subghz) { } void subghz_speaker_unmute(SubGhz* subghz) { + if(subghz->txrx->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_ext_pa7); + } if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) { if(furi_hal_speaker_is_mine()) { if(!subghz->txrx->debug_pin_state) { diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index 5a0a9fcbd..f09b919e6 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -226,6 +226,7 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { elements_button_left(canvas, "Config"); //canvas_draw_line(canvas, 46, 51, 125, 51); } else { + canvas_draw_line(canvas, 2, 52, 125, 52); canvas_draw_str(canvas, 3, 62, furi_string_get_cstr(model->progress_str)); } @@ -279,7 +280,9 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { } } - subghz_view_rssi_draw(canvas, model); + if(model->mode == SubGhzViewReceiverModeLive) { + subghz_view_rssi_draw(canvas, model); + } switch(model->bar_show) { case SubGhzViewReceiverBarShowLock: canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8); diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 05afd758a..c2c238a13 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -121,26 +121,37 @@ bool furi_hal_subghz_init_check(void) { // Prepare GD0 for power on self test furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - - // GD0 low - cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW); - uint32_t test_start_time = furi_get_tick(); - while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != false && result) { - if(furi_get_tick() - test_start_time > INIT_TIMEOUT) { - result = false; + if(furi_hal_subghz.radio_type == SubGhzRadioExternal) { + // GD0 low + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW); + uint32_t test_start_time = furi_get_tick(); + while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != false && result) { + if(furi_get_tick() - test_start_time > INIT_TIMEOUT) { + result = false; + } } - } - // GD0 high - cc1101_write_reg( - furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); - test_start_time = furi_get_tick(); - while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != true && result) { - if(furi_get_tick() - test_start_time > INIT_TIMEOUT) { - result = false; + // GD0 high + cc1101_write_reg( + furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); + test_start_time = furi_get_tick(); + while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != true && result) { + if(furi_get_tick() - test_start_time > INIT_TIMEOUT) { + result = false; + } } - } + } else { + // GD0 low + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW); + while(furi_hal_gpio_read(&gpio_cc1101_g0) != false) + ; + // GD0 high + cc1101_write_reg( + furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); + while(furi_hal_gpio_read(&gpio_cc1101_g0) != true) + ; + } // Reset GD0 to floating state cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance); furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); @@ -499,29 +510,60 @@ static bool furi_hal_subghz_stop_debug() { return ret; } +volatile uint32_t furi_hal_subghz_capture_delta_duration = 0; volatile FuriHalSubGhzCaptureCallback furi_hal_subghz_capture_callback = NULL; volatile void* furi_hal_subghz_capture_callback_context = NULL; static void furi_hal_subghz_capture_ISR() { - if(!furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin)) { - if(furi_hal_subghz_capture_callback) { - if(furi_hal_subghz.async_mirror_pin != NULL) - furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false); + if(furi_hal_subghz.radio_type == SubGhzRadioExternal) { + if(!furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin)) { + if(furi_hal_subghz_capture_callback) { + if(furi_hal_subghz.async_mirror_pin != NULL) + furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false); - furi_hal_subghz_capture_callback( - true, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context); + furi_hal_subghz_capture_callback( + true, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context); + } + } else { + if(furi_hal_subghz_capture_callback) { + if(furi_hal_subghz.async_mirror_pin != NULL) + furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true); + + furi_hal_subghz_capture_callback( + false, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context); + } } + //Forced correction for improved accuracy + TIM2->CNT = 9; } else { - if(furi_hal_subghz_capture_callback) { - if(furi_hal_subghz.async_mirror_pin != NULL) - furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true); + // Channel 1 + if(LL_TIM_IsActiveFlag_CC1(TIM2)) { + LL_TIM_ClearFlag_CC1(TIM2); + furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2); + if(furi_hal_subghz_capture_callback) { + if(furi_hal_subghz.async_mirror_pin != NULL) + furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false); - furi_hal_subghz_capture_callback( - false, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context); + furi_hal_subghz_capture_callback( + true, + furi_hal_subghz_capture_delta_duration, + (void*)furi_hal_subghz_capture_callback_context); + } + } + // Channel 2 + if(LL_TIM_IsActiveFlag_CC2(TIM2)) { + LL_TIM_ClearFlag_CC2(TIM2); + if(furi_hal_subghz_capture_callback) { + if(furi_hal_subghz.async_mirror_pin != NULL) + furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true); + + furi_hal_subghz_capture_callback( + false, + LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration, + (void*)furi_hal_subghz_capture_callback_context); + } } } - //Forced correction for improved accuracy - TIM2->CNT = 9; } void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* context) { @@ -531,13 +573,21 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* furi_hal_subghz_capture_callback = callback; furi_hal_subghz_capture_callback_context = context; - furi_hal_gpio_init( - furi_hal_subghz.cc1101_g0_pin, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedVeryHigh); - furi_hal_gpio_add_int_callback( - furi_hal_subghz.cc1101_g0_pin, - furi_hal_subghz_capture_ISR, - furi_hal_subghz_capture_callback); - furi_hal_gpio_enable_int_callback(furi_hal_subghz.cc1101_g0_pin); + if(furi_hal_subghz.radio_type == SubGhzRadioExternal) { + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, + GpioModeInterruptRiseFall, + GpioPullUp, + GpioSpeedVeryHigh); + furi_hal_gpio_add_int_callback( + furi_hal_subghz.cc1101_g0_pin, + furi_hal_subghz_capture_ISR, + furi_hal_subghz_capture_callback); + furi_hal_gpio_enable_int_callback(furi_hal_subghz.cc1101_g0_pin); + } else { + furi_hal_gpio_init_ex( + &gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2); + } // Timer: base LL_TIM_InitTypeDef TIM_InitStruct = {0}; @@ -550,9 +600,38 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* // Timer: advanced LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); LL_TIM_DisableARRPreload(TIM2); + if(furi_hal_subghz.radio_type == SubGhzRadioInternal) { + LL_TIM_SetTriggerInput(TIM2, LL_TIM_TS_TI2FP2); + LL_TIM_SetSlaveMode(TIM2, LL_TIM_SLAVEMODE_RESET); + LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET); + LL_TIM_EnableMasterSlaveMode(TIM2); + } LL_TIM_DisableDMAReq_TRIG(TIM2); LL_TIM_DisableIT_TRIG(TIM2); + if(furi_hal_subghz.radio_type == SubGhzRadioInternal) { + // Timer: channel 1 indirect + 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); + + // ISR setup + furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_subghz_capture_ISR, NULL); + + // Interrupts and channels + LL_TIM_EnableIT_CC1(TIM2); + LL_TIM_EnableIT_CC2(TIM2); + LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1); + LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); + } + // Start timer LL_TIM_SetCounter(TIM2, 0); LL_TIM_EnableCounter(TIM2); @@ -563,9 +642,8 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* // Switch to RX furi_hal_subghz_rx(); - // Not used with current implementation // Clear the variable after the end of the session - //furi_hal_subghz_capture_delta_duration = 0; + furi_hal_subghz_capture_delta_duration = 0; } void furi_hal_subghz_stop_async_rx() { @@ -582,6 +660,9 @@ void furi_hal_subghz_stop_async_rx() { furi_hal_subghz_stop_debug(); FURI_CRITICAL_EXIT(); + if(furi_hal_subghz.radio_type == SubGhzRadioInternal) { + furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL); + } furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); } @@ -715,9 +796,19 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* furi_hal_subghz_async_tx.buffer = malloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t)); - furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true); - furi_hal_gpio_init( - furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + if(furi_hal_subghz.radio_type == SubGhzRadioExternal) { + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + } else { + // Connect CC1101_GD0 to TIM2 as output + furi_hal_gpio_init_ex( + &gpio_cc1101_g0, + GpioModeAltFunctionPushPull, + GpioPullDown, + GpioSpeedLow, + GpioAltFn1TIM2); + } // Configure DMA LL_DMA_InitTypeDef dma_config = {0}; @@ -777,25 +868,38 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* LL_TIM_SetCounter(TIM2, 0); LL_TIM_EnableCounter(TIM2); - //Signal generation for external G0 - const GpioPin* gpio = furi_hal_subghz.cc1101_g0_pin; - furi_hal_subghz_debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER; - furi_hal_subghz_debug_gpio_buff[1] = gpio->pin; + //Signal generation for external module - dma_config.MemoryOrM2MDstAddress = (uint32_t)furi_hal_subghz_debug_gpio_buff; - dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (gpio->port->BSRR); - dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; - dma_config.Mode = LL_DMA_MODE_CIRCULAR; - dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; - dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; - dma_config.NbData = 2; - dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; - dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH; - LL_DMA_Init(SUBGHZ_DMA_CH2_DEF, &dma_config); - LL_DMA_SetDataLength(SUBGHZ_DMA_CH2_DEF, 2); - LL_DMA_EnableChannel(SUBGHZ_DMA_CH2_DEF); + // Start debug (and speaker) + furi_hal_subghz_start_debug(); + + const GpioPin* gpio = furi_hal_subghz.cc1101_g0_pin; + + if((furi_hal_subghz.async_mirror_pin != NULL) && + (furi_hal_subghz.radio_type == SubGhzRadioInternal)) { + gpio = furi_hal_subghz.async_mirror_pin; + } + if(((furi_hal_subghz.async_mirror_pin != NULL) && + (furi_hal_subghz.radio_type == SubGhzRadioInternal)) || + (furi_hal_subghz.radio_type == SubGhzRadioExternal)) { + furi_hal_subghz_debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER; + furi_hal_subghz_debug_gpio_buff[1] = gpio->pin; + + dma_config.MemoryOrM2MDstAddress = (uint32_t)furi_hal_subghz_debug_gpio_buff; + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (gpio->port->BSRR); + dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + dma_config.Mode = LL_DMA_MODE_CIRCULAR; + dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; + dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; + dma_config.NbData = 2; + dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; + dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH; + LL_DMA_Init(SUBGHZ_DMA_CH2_DEF, &dma_config); + LL_DMA_SetDataLength(SUBGHZ_DMA_CH2_DEF, 2); + LL_DMA_EnableChannel(SUBGHZ_DMA_CH2_DEF); + } return true; } @@ -812,8 +916,9 @@ void furi_hal_subghz_stop_async_tx() { // Shutdown radio furi_hal_subghz_idle(); - - furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); + if(furi_hal_subghz.radio_type == SubGhzRadioExternal) { + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); + } // Deinitialize Timer FURI_CRITICAL_ENTER(); @@ -828,7 +933,14 @@ void furi_hal_subghz_stop_async_tx() { // Deinitialize GPIO furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - LL_DMA_DisableChannel(SUBGHZ_DMA_CH2_DEF); + // Stop debug + furi_hal_subghz_stop_debug(); + + if(((furi_hal_subghz.async_mirror_pin != NULL) && + (furi_hal_subghz.radio_type == SubGhzRadioInternal)) || + (furi_hal_subghz.radio_type == SubGhzRadioExternal)) { + LL_DMA_DisableChannel(SUBGHZ_DMA_CH2_DEF); + } FURI_CRITICAL_EXIT();