From 5dfe371b689a422bb2fd1e06dd16d319c6a20b61 Mon Sep 17 00:00:00 2001 From: Goebish Date: Sat, 31 Aug 2019 18:47:09 +0200 Subject: [PATCH] Add spectrum scanner protocol --- Multiprotocol/Multiprotocol.h | 2 + Multiprotocol/Multiprotocol.ino | 7 ++ Multiprotocol/Scanner_cyrf6936.ino | 136 +++++++++++++++++++++++++++++ Multiprotocol/Telemetry.ino | 22 +++++ Multiprotocol/Validate.h | 4 +- Multiprotocol/_Config.h | 4 + 6 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 Multiprotocol/Scanner_cyrf6936.ino diff --git a/Multiprotocol/Multiprotocol.h b/Multiprotocol/Multiprotocol.h index 5a44ea8..338ad2a 100644 --- a/Multiprotocol/Multiprotocol.h +++ b/Multiprotocol/Multiprotocol.h @@ -78,6 +78,7 @@ enum PROTOCOLS PROTO_KF606 = 49, // =>NRF24L01 PROTO_REDPINE = 50, // =>CC2500 PROTO_POTENSIC = 51, // =>NRF24L01 + PROTO_SCANNER = 54, // =>CYRF6936 PROTO_XN297DUMP = 63, // =>NRF24L01 }; @@ -307,6 +308,7 @@ enum MultiPacketTypes MULTI_TELEMETRY_SYNC = 8, MULTI_TELEMETRY_SPORT_POLLING = 9, MULTI_TELEMETRY_HITEC = 10, + MULTI_TELEMETRY_SCANNER = 11, }; // Macros diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index 1156b12..8d204d6 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -1058,6 +1058,13 @@ static void protocol_init() remote_callback = ReadJ6Pro; 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_cyrf6936.ino b/Multiprotocol/Scanner_cyrf6936.ino new file mode 100644 index 0000000..e207aea --- /dev/null +++ b/Multiprotocol/Scanner_cyrf6936.ino @@ -0,0 +1,136 @@ +/* + 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 = 1; + + 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(); + init_frskyd_link_telemetry(); // use FrSkyD HUB to send scanner data + //telemetry_lost = 1; + CYRF_SetTxRxMode(RX_EN); // Receive mode + BIND_DONE; + return 1250; +} + +#endif diff --git a/Multiprotocol/Telemetry.ino b/Multiprotocol/Telemetry.ino index 3c281b5..9a87fdc 100644 --- a/Multiprotocol/Telemetry.ino +++ b/Multiprotocol/Telemetry.ino @@ -170,6 +170,19 @@ static void multi_send_status() #endif #endif +#ifdef SCANNER_TELEMETRY + void spectrum_scanner_frame() + { + #if defined MULTI_TELEMETRY + multi_send_header(MULTI_TELEMETRY_SCANNER, 2); + #else + Serial_write(0xAA); // Telemetry packet + #endif + Serial_write(pkt[0]); // frequency (channel) + Serial_write(pkt[1]); // RSSI power level + } +#endif + #ifdef AFHDS2A_FW_TELEMETRY void AFHDSA_short_frame() { @@ -1008,6 +1021,15 @@ void TelemetryUpdate() return; } #endif + + #if defined SCANNER_TELEMETRY + if (telemetry_link && protocol == PROTO_SCANNER) + { + spectrum_scanner_frame(); + telemetry_link = 0; + return; + } + #endif } diff --git a/Multiprotocol/Validate.h b/Multiprotocol/Validate.h index 75f82c0..28e737f 100644 --- a/Multiprotocol/Validate.h +++ b/Multiprotocol/Validate.h @@ -152,6 +152,7 @@ #undef WFLY_CYRF6936_INO #undef WK2x01_CYRF6936_INO #undef TRAXXAS_CYRF6936_INO + #undef SCANNER_CYRF6936_INO #endif #ifndef CC2500_INSTALLED #undef FRSKYD_CC2500_INO @@ -217,6 +218,7 @@ #undef DSM_TELEMETRY #undef MULTI_STATUS #undef MULTI_TELEMETRY + #undef SCANNER_TELEMETRY #else #if defined MULTI_TELEMETRY && not defined INVERT_TELEMETRY #warning MULTI_TELEMETRY has been defined but not INVERT_TELEMETRY. They should be both enabled for OpenTX telemetry and status to work. @@ -227,7 +229,7 @@ #if not defined(NCC1701_NRF24L01_INO) #undef NCC1701_HUB_TELEMETRY #endif - #if not ( defined(BUGS_A7105_INO) || defined(BUGSMINI_NRF24L01_INO) ) + #if not defined(BUGS_A7105_INO) || not defined(BUGSMINI_NRF24L01_INO) #undef BUGS_HUB_TELEMETRY #endif #if not defined(CABELL_NRF24L01_INO) diff --git a/Multiprotocol/_Config.h b/Multiprotocol/_Config.h index b39f7ea..dd445be 100644 --- a/Multiprotocol/_Config.h +++ b/Multiprotocol/_Config.h @@ -165,6 +165,7 @@ #define J6PRO_CYRF6936_INO #define WFLY_CYRF6936_INO #define WK2x01_CYRF6936_INO +#define SCANNER_CYRF6936_INO //#define TRAXXAS_CYRF6936_INO @@ -292,6 +293,7 @@ #define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX #define HITEC_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to the radios which can decode it like er9x, ersky9x and OpenTX #define HITEC_FW_TELEMETRY // Under development: Forward received telemetry packets to be decoded by ersky9x and OpenTX +#define SCANNER_TELEMETRY // Forward spectrum scanner data to TX //SPORT_POLLING is an implementation of the same polling routine as XJT module for sport telemetry bidirectional communication. //This is useful for passing sport control frames from TX to RX(ex: changing Betaflight PID or VTX channels on the fly using LUA scripts with OpentX). @@ -607,6 +609,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= { PROTO_REDPINE RED_FAST RED_SLOW + PROTO_SCANNER + NONE PROTO_SFHSS NONE PROTO_SHENQI