From a7c2e13b10fd4220b340251a5ad0a8e0c73e3ad0 Mon Sep 17 00:00:00 2001 From: "Pawel Spychalski (DzikuVx)" Date: Sat, 16 Dec 2017 11:08:39 +0100 Subject: [PATCH 1/7] LoRa non-blocking endPacket from https://github.com/sandeepmistry/arduino-LoRa/pull/62 --- crossbow.ino | 6 +++--- lora.cpp | 23 +++++++++++++++++++++++ lora.h | 3 +++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/crossbow.ino b/crossbow.ino index 79af241..937995b 100644 --- a/crossbow.ino +++ b/crossbow.ino @@ -1,7 +1,7 @@ -// #define DEVICE_MODE_TX -#define DEVICE_MODE_RX +#define DEVICE_MODE_TX +// #define DEVICE_MODE_RX -// #define FEATURE_TX_OLED +#define FEATURE_TX_OLED // #define FORCE_TX_WITHOUT_INPUT // #define DEBUG_SERIAL diff --git a/lora.cpp b/lora.cpp index 80b867e..33906e5 100644 --- a/lora.cpp +++ b/lora.cpp @@ -153,6 +153,29 @@ int LoRaClass::endPacket() return 1; } +//https://github.com/sandeepmistry/arduino-LoRa/pull/62/files +void LoRaClass::endPacketAsync() +{ + // put in TX mode + writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX); + + // apparently this grace time is required for the radio + delayMicroseconds(150); +} + +//https://github.com/sandeepmistry/arduino-LoRa/pull/62/files +bool LoRaClass::isTransmitting() +{ + if ((readRegister(REG_OP_MODE) & MODE_TX) == MODE_TX) + return true; + + if (!(readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0) + // clear IRQ's + writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK); + + return false; +} + int LoRaClass::parsePacket(int size) { int packetLength = 0; diff --git a/lora.h b/lora.h index 17ca80d..b09ea06 100644 --- a/lora.h +++ b/lora.h @@ -26,6 +26,9 @@ public: int beginPacket(int implicitHeader = false); int endPacket(); + void endPacketAsync(); + bool isTransmitting() + int parsePacket(int size = 0); int packetRssi(); float packetSnr(); From e8f1976a2dd2c69d8fafb05b2e3cfbbbc8b55c58 Mon Sep 17 00:00:00 2001 From: "Pawel Spychalski (DzikuVx)" Date: Sun, 17 Dec 2017 09:33:04 +0100 Subject: [PATCH 2/7] async rx mode --- crossbow.ino | 27 +++++++++++++++++++++++---- lora.h | 2 +- variables.h | 4 ++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/crossbow.ino b/crossbow.ino index 937995b..bc37348 100644 --- a/crossbow.ino +++ b/crossbow.ino @@ -1,7 +1,7 @@ #define DEVICE_MODE_TX // #define DEVICE_MODE_RX -#define FEATURE_TX_OLED +// #define FEATURE_TX_OLED // #define FORCE_TX_WITHOUT_INPUT // #define DEBUG_SERIAL @@ -168,6 +168,7 @@ void setup(void) //Setup ISR callback and start receiving LoRa.onReceive(onReceive); LoRa.receive(); + radioState.deviceState = RADIO_STATE_RX; #ifdef DEVICE_MODE_RX //initiallize default ppm values @@ -261,9 +262,23 @@ int8_t getFrameToTransmit(QspConfiguration_t *qsp) { } #endif +/* + * + * Main loop starts here! + * + */ void loop(void) { + /* + * Detect the moment when radio module stopped transmittig and put it + * back in to receive state + */ + if (radioState.deviceState == RADIO_STATE_TX && !LoRa.isTransmitting()) { + LoRa.receive(); + radioState.deviceState = RADIO_STATE_RX; + } + if (radioState.bytesToRead != NO_DATA_TO_READ) { LoRa.read(tmpBuffer, radioState.bytesToRead); @@ -277,6 +292,7 @@ void loop(void) //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; } @@ -404,9 +420,11 @@ void loop(void) qspEncodeFrame(&qsp, tmpBuffer, &size); //Sent it to radio in one SPI transaction LoRa.write(tmpBuffer, size); - LoRa.endPacket(); - //After ending packet, put device into receive mode again - LoRa.receive(); + LoRa.endPacketAsync(); + + //Set state to be able to detect the moment when TX is done + radioState.deviceState = RADIO_STATE_TX; + transmitPayload = false; } @@ -515,6 +533,7 @@ void onReceive(int packetSize) */ LoRa.sleep(); LoRa.receive(); + radioState.deviceState = RADIO_STATE_RX; } } } \ No newline at end of file diff --git a/lora.h b/lora.h index b09ea06..12bb455 100644 --- a/lora.h +++ b/lora.h @@ -27,7 +27,7 @@ public: int endPacket(); void endPacketAsync(); - bool isTransmitting() + bool isTransmitting(); int parsePacket(int size = 0); int packetRssi(); diff --git a/variables.h b/variables.h index 2202804..05f3b5f 100644 --- a/variables.h +++ b/variables.h @@ -74,6 +74,9 @@ enum debugConfigFlags { #define NO_DATA_TO_READ -1 +#define RADIO_STATE_TX 1 +#define RADIO_STATE_RX 2 + struct RadioState_t { uint32_t frequency = 867000000; uint32_t loraBandwidth = 250000; @@ -83,6 +86,7 @@ struct RadioState_t { int8_t bytesToRead = -1; uint8_t rssi = 0; uint8_t snr = 0; + uint8_t deviceState = RADIO_STATE_RX; }; struct TxDeviceState_t { From 9d30a69b22b33326fc049d2635a9151dd056707a Mon Sep 17 00:00:00 2001 From: "Pawel Spychalski (DzikuVx)" Date: Sun, 24 Dec 2017 14:06:34 +0100 Subject: [PATCH 3/7] minor change --- crossbow.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crossbow.ino b/crossbow.ino index bc37348..efd30fa 100644 --- a/crossbow.ino +++ b/crossbow.ino @@ -270,6 +270,8 @@ int8_t getFrameToTransmit(QspConfiguration_t *qsp) { void loop(void) { + uint32_t currentMillis = millis(); + /* * Detect the moment when radio module stopped transmittig and put it * back in to receive state @@ -297,7 +299,6 @@ void loop(void) radioState.bytesToRead = NO_DATA_TO_READ; } - uint32_t currentMillis = millis(); bool transmitPayload = false; /* From 8071d6ac745901cfb149a51091fc25f8681c8d49 Mon Sep 17 00:00:00 2001 From: "Pawel Spychalski (DzikuVx)" Date: Thu, 28 Dec 2017 12:05:18 +0100 Subject: [PATCH 4/7] Fixed compiler warnings --- .vscode/c_cpp_properties.json | 8 ++++++-- crossbow.ino | 6 +++--- qsp.cpp | 2 +- qsp.h | 2 +- variables.h | 4 ++-- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 00c9b0c..705e4b4 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,13 +3,17 @@ { "name": "Win32", "includePath": [ - "C:\\Users\\pspyc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.6.19\\cores\\arduino", + "${workspaceRoot}", + "C:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino", + "C:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\libraries", + "C:\\Users\\pspyc\\Documents\\Arduino\\libraries", "C:\\Users\\pspyc\\Documents\\Arduino\\libraries\\PPMReader" ], "browse": { "limitSymbolsToIncludedHeaders": false, "path": [ - "C:\\Users\\pspyc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.6.19\\cores\\arduino", + "C:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino", + "C:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\libraries", "${workspaceRoot}", "C:\\Users\\pspyc\\Documents\\Arduino\\libraries" ] diff --git a/crossbow.ino b/crossbow.ino index efd30fa..1398bd5 100644 --- a/crossbow.ino +++ b/crossbow.ino @@ -58,7 +58,7 @@ uint32_t lastOledTaskTime = 0; QspConfiguration_t qsp = {}; RxDeviceState_t rxDeviceState = {}; TxDeviceState_t txDeviceState = {}; -volatile RadioState_t radioState; +volatile RadioState_t radioState = {}; uint8_t tmpBuffer[MAX_PACKET_SIZE]; @@ -81,7 +81,7 @@ void writeToRadio(uint8_t dataByte, QspConfiguration_t *qsp) LoRa.write(dataByte); } -void onQspSuccess(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDeviceState_t *rxDeviceState, 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 qsp->canTransmit = true; @@ -121,7 +121,7 @@ void onQspSuccess(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDev qsp->transmitWindowOpen = true; } -void onQspFailure(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDeviceState_t *rxDeviceState, RadioState_t *radioState) { +void onQspFailure(QspConfiguration_t *qsp, TxDeviceState_t *txDeviceState, RxDeviceState_t *rxDeviceState, volatile RadioState_t *radioState) { } diff --git a/qsp.cpp b/qsp.cpp index 84b8c3d..dbcefe1 100644 --- a/qsp.cpp +++ b/qsp.cpp @@ -161,7 +161,7 @@ void qspDecodeIncomingFrame( uint8_t incomingByte, RxDeviceState_t *rxDeviceState, TxDeviceState_t *txDeviceState, - RadioState_t *radioState + volatile RadioState_t *radioState ) { static uint8_t frameId; static uint8_t payloadLength; diff --git a/qsp.h b/qsp.h index 84728b1..106d98f 100644 --- a/qsp.h +++ b/qsp.h @@ -14,7 +14,7 @@ void qspDecodeIncomingFrame( uint8_t incomingByte, RxDeviceState_t *rxDeviceState, TxDeviceState_t *txDeviceState, - RadioState_t *radioState + volatile RadioState_t *radioState ); void qspClearPayload(QspConfiguration_t *qsp); void qspEncodeFrame(QspConfiguration_t *qsp, uint8_t buffer[], uint8_t *size); diff --git a/variables.h b/variables.h index 05f3b5f..e81721d 100644 --- a/variables.h +++ b/variables.h @@ -116,8 +116,8 @@ struct QspConfiguration_t { uint32_t anyFrameRecivedAt = 0; uint8_t deviceState = DEVICE_STATE_UNDETERMINED; void (* hardwareWriteFunction)(uint8_t, QspConfiguration_t*); - void (* onSuccessCallback)(QspConfiguration_t*, TxDeviceState_t*, RxDeviceState_t*, RadioState_t*); - void (* onFailureCallback)(QspConfiguration_t*, TxDeviceState_t*, RxDeviceState_t*, RadioState_t*); + void (* onSuccessCallback)(QspConfiguration_t*, TxDeviceState_t*, RxDeviceState_t*, volatile RadioState_t*); + void (* onFailureCallback)(QspConfiguration_t*, TxDeviceState_t*, RxDeviceState_t*, volatile RadioState_t*); bool canTransmit = false; bool forcePongFrame = false; uint8_t debugConfig = 0; From 8dfc41759e788f19fd79d7513d1fad8af3b7c4ba Mon Sep 17 00:00:00 2001 From: "Pawel Spychalski (DzikuVx)" Date: Tue, 2 Jan 2018 20:14:41 +0100 Subject: [PATCH 5/7] Another compiler warning fiuxed --- .vscode/arduino.json | 2 +- crossbow.ino | 4 ++-- qsp.cpp | 2 +- qsp.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.vscode/arduino.json b/.vscode/arduino.json index 488acc1..7b8a141 100644 --- a/.vscode/arduino.json +++ b/.vscode/arduino.json @@ -2,5 +2,5 @@ "board": "bsfrance:avr:lora32u4", "sketch": "crossbow.ino", "port": "COM4", - "output": "./build" + "output": "../build" } \ No newline at end of file diff --git a/crossbow.ino b/crossbow.ino index 1398bd5..0892af9 100644 --- a/crossbow.ino +++ b/crossbow.ino @@ -1,5 +1,5 @@ -#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/qsp.cpp b/qsp.cpp index dbcefe1..b27c8cb 100644 --- a/qsp.cpp +++ b/qsp.cpp @@ -67,7 +67,7 @@ void qspComputeCrc(QspConfiguration_t *qsp, uint8_t dataByte) qsp->crc = crc8_dvb_s2(qsp->crc, dataByte); } -void encodeRxHealthPayload(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceState, RadioState_t *radioState) { +void encodeRxHealthPayload(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceState, volatile RadioState_t *radioState) { qsp->payload[0] = radioState->rssi; qsp->payload[1] = radioState->snr; qsp->payload[2] = rxDeviceState->rxVoltage; diff --git a/qsp.h b/qsp.h index 106d98f..061f09a 100644 --- a/qsp.h +++ b/qsp.h @@ -7,7 +7,7 @@ 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, RadioState_t *radioState); +void encodeRxHealthPayload(QspConfiguration_t *qsp, RxDeviceState_t *rxDeviceState, volatile RadioState_t *radioState); void encodeRcDataPayload(QspConfiguration_t *qsp, PPMReader *ppmSource, uint8_t noOfChannels); void qspDecodeIncomingFrame( QspConfiguration_t *qsp, From cb3c510815cf061e2adbe0e43c56c557956e315d Mon Sep 17 00:00:00 2001 From: "Pawel Spychalski (DzikuVx)" Date: Tue, 2 Jan 2018 21:14:11 +0100 Subject: [PATCH 6/7] Further changes to async processing --- .vscode/arduino.json | 2 +- crossbow.ino | 16 +++++++++------- variables.h | 1 + 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.vscode/arduino.json b/.vscode/arduino.json index 7b8a141..c4b5be6 100644 --- a/.vscode/arduino.json +++ b/.vscode/arduino.json @@ -1,6 +1,6 @@ { "board": "bsfrance:avr:lora32u4", "sketch": "crossbow.ino", - "port": "COM4", + "port": "COM3", "output": "../build" } \ No newline at end of file diff --git a/crossbow.ino b/crossbow.ino index 0892af9..a3d3ee4 100644 --- a/crossbow.ino +++ b/crossbow.ino @@ -1,10 +1,10 @@ -// #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 -// #define DEBUG_SERIAL +#define DEBUG_SERIAL // #define DEBUG_PING_PONG // #define DEBUG_LED @@ -276,9 +276,14 @@ void loop(void) * Detect the moment when radio module stopped transmittig and put it * back in to receive state */ - if (radioState.deviceState == RADIO_STATE_TX && !LoRa.isTransmitting()) { + if ( + currentMillis > radioState.nextTxCheckMillis && + radioState.deviceState == RADIO_STATE_TX && + !LoRa.isTransmitting() + ) { LoRa.receive(); radioState.deviceState = RADIO_STATE_RX; + radioState.nextTxCheckMillis = currentMillis + 1; //We check of TX done every 1ms } if (radioState.bytesToRead != NO_DATA_TO_READ) { @@ -516,9 +521,6 @@ void loop(void) void onReceive(int packetSize) { - if (packetSize == 0) - return; - /* * We can start reading only when radio is not reading. * If not reading, then we might start diff --git a/variables.h b/variables.h index e81721d..a9f8fdb 100644 --- a/variables.h +++ b/variables.h @@ -87,6 +87,7 @@ struct RadioState_t { uint8_t rssi = 0; uint8_t snr = 0; uint8_t deviceState = RADIO_STATE_RX; + uint32_t nextTxCheckMillis = 0; }; struct TxDeviceState_t { From 702a8331fe4e56b1dd93b320baf1b1b272dab911 Mon Sep 17 00:00:00 2001 From: "Pawel Spychalski (DzikuVx)" Date: Tue, 2 Jan 2018 21:16:12 +0100 Subject: [PATCH 7/7] Allow for TX only when not already transmitting --- crossbow.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/crossbow.ino b/crossbow.ino index a3d3ee4..2b75a9f 100644 --- a/crossbow.ino +++ b/crossbow.ino @@ -319,6 +319,7 @@ void loop(void) #ifdef DEVICE_MODE_TX if ( + radioState.deviceState == RADIO_STATE_RX && qsp.protocolState == QSP_STATE_IDLE && qsp.lastTxSlotTimestamp + TX_TRANSMIT_SLOT_RATE < currentMillis ) {