[SX127x] Implement blocking receive timeout

pull/1592/head
jgromes 2025-09-07 11:16:19 +02:00
rodzic 89804b58d7
commit 4fd6f43eb8
2 zmienionych plików z 53 dodań i 53 usunięć

Wyświetl plik

@ -211,68 +211,66 @@ 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) {
// get currently active modem
uint8_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
// calculate timeout (100 LoRa symbols, the default for SX127x series)
timeoutValue = 100;
float symbolLength = (float)(uint32_t(1) << this->spreadingFactor) / (float) this->bandwidth;
timeoutInternal = (RadioLibTime_t)(symbolLength * (float)timeoutValue);
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
// calculate timeout in ms (500 % of expected time-on-air)
size_t maxLen = len;
if(len == 0) { maxLen = RADIOLIB_SX127X_MAX_PACKET_LENGTH_FSK; }
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) {
float symbolLength = (float) (uint32_t(1) << this->spreadingFactor) / (float) this->bandwidth;
timeout = (RadioLibTime_t)(symbolLength * 100.0f);
}
// FSK modem does not distinguish Rx single and continuous mode
timeoutValue = 0;
// 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();
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);
RADIOLIB_ASSERT(state);
// 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();
if(this->mod->hal->millis() - start > timeout) {
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
return(RADIOLIB_ERR_RX_TIMEOUT);
}
} else {
return(RADIOLIB_ERR_UNKNOWN);
}
}
// read the received data
state = readData(data, len);
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeoutInternal);
return(state);
// 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();
// 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();
// 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
return(readData(data, len));
}
int16_t SX127x::scanChannel() {

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.