User-controlled timeout for blocking receive (#1592)

* [PHY] Add timeout argument to blocking receive method

* [PHY] Add finishReceive method for cleanup after Rx

* [SX126x] Implement finishReceive method

* [SX126x] Implement blocking receive timeout

* [CC1101] Implement blocking receive timeout

* [CC1101] Implement finishReceive

* [nRF24] Implement blocking receive timeout

* [nRF24] Implement finishReceive

* [RF69] Implement finishReceive

* [RF69] Implement finishReceive

* [Si443x] Implement blocking receive timeout

* [Si443x] Implement finishReceive

* [SX128x] Implement blocking receive timeout

* [SX128x] Implement finishReceive

* [LR11x0] Implement blocking receive timeout

* [LR11x0] Implement finishReceive

* [SX127x] Implement blocking receive timeout

* [SX127x] Implement finishReceive

* Add finishReceive to keywords

* [CC1101] Fix incorrect timeout reference

* [SX126x] Simplify receive timeout duration (5x ToA instead of 100 symbols)

* [LR11x0] Simplify receive timeout duration (5x ToA instead of 100 symbols)

* [SX127x] Simplify receive timeout duration (5x ToA instead of 100 symbols)

* Fix swapped order of operations in finishReceive

* [SX128x] Add explanation regarding 10x timeout value
pull/1603/head
Jan Gromeš 2025-09-10 07:07:28 +02:00 zatwierdzone przez GitHub
rodzic bbb2e4e575
commit 7fc83f732c
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
19 zmienionych plików z 303 dodań i 190 usunięć

Wyświetl plik

@ -133,6 +133,7 @@ startTransmit KEYWORD2
finishTransmit KEYWORD2
startReceive KEYWORD2
readData KEYWORD2
finishReceive KEYWORD2
startChannelScan KEYWORD2
getChannelScanResult KEYWORD2
setBandwidth KEYWORD2

Wyświetl plik

@ -58,9 +58,12 @@ int16_t CC1101::transmit(const uint8_t* data, size_t len, uint8_t addr) {
return(finishTransmit());
}
int16_t CC1101::receive(uint8_t* data, size_t len) {
int16_t CC1101::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
RadioLibTime_t timeoutInternal = timeout;
if(!timeoutInternal) {
// calculate timeout (500 ms + 400 full max-length packets at current bit rate)
RadioLibTime_t timeout = 500 + (1.0f/(this->bitRate))*(RADIOLIB_CC1101_MAX_PACKET_LENGTH*400.0f);
timeoutInternal = 500 + (1.0f/(this->bitRate))*(RADIOLIB_CC1101_MAX_PACKET_LENGTH*400.0f);
}
// start reception
int16_t state = startReceive();
@ -71,9 +74,8 @@ int16_t CC1101::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) {
standby();
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
if(this->mod->hal->millis() - start > timeoutInternal) {
(void)finishReceive();
return(RADIOLIB_ERR_RX_TIMEOUT);
}
}
@ -83,9 +85,8 @@ int16_t CC1101::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) {
standby();
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
if(this->mod->hal->millis() - start > timeoutInternal) {
(void)finishReceive();
return(RADIOLIB_ERR_RX_TIMEOUT);
}
}
@ -410,17 +411,18 @@ int16_t CC1101::readData(uint8_t* data, size_t len) {
// Flush then standby according to RXOFF_MODE (default: RADIOLIB_CC1101_RXOFF_IDLE)
if(SPIgetRegValue(RADIOLIB_CC1101_REG_MCSM1, 3, 2) == RADIOLIB_CC1101_RXOFF_IDLE) {
// set mode to standby
standby();
// flush Rx FIFO
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
finishReceive();
}
return(state);
}
int16_t CC1101::finishReceive() {
int16_t state = standby();
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
return(state);
}
int16_t CC1101::setFrequency(float freq) {
// check allowed frequency range
#if RADIOLIB_CHECK_PARAMS

Wyświetl plik

@ -597,11 +597,13 @@ class CC1101: public PhysicalLayer {
/*!
\brief Blocking binary receive method.
Overloads for string-based transmissions are implemented in PhysicalLayer.
\param data Binary data to be sent.
\param len Number of bytes to send.
\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 timeout Reception timeout in milliseconds. If set to 0,
timeout period will be calculated automatically based on the radio configuration.
\returns \ref status_codes
*/
int16_t receive(uint8_t* data, size_t len) override;
int16_t receive(uint8_t* data, size_t len, RadioLibTime_t timeout = 0) override;
/*!
\brief Sets the module to standby mode.
@ -747,6 +749,12 @@ class CC1101: public PhysicalLayer {
*/
int16_t readData(uint8_t* data, size_t len) override;
/*!
\brief Clean up after reception is done.
\returns \ref status_codes
*/
int16_t finishReceive() override;
// configuration methods
/*!

Wyświetl plik

@ -223,30 +223,23 @@ int16_t LR11x0::transmit(const uint8_t* data, size_t len, uint8_t addr) {
return(finishTransmit());
}
int16_t LR11x0::receive(uint8_t* data, size_t len) {
int16_t LR11x0::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
// set mode to standby
int16_t state = standby();
RADIOLIB_ASSERT(state);
RadioLibTime_t timeout = 0;
// calculate timeout based on the configured modem
RadioLibTime_t timeoutInternal = timeout;
if(!timeoutInternal) {
// get currently active modem
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem);
RADIOLIB_ASSERT(state);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
// calculate timeout (100 LoRa symbols, the default for SX127x series)
float symbolLength = (float)(uint32_t(1) << this->spreadingFactor) / (float)this->bandwidthKhz;
timeout = (RadioLibTime_t)(symbolLength * 100.0f);
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
if((modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) || (modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK)) {
// calculate timeout (500 % of expected time-one-air)
size_t maxLen = len;
if(len == 0) {
maxLen = 0xFF;
}
float brBps = ((float)(RADIOLIB_LR11X0_CRYSTAL_FREQ) * 1000000.0f * 32.0f) / (float)this->bitRate;
timeout = (RadioLibTime_t)(((maxLen * 8.0f) / brBps) * 1000.0f * 5.0f);
if(len == 0) { maxLen = RADIOLIB_LR11X0_MAX_PACKET_LENGTH; }
timeoutInternal = (getTimeOnAir(maxLen) * 5) / 1000;
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
// this modem cannot receive
@ -256,11 +249,12 @@ int16_t LR11x0::receive(uint8_t* data, size_t len) {
return(RADIOLIB_ERR_UNKNOWN);
}
}
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeoutInternal);
// start reception
uint32_t timeoutValue = (uint32_t)(((float)timeout * 1000.0f) / 30.52f);
uint32_t timeoutValue = (uint32_t)(((float)timeoutInternal * 1000.0f) / 30.52f);
state = startReceive(timeoutValue);
RADIOLIB_ASSERT(state);
@ -270,7 +264,7 @@ int16_t LR11x0::receive(uint8_t* data, size_t len) {
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
this->mod->hal->yield();
// safety check, the timeout should be done by the radio
if(this->mod->hal->millis() - start > timeout) {
if(this->mod->hal->millis() - start > timeoutInternal) {
softTimeout = true;
break;
}
@ -285,8 +279,7 @@ int16_t LR11x0::receive(uint8_t* data, size_t len) {
// check whether this was a timeout or not
if((getIrqStatus() & RADIOLIB_LR11X0_IRQ_TIMEOUT) || softTimeout) {
standby();
clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
(void)finishReceive();
return(RADIOLIB_ERR_RX_TIMEOUT);
}
@ -480,6 +473,15 @@ int16_t LR11x0::readData(uint8_t* data, size_t len) {
return(state);
}
int16_t LR11x0::finishReceive() {
// set mode to standby to disable RF switch
int16_t state = standby();
RADIOLIB_ASSERT(state);
// clear interrupt flags
return(clearIrqState(RADIOLIB_LR11X0_IRQ_ALL));
}
int16_t LR11x0::startChannelScan() {
ChannelScanConfig_t cfg = {
.cad = {

Wyświetl plik

@ -991,11 +991,13 @@ class LR11x0: public PhysicalLayer {
/*!
\brief Blocking binary receive method.
Overloads for string-based transmissions are implemented in PhysicalLayer.
\param data Binary data to be sent.
\param len Number of bytes to send.
\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 timeout Reception timeout in milliseconds. If set to 0,
timeout period will be calculated automatically based on the radio configuration.
\returns \ref status_codes
*/
int16_t receive(uint8_t* data, size_t len) override;
int16_t receive(uint8_t* data, size_t len, RadioLibTime_t timeout = 0) override;
/*!
\brief Starts direct mode transmission.
@ -1120,6 +1122,12 @@ class LR11x0: public PhysicalLayer {
*/
int16_t readData(uint8_t* data, size_t len) override;
/*!
\brief Clean up after reception is done.
\returns \ref status_codes
*/
int16_t finishReceive() override;
/*!
\brief Interrupt-driven channel activity detection method. IRQ1 will be activated
when LoRa preamble is detected, or upon timeout. Defaults to CAD parameter values recommended by AN1200.48.

Wyświetl plik

@ -122,9 +122,12 @@ int16_t RF69::transmit(const uint8_t* data, size_t len, uint8_t addr) {
return(finishTransmit());
}
int16_t RF69::receive(uint8_t* data, size_t len) {
int16_t RF69::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
RadioLibTime_t timeoutInternal = timeout;
if(!timeoutInternal) {
// calculate timeout (500 ms + 400 full 64-byte packets at current bit rate)
RadioLibTime_t timeout = 500 + (1.0f/(this->bitRate))*(RADIOLIB_RF69_MAX_PACKET_LENGTH*400.0f);
timeoutInternal = 500 + (1.0f/(this->bitRate))*(RADIOLIB_RF69_MAX_PACKET_LENGTH*400.0f);
}
// start reception
int16_t state = startReceive();
@ -135,9 +138,8 @@ int16_t RF69::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) {
standby();
clearIRQFlags();
if(this->mod->hal->millis() - start > timeoutInternal) {
(void)finishReceive();
return(RADIOLIB_ERR_RX_TIMEOUT);
}
}
@ -477,12 +479,20 @@ int16_t RF69::readData(uint8_t* data, size_t len) {
// clear internal flag so getPacketLength can return the new packet length
this->packetLengthQueried = false;
// clear interrupt flags
clearIRQFlags();
finishReceive();
return(RADIOLIB_ERR_NONE);
}
int16_t RF69::finishReceive() {
// set mode to standby to disable RF switch
int16_t state = standby();
// clear interrupt flags
clearIRQFlags();
return(state);
}
int16_t RF69::setOOK(bool enable) {
// set OOK and if successful, save the new setting
int16_t state = RADIOLIB_ERR_NONE;

Wyświetl plik

@ -528,11 +528,13 @@ class RF69: public PhysicalLayer {
/*!
\brief Blocking binary receive method.
Overloads for string-based transmissions are implemented in PhysicalLayer.
\param data Binary data to be sent.
\param len Number of bytes to send.
\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 timeout Reception timeout in milliseconds. If set to 0,
timeout period will be calculated automatically based on the radio configuration.
\returns \ref status_codes
*/
int16_t receive(uint8_t* data, size_t len) override;
int16_t receive(uint8_t* data, size_t len, RadioLibTime_t timeout = 0) override;
/*!
\brief Sets the module to sleep mode.
@ -727,6 +729,12 @@ class RF69: public PhysicalLayer {
*/
int16_t readData(uint8_t* data, size_t len) override;
/*!
\brief Clean up after reception is done.
\returns \ref status_codes
*/
int16_t finishReceive() override;
// configuration methods
/*!

Wyświetl plik

@ -249,38 +249,23 @@ int16_t SX126x::transmit(const uint8_t* data, size_t len, uint8_t addr) {
return(finishTransmit());
}
int16_t SX126x::receive(uint8_t* data, size_t len) {
int16_t SX126x::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
// set mode to standby
int16_t state = standby();
RADIOLIB_ASSERT(state);
RadioLibTime_t timeout = 0;
// get currently active modem
uint8_t modem = getPacketType();
if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
// calculate timeout (100 LoRa symbols, the default for SX127x series)
float symbolLength = (float)(uint32_t(1) << this->spreadingFactor) / (float)this->bandwidthKhz;
timeout = (RadioLibTime_t)(symbolLength * 100.0f);
} else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
RadioLibTime_t timeoutInternal = timeout;
if(!timeoutInternal) {
// calculate timeout (500 % of expected time-one-air)
size_t maxLen = len;
if(len == 0) {
maxLen = 0xFF;
}
float brBps = (RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0f * 32.0f) / (float)this->bitRate;
timeout = (RadioLibTime_t)(((maxLen * 8.0f) / brBps) * 1000.0f * 5.0f);
} else {
return(RADIOLIB_ERR_UNKNOWN);
if(len == 0) { maxLen = RADIOLIB_SX126X_MAX_PACKET_LENGTH; }
timeoutInternal = (getTimeOnAir(maxLen) * 5) / 1000;
}
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeoutInternal);
// start reception
uint32_t timeoutValue = (uint32_t)(((float)timeout * 1000.0f) / 15.625f);
uint32_t timeoutValue = (uint32_t)(((float)timeoutInternal * 1000.0f) / 15.625f);
state = startReceive(timeoutValue);
RADIOLIB_ASSERT(state);
@ -290,7 +275,7 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
this->mod->hal->yield();
// safety check, the timeout should be done by the radio
if(this->mod->hal->millis() - start > timeout) {
if(this->mod->hal->millis() - start > timeoutInternal) {
softTimeout = true;
break;
}
@ -302,18 +287,14 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
return(state);
}
// check whether this was a timeout or not
if((getIrqFlags() & RADIOLIB_SX126X_IRQ_TIMEOUT) || softTimeout) {
standby();
fixImplicitTimeout();
clearIrqStatus();
return(RADIOLIB_ERR_RX_TIMEOUT);
}
// fix timeout in implicit LoRa mode
if(((this->headerType == RADIOLIB_SX126X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_LORA))) {
state = fixImplicitTimeout();
// cache the IRQ flags and clean up after reception
uint32_t irqFlags = getIrqFlags();
state = finishReceive();
RADIOLIB_ASSERT(state);
// check whether this was a timeout or not
if((irqFlags & RADIOLIB_SX126X_IRQ_TIMEOUT) || softTimeout) {
return(RADIOLIB_ERR_RX_TIMEOUT);
}
// read the received data
@ -529,6 +510,20 @@ int16_t SX126x::finishTransmit() {
return(standby());
}
int16_t SX126x::finishReceive() {
// set mode to standby to disable RF switch
int16_t state = standby();
RADIOLIB_ASSERT(state);
// try to fix timeout error in implicit header mode
// check for modem type and header mode is done in fixImplicitTimeout()
state = fixImplicitTimeout();
RADIOLIB_ASSERT(state);
// clear interrupt flags
return(clearIrqStatus());
}
int16_t SX126x::startReceive() {
return(this->startReceive(RADIOLIB_SX126X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
}
@ -2200,7 +2195,8 @@ int16_t SX126x::fixImplicitTimeout() {
//check if we're in implicit LoRa mode
if(!((this->headerType == RADIOLIB_SX126X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_LORA))) {
return(RADIOLIB_ERR_WRONG_MODEM);
// not in the correct mode, nothing to do here
return(RADIOLIB_ERR_NONE);
}
// stop RTC counter

Wyświetl plik

@ -567,11 +567,13 @@ class SX126x: public PhysicalLayer {
/*!
\brief Blocking binary receive method.
Overloads for string-based transmissions are implemented in PhysicalLayer.
\param data Binary data to be sent.
\param len Number of bytes to send.
\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 timeout Reception timeout in milliseconds. If set to 0,
timeout period will be calculated automatically based on the radio configuration.
\returns \ref status_codes
*/
int16_t receive(uint8_t* data, size_t len) override;
int16_t receive(uint8_t* data, size_t len, RadioLibTime_t timeout = 0) override;
/*!
\brief Starts direct mode transmission.
@ -690,6 +692,12 @@ class SX126x: public PhysicalLayer {
*/
int16_t finishTransmit() override;
/*!
\brief Clean up after reception is done.
\returns \ref status_codes
*/
int16_t finishReceive() override;
/*!
\brief Interrupt-driven receive method with default parameters.
Implemented for compatibility with PhysicalLayer.

Wyświetl plik

@ -211,68 +211,55 @@ int16_t SX127x::transmit(const uint8_t* data, size_t len, uint8_t addr) {
return(finishTransmit());
}
int16_t SX127x::receive(uint8_t* data, size_t len) {
int16_t SX127x::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
// set mode to standby
int16_t state = setMode(RADIOLIB_SX127X_STANDBY);
RADIOLIB_ASSERT(state);
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
// set mode to receive
state = startReceive(100, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, len);
RADIOLIB_ASSERT(state);
// calculate timeout based on the configured modem
RadioLibTime_t timeoutInternal = timeout;
uint32_t timeoutValue = 0;
if(!timeoutInternal) {
// calculate timeout (500 % of expected time-one-air)
size_t maxLen = len;
if(len == 0) { maxLen = RADIOLIB_SX127X_MAX_PACKET_LENGTH; }
timeoutInternal = (getTimeOnAir(maxLen) * 5) / 1000;
// if no DIO1 is provided, use software timeout (100 LoRa symbols, same as hardware timeout)
RadioLibTime_t timeout = 0;
if(this->mod->getGpio() == RADIOLIB_NC) {
// convert to symbols
float symbolLength = (float)(uint32_t(1) << this->spreadingFactor) / (float) this->bandwidth;
timeout = (RadioLibTime_t)(symbolLength * 100.0f);
timeoutValue = (float)timeoutInternal / symbolLength;
}
// wait for packet reception or timeout
RadioLibTime_t start = this->mod->hal->millis();
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
this->mod->hal->yield();
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeoutInternal);
if(this->mod->getGpio() == RADIOLIB_NC) {
// no GPIO pin provided, use software timeout
if(this->mod->hal->millis() - start > timeout) {
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
return(RADIOLIB_ERR_RX_TIMEOUT);
}
} else {
// GPIO provided, use that
if(this->mod->hal->digitalRead(this->mod->getGpio())) {
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
return(RADIOLIB_ERR_RX_TIMEOUT);
}
}
}
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
// calculate timeout in ms (500 % of expected time-on-air)
RadioLibTime_t timeout = (getTimeOnAir(len) * 5) / 1000;
// set mode to receive
state = startReceive(0, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, len);
// start reception
state = startReceive(timeoutValue, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, len);
RADIOLIB_ASSERT(state);
// wait for packet reception or timeout
bool softTimeout = false;
RadioLibTime_t start = this->mod->hal->millis();
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
this->mod->hal->yield();
if(this->mod->hal->millis() - start > timeout) {
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// check the blocking timeout
if(this->mod->hal->millis() - start > timeoutInternal) {
softTimeout = true;
break;
}
}
// cache the IRQ flags and clean up after reception
uint16_t irqFlags = getIRQFlags();
state = finishReceive();
RADIOLIB_ASSERT(state);
// check whether this was a timeout or not
if(softTimeout || (irqFlags & this->irqMap[RADIOLIB_IRQ_TIMEOUT])) {
return(RADIOLIB_ERR_RX_TIMEOUT);
}
}
}
// read the received data
state = readData(data, len);
return(state);
return(readData(data, len));
}
int16_t SX127x::scanChannel() {
@ -583,6 +570,15 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
return(state);
}
int16_t SX127x::finishReceive() {
// set mode to standby to disable RF switch
int16_t state = standby();
RADIOLIB_ASSERT(state);
// clear interrupt flags
return(clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL));
}
int16_t SX127x::startChannelScan() {
// check active modem
if(getActiveModem() != RADIOLIB_SX127X_LORA) {

Wyświetl plik

@ -641,9 +641,11 @@ class SX127x: public PhysicalLayer {
For overloads to receive Arduino String, see PhysicalLayer::receive.
\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 timeout Reception timeout in milliseconds. If set to 0,
timeout period will be calculated automatically based on the radio configuration.
\returns \ref status_codes
*/
int16_t receive(uint8_t* data, size_t len) override;
int16_t receive(uint8_t* data, size_t len, RadioLibTime_t timeout = 0) override;
/*!
\brief Performs scan for valid %LoRa preamble in the current channel.
@ -822,6 +824,12 @@ class SX127x: public PhysicalLayer {
*/
int16_t readData(uint8_t* data, size_t len) override;
/*!
\brief Clean up after reception is done.
\returns \ref status_codes
*/
int16_t finishReceive() override;
/*!
\brief Interrupt-driven channel activity detection method. DIO0 will be activated when LoRa preamble is detected.
DIO1 will be activated if there's no preamble detected before timeout.

Wyświetl plik

@ -350,7 +350,7 @@ int16_t SX128x::transmit(const uint8_t* data, size_t len, uint8_t addr) {
return(finishTransmit());
}
int16_t SX128x::receive(uint8_t* data, size_t len) {
int16_t SX128x::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
// check active modem
uint8_t modem = getPacketType();
if(modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
@ -362,11 +362,16 @@ int16_t SX128x::receive(uint8_t* data, size_t len) {
RADIOLIB_ASSERT(state);
// calculate timeout (1000% of expected time-on-air)
RadioLibTime_t timeout = getTimeOnAir(len) * 10;
// for most other modules, it is 500%, however, the overall datarates of SX128x are higher
// so we use higher value for the default timeout
RadioLibTime_t timeoutInternal = timeout;
if(!timeoutInternal) {
timeoutInternal = getTimeOnAir(len) * 10;
}
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", (uint32_t)((timeout + 999) / 1000));
// start reception
uint32_t timeoutValue = (uint32_t)((float)timeout / 15.625f);
uint32_t timeoutValue = (uint32_t)((float)timeoutInternal / 15.625f);
state = startReceive(timeoutValue);
RADIOLIB_ASSERT(state);
@ -390,8 +395,7 @@ int16_t SX128x::receive(uint8_t* data, size_t len) {
// check whether this was a timeout or not
if((getIrqStatus() & RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT) || softTimeout) {
standby();
clearIrqStatus();
(void)finishReceive();
return(RADIOLIB_ERR_RX_TIMEOUT);
}
@ -566,6 +570,15 @@ int16_t SX128x::readData(uint8_t* data, size_t len) {
return(state);
}
int16_t SX128x::finishReceive() {
// set mode to standby to disable RF switch
int16_t state = standby();
RADIOLIB_ASSERT(state);
// clear interrupt flags
return(clearIrqStatus());
}
uint32_t SX128x::getIrqFlags() {
return((uint32_t)this->getIrqStatus());
}

Wyświetl plik

@ -435,11 +435,13 @@ class SX128x: public PhysicalLayer {
/*!
\brief Blocking binary receive method.
Overloads for string-based transmissions are implemented in PhysicalLayer.
\param data Binary data to be sent.
\param len Number of bytes to send.
\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 timeout Reception timeout in milliseconds. If set to 0,
timeout period will be calculated automatically based on the radio configuration.
\returns \ref status_codes
*/
int16_t receive(uint8_t* data, size_t len) override;
int16_t receive(uint8_t* data, size_t len, RadioLibTime_t timeout = 0) override;
/*!
\brief Starts direct mode transmission.
@ -563,6 +565,12 @@ class SX128x: public PhysicalLayer {
*/
int16_t readData(uint8_t* data, size_t len) override;
/*!
\brief Clean up after reception is done.
\returns \ref status_codes
*/
int16_t finishReceive() override;
/*!
\brief Read currently active IRQ flags.
\returns IRQ flags.

Wyświetl plik

@ -97,9 +97,12 @@ int16_t Si443x::transmit(const uint8_t* data, size_t len, uint8_t addr) {
return(finishTransmit());
}
int16_t Si443x::receive(uint8_t* data, size_t len) {
// calculate timeout (500 ms + 400 full 64-byte packets at current bit rate)
RadioLibTime_t timeout = 500 + (1.0f/(this->bitRate))*(RADIOLIB_SI443X_MAX_PACKET_LENGTH*400.0f);
int16_t Si443x::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
RadioLibTime_t timeoutInternal = timeout;
if(!timeoutInternal) {
// calculate timeout (500 ms + 400 full max-length packets at current bit rate)
timeoutInternal = 500 + (1.0f/(this->bitRate))*(RADIOLIB_SI443X_MAX_PACKET_LENGTH*400.0f);
}
// start reception
int16_t state = startReceive();
@ -108,9 +111,8 @@ int16_t Si443x::receive(uint8_t* data, size_t len) {
// wait for packet reception or timeout
RadioLibTime_t start = this->mod->hal->millis();
while(this->mod->hal->digitalRead(this->mod->getIrq())) {
if(this->mod->hal->millis() - start > timeout) {
standby();
clearIrqStatus();
if(this->mod->hal->millis() - start > timeoutInternal) {
(void)finishReceive();
return(RADIOLIB_ERR_RX_TIMEOUT);
}
}
@ -345,14 +347,16 @@ int16_t Si443x::readData(uint8_t* data, size_t len) {
// clear internal flag so getPacketLength can return the new packet length
this->packetLengthQueried = false;
// set mode to standby
return(finishReceive());
}
int16_t Si443x::finishReceive() {
// set mode to standby to disable RF switch
int16_t state = standby();
RADIOLIB_ASSERT(state);
// clear interrupt flags
clearIrqStatus();
return(RADIOLIB_ERR_NONE);
return(state);
}
int16_t Si443x::setBitRate(float br) {

Wyświetl plik

@ -598,9 +598,11 @@ class Si443x: public PhysicalLayer {
For overloads to receive Arduino String, see PhysicalLayer::receive.
\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 timeout Reception timeout in milliseconds. If set to 0,
timeout period will be calculated automatically based on the radio configuration.
\returns \ref status_codes
*/
int16_t receive(uint8_t* data, size_t len) override;
int16_t receive(uint8_t* data, size_t len, RadioLibTime_t timeout = 0) override;
/*!
\brief Sets the module to sleep to save power. %Module will not be able to transmit or receive any data while in sleep mode.
@ -717,6 +719,12 @@ class Si443x: public PhysicalLayer {
*/
int16_t readData(uint8_t* data, size_t len) override;
/*!
\brief Clean up after reception is done.
\returns \ref status_codes
*/
int16_t finishReceive() override;
// configuration methods
/*!

Wyświetl plik

@ -110,7 +110,13 @@ int16_t nRF24::transmit(const uint8_t* data, size_t len, uint8_t addr) {
return(finishTransmit());
}
int16_t nRF24::receive(uint8_t* data, size_t len) {
int16_t nRF24::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
RadioLibTime_t timeoutInternal = timeout;
if(!timeoutInternal) {
// calculate timeout (15 retries * 4ms (max Tx time as per datasheet) + 10 ms)
timeoutInternal = ((15 * 4) + 10);
}
// start reception
int16_t state = startReceive();
RADIOLIB_ASSERT(state);
@ -120,10 +126,9 @@ int16_t nRF24::receive(uint8_t* data, size_t len) {
while(this->mod->hal->digitalRead(this->mod->getIrq())) {
this->mod->hal->yield();
// check timeout: 15 retries * 4ms (max Tx time as per datasheet) + 10 ms
if(this->mod->hal->millis() - start >= ((15 * 4) + 10)) {
standby();
clearIRQ();
// check timeout
if(this->mod->hal->millis() - start >= timeoutInternal) {
(void)finishReceive();
return(RADIOLIB_ERR_RX_TIMEOUT);
}
}
@ -274,10 +279,15 @@ int16_t nRF24::readData(uint8_t* data, size_t len) {
// read packet data
SPIreadRxPayload(data, length);
// clear interrupt
return(finishReceive());
}
int16_t nRF24::finishReceive() {
// clear interrupt flags
clearIRQ();
return(RADIOLIB_ERR_NONE);
// set mode to standby to disable transmitter/RF switch
return(standby());
}
int16_t nRF24::setFrequency(float freq) {

Wyświetl plik

@ -243,13 +243,15 @@ class nRF24: public PhysicalLayer {
int16_t transmit(const uint8_t* data, size_t len, uint8_t addr) override;
/*!
\brief Blocking binary receive method.
Overloads for string-based transmissions are implemented in PhysicalLayer.
\param data Binary data to be sent.
\param len Number of bytes to send.
\brief Binary receive method. Will attempt to receive arbitrary binary data up to 64 bytes long.
For overloads to receive Arduino String, see PhysicalLayer::receive.
\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 timeout Reception timeout in milliseconds. If set to 0,
timeout period will be calculated automatically based on the radio configuration.
\returns \ref status_codes
*/
int16_t receive(uint8_t* data, size_t len) override;
int16_t receive(uint8_t* data, size_t len, RadioLibTime_t timeout = 0) override;
/*!
\brief Starts direct mode transmission.
@ -340,6 +342,12 @@ class nRF24: public PhysicalLayer {
*/
int16_t readData(uint8_t* data, size_t len) override;
/*!
\brief Clean up after reception is done.
\returns \ref status_codes
*/
int16_t finishReceive() override;
// configuration methods
/*!

Wyświetl plik

@ -62,7 +62,7 @@ int16_t PhysicalLayer::transmit(const uint8_t* data, size_t len, uint8_t addr) {
}
#if defined(RADIOLIB_BUILD_ARDUINO)
int16_t PhysicalLayer::receive(String& str, size_t len) {
int16_t PhysicalLayer::receive(String& str, size_t len, RadioLibTime_t timeout) {
int16_t state = RADIOLIB_ERR_NONE;
// user can override the length of data to read
@ -82,7 +82,7 @@ int16_t PhysicalLayer::receive(String& str, size_t len) {
#endif
// attempt packet reception
state = receive(data, length);
state = receive(data, length, timeout);
// any of the following leads to at least some data being available
// let's leave the decision of whether to keep it or not up to the user
@ -108,9 +108,10 @@ int16_t PhysicalLayer::receive(String& str, size_t len) {
}
#endif
int16_t PhysicalLayer::receive(uint8_t* data, size_t len) {
int16_t PhysicalLayer::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
(void)data;
(void)len;
(void)timeout;
return(RADIOLIB_ERR_UNSUPPORTED);
}
@ -174,6 +175,10 @@ int16_t PhysicalLayer::finishTransmit() {
return(RADIOLIB_ERR_UNSUPPORTED);
}
int16_t PhysicalLayer::finishReceive() {
return(RADIOLIB_ERR_UNSUPPORTED);
}
#if defined(RADIOLIB_BUILD_ARDUINO)
int16_t PhysicalLayer::readData(String& str, size_t len) {
int16_t state = RADIOLIB_ERR_NONE;

Wyświetl plik

@ -275,10 +275,12 @@ class PhysicalLayer {
/*!
\brief Arduino String receive method.
\param str Address of Arduino String to save the received data.
\param len Expected number of characters in the message. Leave as 0 if expecting a unknown size packet
\param len Expected number of characters in the message. Leave as 0 if expecting a unknown size packet.
\param timeout Reception timeout in milliseconds. If set to 0,
timeout period will be calculated automatically based on the radio configuration.
\returns \ref status_codes
*/
int16_t receive(String& str, size_t len = 0);
int16_t receive(String& str, size_t len = 0, RadioLibTime_t timeout = 0);
#endif
/*!
@ -321,9 +323,11 @@ class PhysicalLayer {
\brief Binary receive method. Must be implemented in module class.
\param data Pointer to array to save the received binary data.
\param len Packet length, needed for some modules under special circumstances (e.g. LoRa implicit header mode).
\param timeout Reception timeout in milliseconds. If set to 0,
timeout period will be calculated automatically based on the radio configuration.
\returns \ref status_codes
*/
virtual int16_t receive(uint8_t* data, size_t len);
virtual int16_t receive(uint8_t* data, size_t len, RadioLibTime_t timeout = 0);
#if defined(RADIOLIB_BUILD_ARDUINO)
/*!
@ -360,6 +364,12 @@ class PhysicalLayer {
*/
virtual int16_t finishTransmit();
/*!
\brief Clean up after reception is done.
\returns \ref status_codes
*/
virtual int16_t finishReceive();
#if defined(RADIOLIB_BUILD_ARDUINO)
/*!
\brief Reads data that was received after calling startReceive method.