MX 2 лет назад
Родитель
Сommit
df8bafc012

+ 114 - 52
main_apps_sources/spectrum_analyzer/spectrum_analyzer.c

@@ -12,6 +12,7 @@
 typedef struct {
     uint32_t center_freq;
     uint8_t width;
+    uint8_t modulation;
     uint8_t band;
     uint8_t vscroll;
 
@@ -19,6 +20,7 @@ typedef struct {
     uint32_t spacing;
 
     bool mode_change;
+    bool modulation_change;
 
     float max_rssi;
     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);
         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
     if(model->max_rssi > PEAK_THRESHOLD) {
         // 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) {
     SpectrumAnalyzer* spectrum_analyzer = ctx;
-    // Only handle short presses
-    if(input_event->type == InputTypeShort) {
+    // Handle short and long presses
+    if(input_event->type == InputTypeShort || input_event->type == InputTypeLong) {
         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->width = WIDE;
+    model->modulation = DEFAULT_MODULATION;
     model->band = BAND_400;
 
     model->vscroll = DEFAULT_VSCROLL;
@@ -470,65 +491,106 @@ int32_t spectrum_analyzer_app(void* p) {
             break;
         }
 
-        switch(input.key) {
-        case InputKeyUp:
-            model->vscroll = MAX(model->vscroll - vstep, MIN_VSCROLL);
-            FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll);
-            break;
-        case InputKeyDown:
-            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;
+        switch(input.type) {
+        case InputTypeShort:
+            switch(input.key) {
+            case InputKeyUp:
+                model->vscroll = MAX(model->vscroll - vstep, MIN_VSCROLL);
+                FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll);
+                break;
+            case InputKeyDown:
+                model->vscroll = MIN(model->vscroll + vstep, MAX_VSCROLL);
+                FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll);
                 break;
-            case NARROW:
-                model->width = ULTRANARROW;
+            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 ULTRANARROW:
-                model->width = PRECISE;
+            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 PRECISE:
-                model->width = ULTRAWIDE;
+            case InputKeyOk: {
+                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 ULTRAWIDE:
-                model->width = WIDE;
+            case InputKeyBack:
+                exit_loop = true;
                 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;
+        case InputTypeLong:
+            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;
+            default:
+                break;
+            }
             break;
         default:
             break;

+ 5 - 1
main_apps_sources/spectrum_analyzer/spectrum_analyzer.h

@@ -77,4 +77,8 @@
 #define MID_900 848000000
 
 #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

+ 110 - 7
main_apps_sources/spectrum_analyzer/spectrum_analyzer_worker.c

@@ -20,6 +20,7 @@ struct SpectrumAnalyzerWorker {
     uint32_t channel0_frequency;
     uint32_t spacing;
     uint8_t width;
+    uint8_t modulation;
     float max_rssi;
     uint8_t max_rssi_dec;
     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_set_rx(instance->radio_device);
 
-    const uint8_t radio_config[] = {
+    // Default modulation
+    const uint8_t default_modulation[] = {
 
+        /* Frequency Synthesizer Control */
         CC1101_FSCTRL0,
         0x00,
         CC1101_FSCTRL1,
-        0x12,
+        0x12, // IF = (26*10^6) / (2^10) * 0x12 = 304687.5 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,
+        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,
+        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_MDMCFG4,
-        0x6C,
         CC1101_TEST2,
         0x88,
         CC1101_TEST1,
@@ -97,8 +125,69 @@ static int32_t spectrum_analyzer_worker_thread(void* context) {
         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) {
         furi_delay_ms(50);
@@ -106,7 +195,12 @@ static int32_t spectrum_analyzer_worker_thread(void* context) {
         // FURI_LOG_T("SpectrumWorker", "spectrum_analyzer_worker_thread: Worker Loop");
         subghz_devices_idle(instance->radio_device);
         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!
         // spectrum_analyzer_worker_set_filter(instance);
@@ -222,6 +316,15 @@ void spectrum_analyzer_worker_set_frequencies(
     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) {
     FURI_LOG_D("Spectrum", "spectrum_analyzer_worker_start");
 

+ 2 - 0
main_apps_sources/spectrum_analyzer/spectrum_analyzer_worker.h

@@ -28,6 +28,8 @@ void spectrum_analyzer_worker_set_frequencies(
     uint32_t spacing,
     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_stop(SpectrumAnalyzerWorker* instance);