Skip to content

Commit

Permalink
Weather station: new external radio driver (#3)
Browse files Browse the repository at this point in the history
* Weather station: new external radio driver
  • Loading branch information
gid9798 authored Jul 6, 2023
1 parent cb08b84 commit b1850fd
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "radio_device_loader.h"

#include <applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h>
#include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>

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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <lib/subghz/devices/devices.h>

/** 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);
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;

Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
26 changes: 11 additions & 15 deletions applications/external/weather_station/weather_station_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,22 +98,21 @@ 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);
subghz_worker_set_pair_callback(
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);
Expand All @@ -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);
Expand Down
33 changes: 16 additions & 17 deletions applications/external/weather_station/weather_station_app_i.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand All @@ -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;
}

Expand All @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions applications/external/weather_station/weather_station_app_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
#include <lib/subghz/transmitter.h>
#include <lib/subghz/registry.h>

#include "helpers/radio_device_loader.h"

typedef struct WeatherStationApp WeatherStationApp;

struct WeatherStationTxRx {
SubGhzWorker* worker;

const SubGhzDevice* radio_device;
SubGhzEnvironment* environment;
SubGhzReceiver* receiver;
SubGhzRadioPreset* preset;
Expand Down

0 comments on commit b1850fd

Please sign in to comment.