diff --git a/src/main/build/debug.c b/src/main/build/debug.c index e9e08c2df..87237bdd4 100644 --- a/src/main/build/debug.c +++ b/src/main/build/debug.c @@ -50,6 +50,7 @@ const char * const debugModeNames[DEBUG_COUNT] = { "FFT_TIME", "FFT_FREQ", "RX_FRSKY_SPI", + "RX_SFHSS_SPI", "GYRO_RAW", "DUAL_GYRO", "DUAL_GYRO_RAW", diff --git a/src/main/build/debug.h b/src/main/build/debug.h index 455764233..03111c48a 100644 --- a/src/main/build/debug.h +++ b/src/main/build/debug.h @@ -68,6 +68,7 @@ typedef enum { DEBUG_FFT_TIME, DEBUG_FFT_FREQ, DEBUG_RX_FRSKY_SPI, + DEBUG_RX_SFHSS_SPI, DEBUG_GYRO_RAW, DEBUG_DUAL_GYRO, DEBUG_DUAL_GYRO_RAW, diff --git a/src/main/interface/cli.c b/src/main/interface/cli.c index e0233dc98..636d622e3 100644 --- a/src/main/interface/cli.c +++ b/src/main/interface/cli.c @@ -141,6 +141,7 @@ extern uint8_t __config_end; #include "rx/spektrum.h" #include "rx/cc2500_frsky_common.h" #include "rx/cc2500_frsky_x.h" +#include "rx/cc2500_common.h" #include "scheduler/scheduler.h" @@ -2560,13 +2561,14 @@ static void cliBeeper(char *cmdline) } #endif -#ifdef USE_RX_FRSKY_SPI -void cliFrSkyBind(char *cmdline){ +#ifdef USE_RX_BIND +void cliRxBind(char *cmdline){ UNUSED(cmdline); switch (rxSpiConfig()->rx_spi_protocol) { case RX_SPI_FRSKY_D: case RX_SPI_FRSKY_X: - frSkySpiBind(); + case RX_SPI_SFHSS: + cc2500SpiBind(); cliPrint("Binding..."); @@ -4464,8 +4466,9 @@ const clicmd_t cmdTable[] = { CLI_COMMAND_DEF("flash_write", NULL, "
", cliFlashWrite), #endif #endif -#ifdef USE_RX_FRSKY_SPI - CLI_COMMAND_DEF("frsky_bind", "initiate binding for FrSky SPI RX", NULL, cliFrSkyBind), +#ifdef USE_RX_BIND + CLI_COMMAND_DEF("frsky_bind", "initiate binding for FrSky SPI RX", NULL, cliRxBind), /* legacy */ + CLI_COMMAND_DEF("rx_bind", "initiate binding for RX", NULL, cliRxBind), #endif CLI_COMMAND_DEF("get", "get variable value", "[name]", cliGet), #ifdef USE_GPS diff --git a/src/main/interface/settings.c b/src/main/interface/settings.c index 27a000cfc..3abc57f2d 100644 --- a/src/main/interface/settings.c +++ b/src/main/interface/settings.c @@ -87,6 +87,7 @@ #include "rx/rx.h" #include "rx/cc2500_frsky_common.h" +#include "rx/cc2500_sfhss.h" #include "rx/spektrum.h" #include "sensors/acceleration.h" @@ -224,7 +225,8 @@ static const char * const lookupTableRxSpi[] = { "FRSKY_X", "FLYSKY", "FLYSKY_2A", - "KN" + "KN", + "SFHSS" }; #endif @@ -1112,6 +1114,10 @@ const clivalue_t valueTable[] = { { "frsky_spi_bind_hop_data", VAR_UINT8 | MASTER_VALUE | MODE_ARRAY, .config.array.length = 50, PG_RX_FRSKY_SPI_CONFIG, offsetof(rxFrSkySpiConfig_t, bindHopData) }, { "frsky_x_rx_num", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, 255 }, PG_RX_FRSKY_SPI_CONFIG, offsetof(rxFrSkySpiConfig_t, rxNum) }, { "frsky_spi_use_external_adc", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_RX_FRSKY_SPI_CONFIG, offsetof(rxFrSkySpiConfig_t, useExternalAdc) }, +#endif +#ifdef USE_RX_SFHSS_SPI + { "sfhss_spi_tx_id", VAR_UINT8 | MASTER_VALUE | MODE_ARRAY, .config.array.length = 2, PG_RX_SFHSS_SPI_CONFIG, offsetof(rxSfhssSpiConfig_t, bindTxId) }, + { "sfhss_spi_offset", VAR_INT8 | MASTER_VALUE, .config.minmax = { -127, 127 }, PG_RX_SFHSS_SPI_CONFIG, offsetof(rxSfhssSpiConfig_t, bindOffset) }, #endif { "led_inversion", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, ((1 << STATUS_LED_NUMBER) - 1) }, PG_STATUS_LED_CONFIG, offsetof(statusLedConfig_t, inversion) }, #ifdef USE_DASHBOARD diff --git a/src/main/pg/pg_ids.h b/src/main/pg/pg_ids.h index d17448229..1c98456e2 100644 --- a/src/main/pg/pg_ids.h +++ b/src/main/pg/pg_ids.h @@ -135,7 +135,8 @@ #define PG_BOARD_CONFIG 538 #define PG_RCDEVICE_CONFIG 539 #define PG_GYRO_DEVICE_CONFIG 540 -#define PG_BETAFLIGHT_END 540 +#define PG_RX_SFHSS_SPI_CONFIG 541 +#define PG_BETAFLIGHT_END 541 // OSD configuration (subject to change) diff --git a/src/main/rx/cc2500_common.c b/src/main/rx/cc2500_common.c new file mode 100755 index 000000000..5c2183f93 --- /dev/null +++ b/src/main/rx/cc2500_common.c @@ -0,0 +1,229 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software 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. + * + * Cleanflight and Betaflight are distributed in the hope that they + * 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 this software. + * + * If not, see . + */ + +#include + +#include "platform.h" + +#if defined(USE_RX_FRSKY_SPI) || defined(USE_RX_SFHSS_SPI) + +#include "common/maths.h" + +#include "pg/pg.h" +#include "pg/pg_ids.h" +#include "pg/rx.h" +#include "pg/rx_spi.h" + +#include "drivers/rx/rx_cc2500.h" +#include "drivers/io.h" +#include "drivers/time.h" + +#include "fc/config.h" + +#include "rx/rx.h" +#include "rx/rx_spi.h" + +#include "rx/cc2500_common.h" + +static IO_t gdoPin; +static IO_t bindPin = DEFIO_IO(NONE); +static IO_t cc2500LedPin; +static bool bindRequested; + +static bool lastBindPinStatus; +#if defined(USE_RX_CC2500_SPI_PA_LNA) +static IO_t txEnPin; +static IO_t rxLnaEnPin; +static IO_t antSelPin; +#endif +static int16_t rssiDbm; + +uint16_t cc2500getRssiDbm(void) +{ + return rssiDbm; +} + +void cc2500setRssiDbm(uint8_t value) +{ + if (value >= 128) { + rssiDbm = ((((uint16_t)value) * 18) >> 5) - 82; + } else { + rssiDbm = ((((uint16_t)value) * 18) >> 5) + 65; + } + + setRssi(rssiDbm << 3, RSSI_SOURCE_RX_PROTOCOL); +} + +void cc2500SpiBind(void) +{ + bindRequested = true; +} + +bool cc2500checkBindRequested(bool reset) +{ + if (bindPin) { + bool bindPinStatus = IORead(bindPin); + if (lastBindPinStatus && !bindPinStatus) { + bindRequested = true; + } + lastBindPinStatus = bindPinStatus; + } + + if (!bindRequested) { + return false; + } else { + if (reset) { + bindRequested = false; + } + + return true; + } +} + +bool cc2500getGdo(void) +{ + return IORead(gdoPin); +} + +#if defined(USE_RX_CC2500_SPI_PA_LNA) && defined(USE_RX_CC2500_SPI_DIVERSITY) +void cc2500switchAntennae(void) +{ + static bool alternativeAntennaSelected = true; + + if (alternativeAntennaSelected) { + IOLo(antSelPin); + } else { + IOHi(antSelPin); + } + alternativeAntennaSelected = !alternativeAntennaSelected; +} +#endif +#if defined(USE_RX_CC2500_SPI_PA_LNA) +void cc2500TxEnable(void) +{ + IOHi(txEnPin); +} + +void cc2500TxDisable(void) +{ + IOLo(txEnPin); +} +#endif + +void cc2500LedOn(void) +{ +#if defined(RX_CC2500_SPI_LED_PIN_INVERTED) + IOLo(cc2500LedPin); +#else + IOHi(cc2500LedPin); +#endif +} + +void cc2500LedOff(void) +{ +#if defined(RX_CC2500_SPI_LED_PIN_INVERTED) + IOHi(cc2500LedPin); +#else + IOLo(cc2500LedPin); +#endif +} + +void cc2500LedBlink(timeMs_t blinkms) +{ + static bool ledIsOn=true; + static timeMs_t ledBlinkMs = 0; + + if ( (ledBlinkMs + blinkms) > millis() ){ + return; + } + ledBlinkMs = millis(); + + if (ledIsOn) { + cc2500LedOff(); + } else { + cc2500LedOn(); + } + ledIsOn = !ledIsOn; +} + +static bool cc2500SpiDetect(void) +{ + const uint8_t chipPartNum = cc2500ReadReg(CC2500_30_PARTNUM | CC2500_READ_BURST); //CC2500 read registers chip part num + const uint8_t chipVersion = cc2500ReadReg(CC2500_31_VERSION | CC2500_READ_BURST); //CC2500 read registers chip version + if (chipPartNum == 0x80 && chipVersion == 0x03) { + return true; + } + + return false; +} + +bool cc2500SpiInit(void) +{ +#if !defined(RX_CC2500_SPI_DISABLE_CHIP_DETECTION) + if (!cc2500SpiDetect()) { + return false; + } +#else + UNUSED(cc2500SpiDetect); +#endif + + if (rssiSource == RSSI_SOURCE_NONE) { + rssiSource = RSSI_SOURCE_RX_PROTOCOL; + } + + // gpio init here + gdoPin = IOGetByTag(IO_TAG(RX_CC2500_SPI_GDO_0_PIN)); + IOInit(gdoPin, OWNER_RX_SPI, 0); + IOConfigGPIO(gdoPin, IOCFG_IN_FLOATING); + cc2500LedPin = IOGetByTag(IO_TAG(RX_CC2500_SPI_LED_PIN)); + IOInit(cc2500LedPin, OWNER_LED, 0); + IOConfigGPIO(cc2500LedPin, IOCFG_OUT_PP); +#if defined(USE_RX_CC2500_SPI_PA_LNA) + rxLnaEnPin = IOGetByTag(IO_TAG(RX_CC2500_SPI_LNA_EN_PIN)); + IOInit(rxLnaEnPin, OWNER_RX_SPI, 0); + IOConfigGPIO(rxLnaEnPin, IOCFG_OUT_PP); + IOHi(rxLnaEnPin); // always on at the moment + txEnPin = IOGetByTag(IO_TAG(RX_CC2500_SPI_TX_EN_PIN)); + IOInit(txEnPin, OWNER_RX_SPI, 0); + IOConfigGPIO(txEnPin, IOCFG_OUT_PP); +#if defined(USE_RX_CC2500_SPI_DIVERSITY) + antSelPin = IOGetByTag(IO_TAG(RX_CC2500_SPI_ANT_SEL_PIN)); + IOInit(antSelPin, OWNER_RX_SPI, 0); + IOConfigGPIO(antSelPin, IOCFG_OUT_PP); +#endif +#endif // USE_RX_CC2500_SPI_PA_LNA +#if defined(BINDPLUG_PIN) + bindPin = IOGetByTag(IO_TAG(BINDPLUG_PIN)); + IOInit(bindPin, OWNER_RX_BIND, 0); + IOConfigGPIO(bindPin, IOCFG_IPU); + + lastBindPinStatus = IORead(bindPin); +#endif + +#if defined(USE_RX_CC2500_SPI_PA_LNA) +#if defined(USE_RX_CC2500_SPI_DIVERSITY) + IOHi(antSelPin); +#endif + cc2500TxDisable(); +#endif // USE_RX_CC2500_SPI_PA_LNA + + return true; +} +#endif diff --git a/src/main/rx/cc2500_common.h b/src/main/rx/cc2500_common.h new file mode 100755 index 000000000..cfd2092cb --- /dev/null +++ b/src/main/rx/cc2500_common.h @@ -0,0 +1,43 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software 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. + * + * Cleanflight and Betaflight are distributed in the hope that they + * 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 this software. + * + * If not, see . + */ + +#pragma once + +#include "pg/pg.h" + +#include "rx/rx_spi.h" + +uint16_t cc2500getRssiDbm(void); +void cc2500setRssiDbm(uint8_t value); +void cc2500SpiBind(void); +bool cc2500checkBindRequested(bool reset); +bool cc2500getGdo(void); +#if defined(USE_RX_CC2500_SPI_PA_LNA) && defined(USE_RX_CC2500_SPI_DIVERSITY) +void cc2500switchAntennae(void); +#endif +#if defined(USE_RX_CC2500_SPI_PA_LNA) +void cc2500TxEnable(void); +void cc2500TxDisable(void); +#endif +void cc2500LedOn(void); +void cc2500LedOff(void); +void cc2500LedBlink(timeMs_t blinkms); +bool cc2500SpiInit(void); + diff --git a/src/main/rx/cc2500_frsky_common.h b/src/main/rx/cc2500_frsky_common.h index 26d9b98df..381a4e250 100644 --- a/src/main/rx/cc2500_frsky_common.h +++ b/src/main/rx/cc2500_frsky_common.h @@ -39,4 +39,3 @@ bool frSkySpiInit(const rxSpiConfig_t *rxSpiConfig, rxRuntimeConfig_t *rxRuntime rx_spi_received_e frSkySpiDataReceived(uint8_t *packet); void frSkySpiSetRcData(uint16_t *rcData, const uint8_t *payload); -void frSkySpiBind(void); diff --git a/src/main/rx/cc2500_frsky_d.c b/src/main/rx/cc2500_frsky_d.c index 5389afc2a..822ecb56e 100644 --- a/src/main/rx/cc2500_frsky_d.c +++ b/src/main/rx/cc2500_frsky_d.c @@ -46,6 +46,7 @@ #include "fc/config.h" +#include "rx/cc2500_common.h" #include "rx/cc2500_frsky_common.h" #include "rx/cc2500_frsky_shared.h" @@ -123,7 +124,7 @@ static void buildTelemetryFrame(uint8_t *packet) frame[2] = rxFrSkySpiConfig()->bindTxId[1]; frame[3] = a1Value; frame[4] = a2Value; - frame[5] = (uint8_t)rssiDbm; + frame[5] = (uint8_t)cc2500getRssiDbm(); uint8_t bytesUsed = 0; #if defined(USE_TELEMETRY_FRSKY_HUB) if (telemetryEnabled) { @@ -195,7 +196,7 @@ rx_spi_received_e frSkyDHandlePacket(uint8_t * const packet, uint8_t * const pro lastPacketReceivedTime = currentPacketReceivedTime; *protocolState = STATE_DATA; - if (checkBindRequested(false)) { + if (cc2500checkBindRequested(false)) { lastPacketReceivedTime = 0; timeoutUs = 50; missingPackets = 0; @@ -207,7 +208,7 @@ rx_spi_received_e frSkyDHandlePacket(uint8_t * const packet, uint8_t * const pro FALLTHROUGH; //!!TODO -check this fall through is correct // here FS code could be case STATE_DATA: - if (IORead(gdoPin)) { + if (cc2500getGdo()) { uint8_t ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; if (ccLen >= 20) { cc2500ReadFifo(packet, 20); @@ -217,12 +218,12 @@ rx_spi_received_e frSkyDHandlePacket(uint8_t * const packet, uint8_t * const pro if (packet[0] == 0x11) { if ((packet[1] == rxFrSkySpiConfig()->bindTxId[0]) && (packet[2] == rxFrSkySpiConfig()->bindTxId[1])) { - LedOn(); + cc2500LedOn(); nextChannel(1); #if defined(USE_RX_FRSKY_SPI_TELEMETRY) if ((packet[3] % 4) == 2) { telemetryTimeUs = micros(); - setRssiDbm(packet[18]); + cc2500setRssiDbm(packet[18]); buildTelemetryFrame(packet); *protocolState = STATE_TELEMETRY; } else @@ -240,13 +241,13 @@ rx_spi_received_e frSkyDHandlePacket(uint8_t * const packet, uint8_t * const pro } if (cmpTimeUs(currentPacketReceivedTime, lastPacketReceivedTime) > (timeoutUs * SYNC_DELAY_MAX)) { -#if defined(USE_RX_FRSKY_SPI_PA_LNA) - TxDisable(); +#if defined(USE_RX_CC2500_SPI_PA_LNA) + cc2500TxDisable(); #endif if (timeoutUs == 1) { -#if defined(USE_RX_FRSKY_SPI_PA_LNA) && defined(USE_RX_FRSKY_SPI_DIVERSITY) // SE4311 chip +#if defined(USE_RX_CC2500_SPI_PA_LNA) && defined(USE_RX_CC2500_SPI_DIVERSITY) // SE4311 chip if (missingPackets >= 2) { - switchAntennae(); + cc2500switchAntennae(); } #endif @@ -262,9 +263,9 @@ rx_spi_received_e frSkyDHandlePacket(uint8_t * const packet, uint8_t * const pro nextChannel(1); } else { if (ledIsOn) { - LedOff(); + cc2500LedOff(); } else { - LedOn(); + cc2500LedOn(); } ledIsOn = !ledIsOn; @@ -284,8 +285,8 @@ rx_spi_received_e frSkyDHandlePacket(uint8_t * const packet, uint8_t * const pro cc2500Strobe(CC2500_SIDLE); cc2500SetPower(6); cc2500Strobe(CC2500_SFRX); -#if defined(USE_RX_FRSKY_SPI_PA_LNA) - TxEnable(); +#if defined(USE_RX_CC2500_SPI_PA_LNA) + cc2500TxEnable(); #endif cc2500Strobe(CC2500_SIDLE); cc2500WriteFifo(frame, frame[0] + 1); diff --git a/src/main/rx/cc2500_frsky_shared.c b/src/main/rx/cc2500_frsky_shared.c index cb5941752..6ba52305c 100644 --- a/src/main/rx/cc2500_frsky_shared.c +++ b/src/main/rx/cc2500_frsky_shared.c @@ -40,6 +40,7 @@ #include "rx/rx.h" #include "rx/rx_spi.h" +#include "rx/cc2500_common.h" #include "rx/cc2500_frsky_common.h" #include "rx/cc2500_frsky_d.h" #include "rx/cc2500_frsky_x.h" @@ -59,9 +60,6 @@ static timeMs_t timeTunedMs; uint8_t listLength; static uint8_t bindIdx; static int8_t bindOffset; -static bool lastBindPinStatus; - -static bool bindRequested; typedef uint8_t handlePacketFn(uint8_t * const packet, uint8_t * const protocolState); typedef void setRcDataFn(uint16_t *rcData, const uint8_t *payload); @@ -69,20 +67,6 @@ typedef void setRcDataFn(uint16_t *rcData, const uint8_t *payload); static handlePacketFn *handlePacket; static setRcDataFn *setRcData; -IO_t gdoPin; -static IO_t bindPin = DEFIO_IO(NONE); -static IO_t frSkyLedPin; - -#if defined(USE_RX_FRSKY_SPI_PA_LNA) -static IO_t txEnPin; -static IO_t rxLnaEnPin; -static IO_t antSelPin; -#endif - -#ifdef USE_RX_FRSKY_SPI_TELEMETRY -int16_t rssiDbm; -#endif - PG_REGISTER_WITH_RESET_TEMPLATE(rxFrSkySpiConfig_t, rxFrSkySpiConfig, PG_RX_FRSKY_SPI_CONFIG, 1); PG_RESET_TEMPLATE(rxFrSkySpiConfig_t, rxFrSkySpiConfig, @@ -97,52 +81,9 @@ PG_RESET_TEMPLATE(rxFrSkySpiConfig_t, rxFrSkySpiConfig, .useExternalAdc = false, ); -#if defined(USE_RX_FRSKY_SPI_TELEMETRY) -void setRssiDbm(uint8_t value) -{ - if (value >= 128) { - rssiDbm = ((((uint16_t)value) * 18) >> 5) - 82; - } else { - rssiDbm = ((((uint16_t)value) * 18) >> 5) + 65; - } - - setRssi(rssiDbm << 3, RSSI_SOURCE_RX_PROTOCOL); -} -#endif // USE_RX_FRSKY_SPI_TELEMETRY - -#if defined(USE_RX_FRSKY_SPI_PA_LNA) -void TxEnable(void) -{ - IOHi(txEnPin); -} - -void TxDisable(void) -{ - IOLo(txEnPin); -} -#endif - -void LedOn(void) -{ -#if defined(RX_FRSKY_SPI_LED_PIN_INVERTED) - IOLo(frSkyLedPin); -#else - IOHi(frSkyLedPin); -#endif -} - -void LedOff(void) -{ -#if defined(RX_FRSKY_SPI_LED_PIN_INVERTED) - IOHi(frSkyLedPin); -#else - IOLo(frSkyLedPin); -#endif -} - void frSkySpiBind(void) { - bindRequested = true; + cc2500SpiBind(); } static void initialise() { @@ -252,7 +193,7 @@ static bool tuneRx(uint8_t *packet) bindOffset += 5; cc2500WriteReg(CC2500_0C_FSCTRL0, (uint8_t)bindOffset); } - if (IORead(gdoPin)) { + if (cc2500getGdo()) { uint8_t ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; if (ccLen) { cc2500ReadFifo(packet, ccLen); @@ -292,7 +233,7 @@ static bool getBind1(uint8_t *packet) // len|bind |tx // id|03|01|idx|h0|h1|h2|h3|h4|00|00|00|00|00|00|00|00|00|00|00|00|00|00|00|CHK1|CHK2|RSSI|LQI/CRC| // Start by getting bind packet 0 and the txid - if (IORead(gdoPin)) { + if (cc2500getGdo()) { uint8_t ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; if (ccLen) { cc2500ReadFifo(packet, ccLen); @@ -321,7 +262,7 @@ static bool getBind1(uint8_t *packet) static bool getBind2(uint8_t *packet) { if (bindIdx <= 120) { - if (IORead(gdoPin)) { + if (cc2500getGdo()) { uint8_t ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; if (ccLen) { cc2500ReadFifo(packet, ccLen); @@ -369,27 +310,6 @@ static bool getBind2(uint8_t *packet) } } -bool checkBindRequested(bool reset) -{ - if (bindPin) { - bool bindPinStatus = IORead(bindPin); - if (lastBindPinStatus && !bindPinStatus) { - bindRequested = true; - } - lastBindPinStatus = bindPinStatus; - } - - if (!bindRequested) { - return false; - } else { - if (reset) { - bindRequested = false; - } - - return true; - } -} - rx_spi_received_e frSkySpiDataReceived(uint8_t *packet) { rx_spi_received_e ret = RX_SPI_RECEIVED_NONE; @@ -404,8 +324,8 @@ rx_spi_received_e frSkySpiDataReceived(uint8_t *packet) break; case STATE_BIND: - if (checkBindRequested(true) || rxFrSkySpiConfig()->autoBind) { - LedOn(); + if (cc2500checkBindRequested(true) || rxFrSkySpiConfig()->autoBind) { + cc2500LedOn(); initTuneRx(); protocolState = STATE_BIND_TUNING; @@ -443,9 +363,9 @@ rx_spi_received_e frSkySpiDataReceived(uint8_t *packet) } else { uint8_t ctr = 40; while (ctr--) { - LedOn(); + cc2500LedOn(); delay(50); - LedOff(); + cc2500LedOff(); delay(50); } } @@ -489,40 +409,9 @@ void nextChannel(uint8_t skip) } } -#if defined(USE_RX_FRSKY_SPI_PA_LNA) && defined(USE_RX_FRSKY_SPI_DIVERSITY) -void switchAntennae(void) -{ - static bool alternativeAntennaSelected = true; - - if (alternativeAntennaSelected) { - IOLo(antSelPin); - } else { - IOHi(antSelPin); - } - alternativeAntennaSelected = !alternativeAntennaSelected; -} -#endif - -static bool frSkySpiDetect(void) -{ - const uint8_t chipPartNum = cc2500ReadReg(CC2500_30_PARTNUM | CC2500_READ_BURST); //CC2500 read registers chip part num - const uint8_t chipVersion = cc2500ReadReg(CC2500_31_VERSION | CC2500_READ_BURST); //CC2500 read registers chip version - if (chipPartNum == 0x80 && chipVersion == 0x03) { - return true; - } - - return false; -} - bool frSkySpiInit(const rxSpiConfig_t *rxSpiConfig, rxRuntimeConfig_t *rxRuntimeConfig) { -#if !defined(RX_FRSKY_SPI_DISABLE_CHIP_DETECTION) - if (!frSkySpiDetect()) { - return false; - } -#else - UNUSED(frSkySpiDetect); -#endif + cc2500SpiInit(); spiProtocol = rxSpiConfig->rx_spi_protocol; @@ -554,42 +443,6 @@ bool frSkySpiInit(const rxSpiConfig_t *rxSpiConfig, rxRuntimeConfig_t *rxRuntime } #endif - // gpio init here - gdoPin = IOGetByTag(IO_TAG(RX_FRSKY_SPI_GDO_0_PIN)); - IOInit(gdoPin, OWNER_RX_SPI, 0); - IOConfigGPIO(gdoPin, IOCFG_IN_FLOATING); - frSkyLedPin = IOGetByTag(IO_TAG(RX_FRSKY_SPI_LED_PIN)); - IOInit(frSkyLedPin, OWNER_LED, 0); - IOConfigGPIO(frSkyLedPin, IOCFG_OUT_PP); -#if defined(USE_RX_FRSKY_SPI_PA_LNA) - rxLnaEnPin = IOGetByTag(IO_TAG(RX_FRSKY_SPI_LNA_EN_PIN)); - IOInit(rxLnaEnPin, OWNER_RX_SPI, 0); - IOConfigGPIO(rxLnaEnPin, IOCFG_OUT_PP); - IOHi(rxLnaEnPin); // always on at the moment - txEnPin = IOGetByTag(IO_TAG(RX_FRSKY_SPI_TX_EN_PIN)); - IOInit(txEnPin, OWNER_RX_SPI, 0); - IOConfigGPIO(txEnPin, IOCFG_OUT_PP); -#if defined(USE_RX_FRSKY_SPI_DIVERSITY) - antSelPin = IOGetByTag(IO_TAG(RX_FRSKY_SPI_ANT_SEL_PIN)); - IOInit(antSelPin, OWNER_RX_SPI, 0); - IOConfigGPIO(antSelPin, IOCFG_OUT_PP); -#endif -#endif // USE_RX_FRSKY_SPI_PA_LNA -#if defined(BINDPLUG_PIN) - bindPin = IOGetByTag(IO_TAG(BINDPLUG_PIN)); - IOInit(bindPin, OWNER_RX_BIND, 0); - IOConfigGPIO(bindPin, IOCFG_IPU); - - lastBindPinStatus = IORead(bindPin); -#endif - -#if defined(USE_RX_FRSKY_SPI_PA_LNA) -#if defined(USE_RX_FRSKY_SPI_DIVERSITY) - IOHi(antSelPin); -#endif - TxDisable(); -#endif // USE_RX_FRSKY_SPI_PA_LNA - missingPackets = 0; timeoutUs = 50; diff --git a/src/main/rx/cc2500_frsky_shared.h b/src/main/rx/cc2500_frsky_shared.h index da6700da4..e8ed07459 100644 --- a/src/main/rx/cc2500_frsky_shared.h +++ b/src/main/rx/cc2500_frsky_shared.h @@ -50,22 +50,7 @@ enum { extern uint8_t listLength; extern uint32_t missingPackets; extern timeDelta_t timeoutUs; -extern int16_t rssiDbm; - -extern IO_t gdoPin; - -void setRssiDbm(uint8_t value); - -void TxEnable(void); -void TxDisable(void); - -void LedOn(void); -void LedOff(void); - -void switchAntennae(void); void initialiseData(uint8_t adr); -bool checkBindRequested(bool reset); - void nextChannel(uint8_t skip); diff --git a/src/main/rx/cc2500_frsky_x.c b/src/main/rx/cc2500_frsky_x.c index 3a57ccccd..fccd47248 100644 --- a/src/main/rx/cc2500_frsky_x.c +++ b/src/main/rx/cc2500_frsky_x.c @@ -47,6 +47,7 @@ #include "fc/config.h" +#include "rx/cc2500_common.h" #include "rx/cc2500_frsky_common.h" #include "rx/cc2500_frsky_shared.h" @@ -190,7 +191,7 @@ static void buildTelemetryFrame(uint8_t *packet) frame[3] = packet[3]; if (evenRun) { - frame[4] = (uint8_t)rssiDbm | 0x80; + frame[4] = (uint8_t)cc2500getRssiDbm() | 0x80; } else { uint8_t a1Value; if (rxFrSkySpiConfig()->useExternalAdc) { @@ -331,7 +332,7 @@ rx_spi_received_e frSkyXHandlePacket(uint8_t * const packet, uint8_t * const pro *protocolState = STATE_DATA; frameReceived = false; // again set for receive receiveDelayUs = 5300; - if (checkBindRequested(false)) { + if (cc2500checkBindRequested(false)) { packetTimerUs = 0; timeoutUs = 50; missingPackets = 0; @@ -343,7 +344,7 @@ rx_spi_received_e frSkyXHandlePacket(uint8_t * const packet, uint8_t * const pro FALLTHROUGH; // here FS code could be case STATE_DATA: - if (IORead(gdoPin) && (frameReceived == false)){ + if (cc2500getGdo() && (frameReceived == false)){ uint8_t ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; // read 2 times to avoid reading errors if (ccLen > 32) { @@ -360,7 +361,7 @@ rx_spi_received_e frSkyXHandlePacket(uint8_t * const packet, uint8_t * const pro missingPackets = 0; timeoutUs = 1; receiveDelayUs = 0; - LedOn(); + cc2500LedOn(); if (skipChannels) { channelsToSkip = packet[5] << 2; if (packet[4] >= listLength) { @@ -376,7 +377,7 @@ rx_spi_received_e frSkyXHandlePacket(uint8_t * const packet, uint8_t * const pro skipChannels = false; } #ifdef USE_RX_FRSKY_SPI_TELEMETRY - setRssiDbm(packet[ccLen - 2]); + cc2500setRssiDbm(packet[ccLen - 2]); #endif telemetrySequenceMarker_t *inFrameMarker = (telemetrySequenceMarker_t *)&packet[21]; @@ -444,9 +445,9 @@ rx_spi_received_e frSkyXHandlePacket(uint8_t * const packet, uint8_t * const pro } if (cmpTimeUs(micros(), packetTimerUs) > timeoutUs * SYNC_DELAY_MAX) { if (ledIsOn) { - LedOff(); + cc2500LedOff(); } else { - LedOn(); + cc2500LedOn(); } ledIsOn = !ledIsOn; @@ -465,8 +466,8 @@ rx_spi_received_e frSkyXHandlePacket(uint8_t * const packet, uint8_t * const pro cc2500SetPower(6); cc2500Strobe(CC2500_SFRX); delayMicroseconds(30); -#if defined(USE_RX_FRSKY_SPI_PA_LNA) - TxEnable(); +#if defined(USE_RX_CC2500_SPI_PA_LNA) + cc2500TxEnable(); #endif cc2500Strobe(CC2500_SIDLE); cc2500WriteFifo(frame, frame[0] + 1); @@ -514,14 +515,14 @@ rx_spi_received_e frSkyXHandlePacket(uint8_t * const packet, uint8_t * const pro frameReceived = false; // again set for receive nextChannel(channelsToSkip); cc2500Strobe(CC2500_SRX); -#ifdef USE_RX_FRSKY_SPI_PA_LNA - TxDisable(); -#if defined(USE_RX_FRSKY_SPI_DIVERSITY) +#ifdef USE_RX_CC2500_SPI_PA_LNA + cc2500TxDisable(); +#if defined(USE_RX_CC2500_SPI_DIVERSITY) if (missingPackets >= 2) { - switchAntennae(); + cc2500switchAntennae(); } #endif -#endif // USE_RX_FRSKY_SPI_PA_LNA +#endif // USE_RX_CC2500_SPI_PA_LNA if (missingPackets > MAX_MISSING_PKT) { timeoutUs = 50; skipChannels = true; diff --git a/src/main/rx/cc2500_sfhss.c b/src/main/rx/cc2500_sfhss.c new file mode 100755 index 000000000..f77711311 --- /dev/null +++ b/src/main/rx/cc2500_sfhss.c @@ -0,0 +1,448 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software 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. + * + * Cleanflight and Betaflight are distributed in the hope that they + * 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 this software. + * + * If not, see . + */ + +#include + +#include "platform.h" + +#ifdef USE_RX_SFHSS_SPI + +#include "build/build_config.h" +#include "build/debug.h" + +#include "common/maths.h" + +#include "pg/pg.h" +#include "pg/pg_ids.h" +#include "pg/rx.h" +#include "pg/rx_spi.h" + +#include "drivers/rx/rx_cc2500.h" +#include "drivers/io.h" +#include "drivers/time.h" + +#include "fc/config.h" + +#include "rx/rx.h" +#include "rx/rx_spi.h" + +#include "rx/cc2500_common.h" +#include "rx/cc2500_sfhss.h" + +//void cliPrintLinef(const char *format, ...); + +#define BIND_CH 15 +#define SFHSS_PACKET_LEN 15 +#define BIND_TUNE_STEP 4 + +#define SFHSSCH2CHANNR(ch) (ch*6+16) +#define GET_CHAN(x) ((int)((x[5]>>3)&0x1f)) +#define GET_CODE(x) (((x[11] & 0x7) <<2 ) | ((x[12]>>6) & 0x3)) +#define GET_COMMAND(x) (x[12] & 0xf) +#define GET_CH1(x) ((uint16_t)(((x[5] & 0x07) << 9 | x[6]<<1) | (x[7] & 0x80)>>7)) +#define GET_CH2(x) (uint16_t)(((x[7] & 0x7f) << 5 | (x[8] & 0xf8)>>3)) +#define GET_CH3(x) (uint16_t)(((x[8] & 0x07) << 9 | x[9]<<1) | (x[10] & 0x80)>>7) +#define GET_CH4(x) (uint16_t)(((x[10] & 0x7f) << 5 | (x[11] & 0xf8)>>3)) +#define GET_TXID1(x) (uint8_t)(x[1]) +#define GET_TXID2(x) (uint8_t)(x[2]) +#define SET_STATE(x) {protocolState = x; DEBUG_SET(DEBUG_RX_SFHSS_SPI, DEBUG_DATA_STATE, x);} + +#define NEXT_CH_TIME_HUNT 500000 /* hunt */ +#define NEXT_CH_TIME_SYNC0 6800 /* sync no recv */ +#define NEXT_CH_TIME_SYNC1 3500 /* sync ch1-4 recv */ +#define NEXT_CH_TIME_SYNC2 500 /* sync ch5-8 recv */ + +static int8_t sfhss_channel = 0; +static int8_t sfhss_code = 0; + +static timeMs_t start_time; +static uint8_t protocolState; + +static uint32_t missingPackets; + +static uint8_t calData[32][3]; +static timeMs_t timeTunedMs; +static int8_t bindOffset_max=0; +static int8_t bindOffset_min=0; + +PG_REGISTER_WITH_RESET_TEMPLATE(rxSfhssSpiConfig_t, rxSfhssSpiConfig, PG_RX_SFHSS_SPI_CONFIG, 1); + +PG_RESET_TEMPLATE(rxSfhssSpiConfig_t, rxSfhssSpiConfig, + .bindTxId = {0, 0}, + .bindOffset = 0, +); + +static void initialise() { + cc2500Reset(); + + cc2500WriteReg(CC2500_02_IOCFG0, 0x01); + cc2500WriteReg(CC2500_03_FIFOTHR, 0x07); + cc2500WriteReg(CC2500_04_SYNC1, 0xD3); + cc2500WriteReg(CC2500_05_SYNC0, 0x91); + cc2500WriteReg(CC2500_06_PKTLEN, 0x0D); + cc2500WriteReg(CC2500_07_PKTCTRL1, 0x04); + cc2500WriteReg(CC2500_08_PKTCTRL0, 0x0C); + cc2500WriteReg(CC2500_09_ADDR, 0x29); + cc2500WriteReg(CC2500_0B_FSCTRL1, 0x06); + cc2500WriteReg(CC2500_0C_FSCTRL0, (rxSfhssSpiConfigMutable()->bindOffset)); + cc2500WriteReg(CC2500_0D_FREQ2, 0x5C); + cc2500WriteReg(CC2500_0E_FREQ1, 0x4E); + cc2500WriteReg(CC2500_0F_FREQ0, 0xC4); + cc2500WriteReg(CC2500_10_MDMCFG4, 0x7C); + cc2500WriteReg(CC2500_11_MDMCFG3, 0x43); + cc2500WriteReg(CC2500_12_MDMCFG2, 0x03); + cc2500WriteReg(CC2500_13_MDMCFG1, 0x23); + cc2500WriteReg(CC2500_14_MDMCFG0, 0x3B); + cc2500WriteReg(CC2500_15_DEVIATN, 0x44); + cc2500WriteReg(CC2500_17_MCSM1, 0x0F); + cc2500WriteReg(CC2500_18_MCSM0, 0x08); + cc2500WriteReg(CC2500_19_FOCCFG, 0x1D); + cc2500WriteReg(CC2500_1A_BSCFG, 0x6C); + cc2500WriteReg(CC2500_1B_AGCCTRL2, 0x03); + cc2500WriteReg(CC2500_1C_AGCCTRL1, 0x40); + cc2500WriteReg(CC2500_1D_AGCCTRL0, 0x91); + cc2500WriteReg(CC2500_21_FREND1, 0x56); + cc2500WriteReg(CC2500_22_FREND0, 0x10); + cc2500WriteReg(CC2500_23_FSCAL3, 0xA9); + cc2500WriteReg(CC2500_24_FSCAL2, 0x0A); + cc2500WriteReg(CC2500_25_FSCAL1, 0x00); + cc2500WriteReg(CC2500_26_FSCAL0, 0x11); + cc2500WriteReg(CC2500_29_FSTEST, 0x59); + cc2500WriteReg(CC2500_2C_TEST2, 0x88); + cc2500WriteReg(CC2500_2D_TEST1, 0x31); + cc2500WriteReg(CC2500_2E_TEST0, 0x0B); + cc2500WriteReg(CC2500_3E_PATABLE, 0xFF); + + for(unsigned c = 0;c < 30; c++) + { //calibrate all channels + cc2500Strobe(CC2500_SIDLE); + cc2500WriteReg(CC2500_0A_CHANNR, SFHSSCH2CHANNR(c)); + cc2500Strobe(CC2500_SCAL); + delayMicroseconds(900); // + calData[c][0] = cc2500ReadReg(CC2500_23_FSCAL3); + calData[c][1] = cc2500ReadReg(CC2500_24_FSCAL2); + calData[c][2] = cc2500ReadReg(CC2500_25_FSCAL1); + } +} + +static bool sfhssRecv(uint8_t *packet) +{ + uint8_t ccLen; + + if (!(cc2500getGdo())){ + return false; + } + ccLen = cc2500ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F; + if (ccLen < SFHSS_PACKET_LEN){ + return false; + } + + cc2500ReadFifo(packet, SFHSS_PACKET_LEN); + return true; +} + +static bool sfhssPacketParse(uint8_t *packet, bool check_txid) +{ + if (!(packet[SFHSS_PACKET_LEN - 1] & 0x80)){ + return false; /* crc fail */ + } + if (packet[0] != 0x81){ + return false; /* sfhss header fail */ + } + if (GET_CHAN(packet) != sfhss_channel){ + return false; /* channel fail */ + } + + if (check_txid){ + if ((rxSfhssSpiConfigMutable()->bindTxId[0] != GET_TXID1(packet)) || + (rxSfhssSpiConfigMutable()->bindTxId[1] != GET_TXID2(packet))){ + return false; /* txid fail */ + } + } + + cc2500setRssiDbm(packet[SFHSS_PACKET_LEN - 2]); + sfhss_code = GET_CODE(packet); + + return true; +} + +void sfhssRx(void) +{ + cc2500Strobe(CC2500_SIDLE); + cc2500WriteReg(CC2500_23_FSCAL3, calData[sfhss_channel][0]); + cc2500WriteReg(CC2500_24_FSCAL2, calData[sfhss_channel][1]); + cc2500WriteReg(CC2500_25_FSCAL1, calData[sfhss_channel][2]); + cc2500WriteReg(CC2500_0A_CHANNR, SFHSSCH2CHANNR(sfhss_channel)); + cc2500Strobe(CC2500_SFRX); + cc2500Strobe(CC2500_SRX); +} + +static void initTuneRx(void) +{ + timeTunedMs = millis(); + bindOffset_min = -64; + DEBUG_SET(DEBUG_RX_SFHSS_SPI, DEBUG_DATA_OFFSET_MIN, bindOffset_min); + cc2500WriteReg(CC2500_0C_FSCTRL0, (uint8_t)bindOffset_min); + sfhss_channel = BIND_CH; + sfhssRx(); +} + +static bool tune1Rx(uint8_t *packet) +{ + if (bindOffset_min >= 126) { + bindOffset_min = -126; + DEBUG_SET(DEBUG_RX_SFHSS_SPI, DEBUG_DATA_OFFSET_MIN, bindOffset_min); + } + if ((millis() - timeTunedMs) > 220) { // 220ms + timeTunedMs = millis(); + bindOffset_min += BIND_TUNE_STEP<<2; + DEBUG_SET(DEBUG_RX_SFHSS_SPI, DEBUG_DATA_OFFSET_MIN, bindOffset_min); + cc2500WriteReg(CC2500_0C_FSCTRL0, (uint8_t)bindOffset_min); + cc2500Strobe(CC2500_SRX); + } + if (sfhssRecv(packet)){ + if (sfhssPacketParse(packet, false)){ + if ((packet[SFHSS_PACKET_LEN - 1] & 0x7F) > 40 ){ /* lqi */ + rxSfhssSpiConfigMutable()->bindTxId[0] = GET_TXID1(packet); + rxSfhssSpiConfigMutable()->bindTxId[1] = GET_TXID2(packet); + bindOffset_max = bindOffset_min; + DEBUG_SET(DEBUG_RX_SFHSS_SPI, DEBUG_DATA_OFFSET_MAX, bindOffset_max); + cc2500Strobe(CC2500_SRX); + timeTunedMs = millis(); + return true; + } + } + cc2500Strobe(CC2500_SRX); + } + return false; +} + +static bool tune2Rx(uint8_t *packet) +{ + cc2500LedBlink(100); + if (((millis() - timeTunedMs) > 880) || bindOffset_max > (126-BIND_TUNE_STEP)) { // 220ms *4 + timeTunedMs = millis(); + cc2500WriteReg(CC2500_0C_FSCTRL0, (uint8_t)bindOffset_min); + cc2500Strobe(CC2500_SRX); + return true; + } + if (sfhssRecv(packet)){ + if (sfhssPacketParse(packet, true)){ + timeTunedMs = millis(); + bindOffset_max += BIND_TUNE_STEP; + DEBUG_SET(DEBUG_RX_SFHSS_SPI, DEBUG_DATA_OFFSET_MAX, bindOffset_max); + cc2500WriteReg(CC2500_0C_FSCTRL0, (uint8_t)bindOffset_max); + } + cc2500Strobe(CC2500_SRX); + } + return false; +} + +static bool tune3Rx(uint8_t *packet) +{ + cc2500LedBlink(100); + if (((millis() - timeTunedMs) > 880) || bindOffset_min < (-126+BIND_TUNE_STEP)) { // 220ms *4 + return true; + } + if (sfhssRecv(packet)){ + if (sfhssPacketParse(packet, true)){ + timeTunedMs = millis(); + bindOffset_min -= BIND_TUNE_STEP; + DEBUG_SET(DEBUG_RX_SFHSS_SPI, DEBUG_DATA_OFFSET_MIN, bindOffset_min); + cc2500WriteReg(CC2500_0C_FSCTRL0, (uint8_t)bindOffset_min); + } + cc2500Strobe(CC2500_SRX); + } + return false; +} + +void sfhssnextChannel(void) +{ + do { + sfhss_channel += sfhss_code + 2; + if (sfhss_channel > 29) { + sfhss_channel -= 31; + } + }while( sfhss_channel < 0); + + sfhssRx(); +} + +void sfhssSpiSetRcData(uint16_t *rcData, const uint8_t *payload) +{ + if( GET_COMMAND(payload) & 0x8 ){ + rcData[4] = GET_CH1(payload); + rcData[5] = GET_CH2(payload); + rcData[6] = GET_CH3(payload); + rcData[7] = GET_CH4(payload); + }else{ + rcData[0] = GET_CH1(payload); + rcData[1] = GET_CH2(payload); + rcData[2] = GET_CH3(payload); + rcData[3] = GET_CH4(payload); + } +} + +rx_spi_received_e sfhssSpiDataReceived(uint8_t *packet) +{ + static uint16_t dataMissingFrame = 0; + static timeUs_t nextFrameReceiveStartTime = 0; + static uint8_t frame_recvd = 0; + timeUs_t currentPacketReceivedTime; + rx_spi_received_e ret = RX_SPI_RECEIVED_NONE; + + currentPacketReceivedTime = micros(); + switch (protocolState) { + case STATE_INIT: + if ((millis() - start_time) > 10) { + cc2500LedOff(); + dataMissingFrame = 0; + initialise(); + SET_STATE(STATE_BIND); + DEBUG_SET(DEBUG_RX_SFHSS_SPI, DEBUG_DATA_MISSING_FRAME, dataMissingFrame); + } + break; + case STATE_BIND: + if (cc2500checkBindRequested(true)) { + cc2500LedOn(); + initTuneRx(); + SET_STATE( STATE_BIND_TUNING1 ); + } else { + SET_STATE( STATE_HUNT ); + sfhssnextChannel(); + setRssiDirect(0, RSSI_SOURCE_RX_PROTOCOL); + nextFrameReceiveStartTime = currentPacketReceivedTime + NEXT_CH_TIME_HUNT; + } + break; + case STATE_BIND_TUNING1: + if (tune1Rx(packet)) { + SET_STATE( STATE_BIND_TUNING2 ); + } + break; + case STATE_BIND_TUNING2: + if (tune2Rx(packet)) { + SET_STATE( STATE_BIND_TUNING3); + } + break; + case STATE_BIND_TUNING3: + if (tune3Rx(packet)) { + if(((int16_t)bindOffset_max - (int16_t)bindOffset_min) <= 2){ + initTuneRx(); + SET_STATE( STATE_BIND_TUNING1 ); // retry + }else{ + rxSfhssSpiConfigMutable()->bindOffset = ((int16_t)bindOffset_max + (int16_t)bindOffset_min)/2 ; + SET_STATE(STATE_BIND_COMPLETE); + } + } + break; + case STATE_BIND_COMPLETE: + writeEEPROM(); + ret = RX_SPI_RECEIVED_BIND; + SET_STATE(STATE_INIT); + break; + case STATE_HUNT: + if (sfhssRecv(packet)){ + if (sfhssPacketParse(packet, true)){ + if (GET_COMMAND(packet) & 0x8){ /* ch=5-8 */ + missingPackets = 0; + cc2500LedOn(); + frame_recvd = 0x3; + SET_STATE(STATE_SYNC); + nextFrameReceiveStartTime = currentPacketReceivedTime + NEXT_CH_TIME_SYNC2; + return RX_SPI_RECEIVED_NONE; + } + } + cc2500Strobe(CC2500_SRX); + }else if (cmpTimeUs(currentPacketReceivedTime, nextFrameReceiveStartTime) > 0) { + cc2500LedBlink(500); +#if defined(USE_RX_CC2500_SPI_PA_LNA) && defined(USE_RX_CC2500_SPI_DIVERSITY) // SE4311 chip + cc2500switchAntennae(); +#endif + sfhssnextChannel(); + nextFrameReceiveStartTime += NEXT_CH_TIME_HUNT; + }else if (cc2500checkBindRequested(false)) { + SET_STATE(STATE_INIT); + break; + } + break; + case STATE_SYNC: + if (sfhssRecv(packet)){ + if (sfhssPacketParse(packet, true)){ + missingPackets = 0; + if( GET_COMMAND(packet) & 0x8 ){ + nextFrameReceiveStartTime = currentPacketReceivedTime + NEXT_CH_TIME_SYNC2; + frame_recvd |= 0x2; /* ch5-8 */ + }else{ + nextFrameReceiveStartTime = currentPacketReceivedTime + NEXT_CH_TIME_SYNC1; + cc2500Strobe(CC2500_SRX); + frame_recvd |= 0x1; /* ch1-4 */ + } + if (GET_COMMAND(packet) & 0x4){ + return RX_SPI_RECEIVED_NONE; /* failsafe data */ + } + return RX_SPI_RECEIVED_DATA; + } + cc2500Strobe(CC2500_SRX); + }else if (cmpTimeUs(currentPacketReceivedTime, nextFrameReceiveStartTime) > 0) { + nextFrameReceiveStartTime += NEXT_CH_TIME_SYNC0; + if (frame_recvd != 0x3){ + DEBUG_SET(DEBUG_RX_SFHSS_SPI, DEBUG_DATA_MISSING_FRAME, ++dataMissingFrame); + } + if (frame_recvd == 0){ + if (++missingPackets > MAX_MISSING_PKT) { + SET_STATE(STATE_HUNT); + sfhssnextChannel(); + setRssiDirect(0, RSSI_SOURCE_RX_PROTOCOL); + nextFrameReceiveStartTime = currentPacketReceivedTime + NEXT_CH_TIME_HUNT; + break; + } +#if defined(USE_RX_CC2500_SPI_PA_LNA) && defined(USE_RX_CC2500_SPI_DIVERSITY) // SE4311 chip + if (missingPackets >= 2) { + cc2500switchAntennae(); + } +#endif + } + frame_recvd = 0; + sfhssnextChannel(); + }else if (cc2500checkBindRequested(false)) { + SET_STATE(STATE_INIT); + break; + } + break; + } + + return ret; +} + +bool sfhssSpiInit(const rxSpiConfig_t *rxSpiConfig, rxRuntimeConfig_t *rxRuntimeConfig) +{ + UNUSED(rxSpiConfig); + + cc2500SpiInit(); + + rxRuntimeConfig->channelCount = RC_CHANNEL_COUNT_SFHSS; + + start_time = millis(); + SET_STATE(STATE_INIT); + + return true; +} +#endif + diff --git a/src/main/rx/cc2500_sfhss.h b/src/main/rx/cc2500_sfhss.h new file mode 100755 index 000000000..c1490e2ca --- /dev/null +++ b/src/main/rx/cc2500_sfhss.h @@ -0,0 +1,55 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software 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. + * + * Cleanflight and Betaflight are distributed in the hope that they + * 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 this software. + * + * If not, see . + */ + +#pragma once + +#include "pg/pg.h" + +#include "rx/rx_spi.h" + +#define MAX_MISSING_PKT 100 +#define RC_CHANNEL_COUNT_SFHSS 8 + +#define DEBUG_DATA_STATE 0 +#define DEBUG_DATA_MISSING_FRAME 1 +#define DEBUG_DATA_OFFSET_MAX 2 +#define DEBUG_DATA_OFFSET_MIN 3 + +#define STATE_INIT 0 +#define STATE_HUNT 1 +#define STATE_SYNC 2 +#define STATE_BIND 10 +#define STATE_BIND_TUNING1 11 +#define STATE_BIND_TUNING2 12 +#define STATE_BIND_TUNING3 13 +#define STATE_BIND_COMPLETE 14 + +typedef struct rxSfhssSpiConfig_s { + uint8_t bindTxId[2]; + int8_t bindOffset; +} rxSfhssSpiConfig_t; + +PG_DECLARE(rxSfhssSpiConfig_t, rxSfhssSpiConfig); + +bool sfhssSpiInit(const rxSpiConfig_t *rxSpiConfig, rxRuntimeConfig_t *rxRuntimeConfig); +rx_spi_received_e sfhssSpiDataReceived(uint8_t *packet); +void sfhssSpiSetRcData(uint16_t *rcData, const uint8_t *payload); + +void sfhssSpiBind(void); diff --git a/src/main/rx/rx_spi.c b/src/main/rx/rx_spi.c index db1b27db5..66fdf1f95 100644 --- a/src/main/rx/rx_spi.c +++ b/src/main/rx/rx_spi.c @@ -47,6 +47,7 @@ #include "rx/nrf24_inav.h" #include "rx/nrf24_kn.h" #include "rx/flysky.h" +#include "rx/cc2500_sfhss.h" uint16_t rxSpiRcData[MAX_SUPPORTED_RC_CHANNEL_COUNT]; @@ -145,7 +146,14 @@ STATIC_UNIT_TESTED bool rxSpiSetProtocol(rx_spi_protocol_e protocol) protocolSetRcDataFromPayload = flySkySetRcDataFromPayload; break; #endif +#ifdef USE_RX_SFHSS_SPI + case RX_SPI_SFHSS: + protocolInit = sfhssSpiInit; + protocolDataReceived = sfhssSpiDataReceived; + protocolSetRcDataFromPayload = sfhssSpiSetRcData; + break; } +#endif return true; } diff --git a/src/main/rx/rx_spi.h b/src/main/rx/rx_spi.h index 8f095a784..d94554749 100644 --- a/src/main/rx/rx_spi.h +++ b/src/main/rx/rx_spi.h @@ -39,6 +39,7 @@ typedef enum { RX_SPI_A7105_FLYSKY, RX_SPI_A7105_FLYSKY_2A, RX_SPI_NRF24_KN, + RX_SPI_SFHSS, RX_SPI_PROTOCOL_COUNT } rx_spi_protocol_e; diff --git a/src/main/target/CRAZYBEEF3FR/target.h b/src/main/target/CRAZYBEEF3FR/target.h index 057487ad1..05059c176 100644 --- a/src/main/target/CRAZYBEEF3FR/target.h +++ b/src/main/target/CRAZYBEEF3FR/target.h @@ -133,12 +133,13 @@ #define USE_RX_FRSKY_SPI_D #define USE_RX_FRSKY_SPI_X #define USE_RX_FRSKY_SPI_TELEMETRY +#define USE_RX_SFHSS_SPI #define DEFAULT_RX_FEATURE FEATURE_RX_SPI #define RX_SPI_DEFAULT_PROTOCOL RX_SPI_FRSKY_X #define RX_SPI_INSTANCE SPI2 #define RX_NSS_PIN SPI2_NSS_PIN -#define RX_FRSKY_SPI_GDO_0_PIN PA8 -#define RX_FRSKY_SPI_LED_PIN PA10 +#define RX_CC2500_SPI_GDO_0_PIN PA8 +#define RX_CC2500_SPI_LED_PIN PA10 #define BINDPLUG_PIN PA9 #define DEFAULT_FEATURES (FEATURE_TELEMETRY | FEATURE_OSD | FEATURE_MOTOR_STOP) #endif diff --git a/src/main/target/CRAZYBEEF3FR/target.mk b/src/main/target/CRAZYBEEF3FR/target.mk index eca394fa0..a3dad5d7d 100644 --- a/src/main/target/CRAZYBEEF3FR/target.mk +++ b/src/main/target/CRAZYBEEF3FR/target.mk @@ -15,8 +15,10 @@ else ifeq ($(TARGET), CRAZYBEEF3FR) TARGET_SRC += \ drivers/rx/rx_cc2500.c \ + rx/cc2500_common.c \ rx/cc2500_frsky_shared.c \ rx/cc2500_frsky_d.c \ - rx/cc2500_frsky_x.c + rx/cc2500_frsky_x.c \ + rx/cc2500_sfhss.c endif endif diff --git a/src/main/target/MATEKF411RX/target.h b/src/main/target/MATEKF411RX/target.h index 780d2a370..04ad0c1ce 100644 --- a/src/main/target/MATEKF411RX/target.h +++ b/src/main/target/MATEKF411RX/target.h @@ -72,22 +72,23 @@ #define RX_SPI_INSTANCE SPI3 #define RX_NSS_PIN PA15 -#define RX_FRSKY_SPI_DISABLE_CHIP_DETECTION -#define RX_FRSKY_SPI_GDO_0_PIN PC14 -#define RX_FRSKY_SPI_LED_PIN PB9 -#define RX_FRSKY_SPI_LED_PIN_INVERTED +#define RX_CC2500_SPI_DISABLE_CHIP_DETECTION +#define RX_CC2500_SPI_GDO_0_PIN PC14 +#define RX_CC2500_SPI_LED_PIN PB9 +#define RX_CC2500_SPI_LED_PIN_INVERTED -#define USE_RX_FRSKY_SPI_PA_LNA -#define RX_FRSKY_SPI_TX_EN_PIN PA8 -#define RX_FRSKY_SPI_LNA_EN_PIN PA13 +#define USE_RX_CC2500_SPI_PA_LNA +#define RX_CC2500_SPI_TX_EN_PIN PA8 +#define RX_CC2500_SPI_LNA_EN_PIN PA13 -#define USE_RX_FRSKY_SPI_DIVERSITY -#define RX_FRSKY_SPI_ANT_SEL_PIN PA14 +#define USE_RX_CC2500_SPI_DIVERSITY +#define RX_CC2500_SPI_ANT_SEL_PIN PA14 #define BINDPLUG_PIN PB2 #define USE_RX_FRSKY_SPI_D #define USE_RX_FRSKY_SPI_X +#define USE_RX_SFHSS_SPI #define DEFAULT_RX_FEATURE FEATURE_RX_SPI #define RX_SPI_DEFAULT_PROTOCOL RX_SPI_FRSKY_X #define USE_RX_FRSKY_SPI_TELEMETRY diff --git a/src/main/target/MATEKF411RX/target.mk b/src/main/target/MATEKF411RX/target.mk index 977b93bf5..15defe607 100644 --- a/src/main/target/MATEKF411RX/target.mk +++ b/src/main/target/MATEKF411RX/target.mk @@ -6,6 +6,8 @@ TARGET_SRC = \ drivers/accgyro/accgyro_spi_mpu6000.c \ drivers/max7456.c \ drivers/rx/rx_cc2500.c \ + rx/cc2500_common.c \ rx/cc2500_frsky_shared.c \ rx/cc2500_frsky_d.c \ - rx/cc2500_frsky_x.c + rx/cc2500_frsky_x.c \ + rx/cc2500_sfhss.c diff --git a/src/main/target/MIDELICF3/target.h b/src/main/target/MIDELICF3/target.h index 8ecf65194..2aae877b6 100644 --- a/src/main/target/MIDELICF3/target.h +++ b/src/main/target/MIDELICF3/target.h @@ -103,26 +103,27 @@ #define USE_RX_FRSKY_SPI_D #define USE_RX_FRSKY_SPI_X +#define USE_RX_SFHSS_SPI #define DEFAULT_RX_FEATURE FEATURE_RX_SPI #define RX_SPI_DEFAULT_PROTOCOL RX_SPI_FRSKY_X #define USE_RX_FRSKY_SPI_TELEMETRY #define RX_NSS_PIN PA4 -#define RX_FRSKY_SPI_GDO_0_PIN PB0 +#define RX_CC2500_SPI_GDO_0_PIN PB0 -#define RX_FRSKY_SPI_LED_PIN PB6 +#define RX_CC2500_SPI_LED_PIN PB6 -#define USE_RX_FRSKY_SPI_PA_LNA +#define USE_RX_CC2500_SPI_PA_LNA -#define RX_FRSKY_SPI_TX_EN_PIN PB1 -#define RX_FRSKY_SPI_LNA_EN_PIN PB11 +#define RX_CC2500_SPI_TX_EN_PIN PB1 +#define RX_CC2500_SPI_LNA_EN_PIN PB11 -#define USE_RX_FRSKY_SPI_DIVERSITY +#define USE_RX_CC2500_SPI_DIVERSITY -#define RX_FRSKY_SPI_ANT_SEL_PIN PB2 +#define RX_CC2500_SPI_ANT_SEL_PIN PB2 #define BINDPLUG_PIN PC13 diff --git a/src/main/target/MIDELICF3/target.mk b/src/main/target/MIDELICF3/target.mk index 0c78eda41..a367b48ad 100644 --- a/src/main/target/MIDELICF3/target.mk +++ b/src/main/target/MIDELICF3/target.mk @@ -6,6 +6,8 @@ TARGET_SRC = \ drivers/accgyro/accgyro_mpu.c \ drivers/accgyro/accgyro_mpu6050.c \ drivers/rx/rx_cc2500.c \ + rx/cc2500_common.c \ rx/cc2500_frsky_shared.c \ rx/cc2500_frsky_d.c \ - rx/cc2500_frsky_x.c + rx/cc2500_frsky_x.c \ + rx/cc2500_sfhss.c diff --git a/src/main/target/common_post.h b/src/main/target/common_post.h index c881c3f9c..f0d0ce2ca 100644 --- a/src/main/target/common_post.h +++ b/src/main/target/common_post.h @@ -126,6 +126,12 @@ #if defined(USE_RX_FRSKY_SPI_D) || defined(USE_RX_FRSKY_SPI_X) #define USE_RX_CC2500 #define USE_RX_FRSKY_SPI +#define USE_RX_BIND +#endif + +#if defined(USE_RX_SFHSS_SPI) +#define USE_RX_CC2500 +#define USE_RX_BIND #endif // Burst dshot to default off if not configured explicitly by target