From 91ab2fd98422b681803d176be8e054e73225574b Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Wed, 21 Jun 2023 14:00:25 +0300 Subject: [PATCH] Pocsaq pager App: new radio driver --- .../helpers/radio_device_loader.c | 66 +++++++++++++++++++ .../helpers/radio_device_loader.h | 17 +++++ .../external/pocsag_pager/pocsag_pager_app.c | 29 ++++---- .../pocsag_pager/pocsag_pager_app_i.c | 39 ++++++----- .../pocsag_pager/pocsag_pager_app_i.h | 4 ++ .../scenes/pocsag_pager_receiver.c | 7 +- .../views/pocsag_pager_receiver.c | 13 ++-- .../views/pocsag_pager_receiver.h | 2 + 8 files changed, 138 insertions(+), 39 deletions(-) create mode 100644 applications/external/pocsag_pager/helpers/radio_device_loader.c create mode 100644 applications/external/pocsag_pager/helpers/radio_device_loader.h diff --git a/applications/external/pocsag_pager/helpers/radio_device_loader.c b/applications/external/pocsag_pager/helpers/radio_device_loader.c new file mode 100644 index 000000000..ce0920755 --- /dev/null +++ b/applications/external/pocsag_pager/helpers/radio_device_loader.c @@ -0,0 +1,66 @@ +#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(); + } + + is_connect = subghz_devices_is_connect(subghz_devices_get_by_name(name)); + + 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/pocsag_pager/helpers/radio_device_loader.h b/applications/external/pocsag_pager/helpers/radio_device_loader.h new file mode 100644 index 000000000..bae4bacf2 --- /dev/null +++ b/applications/external/pocsag_pager/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/pocsag_pager/pocsag_pager_app.c b/applications/external/pocsag_pager/pocsag_pager_app.c index 1013164f2..70ff49f1a 100644 --- a/applications/external/pocsag_pager/pocsag_pager_app.c +++ b/applications/external/pocsag_pager/pocsag_pager_app.c @@ -91,6 +91,16 @@ POCSAGPagerApp* pocsag_pager_app_alloc() { app->txrx->preset = malloc(sizeof(SubGhzRadioPreset)); app->txrx->preset->name = furi_string_alloc(); + furi_hal_power_suppress_charge_enter(); + + // Radio Devices init & load + 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); + // Custom Presets load without using config file FlipperFormat* temp_fm_preset = flipper_format_string_alloc(); @@ -122,17 +132,6 @@ POCSAGPagerApp* pocsag_pager_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, POCSAGPagerSceneStart); return app; @@ -141,13 +140,11 @@ POCSAGPagerApp* pocsag_pager_app_alloc() { void pocsag_pager_app_free(POCSAGPagerApp* app) { furi_assert(app); - //CC1101 off + // Radio Devices sleep & off pcsg_sleep(app); + 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, POCSAGPagerViewSubmenu); diff --git a/applications/external/pocsag_pager/pocsag_pager_app_i.c b/applications/external/pocsag_pager/pocsag_pager_app_i.c index ff73ab50e..8dda1d8b6 100644 --- a/applications/external/pocsag_pager/pocsag_pager_app_i.c +++ b/applications/external/pocsag_pager/pocsag_pager_app_i.c @@ -36,29 +36,34 @@ void pcsg_get_frequency_modulation( void pcsg_begin(POCSAGPagerApp* 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); + + // furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); app->txrx->txrx_state = PCSGTxRxStateIDLE; } uint32_t pcsg_rx(POCSAGPagerApp* 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("POCSAGPager: Incorrect RX frequency."); } furi_assert( app->txrx->txrx_state != PCSGTxRxStateRx && app->txrx->txrx_state != PCSGTxRxStateSleep); - 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); - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, app->txrx->worker); + // Not need. init in subghz_devices_start_async_tx + // furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + + 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); subghz_worker_start(app->txrx->worker); app->txrx->txrx_state = PCSGTxRxStateRx; return value; @@ -67,7 +72,7 @@ uint32_t pcsg_rx(POCSAGPagerApp* app, uint32_t frequency) { void pcsg_idle(POCSAGPagerApp* app) { furi_assert(app); furi_assert(app->txrx->txrx_state != PCSGTxRxStateSleep); - furi_hal_subghz_idle(); + subghz_devices_idle(app->txrx->radio_device); app->txrx->txrx_state = PCSGTxRxStateIDLE; } @@ -76,15 +81,15 @@ void pcsg_rx_end(POCSAGPagerApp* app) { furi_assert(app->txrx->txrx_state == PCSGTxRxStateRx); 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 = PCSGTxRxStateIDLE; } void pcsg_sleep(POCSAGPagerApp* app) { furi_assert(app); - furi_hal_subghz_sleep(); + subghz_devices_sleep(app->txrx->radio_device); app->txrx->txrx_state = PCSGTxRxStateSleep; } @@ -110,7 +115,7 @@ void pcsg_hopper_update(POCSAGPagerApp* app) { float rssi = -127.0f; if(app->txrx->hopper_state != PCSGHopperStateRSSITimeOut) { // 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/pocsag_pager/pocsag_pager_app_i.h b/applications/external/pocsag_pager/pocsag_pager_app_i.h index 8a0426dc5..c31e5ae1a 100644 --- a/applications/external/pocsag_pager/pocsag_pager_app_i.h +++ b/applications/external/pocsag_pager/pocsag_pager_app_i.h @@ -1,6 +1,7 @@ #pragma once #include "helpers/pocsag_pager_types.h" +#include "helpers/radio_device_loader.h" #include "scenes/pocsag_pager_scene.h" #include @@ -19,6 +20,7 @@ #include #include #include +#include typedef struct POCSAGPagerApp POCSAGPagerApp; @@ -35,6 +37,8 @@ struct POCSAGPagerTxRx { uint8_t hopper_timeout; uint8_t hopper_idx_frequency; PCSGRxKeyState rx_key_state; + + const SubGhzDevice* radio_device; }; typedef struct POCSAGPagerTxRx POCSAGPagerTxRx; diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c b/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c index 658b70fea..cc2abd7e0 100644 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c +++ b/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c @@ -112,6 +112,8 @@ void pocsag_pager_scene_receiver_on_enter(void* context) { } pcsg_view_receiver_set_lock(app->pcsg_receiver, app->lock); + pcsg_view_receiver_set_ext_module_state( + app->pcsg_receiver, radio_device_loader_is_external(app->txrx->radio_device)); //Load history to receiver pcsg_view_receiver_exit(app->pcsg_receiver); @@ -136,6 +138,7 @@ void pocsag_pager_scene_receiver_on_enter(void* context) { }; if((app->txrx->txrx_state == PCSGTxRxStateIDLE) || (app->txrx->txrx_state == PCSGTxRxStateSleep)) { + // Start RX pcsg_begin( app, subghz_setting_get_preset_data_by_name( @@ -157,7 +160,7 @@ bool pocsag_pager_scene_receiver_on_event(void* context, SceneManagerEvent event // Stop CC1101 Rx if(app->txrx->txrx_state == PCSGTxRxStateRx) { pcsg_rx_end(app); - pcsg_sleep(app); + pcsg_idle(app); }; app->txrx->hopper_state = PCSGHopperStateOFF; app->txrx->idx_menu_chosen = 0; @@ -196,7 +199,7 @@ bool pocsag_pager_scene_receiver_on_event(void* context, SceneManagerEvent event pocsag_pager_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); pcsg_receiver_rssi(app->pcsg_receiver, rssi); if(app->txrx->txrx_state == PCSGTxRxStateRx) { diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver.c b/applications/external/pocsag_pager/views/pocsag_pager_receiver.c index 64939a956..fed752de9 100644 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver.c +++ b/applications/external/pocsag_pager/views/pocsag_pager_receiver.c @@ -61,6 +61,7 @@ typedef struct { uint16_t history_item; PCSGReceiverBarShow bar_show; uint8_t u_rssi; + bool ext_module; } PCSGReceiverModel; void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi) { @@ -98,6 +99,12 @@ void pcsg_view_receiver_set_lock(PCSGReceiver* pcsg_receiver, PCSGLock lock) { } } +void pcsg_view_receiver_set_ext_module_state(PCSGReceiver* pcsg_receiver, bool is_external) { + furi_assert(pcsg_receiver); + with_view_model( + pcsg_receiver->view, PCSGReceiverModel * model, { model->ext_module = is_external; }, true); +} + void pcsg_view_receiver_set_callback( PCSGReceiver* pcsg_receiver, PCSGReceiverCallback callback, @@ -207,8 +214,6 @@ void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) { FuriString* str_buff; str_buff = furi_string_alloc(); - bool ext_module = furi_hal_subghz_get_radio_type(); - PCSGReceiverMenuItem* item_menu; for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) { @@ -234,11 +239,11 @@ void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* 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->ext_module ? &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->ext_module ? "Ext" : "Int"); } // Draw RSSI diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver.h b/applications/external/pocsag_pager/views/pocsag_pager_receiver.h index a13f5cdc7..87900748f 100644 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver.h +++ b/applications/external/pocsag_pager/views/pocsag_pager_receiver.h @@ -12,6 +12,8 @@ void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi); void pcsg_view_receiver_set_lock(PCSGReceiver* pcsg_receiver, PCSGLock keyboard); +void pcsg_view_receiver_set_ext_module_state(PCSGReceiver* pcsg_receiver, bool is_external); + void pcsg_view_receiver_set_callback( PCSGReceiver* pcsg_receiver, PCSGReceiverCallback callback,