mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 13:58:36 -07:00
Merge pull request #557 from ALEEF02/analyzer-decoder
SubGHz Analyzer - Modulation switching
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t center_freq;
|
uint32_t center_freq;
|
||||||
uint8_t width;
|
uint8_t width;
|
||||||
|
uint8_t modulation;
|
||||||
uint8_t band;
|
uint8_t band;
|
||||||
uint8_t vscroll;
|
uint8_t vscroll;
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ typedef struct {
|
|||||||
uint32_t spacing;
|
uint32_t spacing;
|
||||||
|
|
||||||
bool mode_change;
|
bool mode_change;
|
||||||
|
bool modulation_change;
|
||||||
|
|
||||||
float max_rssi;
|
float max_rssi;
|
||||||
uint8_t max_rssi_dec;
|
uint8_t max_rssi_dec;
|
||||||
@@ -147,6 +149,24 @@ static void spectrum_analyzer_render_callback(Canvas* const canvas, void* ctx) {
|
|||||||
snprintf(tmp_str, 21, "Mode: %s", temp_mode_str);
|
snprintf(tmp_str, 21, "Mode: %s", temp_mode_str);
|
||||||
canvas_draw_str_aligned(canvas, 127, 4, AlignRight, AlignTop, tmp_str);
|
canvas_draw_str_aligned(canvas, 127, 4, AlignRight, AlignTop, tmp_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(model->modulation_change) {
|
||||||
|
char temp_mod_str[12];
|
||||||
|
switch(model->modulation) {
|
||||||
|
case NARROW_MODULATION:
|
||||||
|
strncpy(temp_mod_str, "NARROW", 12);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strncpy(temp_mod_str, "DEFAULT", 12);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current modulation label
|
||||||
|
char tmp_str[27];
|
||||||
|
snprintf(tmp_str, 27, "Modulation: %s", temp_mod_str);
|
||||||
|
canvas_draw_str_aligned(canvas, 127, 4, AlignRight, AlignTop, tmp_str);
|
||||||
|
}
|
||||||
|
|
||||||
// Draw cross and label
|
// Draw cross and label
|
||||||
if(model->max_rssi > PEAK_THRESHOLD) {
|
if(model->max_rssi > PEAK_THRESHOLD) {
|
||||||
// Compress height to max of 64 values (255>>2)
|
// Compress height to max of 64 values (255>>2)
|
||||||
@@ -194,8 +214,8 @@ static void spectrum_analyzer_render_callback(Canvas* const canvas, void* ctx) {
|
|||||||
|
|
||||||
static void spectrum_analyzer_input_callback(InputEvent* input_event, void* ctx) {
|
static void spectrum_analyzer_input_callback(InputEvent* input_event, void* ctx) {
|
||||||
SpectrumAnalyzer* spectrum_analyzer = ctx;
|
SpectrumAnalyzer* spectrum_analyzer = ctx;
|
||||||
// Only handle short presses
|
// Handle short and long presses
|
||||||
if(input_event->type == InputTypeShort) {
|
if(input_event->type == InputTypeShort || input_event->type == InputTypeLong) {
|
||||||
furi_message_queue_put(spectrum_analyzer->event_queue, input_event, FuriWaitForever);
|
furi_message_queue_put(spectrum_analyzer->event_queue, input_event, FuriWaitForever);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,6 +396,7 @@ SpectrumAnalyzer* spectrum_analyzer_alloc() {
|
|||||||
|
|
||||||
model->center_freq = DEFAULT_FREQ;
|
model->center_freq = DEFAULT_FREQ;
|
||||||
model->width = WIDE;
|
model->width = WIDE;
|
||||||
|
model->modulation = DEFAULT_MODULATION;
|
||||||
model->band = BAND_400;
|
model->band = BAND_400;
|
||||||
|
|
||||||
model->vscroll = DEFAULT_VSCROLL;
|
model->vscroll = DEFAULT_VSCROLL;
|
||||||
@@ -470,65 +491,96 @@ int32_t spectrum_analyzer_app(void* p) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(input.key) {
|
switch(input.type) {
|
||||||
case InputKeyUp:
|
case InputTypeShort:
|
||||||
model->vscroll = MAX(model->vscroll - vstep, MIN_VSCROLL);
|
switch(input.key) {
|
||||||
FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll);
|
case InputKeyUp:
|
||||||
break;
|
model->vscroll = MAX(model->vscroll - vstep, MIN_VSCROLL);
|
||||||
case InputKeyDown:
|
FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll);
|
||||||
model->vscroll = MIN(model->vscroll + vstep, MAX_VSCROLL);
|
|
||||||
FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll);
|
|
||||||
break;
|
|
||||||
case InputKeyRight:
|
|
||||||
model->center_freq += hstep;
|
|
||||||
FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq);
|
|
||||||
spectrum_analyzer_calculate_frequencies(model);
|
|
||||||
spectrum_analyzer_worker_set_frequencies(
|
|
||||||
spectrum_analyzer->worker, model->channel0_frequency, model->spacing, model->width);
|
|
||||||
break;
|
|
||||||
case InputKeyLeft:
|
|
||||||
model->center_freq -= hstep;
|
|
||||||
spectrum_analyzer_calculate_frequencies(model);
|
|
||||||
spectrum_analyzer_worker_set_frequencies(
|
|
||||||
spectrum_analyzer->worker, model->channel0_frequency, model->spacing, model->width);
|
|
||||||
FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq);
|
|
||||||
break;
|
|
||||||
case InputKeyOk: {
|
|
||||||
switch(model->width) {
|
|
||||||
case WIDE:
|
|
||||||
model->width = NARROW;
|
|
||||||
break;
|
break;
|
||||||
case NARROW:
|
case InputKeyDown:
|
||||||
model->width = ULTRANARROW;
|
model->vscroll = MIN(model->vscroll + vstep, MAX_VSCROLL);
|
||||||
|
FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll);
|
||||||
break;
|
break;
|
||||||
case ULTRANARROW:
|
case InputKeyRight:
|
||||||
model->width = PRECISE;
|
model->center_freq += hstep;
|
||||||
|
FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq);
|
||||||
|
spectrum_analyzer_calculate_frequencies(model);
|
||||||
|
spectrum_analyzer_worker_set_frequencies(
|
||||||
|
spectrum_analyzer->worker, model->channel0_frequency, model->spacing, model->width);
|
||||||
break;
|
break;
|
||||||
case PRECISE:
|
case InputKeyLeft:
|
||||||
model->width = ULTRAWIDE;
|
model->center_freq -= hstep;
|
||||||
|
spectrum_analyzer_calculate_frequencies(model);
|
||||||
|
spectrum_analyzer_worker_set_frequencies(
|
||||||
|
spectrum_analyzer->worker, model->channel0_frequency, model->spacing, model->width);
|
||||||
|
FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq);
|
||||||
break;
|
break;
|
||||||
case ULTRAWIDE:
|
case InputKeyOk: {
|
||||||
model->width = WIDE;
|
switch(model->width) {
|
||||||
|
case WIDE:
|
||||||
|
model->width = NARROW;
|
||||||
|
break;
|
||||||
|
case NARROW:
|
||||||
|
model->width = ULTRANARROW;
|
||||||
|
break;
|
||||||
|
case ULTRANARROW:
|
||||||
|
model->width = PRECISE;
|
||||||
|
break;
|
||||||
|
case PRECISE:
|
||||||
|
model->width = ULTRAWIDE;
|
||||||
|
break;
|
||||||
|
case ULTRAWIDE:
|
||||||
|
model->width = WIDE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
model->width = WIDE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
model->mode_change = true;
|
||||||
|
view_port_update(spectrum_analyzer->view_port);
|
||||||
|
|
||||||
|
furi_delay_ms(1000);
|
||||||
|
|
||||||
|
model->mode_change = false;
|
||||||
|
spectrum_analyzer_calculate_frequencies(model);
|
||||||
|
spectrum_analyzer_worker_set_frequencies(
|
||||||
|
spectrum_analyzer->worker, model->channel0_frequency, model->spacing, model->width);
|
||||||
|
FURI_LOG_D("Spectrum", "Width: %u", model->width);
|
||||||
|
break;
|
||||||
|
case InputKeyBack:
|
||||||
|
exit_loop = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
model->width = WIDE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
model->mode_change = true;
|
|
||||||
view_port_update(spectrum_analyzer->view_port);
|
|
||||||
|
|
||||||
furi_delay_ms(1000);
|
|
||||||
|
|
||||||
model->mode_change = false;
|
|
||||||
spectrum_analyzer_calculate_frequencies(model);
|
|
||||||
spectrum_analyzer_worker_set_frequencies(
|
|
||||||
spectrum_analyzer->worker, model->channel0_frequency, model->spacing, model->width);
|
|
||||||
FURI_LOG_D("Spectrum", "Width: %u", model->width);
|
|
||||||
break;
|
break;
|
||||||
case InputKeyBack:
|
case InputTypeLong:
|
||||||
exit_loop = true;
|
switch(input.key) {
|
||||||
|
case InputKeyOk:
|
||||||
|
FURI_LOG_D("Spectrum", "InputTypeLong");
|
||||||
|
switch(model->modulation) {
|
||||||
|
case NARROW_MODULATION:
|
||||||
|
model->modulation = DEFAULT_MODULATION;
|
||||||
|
break;
|
||||||
|
case DEFAULT_MODULATION:
|
||||||
|
default:
|
||||||
|
model->modulation = NARROW_MODULATION;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
model->modulation_change = true;
|
||||||
|
view_port_update(spectrum_analyzer->view_port);
|
||||||
|
|
||||||
|
furi_delay_ms(1000);
|
||||||
|
|
||||||
|
model->modulation_change = false;
|
||||||
|
spectrum_analyzer_worker_set_modulation(
|
||||||
|
spectrum_analyzer->worker,
|
||||||
|
spectrum_analyzer->model->modulation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -78,3 +78,7 @@
|
|||||||
|
|
||||||
#define UPPER(a, b, c) ((((a) - (b) + ((c) / 2)) / (c)) * (c))
|
#define UPPER(a, b, c) ((((a) - (b) + ((c) / 2)) / (c)) * (c))
|
||||||
#define LOWER(a, b, c) ((((a) + (b)) / (c)) * (c))
|
#define LOWER(a, b, c) ((((a) + (b)) / (c)) * (c))
|
||||||
|
|
||||||
|
/* Modulation references */
|
||||||
|
#define DEFAULT_MODULATION 0
|
||||||
|
#define NARROW_MODULATION 1
|
||||||
@@ -20,6 +20,7 @@ struct SpectrumAnalyzerWorker {
|
|||||||
uint32_t channel0_frequency;
|
uint32_t channel0_frequency;
|
||||||
uint32_t spacing;
|
uint32_t spacing;
|
||||||
uint8_t width;
|
uint8_t width;
|
||||||
|
uint8_t modulation;
|
||||||
float max_rssi;
|
float max_rssi;
|
||||||
uint8_t max_rssi_dec;
|
uint8_t max_rssi_dec;
|
||||||
uint8_t max_rssi_channel;
|
uint8_t max_rssi_channel;
|
||||||
@@ -66,18 +67,45 @@ static int32_t spectrum_analyzer_worker_thread(void* context) {
|
|||||||
subghz_devices_flush_rx(instance->radio_device);
|
subghz_devices_flush_rx(instance->radio_device);
|
||||||
subghz_devices_set_rx(instance->radio_device);
|
subghz_devices_set_rx(instance->radio_device);
|
||||||
|
|
||||||
const uint8_t radio_config[] = {
|
// Default modulation
|
||||||
|
const uint8_t default_modulation[] = {
|
||||||
|
|
||||||
|
/* Frequency Synthesizer Control */
|
||||||
CC1101_FSCTRL0,
|
CC1101_FSCTRL0,
|
||||||
0x00,
|
0x00,
|
||||||
CC1101_FSCTRL1,
|
CC1101_FSCTRL1,
|
||||||
0x12,
|
0x12, // IF = (26*10^6) / (2^10) * 0x12 = 304687.5 Hz
|
||||||
|
|
||||||
CC1101_AGCCTRL2,
|
|
||||||
0xC0,
|
|
||||||
|
|
||||||
|
// Modem Configuration
|
||||||
|
// CC1101_MDMCFG0,
|
||||||
|
// 0x00, // Channel spacing is 25kHz
|
||||||
|
// CC1101_MDMCFG1,
|
||||||
|
// 0x00, // Channel spacing is 25kHz
|
||||||
|
// CC1101_MDMCFG2,
|
||||||
|
// 0x30, // Format ASK/OOK, No preamble/sync
|
||||||
|
// CC1101_MDMCFG3,
|
||||||
|
// 0x32, // Data rate is 121.399 kBaud
|
||||||
CC1101_MDMCFG4,
|
CC1101_MDMCFG4,
|
||||||
0x6C,
|
0x6C, // Rx BW filter is 270.83 kHz
|
||||||
|
|
||||||
|
/* Frequency Offset Compensation Configuration */
|
||||||
|
// CC1101_FOCCFG,
|
||||||
|
// 0x18, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||||
|
|
||||||
|
/* Automatic Gain Control */
|
||||||
|
// CC1101_AGCCTRL0,
|
||||||
|
// 0x91, // 10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary
|
||||||
|
// CC1101_AGCCTRL1,
|
||||||
|
// 0x0, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||||
|
CC1101_AGCCTRL2,
|
||||||
|
0xC0, // 03 - The 3 highest DVGA gain settings can not be used; 000 - MAX LNA+LNA2; 000 - MAIN_TARGET 24 dB
|
||||||
|
|
||||||
|
/* Frontend configuration */
|
||||||
|
// CC1101_FREND0,
|
||||||
|
// 0x11, // Adjusts current TX LO buffer + high is PATABLE[1]
|
||||||
|
// CC1101_FREND1,
|
||||||
|
// 0xB6, //
|
||||||
|
|
||||||
CC1101_TEST2,
|
CC1101_TEST2,
|
||||||
0x88,
|
0x88,
|
||||||
CC1101_TEST1,
|
CC1101_TEST1,
|
||||||
@@ -97,16 +125,82 @@ static int32_t spectrum_analyzer_worker_thread(void* context) {
|
|||||||
0x00,
|
0x00,
|
||||||
0x00,
|
0x00,
|
||||||
0x00,
|
0x00,
|
||||||
0x00,
|
0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Narrow modulation
|
||||||
|
const uint8_t narrow_modulation[] = {
|
||||||
|
|
||||||
|
/* Frequency Synthesizer Control */
|
||||||
|
CC1101_FSCTRL0,
|
||||||
|
0x00,
|
||||||
|
CC1101_FSCTRL1,
|
||||||
|
0x00, // IF = (26*10^6) / (2^10) * 0x00 = 0 Hz
|
||||||
|
|
||||||
|
// Modem Configuration
|
||||||
|
// CC1101_MDMCFG0,
|
||||||
|
// 0x00, // Channel spacing is 25kHz
|
||||||
|
// CC1101_MDMCFG1,
|
||||||
|
// 0x00, // Channel spacing is 25kHz
|
||||||
|
// CC1101_MDMCFG2,
|
||||||
|
// 0x30, // Format ASK/OOK, No preamble/sync
|
||||||
|
// CC1101_MDMCFG3,
|
||||||
|
// 0x32, // Data rate is 121.399 kBaud
|
||||||
|
CC1101_MDMCFG4,
|
||||||
|
0xFC, // Rx BW filter is 58.04 kHz
|
||||||
|
|
||||||
|
/* Frequency Offset Compensation Configuration */
|
||||||
|
// CC1101_FOCCFG,
|
||||||
|
// 0x18, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||||
|
|
||||||
|
/* Automatic Gain Control */
|
||||||
|
CC1101_AGCCTRL0,
|
||||||
|
0x30, // 00 - NO hysteresis, symmetric dead zone, high gain ; 11 - 32 samples agc; 00 - Normal AGC, 00 - 8dB boundary
|
||||||
|
CC1101_AGCCTRL1,
|
||||||
|
0x0, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||||
|
CC1101_AGCCTRL2,
|
||||||
|
0x84, // 02 - The 2 highest DVGA gain settings can not be used; 000 - MAX LNA+LNA2; 100 - MAIN_TARGET 36 dB
|
||||||
|
|
||||||
|
/* Frontend configuration */
|
||||||
|
// CC1101_FREND0,
|
||||||
|
// 0x11, // Adjusts current TX LO buffer + high is PATABLE[1]
|
||||||
|
// CC1101_FREND1,
|
||||||
|
// 0xB6, //
|
||||||
|
|
||||||
|
CC1101_TEST2,
|
||||||
|
0x88,
|
||||||
|
CC1101_TEST1,
|
||||||
|
0x31,
|
||||||
|
CC1101_TEST0,
|
||||||
|
0x09,
|
||||||
|
|
||||||
|
/* End */
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
|
||||||
|
// ook_async_patable
|
||||||
|
0x00,
|
||||||
|
0xC0, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t* modulations[] = {default_modulation, narrow_modulation};
|
||||||
|
|
||||||
while(instance->should_work) {
|
while(instance->should_work) {
|
||||||
furi_delay_ms(50);
|
furi_delay_ms(50);
|
||||||
|
|
||||||
// FURI_LOG_T("SpectrumWorker", "spectrum_analyzer_worker_thread: Worker Loop");
|
// FURI_LOG_T("SpectrumWorker", "spectrum_analyzer_worker_thread: Worker Loop");
|
||||||
subghz_devices_idle(instance->radio_device);
|
subghz_devices_idle(instance->radio_device);
|
||||||
subghz_devices_load_preset(
|
subghz_devices_load_preset(
|
||||||
instance->radio_device, FuriHalSubGhzPresetCustom, (uint8_t*)radio_config);
|
instance->radio_device, FuriHalSubGhzPresetCustom, (uint8_t*)modulations[instance->modulation]);
|
||||||
|
//subghz_devices_load_preset(
|
||||||
|
// instance->radio_device, FuriHalSubGhzPresetCustom, (uint8_t*)default_modulation);
|
||||||
|
//furi_hal_subghz_load_custom_preset(modulations[instance->modulation]);
|
||||||
|
|
||||||
// TODO: Check filter!
|
// TODO: Check filter!
|
||||||
// spectrum_analyzer_worker_set_filter(instance);
|
// spectrum_analyzer_worker_set_filter(instance);
|
||||||
@@ -222,6 +316,19 @@ void spectrum_analyzer_worker_set_frequencies(
|
|||||||
instance->width = width;
|
instance->width = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void spectrum_analyzer_worker_set_modulation(
|
||||||
|
SpectrumAnalyzerWorker* instance,
|
||||||
|
uint8_t modulation) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
FURI_LOG_D(
|
||||||
|
"SpectrumWorker",
|
||||||
|
"spectrum_analyzer_worker_set_modulation - modulation = %u",
|
||||||
|
modulation);
|
||||||
|
|
||||||
|
instance->modulation = modulation;
|
||||||
|
}
|
||||||
|
|
||||||
void spectrum_analyzer_worker_start(SpectrumAnalyzerWorker* instance) {
|
void spectrum_analyzer_worker_start(SpectrumAnalyzerWorker* instance) {
|
||||||
FURI_LOG_D("Spectrum", "spectrum_analyzer_worker_start");
|
FURI_LOG_D("Spectrum", "spectrum_analyzer_worker_start");
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ void spectrum_analyzer_worker_set_frequencies(
|
|||||||
uint32_t spacing,
|
uint32_t spacing,
|
||||||
uint8_t width);
|
uint8_t width);
|
||||||
|
|
||||||
|
void spectrum_analyzer_worker_set_modulation(
|
||||||
|
SpectrumAnalyzerWorker* instance,
|
||||||
|
uint8_t modulation);
|
||||||
|
|
||||||
void spectrum_analyzer_worker_start(SpectrumAnalyzerWorker* instance);
|
void spectrum_analyzer_worker_start(SpectrumAnalyzerWorker* instance);
|
||||||
|
|
||||||
void spectrum_analyzer_worker_stop(SpectrumAnalyzerWorker* instance);
|
void spectrum_analyzer_worker_stop(SpectrumAnalyzerWorker* instance);
|
||||||
|
|||||||
Reference in New Issue
Block a user