[PHY] Channel scan configuration (#1190)

* [PHY] Added channel scan configuration

* [LR11x0] Added channel scan configuration

* [SX126x] Added channel scan configuration

* [SX128x] Added channel scan configuration

* Use microsecond timeout

* [PHY] Added generalized IRQ handling via PHY

* [LR11x0] Added generalized IRQ handling via PHY

* [SX126x] Added generalized IRQ handling via PHY

* [SX127x] Added generalized IRQ handling via PHY

* [SX128x] Added generalized IRQ handling via PHY

* Added missing typedef

* [PHY] Fix IRQ method argument type

* [SX128x] Fix non-trivial initializer usage

* [LR11x0] Added missing override specifiers

* [SX126x] Added missing override specifiers

* [SX127x] Added missing override specifiers

* [SX128x] Added missing override specifiers

* [PHY] Added missing IRQ map initializer

* [CI] Drop APRS builds on AVR

* [CI] Drop Morse builds for AVR

* [PHY] Rework generic IRQ to allow multiple flags

* [LR11x0] Rework generic IRQ to allow multiple flags

* [SX126x] Rework generic IRQ to allow multiple flags

* [SX127x] Rework generic IRQ to allow multiple flags

* [SX128x] Rework generic IRQ to allow multiple flags

* [LoRaWAN] Use generic IRQ

* Add missing typedef

* [SX127x] Make Rx mode implicit based on timeout

* [SX127x] Fixed shadowed variable

* [LR11x0] Fix missing initializers

* [SX127x] Added default startReceive arguments

* [LR11x0] Pass scan config by const reference

* [SX126x] Pass scan config by const reference

* [SX128x] Pass scan config by const reference

* [PHY] Pass scan config by const reference

* [SX127x] Add missing IRQ conversion

* [SX126x] Fixed default CAD scan config IRQ

* [LR11x0] Fixed default CAD scan config IRQ

* [LR11x0] Fix comments referencing DIO1
pull/1203/head
Jan Gromeš 2024-09-01 18:19:07 +02:00 zatwierdzone przez GitHub
rodzic d9c0c4ed44
commit bc801c7004
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
14 zmienionych plików z 606 dodań i 350 usunięć

Wyświetl plik

@ -46,7 +46,7 @@ jobs:
# platform-dependent settings - extra board options, board index URLs, skip patterns etc.
include:
- id: arduino:avr:uno
run: echo "skip-pattern=(STM32WL|SSTV|LoRaWAN|LR11x0_Firmware_Update|Pager)" >> $GITHUB_OUTPUT
run: echo "skip-pattern=(STM32WL|SSTV|LoRaWAN|LR11x0_Firmware_Update|Pager|APRS|Morse)" >> $GITHUB_OUTPUT
- id: arduino:avr:mega
run: |
echo "options=':cpu=atmega2560'" >> $GITHUB_OUTPUT

Wyświetl plik

@ -168,9 +168,9 @@ void loop() {
// check if we got a preamble
if(detectedFlag) {
// LoRa preamble was detected
// LoRa preamble was detected, start reception with timeout of 100 LoRa symbols
Serial.print(F("[SX1278] Preamble detected, starting reception ... "));
state = radio.startReceive(0, RADIOLIB_SX127X_RXSINGLE);
state = radio.startReceive(100);
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {

Wyświetl plik

@ -615,6 +615,12 @@
*/
typedef unsigned long RadioLibTime_t;
/*!
\brief Type used for radio-agnostic IRQ flags. IRQ to enable corresponds to the bit index (RadioLibIrq_t).
For example, if bit 0 is set, the module will enable its RADIOLIB_IRQ_TX_DONE (if it is supported).
*/
typedef uint32_t RadioLibIrqFlags_t;
/*!
\}
*/

Wyświetl plik

@ -11,6 +11,16 @@
LR11x0::LR11x0(Module* mod) : PhysicalLayer(RADIOLIB_LR11X0_FREQUENCY_STEP_SIZE, RADIOLIB_LR11X0_MAX_PACKET_LENGTH) {
this->mod = mod;
this->XTAL = false;
this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_LR11X0_IRQ_TX_DONE;
this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_LR11X0_IRQ_RX_DONE;
this->irqMap[RADIOLIB_IRQ_PREAMBLE_DETECTED] = RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED;
this->irqMap[RADIOLIB_IRQ_SYNC_WORD_VALID] = RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID;
this->irqMap[RADIOLIB_IRQ_HEADER_VALID] = RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID;
this->irqMap[RADIOLIB_IRQ_HEADER_ERR] = RADIOLIB_LR11X0_IRQ_HEADER_ERR;
this->irqMap[RADIOLIB_IRQ_CRC_ERR] = RADIOLIB_LR11X0_IRQ_CRC_ERR;
this->irqMap[RADIOLIB_IRQ_CAD_DONE] = RADIOLIB_LR11X0_IRQ_CAD_DONE;
this->irqMap[RADIOLIB_IRQ_CAD_DETECTED] = RADIOLIB_LR11X0_IRQ_CAD_DETECTED;
this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_LR11X0_IRQ_TIMEOUT;
}
int16_t LR11x0::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t preambleLength, float tcxoVoltage) {
@ -278,12 +288,23 @@ int16_t LR11x0::receiveDirect() {
}
int16_t LR11x0::scanChannel() {
return(this->scanChannel(RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, RADIOLIB_LR11X0_CAD_PARAM_DEFAULT));
ChannelScanConfig_t config = {
.cad = {
.symNum = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT,
.detPeak = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT,
.detMin = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT,
.exitMode = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT,
.timeout = 0,
.irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
.irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
},
};
return(this->scanChannel(config));
}
int16_t LR11x0::scanChannel(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
int16_t LR11x0::scanChannel(ChannelScanConfig_t config) {
// set mode to CAD
int state = startChannelScan(symbolNum, detPeak, detMin);
int state = startChannelScan(config);
RADIOLIB_ASSERT(state);
// wait for channel activity detected or timeout
@ -460,10 +481,9 @@ int16_t LR11x0::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMa
// set DIO mapping
uint32_t irq = irqFlags;
if(timeout != RADIOLIB_LR11X0_RX_TIMEOUT_INF) {
irq |= RADIOLIB_LR11X0_IRQ_TIMEOUT;
irq |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
state = setDioIrqParams(irq);
state = setDioIrqParams(getIrqMapped(irq));
RADIOLIB_ASSERT(state);
// clear interrupt flags
@ -541,10 +561,21 @@ int16_t LR11x0::readData(uint8_t* data, size_t len) {
}
int16_t LR11x0::startChannelScan() {
return(this->startChannelScan(RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, RADIOLIB_LR11X0_CAD_PARAM_DEFAULT));
ChannelScanConfig_t config = {
.cad = {
.symNum = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT,
.detPeak = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT,
.detMin = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT,
.exitMode = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT,
.timeout = 0,
.irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
.irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
},
};
return(this->startChannelScan(config));
}
int16_t LR11x0::startChannelScan(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
int16_t LR11x0::startChannelScan(const ChannelScanConfig_t &config) {
// check active modem
int16_t state = RADIOLIB_ERR_NONE;
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
@ -562,7 +593,8 @@ int16_t LR11x0::startChannelScan(uint8_t symbolNum, uint8_t detPeak, uint8_t det
this->mod->setRfSwitchState(Module::MODE_RX);
// set DIO pin mapping
state = setDioIrqParams(RADIOLIB_LR11X0_IRQ_CAD_DETECTED | RADIOLIB_LR11X0_IRQ_CAD_DONE);
uint16_t irqFlags = (config.cad.irqFlags == RADIOLIB_IRQ_NOT_SUPPORTED) ? RADIOLIB_LR11X0_IRQ_CAD_DETECTED | RADIOLIB_LR11X0_IRQ_CAD_DONE : config.cad.irqFlags;
state = setDioIrqParams(irqFlags, irqFlags);
RADIOLIB_ASSERT(state);
// clear interrupt flags
@ -570,7 +602,7 @@ int16_t LR11x0::startChannelScan(uint8_t symbolNum, uint8_t detPeak, uint8_t det
RADIOLIB_ASSERT(state);
// set mode to CAD
return(startCad(symbolNum, detPeak, detMin));
return(startCad(config.cad.symNum, config.cad.detPeak, config.cad.detMin, config.cad.exitMode, config.cad.timeout));
}
int16_t LR11x0::getChannelScanResult() {
@ -1322,39 +1354,16 @@ RadioLibTime_t LR11x0::calculateRxTimeout(RadioLibTime_t timeoutUs) {
return(timeout);
}
int16_t LR11x0::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) {
irqFlags = RADIOLIB_LR11X0_IRQ_RX_DONE | RADIOLIB_LR11X0_IRQ_TIMEOUT; // flags that can appear in the IRQ register
irqMask = irqFlags; // on LR11x0, these are the same
return(RADIOLIB_ERR_NONE);
uint32_t LR11x0::getIrqFlags() {
return((uint32_t)this->getIrqStatus());
}
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);
int16_t LR11x0::setIrqFlags(uint32_t irq) {
return(this->setDioIrqParams(irq, irq));
}
int16_t LR11x0::clearIrqFlags(uint32_t irq) {
return(this->clearIrq(irq));
}
uint8_t LR11x0::randomByte() {
@ -2008,7 +2017,7 @@ int16_t LR11x0::setPacketMode(uint8_t mode, uint8_t len) {
return(state);
}
int16_t LR11x0::startCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
int16_t LR11x0::startCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin, uint8_t exitMode, RadioLibTime_t timeout) {
// check active modem
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
int16_t state = getPacketType(&type);
@ -2035,9 +2044,16 @@ int16_t LR11x0::startCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
min = 10;
}
uint8_t mode = exitMode;
if(mode == RADIOLIB_LR11X0_CAD_PARAM_DEFAULT) {
mode = RADIOLIB_LR11X0_CAD_EXIT_MODE_STBY_RC;
}
uint32_t timeout_raw = (float)timeout / 30.52f;
// set CAD parameters
// TODO add configurable exit mode and timeout
state = setCadParams(num, peak, min, RADIOLIB_LR11X0_CAD_EXIT_MODE_STBY_RC, 0);
state = setCadParams(num, peak, min, mode, timeout_raw);
RADIOLIB_ASSERT(state);
// start CAD

Wyświetl plik

@ -844,12 +844,10 @@ class LR11x0: public PhysicalLayer {
/*!
\brief Performs scan for LoRa transmission in the current channel. Detects both preamble and payload.
\param symbolNum Number of symbols for CAD detection.
\param detPeak Peak value for CAD detection.
\param detMin Minimum value for CAD detection.
\param config CAD configuration structure.
\returns \ref status_codes
*/
int16_t scanChannel(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin);
int16_t scanChannel(ChannelScanConfig_t config) override;
/*!
\brief Sets the module to standby mode (overload for PhysicalLayer compatibility, uses 13 MHz RC oscillator).
@ -979,14 +977,12 @@ class LR11x0: public PhysicalLayer {
int16_t startChannelScan() override;
/*!
\brief Interrupt-driven channel activity detection method. IRQ1 will be activated
\brief Interrupt-driven channel activity detection method. IRQ pin will be activated
when LoRa preamble is detected, or upon timeout.
\param symbolNum Number of symbols for CAD detection.
\param detPeak Peak value for CAD detection.
\param detMin Minimum value for CAD detection.
\param config CAD configuration structure.
\returns \ref status_codes
*/
int16_t startChannelScan(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin);
int16_t startChannelScan(const ChannelScanConfig_t &config) override;
/*!
\brief Read the channel scan result
@ -1221,18 +1217,24 @@ class LR11x0: public PhysicalLayer {
RadioLibTime_t calculateRxTimeout(RadioLibTime_t timeoutUs) override;
/*!
\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
\brief Read currently active IRQ flags.
\returns IRQ flags.
*/
int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) override;
uint32_t getIrqFlags() override;
/*!
\brief Check whether a specific IRQ bit is set (e.g. RxTimeout, CadDone).
\returns Whether requested IRQ is set.
\brief Set interrupt on IRQ pin to be sent on a specific IRQ bit (e.g. RxTimeout, CadDone).
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
int16_t checkIrq(uint8_t irq) override;
int16_t setIrqFlags(uint32_t irq) override;
/*!
\brief Clear interrupt on a specific IRQ bit (e.g. RxTimeout, CadDone).
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
int16_t clearIrqFlags(uint32_t irq) override;
/*!
\brief Get one truly random byte from RSSI noise.
@ -1618,7 +1620,7 @@ class LR11x0: public PhysicalLayer {
bool findChip(uint8_t ver);
int16_t config(uint8_t modem);
int16_t setPacketMode(uint8_t mode, uint8_t len);
int16_t startCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin);
int16_t startCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin, uint8_t exitMode, RadioLibTime_t timeout);
int16_t setHeaderType(uint8_t hdrType, size_t len = 0xFF);
// common methods to avoid some copy-paste

Wyświetl plik

@ -7,6 +7,16 @@ SX126x::SX126x(Module* mod) : PhysicalLayer(RADIOLIB_SX126X_FREQUENCY_STEP_SIZE,
this->mod = mod;
this->XTAL = false;
this->standbyXOSC = false;
this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_SX126X_IRQ_TX_DONE;
this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_SX126X_IRQ_RX_DONE;
this->irqMap[RADIOLIB_IRQ_PREAMBLE_DETECTED] = RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED;
this->irqMap[RADIOLIB_IRQ_SYNC_WORD_VALID] = RADIOLIB_SX126X_IRQ_SYNC_WORD_VALID;
this->irqMap[RADIOLIB_IRQ_HEADER_VALID] = RADIOLIB_SX126X_IRQ_HEADER_VALID;
this->irqMap[RADIOLIB_IRQ_HEADER_ERR] = RADIOLIB_SX126X_IRQ_HEADER_ERR;
this->irqMap[RADIOLIB_IRQ_CRC_ERR] = RADIOLIB_SX126X_IRQ_CRC_ERR;
this->irqMap[RADIOLIB_IRQ_CAD_DONE] = RADIOLIB_SX126X_IRQ_CAD_DONE;
this->irqMap[RADIOLIB_IRQ_CAD_DETECTED] = RADIOLIB_SX126X_IRQ_CAD_DETECTED;
this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_SX126X_IRQ_TIMEOUT;
}
int16_t SX126x::begin(uint8_t cr, uint8_t syncWord, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
@ -317,7 +327,7 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
}
// check whether this was a timeout or not
if((getIrqStatus() & RADIOLIB_SX126X_IRQ_TIMEOUT) || softTimeout) {
if((getIrqFlags() & RADIOLIB_SX126X_IRQ_TIMEOUT) || softTimeout) {
standby();
fixImplicitTimeout();
clearIrqStatus();
@ -425,12 +435,23 @@ int16_t SX126x::packetMode() {
}
int16_t SX126x::scanChannel() {
return(this->scanChannel(RADIOLIB_SX126X_CAD_PARAM_DEFAULT, RADIOLIB_SX126X_CAD_PARAM_DEFAULT, RADIOLIB_SX126X_CAD_PARAM_DEFAULT));
ChannelScanConfig_t config = {
.cad = {
.symNum = RADIOLIB_SX126X_CAD_PARAM_DEFAULT,
.detPeak = RADIOLIB_SX126X_CAD_PARAM_DEFAULT,
.detMin = RADIOLIB_SX126X_CAD_PARAM_DEFAULT,
.exitMode = RADIOLIB_SX126X_CAD_PARAM_DEFAULT,
.timeout = 0,
.irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
.irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
},
};
return(this->scanChannel(config));
}
int16_t SX126x::scanChannel(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
int16_t SX126x::scanChannel(ChannelScanConfig_t config) {
// set mode to CAD
int state = startChannelScan(symbolNum, detPeak, detMin);
int state = startChannelScan(config);
RADIOLIB_ASSERT(state);
// wait for channel activity detected or timeout
@ -442,7 +463,6 @@ int16_t SX126x::scanChannel(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin)
return(getChannelScanResult());
}
int16_t SX126x::sleep() {
return(SX126x::sleep(true));
}
@ -582,10 +602,10 @@ int16_t SX126x::finishTransmit() {
}
int16_t SX126x::startReceive() {
return(this->startReceive(RADIOLIB_SX126X_RX_TIMEOUT_INF, RADIOLIB_SX126X_IRQ_RX_DEFAULT, RADIOLIB_SX126X_IRQ_RX_DONE, 0));
return(this->startReceive(RADIOLIB_SX126X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
}
int16_t SX126x::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
int16_t SX126x::startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
(void)len;
int16_t state = startReceiveCommon(timeout, irqFlags, irqMask);
RADIOLIB_ASSERT(state);
@ -599,7 +619,7 @@ int16_t SX126x::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMa
return(state);
}
int16_t SX126x::startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod, uint16_t irqFlags, uint16_t irqMask) {
int16_t SX126x::startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask) {
// datasheet claims time to go to sleep is ~500us, same to wake up, compensate for that with 1 ms + TCXO delay
uint32_t transitionTime = this->tcxoDelay + 1000;
sleepPeriod -= transitionTime;
@ -626,7 +646,7 @@ int16_t SX126x::startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod, u
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RX_DUTY_CYCLE, data, 6));
}
int16_t SX126x::startReceiveDutyCycleAuto(uint16_t senderPreambleLength, uint16_t minSymbols, uint16_t irqFlags, uint16_t irqMask) {
int16_t SX126x::startReceiveDutyCycleAuto(uint16_t senderPreambleLength, uint16_t minSymbols, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask) {
if(senderPreambleLength == 0) {
senderPreambleLength = this->preambleLengthLoRa;
}
@ -664,12 +684,12 @@ int16_t SX126x::startReceiveDutyCycleAuto(uint16_t senderPreambleLength, uint16_
return(startReceiveDutyCycle(wakePeriod, sleepPeriod, irqFlags, irqMask));
}
int16_t SX126x::startReceiveCommon(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask) {
int16_t SX126x::startReceiveCommon(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask) {
// set DIO mapping
if(timeout != RADIOLIB_SX126X_RX_TIMEOUT_INF) {
irqMask |= RADIOLIB_SX126X_IRQ_TIMEOUT;
irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
int16_t state = setDioIrqParams(irqFlags, irqMask);
int16_t state = setDioIrqParams(getIrqMapped(irqFlags), getIrqMapped(irqMask));
RADIOLIB_ASSERT(state);
// set buffer pointers
@ -697,14 +717,14 @@ int16_t SX126x::readData(uint8_t* data, size_t len) {
// if that's the case, the first call will return "SPI command timeout error"
// check the IRQ to be sure this really originated from timeout event
int16_t state = this->mod->SPIcheckStream();
if((state == RADIOLIB_ERR_SPI_CMD_TIMEOUT) && (getIrqStatus() & RADIOLIB_SX126X_IRQ_TIMEOUT)) {
if((state == RADIOLIB_ERR_SPI_CMD_TIMEOUT) && (getIrqFlags() & RADIOLIB_SX126X_IRQ_TIMEOUT)) {
// this is definitely Rx timeout
return(RADIOLIB_ERR_RX_TIMEOUT);
}
RADIOLIB_ASSERT(state);
// check integrity CRC
uint16_t irq = getIrqStatus();
uint16_t irq = getIrqFlags();
int16_t crcState = RADIOLIB_ERR_NONE;
if((irq & RADIOLIB_SX126X_IRQ_CRC_ERR) || (irq & RADIOLIB_SX126X_IRQ_HEADER_ERR)) {
crcState = RADIOLIB_ERR_CRC_MISMATCH;
@ -732,10 +752,21 @@ int16_t SX126x::readData(uint8_t* data, size_t len) {
}
int16_t SX126x::startChannelScan() {
return(this->startChannelScan(RADIOLIB_SX126X_CAD_PARAM_DEFAULT, RADIOLIB_SX126X_CAD_PARAM_DEFAULT, RADIOLIB_SX126X_CAD_PARAM_DEFAULT));
ChannelScanConfig_t config = {
.cad = {
.symNum = RADIOLIB_SX126X_CAD_PARAM_DEFAULT,
.detPeak = RADIOLIB_SX126X_CAD_PARAM_DEFAULT,
.detMin = RADIOLIB_SX126X_CAD_PARAM_DEFAULT,
.exitMode = RADIOLIB_SX126X_CAD_PARAM_DEFAULT,
.timeout = 0,
.irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
.irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
},
};
return(this->startChannelScan(config));
}
int16_t SX126x::startChannelScan(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
int16_t SX126x::startChannelScan(const ChannelScanConfig_t &config) {
// check active modem
if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
return(RADIOLIB_ERR_WRONG_MODEM);
@ -749,7 +780,7 @@ int16_t SX126x::startChannelScan(uint8_t symbolNum, uint8_t detPeak, uint8_t det
this->mod->setRfSwitchState(Module::MODE_RX);
// set DIO pin mapping
state = setDioIrqParams(RADIOLIB_SX126X_IRQ_CAD_DETECTED | RADIOLIB_SX126X_IRQ_CAD_DONE, RADIOLIB_SX126X_IRQ_CAD_DETECTED | RADIOLIB_SX126X_IRQ_CAD_DONE);
state = setDioIrqParams(getIrqMapped(config.cad.irqFlags), getIrqMapped(config.cad.irqMask));
RADIOLIB_ASSERT(state);
// clear interrupt flags
@ -757,7 +788,7 @@ int16_t SX126x::startChannelScan(uint8_t symbolNum, uint8_t detPeak, uint8_t det
RADIOLIB_ASSERT(state);
// set mode to CAD
state = setCad(symbolNum, detPeak, detMin);
state = setCad(config.cad.symNum, config.cad.detPeak, config.cad.detMin, config.cad.exitMode, config.cad.timeout);
return(state);
}
@ -768,7 +799,7 @@ int16_t SX126x::getChannelScanResult() {
}
// check CAD result
uint16_t cadResult = getIrqStatus();
uint16_t cadResult = getIrqFlags();
if(cadResult & RADIOLIB_SX126X_IRQ_CAD_DETECTED) {
// detected some LoRa activity
return(RADIOLIB_LORA_DETECTED);
@ -1460,39 +1491,18 @@ RadioLibTime_t SX126x::calculateRxTimeout(RadioLibTime_t timeoutUs) {
return(timeout);
}
int16_t SX126x::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) {
irqFlags = RADIOLIB_SX126X_IRQ_RX_DEFAULT; // flags that can appear in the IRQ register
irqMask = RADIOLIB_SX126X_IRQ_RX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT; // flags that will trigger DIO0
return(RADIOLIB_ERR_NONE);
uint32_t SX126x::getIrqFlags() {
uint8_t data[] = { 0x00, 0x00 };
this->mod->SPIreadStream(RADIOLIB_SX126X_CMD_GET_IRQ_STATUS, data, 2);
return(((uint32_t)(data[0]) << 8) | data[1]);
}
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::setIrqFlags(uint32_t irq) {
return(this->setDioIrqParams(irq, irq));
}
int16_t SX126x::clearIrqFlags(uint32_t irq) {
return(this->clearIrqStatus(irq));
}
int16_t SX126x::implicitHeader(size_t len) {
@ -1761,8 +1771,7 @@ int16_t SX126x::setRx(uint32_t timeout) {
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RX, data, 3, true, false));
}
int16_t SX126x::setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
int16_t SX126x::setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin, uint8_t exitMode, RadioLibTime_t timeout) {
// default CAD parameters are shown in Semtech AN1200.48, page 41.
const uint8_t detPeakValues[6] = { 22, 22, 24, 25, 26, 30};
@ -1773,29 +1782,17 @@ int16_t SX126x::setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
this->spreadingFactor = 12;
}
// build the packet
// build the packet with default configuration
uint8_t data[7];
data[0] = RADIOLIB_SX126X_CAD_ON_2_SYMB;
data[1] = detPeakValues[this->spreadingFactor - 7];
data[2] = RADIOLIB_SX126X_CAD_PARAM_DET_MIN;
data[3] = RADIOLIB_SX126X_CAD_GOTO_STDBY;
data[4] = 0x00;
data[5] = 0x00;
data[6] = 0x00;
uint32_t timeout_raw = (float)timeout / 15.625f;
data[4] = (uint8_t)((timeout_raw >> 16) & 0xFF);
data[5] = (uint8_t)((timeout_raw >> 8) & 0xFF);
data[6] = (uint8_t)(timeout_raw & 0xFF);
/*
CAD Configuration Note:
The default CAD configuration applied by `scanChannel` overrides the optimal SF-specific configurations, leading to suboptimal detection.
I.e., anything that is not RADIOLIB_SX126X_CAD_PARAM_DEFAULT is overridden. But CAD settings are SF specific.
To address this, the user override has been commented out, ensuring consistent application of the optimal CAD settings as
per Semtech's Application Note AN1200.48 (page 41) for the 125KHz setting. This approach significantly reduces false CAD occurrences.
Testing has shown that there is no reason for a user to change CAD settings for anything other than most optimal ones described in AN1200.48 .
However, this change does not respect CAD configs from the LoRaWAN layer. Future considerations or use cases might require revisiting this decision.
Hence this note.
*/
/*
// set user-provided values
if(symbolNum != RADIOLIB_SX126X_CAD_PARAM_DEFAULT) {
data[0] = symbolNum;
@ -1809,10 +1806,9 @@ int16_t SX126x::setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
data[2] = detMin;
}
*/
(void)symbolNum;
(void)detPeak;
(void)detMin;
if(exitMode != RADIOLIB_SX126X_CAD_PARAM_DEFAULT) {
data[3] = exitMode;
}
// configure parameters
int16_t state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_CAD_PARAMS, data, 7);
@ -1859,12 +1855,6 @@ int16_t SX126x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t di
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_DIO_IRQ_PARAMS, data, 8));
}
uint16_t SX126x::getIrqStatus() {
uint8_t data[] = { 0x00, 0x00 };
this->mod->SPIreadStream(RADIOLIB_SX126X_CMD_GET_IRQ_STATUS, data, 2);
return(((uint16_t)(data[0]) << 8) | data[1]);
}
int16_t SX126x::clearIrqStatus(uint16_t clearIrqParams) {
uint8_t data[] = { (uint8_t)((clearIrqParams >> 8) & 0xFF), (uint8_t)(clearIrqParams & 0xFF) };
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CLEAR_IRQ_STATUS, data, 2));

Wyświetl plik

@ -222,7 +222,6 @@
#define RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED 0b0000000000000100 // 2 2 preamble detected
#define RADIOLIB_SX126X_IRQ_RX_DONE 0b0000000000000010 // 1 1 packet received
#define RADIOLIB_SX126X_IRQ_TX_DONE 0b0000000000000001 // 0 0 packet transmission completed
#define RADIOLIB_SX126X_IRQ_RX_DEFAULT 0b0000001001100010 // 14 0 default for Rx (RX_DONE, TIMEOUT, CRC_ERR and HEADER_ERR)
#define RADIOLIB_SX126X_IRQ_ALL 0b0100001111111111 // 14 0 all interrupts
#define RADIOLIB_SX126X_IRQ_NONE 0b0000000000000000 // 14 0 no interrupts
@ -533,18 +532,17 @@ class SX126x: public PhysicalLayer {
/*!
\brief Performs scan for LoRa transmission in the current channel. Detects both preamble and payload.
Configuration defaults to the values recommended by AN1200.48.
\returns \ref status_codes
*/
int16_t scanChannel() override;
/*!
\brief Performs scan for LoRa transmission in the current channel. Detects both preamble and payload.
\param symbolNum Number of symbols for CAD detection. Defaults to the value recommended by AN1200.48.
\param detPeak Peak value for CAD detection. Defaults to the value recommended by AN1200.48.
\param detMin Minimum value for CAD detection. Defaults to the value recommended by AN1200.48.
\param config CAD configuration structure.
\returns \ref status_codes
*/
int16_t scanChannel(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin);
int16_t scanChannel(ChannelScanConfig_t config) override;
/*!
\brief Sets the module to sleep mode. To wake the device up, call standby().
@ -656,24 +654,26 @@ class SX126x: public PhysicalLayer {
For any other value, timeout will be applied and signal will be generated on DIO1 for conditions
defined by irqFlags and irqMask.
\param irqFlags Sets the IRQ flags, defaults to RADIOLIB_SX126X_IRQ_RX_DEFAULT.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RADIOLIB_SX126X_IRQ_RX_DONE.
\param irqFlags Sets the IRQ flags, defaults to RX done, RX timeout, CRC error and header error.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RX done.
\param len Only for PhysicalLayer compatibility, not used.
\returns \ref status_codes
*/
int16_t startReceive(uint32_t timeout, uint32_t irqFlags = RADIOLIB_SX126X_IRQ_RX_DEFAULT, uint32_t irqMask = RADIOLIB_SX126X_IRQ_RX_DONE, size_t len = 0);
int16_t startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK, size_t len = 0);
/*!
\brief Interrupt-driven receive method where the device mostly sleeps and periodically wakes to listen.
Note that this function assumes the unit will take 500us + TCXO_delay to change state.
See datasheet section 13.1.7, version 1.2.
\param rxPeriod The duration the receiver will be in Rx mode, in microseconds.
\param sleepPeriod The duration the receiver will not be in Rx mode, in microseconds.
\param irqFlags Sets the IRQ flags, defaults to RADIOLIB_SX126X_IRQ_RX_DEFAULT.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RADIOLIB_SX126X_IRQ_RX_DONE.
\param irqFlags Sets the IRQ flags, defaults to RX done, RX timeout, CRC error and header error.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RX done.
\returns \ref status_codes
*/
int16_t startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod, uint16_t irqFlags = RADIOLIB_SX126X_IRQ_RX_DEFAULT, uint16_t irqMask = RADIOLIB_SX126X_IRQ_RX_DONE);
int16_t startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK);
/*!
\brief Calls \ref startReceiveDutyCycle with rxPeriod and sleepPeriod set so the unit shouldn't miss any messages.
@ -685,17 +685,11 @@ class SX126x: public PhysicalLayer {
According to Semtech, receiver requires 8 symbols to reliably latch a preamble.
This makes this method redundant when transmitter preamble length is less than 17 (2*minSymbols + 1).
\param irqFlags Sets the IRQ flags, defaults to RADIOLIB_SX126X_IRQ_RX_DEFAULT.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RADIOLIB_SX126X_IRQ_RX_DONE.
\param irqFlags Sets the IRQ flags, defaults to RX done, RX timeout, CRC error and header error.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RX done.
\returns \ref status_codes
*/
int16_t startReceiveDutyCycleAuto(uint16_t senderPreambleLength = 0, uint16_t minSymbols = 8, uint16_t irqFlags = RADIOLIB_SX126X_IRQ_RX_DEFAULT, uint16_t irqMask = RADIOLIB_SX126X_IRQ_RX_DONE);
/*!
\brief Reads the current IRQ status.
\returns IRQ status bits
*/
uint16_t getIrqStatus();
int16_t startReceiveDutyCycleAuto(uint16_t senderPreambleLength = 0, uint16_t minSymbols = 8, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK);
/*!
\brief Reads data received after calling startReceive method. When the packet length is not known in advance,
@ -717,12 +711,10 @@ class SX126x: public PhysicalLayer {
/*!
\brief Interrupt-driven channel activity detection method. DIO1 will be activated
when LoRa preamble is detected, or upon timeout.
\param symbolNum Number of symbols for CAD detection.
\param detPeak Peak value for CAD detection.
\param detMin Minimum value for CAD detection.
\param config CAD configuration structure.
\returns \ref status_codes
*/
int16_t startChannelScan(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin);
int16_t startChannelScan(const ChannelScanConfig_t &config) override;
/*!
\brief Read the channel scan result
@ -989,18 +981,24 @@ class SX126x: public PhysicalLayer {
RadioLibTime_t calculateRxTimeout(RadioLibTime_t timeoutUs) override;
/*!
\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
\brief Read currently active IRQ flags.
\returns IRQ flags.
*/
int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) override;
uint32_t getIrqFlags() override;
/*!
\brief Check whether a specific IRQ bit is set (e.g. RxTimeout, CadDone).
\returns Whether requested IRQ is set.
\brief Set interrupt on DIO1 to be sent on a specific IRQ bit (e.g. RxTimeout, CadDone).
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
int16_t checkIrq(uint8_t irq) override;
int16_t setIrqFlags(uint32_t irq) override;
/*!
\brief Clear interrupt on a specific IRQ bit (e.g. RxTimeout, CadDone).
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
int16_t clearIrqFlags(uint32_t irq) override;
/*!
\brief Set implicit header mode for future reception/transmission.
@ -1160,7 +1158,7 @@ class SX126x: public PhysicalLayer {
int16_t setFs();
int16_t setTx(uint32_t timeout = 0);
int16_t setRx(uint32_t timeout);
int16_t setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin);
int16_t setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin, uint8_t exitMode, RadioLibTime_t timeout);
int16_t writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes);
int16_t readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes);
int16_t writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
@ -1222,7 +1220,7 @@ class SX126x: public PhysicalLayer {
int16_t config(uint8_t modem);
bool findChip(const char* verStr);
int16_t startReceiveCommon(uint32_t timeout = RADIOLIB_SX126X_RX_TIMEOUT_INF, uint16_t irqFlags = RADIOLIB_SX126X_IRQ_RX_DEFAULT, uint16_t irqMask = RADIOLIB_SX126X_IRQ_RX_DONE);
int16_t startReceiveCommon(uint32_t timeout = RADIOLIB_SX126X_RX_TIMEOUT_INF, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK);
int16_t setPacketMode(uint8_t mode, uint8_t len);
int16_t setHeaderType(uint8_t hdrType, size_t len = 0xFF);
int16_t directMode();

Wyświetl plik

@ -12,6 +12,18 @@ int16_t SX127x::begin(uint8_t* chipVersions, uint8_t numVersions, uint8_t syncWo
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
// set IRQ mapping - it is different for LoRa and FSK mode
this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_TX_DONE;
this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_DONE;
this->irqMap[RADIOLIB_IRQ_PREAMBLE_DETECTED] = RADIOLIB_IRQ_NOT_SUPPORTED;
this->irqMap[RADIOLIB_IRQ_SYNC_WORD_VALID] = RADIOLIB_IRQ_NOT_SUPPORTED;
this->irqMap[RADIOLIB_IRQ_HEADER_VALID] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_VALID_HEADER;
this->irqMap[RADIOLIB_IRQ_HEADER_ERR] = RADIOLIB_IRQ_NOT_SUPPORTED;
this->irqMap[RADIOLIB_IRQ_CRC_ERR] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR;
this->irqMap[RADIOLIB_IRQ_CAD_DONE] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DONE;
this->irqMap[RADIOLIB_IRQ_CAD_DETECTED] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DETECTED;
this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_TIMEOUT;
// try to find the SX127x chip
if(!SX127x::findChip(chipVersions, numVersions)) {
RADIOLIB_DEBUG_BASIC_PRINTLN("No SX127x found!");
@ -63,6 +75,18 @@ int16_t SX127x::beginFSK(uint8_t* chipVersions, uint8_t numVersions, float freqD
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
// set IRQ mapping - it is different for LoRa and FSK mode
this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_SX127X_FLAG_PACKET_SENT << 8;
this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_SX127X_FLAG_PAYLOAD_READY << 8;
this->irqMap[RADIOLIB_IRQ_PREAMBLE_DETECTED] = RADIOLIB_SX127X_FLAG_PREAMBLE_DETECT << 0;
this->irqMap[RADIOLIB_IRQ_SYNC_WORD_VALID] = RADIOLIB_SX127X_FLAG_SYNC_ADDRESS_MATCH << 0;
this->irqMap[RADIOLIB_IRQ_HEADER_VALID] = RADIOLIB_IRQ_NOT_SUPPORTED;
this->irqMap[RADIOLIB_IRQ_HEADER_ERR] = RADIOLIB_IRQ_NOT_SUPPORTED;
this->irqMap[RADIOLIB_IRQ_CRC_ERR] = RADIOLIB_IRQ_NOT_SUPPORTED;
this->irqMap[RADIOLIB_IRQ_CAD_DONE] = RADIOLIB_IRQ_NOT_SUPPORTED;
this->irqMap[RADIOLIB_IRQ_CAD_DETECTED] = RADIOLIB_IRQ_NOT_SUPPORTED;
this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_SX127X_FLAG_TIMEOUT << 0;
// try to find the SX127x chip
if(!SX127x::findChip(chipVersions, numVersions)) {
RADIOLIB_DEBUG_BASIC_PRINTLN("No SX127x found!");
@ -193,7 +217,7 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
// set mode to receive
state = startReceive(len, RADIOLIB_SX127X_RXSINGLE);
state = startReceive(100, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, len);
RADIOLIB_ASSERT(state);
// if no DIO1 is provided, use software timeout (100 LoRa symbols, same as hardware timeout)
@ -211,13 +235,13 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
if(this->mod->getGpio() == RADIOLIB_NC) {
// no GPIO pin provided, use software timeout
if(this->mod->hal->millis() - start > timeout) {
clearIRQFlags();
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
return(RADIOLIB_ERR_RX_TIMEOUT);
}
} else {
// GPIO provided, use that
if(this->mod->hal->digitalRead(this->mod->getGpio())) {
clearIRQFlags();
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
return(RADIOLIB_ERR_RX_TIMEOUT);
}
}
@ -229,7 +253,7 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
RadioLibTime_t timeout = (getTimeOnAir(len) * 5) / 1000;
// set mode to receive
state = startReceive(len, RADIOLIB_SX127X_RX);
state = startReceive(0, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, len);
RADIOLIB_ASSERT(state);
// wait for packet reception or timeout
@ -237,7 +261,7 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
this->mod->hal->yield();
if(this->mod->hal->millis() - start > timeout) {
clearIRQFlags();
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
return(RADIOLIB_ERR_RX_TIMEOUT);
}
}
@ -362,21 +386,35 @@ int16_t SX127x::packetMode() {
}
int16_t SX127x::startReceive() {
return(this->startReceive(0, RADIOLIB_SX127X_RXCONTINUOUS));
return(this->startReceive(0, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
}
int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
int16_t SX127x::startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
uint8_t mode = RADIOLIB_SX127X_RXCONTINUOUS;
// set mode to standby
int16_t state = setMode(RADIOLIB_SX127X_STANDBY);
RADIOLIB_ASSERT(state);
// set DIO pin mapping
state = this->setIrqFlags(getIrqMapped(irqFlags & irqMask));
RADIOLIB_ASSERT(state);
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
// set DIO pin mapping
if(timeout != 0) {
// for non-zero timeout value, change mode to Rx single and set the timeout
mode = RADIOLIB_SX127X_RXSINGLE;
uint8_t msb_sym = (timeout > 0x3FF) ? 0x3 : (uint8_t)(timeout >> 8);
uint8_t lsb_sym = (timeout > 0x3FF) ? 0xFF : (uint8_t)(timeout & 0xFF);
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, msb_sym, 1, 0);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_SYMB_TIMEOUT_LSB, lsb_sym);
RADIOLIB_ASSERT(state);
}
// in FHSS mode, enable channel change interrupt
if(this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_HOP_PERIOD) > RADIOLIB_SX127X_HOP_PERIOD_OFF) {
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_RX_DONE | RADIOLIB_SX127X_DIO1_LORA_FHSS_CHANGE_CHANNEL, 7, 4);
} else {
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_RX_DONE | RADIOLIB_SX127X_DIO1_LORA_RX_TIMEOUT, 7, 4);
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO1_LORA_FHSS_CHANGE_CHANNEL, 5, 4);
}
// set expected packet length for SF6
@ -389,7 +427,7 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
RADIOLIB_ERRATA_SX127X(true);
// clear interrupt flags
clearIRQFlags();
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set FIFO pointers
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_RX_BASE_ADDR, RADIOLIB_SX127X_FIFO_RX_BASE_ADDR_MAX);
@ -397,19 +435,11 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
RADIOLIB_ASSERT(state);
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
// set DIO pin mapping
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_PACK_PAYLOAD_READY, 7, 6);
RADIOLIB_ASSERT(state);
// clear interrupt flags
clearIRQFlags();
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// FSK modem does not distinguish between Rx single and continuous
if(mode == RADIOLIB_SX127X_RXCONTINUOUS) {
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_RX);
return(setMode(RADIOLIB_SX127X_RX));
}
mode = RADIOLIB_SX127X_RX;
}
// set RF switch (if present)
@ -419,22 +449,6 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
return(setMode(mode));
}
int16_t SX127x::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
(void)irqFlags;
(void)irqMask;
uint8_t mode = RADIOLIB_SX127X_RXCONTINUOUS;
if(timeout != 0) {
// for non-zero timeout value, change mode to Rx single and set the timeout
mode = RADIOLIB_SX127X_RXSINGLE;
uint8_t msb_sym = (timeout > 0x3FF) ? 0x3 : (uint8_t)(timeout >> 8);
uint8_t lsb_sym = (timeout > 0x3FF) ? 0xFF : (uint8_t)(timeout & 0xFF);
int16_t state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, msb_sym, 1, 0);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_SYMB_TIMEOUT_LSB, lsb_sym);
RADIOLIB_ASSERT(state);
}
return(startReceive((uint8_t)len, mode));
}
void SX127x::setDio0Action(void (*func)(void), uint32_t dir) {
this->mod->hal->attachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()), func, dir);
}
@ -571,7 +585,7 @@ int16_t SX127x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
RADIOLIB_ERRATA_SX127X(false);
// clear interrupt flags
clearIRQFlags();
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set packet length
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
@ -582,7 +596,7 @@ int16_t SX127x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
// clear interrupt flags
clearIRQFlags();
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set DIO mapping
if(len > RADIOLIB_SX127X_MAX_PACKET_LENGTH_FSK) {
@ -628,7 +642,7 @@ int16_t SX127x::finishTransmit() {
mod->hal->delayMicroseconds(1000000/1200);
// clear interrupt flags
clearIRQFlags();
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set mode to standby to disable transmitter/RF switch
return(standby());
@ -686,7 +700,7 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
this->packetLengthQueried = false;
// clear interrupt flags
clearIRQFlags();
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
return(state);
}
@ -702,7 +716,7 @@ int16_t SX127x::startChannelScan() {
RADIOLIB_ASSERT(state);
// clear interrupt flags
clearIRQFlags();
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set DIO pin mapping
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_CAD_DONE | RADIOLIB_SX127X_DIO1_LORA_CAD_DETECTED, 7, 4);
@ -1295,36 +1309,66 @@ RadioLibTime_t SX127x::calculateRxTimeout(RadioLibTime_t timeoutUs) {
return(numSymbols);
}
int16_t SX127x::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) {
// IRQ flags/masks are inverted to what seems logical for SX127x (0 being activated, 1 being deactivated)
irqFlags = RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_DEFAULT;
irqMask = RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_DONE & RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_TIMEOUT;
return(RADIOLIB_ERR_NONE);
uint32_t SX127x::getIrqFlags() {
return((uint32_t)this->getIRQFlags());
}
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);
int16_t SX127x::setIrqFlags(uint32_t irq) {
// this is a bit convoluted, but unfortunately SX127x IRQ flags are not used to enable/disable that IRQ ...
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
switch(irq) {
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_TX_DONE):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_PACK_PACKET_SENT, 7, 6));
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_DONE):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_RX_DONE, 7, 6));
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_VALID_HEADER):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO3_LORA_VALID_HEADER, 1, 0));
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO3_LORA_PAYLOAD_CRC_ERROR, 1, 0));
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DONE):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_CAD_DONE, 7, 6));
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DETECTED):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO1_LORA_CAD_DETECTED, 5, 4));
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_TIMEOUT):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO1_LORA_RX_TIMEOUT, 5, 4));
}
return(RADIOLIB_ERR_UNSUPPORTED);
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
switch(irq) {
case(RADIOLIB_SX127X_FLAG_PACKET_SENT << 8):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_PACK_PACKET_SENT, 7, 6));
case(RADIOLIB_SX127X_FLAG_PAYLOAD_READY << 8):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_PACK_PAYLOAD_READY, 7, 6));
case(RADIOLIB_SX127X_FLAG_PREAMBLE_DETECT << 0):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_2, RADIOLIB_SX127X_DIO4_PACK_RSSI_PREAMBLE_DETECT, 7, 6));
case(RADIOLIB_SX127X_FLAG_SYNC_ADDRESS_MATCH << 0):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO2_PACK_SYNC_ADDRESS, 3, 2));
case(RADIOLIB_SX127X_FLAG_TIMEOUT << 0):
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO2_PACK_TIMEOUT, 3, 2));
}
return(RADIOLIB_ERR_UNSUPPORTED);
}
return(RADIOLIB_ERR_UNSUPPORTED);
}
int16_t SX127x::clearIrqFlags(uint32_t irq) {
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS, (uint8_t)irq);
return(RADIOLIB_ERR_NONE);
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS_1, (uint8_t)irq);
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS_2, (uint8_t)(irq >> 8));
return(RADIOLIB_ERR_NONE);
}
return(RADIOLIB_ERR_UNKNOWN);
}
int16_t SX127x::setCrcFiltering(bool enable) {
this->crcOn = enable;
@ -1619,16 +1663,6 @@ int16_t SX127x::setActiveModem(uint8_t modem) {
return(state);
}
void SX127x::clearIRQFlags() {
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS, 0b11111111);
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS_1, 0b11111111);
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS_2, 0b11111111);
}
}
void SX127x::clearFIFO(size_t count) {
while(count) {
this->mod->SPIreadRegister(RADIOLIB_SX127X_REG_FIFO);

Wyświetl plik

@ -160,7 +160,6 @@
#define RADIOLIB_SX127X_MASK_IRQ_FLAG_CAD_DONE 0b11111011 // 2 2 CAD complete
#define RADIOLIB_SX127X_MASK_IRQ_FLAG_FHSS_CHANGE_CHANNEL 0b11111101 // 1 1 FHSS change channel
#define RADIOLIB_SX127X_MASK_IRQ_FLAG_CAD_DETECTED 0b11111110 // 0 0 valid LoRa signal detected during CAD operation
#define RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_DEFAULT 0b00011111 // 7 0 default for Rx (RX_TIMEOUT, RX_DONE, CRC_ERR)
// RADIOLIB_SX127X_REG_FIFO_TX_BASE_ADDR
#define RADIOLIB_SX127X_FIFO_TX_BASE_ADDR_MAX 0b00000000 // 7 0 allocate the entire FIFO buffer for TX only
@ -500,6 +499,7 @@
#define RADIOLIB_SX127X_FLAG_PAYLOAD_READY 0b00000100 // 2 2 packet was successfully received
#define RADIOLIB_SX127X_FLAG_CRC_OK 0b00000010 // 1 1 CRC check passed
#define RADIOLIB_SX127X_FLAG_LOW_BAT 0b00000001 // 0 0 battery voltage dropped below threshold
#define RADIOLIB_SX127X_FLAGS_ALL 0xFFFF
// RADIOLIB_SX127X_REG_DIO_MAPPING_1
#define RADIOLIB_SX127X_DIO0_LORA_RX_DONE 0b00000000 // 7 6
@ -812,27 +812,18 @@ class SX127x: public PhysicalLayer {
*/
int16_t startReceive() override;
/*!
\brief Interrupt-driven receive method. DIO0 will be activated when full valid packet is received.
\param len Expected length of packet to be received, or 0 when unused.
Defaults to 0, non-zero required for LoRa spreading factor 6.
\param mode Receive mode to be used. Defaults to RxContinuous.
\returns \ref status_codes
*/
int16_t startReceive(uint8_t len, uint8_t mode = RADIOLIB_SX127X_RXCONTINUOUS);
/*!
\brief Interrupt-driven receive method, implemented for compatibility with PhysicalLayer.
\param timeout Receive mode type and/or raw timeout value in symbols.
When set to 0, the timeout will be infinite and the device will remain
in Rx mode until explicitly commanded to stop (Rx continuous mode).
When non-zero (maximum 1023), the device will be set to Rx single mode and timeout will be set.
\param irqFlags Ignored.
\param irqMask Ignored.
\param irqFlags Sets the IRQ flags, defaults to RX done, RX timeout, CRC error and header error.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RX done.
\param len Expected length of packet to be received. Required for LoRa spreading factor 6.
\returns \ref status_codes
*/
int16_t startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) override;
int16_t startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK, size_t len = 0) override;
/*!
\brief Reads data that was received after calling startReceive method. When the packet length is not known in advance,
@ -1065,18 +1056,24 @@ class SX127x: public PhysicalLayer {
RadioLibTime_t calculateRxTimeout(RadioLibTime_t timeoutUs) override;
/*!
\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
\brief Read currently active IRQ flags.
\returns IRQ flags.
*/
int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) override;
uint32_t getIrqFlags() override;
/*!
\brief Check whether a specific IRQ bit is set (e.g. RxTimeout, CadDone).
\returns Whether requested IRQ is set.
\brief Set interrupt on DIO1 to be sent on a specific IRQ bit (e.g. RxTimeout, CadDone).
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
int16_t checkIrq(uint8_t irq) override;
int16_t setIrqFlags(uint32_t irq) override;
/*!
\brief Clear interrupt on a specific IRQ bit (e.g. RxTimeout, CadDone).
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
int16_t clearIrqFlags(uint32_t irq) override;
/*!
\brief Enable CRC filtering and generation.
@ -1257,7 +1254,6 @@ class SX127x: public PhysicalLayer {
bool findChip(const uint8_t* vers, uint8_t num);
int16_t setMode(uint8_t mode);
int16_t setActiveModem(uint8_t modem);
void clearIRQFlags();
void clearFIFO(size_t count); // used mostly to clear remaining bytes in FIFO after a packet read
/*!

Wyświetl plik

@ -4,6 +4,16 @@
SX128x::SX128x(Module* mod) : PhysicalLayer(RADIOLIB_SX128X_FREQUENCY_STEP_SIZE, RADIOLIB_SX128X_MAX_PACKET_LENGTH) {
this->mod = mod;
this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_SX128X_IRQ_TX_DONE;
this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_SX128X_IRQ_RX_DONE;
this->irqMap[RADIOLIB_IRQ_PREAMBLE_DETECTED] = RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED;
this->irqMap[RADIOLIB_IRQ_SYNC_WORD_VALID] = RADIOLIB_SX128X_IRQ_SYNC_WORD_VALID;
this->irqMap[RADIOLIB_IRQ_HEADER_VALID] = RADIOLIB_SX128X_IRQ_HEADER_VALID;
this->irqMap[RADIOLIB_IRQ_HEADER_ERR] = RADIOLIB_SX128X_IRQ_HEADER_ERROR;
this->irqMap[RADIOLIB_IRQ_CRC_ERR] = RADIOLIB_SX128X_IRQ_CRC_ERROR;
this->irqMap[RADIOLIB_IRQ_CAD_DONE] = RADIOLIB_SX128X_IRQ_CAD_DONE;
this->irqMap[RADIOLIB_IRQ_CAD_DETECTED] = RADIOLIB_SX128X_IRQ_CAD_DETECTED;
this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT;
}
int16_t SX128x::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t pwr, uint16_t preambleLength) {
@ -411,8 +421,23 @@ int16_t SX128x::receiveDirect() {
}
int16_t SX128x::scanChannel() {
ChannelScanConfig_t config = {
.cad = {
.symNum = RADIOLIB_SX128X_CAD_PARAM_DEFAULT,
.detPeak = 0,
.detMin = 0,
.exitMode = 0,
.timeout = 0,
.irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
.irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
},
};
return(this->scanChannel(config));
}
int16_t SX128x::scanChannel(ChannelScanConfig_t config) {
// set mode to CAD
int16_t state = startChannelScan();
int16_t state = startChannelScan(config);
RADIOLIB_ASSERT(state);
// wait for channel activity detected or timeout
@ -558,10 +583,10 @@ int16_t SX128x::finishTransmit() {
}
int16_t SX128x::startReceive() {
return(this->startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT, RADIOLIB_SX128X_IRQ_RX_DONE, 0));
return(this->startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
}
int16_t SX128x::startReceive(uint16_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
int16_t SX128x::startReceive(uint16_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
(void)len;
// check active modem
@ -571,10 +596,10 @@ int16_t SX128x::startReceive(uint16_t timeout, uint32_t irqFlags, uint32_t irqMa
// set DIO mapping
if(timeout != RADIOLIB_SX128X_RX_TIMEOUT_INF) {
irqMask |= RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT;
irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
int16_t state = setDioIrqParams(irqFlags, irqMask);
int16_t state = setDioIrqParams(getIrqMapped(irqFlags), getIrqMapped(irqMask));
RADIOLIB_ASSERT(state);
// set buffer pointers
@ -638,36 +663,34 @@ 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);
uint32_t SX128x::getIrqFlags() {
return((uint32_t)this->getIrqStatus());
}
int16_t SX128x::setIrqFlags(uint32_t irq) {
return(this->setDioIrqParams(irq, irq));
}
int16_t SX128x::clearIrqFlags(uint32_t irq) {
return(this->clearIrqStatus(irq));
}
int16_t SX128x::startChannelScan() {
ChannelScanConfig_t config = {
.cad = {
.symNum = RADIOLIB_SX128X_CAD_PARAM_DEFAULT,
.detPeak = 0,
.detMin = 0,
.exitMode = 0,
.timeout = 0,
.irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
.irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
},
};
return(this->startChannelScan(config));
}
int16_t SX128x::startChannelScan(const ChannelScanConfig_t &config) {
// check active modem
if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) {
return(RADIOLIB_ERR_WRONG_MODEM);
@ -678,7 +701,7 @@ int16_t SX128x::startChannelScan() {
RADIOLIB_ASSERT(state);
// set DIO pin mapping
state = setDioIrqParams(RADIOLIB_SX128X_IRQ_CAD_DETECTED | RADIOLIB_SX128X_IRQ_CAD_DONE, RADIOLIB_SX128X_IRQ_CAD_DETECTED | RADIOLIB_SX128X_IRQ_CAD_DONE);
state = setDioIrqParams(getIrqMapped(config.cad.irqFlags), getIrqMapped(config.cad.irqMask));
RADIOLIB_ASSERT(state);
// clear interrupt flags
@ -689,7 +712,7 @@ int16_t SX128x::startChannelScan() {
this->mod->setRfSwitchState(Module::MODE_RX);
// set mode to CAD
return(setCad());
return(setCad(config.cad.symNum));
}
int16_t SX128x::getChannelScanResult() {
@ -1464,7 +1487,12 @@ int16_t SX128x::setRx(uint16_t periodBaseCount, uint8_t periodBase) {
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_RX, data, 3));
}
int16_t SX128x::setCad() {
int16_t SX128x::setCad(uint8_t symbolNum) {
// configure parameters
int16_t state = this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_CAD_PARAMS, &symbolNum, 1);
RADIOLIB_ASSERT(state);
// start CAD
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_CAD, NULL, 0));
}

Wyświetl plik

@ -186,6 +186,7 @@
#define RADIOLIB_SX128X_CAD_ON_4_SYMB 0x40 // 7 0 4
#define RADIOLIB_SX128X_CAD_ON_8_SYMB 0x60 // 7 0 8
#define RADIOLIB_SX128X_CAD_ON_16_SYMB 0x80 // 7 0 16
#define RADIOLIB_SX128X_CAD_PARAM_DEFAULT RADIOLIB_SX128X_CAD_ON_8_SYMB
//RADIOLIB_SX128X_CMD_SET_MODULATION_PARAMS
#define RADIOLIB_SX128X_BLE_GFSK_BR_2_000_BW_2_4 0x04 // 7 0 GFSK/BLE bit rate and bandwidth setting: 2.0 Mbps 2.4 MHz
@ -327,7 +328,6 @@
#define RADIOLIB_SX128X_IRQ_SYNC_WORD_VALID 0x0004 // 2 2 sync word valid
#define RADIOLIB_SX128X_IRQ_RX_DONE 0x0002 // 1 1 Rx done
#define RADIOLIB_SX128X_IRQ_TX_DONE 0x0001 // 0 0 Tx done
#define RADIOLIB_SX128X_IRQ_RX_DEFAULT 0x4062 // 15 0 default for Rx (RX_DONE, RX_TX_TIMEOUT, CRC_ERROR and HEADER_ERROR)
#define RADIOLIB_SX128X_IRQ_NONE 0x0000 // 15 0 none
#define RADIOLIB_SX128X_IRQ_ALL 0xFFFF // 15 0 all
@ -457,6 +457,13 @@ class SX128x: public PhysicalLayer {
*/
int16_t scanChannel() override;
/*!
\brief Performs scan for LoRa transmission in the current channel. Detects both preamble and payload.
\param config CAD configuration structure.
\returns \ref status_codes
*/
int16_t scanChannel(ChannelScanConfig_t config) override;
/*!
\brief Sets the module to sleep mode. To wake the device up, call standby().
Overload for PhysicalLayer compatibility.
@ -553,12 +560,12 @@ class SX128x: public PhysicalLayer {
set to RADIOLIB_SX128X_RX_TIMEOUT_NONE for no timeout (Rx single mode).
If timeout other than infinite is set, signal will be generated on DIO1.
\param irqFlags Sets the IRQ flags, defaults to RADIOLIB_SX128X_IRQ_RX_DEFAULT.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RADIOLIB_SX128X_IRQ_RX_DONE.
\param irqFlags Sets the IRQ flags, defaults to RX done, RX timeout, CRC error and header error.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RX done.
\param len Only for PhysicalLayer compatibility, not used.
\returns \ref status_codes
*/
int16_t startReceive(uint16_t timeout, uint32_t irqFlags = RADIOLIB_SX128X_IRQ_RX_DEFAULT, uint32_t irqMask = RADIOLIB_SX128X_IRQ_RX_DONE, size_t len = 0);
int16_t startReceive(uint16_t timeout, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK, size_t len = 0);
/*!
\brief Reads the current IRQ status.
@ -577,18 +584,40 @@ 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.
\brief Read currently active IRQ flags.
\returns IRQ flags.
*/
int16_t checkIrq(uint8_t irq) override;
uint32_t getIrqFlags() override;
/*!
\brief Set interrupt on DIO1 to be sent on a specific IRQ bit (e.g. RxTimeout, CadDone).
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
int16_t setIrqFlags(uint32_t irq) override;
/*!
\brief Clear interrupt on a specific IRQ bit (e.g. RxTimeout, CadDone).
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
int16_t clearIrqFlags(uint32_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.
when LoRa preamble is detected, or upon timeout.
\returns \ref status_codes
*/
int16_t startChannelScan() override;
/*!
\brief Interrupt-driven channel activity detection method. DIO1 will be activated
when LoRa preamble is detected, or upon timeout.
\param config CAD configuration structure.
\returns \ref status_codes
*/
int16_t startChannelScan(const ChannelScanConfig_t &config) override;
/*!
\brief Read the channel scan result
\returns \ref status_codes
@ -837,7 +866,7 @@ class SX128x: public PhysicalLayer {
int16_t readBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
int16_t setTx(uint16_t periodBaseCount = RADIOLIB_SX128X_TX_TIMEOUT_NONE, uint8_t periodBase = RADIOLIB_SX128X_PERIOD_BASE_15_625_US);
int16_t setRx(uint16_t periodBaseCount, uint8_t periodBase = RADIOLIB_SX128X_PERIOD_BASE_15_625_US);
int16_t setCad();
int16_t setCad(uint8_t symbolNum);
uint8_t getPacketType();
int16_t setRfFrequency(uint32_t frf);
int16_t setTxParams(uint8_t pwr, uint8_t rampTime = RADIOLIB_SX128X_PA_RAMP_10_US);

Wyświetl plik

@ -1190,9 +1190,8 @@ int16_t LoRaWANNode::downlinkCommon() {
RADIOLIB_ASSERT(state);
// create the masks that are required for receiving downlinks
uint32_t irqFlags = 0;
uint32_t irqMask = 0;
this->phyLayer->irqRxDoneRxTimeout(irqFlags, irqMask);
RadioLibIrqFlags_t irqFlags = (1UL << RADIOLIB_IRQ_RX_DONE) | (1UL << RADIOLIB_IRQ_TIMEOUT);
RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK;
this->phyLayer->setPacketReceivedAction(LoRaWANNodeOnDownlinkAction);

Wyświetl plik

@ -132,7 +132,7 @@ int16_t PhysicalLayer::startReceive() {
return(RADIOLIB_ERR_UNSUPPORTED);
}
int16_t PhysicalLayer::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
int16_t PhysicalLayer::startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
(void)timeout;
(void)irqFlags;
(void)irqMask;
@ -310,13 +310,44 @@ RadioLibTime_t PhysicalLayer::calculateRxTimeout(RadioLibTime_t timeoutUs) {
return(0);
}
int16_t PhysicalLayer::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) {
(void)irqFlags;
(void)irqMask;
uint32_t PhysicalLayer::getIrqMapped(RadioLibIrqFlags_t irq) {
// iterate over all set bits and build the module-specific flags
uint32_t irqRaw = 0;
for(uint8_t i = 0; i < 8*(sizeof(RadioLibIrqFlags_t)); i++) {
if((irq & (uint32_t)(1UL << i)) && (this->irqMap[i] != RADIOLIB_IRQ_NOT_SUPPORTED)) {
irqRaw |= this->irqMap[i];
}
}
return(irqRaw);
}
int16_t PhysicalLayer::checkIrq(RadioLibIrqType_t irq) {
if((irq > RADIOLIB_IRQ_TIMEOUT) || (this->irqMap[irq] == RADIOLIB_IRQ_NOT_SUPPORTED)) {
return(RADIOLIB_ERR_UNSUPPORTED);
}
return(getIrqFlags() & this->irqMap[irq]);
}
int16_t PhysicalLayer::setIrq(RadioLibIrqFlags_t irq) {
return(setIrqFlags(getIrqMapped(irq)));
}
int16_t PhysicalLayer::clearIrq(RadioLibIrqFlags_t irq) {
return(clearIrqFlags(getIrqMapped(irq)));
}
uint32_t PhysicalLayer::getIrqFlags() {
return(RADIOLIB_ERR_UNSUPPORTED);
}
int16_t PhysicalLayer::checkIrq(uint8_t irq) {
int16_t PhysicalLayer::setIrqFlags(uint32_t irq) {
(void)irq;
return(RADIOLIB_ERR_UNSUPPORTED);
}
int16_t PhysicalLayer::clearIrqFlags(uint32_t irq) {
(void)irq;
return(RADIOLIB_ERR_UNSUPPORTED);
}
@ -325,6 +356,11 @@ int16_t PhysicalLayer::startChannelScan() {
return(RADIOLIB_ERR_UNSUPPORTED);
}
int16_t PhysicalLayer::startChannelScan(const ChannelScanConfig_t &config) {
(void)config;
return(RADIOLIB_ERR_UNSUPPORTED);
}
int16_t PhysicalLayer::getChannelScanResult() {
return(RADIOLIB_ERR_UNSUPPORTED);
}
@ -333,6 +369,11 @@ int16_t PhysicalLayer::scanChannel() {
return(RADIOLIB_ERR_UNSUPPORTED);
}
int16_t PhysicalLayer::scanChannel(ChannelScanConfig_t config) {
(void)config;
return(RADIOLIB_ERR_UNSUPPORTED);
}
int32_t PhysicalLayer::random(int32_t max) {
if(max == 0) {
return(0);

Wyświetl plik

@ -4,17 +4,26 @@
#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
// common IRQ values - the IRQ flags in RadioLibIrqFlags_t arguments are offset by this value
enum RadioLibIrqType_t {
RADIOLIB_IRQ_TX_DONE = 0x00,
RADIOLIB_IRQ_RX_DONE = 0x01,
RADIOLIB_IRQ_PREAMBLE_DETECTED = 0x02,
RADIOLIB_IRQ_SYNC_WORD_VALID = 0x03,
RADIOLIB_IRQ_HEADER_VALID = 0x04,
RADIOLIB_IRQ_HEADER_ERR = 0x05,
RADIOLIB_IRQ_CRC_ERR = 0x06,
RADIOLIB_IRQ_CAD_DONE = 0x07,
RADIOLIB_IRQ_CAD_DETECTED = 0x08,
RADIOLIB_IRQ_TIMEOUT = 0x09,
RADIOLIB_IRQ_NOT_SUPPORTED = 0x1F, // this must be the last value, intentionally set to 31
};
// some commonly used default values - defined here to ensure all modules have the same default behavior
#define RADIOLIB_IRQ_RX_DEFAULT_FLAGS ((1UL << RADIOLIB_IRQ_RX_DONE) | (1UL << RADIOLIB_IRQ_TIMEOUT) | (1UL << RADIOLIB_IRQ_CRC_ERR) | (1UL << RADIOLIB_IRQ_HEADER_ERR))
#define RADIOLIB_IRQ_RX_DEFAULT_MASK ((1UL << RADIOLIB_IRQ_RX_DONE))
#define RADIOLIB_IRQ_CAD_DEFAULT_FLAGS ((1UL << RADIOLIB_IRQ_CAD_DETECTED) | (1UL << RADIOLIB_IRQ_CAD_DONE))
#define RADIOLIB_IRQ_CAD_DEFAULT_MASK ((1UL << RADIOLIB_IRQ_CAD_DETECTED) | (1UL << RADIOLIB_IRQ_CAD_DONE))
/*!
\struct LoRaRate_t
@ -39,7 +48,7 @@ struct FSKRate_t {
/*! \brief FSK bit rate in kbps */
float bitRate;
/*! \brief FS frequency deviation in kHz*/
/*! \brief FSK frequency deviation in kHz */
float freqDev;
};
@ -55,6 +64,54 @@ union DataRate_t {
FSKRate_t fsk;
};
/*!
\struct CADScanConfig_t
\brief Channel scan configuration interpretation in case LoRa CAD is used
*/
struct CADScanConfig_t {
/*! \brief Number of symbols to consider signal present */
uint8_t symNum;
/*! \brief Number of peak detection symbols */
uint8_t detPeak;
/*! \brief Number of minimum detection symbols */
uint8_t detMin;
/*! \brief Exit mode after signal detection is complete - module-specific value */
uint8_t exitMode;
/*! \brief Timeout in microseconds */
RadioLibTime_t timeout;
/*! \brief Optional IRQ flags to set, bits offset by the value of RADIOLIB_IRQ_ */
RadioLibIrqFlags_t irqFlags;
/*! \brief Optional IRQ mask to set, bits offset by the value of RADIOLIB_IRQ_ */
RadioLibIrqFlags_t irqMask;
};
/*!
\struct RSSIScanConfig_t
\brief Channel scan configuration interpretation in case RSSI threshold is used
*/
struct RSSIScanConfig_t {
/*! \brief RSSI limit in dBm */
float limit;
};
/*!
\union ChannelScanConfig_t
\brief Common channel scan configuration structure
*/
union ChannelScanConfig_t {
/*! \brief Interpretation for modems that use CAD (usually LoRa modems)*/
CADScanConfig_t cad;
/*! \brief Interpretation for modems that use RSSI threshold*/
RSSIScanConfig_t rssi;
};
/*!
\class PhysicalLayer
@ -152,16 +209,16 @@ class PhysicalLayer {
\param timeout Raw timeout value. Some modules use this argument to specify operation mode
(single vs. continuous receive).
\param irqFlags Sets the IRQ flags.
\param irqMask Sets the mask of IRQ flags that will trigger the DIO pin.
\param irqMask Sets the mask of IRQ flags that will trigger the radio interrupt pin.
\param len Packet length, needed for some modules under special circumstances (e.g. LoRa implicit header mode).
\returns \ref status_codes
*/
virtual int16_t startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len);
virtual int16_t startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len);
/*!
\brief Binary receive method. Must be implemented in module class.
\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 len Packet length, needed for some modules under special circumstances (e.g. LoRa implicit header mode).
\returns \ref status_codes
*/
virtual int16_t receive(uint8_t* data, size_t len);
@ -366,18 +423,59 @@ class PhysicalLayer {
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.
\returns \ref status_codes
\brief Convert from radio-agnostic IRQ flags to radio-specific flags.
\param irq Radio-agnostic IRQ flags.
\returns Flags for a specific radio module.
*/
virtual int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask);
uint32_t getIrqMapped(RadioLibIrqFlags_t irq);
/*!
\brief Check whether a specific IRQ bit is set (e.g. RxTimeout, CadDone).
\returns Whether requested IRQ is set.
\param irq IRQ type to check, one of RADIOLIB_IRQ_*.
\returns 1 when requested IRQ is set, 0 when it is not or RADIOLIB_ERR_UNSUPPORTED if the IRQ is not supported.
*/
virtual int16_t checkIrq(uint8_t irq);
int16_t checkIrq(RadioLibIrqType_t irq);
/*!
\brief Set interrupt on specific IRQ bit(s) (e.g. RxTimeout, CadDone).
Keep in mind that not all radio modules support all RADIOLIB_IRQ_ flags!
\param irq Flags to set, multiple bits may be enabled. IRQ to enable corresponds to the bit index (RadioLibIrq_t).
For example, if bit 0 is enabled, the module will enable its RADIOLIB_IRQ_TX_DONE (if it is supported).
\returns \ref status_codes
*/
int16_t setIrq(RadioLibIrqFlags_t irq);
/*!
\brief Clear interrupt on a specific IRQ bit (e.g. RxTimeout, CadDone).
Keep in mind that not all radio modules support all RADIOLIB_IRQ_ flags!
\param irq Flags to set, multiple bits may be enabled. IRQ to enable corresponds to the bit index (RadioLibIrq_t).
For example, if bit 0 is enabled, the module will enable its RADIOLIB_IRQ_TX_DONE (if it is supported).
\returns \ref status_codes
*/
int16_t clearIrq(RadioLibIrqFlags_t irq);
/*!
\brief Read currently active IRQ flags.
Must be implemented in module class.
\returns IRQ flags.
*/
virtual uint32_t getIrqFlags();
/*!
\brief Set interrupt on DIO1 to be sent on a specific IRQ bit (e.g. RxTimeout, CadDone).
Must be implemented in module class.
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
virtual int16_t setIrqFlags(uint32_t irq);
/*!
\brief Clear interrupt on a specific IRQ bit (e.g. RxTimeout, CadDone).
Must be implemented in module class.
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
virtual int16_t clearIrqFlags(uint32_t irq);
/*!
\brief Interrupt-driven channel activity detection method. Interrupt will be activated
@ -386,6 +484,14 @@ class PhysicalLayer {
*/
virtual int16_t startChannelScan();
/*!
\brief Interrupt-driven channel activity detection method. interrupt will be activated
when packet is detected. Must be implemented in module class.
\param config Scan configuration structure. Interpretation depends on currently active modem.
\returns \ref status_codes
*/
virtual int16_t startChannelScan(const ChannelScanConfig_t &config);
/*!
\brief Read the channel scan result
\returns \ref status_codes
@ -400,6 +506,15 @@ class PhysicalLayer {
*/
virtual int16_t scanChannel();
/*!
\brief Check whether the current communication channel is free or occupied. Performs CAD for LoRa modules,
or RSSI measurement for FSK modules.
\param config Scan configuration structure. Interpretation depends on currently active modem.
\returns RADIOLIB_CHANNEL_FREE when channel is free,
RADIOLIB_PREAMBLE_DETECTEDwhen occupied or other \ref status_codes.
*/
virtual int16_t scanChannel(ChannelScanConfig_t config);
/*!
\brief Get truly random number in range 0 - max.
\param max The maximum value of the random number (non-inclusive).
@ -531,6 +646,8 @@ class PhysicalLayer {
#if !RADIOLIB_GODMODE
protected:
#endif
uint32_t irqMap[10] = { 0 };
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
void updateDirectBuffer(uint8_t bit);
#endif