diff options
author | Skorpionm <85568270+Skorpionm@users.noreply.github.com> | 2021-09-15 18:24:19 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-15 18:24:19 +0300 |
commit | 8fd411097ec3cd96c5f744008d71529661eea732 (patch) | |
tree | ec84a27b360a5a1b372ed1c2ae941e143364e62b /firmware | |
parent | 72ca76097a9752cc539c22cb8961ee481939eac4 (diff) |
[FL-1758, FL-1790] SubGhz refactoring part 2, fix generation of a new GateTX serial (#696)
* WidGet: fix name Multiline String Element
* SubGhz: rename SubGhzProtocol to SubGhzParser and bring it up
* SubGhz: a new way to navigate in receiver views
* SubGhz: fix syntax
* WedGet: add forwarding input type to wedget button callback, fix using a callback in an application
* SubGhz: add assertions and status checks
* SubGhz: fix syntax
* [FL-1790] SubGhz: fix GateTX
* SubGhz: add 434.42 MHz frequency support
* SubGhz: rename type protocol, add decoder stage names
* SubGhz: fix navigation through received signals when changing scenes
* SubGhz: fix 2-fsk config
Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/targets/f6/furi-hal/furi-hal-subghz.c | 276 | ||||
-rw-r--r-- | firmware/targets/f7/furi-hal/furi-hal-subghz.c | 278 |
2 files changed, 294 insertions, 260 deletions
diff --git a/firmware/targets/f6/furi-hal/furi-hal-subghz.c b/firmware/targets/f6/furi-hal/furi-hal-subghz.c index c200fc60..4d1f0cbf 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-subghz.c +++ b/firmware/targets/f6/furi-hal/furi-hal-subghz.c @@ -15,166 +15,174 @@ 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 + {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 + {CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32 /* Packet engine */ - { CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening /* Frequency Synthesizer Control */ - { CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + {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 + {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) + {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 + {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_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB + {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_AGCTRL2, 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 + {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 }, // + {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1] + {CC1101_FREND1, 0xB6}, // /* Frequency Synthesizer Calibration, valid for 433.92 */ - { CC1101_FSCAL3, 0xE9 }, - { CC1101_FSCAL2, 0x2A }, - { CC1101_FSCAL1, 0x00 }, - { CC1101_FSCAL0, 0x1F }, + {CC1101_FSCAL3, 0xE9}, + {CC1101_FSCAL2, 0x2A}, + {CC1101_FSCAL1, 0x00}, + {CC1101_FSCAL0, 0x1F}, /* Magic f4ckery */ - { CC1101_TEST2, 0x81 }, // FIFOTHR ADC_RETENTION=1 matched value - { CC1101_TEST1, 0x35 }, // FIFOTHR ADC_RETENTION=1 matched value - { CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled + {CC1101_TEST2, 0x81}, // FIFOTHR ADC_RETENTION=1 matched value + {CC1101_TEST1, 0x35}, // FIFOTHR ADC_RETENTION=1 matched value + {CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled /* End */ - { 0, 0 }, + {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 + {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input /* FIFO and internals */ - { CC1101_FIFOTHR, 0x07 }, // The only important bit is ADC_RETENTION + {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION /* Packet engine */ - { CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening /* Frequency Synthesizer Control */ - { CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + {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 - + {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) + {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 + {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_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB + {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_AGCTRL2, 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 + {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 }, // + {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1] + {CC1101_FREND1, 0xB6}, // /* Frequency Synthesizer Calibration, valid for 433.92 */ - { CC1101_FSCAL3, 0xE9 }, - { CC1101_FSCAL2, 0x2A }, - { CC1101_FSCAL1, 0x00 }, - { CC1101_FSCAL0, 0x1F }, + {CC1101_FSCAL3, 0xE9}, + {CC1101_FSCAL2, 0x2A}, + {CC1101_FSCAL1, 0x00}, + {CC1101_FSCAL0, 0x1F}, /* Magic f4ckery */ - { CC1101_TEST2, 0x88 }, - { CC1101_TEST1, 0x31 }, - { CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled + {CC1101_TEST2, 0x88}, + {CC1101_TEST1, 0x31}, + {CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled /* End */ - { 0, 0 }, + {0, 0}, }; static const uint8_t furi_hal_subghz_preset_2fsk_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 + {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input /* FIFO and internals */ - { CC1101_FIFOTHR, 0x47 }, // The only important bit is ADC_RETENTION + {CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION /* Packet engine */ - { CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening /* Frequency Synthesizer Control */ - { CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz // Modem Configuration - { CC1101_MDMCFG0, 0xF8 }, - { CC1101_MDMCFG1, 0x00 }, // No preamble/sync - { CC1101_MDMCFG2, 0x80 }, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized) - { CC1101_MDMCFG3, 0x83 }, // Data rate is 9.59587 kBaud - { CC1101_MDMCFG4, 0x88 }, // Rx BW filter is 203.125000kHz + {CC1101_MDMCFG0, 0x00}, + {CC1101_MDMCFG1, 0x02}, + {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized) + {CC1101_MDMCFG3, 0x8B}, // Data rate is 19.5885 kBaud + {CC1101_MDMCFG4, 0x69}, // Rx BW filter is 270.833333 kHz - { CC1101_DEVIATN, 0x14}, //Deviation 4.760742 khz + {CC1101_DEVIATN, 0x47}, //Deviation 47.607422 khz /* Main Radio Control State Machine */ - { CC1101_MCSM0, 0x18 }, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) + {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 + {CC1101_FOCCFG, + 0x16}, // 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_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB + {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_AGCTRL2, 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 + {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, 0xB6 }, // + {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer + {CC1101_FREND1, 0xB6}, // /* Frequency Synthesizer Calibration, valid for 433.92 */ - { CC1101_FSCAL3, 0xE9 }, - { CC1101_FSCAL2, 0x2A }, - { CC1101_FSCAL1, 0x00 }, - { CC1101_FSCAL0, 0x1F }, + {CC1101_FSCAL3, 0xE9}, + {CC1101_FSCAL2, 0x2A}, + {CC1101_FSCAL1, 0x00}, + {CC1101_FSCAL0, 0x1F}, /* Magic f4ckery */ - { CC1101_TEST2, 0x81 }, // FIFOTHR ADC_RETENTION=1 matched value - { CC1101_TEST1, 0x35 }, // FIFOTHR ADC_RETENTION=1 matched value - { CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled + {CC1101_TEST2, 0x81}, // FIFOTHR ADC_RETENTION=1 matched value + {CC1101_TEST1, 0x35}, // FIFOTHR ADC_RETENTION=1 matched value + {CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled /* End */ - { 0, 0 }, + {0, 0}, }; static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { 0x00, @@ -184,8 +192,7 @@ static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { 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, @@ -195,6 +202,7 @@ static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = { 0x00, 0x00, 0x00 + }; void furi_hal_subghz_init() { @@ -217,11 +225,13 @@ void furi_hal_subghz_init() { // GD0 low cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW); - while(hal_gpio_read(&gpio_cc1101_g0) != false); + while(hal_gpio_read(&gpio_cc1101_g0) != false) + ; // GD0 high cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); - while(hal_gpio_read(&gpio_cc1101_g0) != true); + while(hal_gpio_read(&gpio_cc1101_g0) != true) + ; // Reset GD0 to floating state cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); @@ -257,8 +267,7 @@ void furi_hal_subghz_dump_state() { printf( "[furi_hal_subghz] cc1101 chip %d, version %d\r\n", cc1101_get_partnumber(device), - cc1101_get_version(device) - ); + cc1101_get_version(device)); furi_hal_spi_device_return(device); } @@ -266,10 +275,10 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { if(preset == FuriHalSubGhzPresetOok650Async) { furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_650khz_async_regs); furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable); - } else if(preset == FuriHalSubGhzPresetOok270Async){ + } else if(preset == FuriHalSubGhzPresetOok270Async) { furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_270khz_async_regs); furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable); - } else if(preset == FuriHalSubGhzPreset2FSKAsync){ + } else if(preset == FuriHalSubGhzPreset2FSKAsync) { furi_hal_subghz_load_registers(furi_hal_subghz_preset_2fsk_async_regs); furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable); }else { @@ -289,7 +298,7 @@ void furi_hal_subghz_load_registers(const uint8_t data[][2]) { const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); cc1101_reset(device); uint32_t i = 0; - while (data[i][0]) { + while(data[i][0]) { cc1101_write_reg(device, data[i][0], data[i][1]); i++; } @@ -401,7 +410,7 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { while(true) { CC1101Status status = cc1101_get_status(device); - if (status.STATE == CC1101StateIDLE) break; + if(status.STATE == CC1101StateIDLE) break; } furi_hal_spi_device_return(device); @@ -411,16 +420,16 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); - if (path == FuriHalSubGhzPath433) { + if(path == FuriHalSubGhzPath433) { hal_gpio_write(&gpio_rf_sw_0, 0); cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); - } else if (path == FuriHalSubGhzPath315) { + } else if(path == FuriHalSubGhzPath315) { hal_gpio_write(&gpio_rf_sw_0, 1); cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); - } else if (path == FuriHalSubGhzPath868) { + } else if(path == FuriHalSubGhzPath868) { hal_gpio_write(&gpio_rf_sw_0, 1); cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); - } else if (path == FuriHalSubGhzPathIsolate) { + } else if(path == FuriHalSubGhzPathIsolate) { hal_gpio_write(&gpio_rf_sw_0, 0); cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); } else { @@ -438,24 +447,25 @@ static void furi_hal_subghz_capture_ISR() { if(LL_TIM_IsActiveFlag_CC1(TIM2)) { LL_TIM_ClearFlag_CC1(TIM2); furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2); - if (furi_hal_subghz_capture_callback) { - furi_hal_subghz_capture_callback(true, furi_hal_subghz_capture_delta_duration, - (void*)furi_hal_subghz_capture_callback_context - ); + if(furi_hal_subghz_capture_callback) { + furi_hal_subghz_capture_callback( + true, + furi_hal_subghz_capture_delta_duration, + (void*)furi_hal_subghz_capture_callback_context); } } // Channel 2 if(LL_TIM_IsActiveFlag_CC2(TIM2)) { LL_TIM_ClearFlag_CC2(TIM2); - if (furi_hal_subghz_capture_callback) { - furi_hal_subghz_capture_callback(false, LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration, - (void*)furi_hal_subghz_capture_callback_context - ); + if(furi_hal_subghz_capture_callback) { + furi_hal_subghz_capture_callback( + false, + LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration, + (void*)furi_hal_subghz_capture_callback_context); } } } - void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* context) { furi_assert(furi_hal_subghz_state == SubGhzStateIdle); furi_hal_subghz_state = SubGhzStateAsyncRx; @@ -463,12 +473,13 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* furi_hal_subghz_capture_callback = callback; furi_hal_subghz_capture_callback_context = context; - hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2); + hal_gpio_init_ex( + &gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2); // Timer: base LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); LL_TIM_InitTypeDef TIM_InitStruct = {0}; - TIM_InitStruct.Prescaler = 64-1; + TIM_InitStruct.Prescaler = 64 - 1; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.Autoreload = 0x7FFFFFFE; TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; @@ -498,7 +509,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* // ISR setup furi_hal_interrupt_set_timer_isr(TIM2, furi_hal_subghz_capture_ISR); - NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0)); + NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(TIM2_IRQn); // Interrupts and channels @@ -508,7 +519,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); // Enable NVIC - NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0)); + NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(TIM2_IRQn); // Start timer @@ -534,8 +545,8 @@ void furi_hal_subghz_stop_async_rx() { } #define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL (256) -#define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF (API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL/2) -#define API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME 333 +#define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF (API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL / 2) +#define API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME 333 typedef struct { uint32_t* buffer; @@ -547,12 +558,13 @@ typedef struct { static FuriHalSubGhzAsyncTx furi_hal_subghz_async_tx = {0}; static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { - while (samples > 0) { + while(samples > 0) { bool is_odd = samples % 2; - LevelDuration ld = furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context); - if (level_duration_is_reset(ld)) { + LevelDuration ld = + furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context); + if(level_duration_is_reset(ld)) { // One more even sample required to end at low level - if (is_odd) { + if(is_odd) { *buffer = API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME; buffer++; samples--; @@ -560,7 +572,7 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { break; } else { // Inject guard time if level is incorrect - if (is_odd == level_duration_get_level(ld)) { + if(is_odd == level_duration_get_level(ld)) { *buffer = API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME; buffer++; samples--; @@ -579,21 +591,24 @@ 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); - if (LL_DMA_IsActiveFlag_HT1(DMA1)) { + if(LL_DMA_IsActiveFlag_HT1(DMA1)) { LL_DMA_ClearFlag_HT1(DMA1); - furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF); + furi_hal_subghz_async_tx_refill( + furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF); } - if (LL_DMA_IsActiveFlag_TC1(DMA1)) { + if(LL_DMA_IsActiveFlag_TC1(DMA1)) { LL_DMA_ClearFlag_TC1(DMA1); - furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer+API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF); + furi_hal_subghz_async_tx_refill( + furi_hal_subghz_async_tx.buffer + API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF, + API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF); } } 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) { + if(LL_TIM_GetAutoReload(TIM2) == 0) { + if(furi_hal_subghz_state == SubGhzStateAsyncTx) { furi_hal_subghz_state = SubGhzStateAsyncTxLast; } else { furi_hal_subghz_state = SubGhzStateAsyncTxEnd; @@ -612,15 +627,18 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* furi_hal_subghz_state = SubGhzStateAsyncTx; - furi_hal_subghz_async_tx.buffer = furi_alloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t)); - furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL); + furi_hal_subghz_async_tx.buffer = + furi_alloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t)); + furi_hal_subghz_async_tx_refill( + furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL); // Connect CC1101_GD0 to TIM2 as output - hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2); + hal_gpio_init_ex( + &gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2); // Configure DMA LL_DMA_InitTypeDef dma_config = {0}; - dma_config.PeriphOrM2MSrcAddress = (uint32_t)&(TIM2->ARR); + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR); dma_config.MemoryOrM2MDstAddress = (uint32_t)furi_hal_subghz_async_tx.buffer; dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; dma_config.Mode = LL_DMA_MODE_CIRCULAR; @@ -632,7 +650,8 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; dma_config.Priority = LL_DMA_MODE_NORMAL; LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config); - furi_hal_interrupt_set_dma_channel_isr(DMA1, LL_DMA_CHANNEL_1, furi_hal_subghz_async_tx_dma_isr); + furi_hal_interrupt_set_dma_channel_isr( + DMA1, LL_DMA_CHANNEL_1, furi_hal_subghz_async_tx_dma_isr); LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1); LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_1); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); @@ -640,7 +659,7 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* // Configure TIM2 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); LL_TIM_InitTypeDef TIM_InitStruct = {0}; - TIM_InitStruct.Prescaler = 64-1; + TIM_InitStruct.Prescaler = 64 - 1; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.Autoreload = 1000; TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; @@ -672,7 +691,7 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* furi_hal_subghz_tx(); // Enable NVIC - NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0)); + NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(TIM2_IRQn); LL_TIM_SetCounter(TIM2, 0); @@ -685,10 +704,9 @@ bool furi_hal_subghz_is_async_tx_complete() { 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(); diff --git a/firmware/targets/f7/furi-hal/furi-hal-subghz.c b/firmware/targets/f7/furi-hal/furi-hal-subghz.c index c200fc60..7e8c12cd 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-subghz.c +++ b/firmware/targets/f7/furi-hal/furi-hal-subghz.c @@ -15,166 +15,174 @@ 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 + {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 + {CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32 /* Packet engine */ - { CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening /* Frequency Synthesizer Control */ - { CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + {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 + {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) + {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 + {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_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB + {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_AGCTRL2, 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 + {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 }, // + {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1] + {CC1101_FREND1, 0xB6}, // /* Frequency Synthesizer Calibration, valid for 433.92 */ - { CC1101_FSCAL3, 0xE9 }, - { CC1101_FSCAL2, 0x2A }, - { CC1101_FSCAL1, 0x00 }, - { CC1101_FSCAL0, 0x1F }, + {CC1101_FSCAL3, 0xE9}, + {CC1101_FSCAL2, 0x2A}, + {CC1101_FSCAL1, 0x00}, + {CC1101_FSCAL0, 0x1F}, /* Magic f4ckery */ - { CC1101_TEST2, 0x81 }, // FIFOTHR ADC_RETENTION=1 matched value - { CC1101_TEST1, 0x35 }, // FIFOTHR ADC_RETENTION=1 matched value - { CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled + {CC1101_TEST2, 0x81}, // FIFOTHR ADC_RETENTION=1 matched value + {CC1101_TEST1, 0x35}, // FIFOTHR ADC_RETENTION=1 matched value + {CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled /* End */ - { 0, 0 }, + {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 + {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input /* FIFO and internals */ - { CC1101_FIFOTHR, 0x07 }, // The only important bit is ADC_RETENTION + {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION /* Packet engine */ - { CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening /* Frequency Synthesizer Control */ - { CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + {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 - + {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) + {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 + {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_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB + {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_AGCTRL2, 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 + {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 }, // + {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1] + {CC1101_FREND1, 0xB6}, // /* Frequency Synthesizer Calibration, valid for 433.92 */ - { CC1101_FSCAL3, 0xE9 }, - { CC1101_FSCAL2, 0x2A }, - { CC1101_FSCAL1, 0x00 }, - { CC1101_FSCAL0, 0x1F }, + {CC1101_FSCAL3, 0xE9}, + {CC1101_FSCAL2, 0x2A}, + {CC1101_FSCAL1, 0x00}, + {CC1101_FSCAL0, 0x1F}, /* Magic f4ckery */ - { CC1101_TEST2, 0x88 }, - { CC1101_TEST1, 0x31 }, - { CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled + {CC1101_TEST2, 0x88}, + {CC1101_TEST1, 0x31}, + {CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled /* End */ - { 0, 0 }, + {0, 0}, }; static const uint8_t furi_hal_subghz_preset_2fsk_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 + {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input /* FIFO and internals */ - { CC1101_FIFOTHR, 0x47 }, // The only important bit is ADC_RETENTION + {CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION /* Packet engine */ - { CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening /* Frequency Synthesizer Control */ - { CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz // Modem Configuration - { CC1101_MDMCFG0, 0xF8 }, - { CC1101_MDMCFG1, 0x00 }, // No preamble/sync - { CC1101_MDMCFG2, 0x80 }, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized) - { CC1101_MDMCFG3, 0x83 }, // Data rate is 9.59587 kBaud - { CC1101_MDMCFG4, 0x88 }, // Rx BW filter is 203.125000kHz + {CC1101_MDMCFG0, 0x00}, + {CC1101_MDMCFG1, 0x02}, + {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized) + {CC1101_MDMCFG3, 0x8B}, // Data rate is 19.5885 kBaud + {CC1101_MDMCFG4, 0x69}, // Rx BW filter is 270.833333 kHz - { CC1101_DEVIATN, 0x14}, //Deviation 4.760742 khz + {CC1101_DEVIATN, 0x47}, //Deviation 47.607422 khz /* Main Radio Control State Machine */ - { CC1101_MCSM0, 0x18 }, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) + {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 + {CC1101_FOCCFG, + 0x16}, // 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_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB + {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_AGCTRL2, 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 + {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, 0xB6 }, // + {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer + {CC1101_FREND1, 0xB6}, // /* Frequency Synthesizer Calibration, valid for 433.92 */ - { CC1101_FSCAL3, 0xE9 }, - { CC1101_FSCAL2, 0x2A }, - { CC1101_FSCAL1, 0x00 }, - { CC1101_FSCAL0, 0x1F }, + {CC1101_FSCAL3, 0xE9}, + {CC1101_FSCAL2, 0x2A}, + {CC1101_FSCAL1, 0x00}, + {CC1101_FSCAL0, 0x1F}, /* Magic f4ckery */ - { CC1101_TEST2, 0x81 }, // FIFOTHR ADC_RETENTION=1 matched value - { CC1101_TEST1, 0x35 }, // FIFOTHR ADC_RETENTION=1 matched value - { CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled + {CC1101_TEST2, 0x81}, // FIFOTHR ADC_RETENTION=1 matched value + {CC1101_TEST1, 0x35}, // FIFOTHR ADC_RETENTION=1 matched value + {CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled /* End */ - { 0, 0 }, + {0, 0}, }; static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { 0x00, @@ -184,8 +192,7 @@ static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { 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, @@ -194,8 +201,7 @@ static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = { 0x00, 0x00, 0x00, - 0x00 -}; + 0x00}; void furi_hal_subghz_init() { furi_assert(furi_hal_subghz_state == SubGhzStateInit); @@ -217,11 +223,13 @@ void furi_hal_subghz_init() { // GD0 low cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW); - while(hal_gpio_read(&gpio_cc1101_g0) != false); + while(hal_gpio_read(&gpio_cc1101_g0) != false) + ; // GD0 high cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); - while(hal_gpio_read(&gpio_cc1101_g0) != true); + while(hal_gpio_read(&gpio_cc1101_g0) != true) + ; // Reset GD0 to floating state cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); @@ -257,8 +265,7 @@ void furi_hal_subghz_dump_state() { printf( "[furi_hal_subghz] cc1101 chip %d, version %d\r\n", cc1101_get_partnumber(device), - cc1101_get_version(device) - ); + cc1101_get_version(device)); furi_hal_spi_device_return(device); } @@ -266,10 +273,10 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { if(preset == FuriHalSubGhzPresetOok650Async) { furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_650khz_async_regs); furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable); - } else if(preset == FuriHalSubGhzPresetOok270Async){ + } else if(preset == FuriHalSubGhzPresetOok270Async) { furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_270khz_async_regs); furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable); - } else if(preset == FuriHalSubGhzPreset2FSKAsync){ + } else if(preset == FuriHalSubGhzPreset2FSKAsync) { furi_hal_subghz_load_registers(furi_hal_subghz_preset_2fsk_async_regs); furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable); }else { @@ -289,7 +296,7 @@ void furi_hal_subghz_load_registers(const uint8_t data[][2]) { const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); cc1101_reset(device); uint32_t i = 0; - while (data[i][0]) { + while(data[i][0]) { cc1101_write_reg(device, data[i][0], data[i][1]); i++; } @@ -401,7 +408,7 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { while(true) { CC1101Status status = cc1101_get_status(device); - if (status.STATE == CC1101StateIDLE) break; + if(status.STATE == CC1101StateIDLE) break; } furi_hal_spi_device_return(device); @@ -411,16 +418,16 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); - if (path == FuriHalSubGhzPath433) { + if(path == FuriHalSubGhzPath433) { hal_gpio_write(&gpio_rf_sw_0, 0); cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); - } else if (path == FuriHalSubGhzPath315) { + } else if(path == FuriHalSubGhzPath315) { hal_gpio_write(&gpio_rf_sw_0, 1); cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); - } else if (path == FuriHalSubGhzPath868) { + } else if(path == FuriHalSubGhzPath868) { hal_gpio_write(&gpio_rf_sw_0, 1); cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); - } else if (path == FuriHalSubGhzPathIsolate) { + } else if(path == FuriHalSubGhzPathIsolate) { hal_gpio_write(&gpio_rf_sw_0, 0); cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); } else { @@ -438,24 +445,25 @@ static void furi_hal_subghz_capture_ISR() { if(LL_TIM_IsActiveFlag_CC1(TIM2)) { LL_TIM_ClearFlag_CC1(TIM2); furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2); - if (furi_hal_subghz_capture_callback) { - furi_hal_subghz_capture_callback(true, furi_hal_subghz_capture_delta_duration, - (void*)furi_hal_subghz_capture_callback_context - ); + if(furi_hal_subghz_capture_callback) { + furi_hal_subghz_capture_callback( + true, + furi_hal_subghz_capture_delta_duration, + (void*)furi_hal_subghz_capture_callback_context); } } // Channel 2 if(LL_TIM_IsActiveFlag_CC2(TIM2)) { LL_TIM_ClearFlag_CC2(TIM2); - if (furi_hal_subghz_capture_callback) { - furi_hal_subghz_capture_callback(false, LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration, - (void*)furi_hal_subghz_capture_callback_context - ); + if(furi_hal_subghz_capture_callback) { + furi_hal_subghz_capture_callback( + false, + LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration, + (void*)furi_hal_subghz_capture_callback_context); } } } - void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* context) { furi_assert(furi_hal_subghz_state == SubGhzStateIdle); furi_hal_subghz_state = SubGhzStateAsyncRx; @@ -463,12 +471,13 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* furi_hal_subghz_capture_callback = callback; furi_hal_subghz_capture_callback_context = context; - hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2); + hal_gpio_init_ex( + &gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2); // Timer: base LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); LL_TIM_InitTypeDef TIM_InitStruct = {0}; - TIM_InitStruct.Prescaler = 64-1; + TIM_InitStruct.Prescaler = 64 - 1; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.Autoreload = 0x7FFFFFFE; TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; @@ -498,7 +507,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* // ISR setup furi_hal_interrupt_set_timer_isr(TIM2, furi_hal_subghz_capture_ISR); - NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0)); + NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(TIM2_IRQn); // Interrupts and channels @@ -508,7 +517,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); // Enable NVIC - NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0)); + NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(TIM2_IRQn); // Start timer @@ -534,8 +543,8 @@ void furi_hal_subghz_stop_async_rx() { } #define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL (256) -#define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF (API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL/2) -#define API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME 333 +#define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF (API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL / 2) +#define API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME 333 typedef struct { uint32_t* buffer; @@ -547,12 +556,13 @@ typedef struct { static FuriHalSubGhzAsyncTx furi_hal_subghz_async_tx = {0}; static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { - while (samples > 0) { + while(samples > 0) { bool is_odd = samples % 2; - LevelDuration ld = furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context); - if (level_duration_is_reset(ld)) { + LevelDuration ld = + furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context); + if(level_duration_is_reset(ld)) { // One more even sample required to end at low level - if (is_odd) { + if(is_odd) { *buffer = API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME; buffer++; samples--; @@ -560,7 +570,7 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { break; } else { // Inject guard time if level is incorrect - if (is_odd == level_duration_get_level(ld)) { + if(is_odd == level_duration_get_level(ld)) { *buffer = API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME; buffer++; samples--; @@ -579,21 +589,24 @@ 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); - if (LL_DMA_IsActiveFlag_HT1(DMA1)) { + if(LL_DMA_IsActiveFlag_HT1(DMA1)) { LL_DMA_ClearFlag_HT1(DMA1); - furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF); + furi_hal_subghz_async_tx_refill( + furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF); } - if (LL_DMA_IsActiveFlag_TC1(DMA1)) { + if(LL_DMA_IsActiveFlag_TC1(DMA1)) { LL_DMA_ClearFlag_TC1(DMA1); - furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer+API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF); + furi_hal_subghz_async_tx_refill( + furi_hal_subghz_async_tx.buffer + API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF, + API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF); } } 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) { + if(LL_TIM_GetAutoReload(TIM2) == 0) { + if(furi_hal_subghz_state == SubGhzStateAsyncTx) { furi_hal_subghz_state = SubGhzStateAsyncTxLast; } else { furi_hal_subghz_state = SubGhzStateAsyncTxEnd; @@ -612,15 +625,18 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* furi_hal_subghz_state = SubGhzStateAsyncTx; - furi_hal_subghz_async_tx.buffer = furi_alloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t)); - furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL); + furi_hal_subghz_async_tx.buffer = + furi_alloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t)); + furi_hal_subghz_async_tx_refill( + furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL); // Connect CC1101_GD0 to TIM2 as output - hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2); + hal_gpio_init_ex( + &gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2); // Configure DMA LL_DMA_InitTypeDef dma_config = {0}; - dma_config.PeriphOrM2MSrcAddress = (uint32_t)&(TIM2->ARR); + dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR); dma_config.MemoryOrM2MDstAddress = (uint32_t)furi_hal_subghz_async_tx.buffer; dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; dma_config.Mode = LL_DMA_MODE_CIRCULAR; @@ -632,7 +648,8 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; dma_config.Priority = LL_DMA_MODE_NORMAL; LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config); - furi_hal_interrupt_set_dma_channel_isr(DMA1, LL_DMA_CHANNEL_1, furi_hal_subghz_async_tx_dma_isr); + furi_hal_interrupt_set_dma_channel_isr( + DMA1, LL_DMA_CHANNEL_1, furi_hal_subghz_async_tx_dma_isr); LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1); LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_1); LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); @@ -640,7 +657,7 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* // Configure TIM2 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); LL_TIM_InitTypeDef TIM_InitStruct = {0}; - TIM_InitStruct.Prescaler = 64-1; + TIM_InitStruct.Prescaler = 64 - 1; TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; TIM_InitStruct.Autoreload = 1000; TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; @@ -672,7 +689,7 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* furi_hal_subghz_tx(); // Enable NVIC - NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0)); + NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); NVIC_EnableIRQ(TIM2_IRQn); LL_TIM_SetCounter(TIM2, 0); @@ -685,10 +702,9 @@ bool furi_hal_subghz_is_async_tx_complete() { 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(); |