From 3d5adf8779d12fdf8c8372654002259e14b45b95 Mon Sep 17 00:00:00 2001 From: jgromes Date: Sat, 6 Sep 2025 16:27:45 +0100 Subject: [PATCH] [SX126x] Implement blocking receive timeout --- src/modules/SX126x/SX126x.cpp | 63 ++++++++++++++++------------------- src/modules/SX126x/SX126x.h | 8 +++-- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/modules/SX126x/SX126x.cpp b/src/modules/SX126x/SX126x.cpp index 4d2f8555..922e9389 100644 --- a/src/modules/SX126x/SX126x.cpp +++ b/src/modules/SX126x/SX126x.cpp @@ -249,38 +249,37 @@ int16_t SX126x::transmit(const uint8_t* data, size_t len, uint8_t addr) { return(finishTransmit()); } -int16_t SX126x::receive(uint8_t* data, size_t len) { +int16_t SX126x::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) { // set mode to standby int16_t state = standby(); RADIOLIB_ASSERT(state); - RadioLibTime_t timeout = 0; + RadioLibTime_t timeoutInternal = timeout; + if(!timeoutInternal) { + // get currently active modem + uint8_t modem = getPacketType(); + if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) { + // calculate timeout (100 LoRa symbols, the default for SX127x series) + float symbolLength = (float)(uint32_t(1) << this->spreadingFactor) / (float)this->bandwidthKhz; + timeoutInternal = (RadioLibTime_t)(symbolLength * 100.0f); + + } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) { + // calculate timeout (500 % of expected time-one-air) + size_t maxLen = len; + if(len == 0) { maxLen = 0xFF; } + float brBps = (RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0f * 32.0f) / (float)this->bitRate; + timeoutInternal = (RadioLibTime_t)(((maxLen * 8.0f) / brBps) * 1000.0f * 5.0f); - // get currently active modem - uint8_t modem = getPacketType(); - if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) { - // calculate timeout (100 LoRa symbols, the default for SX127x series) - float symbolLength = (float)(uint32_t(1) << this->spreadingFactor) / (float)this->bandwidthKhz; - timeout = (RadioLibTime_t)(symbolLength * 100.0f); - - } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) { - // calculate timeout (500 % of expected time-one-air) - size_t maxLen = len; - if(len == 0) { - maxLen = 0xFF; + } else { + return(RADIOLIB_ERR_UNKNOWN); + } - float brBps = (RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0f * 32.0f) / (float)this->bitRate; - timeout = (RadioLibTime_t)(((maxLen * 8.0f) / brBps) * 1000.0f * 5.0f); - - } else { - return(RADIOLIB_ERR_UNKNOWN); - } - RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout); + RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeoutInternal); // start reception - uint32_t timeoutValue = (uint32_t)(((float)timeout * 1000.0f) / 15.625f); + uint32_t timeoutValue = (uint32_t)(((float)timeoutInternal * 1000.0f) / 15.625f); state = startReceive(timeoutValue); RADIOLIB_ASSERT(state); @@ -290,7 +289,7 @@ int16_t SX126x::receive(uint8_t* data, size_t len) { while(!this->mod->hal->digitalRead(this->mod->getIrq())) { this->mod->hal->yield(); // safety check, the timeout should be done by the radio - if(this->mod->hal->millis() - start > timeout) { + if(this->mod->hal->millis() - start > timeoutInternal) { softTimeout = true; break; } @@ -302,18 +301,14 @@ int16_t SX126x::receive(uint8_t* data, size_t len) { return(state); } - // check whether this was a timeout or not - if((getIrqFlags() & RADIOLIB_SX126X_IRQ_TIMEOUT) || softTimeout) { - standby(); - fixImplicitTimeout(); - clearIrqStatus(); - return(RADIOLIB_ERR_RX_TIMEOUT); - } + // cache the IRQ flags and clean up after reception + uint32_t irqFlags = getIrqFlags(); + state = finishReceive(); + RADIOLIB_ASSERT(state); - // fix timeout in implicit LoRa mode - if(((this->headerType == RADIOLIB_SX126X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_LORA))) { - state = fixImplicitTimeout(); - RADIOLIB_ASSERT(state); + // check whether this was a timeout or not + if((irqFlags & RADIOLIB_SX126X_IRQ_TIMEOUT) || softTimeout) { + return(RADIOLIB_ERR_RX_TIMEOUT); } // read the received data diff --git a/src/modules/SX126x/SX126x.h b/src/modules/SX126x/SX126x.h index aa262009..28173994 100644 --- a/src/modules/SX126x/SX126x.h +++ b/src/modules/SX126x/SX126x.h @@ -567,11 +567,13 @@ class SX126x: public PhysicalLayer { /*! \brief Blocking binary receive method. Overloads for string-based transmissions are implemented in PhysicalLayer. - \param data Binary data to be sent. - \param len Number of bytes to send. + \param data Pointer to array to save the received binary data. + \param len Number of bytes that will be received. Must be known in advance for binary transmissions. + \param timeout Reception timeout in milliseconds. If set to 0, + timeout period will be calculated automatically based on the radio configuration. \returns \ref status_codes */ - int16_t receive(uint8_t* data, size_t len) override; + int16_t receive(uint8_t* data, size_t len, RadioLibTime_t timeout = 0) override; /*! \brief Starts direct mode transmission.