diff --git a/.vscode/settings.json b/.vscode/settings.json index 77f0cd2..d00452d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,9 @@ { "files.associations": { "variables.h": "c", - "arduino.h": "c" + "arduino.h": "c", + "algorithm": "cpp", + "random": "cpp" }, "files.exclude": { "**/build": true diff --git a/crossbow/crossbow.ino b/crossbow/crossbow.ino index 6e17397..1d42577 100644 --- a/crossbow/crossbow.ino +++ b/crossbow/crossbow.ino @@ -9,11 +9,11 @@ Copyright (c) 20xx, MPL Contributor1 contrib1@example.net #include "config.h" #include "lora.h" +#include "radio_node.h" #include "variables.h" #include "main_variables.h" #include "qsp.h" #include "sbus.h" -#include "radio_node.h" #ifdef ARDUINO_AVR_FEATHER32U4 #define LORA_SS_PIN 8 @@ -184,7 +184,7 @@ void setup(void) //Setup ISR callback and start receiving LoRa.onReceive(onReceive); LoRa.receive(); - radioState.deviceState = RADIO_STATE_RX; + radioNode.deviceState = RADIO_STATE_RX; #ifdef DEVICE_MODE_RX //initiallize default ppm values @@ -368,7 +368,7 @@ void loop(void) */ if ( currentMillis > radioState.nextTxCheckMillis && - radioState.deviceState == RADIO_STATE_TX && + radioNode.deviceState == RADIO_STATE_TX && !LoRa.isTransmitting() ) { @@ -380,27 +380,16 @@ void loop(void) #endif LoRa.receive(); - radioState.deviceState = RADIO_STATE_RX; + radioNode.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); - - for (int i = 0; i < radioState.bytesToRead; i++) { - qspDecodeIncomingFrame(&qsp, tmpBuffer[i], &rxDeviceState, &txDeviceState, &radioState); - } - - //After reading, flush radio buffer, we have no need for whatever might be over there - LoRa.sleep(); - LoRa.receive(); - radioState.deviceState = RADIO_STATE_RX; - - radioState.bytesToRead = NO_DATA_TO_READ; - } + radioNode.readAndDecode( + &radioState, + &qsp, + &rxDeviceState, + &txDeviceState + ); bool transmitPayload = false; @@ -419,7 +408,7 @@ void loop(void) txInput.loop(); if ( - radioState.deviceState == RADIO_STATE_RX && + radioNode.deviceState == RADIO_STATE_RX && qsp.protocolState == QSP_STATE_IDLE && qsp.lastTxSlotTimestamp + TX_TRANSMIT_SLOT_RATE < currentMillis ) { @@ -536,7 +525,7 @@ void loop(void) LoRa.endPacketAsync(); //Set state to be able to detect the moment when TX is done - radioState.deviceState = RADIO_STATE_TX; + radioNode.deviceState = RADIO_STATE_TX; transmitPayload = false; } @@ -615,18 +604,18 @@ void onReceive(int packetSize) * We can start reading only when radio is not reading. * If not reading, then we might start */ - if (radioState.bytesToRead == NO_DATA_TO_READ) { + if (radioNode.bytesToRead == NO_DATA_TO_READ) { if (packetSize >= MIN_PACKET_SIZE && packetSize <= MAX_PACKET_SIZE) { //We have a packet candidate that might contain a valid QSP packet - radioState.bytesToRead = packetSize; + radioNode.bytesToRead = packetSize; } else { /* That packet was not very interesting, just flush it, we have no use */ LoRa.sleep(); LoRa.receive(); - radioState.deviceState = RADIO_STATE_RX; + radioNode.deviceState = RADIO_STATE_RX; } } } \ No newline at end of file diff --git a/crossbow/qsp.h b/crossbow/qsp.h index 74e28d3..c2b1a7a 100644 --- a/crossbow/qsp.h +++ b/crossbow/qsp.h @@ -1,4 +1,5 @@ #include "Arduino.h" +#include "variables.h" void qspDecodeRcDataFrame(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceSate); void decodeRxHealthPayload(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceState); diff --git a/crossbow/radio_node.cpp b/crossbow/radio_node.cpp index 5da105f..9a7865c 100644 --- a/crossbow/radio_node.cpp +++ b/crossbow/radio_node.cpp @@ -35,6 +35,32 @@ static uint8_t RadioNode::getPrevChannel(uint8_t channel) { return (RADIO_CHANNEL_COUNT + channel - RADIO_HOP_OFFSET) % RADIO_CHANNEL_COUNT; } +void RadioNode::readAndDecode( + volatile RadioState_t *radioState, + QspConfiguration_t *qsp, + RxDeviceState_t *rxDeviceState, + TxDeviceState_t *txDeviceState +) { + uint8_t tmpBuffer[MAX_PACKET_SIZE]; + /* + * There is data to be read from radio! + */ + if (bytesToRead != NO_DATA_TO_READ) { + LoRa.read(tmpBuffer, bytesToRead); + + for (int i = 0; i < bytesToRead; i++) { + qspDecodeIncomingFrame(qsp, tmpBuffer[i], rxDeviceState, txDeviceState, radioState); + } + + //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; + } +} + void RadioNode::hopFrequency(bool forward, uint8_t fromChannel, uint32_t timestamp) { _channelEntryMillis = timestamp; diff --git a/crossbow/radio_node.h b/crossbow/radio_node.h index 9789813..02bcd4a 100644 --- a/crossbow/radio_node.h +++ b/crossbow/radio_node.h @@ -1,17 +1,7 @@ #pragma once #include "Arduino.h" - -#ifndef RADIO_NODE_H -#define RADIO_NODE_H - -#define RADIO_STATE_TX 1 -#define RADIO_STATE_RX 2 - -#define TX_TRANSMIT_SLOT_RATE 67 //ms -#define RX_CHANNEL_DWELL_TIME (TX_TRANSMIT_SLOT_RATE + 10) //Dwell on a channel slightly longer -#define RX_FAILSAFE_DELAY (TX_TRANSMIT_SLOT_RATE * 8) -#define TX_FAILSAFE_DELAY (RX_FAILSAFE_DELAY * 4) +#include "qsp.h" #define RADIO_FREQUENCY_MIN 868000000 #define RADIO_FREQUENCY_MAX 870000000 @@ -20,21 +10,10 @@ #define RADIO_CHANNEL_COUNT 9 // 9 channels in 2MHz range (RADIO_FREQUENCY_RANGE/RADIO_CHANNEL_WIDTH) + 1 #define RADIO_HOP_OFFSET 5 -struct RadioState_t { - uint32_t loraBandwidth = 250000; - uint8_t loraSpreadingFactor = 7; - uint8_t loraCodingRate = 6; - uint8_t loraTxPower = 17; // Defines output power of TX, defined in dBm range from 2-17 - int8_t bytesToRead = -1; - uint8_t rssi = 0; - uint8_t snr = 0; - uint8_t deviceState = RADIO_STATE_RX; - uint32_t nextTxCheckMillis = 0; +#ifndef RADIO_NODE_H +#define RADIO_NODE_H - const uint32_t dwellTime = TX_TRANSMIT_SLOT_RATE * 2; - uint8_t lastReceivedChannel = 0; - uint8_t failedDwellsCount = 0; -}; +#include "variables.h" class RadioNode { public: @@ -45,8 +24,16 @@ class RadioNode { static uint8_t getNextChannel(uint8_t channel); static uint8_t getPrevChannel(uint8_t channel); void hopFrequency(bool forward, uint8_t fromChannel, uint32_t timestamp); + void readAndDecode( + volatile RadioState_t *radioState, + QspConfiguration_t *qsp, + RxDeviceState_t *rxDeviceState, + TxDeviceState_t *txDeviceState + ); uint8_t getChannel(void); uint32_t getChannelEntryMillis(void); + int8_t bytesToRead = -1; + uint8_t deviceState = RADIO_STATE_RX; private: uint8_t _channel = 0; uint32_t _channelEntryMillis = 0; diff --git a/crossbow/variables.h b/crossbow/variables.h index 55e1f92..3cb5bb4 100644 --- a/crossbow/variables.h +++ b/crossbow/variables.h @@ -3,6 +3,17 @@ #pragma once +#ifndef VARIABLES_H +#define VARIABLES_H + +#define RADIO_STATE_TX 1 +#define RADIO_STATE_RX 2 + +#define TX_TRANSMIT_SLOT_RATE 67 //ms +#define RX_CHANNEL_DWELL_TIME (TX_TRANSMIT_SLOT_RATE + 10) //Dwell on a channel slightly longer +#define RX_FAILSAFE_DELAY (TX_TRANSMIT_SLOT_RATE * 8) +#define TX_FAILSAFE_DELAY (RX_FAILSAFE_DELAY * 4) + #define OLED_UPDATE_RATE 750 #define SBUS_UPDATE_RATE 15 //ms @@ -79,6 +90,20 @@ enum debugConfigFlags { #define NO_DATA_TO_READ -1 +struct RadioState_t { + uint32_t loraBandwidth = 250000; + 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 { uint8_t flags = 0; uint32_t roundtrip = 0; @@ -117,3 +142,5 @@ struct QspConfiguration_t { uint32_t lastTxSlotTimestamp = 0; bool transmitWindowOpen = false; }; + +#endif \ No newline at end of file