Speed Option 3 builds and harden radio IRQ handling

This commit is contained in:
mikecarper committed 2026-07-29 14:26:57 -07:00
1 parent 6460aaa53b
commit 07c968cb54
8 files changed
+432 -49

No files matched your search

+3 -1
View File
@@ -530,7 +530,9 @@ bool NRF52Board::startOTAUpdate(const char *id, char reply[], bool force_ap) {
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.configPrphConn(92, BLE_GAP_EVENT_LENGTH_MIN, 16, 16);
Bluefruit.begin(1, 0);
if (!Bluefruit.begin(1, 0)) {
return false;
}
ota_ble_started = true;
// To be consistent OTA DFU should be added first if it exists
+76 -7
View File
@@ -2,10 +2,12 @@
#include <RadioLib.h>
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
#define SX126X_IRQ_PREAMBLE_DETECTED 0x04
class CustomLLCC68 : public LLCC68 {
uint32_t _preambleMillis = 66;
uint32_t _maxPayloadMillis = 3934;
uint32_t _activityAt = 0;
bool _headerSeen = false;
public:
CustomLLCC68(Module *mod) : LLCC68(mod) { }
@@ -78,10 +80,77 @@ class CustomLLCC68 : public LLCC68 {
return true; // success
}
int16_t startReceive() override {
return LLCC68::startReceive(
RADIOLIB_SX126X_RX_TIMEOUT_INF,
RADIOLIB_IRQ_RX_DEFAULT_FLAGS | (1UL << RADIOLIB_IRQ_PREAMBLE_DETECTED),
RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
}
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;
bool header = irq & RADIOLIB_SX126X_IRQ_HEADER_VALID;
bool headerError = irq & RADIOLIB_SX126X_IRQ_HEADER_ERR;
uint32_t now = millis();
if (headerError) {
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 && _headerSeen) {
_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) {
clearIrqFlags(RADIOLIB_SX126X_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 setPreambleMillis(uint32_t preambleMillis) {
_preambleMillis = preambleMillis;
MESH_DEBUG_PRINTLN("Set _preambleMillis=%u", _preambleMillis);
}
void setMaxPayloadMillis(uint32_t payloadMillis) {
_maxPayloadMillis = payloadMillis;
MESH_DEBUG_PRINTLN("Set _maxPayloadMillis=%u", _maxPayloadMillis);
}
bool getRxBoostedGainMode() {
@@ -89,4 +158,4 @@ class CustomLLCC68 : public LLCC68 {
readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1);
return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED);
}
};
};
+7 -1
View File
@@ -10,11 +10,17 @@ public:
protected:
bool applyParams(float freq, float bw, uint8_t sf, uint8_t cr) override {
return ((CustomLLCC68 *)_radio)->setFrequency(freq) == RADIOLIB_ERR_NONE
bool success = ((CustomLLCC68 *)_radio)->setFrequency(freq) == RADIOLIB_ERR_NONE
&& ((CustomLLCC68 *)_radio)->setSpreadingFactor(sf) == RADIOLIB_ERR_NONE
&& ((CustomLLCC68 *)_radio)->setBandwidth(bw) == RADIOLIB_ERR_NONE
&& ((CustomLLCC68 *)_radio)->setCodingRate(cr) == RADIOLIB_ERR_NONE
&& updatePreamble(sf);
if (!success) return false;
PacketMillis pm = calcMaxPacketMillis(sf, bw, cr, preambleLengthForSF(sf));
((CustomLLCC68 *)_radio)->setPreambleMillis(pm.preambleMillis);
((CustomLLCC68 *)_radio)->setMaxPayloadMillis(pm.payloadMillis);
return true;
}
public:
+15
View File
@@ -74,6 +74,15 @@ class CustomLR1110 : public LR1110 {
bool getRxBoostedGainMode() const { return _rx_boosted; }
int16_t startReceive() override {
// Make preamble detection visible to CAD while retaining RadioLib's
// normal RX-complete and error events.
return LR1110::startReceive(
RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED,
RADIOLIB_IRQ_RX_DEFAULT_FLAGS | (1UL << RADIOLIB_IRQ_PREAMBLE_DETECTED),
RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
}
// BUSY high means the chip is asleep (RX duty-cycle sleep window) or mid
// command; any SPI access would stall until the chip's next listen window.
bool isChipBusy() {
@@ -95,6 +104,12 @@ class CustomLR1110 : public LR1110 {
_headerSeen = false;
return false;
}
if (!header && _headerSeen) {
// Another path consumed the header IRQ; reset only our local timer.
_activityAt = 0;
_headerSeen = false;
return false;
}
if (header) {
if (!_headerSeen) { _headerSeen = true; _activityAt = now; };
if (now - _activityAt > _maxPayloadMillis) {
+15
View File
@@ -140,6 +140,15 @@ class CustomSX1262 : public SX1262 {
return RADIOLIB_ERR_NONE;
}
int16_t startReceive() override {
// Make preamble detection visible to CAD while retaining RadioLib's
// normal RX-complete and error events.
return SX1262::startReceive(
RADIOLIB_SX126X_RX_TIMEOUT_INF,
RADIOLIB_IRQ_RX_DEFAULT_FLAGS | (1UL << RADIOLIB_IRQ_PREAMBLE_DETECTED),
RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
}
bool isReceiving() {
if (isChipBusy()) return false; // asleep, cannot be mid-receive
@@ -154,6 +163,12 @@ class CustomSX1262 : public SX1262 {
_headerSeen = false;
return false;
}
if (!header && _headerSeen) {
// Another path consumed the header IRQ; reset only our local timer.
_activityAt = 0;
_headerSeen = false;
return false;
}
if (header) {
if (!_headerSeen) { _headerSeen = true; _activityAt = now; };
if (now - _activityAt > _maxPayloadMillis) {
+76 -7
View File
@@ -2,10 +2,12 @@
#include <RadioLib.h>
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
#define SX126X_IRQ_PREAMBLE_DETECTED 0x04
class CustomSX1268 : public SX1268 {
uint32_t _preambleMillis = 66;
uint32_t _maxPayloadMillis = 3934;
uint32_t _activityAt = 0;
bool _headerSeen = false;
public:
CustomSX1268(Module *mod) : SX1268(mod) { }
@@ -78,10 +80,77 @@ class CustomSX1268 : public SX1268 {
return true; // success
}
int16_t startReceive() override {
return SX1268::startReceive(
RADIOLIB_SX126X_RX_TIMEOUT_INF,
RADIOLIB_IRQ_RX_DEFAULT_FLAGS | (1UL << RADIOLIB_IRQ_PREAMBLE_DETECTED),
RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
}
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;
bool header = irq & RADIOLIB_SX126X_IRQ_HEADER_VALID;
bool headerError = irq & RADIOLIB_SX126X_IRQ_HEADER_ERR;
uint32_t now = millis();
if (headerError) {
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 && _headerSeen) {
_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) {
clearIrqFlags(RADIOLIB_SX126X_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 setPreambleMillis(uint32_t preambleMillis) {
_preambleMillis = preambleMillis;
MESH_DEBUG_PRINTLN("Set _preambleMillis=%u", _preambleMillis);
}
void setMaxPayloadMillis(uint32_t payloadMillis) {
_maxPayloadMillis = payloadMillis;
MESH_DEBUG_PRINTLN("Set _maxPayloadMillis=%u", _maxPayloadMillis);
}
bool getRxBoostedGainMode() {
@@ -89,4 +158,4 @@ class CustomSX1268 : public SX1268 {
readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1);
return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED);
}
};
};
+7 -1
View File
@@ -14,11 +14,17 @@ public:
protected:
bool applyParams(float freq, float bw, uint8_t sf, uint8_t cr) override {
return ((CustomSX1268 *)_radio)->setFrequency(freq) == RADIOLIB_ERR_NONE
bool success = ((CustomSX1268 *)_radio)->setFrequency(freq) == RADIOLIB_ERR_NONE
&& ((CustomSX1268 *)_radio)->setSpreadingFactor(sf) == RADIOLIB_ERR_NONE
&& ((CustomSX1268 *)_radio)->setBandwidth(bw) == RADIOLIB_ERR_NONE
&& ((CustomSX1268 *)_radio)->setCodingRate(cr) == RADIOLIB_ERR_NONE
&& updatePreamble(sf);
if (!success) return false;
PacketMillis pm = calcMaxPacketMillis(sf, bw, cr, preambleLengthForSF(sf));
((CustomSX1268 *)_radio)->setPreambleMillis(pm.preambleMillis);
((CustomSX1268 *)_radio)->setMaxPayloadMillis(pm.payloadMillis);
return true;
}
public: