Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PHY, modules, LoRaWAN] Generalize IRQ checks #1188

Merged
merged 9 commits into from
Aug 18, 2024
33 changes: 28 additions & 5 deletions src/modules/LR11x0/LR11x0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions src/modules/LR11x0/LR11x0.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
31 changes: 27 additions & 4 deletions src/modules/SX126x/SX126x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions src/modules/SX126x/SX126x.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
25 changes: 21 additions & 4 deletions src/modules/SX127x/SX127x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions src/modules/SX127x/SX127x.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
29 changes: 29 additions & 0 deletions src/modules/SX128x/SX128x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 6 additions & 0 deletions src/modules/SX128x/SX128x.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 8 additions & 2 deletions src/protocols/LoRaWAN/LoRaWAN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand Down
5 changes: 3 additions & 2 deletions src/protocols/PhysicalLayer/PhysicalLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
33 changes: 23 additions & 10 deletions src/protocols/PhysicalLayer/PhysicalLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
*/
Expand Down
Loading