From c688d63b8ffe03437628f131b19169a900233b03 Mon Sep 17 00:00:00 2001 From: Goebish Date: Wed, 4 Sep 2019 13:57:07 +0200 Subject: [PATCH] CC2500 spectrum analyzer --- Multiprotocol/Multiprotocol.ino | 17 +-- Multiprotocol/Scanner_cc2500.ino | 196 +++++++++++++++++++++++++++++ Multiprotocol/Scanner_cyrf6936.ino | 134 -------------------- Multiprotocol/Validate.h | 2 +- Multiprotocol/_Config.h | 6 +- 5 files changed, 209 insertions(+), 146 deletions(-) create mode 100644 Multiprotocol/Scanner_cc2500.ino delete mode 100644 Multiprotocol/Scanner_cyrf6936.ino diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index 1f0b843..ca92421 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -23,7 +23,7 @@ #include //#define DEBUG_PIN // Use pin TX for AVR and SPI_CS for STM32 => DEBUG_PIN_on, DEBUG_PIN_off, DEBUG_PIN_toggle -//#define DEBUG_SERIAL // Only for STM32_BOARD, compiled with Upload method "Serial"->usart1, "STM32duino bootloader"->USB serial +#define DEBUG_SERIAL // Only for STM32_BOARD, compiled with Upload method "Serial"->usart1, "STM32duino bootloader"->USB serial #ifdef __arm__ // Let's automatically select the board if arm is selected #define STM32_BOARD @@ -998,6 +998,14 @@ static void protocol_init() remote_callback = ReadHITEC; break; #endif + #if defined(SCANNER_CC2500_INO) + case PROTO_SCANNER: + PE1_off; + PE2_on; //antenna RF2 + next_callback = initScanner(); + remote_callback = Scanner_callback; + break; + #endif #endif #ifdef CYRF6936_INSTALLED #if defined(DSM_CYRF6936_INO) @@ -1072,13 +1080,6 @@ static void protocol_init() remote_callback = ReadTRAXXAS; break; #endif - #if defined(SCANNER_CYRF6936_INO) - case PROTO_SCANNER: - PE2_on; //antenna RF4 - next_callback = initScanner(); - remote_callback = Scanner_callback; - break; - #endif #endif #ifdef NRF24L01_INSTALLED #if defined(HISKY_NRF24L01_INO) diff --git a/Multiprotocol/Scanner_cc2500.ino b/Multiprotocol/Scanner_cc2500.ino new file mode 100644 index 0000000..ae19dc9 --- /dev/null +++ b/Multiprotocol/Scanner_cc2500.ino @@ -0,0 +1,196 @@ +/* + This project is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Multiprotocol is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Multiprotocol. If not, see . + */ + +#if defined(SCANNER_CC2500_INO) + +// Ported from DeviationTX frequency scanner + +#include "iface_cc2500.h" + +struct Scanner { + uint8_t rssi[255]; + uint8_t chan_min; + uint8_t chan_max; + uint16_t averaging; +} Scanner; + +#define MIN_RADIOCHANNEL 0x00 +#define MAX_RADIOCHANNEL 255 //0x62 +#define CHANNEL_LOCK_TIME 300 // slow scan_channel requires 270 usec for synthesizer to settle +#define INTERNAL_AVERAGE 1 +#define AVERAGE_INTVL 50 + +static int scan_averages, scan_channel, scan_state; +static uint32_t rssi_sum; +static uint8_t calibration[MAX_RADIOCHANNEL]; +static uint8_t calibration_fscal2, calibration_fscal3; + +enum ScanStates { + SCAN_CHANNEL_CHANGE = 0, + SCAN_GET_RSSI = 1, +}; + +static void __attribute__((unused)) Scanner_cc2500_init() +{ + /* Initialize CC2500 chip */ + /*CC2500_WriteReg(0x30, 0x3d); // soft reset + CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x00); // packet automation control + CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x00); // packet automation control + CC2500_WriteReg(CC2500_0A_CHANNR, 0x00); // scan_channel number + CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x08); // frequency synthesizer control + CC2500_WriteReg(CC2500_0C_FSCTRL0, 0x00); // frequency synthesizer control + CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // frequency control word, high byte + CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // frequency control word, middle byte + CC2500_WriteReg(CC2500_0F_FREQ0, 0xDE); // frequency control word, low byte + CC2500_WriteReg(CC2500_10_MDMCFG4, 0x86); // modem configuration + CC2500_WriteReg(CC2500_11_MDMCFG3, 0x83); // modem configuration + CC2500_WriteReg(CC2500_12_MDMCFG2, 0x00); // modem configuration FSK for better sensitivity + CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // modem configuration + CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // modem configuration + CC2500_WriteReg(CC2500_15_DEVIATN, 0x44); // modem deviation setting 38.085938 + CC2500_WriteReg(CC2500_17_MCSM1, 0x0F); // always stay in RX mode + CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // disable auto-calibration + CC2500_WriteReg(CC2500_19_FOCCFG, 0x16); // frequency offset compensation configuration + CC2500_WriteReg(CC2500_1A_BSCFG, 0x6C); // bit synchronization configuration + CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0x03); // agc control + CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x40); // agc control + CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0x91); // agc control + CC2500_WriteReg(CC2500_21_FREND1, 0x56); // front end rx configuration + CC2500_WriteReg(CC2500_22_FREND0, 0x10); // front end tx configuration + CC2500_WriteReg(CC2500_23_FSCAL3, 0xA9); // frequency synthesizer calibration + CC2500_WriteReg(CC2500_24_FSCAL2, 0x0A); // frequency synthesizer calibration + CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // frequency synthesizer calibration + CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // frequency synthesizer calibration + CC2500_WriteReg(CC2500_2C_TEST2, 0x88); // various test settings + CC2500_WriteReg(CC2500_2D_TEST1, 0x31); // various test settings + CC2500_WriteReg(CC2500_2E_TEST0, 0x0B); // various test settings + CC2500_WriteReg(CC2500_3E_PATABLE, 0xfe); + CC2500_SetTxRxMode(RX_EN); // Receive mode + CC2500_Strobe(CC2500_SIDLE); + CC2500_Strobe(CC2500_SRX);*/ + + CC2500_WriteReg(0x30, 0x3D); // software reset + CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0F); // Frequency Synthesizer Control (0x0F) + CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x12); // Packet Automation Control (0x12) + CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency control word, high byte + CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency control word, middle byte + CC2500_WriteReg(CC2500_0F_FREQ0, 0xDE); // Frequency control word, low byte + CC2500_WriteReg(CC2500_10_MDMCFG4, 0x0D); // Modem Configuration + CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration (0x3B) + CC2500_WriteReg(CC2500_12_MDMCFG2, 0x00); // Modem Configuration 0x30 - OOK modulation, 0x00 - FSK modulation (better sensitivity) + CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration + CC2500_WriteReg(CC2500_14_MDMCFG0, 0xFF); // Modem Configuration (0xFF) + CC2500_WriteReg(CC2500_17_MCSM1, 0x0F); // Always stay in RX mode + CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // Main Radio Control State Machine Configuration (0x04) + CC2500_WriteReg(CC2500_19_FOCCFG, 0x15); // Frequency Offset Compensation configuration + CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0x83); // AGC Control (0x83) + CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control + CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0x91); // AGC Control + CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_24_FSCAL2, 0x0A); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration + CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration + CC2500_SetTxRxMode(RX_EN); + delayMicroseconds(1000); // wait for RX to activate +} + +static void __attribute__((unused)) _calibrate() +{ + for (int c = 0; c < MAX_RADIOCHANNEL; c++) { + CC2500_Strobe(CC2500_SIDLE); + CC2500_WriteReg(CC2500_0A_CHANNR, c); + CC2500_Strobe(CC2500_SCAL); + delayMicroseconds(900); + calibration[c] = CC2500_ReadReg(CC2500_25_FSCAL1); + } + calibration_fscal3 = CC2500_ReadReg(CC2500_23_FSCAL3); // only needs to be done once + calibration_fscal2 = CC2500_ReadReg(CC2500_24_FSCAL2); // only needs to be done once + CC2500_Strobe(CC2500_SIDLE); +} + +static void __attribute__((unused)) _scan_next() +{ + CC2500_WriteReg(CC2500_0A_CHANNR, Scanner.chan_min + scan_channel); + + CC2500_WriteReg(CC2500_23_FSCAL3, calibration_fscal3); + CC2500_WriteReg(CC2500_24_FSCAL2, calibration_fscal2); + CC2500_WriteReg(CC2500_25_FSCAL1, calibration[scan_channel]); + + //debugln("_scan_next %d", Scanner.chan_min + scan_channel); +} + +static int __attribute__((unused)) _scan_rssi() +{ + uint8_t rssi = CC2500_ReadReg(0x40 | CC2500_34_RSSI); // 0.5 db/count, RSSI value read from the RSSI status register is a 2’s complement number + + debugln("rssi %d", rssi); + + uint8_t rssi_rel; + if (rssi >= 128) { + rssi_rel = rssi - 128; // relative power levels 0-127 (equals -137 to -72 dBm) + } + else { + rssi_rel = rssi + 128; // relativ power levels 128-255 (equals -73 to -10 dBm) + } + return rssi_rel; +} + +uint16 Scanner_callback() +{ + int rssi_value; + switch (scan_state) { + case SCAN_CHANNEL_CHANGE: + scan_channel++; + if (scan_channel >= (Scanner.chan_max - Scanner.chan_min + 1)) + scan_channel = 0; + _scan_next(); + scan_state = SCAN_GET_RSSI; + return CHANNEL_LOCK_TIME; + case SCAN_GET_RSSI: + rssi_value = _scan_rssi(); + scan_state = SCAN_CHANNEL_CHANGE; + + // debugln("%d\t%d", scan_channel, CC2500_ReadReg(CC2500_34_RSSI)); + // send data to TX + pkt[0] = scan_channel; // scan_channel + pkt[1] = rssi_value; // Scanner.rssi[scan_channel]; // power + telemetry_link = 1; + } + return AVERAGE_INTVL; +} + +uint16_t initScanner(void) +{ + Scanner.chan_min = 1;//MIN_RADIOCHANNEL; + Scanner.chan_max = 1;//MAX_RADIOCHANNEL; + + scan_averages = 0; + scan_channel = 0; + scan_state = SCAN_CHANNEL_CHANGE; + memset(Scanner.rssi, 0, sizeof(Scanner.rssi)); // clear old rssi values + CC2500_Reset(); + Scanner_cc2500_init(); + CC2500_SetPower(); + CC2500_Strobe(CC2500_SRX); + _calibrate(); + CC2500_Strobe(CC2500_SFSTXON); + delayMicroseconds(800); + CC2500_Strobe(CC2500_SIDLE); + CC2500_Strobe(CC2500_SRX); // Receive mode + BIND_DONE; + return 1250; +} + +#endif diff --git a/Multiprotocol/Scanner_cyrf6936.ino b/Multiprotocol/Scanner_cyrf6936.ino deleted file mode 100644 index f1e4cdc..0000000 --- a/Multiprotocol/Scanner_cyrf6936.ino +++ /dev/null @@ -1,134 +0,0 @@ -/* - This project is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Multiprotocol is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Multiprotocol. If not, see . - */ - -#if defined(SCANNER_CYRF6936_INO) - -// Ported from DeviationTX frequency scanner - -#include "iface_cyrf6936.h" - -struct Scanner { - uint8_t rssi[255]; - uint8_t chan_min; - uint8_t chan_max; - uint8_t attenuator; - uint16_t averaging; -} Scanner; - -#define MIN_RADIOCHANNEL 0x00 -#define MAX_RADIOCHANNEL 0x62 -#define CHANNEL_LOCK_TIME 300 // slow channel requires 270 usec for synthesizer to settle -#define AVERAGE_INTVL 30 - -static int scan_averages, scan_channel, scan_state; - -enum ScanStates { - SCAN_CHANNEL_CHANGE = 0, - SCAN_GET_RSSI = 1, -}; - -static void __attribute__((unused)) Scanner_cyrf_init() -{ - /* Initialize CYRF chip */ - CYRF_WriteRegister(CYRF_1D_MODE_OVERRIDE, 0x38); // FRC SEN (forces the synthesizer to start) + FRC AWAKE (force the oscillator to keep running at all times) - CYRF_WriteRegister(CYRF_03_TX_CFG, 0x08 | 7); // Data Code Length = 32 chip codes + Data Mode = 8DR Mode + max-power(+4 dBm) - CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4A); // LNA + FAST TURN EN + RXOW EN, enable low noise amplifier, fast turning, overwrite enable - CYRF_WriteRegister(CYRF_0B_PWR_CTRL, 0x00); // Reset power control - CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0xA4); // SOP EN + SOP LEN = 32 chips + LEN EN + SOP TH = 04h - CYRF_WriteRegister(CYRF_11_DATA32_THOLD, 0x05); // TH32 = 0x05 - CYRF_WriteRegister(CYRF_12_DATA64_THOLD, 0x0E); // TH64 = 0Eh, set pn correlation threshold - CYRF_WriteRegister(CYRF_1B_TX_OFFSET_LSB, 0x55); // STRIM LSB = 0x55, typical configuration - CYRF_WriteRegister(CYRF_1C_TX_OFFSET_MSB, 0x05); // STRIM MSB = 0x05, typical configuration - CYRF_WriteRegister(CYRF_32_AUTO_CAL_TIME, 0x3C); // AUTO_CAL_TIME = 3Ch, typical configuration - CYRF_WriteRegister(CYRF_35_AUTOCAL_OFFSET, 0x14); // AUTO_CAL_OFFSET = 14h, typical configuration - CYRF_WriteRegister(CYRF_39_ANALOG_CTRL, 0x01); // ALL SLOW - CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x10); // FRC RXDR (Force Receive Data Rate) - CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x00); // Reset TX overrides - CYRF_WriteRegister(CYRF_01_TX_LENGTH, 0x10); // TX Length = 16 byte packet - CYRF_WriteRegister(CYRF_27_CLK_OVERRIDE, 0x02); // RXF, force receive clock - CYRF_WriteRegister(CYRF_28_CLK_EN, 0x02); // RXF, force receive clock enable -} - -static void __attribute__((unused)) _scan_next() -{ - CYRF_ConfigRFChannel(scan_channel + Scanner.chan_min); - switch (Scanner.attenuator) { - case 0: CYRF_WriteRegister(CYRF_06_RX_CFG, 0x4A); break; // LNA on, ATT off - case 1: CYRF_WriteRegister(CYRF_06_RX_CFG, 0x0A); break; // LNA off, ATT off - default: CYRF_WriteRegister(CYRF_06_RX_CFG, 0x2A); break; // LNA off, no ATT on - } -} - -static int __attribute__((unused)) _scan_rssi() -{ - if (!(CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80)) { - CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x80); // Prepare to receive - delayMicroseconds(1); - CYRF_ReadRegister(CYRF_13_RSSI); // dummy read - delayMicroseconds(1); - } - return CYRF_ReadRegister(CYRF_13_RSSI) & 0x1F; -} - -uint16 Scanner_callback() -{ - int rssi_value; - switch (scan_state) { - case SCAN_CHANNEL_CHANGE: - scan_averages = 0; - scan_channel++; - if (scan_channel == (Scanner.chan_max - Scanner.chan_min + 1)) - scan_channel = 0; - _scan_next(); - scan_state = SCAN_GET_RSSI; - return CHANNEL_LOCK_TIME; - case SCAN_GET_RSSI: - rssi_value = _scan_rssi(); - Scanner.rssi[scan_channel] = (rssi_value + 9 * Scanner.rssi[scan_channel]) / 10; // fast exponential smoothing with alpha 0.1 - scan_averages++; - if (scan_averages < Scanner.averaging) - return AVERAGE_INTVL + random(0xfefefefe) % 10; // make measurements slightly random in time - scan_state = SCAN_CHANNEL_CHANGE; - - // send data to TX - pkt[0] = scan_channel; // channel - pkt[1] = Scanner.rssi[scan_channel]; // power - telemetry_link = 1; - - return AVERAGE_INTVL; - } -} - -uint16_t initScanner(void) -{ - Scanner.chan_min = MIN_RADIOCHANNEL; - Scanner.chan_max = MAX_RADIOCHANNEL; - - // todo: find optimal values or use user options - Scanner.averaging = 2; - Scanner.attenuator = 0; - - scan_averages = 0; - scan_channel = 0; - scan_state = SCAN_CHANNEL_CHANGE; - memset(Scanner.rssi, 0, sizeof(Scanner.rssi)); // clear old rssi values - CYRF_Reset(); - Scanner_cyrf_init(); - CYRF_SetTxRxMode(RX_EN); // Receive mode - BIND_DONE; - return 1250; -} - -#endif diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index e451420..ede08d2 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -177,7 +177,6 @@ #undef WFLY_CYRF6936_INO #undef WK2x01_CYRF6936_INO #undef TRAXXAS_CYRF6936_INO - #undef SCANNER_CYRF6936_INO #endif #ifndef CC2500_INSTALLED #undef FRSKYD_CC2500_INO @@ -188,6 +187,7 @@ #undef REDPINE_CC2500_INO #undef HITEC_CC2500_INO #undef XN297L_CC2500_EMU + #undef SCANNER_CC2500_INO #endif #ifndef NRF24L01_INSTALLED #undef BAYANG_NRF24L01_INO diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index af5dff1..8155f10 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -23,7 +23,7 @@ //If you know parameters you want for sure to be enabled or disabled which survives in future, you can use a file named "_MyConfig.h". //An example is given within the file named "_MyConfig.h.example" which needs to be renamed if you want to use it. //To enable this config file remove the // from the line below. -//#define USE_MY_CONFIG +#define USE_MY_CONFIG /*************************/ @@ -32,7 +32,7 @@ //Allow flashing multimodule directly with TX(erky9x or opentx maintenance mode) //Instructions:https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/docs/Flash_from_Tx.md //To disable this feature add "//" at the begining of the next line. Requires a compatible bootloader or upload method to be selected when you use the Multi 4-in-1 Boards Manager definitions. -#define CHECK_FOR_BOOTLOADER +//#define CHECK_FOR_BOOTLOADER /*******************/ @@ -168,7 +168,6 @@ #define TRAXXAS_CYRF6936_INO #define WFLY_CYRF6936_INO #define WK2x01_CYRF6936_INO -#define SCANNER_CYRF6936_INO //The protocols below need a CC2500 to be installed #define CORONA_CC2500_INO @@ -178,6 +177,7 @@ #define HITEC_CC2500_INO #define SFHSS_CC2500_INO #define REDPINE_CC2500_INO +#define SCANNER_CC2500_INO //The protocols below need a NRF24L01 to be installed #define ASSAN_NRF24L01_INO