소스 검색

Protoview: Add back tweaks and fixes

Willy-JL 2 년 전
부모
커밋
c5cff2e5a6

+ 13 - 3
protoview/app.c

@@ -108,6 +108,8 @@ static void app_switch_view(ProtoViewApp *app, ProtoViewCurrentView switchto) {
 /* Allocate the application state and initialize a number of stuff.
  * This is called in the entry point to create the application state. */
 ProtoViewApp* protoview_app_alloc() {
+    furi_hal_power_suppress_charge_enter();
+
     ProtoViewApp *app = malloc(sizeof(ProtoViewApp));
 
     // Init shared data structures
@@ -157,7 +159,13 @@ ProtoViewApp* protoview_app_alloc() {
     app->frequency = subghz_setting_get_default_frequency(app->setting);
     app->modulation = 0; /* Defaults to ProtoViewModulations[0]. */
 
-    furi_hal_power_suppress_charge_enter();
+    // Init & set radio_device
+    subghz_devices_init();
+    app->radio_device =
+        radio_device_loader_set(app->radio_device, SubGhzRadioDeviceTypeExternalCC1101);
+
+    subghz_devices_reset(app->radio_device);
+    subghz_devices_idle(app->radio_device);
     app->running = 1;
 
     return app;
@@ -169,8 +177,10 @@ ProtoViewApp* protoview_app_alloc() {
 void protoview_app_free(ProtoViewApp *app) {
     furi_assert(app);
 
-    // Put CC1101 on sleep, this also restores charging.
-    radio_sleep(app);
+    subghz_devices_sleep(app->radio_device);
+    radio_device_loader_end(app->radio_device);
+
+    subghz_devices_deinit();
 
     // View related.
     view_port_enabled_set(app->view_port, false);

+ 5 - 1
protoview/app.h

@@ -20,12 +20,14 @@
 #include <lib/subghz/registry.h>
 #include "raw_samples.h"
 
+#include "helpers/radio_device_loader.h"
+
 #define TAG "ProtoView"
 #define PROTOVIEW_RAW_VIEW_DEFAULT_SCALE 100 // 100us is 1 pixel by default
 #define BITMAP_SEEK_NOT_FOUND UINT32_MAX // Returned by function as sentinel
 #define PROTOVIEW_VIEW_PRIVDATA_LEN 64 // View specific private data len
 
-#define DEBUG_MSG 1
+#define DEBUG_MSG 0
 
 /* Forward declarations. */
 
@@ -132,6 +134,8 @@ struct ProtoViewApp {
     ProtoViewTxRx *txrx;     /* Radio state. */
     SubGhzSetting *setting;  /* A list of valid frequencies. */
 
+    const SubGhzDevice* radio_device;
+
     /* Generic app state. */
     int running;             /* Once false exists the app. */
     uint32_t signal_bestlen; /* Longest coherent signal observed so far. */

+ 34 - 31
protoview/app_subghz.c

@@ -38,24 +38,23 @@ ProtoViewModulation ProtoViewModulations[] = {
  * subghz system and put it into idle state. */
 void radio_begin(ProtoViewApp* app) {
     furi_assert(app);
-    furi_hal_subghz_reset();
-    furi_hal_subghz_idle();
-
-    /* Power circuits are noisy. Suppressing the charge while we use
-     * ProtoView will improve the RF performances. */
-    furi_hal_power_suppress_charge_enter();
+    subghz_devices_reset(app->radio_device);
+    subghz_devices_idle(app->radio_device);
 
     /* The CC1101 preset can be either one of the standard presets, if
      * the modulation "custom" field is NULL, or a custom preset we
      * defined in custom_presets.h. */
     if (ProtoViewModulations[app->modulation].custom == NULL) {
-        furi_hal_subghz_load_preset(
-            ProtoViewModulations[app->modulation].preset);
+        subghz_devices_load_preset(
+            app->radio_device, ProtoViewModulations[app->modulation].preset, NULL);
     } else {
-        furi_hal_subghz_load_custom_preset(
+        subghz_devices_load_preset(
+            app->radio_device,
+            FuriHalSubGhzPresetCustom,
             ProtoViewModulations[app->modulation].custom);
     }
-    furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
+    furi_hal_gpio_init(
+        subghz_devices_get_data_gpio(app->radio_device), GpioModeInput, GpioPullNo, GpioSpeedLow);
     app->txrx->txrx_state = TxRxStateIDLE;
 }
 
@@ -74,21 +73,26 @@ void protoview_rx_callback(bool level, uint32_t duration, void *context) {
 /* Setup the CC1101 to start receiving using a background worker. */
 uint32_t radio_rx(ProtoViewApp* app) {
     furi_assert(app);
-    if(!furi_hal_subghz_is_frequency_valid(app->frequency)) {
+    if(!subghz_devices_is_frequency_valid(app->radio_device, app->frequency)) {
         furi_crash(TAG" Incorrect RX frequency.");
     }
 
     if (app->txrx->txrx_state == TxRxStateRx) return app->frequency;
 
-    furi_hal_subghz_idle(); /* Put it into idle state in case it is sleeping. */
-    uint32_t value = furi_hal_subghz_set_frequency_and_path(app->frequency);
+    subghz_devices_idle(app->radio_device); /* Put it into idle state in case it is sleeping. */
+    uint32_t value = subghz_devices_set_frequency(app->radio_device, app->frequency);
     FURI_LOG_E(TAG, "Switched to frequency: %lu", value);
-    furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
-    furi_hal_subghz_flush_rx();
-    furi_hal_subghz_rx();
+
+    subghz_devices_flush_rx(app->radio_device);
+    subghz_devices_set_rx(app->radio_device);
     if (!app->txrx->debug_timer_sampling) {
-        furi_hal_subghz_start_async_rx(protoview_rx_callback, NULL);
+        subghz_devices_start_async_rx(app->radio_device, protoview_rx_callback, NULL);
     } else {
+        furi_hal_gpio_init(
+            subghz_devices_get_data_gpio(app->radio_device),
+            GpioModeInput,
+            GpioPullNo,
+            GpioSpeedLow);
         raw_sampling_worker_start(app);
     }
     app->txrx->txrx_state = TxRxStateRx;
@@ -101,12 +105,12 @@ void radio_rx_end(ProtoViewApp* app) {
 
     if (app->txrx->txrx_state == TxRxStateRx) {
         if (!app->txrx->debug_timer_sampling) {
-            furi_hal_subghz_stop_async_rx();
+            subghz_devices_stop_async_rx(app->radio_device);
         } else {
             raw_sampling_worker_stop(app);
         }
     }
-    furi_hal_subghz_idle();
+    subghz_devices_idle(app->radio_device);
     app->txrx->txrx_state = TxRxStateIDLE;
 }
 
@@ -118,9 +122,8 @@ void radio_sleep(ProtoViewApp* app) {
          * chip into sleep. */
         radio_rx_end(app);
     }
-    furi_hal_subghz_sleep();
+    subghz_devices_sleep(app->radio_device);
     app->txrx->txrx_state = TxRxStateSleep;
-    furi_hal_power_suppress_charge_exit();
 }
 
 /* =============================== Transmission ============================= */
@@ -134,16 +137,14 @@ void radio_tx_signal(ProtoViewApp *app, FuriHalSubGhzAsyncTxCallback data_feeder
     if (oldstate == TxRxStateRx) radio_rx_end(app);
     radio_begin(app);
 
-    furi_hal_subghz_idle();
-    uint32_t value = furi_hal_subghz_set_frequency_and_path(app->frequency);
+    subghz_devices_idle(app->radio_device);
+    uint32_t value = subghz_devices_set_frequency(app->radio_device, app->frequency);
     FURI_LOG_E(TAG, "Switched to frequency: %lu", value);
-    furi_hal_gpio_write(&gpio_cc1101_g0, false);
-    furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
 
-    furi_hal_subghz_start_async_tx(data_feeder, ctx);
-    while(!furi_hal_subghz_is_async_tx_complete()) furi_delay_ms(10);
-    furi_hal_subghz_stop_async_tx();
-    furi_hal_subghz_idle();
+    subghz_devices_start_async_tx(app->radio_device, data_feeder, ctx);
+    while(!subghz_devices_is_async_complete_tx(app->radio_device)) furi_delay_ms(10);
+    subghz_devices_stop_async_tx(app->radio_device);
+    subghz_devices_idle(app->radio_device);
 
     radio_begin(app);
     if (oldstate == TxRxStateRx) radio_rx(app);
@@ -159,7 +160,7 @@ void radio_tx_signal(ProtoViewApp *app, FuriHalSubGhzAsyncTxCallback data_feeder
 void protoview_timer_isr(void *ctx) {
     ProtoViewApp *app = ctx;
 
-    bool level = furi_hal_gpio_read(&gpio_cc1101_g0);
+    bool level = furi_hal_gpio_read(subghz_devices_get_data_gpio(app->radio_device));
     if (app->txrx->last_g0_value != level) {
         uint32_t now = DWT->CYCCNT;
         uint32_t dur = now - app->txrx->last_g0_change_time;
@@ -175,6 +176,8 @@ void protoview_timer_isr(void *ctx) {
 void raw_sampling_worker_start(ProtoViewApp *app) {
     UNUSED(app);
 
+    furi_hal_bus_enable(FuriHalBusTIM2);
+
     LL_TIM_InitTypeDef tim_init = {
         .Prescaler = 63,    /* CPU frequency is ~64Mhz. */
         .CounterMode = LL_TIM_COUNTERMODE_UP,
@@ -197,6 +200,6 @@ void raw_sampling_worker_stop(ProtoViewApp *app) {
     LL_TIM_DisableCounter(TIM2);
     LL_TIM_DisableIT_UPDATE(TIM2);
     furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
-    LL_TIM_DeInit(TIM2);
+    furi_hal_bus_disable(FuriHalBusTIM2);
     FURI_CRITICAL_EXIT();
 }

+ 1 - 1
protoview/application.fam

@@ -8,5 +8,5 @@ App(
     stack_size=8*1024,
     order=50,
     fap_icon="appicon.png",
-    fap_category="Tools",
+    fap_category="Sub-GHz",
 )

+ 1 - 1
protoview/custom_presets.h

@@ -1,4 +1,4 @@
-#include <cc1101.h>
+#include <cc1101_regs.h>
 /* ========================== DATA RATE SETTINGS ===============================
  *
  * This is how to configure registers MDMCFG3 and MDMCFG4.

+ 64 - 0
protoview/helpers/radio_device_loader.c

@@ -0,0 +1,64 @@
+#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;
+}
+
+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);
+    }
+}

+ 15 - 0
protoview/helpers/radio_device_loader.h

@@ -0,0 +1,15 @@
+#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);
+
+void radio_device_loader_end(const SubGhzDevice* radio_device);

+ 7 - 7
protoview/protocols/unknown.c

@@ -253,7 +253,7 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
         linecode = LineCodeManchester;
         start1 = tmp1;
         msgbits = manchester_bits*2;
-        FURI_LOG_E(TAG, "MANCHESTER START: %lu", tmp1);
+        //FURI_LOG_T(TAG, "MANCHESTER START: %lu", tmp1);s
     }
 
     if (linecode == LineCodeNone) return false;
@@ -286,12 +286,12 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
                                * transfer all that is needed, like a message
                                * terminator (that we don't detect). */
 
-    if (preamble_found)
-        FURI_LOG_E(TAG, "PREAMBLE AT: %lu", preamble_start);
-    FURI_LOG_E(TAG, "START: %lu", info->start_off);
-    FURI_LOG_E(TAG, "MSGBITS: %lu", msgbits);
-    FURI_LOG_E(TAG, "DATASTART: %lu", start1);
-    FURI_LOG_E(TAG, "PULSES: %lu", info->pulses_count);
+    // if (preamble_found)
+    //     FURI_LOG_T(TAG, "PREAMBLE AT: %lu", preamble_start);
+    // FURI_LOG_T(TAG, "START: %lu", info->start_off);
+    // FURI_LOG_T(TAG, "MSGBITS: %lu", msgbits);
+    // FURI_LOG_T(TAG, "DATASTART: %lu", start1);
+    // FURI_LOG_T(TAG, "PULSES: %lu", info->pulses_count);
 
     /* We think there is a message and we know where it starts and the
      * line code used. We can turn it into bits and bytes. */

+ 12 - 2
protoview/signal_file.c

@@ -43,11 +43,21 @@ bool save_signal(ProtoViewApp *app, const char *filename) {
             furi_string_printf(custom,
                 "Custom_preset_module: CC1101\n"
                  "Custom_preset_data: ");
-            for (int j = 0; regs[j]; j += 2) {
+
+            /* We will know the size of the preset data once we reach the end
+             * of the registers (null address). For now it's INT_MAX. */
+            int preset_data_size = INT_MAX;
+            bool patable_reached = false;
+            for(int j = 0; j <= preset_data_size; j += 2) {
+                // End reached, set the size to write the remaining 8 bytes (PATABLE)
+                if(!patable_reached && regs[j] == 0) {
+                    preset_data_size = j + 8;
+                    patable_reached = true;
+                }
                 furi_string_cat_printf(custom, "%02X %02X ",
                     (int)regs[j], (int)regs[j+1]);
             }
-            size_t len = furi_string_size(file_content);
+            size_t len = furi_string_size(custom);
             furi_string_set_char(custom,len-1,'\n');
             furi_string_cat(file_content,custom);
             furi_string_free(custom);

+ 18 - 8
protoview/view_direct_sampling.c

@@ -2,7 +2,7 @@
  * See the LICENSE file for information about the license. */
 
 #include "app.h"
-#include <cc1101.h>
+#include <cc1101_regs.h>
 
 static void direct_sampling_timer_start(ProtoViewApp *app);
 static void direct_sampling_timer_stop(ProtoViewApp *app);
@@ -93,15 +93,18 @@ void view_enter_direct_sampling(ProtoViewApp *app) {
     if (app->txrx->txrx_state == TxRxStateRx &&
         !app->txrx->debug_timer_sampling)
     {
-        furi_hal_subghz_stop_async_rx();
+        subghz_devices_stop_async_rx(app->radio_device);
 
         /* To read data asynchronously directly from the view, we need
          * to put the CC1101 back into reception mode (the previous call
          * to stop the async RX will put it into idle) and configure the
          * G0 pin for reading. */
-        furi_hal_subghz_rx();
-        furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo,
-                           GpioSpeedLow);
+        subghz_devices_set_rx(app->radio_device);
+        furi_hal_gpio_init(
+            subghz_devices_get_data_gpio(app->radio_device),
+            GpioModeInput,
+            GpioPullNo,
+            GpioSpeedLow);
     } else {
         raw_sampling_worker_stop(app);
     }
@@ -122,8 +125,13 @@ void view_exit_direct_sampling(ProtoViewApp *app) {
     if (app->txrx->txrx_state == TxRxStateRx &&
         !app->txrx->debug_timer_sampling)
     {
-        furi_hal_subghz_start_async_rx(protoview_rx_callback, NULL);
+        subghz_devices_start_async_rx(app->radio_device, protoview_rx_callback, NULL);
     } else {
+        furi_hal_gpio_init(
+            subghz_devices_get_data_gpio(app->radio_device),
+            GpioModeInput,
+            GpioPullNo,
+            GpioSpeedLow);
         raw_sampling_worker_start(app);
     }
 }
@@ -135,7 +143,7 @@ static void ds_timer_isr(void *ctx) {
     DirectSamplingViewPrivData *privdata = app->view_privdata;
 
     if (app->direct_sampling_enabled) {
-        bool level = furi_hal_gpio_read(&gpio_cc1101_g0);
+        bool level = furi_hal_gpio_read(subghz_devices_get_data_gpio(app->radio_device));
         bitmap_set(privdata->captured,CAPTURED_BITMAP_BYTES,
                    privdata->captured_idx,level);
         privdata->captured_idx = (privdata->captured_idx+1) %
@@ -147,6 +155,8 @@ static void ds_timer_isr(void *ctx) {
 static void direct_sampling_timer_start(ProtoViewApp *app) {
     DirectSamplingViewPrivData *privdata = app->view_privdata;
 
+    furi_hal_bus_enable(FuriHalBusTIM2);
+
     LL_TIM_InitTypeDef tim_init = {
         .Prescaler = 63,    /* CPU frequency is ~64Mhz. */
         .CounterMode = LL_TIM_COUNTERMODE_UP,
@@ -168,6 +178,6 @@ static void direct_sampling_timer_stop(ProtoViewApp *app) {
     LL_TIM_DisableCounter(TIM2);
     LL_TIM_DisableIT_UPDATE(TIM2);
     furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
-    LL_TIM_DeInit(TIM2);
+    furi_hal_bus_disable(FuriHalBusTIM2);
     FURI_CRITICAL_EXIT();
 }

+ 2 - 7
protoview/view_info.c

@@ -3,7 +3,7 @@
 
 #include "app.h"
 #include <gui/view.h>
-#include <lib/toolbox/random_name.h>
+#include <toolbox/name_generator.h>
 
 /* This view has subviews accessible navigating up/down. This
  * enumaration is used to track the currently active subview. */
@@ -161,12 +161,7 @@ void str_replace(char *buf, char c1, char c2) {
 
 /* Set a random filename the user can edit. */
 void set_signal_random_filename(ProtoViewApp *app, char *buf, size_t buflen) {
-    char suffix[6];
-    set_random_name(suffix,sizeof(suffix));
-    snprintf(buf,buflen,"%.10s-%s-%d",app->msg_info->decoder->name,suffix,rand()%1000);
-    str_replace(buf,' ','_');
-    str_replace(buf,'-','_');
-    str_replace(buf,'/','_');
+    name_generator_make_auto(buf, buflen, app->msg_info->decoder->name);
 }
 
 /* ========================== Signal transmission =========================== */