Skip to content

Commit 2c9a5ca

Browse files
authored
WS: External radio support CC1101 (#200)
1 parent c91677a commit 2c9a5ca

File tree

12 files changed

+152
-40
lines changed

12 files changed

+152
-40
lines changed

weather_station/.catalog/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## 1.7
2+
- Added external CC1101 radio modules support
13
## 1.6
24
- Add protocol Acurite 5n1 Weather Station
35
## 1.5

weather_station/application.fam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ App(
77
requires=["gui"],
88
stack_size=4 * 1024,
99
fap_description="Receive weather data from a wide range of supported Sub-1GHz remote sensor",
10-
fap_version="1.6",
10+
fap_version="1.7",
1111
fap_icon="weather_station_10px.png",
1212
fap_category="Sub-GHz",
1313
fap_icon_assets="images",
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "radio_device_loader.h"
2+
3+
#include <applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h>
4+
#include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
5+
6+
static void radio_device_loader_power_on() {
7+
uint8_t attempts = 0;
8+
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
9+
furi_hal_power_enable_otg();
10+
//CC1101 power-up time
11+
furi_delay_ms(10);
12+
}
13+
}
14+
15+
static void radio_device_loader_power_off() {
16+
if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg();
17+
}
18+
19+
bool radio_device_loader_is_connect_external(const char* name) {
20+
bool is_connect = false;
21+
bool is_otg_enabled = furi_hal_power_is_otg_enabled();
22+
23+
if(!is_otg_enabled) {
24+
radio_device_loader_power_on();
25+
}
26+
27+
const SubGhzDevice* device = subghz_devices_get_by_name(name);
28+
if(device) {
29+
is_connect = subghz_devices_is_connect(device);
30+
}
31+
32+
if(!is_otg_enabled) {
33+
radio_device_loader_power_off();
34+
}
35+
return is_connect;
36+
}
37+
38+
const SubGhzDevice* radio_device_loader_set(
39+
const SubGhzDevice* current_radio_device,
40+
SubGhzRadioDeviceType radio_device_type) {
41+
const SubGhzDevice* radio_device;
42+
43+
if(radio_device_type == SubGhzRadioDeviceTypeExternalCC1101 &&
44+
radio_device_loader_is_connect_external(SUBGHZ_DEVICE_CC1101_EXT_NAME)) {
45+
radio_device_loader_power_on();
46+
radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_EXT_NAME);
47+
subghz_devices_begin(radio_device);
48+
} else if(current_radio_device == NULL) {
49+
radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
50+
} else {
51+
radio_device_loader_end(current_radio_device);
52+
radio_device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
53+
}
54+
55+
return radio_device;
56+
}
57+
58+
bool radio_device_loader_is_external(const SubGhzDevice* radio_device) {
59+
furi_assert(radio_device);
60+
return (radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME));
61+
}
62+
63+
void radio_device_loader_end(const SubGhzDevice* radio_device) {
64+
furi_assert(radio_device);
65+
radio_device_loader_power_off();
66+
if(radio_device != subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME)) {
67+
subghz_devices_end(radio_device);
68+
}
69+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include <lib/subghz/devices/devices.h>
4+
5+
/** SubGhzRadioDeviceType */
6+
typedef enum {
7+
SubGhzRadioDeviceTypeInternal,
8+
SubGhzRadioDeviceTypeExternalCC1101,
9+
} SubGhzRadioDeviceType;
10+
11+
const SubGhzDevice* radio_device_loader_set(
12+
const SubGhzDevice* current_radio_device,
13+
SubGhzRadioDeviceType radio_device_type);
14+
15+
bool radio_device_loader_is_external(const SubGhzDevice* radio_device);
16+
17+
void radio_device_loader_end(const SubGhzDevice* radio_device);
966 Bytes
Loading

