From b1850fd7006b15b0d1c8dcf3670b38b063a8332c Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Thu, 6 Jul 2023 16:23:48 +0300 Subject: [PATCH] Weather station: new external radio driver (#3) * Weather station: new external radio driver --- .../helpers/radio_device_loader.c | 69 +++++++++++++++++++ .../helpers/radio_device_loader.h | 17 +++++ .../scenes/weather_station_receiver.c | 11 ++- .../views/weather_station_receiver.c | 13 ++-- .../views/weather_station_receiver.h | 3 +- .../weather_station/weather_station_app.c | 26 +++---- .../weather_station/weather_station_app_i.c | 33 +++++---- .../weather_station/weather_station_app_i.h | 3 + 8 files changed, 135 insertions(+), 40 deletions(-) create mode 100644 applications/external/weather_station/helpers/radio_device_loader.c create mode 100644 applications/external/weather_station/helpers/radio_device_loader.h diff --git a/applications/external/weather_station/helpers/radio_device_loader.c b/applications/external/weather_station/helpers/radio_device_loader.c new file mode 100644 index 000000000..0d99549eb --- /dev/null +++ b/applications/external/weather_station/helpers/radio_device_loader.c @@ -0,0 +1,69 @@ +#include "radio_device_loader.h" + +#include +#include + +static void radio_device_loader_power_on() { + uint8_t attempts = 0; + while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { + furi_hal_power_enable_otg(); + //CC1101 power-up time + furi_delay_ms(10); + } +} + +static void radio_device_loader_power_off() { + if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg(); +} + +bool radio_device_loader_is_connect_external(const char* name) { + bool is_connect = false; + bool is_otg_enabled = furi_hal_power_is_otg_enabled(); + + if(!is_otg_enabled) { + radio_device_loader_power_on(); + } + + const SubGhzDevice* device = subghz_devices_get_by_name(name); + if(device) { + is_connect = subghz_devices_is_connect(device); + } + + if(!is_otg_enabled) { + radio_device_loader_power_off(); + } + return is_connect; +} + +const SubGhzDevice* radio_device_loader_set( + const SubGhzDevice* current_radio_device, + SubGhzRadioDeviceType radio_device_type) { + const SubGhzDevice* radio_device; + + if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 && + radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) { + radio_device_loader_power_on(); + radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME); + subghz_devices_begin(radio_device); + } else if(current_radio_device == NULL) { + radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); + } else { + radio_device_loader_end(current_radio_device); + radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME); + } + + return radio_device; +} + +bool radio_device_loader_is_external(const SubGhzDevice* radio_device) { + furi_assert(radio_device); + return (radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)); +} + +void radio_device_loader_end(const SubGhzDevice* radio_device) { + furi_assert(radio_device); + radio_device_loader_power_off(); + if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) { + subghz_devices_end(radio_device); + } +} \ No newline at end of file diff --git a/applications/external/weather_station/helpers/radio_device_loader.h b/applications/external/weather_station/helpers/radio_device_loader.h new file mode 100644 index 000000000..bae4bacf2 --- /dev/null +++ b/applications/external/weather_station/helpers/radio_device_loader.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +/** SubGhzRadioDeviceType */ +typedef enum { + SubGhzRadioDeviceTypeInternal, + SubGhzRadioDeviceTypeExternalCC1101, +} SubGhzRadioDeviceType; + +const SubGhzDevice* radio_device_loader_set( + const SubGhzDevice* current_radio_device, + SubGhzRadioDeviceType radio_device_type); + +bool radio_device_loader_is_external(const SubGhzDevice* radio_device); + +void radio_device_loader_end(const SubGhzDevice* radio_device); \ No newline at end of file diff --git a/applications/external/weather_station/scenes/weather_station_receiver.c b/applications/external/weather_station/scenes/weather_station_receiver.c index e76810430..76d808e7e 100644 --- a/applications/external/weather_station/scenes/weather_station_receiver.c +++ b/applications/external/weather_station/scenes/weather_station_receiver.c @@ -48,13 +48,18 @@ static void weather_station_scene_receiver_update_statusbar(void* context) { app->ws_receiver, furi_string_get_cstr(frequency_str), furi_string_get_cstr(modulation_str), - furi_string_get_cstr(history_stat_str)); + furi_string_get_cstr(history_stat_str), + radio_device_loader_is_external(app->txrx->radio_device)); furi_string_free(frequency_str); furi_string_free(modulation_str); } else { ws_view_receiver_add_data_statusbar( - app->ws_receiver, furi_string_get_cstr(history_stat_str), "", ""); + app->ws_receiver, + furi_string_get_cstr(history_stat_str), + "", + "", + radio_device_loader_is_external(app->txrx->radio_device)); } furi_string_free(history_stat_str); } @@ -196,7 +201,7 @@ bool weather_station_scene_receiver_on_event(void* context, SceneManagerEvent ev weather_station_scene_receiver_update_statusbar(app); } // Get current RSSI - float rssi = furi_hal_subghz_get_rssi(); + float rssi = subghz_devices_get_rssi(app->txrx->radio_device); ws_view_receiver_set_rssi(app->ws_receiver, rssi); if(app->txrx->txrx_state == WSTxRxStateRx) { diff --git a/applications/external/weather_station/views/weather_station_receiver.c b/applications/external/weather_station/views/weather_station_receiver.c index e994e7830..a29ff68f6 100644 --- a/applications/external/weather_station/views/weather_station_receiver.c +++ b/applications/external/weather_station/views/weather_station_receiver.c @@ -61,6 +61,7 @@ typedef struct { uint16_t history_item; WSReceiverBarShow bar_show; uint8_t u_rssi; + bool external_redio; } WSReceiverModel; void ws_view_receiver_set_rssi(WSReceiver* instance, float rssi) { @@ -154,7 +155,8 @@ void ws_view_receiver_add_data_statusbar( WSReceiver* ws_receiver, const char* frequency_str, const char* preset_str, - const char* history_stat_str) { + const char* history_stat_str, + bool external) { furi_assert(ws_receiver); with_view_model( ws_receiver->view, @@ -163,6 +165,7 @@ void ws_view_receiver_add_data_statusbar( furi_string_set_str(model->frequency_str, frequency_str); furi_string_set_str(model->preset_str, preset_str); furi_string_set_str(model->history_stat_str, history_stat_str); + model->external_redio = external; }, true); } @@ -202,7 +205,7 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) { FuriString* str_buff; str_buff = furi_string_alloc(); - bool ext_module = furi_hal_subghz_get_radio_type(); + // bool ext_module = furi_hal_subghz_get_radio_type(); WSReceiverMenuItem* item_menu; @@ -228,11 +231,12 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) { canvas_set_color(canvas, ColorBlack); if(model->history_item == 0) { - canvas_draw_icon(canvas, 0, 0, ext_module ? &I_Fishing_123x52 : &I_Scanning_123x52); + canvas_draw_icon( + canvas, 0, 0, model->external_redio ? &I_Fishing_123x52 : &I_Scanning_123x52); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 63, 46, "Scanning..."); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 44, 10, ext_module ? "Ext" : "Int"); + canvas_draw_str(canvas, 44, 10, model->external_redio ? "Ext" : "Int"); } // Draw RSSI @@ -408,6 +412,7 @@ WSReceiver* ws_view_receiver_alloc() { model->history_stat_str = furi_string_alloc(); model->bar_show = WSReceiverBarShowDefault; model->history = malloc(sizeof(WSReceiverHistory)); + model->external_redio = false; WSReceiverMenuItemArray_init(model->history->data); }, true); diff --git a/applications/external/weather_station/views/weather_station_receiver.h b/applications/external/weather_station/views/weather_station_receiver.h index f81aa1f5e..ade61e2dc 100644 --- a/applications/external/weather_station/views/weather_station_receiver.h +++ b/applications/external/weather_station/views/weather_station_receiver.h @@ -27,7 +27,8 @@ void ws_view_receiver_add_data_statusbar( WSReceiver* ws_receiver, const char* frequency_str, const char* preset_str, - const char* history_stat_str); + const char* history_stat_str, + bool external); void ws_view_receiver_add_item_to_menu(WSReceiver* ws_receiver, const char* name, uint8_t type); diff --git a/applications/external/weather_station/weather_station_app.c b/applications/external/weather_station/weather_station_app.c index 8bea4961d..2305fa77b 100644 --- a/applications/external/weather_station/weather_station_app.c +++ b/applications/external/weather_station/weather_station_app.c @@ -98,6 +98,14 @@ WeatherStationApp* weather_station_app_alloc() { app->txrx->environment, (void*)&weather_station_protocol_registry); app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment); + subghz_devices_init(); + + app->txrx->radio_device = + radio_device_loader_set(app->txrx->radio_device, SubGhzRadioDeviceTypeExternalCC1101); + + subghz_devices_reset(app->txrx->radio_device); + subghz_devices_idle(app->txrx->radio_device); + subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable); subghz_worker_set_overrun_callback( app->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); @@ -105,15 +113,6 @@ WeatherStationApp* weather_station_app_alloc() { app->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); subghz_worker_set_context(app->txrx->worker, app->txrx->receiver); - // Enable power for External CC1101 if it is connected - furi_hal_subghz_enable_ext_power(); - // Auto switch to internal radio if external radio is not available - furi_delay_ms(15); - if(!furi_hal_subghz_check_radio()) { - furi_hal_subghz_select_radio_type(SubGhzRadioInternal); - furi_hal_subghz_init_radio_type(SubGhzRadioInternal); - } - furi_hal_power_suppress_charge_enter(); scene_manager_next_scene(app->scene_manager, WeatherStationSceneStart); @@ -124,13 +123,10 @@ WeatherStationApp* weather_station_app_alloc() { void weather_station_app_free(WeatherStationApp* app) { furi_assert(app); - //CC1101 off - ws_sleep(app); + subghz_devices_sleep(app->txrx->radio_device); + radio_device_loader_end(app->txrx->radio_device); - // Disable power for External CC1101 if it was enabled and module is connected - furi_hal_subghz_disable_ext_power(); - // Reinit SPI handles for internal radio / nfc - furi_hal_subghz_init_radio_type(SubGhzRadioInternal); + subghz_devices_deinit(); // Submenu view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewSubmenu); diff --git a/applications/external/weather_station/weather_station_app_i.c b/applications/external/weather_station/weather_station_app_i.c index 7236b6625..e98c61ee5 100644 --- a/applications/external/weather_station/weather_station_app_i.c +++ b/applications/external/weather_station/weather_station_app_i.c @@ -54,29 +54,28 @@ void ws_get_frequency_modulation( void ws_begin(WeatherStationApp* app, uint8_t* preset_data) { furi_assert(app); - UNUSED(preset_data); - furi_hal_subghz_reset(); - furi_hal_subghz_idle(); - furi_hal_subghz_load_custom_preset(preset_data); - furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + subghz_devices_reset(app->txrx->radio_device); + subghz_devices_idle(app->txrx->radio_device); + subghz_devices_load_preset(app->txrx->radio_device, FuriHalSubGhzPresetCustom, preset_data); app->txrx->txrx_state = WSTxRxStateIDLE; } uint32_t ws_rx(WeatherStationApp* app, uint32_t frequency) { furi_assert(app); - if(!furi_hal_subghz_is_frequency_valid(frequency)) { + if(!subghz_devices_is_frequency_valid(app->txrx->radio_device, frequency)) { furi_crash("WeatherStation: Incorrect RX frequency."); } furi_assert( app->txrx->txrx_state != WSTxRxStateRx && app->txrx->txrx_state != WSTxRxStateSleep); - furi_hal_subghz_idle(); - uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - furi_hal_subghz_flush_rx(); - furi_hal_subghz_rx(); + subghz_devices_idle(app->txrx->radio_device); + uint32_t value = subghz_devices_set_frequency(app->txrx->radio_device, frequency); + subghz_devices_flush_rx(app->txrx->radio_device); + subghz_devices_set_rx(app->txrx->radio_device); + + subghz_devices_start_async_rx( + app->txrx->radio_device, subghz_worker_rx_callback, app->txrx->worker); - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, app->txrx->worker); subghz_worker_start(app->txrx->worker); app->txrx->txrx_state = WSTxRxStateRx; return value; @@ -85,7 +84,7 @@ uint32_t ws_rx(WeatherStationApp* app, uint32_t frequency) { void ws_idle(WeatherStationApp* app) { furi_assert(app); furi_assert(app->txrx->txrx_state != WSTxRxStateSleep); - furi_hal_subghz_idle(); + subghz_devices_idle(app->txrx->radio_device); app->txrx->txrx_state = WSTxRxStateIDLE; } @@ -94,15 +93,15 @@ void ws_rx_end(WeatherStationApp* app) { furi_assert(app->txrx->txrx_state == WSTxRxStateRx); if(subghz_worker_is_running(app->txrx->worker)) { subghz_worker_stop(app->txrx->worker); - furi_hal_subghz_stop_async_rx(); + subghz_devices_stop_async_rx(app->txrx->radio_device); } - furi_hal_subghz_idle(); + subghz_devices_idle(app->txrx->radio_device); app->txrx->txrx_state = WSTxRxStateIDLE; } void ws_sleep(WeatherStationApp* app) { furi_assert(app); - furi_hal_subghz_sleep(); + subghz_devices_sleep(app->txrx->radio_device); app->txrx->txrx_state = WSTxRxStateSleep; } @@ -125,7 +124,7 @@ void ws_hopper_update(WeatherStationApp* app) { float rssi = -127.0f; if(app->txrx->hopper_state != WSHopperStateRSSITimeOut) { // See RSSI Calculation timings in CC1101 17.3 RSSI - rssi = furi_hal_subghz_get_rssi(); + rssi = subghz_devices_get_rssi(app->txrx->radio_device); // Stay if RSSI is high enough if(rssi > -90.0f) { diff --git a/applications/external/weather_station/weather_station_app_i.h b/applications/external/weather_station/weather_station_app_i.h index 41e248112..0950f5975 100644 --- a/applications/external/weather_station/weather_station_app_i.h +++ b/applications/external/weather_station/weather_station_app_i.h @@ -20,11 +20,14 @@ #include #include +#include "helpers/radio_device_loader.h" + typedef struct WeatherStationApp WeatherStationApp; struct WeatherStationTxRx { SubGhzWorker* worker; + const SubGhzDevice* radio_device; SubGhzEnvironment* environment; SubGhzReceiver* receiver; SubGhzRadioPreset* preset;