[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
This commit is contained in:
parent
d9c0c4ed44
commit
bc801c7004
14 changed files with 606 additions and 350 deletions
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
/*!
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue