Happy path frequency hopping

This commit is contained in:
Pawel Spychalski
2018-04-10 15:01:27 +02:00
parent 6ee2caf68d
commit f1e659bfd0
5 changed files with 82 additions and 8 deletions

View File

@@ -11,6 +11,12 @@
"${workspaceRoot}" "${workspaceRoot}"
] ]
}, },
"defines": [
"SPI_HAS_NOTUSINGINTERRUPT",
"FEATURE_TX_INPUT_SBUS",
"DEVICE_MODE_TX",
"DEVICE_MODE_RX"
],
"intelliSenseMode": "msvc-x64", "intelliSenseMode": "msvc-x64",
"cStandard": "c11", "cStandard": "c11",
"cppStandard": "c++17", "cppStandard": "c++17",
@@ -29,7 +35,13 @@
"~/Documents/Arduino/libraries/" "~/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 "version": 3

View File

@@ -13,8 +13,8 @@
* DEVICE_MODE_TX * DEVICE_MODE_TX
* DEVICE_MODE_RX * DEVICE_MODE_RX
*/ */
// #define DEVICE_MODE_TX #define DEVICE_MODE_TX
#define DEVICE_MODE_RX // #define DEVICE_MODE_RX
// #define FEATURE_TX_OLED // #define FEATURE_TX_OLED
// #define FORCE_TX_WITHOUT_INPUT // #define FORCE_TX_WITHOUT_INPUT

View File

@@ -92,8 +92,37 @@ uint8_t getRadioSnr(void)
return (uint8_t) constrain(LoRa.packetSnr(), 0, 255); 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) { 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; qsp->canTransmit = true;
//Store the last timestamp when frame was received //Store the last timestamp when frame was received
@@ -129,6 +158,14 @@ void onQspSuccess(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDev
break; 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; qsp->transmitWindowOpen = true;
} }
@@ -160,7 +197,7 @@ void setup(void)
LORA_DI0_PIN LORA_DI0_PIN
); );
if (!LoRa.begin(radioState.frequency)) if (!LoRa.begin(getFrequencyForChannel(radioState.channel)))
{ {
#ifdef DEBUG_SERIAL #ifdef DEBUG_SERIAL
Serial.println("LoRa init failed. Check your connections."); Serial.println("LoRa init failed. Check your connections.");
@@ -298,11 +335,22 @@ void loop(void)
radioState.deviceState == RADIO_STATE_TX && radioState.deviceState == RADIO_STATE_TX &&
!LoRa.isTransmitting() !LoRa.isTransmitting()
) { ) {
/*
* In case of TX module, hop right now
*/
#ifdef DEVICE_MODE_TX
hopFrequency(&radioState, true, radioState.channel);
#endif
LoRa.receive(); LoRa.receive();
radioState.deviceState = RADIO_STATE_RX; radioState.deviceState = RADIO_STATE_RX;
radioState.nextTxCheckMillis = currentMillis + 1; //We check of TX done every 1ms 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) { if (radioState.bytesToRead != NO_DATA_TO_READ) {
LoRa.read(tmpBuffer, radioState.bytesToRead); LoRa.read(tmpBuffer, radioState.bytesToRead);
@@ -380,6 +428,8 @@ void loop(void)
#ifdef DEVICE_MODE_RX #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 * This routine updates RX device state and updates one of radio channels with RSSI value
*/ */

View File

@@ -161,6 +161,7 @@ void qspDecodeIncomingFrame(
static uint8_t frameId; static uint8_t frameId;
static uint8_t payloadLength; static uint8_t payloadLength;
static uint8_t receivedPayload; static uint8_t receivedPayload;
static uint8_t receivedChannel;
if (qsp->protocolState == QSP_STATE_IDLE) if (qsp->protocolState == QSP_STATE_IDLE)
{ {
@@ -187,8 +188,7 @@ void qspDecodeIncomingFrame(
qsp->frameId = (incomingByte >> 4) & 0x0f; qsp->frameId = (incomingByte >> 4) & 0x0f;
payloadLength = qspFrameLengths[qsp->frameId]; payloadLength = qspFrameLengths[qsp->frameId];
//4 bytes are now free to use for something else receivedChannel = incomingByte & 0x0f;
// payloadLength = incomingByte & 0x0f;
qsp->protocolState = QSP_STATE_FRAME_TYPE_RECEIVED; qsp->protocolState = QSP_STATE_FRAME_TYPE_RECEIVED;
} }
@@ -214,6 +214,7 @@ void qspDecodeIncomingFrame(
{ {
if (qsp->crc == incomingByte) { if (qsp->crc == incomingByte) {
//CRC is correct //CRC is correct
radioState->lastReceivedChannel = receivedChannel;
qsp->onSuccessCallback(qsp, txDeviceState, rxDeviceState, radioState); qsp->onSuccessCallback(qsp, txDeviceState, rxDeviceState, radioState);
} else { } else {
qsp->onFailureCallback(qsp, txDeviceState, rxDeviceState, radioState); qsp->onFailureCallback(qsp, txDeviceState, rxDeviceState, radioState);

View File

@@ -86,8 +86,14 @@ enum debugConfigFlags {
#define RADIO_STATE_TX 1 #define RADIO_STATE_TX 1
#define RADIO_STATE_RX 2 #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 { struct RadioState_t {
uint32_t frequency = 867000000;
uint32_t loraBandwidth = 250000; uint32_t loraBandwidth = 250000;
uint8_t loraSpreadingFactor = 7; uint8_t loraSpreadingFactor = 7;
uint8_t loraCodingRate = 6; uint8_t loraCodingRate = 6;
@@ -97,6 +103,11 @@ struct RadioState_t {
uint8_t snr = 0; uint8_t snr = 0;
uint8_t deviceState = RADIO_STATE_RX; uint8_t deviceState = RADIO_STATE_RX;
uint32_t nextTxCheckMillis = 0; 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 { struct TxDeviceState_t {