From f1e659bfd00b90617b9eadaa10e799718f585d4d Mon Sep 17 00:00:00 2001 From: Pawel Spychalski Date: Tue, 10 Apr 2018 15:01:27 +0200 Subject: [PATCH] Happy path frequency hopping --- .vscode/c_cpp_properties.json | 14 ++++++++++- crossbow/config.h | 4 ++-- crossbow/crossbow.ino | 54 +++++++++++++++++++++++++++++++++++++++++-- crossbow/qsp.cpp | 5 ++-- crossbow/variables.h | 13 ++++++++++- 5 files changed, 82 insertions(+), 8 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index cfa69c7..5a0e42f 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -11,6 +11,12 @@ "${workspaceRoot}" ] }, + "defines": [ + "SPI_HAS_NOTUSINGINTERRUPT", + "FEATURE_TX_INPUT_SBUS", + "DEVICE_MODE_TX", + "DEVICE_MODE_RX" + ], "intelliSenseMode": "msvc-x64", "cStandard": "c11", "cppStandard": "c++17", @@ -29,7 +35,13 @@ "~/Documents/Arduino/libraries/" ] }, - "intelliSenseMode": "clang-x64" + "intelliSenseMode": "clang-x64", + "defines": [ + "SPI_HAS_NOTUSINGINTERRUPT", + "FEATURE_TX_INPUT_SBUS", + "DEVICE_MODE_TX", + "DEVICE_MODE_RX" + ] } ], "version": 3 diff --git a/crossbow/config.h b/crossbow/config.h index 2ca699a..0b540aa 100644 --- a/crossbow/config.h +++ b/crossbow/config.h @@ -13,8 +13,8 @@ * DEVICE_MODE_TX * DEVICE_MODE_RX */ -// #define DEVICE_MODE_TX -#define DEVICE_MODE_RX +#define DEVICE_MODE_TX +// #define DEVICE_MODE_RX // #define FEATURE_TX_OLED // #define FORCE_TX_WITHOUT_INPUT diff --git a/crossbow/crossbow.ino b/crossbow/crossbow.ino index a880816..f9a6d10 100644 --- a/crossbow/crossbow.ino +++ b/crossbow/crossbow.ino @@ -92,8 +92,37 @@ uint8_t getRadioSnr(void) return (uint8_t) constrain(LoRa.packetSnr(), 0, 255); } +uint32_t getFrequencyForChannel(uint8_t channel) { + return RADIO_FREQUENCY_MIN + (RADIO_CHANNEL_WIDTH * channel); +} + +uint8_t getNextChannel(uint8_t channel) { + return (channel + RADIO_HOP_OFFSET) % RADIO_CHANNEL_COUNT; +} + +uint8_t getPrevChannel(uint8_t channel) { + return (RADIO_CHANNEL_COUNT + channel - RADIO_HOP_OFFSET) % RADIO_CHANNEL_COUNT; +} + +void hopFrequency(RadioState_t *radioState, bool forward, uint8_t fromChannel) { + radioState->channelEntryMillis = millis(); + + if (forward) { + radioState->channel = getNextChannel(fromChannel); + } else { + radioState->channel = getPrevChannel(fromChannel); + } + + // And set hardware + LoRa.sleep(); + LoRa.setFrequency( + getFrequencyForChannel(radioState->channel) + ); + LoRa.idle(); +} + void onQspSuccess(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDeviceState_t *rxDeviceState, volatile RadioState_t *radioState) { - //If devide received a valid frame, that means it can start to talk + //If recide received a valid frame, that means it can start to talk qsp->canTransmit = true; //Store the last timestamp when frame was received @@ -129,6 +158,14 @@ void onQspSuccess(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDev break; } + /* + * RX module hops to next channel after frame has been received + */ +#ifdef DEVICE_MODE_RX + hopFrequency(radioState, true, radioState->lastReceivedChannel); + LoRa.receive(); //Put radio back into receive mode +#endif + qsp->transmitWindowOpen = true; } @@ -160,7 +197,7 @@ void setup(void) LORA_DI0_PIN ); - if (!LoRa.begin(radioState.frequency)) + if (!LoRa.begin(getFrequencyForChannel(radioState.channel))) { #ifdef DEBUG_SERIAL Serial.println("LoRa init failed. Check your connections."); @@ -298,11 +335,22 @@ void loop(void) radioState.deviceState == RADIO_STATE_TX && !LoRa.isTransmitting() ) { + + /* + * In case of TX module, hop right now + */ +#ifdef DEVICE_MODE_TX + hopFrequency(&radioState, true, radioState.channel); +#endif + LoRa.receive(); radioState.deviceState = RADIO_STATE_RX; radioState.nextTxCheckMillis = currentMillis + 1; //We check of TX done every 1ms } + /* + * There is data to be read from radio! + */ if (radioState.bytesToRead != NO_DATA_TO_READ) { LoRa.read(tmpBuffer, radioState.bytesToRead); @@ -380,6 +428,8 @@ void loop(void) #ifdef DEVICE_MODE_RX + //FIXME here we are missing the whole procedure for jumping to next channel when frame was not recived + /* * This routine updates RX device state and updates one of radio channels with RSSI value */ diff --git a/crossbow/qsp.cpp b/crossbow/qsp.cpp index 159eec9..2fe7ef0 100644 --- a/crossbow/qsp.cpp +++ b/crossbow/qsp.cpp @@ -161,6 +161,7 @@ void qspDecodeIncomingFrame( static uint8_t frameId; static uint8_t payloadLength; static uint8_t receivedPayload; + static uint8_t receivedChannel; if (qsp->protocolState == QSP_STATE_IDLE) { @@ -187,8 +188,7 @@ void qspDecodeIncomingFrame( qsp->frameId = (incomingByte >> 4) & 0x0f; payloadLength = qspFrameLengths[qsp->frameId]; - //4 bytes are now free to use for something else - // payloadLength = incomingByte & 0x0f; + receivedChannel = incomingByte & 0x0f; qsp->protocolState = QSP_STATE_FRAME_TYPE_RECEIVED; } @@ -214,6 +214,7 @@ void qspDecodeIncomingFrame( { if (qsp->crc == incomingByte) { //CRC is correct + radioState->lastReceivedChannel = receivedChannel; qsp->onSuccessCallback(qsp, txDeviceState, rxDeviceState, radioState); } else { qsp->onFailureCallback(qsp, txDeviceState, rxDeviceState, radioState); diff --git a/crossbow/variables.h b/crossbow/variables.h index 4e9d624..d8bab73 100644 --- a/crossbow/variables.h +++ b/crossbow/variables.h @@ -86,8 +86,14 @@ enum debugConfigFlags { #define RADIO_STATE_TX 1 #define RADIO_STATE_RX 2 +#define RADIO_FREQUENCY_MIN 868000000 +#define RADIO_FREQUENCY_MAX 870000000 +#define RADIO_FREQUENCY_RANGE (RADIO_FREQUENCY_MAX-RADIO_FREQUENCY_MIN) +#define RADIO_CHANNEL_WIDTH 250000 +#define RADIO_CHANNEL_COUNT (RADIO_FREQUENCY_RANGE/RADIO_CHANNEL_WIDTH) + 1 // 9 channels in 2MHz range +#define RADIO_HOP_OFFSET 5 + struct RadioState_t { - uint32_t frequency = 867000000; uint32_t loraBandwidth = 250000; uint8_t loraSpreadingFactor = 7; uint8_t loraCodingRate = 6; @@ -97,6 +103,11 @@ struct RadioState_t { uint8_t snr = 0; uint8_t deviceState = RADIO_STATE_RX; uint32_t nextTxCheckMillis = 0; + + const uint32_t dwellTime = TX_TRANSMIT_SLOT_RATE * 2; + uint8_t channel = 0; + uint8_t lastReceivedChannel = 0; + uint32_t channelEntryMillis = 0; }; struct TxDeviceState_t {