From 545815792405a6b656c4de5afdbf7b0397a42ea6 Mon Sep 17 00:00:00 2001 From: Victor Date: Thu, 2 Feb 2023 22:47:50 +0300 Subject: [PATCH] Added external CC1101 support --- .../subghz_frequency_analyzer_worker.c | 57 +-- .../main/subghz/scenes/subghz_scene_config.h | 1 + .../scenes/subghz_scene_ext_module_settings.c | 54 +++ .../subghz/scenes/subghz_scene_receiver.c | 5 +- .../main/subghz/scenes/subghz_scene_start.c | 20 +- applications/main/subghz/subghz_cli.c | 7 +- applications/main/subghz/subghz_i.c | 9 +- applications/main/subghz/views/receiver.c | 12 +- .../subghz/views/subghz_frequency_analyzer.c | 1 + .../main/subghz/views/subghz_read_raw.c | 5 +- .../main/subghz/views/subghz_test_carrier.c | 12 +- .../main/subghz/views/subghz_test_static.c | 5 +- applications/main/subghz/views/transmitter.c | 5 +- applications/main/unirfremix/unirfremix_app.c | 7 +- .../plugins/pocsag_pager/pocsag_pager_app_i.c | 4 +- applications/plugins/protoview/app_subghz.c | 11 +- .../plugins/protoview/view_direct_sampling.c | 4 +- .../weather_station/weather_station_app_i.c | 4 +- assets/icons/SubGhz/Fishing_123x52.png | Bin 0 -> 966 bytes firmware/targets/f7/api_symbols.csv | 14 + .../targets/f7/furi_hal/furi_hal_resources.c | 5 + .../targets/f7/furi_hal/furi_hal_resources.h | 5 + firmware/targets/f7/furi_hal/furi_hal_spi.c | 3 +- .../targets/f7/furi_hal/furi_hal_spi_config.c | 18 + .../targets/f7/furi_hal/furi_hal_spi_config.h | 6 +- .../targets/f7/furi_hal/furi_hal_subghz.c | 385 ++++++++++-------- .../furi_hal_include/furi_hal_subghz.h | 51 +++ lib/subghz/subghz_tx_rx_worker.c | 10 +- 28 files changed, 480 insertions(+), 240 deletions(-) create mode 100644 applications/main/subghz/scenes/subghz_scene_ext_module_settings.c create mode 100644 assets/icons/SubGhz/Fishing_123x52.png diff --git a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c index 7dc67c9f2..6452792a6 100644 --- a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c +++ b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c @@ -36,13 +36,13 @@ struct SubGhzFrequencyAnalyzerWorker { }; static void subghz_frequency_analyzer_worker_load_registers(const uint8_t data[][2]) { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); size_t i = 0; while(data[i][0]) { - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i][0], data[i][1]); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, data[i][0], data[i][1]); i++; } - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } // running average with adaptive coefficient @@ -80,26 +80,26 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { //Start CC1101 furi_hal_subghz_reset(); - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz); - cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_MDMCFG3, + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_flush_rx(furi_hal_subghz.spi_bus_handle); + cc1101_flush_tx(furi_hal_subghz.spi_bus_handle); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_MDMCFG3, 0b01111111); // symbol rate cc1101_write_reg( - &furi_hal_spi_bus_handle_subghz, + furi_hal_subghz.spi_bus_handle, CC1101_AGCCTRL2, 0b00000111); // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAGN_TARGET 42 dB cc1101_write_reg( - &furi_hal_spi_bus_handle_subghz, + furi_hal_subghz.spi_bus_handle, CC1101_AGCCTRL1, 0b00001000); // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 1000 - Absolute carrier sense threshold disabled cc1101_write_reg( - &furi_hal_spi_bus_handle_subghz, + furi_hal_subghz.spi_bus_handle, CC1101_AGCCTRL0, 0b00110000); // 00 - No hysteresis, medium asymmetric dead zone, medium gain ; 11 - 64 samples agc; 00 - Normal AGC, 00 - 4dB boundary - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); @@ -118,20 +118,23 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { // First stage: coarse scan for(size_t i = 0; i < subghz_setting_get_frequency_count(instance->setting); i++) { if(furi_hal_subghz_is_frequency_valid( - subghz_setting_get_frequency(instance->setting, i))) { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); + subghz_setting_get_frequency(instance->setting, i)) && + !((furi_hal_subghz.radio_type == SubGhzRadioExternal) && + (subghz_setting_get_frequency(instance->setting, i) >= 311900000 && + subghz_setting_get_frequency(instance->setting, i) <= 312200000))) { + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_switch_to_idle(furi_hal_subghz.spi_bus_handle); frequency = cc1101_set_frequency( - &furi_hal_spi_bus_handle_subghz, + furi_hal_subghz.spi_bus_handle, subghz_setting_get_frequency(instance->setting, i)); - cc1101_calibrate(&furi_hal_spi_bus_handle_subghz); + cc1101_calibrate(furi_hal_subghz.spi_bus_handle); do { - status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz); + status = cc1101_get_status(furi_hal_subghz.spi_bus_handle); } while(status.STATE != CC1101StateIDLE); - cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + cc1101_switch_to_rx(furi_hal_subghz.spi_bus_handle); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); furi_delay_ms(2); @@ -166,17 +169,17 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { i < frequency_rssi.frequency_coarse + 300000; i += 20000) { if(furi_hal_subghz_is_frequency_valid(i)) { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); - frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, i); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_switch_to_idle(furi_hal_subghz.spi_bus_handle); + frequency = cc1101_set_frequency(furi_hal_subghz.spi_bus_handle, i); - cc1101_calibrate(&furi_hal_spi_bus_handle_subghz); + cc1101_calibrate(furi_hal_subghz.spi_bus_handle); do { - status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz); + status = cc1101_get_status(furi_hal_subghz.spi_bus_handle); } while(status.STATE != CC1101StateIDLE); - cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + cc1101_switch_to_rx(furi_hal_subghz.spi_bus_handle); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); furi_delay_ms(2); diff --git a/applications/main/subghz/scenes/subghz_scene_config.h b/applications/main/subghz/scenes/subghz_scene_config.h index 1ad41a8b5..5acd534dc 100644 --- a/applications/main/subghz/scenes/subghz_scene_config.h +++ b/applications/main/subghz/scenes/subghz_scene_config.h @@ -26,6 +26,7 @@ ADD_SCENE(subghz, set_fix_bft, SetFixBft) ADD_SCENE(subghz, set_cnt_bft, SetCntBft) ADD_SCENE(subghz, set_seed_bft, SetSeedBft) ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer) +ADD_SCENE(subghz, ext_module_settings, ExtModuleSettings) ADD_SCENE(subghz, read_raw, ReadRAW) ADD_SCENE(subghz, more_raw, MoreRAW) ADD_SCENE(subghz, decode_raw, DecodeRAW) diff --git a/applications/main/subghz/scenes/subghz_scene_ext_module_settings.c b/applications/main/subghz/scenes/subghz_scene_ext_module_settings.c new file mode 100644 index 000000000..dabf42d42 --- /dev/null +++ b/applications/main/subghz/scenes/subghz_scene_ext_module_settings.c @@ -0,0 +1,54 @@ +#include "../subghz_i.h" +#include "../helpers/subghz_custom_event.h" + +uint8_t value_index; + +#define EXT_MODULES_COUNT (sizeof(radio_modules_variables_text) / sizeof(char* const)) +const char* const radio_modules_variables_text[] = { + "Internal", + "External", +}; + +static void subghz_scene_ext_module_changed(VariableItem* item) { + SubGhz* subghz = variable_item_get_context(item); + value_index = variable_item_get_current_value_index(item); + UNUSED(subghz); + + variable_item_set_current_value_text(item, radio_modules_variables_text[value_index]); +} +static void subghz_ext_module_start_var_list_enter_callback(void* context, uint32_t index) { + SubGhz* subghz = context; + view_dispatcher_send_custom_event(subghz->view_dispatcher, index); +} + +void subghz_scene_ext_module_settings_on_enter(void* context) { + SubGhz* subghz = context; + + VariableItemList* variable_item_list = subghz->variable_item_list; + + value_index = furi_hal_subghz.radio_type; + VariableItem* item = variable_item_list_add( + variable_item_list, "Module", EXT_MODULES_COUNT, subghz_scene_ext_module_changed, subghz); + + variable_item_list_set_enter_callback( + variable_item_list, subghz_ext_module_start_var_list_enter_callback, subghz); + + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, radio_modules_variables_text[value_index]); + + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList); +} + +bool subghz_scene_ext_module_settings_on_event(void* context, SceneManagerEvent event) { + SubGhz* subghz = context; + 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); + furi_hal_subghz_set_radio_type(value_index); +} diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 4f7f7be6c..106b9de50 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -53,7 +53,10 @@ static void subghz_scene_receiver_update_statusbar(void* context) { } else { subghz_get_frequency_modulation(subghz, frequency_str, NULL); furi_string_printf( - modulation_str, "Mod: %s", furi_string_get_cstr(subghz->txrx->preset->name)); + modulation_str, + "%s Mod: %s", + furi_hal_subghz_get_radio_type() ? "Ext" : "Int", + furi_string_get_cstr(subghz->txrx->preset->name)); } #else subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); diff --git a/applications/main/subghz/scenes/subghz_scene_start.c b/applications/main/subghz/scenes/subghz_scene_start.c index 8e6e01469..03feccb25 100644 --- a/applications/main/subghz/scenes/subghz_scene_start.c +++ b/applications/main/subghz/scenes/subghz_scene_start.c @@ -10,6 +10,7 @@ enum SubmenuIndex { SubmenuIndexAddManually, SubmenuIndexFrequencyAnalyzer, SubmenuIndexReadRAW, + SubmenuIndexExtSettings, }; void subghz_scene_start_submenu_callback(void* context, uint32_t index) { @@ -54,6 +55,12 @@ void subghz_scene_start_on_enter(void* context) { SubmenuIndexFrequencyAnalyzer, subghz_scene_start_submenu_callback, subghz); + submenu_add_item( + subghz->submenu, + "Radio settings", + SubmenuIndexExtSettings, + subghz_scene_start_submenu_callback, + subghz); if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { submenu_add_item( subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz); @@ -72,7 +79,17 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { view_dispatcher_stop(subghz->view_dispatcher); return true; } else if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexReadRAW) { + if(event.event == SubmenuIndexExtSettings) { + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneStart, SubmenuIndexExtSettings); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneExtModuleSettings); + return true; + + } else if(!furi_hal_subghz_check_radio()) { + furi_string_set(subghz->error_str, "Please connect\nexternal radio"); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub); + return true; + } else if(event.event == SubmenuIndexReadRAW) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneStart, SubmenuIndexReadRAW); subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; @@ -99,7 +116,6 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer); DOLPHIN_DEED(DolphinDeedSubGhzFrequencyAnalyzer); return true; - } else if(event.event == SubmenuIndexTest) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest); diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 684733c2b..b5dcf2669 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -42,8 +42,9 @@ void subghz_cli_command_tx_carrier(Cli* cli, FuriString* args, void* context) { furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); frequency = furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&gpio_cc1101_g0, true); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true); furi_hal_power_suppress_charge_enter(); @@ -264,7 +265,7 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { furi_hal_subghz_reset(); furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); frequency = furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_power_suppress_charge_enter(); diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index 77ee7c950..02ff8dd3f 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -69,7 +69,7 @@ void subghz_begin(SubGhz* subghz, uint8_t* preset_data) { furi_hal_subghz_reset(); furi_hal_subghz_idle(); furi_hal_subghz_load_custom_preset(preset_data); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); subghz->txrx->txrx_state = SubGhzTxRxStateIDLE; } @@ -84,7 +84,7 @@ uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency) { furi_hal_subghz_idle(); uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_flush_rx(); subghz_speaker_on(subghz); furi_hal_subghz_rx(); @@ -103,8 +103,9 @@ static bool subghz_tx(SubGhz* subghz, uint32_t frequency) { furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep); furi_hal_subghz_idle(); furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_write(&gpio_cc1101_g0, false); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); subghz_speaker_on(subghz); bool ret = furi_hal_subghz_tx(); subghz->txrx->txrx_state = SubGhzTxRxStateTx; diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index 6146c4641..bb7a5c38f 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -230,13 +230,21 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { if(model->history_item == 0) { if(model->mode == SubGhzViewReceiverModeLive) { - canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); + canvas_draw_icon( + canvas, + 0, + 0, + furi_hal_subghz_get_radio_type() ? &I_Fishing_123x52 : &I_Scanning_123x52); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 63, 46, "Scanning..."); canvas_draw_line(canvas, 46, 51, 125, 51); canvas_set_font(canvas, FontSecondary); } else { - canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); + canvas_draw_icon( + canvas, + 0, + 0, + furi_hal_subghz_get_radio_type() ? &I_Fishing_123x52 : &I_Scanning_123x52); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 63, 46, "Decoding..."); canvas_set_font(canvas, FontSecondary); diff --git a/applications/main/subghz/views/subghz_frequency_analyzer.c b/applications/main/subghz/views/subghz_frequency_analyzer.c index 4ca2afed2..9fa304e90 100644 --- a/applications/main/subghz/views/subghz_frequency_analyzer.c +++ b/applications/main/subghz/views/subghz_frequency_analyzer.c @@ -165,6 +165,7 @@ void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel // Title canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 0, 7, furi_hal_subghz_get_radio_type() ? "Ext" : "Int"); canvas_draw_str(canvas, 20, 7, "Frequency Analyzer"); // RSSI diff --git a/applications/main/subghz/views/subghz_read_raw.c b/applications/main/subghz/views/subghz_read_raw.c index dcfc281d2..2309fe86c 100644 --- a/applications/main/subghz/views/subghz_read_raw.c +++ b/applications/main/subghz/views/subghz_read_raw.c @@ -280,8 +280,9 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { uint8_t graphics_mode = 1; canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 5, 7, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 40, 7, furi_string_get_cstr(model->preset_str)); + canvas_draw_str(canvas, 0, 7, furi_string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 35, 7, furi_string_get_cstr(model->preset_str)); + canvas_draw_str(canvas, 70, 7, furi_hal_subghz_get_radio_type() ? "E" : "I"); canvas_draw_str_aligned( canvas, 126, 0, AlignRight, AlignTop, furi_string_get_cstr(model->sample_write)); diff --git a/applications/main/subghz/views/subghz_test_carrier.c b/applications/main/subghz/views/subghz_test_carrier.c index e533a6aac..0cc9a2966 100644 --- a/applications/main/subghz/views/subghz_test_carrier.c +++ b/applications/main/subghz/views/subghz_test_carrier.c @@ -115,14 +115,16 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) { furi_hal_subghz_set_path(model->path); if(model->status == SubGhzTestCarrierModelStatusRx) { - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_rx(); } else { furi_hal_gpio_init( - &gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&gpio_cc1101_g0, true); + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true); if(!furi_hal_subghz_tx()) { - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); subghz_test_carrier->callback( SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context); } @@ -140,7 +142,7 @@ void subghz_test_carrier_enter(void* context) { furi_hal_subghz_reset(); furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); with_view_model( subghz_test_carrier->view, diff --git a/applications/main/subghz/views/subghz_test_static.c b/applications/main/subghz/views/subghz_test_static.c index 6abefda76..b9e5a8c9c 100644 --- a/applications/main/subghz/views/subghz_test_static.c +++ b/applications/main/subghz/views/subghz_test_static.c @@ -143,8 +143,9 @@ void subghz_test_static_enter(void* context) { furi_hal_subghz_reset(); furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&gpio_cc1101_g0, false); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); instance->status_tx = SubGhzTestStaticStatusIDLE; with_view_model( diff --git a/applications/main/subghz/views/transmitter.c b/applications/main/subghz/views/transmitter.c index dc324a6a5..39f9161ef 100644 --- a/applications/main/subghz/views/transmitter.c +++ b/applications/main/subghz/views/transmitter.c @@ -85,8 +85,9 @@ void subghz_view_transmitter_draw(Canvas* canvas, SubGhzViewTransmitterModel* mo canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); elements_multiline_text(canvas, 0, 7, furi_string_get_cstr(model->key_str)); - canvas_draw_str(canvas, 78, 7, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 113, 7, furi_string_get_cstr(model->preset_str)); + canvas_draw_str(canvas, 72, 7, furi_string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 107, 7, furi_string_get_cstr(model->preset_str)); + canvas_draw_str(canvas, 123, 7, furi_hal_subghz_get_radio_type() ? "E" : "I"); if(model->show_button) subghz_view_transmitter_button_right(canvas, "Send"); } diff --git a/applications/main/unirfremix/unirfremix_app.c b/applications/main/unirfremix/unirfremix_app.c index d981c3cd5..03c3c2f27 100644 --- a/applications/main/unirfremix/unirfremix_app.c +++ b/applications/main/unirfremix/unirfremix_app.c @@ -522,13 +522,14 @@ static bool unirfremix_send_sub(UniRFRemix* app, FlipperFormat* fff_data) { furi_hal_subghz_reset(); furi_hal_subghz_idle(); furi_hal_subghz_load_custom_preset(app->txpreset->data); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_idle(); furi_hal_subghz_set_frequency_and_path(app->txpreset->frequency); - furi_hal_gpio_write(&gpio_cc1101_g0, false); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); if(!furi_hal_subghz_tx()) { FURI_LOG_E(TAG, "Sending not allowed"); diff --git a/applications/plugins/pocsag_pager/pocsag_pager_app_i.c b/applications/plugins/pocsag_pager/pocsag_pager_app_i.c index ba6e87c28..ff73ab50e 100644 --- a/applications/plugins/pocsag_pager/pocsag_pager_app_i.c +++ b/applications/plugins/pocsag_pager/pocsag_pager_app_i.c @@ -40,7 +40,7 @@ void pcsg_begin(POCSAGPagerApp* app, uint8_t* preset_data) { furi_hal_subghz_reset(); furi_hal_subghz_idle(); furi_hal_subghz_load_custom_preset(preset_data); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); app->txrx->txrx_state = PCSGTxRxStateIDLE; } @@ -54,7 +54,7 @@ uint32_t pcsg_rx(POCSAGPagerApp* app, uint32_t frequency) { furi_hal_subghz_idle(); uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_flush_rx(); furi_hal_subghz_rx(); diff --git a/applications/plugins/protoview/app_subghz.c b/applications/plugins/protoview/app_subghz.c index 80d6cf18c..69197df5c 100644 --- a/applications/plugins/protoview/app_subghz.c +++ b/applications/plugins/protoview/app_subghz.c @@ -52,7 +52,7 @@ void radio_begin(ProtoViewApp* app) { } else { furi_hal_subghz_load_custom_preset(ProtoViewModulations[app->modulation].custom); } - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); app->txrx->txrx_state = TxRxStateIDLE; } @@ -80,7 +80,7 @@ uint32_t radio_rx(ProtoViewApp* app) { furi_hal_subghz_idle(); /* Put it into idle state in case it is sleeping. */ uint32_t value = furi_hal_subghz_set_frequency_and_path(app->frequency); FURI_LOG_E(TAG, "Switched to frequency: %lu", value); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_flush_rx(); furi_hal_subghz_rx(); if(!app->txrx->debug_timer_sampling) { @@ -134,8 +134,9 @@ void radio_tx_signal(ProtoViewApp* app, FuriHalSubGhzAsyncTxCallback data_feeder furi_hal_subghz_idle(); uint32_t value = furi_hal_subghz_set_frequency_and_path(app->frequency); FURI_LOG_E(TAG, "Switched to frequency: %lu", value); - furi_hal_gpio_write(&gpio_cc1101_g0, false); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); furi_hal_subghz_start_async_tx(data_feeder, ctx); while(!furi_hal_subghz_is_async_tx_complete()) furi_delay_ms(10); @@ -156,7 +157,7 @@ void radio_tx_signal(ProtoViewApp* app, FuriHalSubGhzAsyncTxCallback data_feeder void protoview_timer_isr(void* ctx) { ProtoViewApp* app = ctx; - bool level = furi_hal_gpio_read(&gpio_cc1101_g0); + bool level = furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin); if(app->txrx->last_g0_value != level) { uint32_t now = DWT->CYCCNT; uint32_t dur = now - app->txrx->last_g0_change_time; diff --git a/applications/plugins/protoview/view_direct_sampling.c b/applications/plugins/protoview/view_direct_sampling.c index 5d9e08c4a..0268e5297 100644 --- a/applications/plugins/protoview/view_direct_sampling.c +++ b/applications/plugins/protoview/view_direct_sampling.c @@ -95,7 +95,7 @@ void view_enter_direct_sampling(ProtoViewApp* app) { * to stop the async RX will put it into idle) and configure the * G0 pin for reading. */ furi_hal_subghz_rx(); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); } else { raw_sampling_worker_stop(app); } @@ -127,7 +127,7 @@ static void ds_timer_isr(void* ctx) { DirectSamplingViewPrivData* privdata = app->view_privdata; if(app->direct_sampling_enabled) { - bool level = furi_hal_gpio_read(&gpio_cc1101_g0); + bool level = furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin); bitmap_set(privdata->captured, CAPTURED_BITMAP_BYTES, privdata->captured_idx, level); privdata->captured_idx = (privdata->captured_idx + 1) % CAPTURED_BITMAP_BITS; } diff --git a/applications/plugins/weather_station/weather_station_app_i.c b/applications/plugins/weather_station/weather_station_app_i.c index 712634a2c..7236b6625 100644 --- a/applications/plugins/weather_station/weather_station_app_i.c +++ b/applications/plugins/weather_station/weather_station_app_i.c @@ -58,7 +58,7 @@ void ws_begin(WeatherStationApp* app, uint8_t* preset_data) { furi_hal_subghz_reset(); furi_hal_subghz_idle(); furi_hal_subghz_load_custom_preset(preset_data); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); app->txrx->txrx_state = WSTxRxStateIDLE; } @@ -72,7 +72,7 @@ uint32_t ws_rx(WeatherStationApp* app, uint32_t frequency) { furi_hal_subghz_idle(); uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_flush_rx(); furi_hal_subghz_rx(); diff --git a/assets/icons/SubGhz/Fishing_123x52.png b/assets/icons/SubGhz/Fishing_123x52.png new file mode 100644 index 0000000000000000000000000000000000000000..1e365de8f4d9c5aeb0b3b11097a2e65eb3451b99 GIT binary patch literal 966 zcmV;%13CPOP)w&j00001b5ch_0Itp) z=>Px&fJsC_RCt{2o7ryVAPj~{)c1d7dQlO%9NTzf35QP_r88l1_%RsMxpK}q9lnBl zwgHE69I?NMA8WfkPZk&xWE>@309V>Reg=;Dhz-mKd1O8jsbMKlmU$+v0WBU~C5u zA9XtMj1?-jRcK4l=IL`bmT&b0sopU%pR;SMOZnTV1+KrDi*Mlj8S%}BXL}o!d^|T9 zR`hPpgX{64zKt3O>5(;JT*5rNKzX=y$y;SPm)MKhsEFz=s|1+T##P2QQsaN#Ia&immXMTS%d9mvpoXR^5RwOtnn=CkJv3w)Fcg7K6>qV z3nz6VS2P|a>IjdwM%OzLe)Qtta_Q7FBE1Ov=gRCXbV^3CwM#W8aBG0Q=TK-f^?rAe z3#8bsXjv+_MPSYjDOi+^wY>w-K?7sFeiQ2Ay8J?@{SZ zcv}=T*i`NwdpA3U>+L^6r#mWX!Ikld%9fA|f={mf(b4MexIA0y zu^KF?(UHlaH{$Ya?PZCSBUT^G=WI@BkKm*0eG{$>npE)Cv-~WvgS)gj@VIm162V(f z%VdKSCUOhenJ0thZb%_;L48FB&Z< +#include #include #include @@ -25,7 +26,7 @@ void furi_hal_spi_deinit_early() { void furi_hal_spi_init() { furi_hal_spi_bus_init(&furi_hal_spi_bus_r); - furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_bus_handle_init(furi_hal_subghz.spi_bus_handle); furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast); furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow); diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi_config.c b/firmware/targets/f7/furi_hal/furi_hal_spi_config.c index 56f67bbf8..8f2877513 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi_config.c +++ b/firmware/targets/f7/furi_hal/furi_hal_spi_config.c @@ -260,6 +260,15 @@ static void furi_hal_spi_bus_handle_subghz_event_callback( furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m); } +FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz_int = { + .bus = &furi_hal_spi_bus_r, + .callback = furi_hal_spi_bus_handle_subghz_event_callback, + .miso = &gpio_spi_r_miso, + .mosi = &gpio_spi_r_mosi, + .sck = &gpio_spi_r_sck, + .cs = &gpio_subghz_cs, +}; + FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = { .bus = &furi_hal_spi_bus_r, .callback = furi_hal_spi_bus_handle_subghz_event_callback, @@ -269,6 +278,15 @@ FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = { .cs = &gpio_subghz_cs, }; +FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz_ext = { + .bus = &furi_hal_spi_bus_r, + .callback = furi_hal_spi_bus_handle_subghz_event_callback, + .miso = &gpio_ext_pa6, + .mosi = &gpio_ext_pa7, + .sck = &gpio_ext_pb3, + .cs = &gpio_ext_pa4, +}; + static void furi_hal_spi_bus_handle_nfc_event_callback( FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi_config.h b/firmware/targets/f7/furi_hal/furi_hal_spi_config.h index eab633a19..8ea138bdc 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi_config.h +++ b/firmware/targets/f7/furi_hal/furi_hal_spi_config.h @@ -27,8 +27,12 @@ extern FuriHalSpiBus furi_hal_spi_bus_r; /** Furi Hal Spi Bus D (Display, SdCard) */ extern FuriHalSpiBus furi_hal_spi_bus_d; -/** CC1101 on `furi_hal_spi_bus_r` */ +/** CC1101 on current SPI bus */ extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz; +/** CC1101 on `furi_hal_spi_bus_r` */ +extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz_int; +/** CC1101 on external `furi_hal_spi_bus_r` */ +extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz_ext; /** ST25R3916 on `furi_hal_spi_bus_r` */ extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc; diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 4ea6f3524..9b0a1b2e2 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -16,95 +17,169 @@ #include #define TAG "FuriHalSubGhz" +//Initialisation timeout (ms) +#define INIT_TIMEOUT 10 static uint32_t furi_hal_subghz_debug_gpio_buff[2]; - -typedef struct { - volatile SubGhzState state; - volatile SubGhzRegulation regulation; - volatile FuriHalSubGhzPreset preset; - const GpioPin* async_mirror_pin; -} FuriHalSubGhz; +static bool last_OTG_state = false; volatile FuriHalSubGhz furi_hal_subghz = { .state = SubGhzStateInit, .regulation = SubGhzRegulationTxRx, .preset = FuriHalSubGhzPresetIDLE, .async_mirror_pin = NULL, + .radio_type = SubGhzRadioInternal, + .spi_bus_handle = &furi_hal_spi_bus_handle_subghz, + .cc1101_g0_pin = &gpio_cc1101_g0, }; +bool furi_hal_subghz_set_radio_type(SubGhzRadioType state) { + furi_hal_subghz.radio_type = state; + furi_hal_spi_bus_handle_deinit(furi_hal_subghz.spi_bus_handle); + if(state) { + furi_hal_subghz.spi_bus_handle = &furi_hal_spi_bus_handle_subghz_ext; + furi_hal_subghz.cc1101_g0_pin = &gpio_cc1101_g0_ext; + } else { + furi_hal_subghz.spi_bus_handle = &furi_hal_spi_bus_handle_subghz; + furi_hal_subghz.cc1101_g0_pin = &gpio_cc1101_g0; + } + furi_hal_spi_bus_handle_init(furi_hal_subghz.spi_bus_handle); + furi_hal_subghz_init_check(); + return true; +} + +SubGhzRadioType furi_hal_subghz_get_radio_type(void) { + return furi_hal_subghz.radio_type; +} + void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin) { furi_hal_subghz.async_mirror_pin = pin; } -void furi_hal_subghz_init() { +void furi_hal_subghz_init(void) { + furi_hal_subghz_init_check(); +} + +void furi_hal_subghz_enable_ext_power(void) { + if(furi_hal_subghz.radio_type != SubGhzRadioInternal && !furi_hal_power_is_otg_enabled()) { + furi_hal_power_enable_otg(); + } +} + +void furi_hal_subghz_disable_ext_power(void) { + if(furi_hal_subghz.radio_type != SubGhzRadioInternal && !last_OTG_state) { + furi_hal_power_disable_otg(); + } +} + +bool furi_hal_subghz_check_radio(void) { + bool result = true; + + furi_hal_subghz_enable_ext_power(); + + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + uint8_t ver = cc1101_get_version(furi_hal_subghz.spi_bus_handle); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); + + if((ver != 0) && (ver != 255)) { + FURI_LOG_D(TAG, "Radio check ok"); + } else { + FURI_LOG_D(TAG, "Radio check failed"); + furi_hal_subghz_disable_ext_power(); + result = false; + } + return result; +} + +bool furi_hal_subghz_init_check(void) { + bool result = true; + furi_assert(furi_hal_subghz.state == SubGhzStateInit); furi_hal_subghz.state = SubGhzStateIdle; furi_hal_subghz.preset = FuriHalSubGhzPresetIDLE; - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); + last_OTG_state = furi_hal_power_is_otg_enabled(); + furi_hal_subghz_enable_ext_power(); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); #ifdef FURI_HAL_SUBGHZ_TX_GPIO furi_hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); #endif // Reset - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - cc1101_reset(&furi_hal_spi_bus_handle_subghz); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + cc1101_reset(furi_hal_subghz.spi_bus_handle); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance); // Prepare GD0 for power on self test - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); // GD0 low - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW); - while(furi_hal_gpio_read(&gpio_cc1101_g0) != false) - ; + 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_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); - while(furi_hal_gpio_read(&gpio_cc1101_g0) != true) - ; + 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; + } + } // Reset GD0 to floating state - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + 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); // RF switches furi_hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG2, CC1101IocfgHW); // Go to sleep - cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); + cc1101_shutdown(furi_hal_subghz.spi_bus_handle); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); - FURI_LOG_I(TAG, "Init OK"); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); + + if(result) { + FURI_LOG_I(TAG, "Init OK"); + } else { + FURI_LOG_E(TAG, "Failed to initialization"); + furi_hal_subghz_disable_ext_power(); + } + return result; } void furi_hal_subghz_sleep() { furi_assert(furi_hal_subghz.state == SubGhzStateIdle); - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); - cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); + cc1101_switch_to_idle(furi_hal_subghz.spi_bus_handle); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + 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); - cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); + cc1101_shutdown(furi_hal_subghz.spi_bus_handle); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); + + furi_hal_subghz_disable_ext_power(); furi_hal_subghz.preset = FuriHalSubGhzPresetIDLE; } void furi_hal_subghz_dump_state() { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); printf( "[furi_hal_subghz] cc1101 chip %d, version %d\r\n", - cc1101_get_partnumber(&furi_hal_spi_bus_handle_subghz), - cc1101_get_version(&furi_hal_spi_bus_handle_subghz)); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + cc1101_get_partnumber(furi_hal_subghz.spi_bus_handle), + cc1101_get_version(furi_hal_subghz.spi_bus_handle)); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { @@ -136,15 +211,15 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { void furi_hal_subghz_load_custom_preset(uint8_t* preset_data) { //load config - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_reset(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_reset(furi_hal_subghz.spi_bus_handle); uint32_t i = 0; uint8_t pa[8] = {0}; while(preset_data[i]) { - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, preset_data[i], preset_data[i + 1]); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, preset_data[i], preset_data[i + 1]); i += 2; } - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); //load pa table memcpy(&pa[0], &preset_data[i + 2], 8); @@ -166,48 +241,48 @@ void furi_hal_subghz_load_custom_preset(uint8_t* preset_data) { } void furi_hal_subghz_load_registers(uint8_t* data) { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_reset(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_reset(furi_hal_subghz.spi_bus_handle); uint32_t i = 0; while(data[i]) { - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i], data[i + 1]); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, data[i], data[i + 1]); i += 2; } - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } void furi_hal_subghz_load_patable(const uint8_t data[8]) { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_set_pa_table(&furi_hal_spi_bus_handle_subghz, data); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_set_pa_table(furi_hal_subghz.spi_bus_handle, data); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_FIFO, size); - cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_flush_tx(furi_hal_subghz.spi_bus_handle); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_FIFO, size); + cc1101_write_fifo(furi_hal_subghz.spi_bus_handle, data, size); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } void furi_hal_subghz_flush_rx() { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_flush_rx(furi_hal_subghz.spi_bus_handle); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } void furi_hal_subghz_flush_tx() { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_flush_tx(furi_hal_subghz.spi_bus_handle); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } bool furi_hal_subghz_rx_pipe_not_empty() { CC1101RxBytes status[1]; - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); cc1101_read_reg( - &furi_hal_spi_bus_handle_subghz, (CC1101_STATUS_RXBYTES) | CC1101_BURST, (uint8_t*)status); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_subghz.spi_bus_handle, (CC1101_STATUS_RXBYTES) | CC1101_BURST, (uint8_t*)status); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); // TODO: you can add a buffer overflow flag if needed if(status->NUM_RXBYTES > 0) { return true; @@ -217,10 +292,10 @@ bool furi_hal_subghz_rx_pipe_not_empty() { } bool furi_hal_subghz_is_rx_data_crc_valid() { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); uint8_t data[1]; - cc1101_read_reg(&furi_hal_spi_bus_handle_subghz, CC1101_STATUS_LQI | CC1101_BURST, data); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + cc1101_read_reg(furi_hal_subghz.spi_bus_handle, CC1101_STATUS_LQI | CC1101_BURST, data); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); if(((data[0] >> 7) & 0x01)) { return true; } else { @@ -229,51 +304,52 @@ bool furi_hal_subghz_is_rx_data_crc_valid() { } void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_read_fifo(furi_hal_subghz.spi_bus_handle, data, size); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } void furi_hal_subghz_shutdown() { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); // Reset and shutdown - cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + cc1101_shutdown(furi_hal_subghz.spi_bus_handle); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); + furi_hal_subghz_disable_ext_power(); } void furi_hal_subghz_reset() { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); - cc1101_reset(&furi_hal_spi_bus_handle_subghz); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + cc1101_switch_to_idle(furi_hal_subghz.spi_bus_handle); + cc1101_reset(furi_hal_subghz.spi_bus_handle); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } void furi_hal_subghz_idle() { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_switch_to_idle(furi_hal_subghz.spi_bus_handle); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } void furi_hal_subghz_rx() { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_switch_to_rx(furi_hal_subghz.spi_bus_handle); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } bool furi_hal_subghz_tx() { if(furi_hal_subghz.regulation != SubGhzRegulationTxRx) return false; - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - cc1101_switch_to_tx(&furi_hal_spi_bus_handle_subghz); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + cc1101_switch_to_tx(furi_hal_subghz.spi_bus_handle); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); return true; } float furi_hal_subghz_get_rssi() { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - int32_t rssi_dec = cc1101_get_rssi(&furi_hal_spi_bus_handle_subghz); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + int32_t rssi_dec = cc1101_get_rssi(furi_hal_subghz.spi_bus_handle); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); float rssi = rssi_dec; if(rssi_dec >= 128) { @@ -286,10 +362,10 @@ float furi_hal_subghz_get_rssi() { } uint8_t furi_hal_subghz_get_lqi() { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); uint8_t data[1]; - cc1101_read_reg(&furi_hal_spi_bus_handle_subghz, CC1101_STATUS_LQI | CC1101_BURST, data); - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + cc1101_read_reg(furi_hal_subghz.spi_bus_handle, CC1101_STATUS_LQI | CC1101_BURST, data); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); return data[0] & 0x7F; } @@ -357,39 +433,39 @@ bool furi_hal_subghz_is_tx_allowed(uint32_t value) { uint32_t furi_hal_subghz_set_frequency(uint32_t value) { furi_hal_subghz.regulation = SubGhzRegulationTxRx; - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); - uint32_t real_frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, value); - cc1101_calibrate(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); + uint32_t real_frequency = cc1101_set_frequency(furi_hal_subghz.spi_bus_handle, value); + cc1101_calibrate(furi_hal_subghz.spi_bus_handle); while(true) { - CC1101Status status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz); + CC1101Status status = cc1101_get_status(furi_hal_subghz.spi_bus_handle); if(status.STATE == CC1101StateIDLE) break; } - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); return real_frequency; } void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { - furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle); if(path == FuriHalSubGhzPath433) { furi_hal_gpio_write(&gpio_rf_sw_0, 0); cc1101_write_reg( - &furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); + furi_hal_subghz.spi_bus_handle, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); } else if(path == FuriHalSubGhzPath315) { furi_hal_gpio_write(&gpio_rf_sw_0, 1); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG2, CC1101IocfgHW); } else if(path == FuriHalSubGhzPath868) { furi_hal_gpio_write(&gpio_rf_sw_0, 1); cc1101_write_reg( - &furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); + furi_hal_subghz.spi_bus_handle, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); } else if(path == FuriHalSubGhzPathIsolate) { furi_hal_gpio_write(&gpio_rf_sw_0, 0); - cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); + cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG2, CC1101IocfgHW); } else { furi_crash("SubGhz: Incorrect path during set."); } - furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); + furi_hal_spi_release(furi_hal_subghz.spi_bus_handle); } static bool furi_hal_subghz_start_debug() { @@ -415,38 +491,29 @@ 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() { - // 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_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, - furi_hal_subghz_capture_delta_duration, - (void*)furi_hal_subghz_capture_callback_context); + true, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context); } - } - // Channel 2 - if(LL_TIM_IsActiveFlag_CC2(TIM2)) { - LL_TIM_ClearFlag_CC2(TIM2); + } 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, - LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration, - (void*)furi_hal_subghz_capture_callback_context); + false, TIM2->CNT, (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) { @@ -456,8 +523,13 @@ 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_ex( - &gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2); + 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); // Timer: base LL_TIM_InitTypeDef TIM_InitStruct = {0}; @@ -470,34 +542,9 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* // Timer: advanced LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); LL_TIM_DisableARRPreload(TIM2); - 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); - // 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); @@ -523,9 +570,8 @@ void furi_hal_subghz_stop_async_rx() { furi_hal_subghz_stop_debug(); FURI_CRITICAL_EXIT(); - furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); } typedef struct { @@ -624,7 +670,8 @@ static void furi_hal_subghz_async_tx_timer_isr() { } else if(furi_hal_subghz.state == SubGhzStateAsyncTxLast) { furi_hal_subghz.state = SubGhzStateAsyncTxEnd; //forcibly pulls the pin to the ground so that there is no carrier - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullDown, GpioSpeedLow); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullDown, GpioSpeedLow); LL_TIM_DisableCounter(TIM2); } else { furi_crash(NULL); @@ -651,9 +698,9 @@ 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)); - // Connect CC1101_GD0 to TIM2 as output - furi_hal_gpio_init_ex( - &gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); // Configure DMA LL_DMA_InitTypeDef dma_config = {0}; @@ -713,27 +760,25 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* LL_TIM_SetCounter(TIM2, 0); LL_TIM_EnableCounter(TIM2); - // Start debug - if(furi_hal_subghz_start_debug()) { - const GpioPin* gpio = furi_hal_subghz.async_mirror_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 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; - 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(DMA1, LL_DMA_CHANNEL_2, &dma_config); - LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 2); - LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); - } + 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(DMA1, LL_DMA_CHANNEL_2, &dma_config); + LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 2); + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); return true; } @@ -765,7 +810,7 @@ void furi_hal_subghz_stop_async_tx() { furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL); // Deinitialize GPIO - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow); // Stop debug if(furi_hal_subghz_stop_debug()) { diff --git a/firmware/targets/furi_hal_include/furi_hal_subghz.h b/firmware/targets/furi_hal_include/furi_hal_subghz.h index b3319e226..b19a71f9a 100644 --- a/firmware/targets/furi_hal_include/furi_hal_subghz.h +++ b/firmware/targets/furi_hal_include/furi_hal_subghz.h @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -61,6 +62,25 @@ typedef enum { SubGhzRegulationTxRx, /**TxRx*/ } SubGhzRegulation; +/** SubGhz radio types */ +typedef enum { + SubGhzRadioInternal, + SubGhzRadioExternal, +} SubGhzRadioType; + +/** Structure for accessing SubGhz settings*/ +typedef struct { + volatile SubGhzState state; + volatile SubGhzRegulation regulation; + volatile FuriHalSubGhzPreset preset; + const GpioPin* async_mirror_pin; + SubGhzRadioType radio_type; + FuriHalSpiBusHandle* spi_bus_handle; + const GpioPin* cc1101_g0_pin; +} FuriHalSubGhz; + +extern volatile FuriHalSubGhz furi_hal_subghz; + /* Mirror RX/TX async modulation signal to specified pin * * @warning Configures pin to output mode. Make sure it is not connected @@ -76,6 +96,13 @@ void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin); */ void furi_hal_subghz_init(); +/** Initialize and switch to power save mode Used by internal API-HAL + * initialization routine Can be used to reinitialize device to safe state and + * send it to sleep + * @return true if initialisation is successfully + */ +bool furi_hal_subghz_init_check(void); + /** Send device to sleep mode */ void furi_hal_subghz_sleep(); @@ -258,6 +285,30 @@ bool furi_hal_subghz_is_async_tx_complete(); */ void furi_hal_subghz_stop_async_tx(); +/** Switching between internal and external radio + * @param state SubGhzRadioInternal or SubGhzRadioExternal + * @return true if switching is successful + */ +bool furi_hal_subghz_set_radio_type(SubGhzRadioType state); + +/** Get current radio + * @return SubGhzRadioInternal or SubGhzRadioExternal + */ +SubGhzRadioType furi_hal_subghz_get_radio_type(void); + +/** Check for a radio module + * @return true if check is successful + */ +bool furi_hal_subghz_check_radio(void); + +/** Turn on the power of the external radio module + */ +void furi_hal_subghz_enable_ext_power(void); + +/** Turn off the power of the external radio module + */ +void furi_hal_subghz_disable_ext_power(void); + #ifdef __cplusplus } #endif diff --git a/lib/subghz/subghz_tx_rx_worker.c b/lib/subghz/subghz_tx_rx_worker.c index 6300ec630..e380fc967 100644 --- a/lib/subghz/subghz_tx_rx_worker.c +++ b/lib/subghz/subghz_tx_rx_worker.c @@ -70,7 +70,7 @@ bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* furi_delay_tick(1); } //waiting for reception to complete - while(furi_hal_gpio_read(&gpio_cc1101_g0)) { + while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin)) { furi_delay_tick(1); if(!--timeout) { FURI_LOG_W(TAG, "RX cc1101_g0 timeout"); @@ -104,14 +104,16 @@ void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t si furi_hal_subghz_write_packet(data, size); furi_hal_subghz_tx(); //start send instance->status = SubGhzTxRxWorkerStatusTx; - while(!furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be set -> sync transmitted + while(!furi_hal_gpio_read( + furi_hal_subghz.cc1101_g0_pin)) { // Wait for GDO0 to be set -> sync transmitted furi_delay_tick(1); if(!--timeout) { FURI_LOG_W(TAG, "TX !cc1101_g0 timeout"); break; } } - while(furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be cleared -> end of packet + while(furi_hal_gpio_read( + furi_hal_subghz.cc1101_g0_pin)) { // Wait for GDO0 to be cleared -> end of packet furi_delay_tick(1); if(!--timeout) { FURI_LOG_W(TAG, "TX cc1101_g0 timeout"); @@ -134,7 +136,7 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { furi_hal_subghz_idle(); furi_hal_subghz_load_preset(FuriHalSubGhzPresetGFSK9_99KbAsync); //furi_hal_subghz_load_preset(FuriHalSubGhzPresetMSK99_97KbAsync); - furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_set_frequency_and_path(instance->frequency); furi_hal_subghz_flush_rx();