diff --git a/.vscode/settings.json b/.vscode/settings.json index d00452d..3f3fc72 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,9 @@ "variables.h": "c", "arduino.h": "c", "algorithm": "cpp", - "random": "cpp" + "random": "cpp", + "type_traits": "cpp", + "iterator": "cpp" }, "files.exclude": { "**/build": true diff --git a/crossbow/config.h b/crossbow/config.h index 9dc179b..ebd82da 100644 --- a/crossbow/config.h +++ b/crossbow/config.h @@ -15,8 +15,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 1d42577..b5467da 100644 --- a/crossbow/crossbow.ino +++ b/crossbow/crossbow.ino @@ -90,19 +90,21 @@ volatile RadioState_t radioState = {}; uint8_t tmpBuffer[MAX_PACKET_SIZE]; -void onQspSuccess(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDeviceState_t *rxDeviceState, volatile RadioState_t *radioState) { +void onQspSuccess(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDeviceState_t *rxDeviceState, uint8_t receivedChannel) { //If recide received a valid frame, that means it can start to talk + radioNode.lastReceivedChannel = receivedChannel; + qsp->canTransmit = true; - radioState->rssi = radioNode.getRadioRssi(); - radioState->snr = radioNode.getRadioSnr(); + radioNode.readRssi(); + radioNode.readSnr(); /* * RX module hops to next channel after frame has been received */ #ifdef DEVICE_MODE_RX - radioNode.hopFrequency(true, radioState->lastReceivedChannel, millis()); - radioState->failedDwellsCount = 0; // We received a frame, so we can just reset this counter + radioNode.hopFrequency(true, radioNode.lastReceivedChannel, millis()); + radioNode.failedDwellsCount = 0; // We received a frame, so we can just reset this counter LoRa.receive(); //Put radio back into receive mode #endif @@ -142,7 +144,7 @@ void onQspSuccess(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDev qsp->transmitWindowOpen = true; } -void onQspFailure(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDeviceState_t *rxDeviceState, volatile RadioState_t *radioState) { +void onQspFailure(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDeviceState_t *rxDeviceState) { } @@ -346,20 +348,7 @@ void loop(void) * This routine handles resync of TX/RX while hoppping frequencies */ #ifdef DEVICE_MODE_RX - - //In the beginning just keep jumping forward and try to resync over lost single frames - if (radioState.failedDwellsCount < 6 && radioNode.getChannelEntryMillis() + RX_CHANNEL_DWELL_TIME < currentMillis) { - radioState.failedDwellsCount++; - radioNode.hopFrequency(true, radioNode.getChannel(), radioNode.getChannelEntryMillis() + RX_CHANNEL_DWELL_TIME); - LoRa.receive(); - } - - // If we are loosing more frames, start jumping in the opposite direction since probably we are completely out of sync now - if (radioState.failedDwellsCount >= 6 && radioNode.getChannelEntryMillis() + (RX_CHANNEL_DWELL_TIME * 5) < currentMillis) { - radioNode.hopFrequency(false, radioNode.getChannel(), radioNode.getChannelEntryMillis() + RX_CHANNEL_DWELL_TIME); //Start jumping in opposite direction to resync - LoRa.receive(); - } - + radioNode.handleChannelDwell(); #endif /* @@ -456,7 +445,7 @@ void loop(void) lastRxStateTaskTime = currentMillis; updateRxDeviceState(&rxDeviceState); - uint8_t output = constrain(radioState.rssi - 40, 0, 100); + uint8_t output = constrain(radioNode.rssi - 40, 0, 100); rxDeviceState.indicatedRssi = (output * 10) + 1000; if (qsp.deviceState == DEVICE_STATE_FAILSAFE) { @@ -487,7 +476,7 @@ void loop(void) break; case QSP_FRAME_RX_HEALTH: - encodeRxHealthPayload(&qsp, &rxDeviceState, &radioState); + encodeRxHealthPayload(&qsp, &rxDeviceState, radioNode.rssi, radioNode.snr); break; } @@ -507,7 +496,7 @@ void loop(void) if (qsp.lastFrameReceivedAt[QSP_FRAME_RC_DATA] + RX_FAILSAFE_DELAY < currentMillis) { qsp.deviceState = DEVICE_STATE_FAILSAFE; rxDeviceState.indicatedRssi = 0; - radioState.rssi = 0; + radioNode.rssi = 0; } else { qsp.deviceState = DEVICE_STATE_OK; } @@ -569,9 +558,9 @@ void loop(void) } else if (txDeviceState.isReceiving && (rxDeviceState.flags & 0x1) == 1) { //Failsafe reported by RX module buzzerContinousMode(BUZZER_MODE_SLOW_BEEP, &buzzer); - } else if (txDeviceState.isReceiving && radioState.rssi < 45) { + } else if (txDeviceState.isReceiving && radioNode.rssi < 45) { buzzerContinousMode(BUZZER_MODE_DOUBLE_CHIRP, &buzzer); // RSSI below 45dB // Critical state - } else if (txDeviceState.isReceiving && radioState.rssi < 55) { + } else if (txDeviceState.isReceiving && radioNode.rssi < 55) { buzzerContinousMode(BUZZER_MODE_CHIRP, &buzzer); // RSSI below 55dB // Warning state } else { buzzerContinousMode(BUZZER_MODE_OFF, &buzzer); diff --git a/crossbow/qsp.cpp b/crossbow/qsp.cpp index 90982be..6a12363 100644 --- a/crossbow/qsp.cpp +++ b/crossbow/qsp.cpp @@ -62,9 +62,9 @@ void qspComputeCrc(QspConfiguration_t *qsp, uint8_t dataByte) qsp->crc = crc8_dvb_s2(qsp->crc, dataByte); } -void encodeRxHealthPayload(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceState, volatile RadioState_t *radioState) { - qsp->payload[0] = radioState->rssi; - qsp->payload[1] = radioState->snr; +void encodeRxHealthPayload(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceState, uint8_t rssi, uint8_t snr) { + qsp->payload[0] = rssi; + qsp->payload[1] = snr; qsp->payload[2] = rxDeviceState->rxVoltage; qsp->payload[3] = rxDeviceState->a1Voltage; qsp->payload[4] = rxDeviceState->a2Voltage; @@ -165,8 +165,7 @@ void qspDecodeIncomingFrame( QspConfiguration_t *qsp, uint8_t incomingByte, RxDeviceState_t *rxDeviceState, - TxDeviceState_t *txDeviceState, - volatile RadioState_t *radioState + TxDeviceState_t *txDeviceState ) { static uint8_t frameId; static uint8_t payloadLength; @@ -210,10 +209,9 @@ void qspDecodeIncomingFrame( { if (qsp->crc == incomingByte) { //CRC is correct - radioState->lastReceivedChannel = receivedChannel; - qsp->onSuccessCallback(qsp, txDeviceState, rxDeviceState, radioState); + qsp->onSuccessCallback(qsp, txDeviceState, rxDeviceState, receivedChannel); } else { - qsp->onFailureCallback(qsp, txDeviceState, rxDeviceState, radioState); + qsp->onFailureCallback(qsp, txDeviceState, rxDeviceState); } // In both cases switch to listening for next preamble diff --git a/crossbow/qsp.h b/crossbow/qsp.h index c2b1a7a..834368c 100644 --- a/crossbow/qsp.h +++ b/crossbow/qsp.h @@ -1,5 +1,6 @@ #include "Arduino.h" #include "variables.h" +#include "radio_node.h" void qspDecodeRcDataFrame(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceSate); void decodeRxHealthPayload(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceState); @@ -7,14 +8,13 @@ void decodeRxHealthPayload(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceSta uint8_t get10bitHighShift(uint8_t channel); uint8_t get10bitLowShift(uint8_t channel); void qspComputeCrc(QspConfiguration_t *qsp, uint8_t dataByte); -void encodeRxHealthPayload(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceState, volatile RadioState_t *radioState); +void encodeRxHealthPayload(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceState, uint8_t rssi, uint8_t snr); void encodeRcDataPayload(QspConfiguration_t *qsp, volatile int16_t channels[], uint8_t noOfChannels); void qspDecodeIncomingFrame( QspConfiguration_t *qsp, uint8_t incomingByte, RxDeviceState_t *rxDeviceState, - TxDeviceState_t *txDeviceState, - volatile RadioState_t *radioState + TxDeviceState_t *txDeviceState ); void qspClearPayload(QspConfiguration_t *qsp); void qspEncodeFrame(QspConfiguration_t *qsp, volatile RadioState_t *radioState, uint8_t buffer[], uint8_t *size, uint8_t radioChannel); diff --git a/crossbow/radio_node.cpp b/crossbow/radio_node.cpp index 9a7865c..1579aa8 100644 --- a/crossbow/radio_node.cpp +++ b/crossbow/radio_node.cpp @@ -5,14 +5,14 @@ RadioNode::RadioNode(void) { } -static uint8_t RadioNode::getRadioRssi(void) +void RadioNode::readRssi(void) { - return 164 - constrain(LoRa.packetRssi() * -1, 0, 164); + rssi = 164 - constrain(LoRa.packetRssi() * -1, 0, 164); } -static uint8_t RadioNode::getRadioSnr(void) +void RadioNode::readSnr(void) { - return (uint8_t) constrain(LoRa.packetSnr(), 0, 255); + snr = (uint8_t) constrain(LoRa.packetSnr(), 0, 255); } uint8_t RadioNode::getChannel(void) { @@ -49,13 +49,13 @@ void RadioNode::readAndDecode( LoRa.read(tmpBuffer, bytesToRead); for (int i = 0; i < bytesToRead; i++) { - qspDecodeIncomingFrame(qsp, tmpBuffer[i], rxDeviceState, txDeviceState, radioState); + qspDecodeIncomingFrame(qsp, tmpBuffer[i], rxDeviceState, txDeviceState); } //After reading, flush radio buffer, we have no need for whatever might be over there LoRa.sleep(); LoRa.receive(); - + deviceState = RADIO_STATE_RX; bytesToRead = NO_DATA_TO_READ; } @@ -76,4 +76,19 @@ void RadioNode::hopFrequency(bool forward, uint8_t fromChannel, uint32_t timesta RadioNode::getFrequencyForChannel(_channel) ); LoRa.idle(); +} + +void RadioNode::handleChannelDwell(void) { + //In the beginning just keep jumping forward and try to resync over lost single frames + if (failedDwellsCount < 6 && getChannelEntryMillis() + RX_CHANNEL_DWELL_TIME < millis()) { + failedDwellsCount++; + hopFrequency(true, getChannel(), getChannelEntryMillis() + RX_CHANNEL_DWELL_TIME); + LoRa.receive(); + } + + // If we are loosing more frames, start jumping in the opposite direction since probably we are completely out of sync now + if (failedDwellsCount >= 6 && getChannelEntryMillis() + (RX_CHANNEL_DWELL_TIME * 5) < millis()) { + hopFrequency(false, getChannel(), getChannelEntryMillis() + RX_CHANNEL_DWELL_TIME); //Start jumping in opposite direction to resync + LoRa.receive(); + } } \ No newline at end of file diff --git a/crossbow/radio_node.h b/crossbow/radio_node.h index 02bcd4a..b4346ce 100644 --- a/crossbow/radio_node.h +++ b/crossbow/radio_node.h @@ -18,8 +18,8 @@ class RadioNode { public: RadioNode(void); - static uint8_t getRadioRssi(void); - static uint8_t getRadioSnr(void); + void readRssi(void); + void readSnr(void); static uint32_t getFrequencyForChannel(uint8_t channel); static uint8_t getNextChannel(uint8_t channel); static uint8_t getPrevChannel(uint8_t channel); @@ -32,8 +32,13 @@ class RadioNode { ); uint8_t getChannel(void); uint32_t getChannelEntryMillis(void); + void handleChannelDwell(void); int8_t bytesToRead = -1; uint8_t deviceState = RADIO_STATE_RX; + uint8_t rssi = 0; + uint8_t snr = 0; + uint8_t lastReceivedChannel = 0; + uint8_t failedDwellsCount = 0; private: uint8_t _channel = 0; uint32_t _channelEntryMillis = 0; diff --git a/crossbow/tx_oled.cpp b/crossbow/tx_oled.cpp index cd4e930..65c377e 100644 --- a/crossbow/tx_oled.cpp +++ b/crossbow/tx_oled.cpp @@ -151,11 +151,11 @@ void TxOled::renderPageStats( _display.setCursor(0, 0); _display.setTextSize(3); - _display.print(radioState->rssi); + _display.print(radioNode.rssi); _display.setCursor(18, 28); _display.setTextSize(2); - _display.print(radioState->snr); + _display.print(radioNode.snr); _display.setCursor(74, 0); _display.setTextSize(3); diff --git a/crossbow/tx_oled.h b/crossbow/tx_oled.h index cd43e13..f571807 100644 --- a/crossbow/tx_oled.h +++ b/crossbow/tx_oled.h @@ -7,6 +7,9 @@ #include "Wire.h" #include "variables.h" #include "tactile.h" +#include "radio_node.h" + +extern volatile RadioNode radioNode; enum txOledPages { TX_PAGE_NONE, diff --git a/crossbow/variables.h b/crossbow/variables.h index 3cb5bb4..30b35a5 100644 --- a/crossbow/variables.h +++ b/crossbow/variables.h @@ -95,13 +95,7 @@ struct RadioState_t { uint8_t loraSpreadingFactor = 7; uint8_t loraCodingRate = 6; uint8_t loraTxPower = 17; // Defines output power of TX, defined in dBm range from 2-17 - uint8_t rssi = 0; - uint8_t snr = 0; uint32_t nextTxCheckMillis = 0; - - const uint32_t dwellTime = TX_TRANSMIT_SLOT_RATE * 2; - uint8_t lastReceivedChannel = 0; - uint8_t failedDwellsCount = 0; }; struct TxDeviceState_t { @@ -133,8 +127,8 @@ struct QspConfiguration_t { uint32_t lastFrameReceivedAt[QSP_FRAME_COUNT] = {0}; uint32_t anyFrameRecivedAt = 0; uint8_t deviceState = DEVICE_STATE_UNDETERMINED; - void (* onSuccessCallback)(QspConfiguration_t*, TxDeviceState_t*, RxDeviceState_t*, volatile RadioState_t*); - void (* onFailureCallback)(QspConfiguration_t*, TxDeviceState_t*, RxDeviceState_t*, volatile RadioState_t*); + void (* onSuccessCallback)(QspConfiguration_t*, TxDeviceState_t*, RxDeviceState_t*, uint8_t receivedChannel); + void (* onFailureCallback)(QspConfiguration_t*, TxDeviceState_t*, RxDeviceState_t*); bool canTransmit = false; bool forcePongFrame = false; uint8_t debugConfig = 0;