mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-07-21 09:02:16 +00:00
Merge pull request #2977 from oltaco/rx-irq-timeout
Add IRQ timeout logic for SX1262 and LR1121
This commit is contained in:
@@ -4,6 +4,10 @@
|
||||
#include "MeshCore.h"
|
||||
|
||||
class CustomLR1110 : public LR1110 {
|
||||
uint32_t _preambleMillis = 66;
|
||||
uint32_t _maxPayloadMillis = 3934;
|
||||
uint32_t _activityAt = 0;
|
||||
bool _headerSeen = false;
|
||||
bool _rx_boosted = false;
|
||||
|
||||
public:
|
||||
@@ -32,9 +36,46 @@ class CustomLR1110 : public LR1110 {
|
||||
bool getRxBoostedGainMode() const { return _rx_boosted; }
|
||||
|
||||
bool isReceiving() {
|
||||
uint16_t irq = getIrqStatus();
|
||||
bool detected = ((irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || (irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED));
|
||||
return detected;
|
||||
uint32_t irq = getIrqStatus();
|
||||
bool preamble = irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED; // bit 4
|
||||
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; }
|
||||
|
||||
@@ -14,6 +14,8 @@ public:
|
||||
((CustomLR1110 *)_radio)->setBandwidth(bw);
|
||||
((CustomLR1110 *)_radio)->setCodingRate(cr);
|
||||
updatePreamble(sf);
|
||||
((CustomLR1110 *)_radio)->setMaxPacketMillis(calcMaxPacketMillis(sf, bw, cr, preambleLengthForSF(sf)));
|
||||
|
||||
}
|
||||
|
||||
void doResetAGC() override { lr11x0ResetAGC((LR11x0 *)_radio, ((CustomLR1110 *)_radio)->getFreqMHz()); }
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
#include <RadioLib.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 {
|
||||
uint32_t _preambleMillis = 66;
|
||||
uint32_t _maxPayloadMillis = 3934;
|
||||
uint32_t _activityAt = 0;
|
||||
bool _headerSeen = false;
|
||||
|
||||
public:
|
||||
CustomSX1262(Module *mod) : SX1262(mod) { }
|
||||
|
||||
@@ -99,9 +101,46 @@ class CustomSX1262 : public SX1262 {
|
||||
}
|
||||
|
||||
bool isReceiving() {
|
||||
uint16_t irq = getIrqFlags();
|
||||
bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED);
|
||||
return detected;
|
||||
uint32_t irq = getIrqFlags();
|
||||
bool preamble = irq & RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED; // bit 2
|
||||
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() {
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
((CustomSX1262 *)_radio)->setBandwidth(bw);
|
||||
((CustomSX1262 *)_radio)->setCodingRate(cr);
|
||||
updatePreamble(sf);
|
||||
((CustomSX1262 *)_radio)->setMaxPacketMillis(calcMaxPacketMillis(sf, bw, cr, preambleLengthForSF(sf)));
|
||||
}
|
||||
|
||||
bool isReceivingPacket() override {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
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};
|
||||
}
|
||||
@@ -3,6 +3,11 @@
|
||||
#include <Mesh.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 {
|
||||
protected:
|
||||
PhysicalLayer* _radio;
|
||||
@@ -47,6 +52,7 @@ public:
|
||||
virtual uint8_t getSpreadingFactor() const { return LORA_SF; }
|
||||
static uint16_t preambleLengthForSF(uint8_t sf) { return sf <= 8 ? 32 : 16; }
|
||||
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();
|
||||
|
||||
int getNoiseFloor() const override { return _noise_floor; }
|
||||
|
||||
Reference in New Issue
Block a user