From 5b9cad0c8cf480314dcda4fc7688c0235f0ab002 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 10 Jul 2024 19:10:52 +1000 Subject: [PATCH] protocol: LoRaWAN: Allow configuring scanGuard The current code uses scanGuard to increase the Rx window. Sometimes the default 10ms scanGuard isn't enough. So allow uses of LoRaWAN to set a larger scanGuard. Signed-off-by: Alistair Francis --- src/protocols/LoRaWAN/LoRaWAN.cpp | 14 +++++--------- src/protocols/LoRaWAN/LoRaWAN.h | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp index bd12c06f6..7aac3bca5 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.cpp +++ b/src/protocols/LoRaWAN/LoRaWAN.cpp @@ -1155,14 +1155,10 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t fPort, bool isCon int16_t LoRaWANNode::downlinkCommon() { Module* mod = this->phyLayer->getMod(); - // according to the spec, the Rx window must be at least enough time to effectively detect a preamble - // but we pad it a bit on both sides (start and end) to make sure it is wide enough - const RadioLibTime_t scanGuard = 10; // Rx window padding in milliseconds - // check if there are any upcoming Rx windows // if the Rx1 window has already started, you're too late, because most downlinks happen in Rx1 RadioLibTime_t now = mod->hal->millis(); // fix the current timestamp to prevent negative delays - if(now > this->rxDelayStart + this->rxDelays[0] - scanGuard) { + if(now > this->rxDelayStart + this->rxDelays[0] - this->scanGuard) { // if between start of Rx1 and end of Rx2, wait until Rx2 closes if(now < this->rxDelayStart + this->rxDelays[1]) { mod->hal->delay(this->rxDelays[1] + this->rxDelayStart - now); @@ -1188,7 +1184,7 @@ int16_t LoRaWANNode::downlinkCommon() { downlinkAction = false; // calculate the Rx timeout - RadioLibTime_t timeoutHost = this->phyLayer->getTimeOnAir(0) + 2*scanGuard*1000; + RadioLibTime_t timeoutHost = this->phyLayer->getTimeOnAir(0) + 2*this->scanGuard*1000; RadioLibTime_t timeoutMod = this->phyLayer->calculateRxTimeout(timeoutHost); // wait for the start of the Rx window @@ -1198,8 +1194,8 @@ int16_t LoRaWANNode::downlinkCommon() { waitLen = this->rxDelays[i]; } // the waiting duration is shortened a bit to cover any possible timing errors - if(waitLen > scanGuard) { - waitLen -= scanGuard; + if(waitLen > this->scanGuard) { + waitLen -= this->scanGuard; } mod->hal->delay(waitLen); @@ -1209,7 +1205,7 @@ int16_t LoRaWANNode::downlinkCommon() { RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Opening Rx%d window (%d ms timeout)... <-- Rx Delay end ", i+1, (int)(timeoutHost / 1000 + scanGuard / 2)); // wait for the timeout to complete (and a small additional delay) - mod->hal->delay(timeoutHost / 1000 + scanGuard / 2); + mod->hal->delay(timeoutHost / 1000 + this->scanGuard / 2); RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Closing Rx%d window", i+1); // check if the IRQ bit for Rx Timeout is set diff --git a/src/protocols/LoRaWAN/LoRaWAN.h b/src/protocols/LoRaWAN/LoRaWAN.h index 3af9477f4..13e393987 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.h +++ b/src/protocols/LoRaWAN/LoRaWAN.h @@ -871,6 +871,20 @@ class LoRaWANNode { */ bool TS009 = false; + /*! + \brief Rx window padding in milliseconds + according to the spec, the Rx window must be at least enough time to effectively detect a preamble + but we pad it a bit on both sides (start and end) to make sure it is wide enough + The larger this number the more power will be consumed! So be careful about changing it. + For debugging purposes 50 is a reasonable start, but for production devices it should + be as low as possible. + 0 is a valid time. + + 500 is the **maximum** value, but it is not a good idea to go anywhere near that. + If you have to go above 50 you probably have a bug somewhere. Check your device timing. + */ + RadioLibTime_t scanGuard = 10; + #if !RADIOLIB_GODMODE private: #endif