kopia lustrzana https://github.com/jgromes/RadioLib
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 valuepull/1603/head
rodzic
bbb2e4e575
commit
7fc83f732c
|
@ -133,6 +133,7 @@ startTransmit KEYWORD2
|
|||
finishTransmit KEYWORD2
|
||||
startReceive KEYWORD2
|
||||
readData KEYWORD2
|
||||
finishReceive KEYWORD2
|
||||
startChannelScan KEYWORD2
|
||||
getChannelScanResult KEYWORD2
|
||||
setBandwidth KEYWORD2
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/*!
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
/*!
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
||||
/*!
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
||||
/*!
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
Ładowanie…
Reference in New Issue