فهرست منبع

SubGhz: allow refill attempt at the end of transmission (#1314)

あく 3 سال پیش
والد
کامیت
fb4d4011f4
2فایلهای تغییر یافته به همراه357 افزوده شده و 334 حذف شده
  1. 43 334
      firmware/targets/f7/furi_hal/furi_hal_subghz.c
  2. 314 0
      firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h

+ 43 - 334
firmware/targets/f7/furi_hal/furi_hal_subghz.c

@@ -1,7 +1,8 @@
 #include "furi_hal_subghz.h"
-#include "furi_hal_version.h"
-#include "furi_hal_rtc.h"
+#include "furi_hal_subghz_configs.h"
 
+#include <furi_hal_version.h>
+#include <furi_hal_rtc.h>
 #include <furi_hal_gpio.h>
 #include <furi_hal_spi.h>
 #include <furi_hal_interrupt.h>
@@ -15,317 +16,22 @@
 
 #define TAG "FuriHalSubGhz"
 
-static volatile SubGhzState furi_hal_subghz_state = SubGhzStateInit;
-static volatile SubGhzRegulation furi_hal_subghz_regulation = SubGhzRegulationTxRx;
-static volatile FuriHalSubGhzPreset furi_hal_subghz_preset = FuriHalSubGhzPresetIDLE;
-
-static const uint8_t furi_hal_subghz_preset_ook_270khz_async_regs[][2] = {
-    // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
-
-    /* GPIO GD0 */
-    {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
-
-    /* FIFO and internals */
-    {CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32
-
-    /* Packet engine */
-    {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
-
-    /* Frequency Synthesizer Control */
-    {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
-
-    // 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 3.79372 kBaud
-    {CC1101_MDMCFG4, 0x67}, // Rx BW filter is 270.833333kHz
-
-    /* Main Radio Control State Machine */
-    {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
-
-    /* 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,
-     0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
-    {CC1101_AGCCTRL1,
-     0x00}, // 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, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
-
-    /* Wake on radio and timeouts control */
-    {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
-
-    /* Frontend configuration */
-    {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1]
-    {CC1101_FREND1, 0xB6}, //
-
-    /* End  */
-    {0, 0},
-};
-
-static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = {
-    // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
-
-    /* GPIO GD0 */
-    {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
-
-    /* FIFO and internals */
-    {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION
-
-    /* Packet engine */
-    {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
-
-    /* Frequency Synthesizer Control */
-    {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
-
-    // 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 3.79372 kBaud
-    {CC1101_MDMCFG4, 0x17}, // Rx BW filter is 650.000kHz
-
-    /* Main Radio Control State Machine */
-    {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
-
-    /* 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_AGCTRL0,0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
-    // {CC1101_AGCTRL1,0x00}, // 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, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
-    //MAGN_TARGET for RX filter BW =< 100 kHz is 0x3. For higher RX filter BW's MAGN_TARGET is 0x7.
-    {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, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
-
-    /* Wake on radio and timeouts control */
-    {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
-
-    /* Frontend configuration */
-    {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1]
-    {CC1101_FREND1, 0xB6}, //
-
-    /* End  */
-    {0, 0},
-};
-static const uint8_t furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs[][2] = {
-
-    /* GPIO GD0 */
-    {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
-
-    /* Frequency Synthesizer Control */
-    {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
-
-    /* Packet engine */
-    {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
-    {CC1101_PKTCTRL1, 0x04},
-
-    // // Modem Configuration
-    {CC1101_MDMCFG0, 0x00},
-    {CC1101_MDMCFG1, 0x02},
-    {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
-    {CC1101_MDMCFG3, 0x83}, // Data rate is 4.79794 kBaud
-    {CC1101_MDMCFG4, 0x67}, //Rx BW filter is 270.833333 kHz
-    {CC1101_DEVIATN, 0x04}, //Deviation 2.380371 kHz
-
-    /* Main Radio Control State Machine */
-    {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
-
-    /* Frequency Offset Compensation Configuration */
-    {CC1101_FOCCFG,
-     0x16}, // 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,
-     0x00}, // 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, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
-
-    /* Wake on radio and timeouts control */
-    {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
-
-    /* Frontend configuration */
-    {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer
-    {CC1101_FREND1, 0x56},
-
-    /* End  */
-    {0, 0},
-};
-static const uint8_t furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs[][2] = {
-
-    /* GPIO GD0 */
-    {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
-
-    /* Frequency Synthesizer Control */
-    {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
-
-    /* Packet engine */
-    {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
-    {CC1101_PKTCTRL1, 0x04},
-
-    // // Modem Configuration
-    {CC1101_MDMCFG0, 0x00},
-    {CC1101_MDMCFG1, 0x02},
-    {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
-    {CC1101_MDMCFG3, 0x83}, // Data rate is 4.79794 kBaud
-    {CC1101_MDMCFG4, 0x67}, //Rx BW filter is 270.833333 kHz
-    {CC1101_DEVIATN, 0x47}, //Deviation 47.60742 kHz
-
-    /* Main Radio Control State Machine */
-    {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
-
-    /* Frequency Offset Compensation Configuration */
-    {CC1101_FOCCFG,
-     0x16}, // 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,
-     0x00}, // 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, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
-
-    /* Wake on radio and timeouts control */
-    {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
-
-    /* Frontend configuration */
-    {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer
-    {CC1101_FREND1, 0x56},
-
-    /* End  */
-    {0, 0},
-};
-static const uint8_t furi_hal_subghz_preset_msk_99_97kb_async_regs[][2] = {
-    /* GPIO GD0 */
-    {CC1101_IOCFG0, 0x06},
-
-    {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION
-    {CC1101_SYNC1, 0x46},
-    {CC1101_SYNC0, 0x4C},
-    {CC1101_ADDR, 0x00},
-    {CC1101_PKTLEN, 0x00},
-    {CC1101_CHANNR, 0x00},
-
-    {CC1101_PKTCTRL0, 0x05},
-
-    {CC1101_FSCTRL0, 0x23},
-    {CC1101_FSCTRL1, 0x06},
-
-    {CC1101_MDMCFG0, 0xF8},
-    {CC1101_MDMCFG1, 0x22},
-    {CC1101_MDMCFG2, 0x72},
-    {CC1101_MDMCFG3, 0xF8},
-    {CC1101_MDMCFG4, 0x5B},
-    {CC1101_DEVIATN, 0x47},
-
-    {CC1101_MCSM0, 0x18},
-    {CC1101_FOCCFG, 0x16},
-
-    {CC1101_AGCCTRL0, 0xB2},
-    {CC1101_AGCCTRL1, 0x00},
-    {CC1101_AGCCTRL2, 0xC7},
-
-    {CC1101_FREND0, 0x10},
-    {CC1101_FREND1, 0x56},
-
-    {CC1101_BSCFG, 0x1C},
-    {CC1101_FSTEST, 0x59},
-
-    /* End  */
-    {0, 0},
-};
-static const uint8_t furi_hal_subghz_preset_gfsk_9_99kb_async_regs[][2] = {
-
-    {CC1101_IOCFG0, 0x06}, //GDO0 Output Pin Configuration
-    {CC1101_FIFOTHR, 0x47}, //RX FIFO and TX FIFO Thresholds
-
-    //1 : CRC calculation in TX and CRC check in RX enabled,
-    //1 : Variable packet length mode. Packet length configured by the first byte after sync word
-    {CC1101_PKTCTRL0, 0x05},
-
-    {CC1101_FSCTRL1, 0x06}, //Frequency Synthesizer Control
-
-    {CC1101_SYNC1, 0x46},
-    {CC1101_SYNC0, 0x4C},
-    {CC1101_ADDR, 0x00},
-    {CC1101_PKTLEN, 0x00},
-
-    {CC1101_MDMCFG4, 0xC8}, //Modem Configuration 9.99
-    {CC1101_MDMCFG3, 0x93}, //Modem Configuration
-    {CC1101_MDMCFG2, 0x12}, // 2: 16/16 sync word bits detected
-
-    {CC1101_DEVIATN, 0x34}, //Deviation = 19.042969
-    {CC1101_MCSM0, 0x18}, //Main Radio Control State Machine Configuration
-    {CC1101_FOCCFG, 0x16}, //Frequency Offset Compensation Configuration
-
-    {CC1101_AGCCTRL2, 0x43}, //AGC Control
-    {CC1101_AGCCTRL1, 0x40},
-    {CC1101_AGCCTRL0, 0x91},
-
-    {CC1101_WORCTRL, 0xFB}, //Wake On Radio Control
-    /* End  */
-    {0, 0},
+typedef struct {
+    volatile SubGhzState state;
+    volatile SubGhzRegulation regulation;
+    volatile FuriHalSubGhzPreset preset;
+} FuriHalSubGhz;
+
+volatile FuriHalSubGhz furi_hal_subghz = {
+    .state = SubGhzStateInit,
+    .regulation = SubGhzRegulationTxRx,
+    .preset = FuriHalSubGhzPresetIDLE,
 };
 
-static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = {
-    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};
-static const uint8_t furi_hal_subghz_preset_ook_async_patable_au[8] = {
-    0x00,
-    0x37, // 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};
-static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = {
-    0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
-    0x00,
-    0x00,
-    0x00,
-    0x00,
-    0x00,
-    0x00,
-    0x00};
-static const uint8_t furi_hal_subghz_preset_msk_async_patable[8] = {
-    0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
-    0x00,
-    0x00,
-    0x00,
-    0x00,
-    0x00,
-    0x00,
-    0x00};
-static const uint8_t furi_hal_subghz_preset_gfsk_async_patable[8] = {
-    0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
-    0x00,
-    0x00,
-    0x00,
-    0x00,
-    0x00,
-    0x00,
-    0x00};
-
 void furi_hal_subghz_init() {
-    furi_assert(furi_hal_subghz_state == SubGhzStateInit);
-    furi_hal_subghz_state = SubGhzStateIdle;
-    furi_hal_subghz_preset = FuriHalSubGhzPresetIDLE;
+    furi_assert(furi_hal_subghz.state == SubGhzStateInit);
+    furi_hal_subghz.state = SubGhzStateIdle;
+    furi_hal_subghz.preset = FuriHalSubGhzPresetIDLE;
 
     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
 
@@ -368,7 +74,7 @@ void furi_hal_subghz_init() {
 }
 
 void furi_hal_subghz_sleep() {
-    furi_assert(furi_hal_subghz_state == SubGhzStateIdle);
+    furi_assert(furi_hal_subghz.state == SubGhzStateIdle);
     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
 
     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
@@ -380,7 +86,7 @@ void furi_hal_subghz_sleep() {
 
     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
 
-    furi_hal_subghz_preset = FuriHalSubGhzPresetIDLE;
+    furi_hal_subghz.preset = FuriHalSubGhzPresetIDLE;
 }
 
 void furi_hal_subghz_dump_state() {
@@ -414,7 +120,7 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
     } else {
         furi_crash("SubGhz: Missing config.");
     }
-    furi_hal_subghz_preset = preset;
+    furi_hal_subghz.preset = preset;
 }
 
 void furi_hal_subghz_load_registers(const uint8_t data[][2]) {
@@ -515,7 +221,7 @@ void furi_hal_subghz_rx() {
 }
 
 bool furi_hal_subghz_tx() {
-    if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false;
+    if(furi_hal_subghz.regulation != SubGhzRegulationTxRx) return false;
     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
     cc1101_switch_to_tx(&furi_hal_spi_bus_handle_subghz);
     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
@@ -589,8 +295,8 @@ bool furi_hal_subghz_is_tx_allowed(uint32_t value) {
         } else {
             if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
                 if((value >= 304100000 && value <= 321950000) &&
-                   ((furi_hal_subghz_preset == FuriHalSubGhzPresetOok270Async) ||
-                    (furi_hal_subghz_preset == FuriHalSubGhzPresetOok650Async))) {
+                   ((furi_hal_subghz.preset == FuriHalSubGhzPresetOok270Async) ||
+                    (furi_hal_subghz.preset == FuriHalSubGhzPresetOok650Async))) {
                     furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable_au);
                 }
             }
@@ -615,9 +321,9 @@ bool furi_hal_subghz_is_tx_allowed(uint32_t value) {
 
 uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
     if(furi_hal_subghz_is_tx_allowed(value)) {
-        furi_hal_subghz_regulation = SubGhzRegulationTxRx;
+        furi_hal_subghz.regulation = SubGhzRegulationTxRx;
     } else {
-        furi_hal_subghz_regulation = SubGhzRegulationOnlyRx;
+        furi_hal_subghz.regulation = SubGhzRegulationOnlyRx;
     }
 
     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
@@ -684,8 +390,8 @@ static void furi_hal_subghz_capture_ISR() {
 }
 
 void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* context) {
-    furi_assert(furi_hal_subghz_state == SubGhzStateIdle);
-    furi_hal_subghz_state = SubGhzStateAsyncRx;
+    furi_assert(furi_hal_subghz.state == SubGhzStateIdle);
+    furi_hal_subghz.state = SubGhzStateAsyncRx;
 
     furi_hal_subghz_capture_callback = callback;
     furi_hal_subghz_capture_callback_context = context;
@@ -741,8 +447,8 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
 }
 
 void furi_hal_subghz_stop_async_rx() {
-    furi_assert(furi_hal_subghz_state == SubGhzStateAsyncRx);
-    furi_hal_subghz_state = SubGhzStateIdle;
+    furi_assert(furi_hal_subghz.state == SubGhzStateAsyncRx);
+    furi_hal_subghz.state = SubGhzStateIdle;
 
     // Shutdown radio
     furi_hal_subghz_idle();
@@ -822,7 +528,10 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) {
 }
 
 static void furi_hal_subghz_async_tx_dma_isr() {
-    furi_assert(furi_hal_subghz_state == SubGhzStateAsyncTx);
+    furi_assert(
+        furi_hal_subghz.state == SubGhzStateAsyncTx ||
+        furi_hal_subghz.state == SubGhzStateAsyncTxEnd ||
+        furi_hal_subghz.state == SubGhzStateAsyncTxLast);
     if(LL_DMA_IsActiveFlag_HT1(DMA1)) {
         LL_DMA_ClearFlag_HT1(DMA1);
         furi_hal_subghz_async_tx_refill(
@@ -840,12 +549,12 @@ static void furi_hal_subghz_async_tx_timer_isr() {
     if(LL_TIM_IsActiveFlag_UPDATE(TIM2)) {
         LL_TIM_ClearFlag_UPDATE(TIM2);
         if(LL_TIM_GetAutoReload(TIM2) == 0) {
-            if(furi_hal_subghz_state == SubGhzStateAsyncTx) {
-                furi_hal_subghz_state = SubGhzStateAsyncTxLast;
+            if(furi_hal_subghz.state == SubGhzStateAsyncTx) {
+                furi_hal_subghz.state = SubGhzStateAsyncTxLast;
                 //forcibly pulls the pin to the ground so that there is no carrier
                 furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullDown, GpioSpeedLow);
             } else {
-                furi_hal_subghz_state = SubGhzStateAsyncTxEnd;
+                furi_hal_subghz.state = SubGhzStateAsyncTxEnd;
                 LL_TIM_DisableCounter(TIM2);
             }
         }
@@ -853,16 +562,16 @@ static void furi_hal_subghz_async_tx_timer_isr() {
 }
 
 bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* context) {
-    furi_assert(furi_hal_subghz_state == SubGhzStateIdle);
+    furi_assert(furi_hal_subghz.state == SubGhzStateIdle);
     furi_assert(callback);
 
     //If transmission is prohibited by regional settings
-    if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false;
+    if(furi_hal_subghz.regulation != SubGhzRegulationTxRx) return false;
 
     furi_hal_subghz_async_tx.callback = callback;
     furi_hal_subghz_async_tx.callback_context = context;
 
-    furi_hal_subghz_state = SubGhzStateAsyncTx;
+    furi_hal_subghz.state = SubGhzStateAsyncTx;
 
     furi_hal_subghz_async_tx.duty_low = 0;
     furi_hal_subghz_async_tx.duty_high = 0;
@@ -935,14 +644,14 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
 }
 
 bool furi_hal_subghz_is_async_tx_complete() {
-    return furi_hal_subghz_state == SubGhzStateAsyncTxEnd;
+    return furi_hal_subghz.state == SubGhzStateAsyncTxEnd;
 }
 
 void furi_hal_subghz_stop_async_tx() {
     furi_assert(
-        furi_hal_subghz_state == SubGhzStateAsyncTx ||
-        furi_hal_subghz_state == SubGhzStateAsyncTxLast ||
-        furi_hal_subghz_state == SubGhzStateAsyncTxEnd);
+        furi_hal_subghz.state == SubGhzStateAsyncTx ||
+        furi_hal_subghz.state == SubGhzStateAsyncTxLast ||
+        furi_hal_subghz.state == SubGhzStateAsyncTxEnd);
 
     // Shutdown radio
     furi_hal_subghz_idle();
@@ -976,5 +685,5 @@ void furi_hal_subghz_stop_async_tx() {
         (double)furi_hal_subghz_async_tx.duty_low,
         (double)duty_cycle);
 
-    furi_hal_subghz_state = SubGhzStateIdle;
+    furi_hal_subghz.state = SubGhzStateIdle;
 }

+ 314 - 0
firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h

@@ -0,0 +1,314 @@
+#pragma once
+
+#include <cc1101.h>
+
+static const uint8_t furi_hal_subghz_preset_ook_270khz_async_regs[][2] = {
+    // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
+
+    /* GPIO GD0 */
+    {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
+
+    /* FIFO and internals */
+    {CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32
+
+    /* Packet engine */
+    {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
+
+    /* Frequency Synthesizer Control */
+    {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
+
+    // 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 3.79372 kBaud
+    {CC1101_MDMCFG4, 0x67}, // Rx BW filter is 270.833333kHz
+
+    /* Main Radio Control State Machine */
+    {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
+
+    /* 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,
+     0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
+    {CC1101_AGCCTRL1,
+     0x00}, // 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, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
+
+    /* Wake on radio and timeouts control */
+    {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
+
+    /* Frontend configuration */
+    {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1]
+    {CC1101_FREND1, 0xB6}, //
+
+    /* End  */
+    {0, 0},
+};
+
+static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = {
+    // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
+
+    /* GPIO GD0 */
+    {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
+
+    /* FIFO and internals */
+    {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION
+
+    /* Packet engine */
+    {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
+
+    /* Frequency Synthesizer Control */
+    {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
+
+    // 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 3.79372 kBaud
+    {CC1101_MDMCFG4, 0x17}, // Rx BW filter is 650.000kHz
+
+    /* Main Radio Control State Machine */
+    {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
+
+    /* 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_AGCTRL0,0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
+    // {CC1101_AGCTRL1,0x00}, // 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, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
+    //MAGN_TARGET for RX filter BW =< 100 kHz is 0x3. For higher RX filter BW's MAGN_TARGET is 0x7.
+    {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, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
+
+    /* Wake on radio and timeouts control */
+    {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
+
+    /* Frontend configuration */
+    {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1]
+    {CC1101_FREND1, 0xB6}, //
+
+    /* End  */
+    {0, 0},
+};
+
+static const uint8_t furi_hal_subghz_preset_2fsk_dev2_38khz_async_regs[][2] = {
+
+    /* GPIO GD0 */
+    {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
+
+    /* Frequency Synthesizer Control */
+    {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
+
+    /* Packet engine */
+    {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
+    {CC1101_PKTCTRL1, 0x04},
+
+    // // Modem Configuration
+    {CC1101_MDMCFG0, 0x00},
+    {CC1101_MDMCFG1, 0x02},
+    {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
+    {CC1101_MDMCFG3, 0x83}, // Data rate is 4.79794 kBaud
+    {CC1101_MDMCFG4, 0x67}, //Rx BW filter is 270.833333 kHz
+    {CC1101_DEVIATN, 0x04}, //Deviation 2.380371 kHz
+
+    /* Main Radio Control State Machine */
+    {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
+
+    /* Frequency Offset Compensation Configuration */
+    {CC1101_FOCCFG,
+     0x16}, // 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,
+     0x00}, // 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, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
+
+    /* Wake on radio and timeouts control */
+    {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
+
+    /* Frontend configuration */
+    {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer
+    {CC1101_FREND1, 0x56},
+
+    /* End  */
+    {0, 0},
+};
+
+static const uint8_t furi_hal_subghz_preset_2fsk_dev47_6khz_async_regs[][2] = {
+
+    /* GPIO GD0 */
+    {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
+
+    /* Frequency Synthesizer Control */
+    {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
+
+    /* Packet engine */
+    {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
+    {CC1101_PKTCTRL1, 0x04},
+
+    // // Modem Configuration
+    {CC1101_MDMCFG0, 0x00},
+    {CC1101_MDMCFG1, 0x02},
+    {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
+    {CC1101_MDMCFG3, 0x83}, // Data rate is 4.79794 kBaud
+    {CC1101_MDMCFG4, 0x67}, //Rx BW filter is 270.833333 kHz
+    {CC1101_DEVIATN, 0x47}, //Deviation 47.60742 kHz
+
+    /* Main Radio Control State Machine */
+    {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
+
+    /* Frequency Offset Compensation Configuration */
+    {CC1101_FOCCFG,
+     0x16}, // 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,
+     0x00}, // 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, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
+
+    /* Wake on radio and timeouts control */
+    {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
+
+    /* Frontend configuration */
+    {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer
+    {CC1101_FREND1, 0x56},
+
+    /* End  */
+    {0, 0},
+};
+
+static const uint8_t furi_hal_subghz_preset_msk_99_97kb_async_regs[][2] = {
+    /* GPIO GD0 */
+    {CC1101_IOCFG0, 0x06},
+
+    {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION
+    {CC1101_SYNC1, 0x46},
+    {CC1101_SYNC0, 0x4C},
+    {CC1101_ADDR, 0x00},
+    {CC1101_PKTLEN, 0x00},
+    {CC1101_CHANNR, 0x00},
+
+    {CC1101_PKTCTRL0, 0x05},
+
+    {CC1101_FSCTRL0, 0x23},
+    {CC1101_FSCTRL1, 0x06},
+
+    {CC1101_MDMCFG0, 0xF8},
+    {CC1101_MDMCFG1, 0x22},
+    {CC1101_MDMCFG2, 0x72},
+    {CC1101_MDMCFG3, 0xF8},
+    {CC1101_MDMCFG4, 0x5B},
+    {CC1101_DEVIATN, 0x47},
+
+    {CC1101_MCSM0, 0x18},
+    {CC1101_FOCCFG, 0x16},
+
+    {CC1101_AGCCTRL0, 0xB2},
+    {CC1101_AGCCTRL1, 0x00},
+    {CC1101_AGCCTRL2, 0xC7},
+
+    {CC1101_FREND0, 0x10},
+    {CC1101_FREND1, 0x56},
+
+    {CC1101_BSCFG, 0x1C},
+    {CC1101_FSTEST, 0x59},
+
+    /* End  */
+    {0, 0},
+};
+
+static const uint8_t furi_hal_subghz_preset_gfsk_9_99kb_async_regs[][2] = {
+
+    {CC1101_IOCFG0, 0x06}, //GDO0 Output Pin Configuration
+    {CC1101_FIFOTHR, 0x47}, //RX FIFO and TX FIFO Thresholds
+
+    //1 : CRC calculation in TX and CRC check in RX enabled,
+    //1 : Variable packet length mode. Packet length configured by the first byte after sync word
+    {CC1101_PKTCTRL0, 0x05},
+
+    {CC1101_FSCTRL1, 0x06}, //Frequency Synthesizer Control
+
+    {CC1101_SYNC1, 0x46},
+    {CC1101_SYNC0, 0x4C},
+    {CC1101_ADDR, 0x00},
+    {CC1101_PKTLEN, 0x00},
+
+    {CC1101_MDMCFG4, 0xC8}, //Modem Configuration 9.99
+    {CC1101_MDMCFG3, 0x93}, //Modem Configuration
+    {CC1101_MDMCFG2, 0x12}, // 2: 16/16 sync word bits detected
+
+    {CC1101_DEVIATN, 0x34}, //Deviation = 19.042969
+    {CC1101_MCSM0, 0x18}, //Main Radio Control State Machine Configuration
+    {CC1101_FOCCFG, 0x16}, //Frequency Offset Compensation Configuration
+
+    {CC1101_AGCCTRL2, 0x43}, //AGC Control
+    {CC1101_AGCCTRL1, 0x40},
+    {CC1101_AGCCTRL0, 0x91},
+
+    {CC1101_WORCTRL, 0xFB}, //Wake On Radio Control
+    /* End  */
+    {0, 0},
+};
+
+static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = {
+    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};
+
+static const uint8_t furi_hal_subghz_preset_ook_async_patable_au[8] = {
+    0x00,
+    0x37, // 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};
+
+static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = {
+    0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
+    0x00,
+    0x00,
+    0x00,
+    0x00,
+    0x00,
+    0x00,
+    0x00};
+
+static const uint8_t furi_hal_subghz_preset_msk_async_patable[8] = {
+    0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
+    0x00,
+    0x00,
+    0x00,
+    0x00,
+    0x00,
+    0x00,
+    0x00};
+
+static const uint8_t furi_hal_subghz_preset_gfsk_async_patable[8] = {
+    0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
+    0x00,
+    0x00,
+    0x00,
+    0x00,
+    0x00,
+    0x00,
+    0x00};