weather_station/protocols/acurite_986.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ void ws_protocol_decoder_acurite_986_reset(void* context) {
105105
static bool ws_protocol_acurite_986_check(WSProtocolDecoderAcurite_986* instance) {
106106
if(!instance->decoder.decode_data) return false;
107107
uint8_t msg[] = {
108-
instance->decoder.decode_data >> 32,
109-
instance->decoder.decode_data >> 24,
110-
instance->decoder.decode_data >> 16,
111-
instance->decoder.decode_data >> 8 };
108+
instance->decoder.decode_data >> 32,
109+
instance->decoder.decode_data >> 24,
110+
instance->decoder.decode_data >> 16,
111+
instance->decoder.decode_data >> 8};
112112

113113
uint8_t crc = subghz_protocol_blocks_crc8(msg, 4, 0x07, 0x00);
114114
return (crc == (instance->decoder.decode_data & 0xFF));
@@ -122,7 +122,8 @@ static void ws_protocol_acurite_986_remote_controller(WSBlockGeneric* instance)
122122
int temp;
123123

124124
instance->id = subghz_protocol_blocks_reverse_key(instance->data >> 24, 8);
125-
instance->id = (instance->id << 8) | subghz_protocol_blocks_reverse_key(instance->data >> 16, 8);
125+
instance->id = (instance->id << 8) |
126+
subghz_protocol_blocks_reverse_key(instance->data >> 16, 8);
126127
instance->battery_low = (instance->data >> 14) & 1;
127128
instance->channel = ((instance->data >> 15) & 1) + 1;
128129

@@ -152,7 +153,7 @@ void ws_protocol_decoder_acurite_986_feed(void* context, bool level, uint32_t du
152153

153154
case Acurite_986DecoderStepSync1:
154155
if(DURATION_DIFF(duration, ws_protocol_acurite_986_const.te_long) <
155-
ws_protocol_acurite_986_const.te_delta * 15) {
156+
ws_protocol_acurite_986_const.te_delta * 15) {
156157
if(!level) {
157158
instance->decoder.parser_step = Acurite_986DecoderStepSync2;
158159
}
@@ -163,7 +164,7 @@ void ws_protocol_decoder_acurite_986_feed(void* context, bool level, uint32_t du
163164

164165
case Acurite_986DecoderStepSync2:
165166
if(DURATION_DIFF(duration, ws_protocol_acurite_986_const.te_long) <
166-
ws_protocol_acurite_986_const.te_delta * 15) {
167+
ws_protocol_acurite_986_const.te_delta * 15) {
167168
if(!level) {
168169
instance->decoder.parser_step = Acurite_986DecoderStepSync3;
169170
}
@@ -174,7 +175,7 @@ void ws_protocol_decoder_acurite_986_feed(void* context, bool level, uint32_t du
174175

175176
case Acurite_986DecoderStepSync3:
176177
if(DURATION_DIFF(duration, ws_protocol_acurite_986_const.te_long) <
177-
ws_protocol_acurite_986_const.te_delta * 15) {
178+
ws_protocol_acurite_986_const.te_delta * 15) {
178179
if(!level) {
179180
instance->decoder.parser_step = Acurite_986DecoderStepSaveDuration;
180181
}
@@ -195,7 +196,7 @@ void ws_protocol_decoder_acurite_986_feed(void* context, bool level, uint32_t du
195196
case Acurite_986DecoderStepCheckDuration:
196197
if(!level) {
197198
if(DURATION_DIFF(duration, ws_protocol_acurite_986_const.te_short) <
198-
ws_protocol_acurite_986_const.te_delta * 10) {
199+
ws_protocol_acurite_986_const.te_delta * 10) {
199200
if(duration < ws_protocol_acurite_986_const.te_short) {
200201
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
201202
instance->decoder.parser_step = Acurite_986DecoderStepSaveDuration;
@@ -206,8 +207,9 @@ void ws_protocol_decoder_acurite_986_feed(void* context, bool level, uint32_t du
206207
} else {
207208
//Found syncPostfix
208209
instance->decoder.parser_step = Acurite_986DecoderStepReset;
209-
if((instance->decoder.decode_count_bit == ws_protocol_acurite_986_const.min_count_bit_for_found) &&
210-
ws_protocol_acurite_986_check(instance)) {
210+
if((instance->decoder.decode_count_bit ==
211+
ws_protocol_acurite_986_const.min_count_bit_for_found) &&
212+
ws_protocol_acurite_986_check(instance)) {
211213
instance->generic.data = instance->decoder.decode_data;
212214
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
213215
ws_protocol_acurite_986_remote_controller(&instance->generic);
@@ -245,9 +247,7 @@ SubGhzProtocolStatus
245247
furi_assert(context);
246248
WSProtocolDecoderAcurite_986* instance = context;
247249
return ws_block_generic_deserialize_check_count_bit(
248-
&instance->generic,
249-
flipper_format,
250-
ws_protocol_acurite_986_const.min_count_bit_for_found);
250+
&instance->generic, flipper_format, ws_protocol_acurite_986_const.min_count_bit_for_found);
251251
}
252252

253253
void ws_protocol_decoder_acurite_986_get_string(void* context, FuriString* output) {

weather_station/scenes/weather_station_receiver.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,18 @@ static void weather_station_scene_receiver_update_statusbar(void* context) {
4848
app->ws_receiver,
4949
furi_string_get_cstr(frequency_str),
5050
furi_string_get_cstr(modulation_str),
51-
furi_string_get_cstr(history_stat_str));
51+
furi_string_get_cstr(history_stat_str),
52+
radio_device_loader_is_external(app->txrx->radio_device));
5253

5354
furi_string_free(frequency_str);
5455
furi_string_free(modulation_str);
5556
} else {
5657
ws_view_receiver_add_data_statusbar(
57-
app->ws_receiver, furi_string_get_cstr(history_stat_str), "", "");
58+
app->ws_receiver,
59+
furi_string_get_cstr(history_stat_str),
60+
"",
61+
"",
62+
radio_device_loader_is_external(app->txrx->radio_device));
5863
}
5964
furi_string_free(history_stat_str);
6065
}
@@ -196,7 +201,7 @@ bool weather_station_scene_receiver_on_event(void* context, SceneManagerEvent ev
196201
weather_station_scene_receiver_update_statusbar(app);
197202
}
198203
// Get current RSSI
199-
float rssi = furi_hal_subghz_get_rssi();
204+
float rssi = subghz_devices_get_rssi(app->txrx->radio_device);
200205
ws_view_receiver_set_rssi(app->ws_receiver, rssi);
201206

202207
if(app->txrx->txrx_state == WSTxRxStateRx) {

weather_station/views/weather_station_receiver.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ typedef struct {
6161
uint16_t history_item;
6262
WSReceiverBarShow bar_show;
6363
uint8_t u_rssi;
64+
bool external_radio;
6465
} WSReceiverModel;
6566

6667
void ws_view_receiver_set_rssi(WSReceiver* instance, float rssi) {
@@ -154,7 +155,8 @@ void ws_view_receiver_add_data_statusbar(
154155
WSReceiver* ws_receiver,
155156
const char* frequency_str,
156157
const char* preset_str,
157-
const char* history_stat_str) {
158+
const char* history_stat_str,
159+
bool external) {
158160
furi_assert(ws_receiver);
159161
with_view_model(
160162
ws_receiver->view,
@@ -163,6 +165,7 @@ void ws_view_receiver_add_data_statusbar(
163165
furi_string_set_str(model->frequency_str, frequency_str);
164166
furi_string_set_str(model->preset_str, preset_str);
165167
furi_string_set_str(model->history_stat_str, history_stat_str);
168+
model->external_radio = external;
166169
},
167170
true);
168171
}
@@ -226,10 +229,12 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) {
226229
canvas_set_color(canvas, ColorBlack);
227230

228231
if(model->history_item == 0) {
229-
canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
232+
canvas_draw_icon(
233+
canvas, 0, 0, model->external_radio ? &I_Fishing_123x52 : &I_Scanning_123x52);
230234
canvas_set_font(canvas, FontPrimary);
231235
canvas_draw_str(canvas, 63, 46, "Scanning...");
232236
canvas_set_font(canvas, FontSecondary);
237+
canvas_draw_str(canvas, 44, 10, model->external_radio ? "Ext" : "Int");
233238
}
234239

235240
// Draw RSSI
@@ -405,6 +410,7 @@ WSReceiver* ws_view_receiver_alloc() {
405410
model->history_stat_str = furi_string_alloc();
406411
model->bar_show = WSReceiverBarShowDefault;
407412
model->history = malloc(sizeof(WSReceiverHistory));
413+
model->external_radio = false;
408414
WSReceiverMenuItemArray_init(model->history->data);
409415
},
410416
true);

weather_station/views/weather_station_receiver.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ void ws_view_receiver_add_data_statusbar(
2727
WSReceiver* ws_receiver,
2828
const char* frequency_str,
2929
const char* preset_str,
30-
const char* history_stat_str);
30+
const char* history_stat_str,
31+
bool external);
3132

3233
void ws_view_receiver_add_item_to_menu(WSReceiver* ws_receiver, const char* name, uint8_t type);
3334

weather_station/weather_station_app.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,14 @@ WeatherStationApp* weather_station_app_alloc() {
9898
app->txrx->environment, (void*)&weather_station_protocol_registry);
9999
app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment);
100100

101+
subghz_devices_init();
102+
103+
app->txrx->radio_device =
104+
radio_device_loader_set(app->txrx->radio_device, SubGhzRadioDeviceTypeExternalCC1101);
105+
106+
subghz_devices_reset(app->txrx->radio_device);
107+
subghz_devices_idle(app->txrx->radio_device);
108+
101109
subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable);
102110
subghz_worker_set_overrun_callback(
103111
app->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset);
@@ -115,8 +123,10 @@ WeatherStationApp* weather_station_app_alloc() {
115123
void weather_station_app_free(WeatherStationApp* app) {
116124
furi_assert(app);
117125

118-
//CC1101 off
119-
ws_sleep(app);
126+
subghz_devices_sleep(app->txrx->radio_device);
127+
radio_device_loader_end(app->txrx->radio_device);
128+
129+
subghz_devices_deinit();
120130

121131
// Submenu
122132
view_dispatcher_remove_view(app->view_dispatcher, WeatherStationViewSubmenu);

0 commit comments

Comments
 (0)