fix: airtime LDRO threshold must track driver (was BW-blind sf>=11)

getEstAirtimeFor() set LDRO from `sf >= 11`, correct only at BW125. Now
matches the driver's should_enable_ldro() (t_sym > 16.38 ms) so the
estimate's DE tracks hardware DE on every SF/BW. Also drop dead
calcRxDelay() + unused MAX_RX_DELAY_MILLIS.
This commit is contained in:
liquidraver
2026-05-29 15:48:48 +02:00
parent ea27b93ac5
commit 7d7a64ff5a
4 changed files with 6 additions and 20 deletions
+1 -1
View File
@@ -687,7 +687,7 @@ DIO1 interrupt → Zephyr lora driver → async RX callback
→ k_event_post(MESH_EVENT_LORA_RX) → main thread wakes
→ Dispatcher::loop() → checkRecv() → drain ring buffer
→ tryParsePacket() → score + airtime calc
→ flood: calcRxDelay() → queue inbound or process immediately
→ flood: dedup + adaptive contention delay → queue for retransmit
→ direct: process immediately
→ Mesh::onRecvPacket() → decrypt → dispatch by type
→ BaseChatMesh::onPeerDataRecv() → onMessageRecv()
+5 -1
View File
@@ -598,7 +598,11 @@ uint32_t LoRaRadioBase::getEstAirtimeFor(int len_bytes)
float t_sym = (float)(1 << sf) / (bw * 1000.0f);
float t_preamble = (preambleLengthForSF(sf) + 4.25f) * t_sym;
float de = (sf >= 11) ? 1.0f : 0.0f;
/* LDRO threshold must track the SX126x driver's should_enable_ldro()
* exactly (symbol time > 16.38 ms) so this estimate's DE matches the
* hardware's DE on every SF/BW pair. The old `sf >= 11` was only
* correct at BW 125 kHz and diverged on every other bandwidth. */
float de = (t_sym > 0.01638f) ? 1.0f : 0.0f;
float num = 8.0f * len_bytes - 4.0f * sf + 28.0f + 16.0f;
float den = 4.0f * (sf - 2.0f * de);
if (den < 1.0f) den = 4.0f;
-1
View File
@@ -84,7 +84,6 @@ protected:
virtual const char *getLogDateTime() { return ""; }
virtual uint8_t getDutyCyclePercent() const;
static bool isAdminPacket(const Packet *pkt);
virtual int calcRxDelay(float score, uint32_t air_time) const;
virtual uint32_t getCADFailRetryDelay() const;
virtual uint32_t getCADFailMaxDuration() const;
virtual int getInterferenceThreshold() const { return 0; }
-17
View File
@@ -21,7 +21,6 @@ LOG_MODULE_REGISTER(zephcore_dispatcher, CONFIG_ZEPHCORE_LORA_LOG_LEVEL);
namespace mesh {
#define MAX_RX_DELAY_MILLIS 32000 /* upper bound for score-based RX delay */
#define MIN_TX_BUDGET_AIRTIME_DIV 2 /* require at least 1/N MTU airtime as budget before TX */
Dispatcher::Dispatcher(Radio &radio, MillisecondClock &ms, PacketManager &mgr)
@@ -105,22 +104,6 @@ bool Dispatcher::isAdminPacket(const Packet *pkt)
t == PAYLOAD_TYPE_ANON_REQ || t == PAYLOAD_TYPE_CONTROL;
}
int Dispatcher::calcRxDelay(float score, uint32_t air_time) const
{
/* LUT: 10^(0.85 - i*0.1) - 1, i=0..10; replaces powf() (~1.9KB saved) */
static const float lut[11] = {
6.0793f, 4.6236f, 3.4674f, 2.5489f, 1.8184f, 1.2389f,
0.7783f, 0.4125f, 0.1220f, -0.1089f, -0.2921f
};
if (score <= 0.0f) return (int)(lut[0] * (float)air_time);
if (score >= 1.0f) return (int)(lut[10] * (float)air_time);
float idx = score * 10.0f;
int i = (int)idx;
float frac = idx - (float)i;
float val = lut[i] + frac * (lut[i + 1] - lut[i]);
return (int)(val * (float)air_time);
}
uint32_t Dispatcher::getCADFailRetryDelay() const
{
/* 100-200ms jittered retry: tighter than one SF8 flood airtime so we