Browse Source

Merge pull request #2977 from oltaco/rx-irq-timeout

Add IRQ timeout logic for SX1262 and LR1121
pull/1551/merge
ripplebiz 2 days ago
committed by GitHub
parent
commit
dc7dd5105e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 47
      src/helpers/radiolib/CustomLR1110.h
  2. 2
      src/helpers/radiolib/CustomLR1110Wrapper.h
  3. 51
      src/helpers/radiolib/CustomSX1262.h
  4. 1
      src/helpers/radiolib/CustomSX1262Wrapper.h
  5. 18
      src/helpers/radiolib/RadioLibWrappers.cpp
  6. 6
      src/helpers/radiolib/RadioLibWrappers.h

47
src/helpers/radiolib/CustomLR1110.h

@ -4,6 +4,10 @@
#include "MeshCore.h" #include "MeshCore.h"
class CustomLR1110 : public LR1110 { class CustomLR1110 : public LR1110 {
uint32_t _preambleMillis = 66;
uint32_t _maxPayloadMillis = 3934;
uint32_t _activityAt = 0;
bool _headerSeen = false;
bool _rx_boosted = false; bool _rx_boosted = false;
public: public:
@ -32,9 +36,46 @@ class CustomLR1110 : public LR1110 {
bool getRxBoostedGainMode() const { return _rx_boosted; } bool getRxBoostedGainMode() const { return _rx_boosted; }
bool isReceiving() { bool isReceiving() {
uint16_t irq = getIrqStatus(); uint32_t irq = getIrqStatus();
bool detected = ((irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || (irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED)); bool preamble = irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED; // bit 4
return detected; bool header = irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID; // bit 5
bool hdrErr = irq & RADIOLIB_LR11X0_IRQ_HEADER_ERR; // bit 6
uint32_t now = millis();
if (hdrErr) {
clearIrqState(RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED | RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID | RADIOLIB_LR11X0_IRQ_HEADER_ERR);
_activityAt = 0;
_headerSeen = false;
return false;
}
if (header) {
if (!_headerSeen) { _headerSeen = true; _activityAt = now; };
if (now - _activityAt > _maxPayloadMillis) {
MESH_DEBUG_PRINTLN("Clearing header IRQ after %ums", _maxPayloadMillis);
clearIrqState(RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED | RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID | RADIOLIB_LR11X0_IRQ_HEADER_ERR);
_activityAt = 0; _headerSeen = false;
return false;
}
return true;
}
if (preamble) {
if (_activityAt == 0) _activityAt = now;
if (now - _activityAt > _preambleMillis) {
clearIrqState(RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED);
_activityAt = 0;
MESH_DEBUG_PRINTLN("Clearing preamble IRQ after %ums", _preambleMillis);
return false;
}
return true;
}
_activityAt = 0; _headerSeen = false;
return false;
}
void setMaxPacketMillis(PacketMillis maxPacketMillis) {
MESH_DEBUG_PRINTLN("Setting _preambleMillis=%u, _maxPacketMillis=%u", maxPacketMillis.preambleMillis, maxPacketMillis.payloadMillis);
_preambleMillis = maxPacketMillis.preambleMillis;
_maxPayloadMillis = maxPacketMillis.payloadMillis;
} }
uint8_t getSpreadingFactor() const { return spreadingFactor; } uint8_t getSpreadingFactor() const { return spreadingFactor; }

2
src/helpers/radiolib/CustomLR1110Wrapper.h

@ -14,6 +14,8 @@ public:
((CustomLR1110 *)_radio)->setBandwidth(bw); ((CustomLR1110 *)_radio)->setBandwidth(bw);
((CustomLR1110 *)_radio)->setCodingRate(cr); ((CustomLR1110 *)_radio)->setCodingRate(cr);
updatePreamble(sf); updatePreamble(sf);
((CustomLR1110 *)_radio)->setMaxPacketMillis(calcMaxPacketMillis(sf, bw, cr, preambleLengthForSF(sf)));
} }
void doResetAGC() override { lr11x0ResetAGC((LR11x0 *)_radio, ((CustomLR1110 *)_radio)->getFreqMHz()); } void doResetAGC() override { lr11x0ResetAGC((LR11x0 *)_radio, ((CustomLR1110 *)_radio)->getFreqMHz()); }

51
src/helpers/radiolib/CustomSX1262.h

@ -3,10 +3,12 @@
#include <RadioLib.h> #include <RadioLib.h>
#include "MeshCore.h" #include "MeshCore.h"
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
#define SX126X_IRQ_PREAMBLE_DETECTED 0x04
class CustomSX1262 : public SX1262 { class CustomSX1262 : public SX1262 {
uint32_t _preambleMillis = 66;
uint32_t _maxPayloadMillis = 3934;
uint32_t _activityAt = 0;
bool _headerSeen = false;
public: public:
CustomSX1262(Module *mod) : SX1262(mod) { } CustomSX1262(Module *mod) : SX1262(mod) { }
@ -99,9 +101,46 @@ class CustomSX1262 : public SX1262 {
} }
bool isReceiving() { bool isReceiving() {
uint16_t irq = getIrqFlags(); uint32_t irq = getIrqFlags();
bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED); bool preamble = irq & RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED; // bit 2
return detected; bool header = irq & RADIOLIB_SX126X_IRQ_HEADER_VALID; // bit 4
bool hdrErr = irq & RADIOLIB_SX126X_IRQ_HEADER_ERR; // bit 5
uint32_t now = millis();
if (hdrErr) {
clearIrqFlags(RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED | RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_HEADER_ERR | RADIOLIB_SX126X_IRQ_SYNC_WORD_VALID);
_activityAt = 0;
_headerSeen = false;
return false;
}
if (header) {
if (!_headerSeen) { _headerSeen = true; _activityAt = now; };
if (now - _activityAt > _maxPayloadMillis) {
MESH_DEBUG_PRINTLN("Clearing header IRQ after %ums", _maxPayloadMillis);
clearIrqFlags(RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED | RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_HEADER_ERR | RADIOLIB_SX126X_IRQ_SYNC_WORD_VALID);
_activityAt = 0; _headerSeen = false;
return false;
}
return true;
}
if (preamble) {
if (_activityAt == 0) _activityAt = now;
if (now - _activityAt > _preambleMillis) {
clearIrqStatus(RADIOLIB_IRQ_PREAMBLE_DETECTED);
_activityAt = 0;
MESH_DEBUG_PRINTLN("Clearing preamble IRQ after %ums", _preambleMillis);
return false;
}
return true;
}
_activityAt = 0; _headerSeen = false;
return false;
}
void setMaxPacketMillis(PacketMillis maxPacketMillis) {
MESH_DEBUG_PRINTLN("Setting _preambleMillis=%u, _maxPacketMillis=%u", maxPacketMillis.preambleMillis, maxPacketMillis.payloadMillis);
_preambleMillis = maxPacketMillis.preambleMillis;
_maxPayloadMillis = maxPacketMillis.payloadMillis;
} }
bool getRxBoostedGainMode() { bool getRxBoostedGainMode() {

1
src/helpers/radiolib/CustomSX1262Wrapper.h

@ -18,6 +18,7 @@ public:
((CustomSX1262 *)_radio)->setBandwidth(bw); ((CustomSX1262 *)_radio)->setBandwidth(bw);
((CustomSX1262 *)_radio)->setCodingRate(cr); ((CustomSX1262 *)_radio)->setCodingRate(cr);
updatePreamble(sf); updatePreamble(sf);
((CustomSX1262 *)_radio)->setMaxPacketMillis(calcMaxPacketMillis(sf, bw, cr, preambleLengthForSF(sf)));
} }
bool isReceivingPacket() override { bool isReceivingPacket() override {

18
src/helpers/radiolib/RadioLibWrappers.cpp

@ -228,3 +228,21 @@ float RadioLibWrapper::packetScoreInt(float snr, int sf, int packet_len) {
return max(0.0, min(1.0, success_rate_based_on_snr * collision_penalty)); return max(0.0, min(1.0, success_rate_based_on_snr * collision_penalty));
} }
PacketMillis RadioLibWrapper::calcMaxPacketMillis(uint8_t sf, float bw, uint8_t cr, uint8_t preambleSymbols) {
// based on RadioLib's calculateTimeOnAir()
uint32_t tsym_us = ((uint32_t)10000 << sf) / (bw * 10);
uint32_t sfCoeff1_x4 = (sf == 5 || sf == 6) ? 25 : 17; // 6.25 : 4.25, semtech magic numbers to account for sync word + sfd
// preamble + syncword + sfd + header
uint32_t preamble_us = (((preambleSymbols + 8) * 4 + sfCoeff1_x4) * tsym_us) / 4;
// airtime for max packet at current radio settings
uint32_t total_us = _radio->getTimeOnAir(MAX_TRANS_UNIT);
// airtime for payload only (no preamble, header or SOF)
uint32_t payload_us = total_us > preamble_us ? total_us - preamble_us : 4000 - preamble_us; // fallback to 4 secs at worst case
// rescale payload_us for max possible CR
if (cr >= 5 && cr < 8) { payload_us = (payload_us * 8) / cr; }
return PacketMillis {(preamble_us + 999) / 1000, (payload_us + 999) / 1000};
}

6
src/helpers/radiolib/RadioLibWrappers.h

@ -3,6 +3,11 @@
#include <Mesh.h> #include <Mesh.h>
#include <RadioLib.h> #include <RadioLib.h>
struct PacketMillis {
uint32_t preambleMillis; // preamble-detect -> header-valid deadline
uint32_t payloadMillis; // header-valid -> rx-done deadline
};
class RadioLibWrapper : public mesh::Radio { class RadioLibWrapper : public mesh::Radio {
protected: protected:
PhysicalLayer* _radio; PhysicalLayer* _radio;
@ -47,6 +52,7 @@ public:
virtual uint8_t getSpreadingFactor() const { return LORA_SF; } virtual uint8_t getSpreadingFactor() const { return LORA_SF; }
static uint16_t preambleLengthForSF(uint8_t sf) { return sf <= 8 ? 32 : 16; } static uint16_t preambleLengthForSF(uint8_t sf) { return sf <= 8 ? 32 : 16; }
void updatePreamble(uint8_t sf) { _preamble_sf = sf; _radio->setPreambleLength(preambleLengthForSF(sf)); } void updatePreamble(uint8_t sf) { _preamble_sf = sf; _radio->setPreambleLength(preambleLengthForSF(sf)); }
PacketMillis calcMaxPacketMillis(uint8_t sf, float bw, uint8_t cr, uint8_t preambleSymbols);
virtual int16_t performChannelScan(); virtual int16_t performChannelScan();
int getNoiseFloor() const override { return _noise_floor; } int getNoiseFloor() const override { return _noise_floor; }

Loading…
Cancel
Save