From 8426fddcb7af7243f97c665067e6ed4d03910f97 Mon Sep 17 00:00:00 2001 From: Woodie-07 Date: Sun, 12 Oct 2025 16:09:57 +0100 Subject: [PATCH] workaround for LR1110 shift issue it seems that if the LR1110 radio hears a packet corrupted in a specific way, it'll report a packet of 0 length and with the header error IRQ set. every packet received afterwards will then be shifted to the right by 4 bytes on top of the radio's reported offset. this can occur multiple times with the shift increasing by 4 bytes each time. thus, this patch will read from an additional offset after hearing the trigger packet. transmitting seems to reset the shift - unsure exactly what operation resets it but standby() is called after tx so patch assumes shift is 0 after standby(). more investigation may be needed here. --- platformio.ini | 2 +- src/helpers/radiolib/CustomLR1110.h | 68 +++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 4fe17af9..e72b7b3a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -18,7 +18,7 @@ monitor_speed = 115200 lib_deps = SPI Wire - jgromes/RadioLib @ ^7.1.2 + jgromes/RadioLib @ ^7.3.0 rweather/Crypto @ ^0.4.0 adafruit/RTClib @ ^2.1.3 melopero/Melopero RV3028 @ ^1.1.0 diff --git a/src/helpers/radiolib/CustomLR1110.h b/src/helpers/radiolib/CustomLR1110.h index e82f48f5..0d1fbccc 100644 --- a/src/helpers/radiolib/CustomLR1110.h +++ b/src/helpers/radiolib/CustomLR1110.h @@ -9,6 +9,74 @@ class CustomLR1110 : public LR1110 { public: CustomLR1110(Module *mod) : LR1110(mod) { } + uint8_t shiftCount = 0; + + int16_t standby() override { + // tx resets the shift, standby is called on tx completion + // this might not actually be what resets it, but it seems to work + // more investigation needed + this->shiftCount = 0; + return LR1110::standby(); + } + + size_t getPacketLength(bool update) override { + size_t len = LR1110::getPacketLength(update); + if (len == 0) { + uint32_t irq = getIrqStatus(); + if (irq & RADIOLIB_LR11X0_IRQ_HEADER_ERR) { + Serial.println(F("got possible bug packet")); + this->shiftCount += 4; // uint8 will loop around to 0 at 256, perfect as rx buffer is 256 bytes + } else { + Serial.println(F("got zero-length packet without header err irq")); + } + } + return len; + } + + int16_t readData(uint8_t *data, size_t len) override { + // check active modem + uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE; + int16_t state = getPacketType(&modem); + RADIOLIB_ASSERT(state); + if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) && + (modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK)) { + return(RADIOLIB_ERR_WRONG_MODEM); + } + + // check integrity CRC + uint32_t irq = getIrqStatus(); + int16_t crcState = RADIOLIB_ERR_NONE; + // Report CRC mismatch when there's a payload CRC error, or a header error and no valid header (to avoid false alarm from previous packet) + if((irq & RADIOLIB_LR11X0_IRQ_CRC_ERR) || ((irq & RADIOLIB_LR11X0_IRQ_HEADER_ERR) && !(irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID))) { + crcState = RADIOLIB_ERR_CRC_MISMATCH; + } + + // get packet length + // the offset is needed since LR11x0 seems to move the buffer base by 4 bytes on every packet + uint8_t offset = 0; + size_t length = LR1110::getPacketLength(true, &offset); + if((len != 0) && (len < length)) { + // user requested less data than we got, only return what was requested + length = len; + } + + // read packet data + state = readBuffer8(data, length, (uint8_t)(offset + this->shiftCount)); // add shiftCount to offset - only change from radiolib + RADIOLIB_ASSERT(state); + + // clear the Rx buffer + state = clearRxBuffer(); + RADIOLIB_ASSERT(state); + + // clear interrupt flags + state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL); + + // check if CRC failed - this is done after reading data to give user the option to keep them + RADIOLIB_ASSERT(crcState); + + return(state); + } + RadioLibTime_t getTimeOnAir(size_t len) override { // calculate number of symbols float N_symbol = 0;