diff --git a/src/modules/LR11x0/LR11x0.cpp b/src/modules/LR11x0/LR11x0.cpp index d1e1c0aa3..bcef4d0bd 100644 --- a/src/modules/LR11x0/LR11x0.cpp +++ b/src/modules/LR11x0/LR11x0.cpp @@ -1328,12 +1328,35 @@ int16_t LR11x0::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) { return(RADIOLIB_ERR_NONE); } -bool LR11x0::isRxTimeout() { - uint32_t irq = getIrqStatus(); - bool rxTimedOut = irq & RADIOLIB_LR11X0_IRQ_TIMEOUT; - return(rxTimedOut); +int16_t LR11x0::checkIrq(uint8_t irq) { + uint16_t flags = getIrqStatus(); + switch(irq) { + case RADIOLIB_IRQ_TX_DONE: + return(flags & RADIOLIB_LR11X0_IRQ_TX_DONE); + case RADIOLIB_IRQ_RX_DONE: + return(flags & RADIOLIB_LR11X0_IRQ_RX_DONE); + case RADIOLIB_IRQ_PREAMBLE_DETECTED: + return(flags & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED); + case RADIOLIB_IRQ_SYNC_WORD_VALID: + return(flags & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID); + case RADIOLIB_IRQ_HEADER_VALID: + return(flags & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID); + case RADIOLIB_IRQ_HEADER_ERR: + return(flags & RADIOLIB_LR11X0_IRQ_HEADER_ERR); + case RADIOLIB_IRQ_CRC_ERR: + return(flags & RADIOLIB_LR11X0_IRQ_CRC_ERR); + case RADIOLIB_IRQ_CAD_DONE: + return(flags & RADIOLIB_LR11X0_IRQ_CAD_DONE); + case RADIOLIB_IRQ_CAD_DETECTED: + return(flags & RADIOLIB_LR11X0_IRQ_CAD_DETECTED); + case RADIOLIB_IRQ_TIMEOUT: + return(flags & RADIOLIB_LR11X0_IRQ_TIMEOUT); + default: + return(RADIOLIB_ERR_UNSUPPORTED); + } + return(RADIOLIB_ERR_UNSUPPORTED); } - + uint8_t LR11x0::randomByte() { uint32_t num = 0; (void)getRandomNumber(&num); diff --git a/src/modules/LR11x0/LR11x0.h b/src/modules/LR11x0/LR11x0.h index 741e86230..dffac085f 100644 --- a/src/modules/LR11x0/LR11x0.h +++ b/src/modules/LR11x0/LR11x0.h @@ -1229,10 +1229,10 @@ class LR11x0: public PhysicalLayer { int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) override; /*! - \brief Check whether the IRQ bit for RxTimeout is set - \returns Whether RxTimeout IRQ is set + \brief Check whether a specific IRQ bit is set (e.g. RxTimeout, CadDone). + \returns Whether requested IRQ is set. */ - bool isRxTimeout() override; + int16_t checkIrq(uint8_t irq) override; /*! \brief Get one truly random byte from RSSI noise. diff --git a/src/modules/SX126x/SX126x.cpp b/src/modules/SX126x/SX126x.cpp index b98fad596..1c2a9e483 100644 --- a/src/modules/SX126x/SX126x.cpp +++ b/src/modules/SX126x/SX126x.cpp @@ -1466,10 +1466,33 @@ int16_t SX126x::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) { return(RADIOLIB_ERR_NONE); } -bool SX126x::isRxTimeout() { - uint16_t irq = getIrqStatus(); - bool rxTimedOut = irq & RADIOLIB_SX126X_IRQ_TIMEOUT; - return(rxTimedOut); +int16_t SX126x::checkIrq(uint8_t irq) { + uint16_t flags = getIrqStatus(); + switch(irq) { + case RADIOLIB_IRQ_TX_DONE: + return(flags & RADIOLIB_SX126X_IRQ_TX_DONE); + case RADIOLIB_IRQ_RX_DONE: + return(flags & RADIOLIB_SX126X_IRQ_RX_DONE); + case RADIOLIB_IRQ_PREAMBLE_DETECTED: + return(flags & RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED); + case RADIOLIB_IRQ_SYNC_WORD_VALID: + return(flags & RADIOLIB_SX126X_IRQ_SYNC_WORD_VALID); + case RADIOLIB_IRQ_HEADER_VALID: + return(flags & RADIOLIB_SX126X_IRQ_HEADER_VALID); + case RADIOLIB_IRQ_HEADER_ERR: + return(flags & RADIOLIB_SX126X_IRQ_HEADER_ERR); + case RADIOLIB_IRQ_CRC_ERR: + return(flags & RADIOLIB_SX126X_IRQ_CRC_ERR); + case RADIOLIB_IRQ_CAD_DONE: + return(flags & RADIOLIB_SX126X_IRQ_CAD_DONE); + case RADIOLIB_IRQ_CAD_DETECTED: + return(flags & RADIOLIB_SX126X_IRQ_CAD_DETECTED); + case RADIOLIB_IRQ_TIMEOUT: + return(flags & RADIOLIB_SX126X_IRQ_TIMEOUT); + default: + return(RADIOLIB_ERR_UNSUPPORTED); + } + return(RADIOLIB_ERR_UNSUPPORTED); } int16_t SX126x::implicitHeader(size_t len) { diff --git a/src/modules/SX126x/SX126x.h b/src/modules/SX126x/SX126x.h index 631695191..68598650c 100644 --- a/src/modules/SX126x/SX126x.h +++ b/src/modules/SX126x/SX126x.h @@ -997,10 +997,10 @@ class SX126x: public PhysicalLayer { int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) override; /*! - \brief Check whether the IRQ bit for RxTimeout is set - \returns Whether RxTimeout IRQ is set + \brief Check whether a specific IRQ bit is set (e.g. RxTimeout, CadDone). + \returns Whether requested IRQ is set. */ - bool isRxTimeout() override; + int16_t checkIrq(uint8_t irq) override; /*! \brief Set implicit header mode for future reception/transmission. diff --git a/src/modules/SX127x/SX127x.cpp b/src/modules/SX127x/SX127x.cpp index eaa8c46f6..7cc33c9fd 100644 --- a/src/modules/SX127x/SX127x.cpp +++ b/src/modules/SX127x/SX127x.cpp @@ -1302,10 +1302,27 @@ int16_t SX127x::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) { return(RADIOLIB_ERR_NONE); } -bool SX127x::isRxTimeout() { - uint16_t irq = getIRQFlags(); - bool rxTimedOut = irq & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_TIMEOUT; - return(rxTimedOut); +int16_t SX127x::checkIrq(uint8_t irq) { + uint16_t flags = getIRQFlags(); + switch(irq) { + case RADIOLIB_IRQ_TX_DONE: + return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_TX_DONE); + case RADIOLIB_IRQ_RX_DONE: + return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_DONE); + case RADIOLIB_IRQ_HEADER_VALID: + return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_VALID_HEADER); + case RADIOLIB_IRQ_CRC_ERR: + return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR); + case RADIOLIB_IRQ_CAD_DONE: + return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DONE); + case RADIOLIB_IRQ_CAD_DETECTED: + return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DETECTED); + case RADIOLIB_IRQ_TIMEOUT: + return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_TIMEOUT); + default: + return(RADIOLIB_ERR_UNSUPPORTED); + } + return(RADIOLIB_ERR_UNSUPPORTED); } int16_t SX127x::setCrcFiltering(bool enable) { diff --git a/src/modules/SX127x/SX127x.h b/src/modules/SX127x/SX127x.h index 7e8d5e5a4..c00cd42f9 100644 --- a/src/modules/SX127x/SX127x.h +++ b/src/modules/SX127x/SX127x.h @@ -1073,10 +1073,10 @@ class SX127x: public PhysicalLayer { int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) override; /*! - \brief Check whether the IRQ bit for RxTimeout is set - \returns Whether RxTimeout IRQ is set + \brief Check whether a specific IRQ bit is set (e.g. RxTimeout, CadDone). + \returns Whether requested IRQ is set. */ - bool isRxTimeout() override; + int16_t checkIrq(uint8_t irq) override; /*! \brief Enable CRC filtering and generation. diff --git a/src/modules/SX128x/SX128x.cpp b/src/modules/SX128x/SX128x.cpp index 3d17e029d..fb9ed3283 100644 --- a/src/modules/SX128x/SX128x.cpp +++ b/src/modules/SX128x/SX128x.cpp @@ -638,6 +638,35 @@ int16_t SX128x::readData(uint8_t* data, size_t len) { return(state); } +int16_t SX128x::checkIrq(uint8_t irq) { + uint16_t flags = getIrqStatus(); + switch(irq) { + case RADIOLIB_IRQ_TX_DONE: + return(flags & RADIOLIB_SX128X_IRQ_TX_DONE); + case RADIOLIB_IRQ_RX_DONE: + return(flags & RADIOLIB_SX128X_IRQ_RX_DONE); + case RADIOLIB_IRQ_PREAMBLE_DETECTED: + return(flags & RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED); + case RADIOLIB_IRQ_SYNC_WORD_VALID: + return(flags & RADIOLIB_SX128X_IRQ_SYNC_WORD_VALID); + case RADIOLIB_IRQ_HEADER_VALID: + return(flags & RADIOLIB_SX128X_IRQ_HEADER_VALID); + case RADIOLIB_IRQ_HEADER_ERR: + return(flags & RADIOLIB_SX128X_IRQ_HEADER_ERROR); + case RADIOLIB_IRQ_CRC_ERR: + return(flags & RADIOLIB_SX128X_IRQ_CRC_ERROR); + case RADIOLIB_IRQ_CAD_DONE: + return(flags & RADIOLIB_SX128X_IRQ_CAD_DONE); + case RADIOLIB_IRQ_CAD_DETECTED: + return(flags & RADIOLIB_SX128X_IRQ_CAD_DETECTED); + case RADIOLIB_IRQ_TIMEOUT: + return(flags & RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT); + default: + return(RADIOLIB_ERR_UNSUPPORTED); + } + return(RADIOLIB_ERR_UNSUPPORTED); +} + int16_t SX128x::startChannelScan() { // check active modem if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) { diff --git a/src/modules/SX128x/SX128x.h b/src/modules/SX128x/SX128x.h index 8c0d465a1..43c1f4128 100644 --- a/src/modules/SX128x/SX128x.h +++ b/src/modules/SX128x/SX128x.h @@ -576,6 +576,12 @@ class SX128x: public PhysicalLayer { */ int16_t readData(uint8_t* data, size_t len) override; + /*! + \brief Check whether a specific IRQ bit is set (e.g. RxTimeout, CadDone). + \returns Whether requested IRQ is set. + */ + int16_t checkIrq(uint8_t irq) override; + /*! \brief Interrupt-driven channel activity detection method. DIO1 will be activated when LoRa preamble is detected, or upon timeout. Defaults to CAD parameter values recommended by AN1200.48. diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp index 90325ecf5..c27feaa4f 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.cpp +++ b/src/protocols/LoRaWAN/LoRaWAN.cpp @@ -1196,6 +1196,8 @@ int16_t LoRaWANNode::downlinkCommon() { this->phyLayer->setPacketReceivedAction(LoRaWANNodeOnDownlinkAction); + int16_t timedOut = 0; + // perform listening in the two Rx windows for(uint8_t i = 0; i < 2; i++) { downlinkAction = false; @@ -1226,7 +1228,11 @@ int16_t LoRaWANNode::downlinkCommon() { RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Closing Rx%d window", i+1); // check if the IRQ bit for Rx Timeout is set - if(!this->phyLayer->isRxTimeout()) { + timedOut = this->phyLayer->checkIrq(RADIOLIB_IRQ_TIMEOUT); + if(timedOut == RADIOLIB_ERR_UNSUPPORTED) { + return(timedOut); + } + if(!timedOut) { break; } else if(i == 0) { @@ -1248,7 +1254,7 @@ int16_t LoRaWANNode::downlinkCommon() { this->rxDelayEnd = mod->hal->millis(); // if we got here due to a timeout, stop ongoing activities - if(this->phyLayer->isRxTimeout()) { + if(timedOut) { this->phyLayer->standby(); // TODO check: this should be done automagically due to RxSingle? if(this->modulation == RADIOLIB_LORAWAN_MODULATION_LORA) { this->phyLayer->invertIQ(false); diff --git a/src/protocols/PhysicalLayer/PhysicalLayer.cpp b/src/protocols/PhysicalLayer/PhysicalLayer.cpp index dc97908bc..6953447c9 100644 --- a/src/protocols/PhysicalLayer/PhysicalLayer.cpp +++ b/src/protocols/PhysicalLayer/PhysicalLayer.cpp @@ -316,8 +316,9 @@ int16_t PhysicalLayer::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) return(RADIOLIB_ERR_UNSUPPORTED); } -bool PhysicalLayer::isRxTimeout() { - return(false); +int16_t PhysicalLayer::checkIrq(uint8_t irq) { + (void)irq; + return(RADIOLIB_ERR_UNSUPPORTED); } int16_t PhysicalLayer::startChannelScan() { diff --git a/src/protocols/PhysicalLayer/PhysicalLayer.h b/src/protocols/PhysicalLayer/PhysicalLayer.h index ad53f622b..408408aed 100644 --- a/src/protocols/PhysicalLayer/PhysicalLayer.h +++ b/src/protocols/PhysicalLayer/PhysicalLayer.h @@ -4,6 +4,18 @@ #include "../../TypeDef.h" #include "../../Module.h" +// common IRQ flags +#define RADIOLIB_IRQ_TX_DONE 0x00 +#define RADIOLIB_IRQ_RX_DONE 0x01 +#define RADIOLIB_IRQ_PREAMBLE_DETECTED 0x02 +#define RADIOLIB_IRQ_SYNC_WORD_VALID 0x03 +#define RADIOLIB_IRQ_HEADER_VALID 0x04 +#define RADIOLIB_IRQ_HEADER_ERR 0x05 +#define RADIOLIB_IRQ_CRC_ERR 0x06 +#define RADIOLIB_IRQ_CAD_DONE 0x07 +#define RADIOLIB_IRQ_CAD_DETECTED 0x08 +#define RADIOLIB_IRQ_TIMEOUT 0x09 + /*! \struct LoRaRate_t \brief Data rate structure interpretation in case LoRa is used @@ -346,28 +358,29 @@ class PhysicalLayer { virtual RadioLibTime_t getTimeOnAir(size_t len); /*! - \brief Calculate the timeout value for this specific module / series (in number of symbols or units of time) - \param timeoutUs Timeout in microseconds to listen for - \returns Timeout value in a unit that is specific for the used module + \brief Calculate the timeout value for this specific module / series + (in number of symbols or units of time). + \param timeoutUs Timeout in microseconds to listen for. + \returns Timeout value in a unit that is specific for the used module. */ virtual RadioLibTime_t calculateRxTimeout(RadioLibTime_t timeoutUs); /*! - \brief Create the flags that make up RxDone and RxTimeout used for receiving downlinks - \param irqFlags The flags for which IRQs must be triggered - \param irqMask Mask indicating which IRQ triggers a DIO + \brief Create the flags that make up RxDone and RxTimeout used for receiving downlinks. + \param irqFlags The flags for which IRQs must be triggered. + \param irqMask Mask indicating which IRQ triggers a DIO. \returns \ref status_codes */ virtual int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask); /*! - \brief Check whether the IRQ bit for RxTimeout is set - \returns Whether RxTimeout IRQ is set + \brief Check whether a specific IRQ bit is set (e.g. RxTimeout, CadDone). + \returns Whether requested IRQ is set. */ - virtual bool isRxTimeout(); + virtual int16_t checkIrq(uint8_t irq); /*! - \brief Interrupt-driven channel activity detection method. interrupt will be activated + \brief Interrupt-driven channel activity detection method. Interrupt will be activated when packet is detected. Must be implemented in module class. \returns \ref status_codes */