|
|
@@ -1,4 +1,5 @@
|
|
|
#include "furi-hal-subghz.h"
|
|
|
+#include "furi-hal-version.h"
|
|
|
|
|
|
#include <furi-hal-gpio.h>
|
|
|
#include <furi-hal-spi.h>
|
|
|
@@ -10,6 +11,7 @@
|
|
|
#include <stdio.h>
|
|
|
|
|
|
static volatile SubGhzState furi_hal_subghz_state = SubGhzStateInit;
|
|
|
+static volatile SubGhzRegulation furi_hal_subghz_regulation = SubGhzRegulationTxRx;
|
|
|
|
|
|
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
|
|
|
@@ -41,11 +43,11 @@ static const uint8_t furi_hal_subghz_preset_ook_270khz_async_regs[][2] = {
|
|
|
0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
|
|
|
|
|
/* Automatic Gain Control */
|
|
|
- {CC1101_AGCTRL0,
|
|
|
+ {CC1101_AGCCTRL0,
|
|
|
0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
|
|
- {CC1101_AGCTRL1,
|
|
|
+ {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_AGCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
|
|
+ {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
|
|
|
@@ -99,11 +101,15 @@ static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = {
|
|
|
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_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
|
|
|
@@ -131,23 +137,21 @@ static const uint8_t furi_hal_subghz_preset_2fsk_async_regs[][2] = {
|
|
|
/* 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
|
|
|
+ /* 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},
|
|
|
|
|
|
- /* Frequency Synthesizer Control */
|
|
|
- {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
|
|
-
|
|
|
- // Modem Configuration
|
|
|
+ // // Modem Configuration
|
|
|
{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, 0x47}, //Deviation 47.607422 khz
|
|
|
+ {CC1101_MDMCFG1, 0x2},
|
|
|
+ {CC1101_MDMCFG2, 0x4}, // 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, 0x14 }, //Deviation 4.760742 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)
|
|
|
@@ -157,18 +161,18 @@ static const uint8_t furi_hal_subghz_preset_2fsk_async_regs[][2] = {
|
|
|
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,
|
|
|
+ {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_AGCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
|
|
+ {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, 0xB6}, //
|
|
|
+ {CC1101_FREND1, 0x56},
|
|
|
|
|
|
/* Frequency Synthesizer Calibration, valid for 433.92 */
|
|
|
{CC1101_FSCAL3, 0xE9},
|
|
|
@@ -201,7 +205,9 @@ 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);
|
|
|
@@ -279,7 +285,7 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
|
|
|
} 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 {
|
|
|
+ } else {
|
|
|
furi_crash(NULL);
|
|
|
}
|
|
|
}
|
|
|
@@ -356,10 +362,12 @@ void furi_hal_subghz_rx() {
|
|
|
furi_hal_spi_device_return(device);
|
|
|
}
|
|
|
|
|
|
-void furi_hal_subghz_tx() {
|
|
|
+bool furi_hal_subghz_tx() {
|
|
|
+ if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false;
|
|
|
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz);
|
|
|
cc1101_switch_to_tx(device);
|
|
|
furi_hal_spi_device_return(device);
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
float furi_hal_subghz_get_rssi() {
|
|
|
@@ -383,6 +391,7 @@ bool furi_hal_subghz_is_frequency_valid(uint32_t value) {
|
|
|
!(value >= 778999847 && value <= 928000000)) {
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
@@ -403,6 +412,46 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) {
|
|
|
uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
|
|
|
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz);
|
|
|
|
|
|
+ //checking regional settings
|
|
|
+ bool txrx = false;
|
|
|
+ switch(furi_hal_version_get_hw_region()) {
|
|
|
+ case FuriHalVersionRegionEuRu:
|
|
|
+ //433,05..434,79; 868,15..868,55
|
|
|
+ if(!(value >= 433050000 && value <= 434790000) &&
|
|
|
+ !(value >= 868150000 && value <= 8680550000)) {
|
|
|
+ } else {
|
|
|
+ txrx = true;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case FuriHalVersionRegionUsCaAu:
|
|
|
+ //304,10..315,25; 433,05..434,79; 915,00..928,00
|
|
|
+ if(!(value >= 304100000 && value <= 315250000) &&
|
|
|
+ !(value >= 433050000 && value <= 434790000) &&
|
|
|
+ !(value >= 915000000 && value <= 928000000)) {
|
|
|
+ } else {
|
|
|
+ txrx = true;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case FuriHalVersionRegionJp:
|
|
|
+ //312,00..315,25; 920,50..923,50
|
|
|
+ if(!(value >= 312000000 && value <= 315250000) &&
|
|
|
+ !(value >= 920500000 && value <= 923500000)) {
|
|
|
+ } else {
|
|
|
+ txrx = true;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ txrx = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(txrx) {
|
|
|
+ furi_hal_subghz_regulation = SubGhzRegulationTxRx;
|
|
|
+ } else {
|
|
|
+ furi_hal_subghz_regulation = SubGhzRegulationOnlyRx;
|
|
|
+ }
|
|
|
+
|
|
|
uint32_t real_frequency = cc1101_set_frequency(device, value);
|
|
|
cc1101_calibrate(device);
|
|
|
|
|
|
@@ -480,7 +529,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
|
|
TIM_InitStruct.Prescaler = 64 - 1;
|
|
|
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
|
|
TIM_InitStruct.Autoreload = 0x7FFFFFFE;
|
|
|
- TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
|
|
+ TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4;
|
|
|
LL_TIM_Init(TIM2, &TIM_InitStruct);
|
|
|
|
|
|
// Timer: advanced
|
|
|
@@ -503,7 +552,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
|
|
LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI);
|
|
|
LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
|
|
|
LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING);
|
|
|
- LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1);
|
|
|
+ LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV32_N8);
|
|
|
|
|
|
// ISR setup
|
|
|
furi_hal_interrupt_set_timer_isr(TIM2, furi_hal_subghz_capture_ISR);
|
|
|
@@ -608,6 +657,8 @@ static void furi_hal_subghz_async_tx_timer_isr() {
|
|
|
if(LL_TIM_GetAutoReload(TIM2) == 0) {
|
|
|
if(furi_hal_subghz_state == SubGhzStateAsyncTx) {
|
|
|
furi_hal_subghz_state = SubGhzStateAsyncTxLast;
|
|
|
+ //forcibly pulls the pin to the ground so that there is no carrier
|
|
|
+ hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullDown, GpioSpeedLow);
|
|
|
} else {
|
|
|
furi_hal_subghz_state = SubGhzStateAsyncTxEnd;
|
|
|
LL_TIM_DisableCounter(TIM2);
|
|
|
@@ -616,10 +667,13 @@ static void furi_hal_subghz_async_tx_timer_isr() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* context) {
|
|
|
+bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* context) {
|
|
|
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;
|
|
|
+
|
|
|
furi_hal_subghz_async_tx.callback = callback;
|
|
|
furi_hal_subghz_async_tx.callback_context = context;
|
|
|
|
|
|
@@ -694,6 +748,7 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
|
|
|
|
|
LL_TIM_SetCounter(TIM2, 0);
|
|
|
LL_TIM_EnableCounter(TIM2);
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
bool furi_hal_subghz_is_async_tx_complete() {
|