mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-25 20:26:37 +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"
|
#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; }
|
||||||
|
|||||||
@@ -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()); }
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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};
|
||||||
|
}
|
||||||
@@ -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; }
|
||||||
|
|||||||
Reference in New Issue
Block a user