Browse Source

JP LBT: suppress txdelay to jitter-scale at SF12/BW125

pull/2218/head
me 1 month ago
parent
commit
2d961b6a5f
  1. 12
      examples/simple_repeater/MyMesh.cpp
  2. 12
      examples/simple_room_server/MyMesh.cpp
  3. 16
      examples/simple_sensor/SensorMesh.cpp
  4. 8
      src/helpers/radiolib/RadioLibWrappers.cpp
  5. 2
      src/helpers/radiolib/RadioLibWrappers.h

12
examples/simple_repeater/MyMesh.cpp

@ -541,10 +541,22 @@ int MyMesh::calcRxDelay(float score, uint32_t air_time) const {
}
uint32_t MyMesh::getRetransmitDelay(const mesh::Packet *packet) {
if (_radio->isAS923_1_JP()) {
// JP LBT: suppress txdelay to jitter-scale to avoid adding unnecessary
// latency on top of LBT backoff. A window equal to jitter_max gives
// ~33% collision reduction vs zero, scales naturally with airtime as
// CR changes, and keeps average added delay to ~56ms at SF12/BW125.
uint32_t jitter_max = _radio->getEstAirtimeFor(MAX_TRANS_UNIT) / RadioLibWrapper::JP_LBT_JITTER_DIVISOR;
return getRNG()->nextInt(0, jitter_max + 1);
}
uint32_t t = (_radio->getEstAirtimeFor(packet->getPathByteLen() + packet->payload_len + 2) * _prefs.tx_delay_factor);
return getRNG()->nextInt(0, 5*t + 1);
}
uint32_t MyMesh::getDirectRetransmitDelay(const mesh::Packet *packet) {
if (_radio->isAS923_1_JP()) {
uint32_t jitter_max = _radio->getEstAirtimeFor(MAX_TRANS_UNIT) / RadioLibWrapper::JP_LBT_JITTER_DIVISOR;
return getRNG()->nextInt(0, jitter_max + 1);
}
uint32_t t = (_radio->getEstAirtimeFor(packet->getPathByteLen() + packet->payload_len + 2) * _prefs.direct_tx_delay_factor);
return getRNG()->nextInt(0, 5*t + 1);
}

12
examples/simple_room_server/MyMesh.cpp

@ -272,10 +272,22 @@ const char *MyMesh::getLogDateTime() {
}
uint32_t MyMesh::getRetransmitDelay(const mesh::Packet *packet) {
if (_radio->isAS923_1_JP()) {
// JP LBT: suppress txdelay to jitter-scale to avoid adding unnecessary
// latency on top of LBT backoff. A window equal to jitter_max gives
// ~33% collision reduction vs zero, scales naturally with airtime as
// CR changes, and keeps average added delay to ~56ms at SF12/BW125.
uint32_t jitter_max = _radio->getEstAirtimeFor(MAX_TRANS_UNIT) / RadioLibWrapper::JP_LBT_JITTER_DIVISOR;
return getRNG()->nextInt(0, jitter_max + 1);
}
uint32_t t = (_radio->getEstAirtimeFor(packet->getPathByteLen() + packet->payload_len + 2) * _prefs.tx_delay_factor);
return getRNG()->nextInt(0, 5*t + 1);
}
uint32_t MyMesh::getDirectRetransmitDelay(const mesh::Packet *packet) {
if (_radio->isAS923_1_JP()) {
uint32_t jitter_max = _radio->getEstAirtimeFor(MAX_TRANS_UNIT) / RadioLibWrapper::JP_LBT_JITTER_DIVISOR;
return getRNG()->nextInt(0, jitter_max + 1);
}
uint32_t t = (_radio->getEstAirtimeFor(packet->getPathByteLen() + packet->payload_len + 2) * _prefs.direct_tx_delay_factor);
return getRNG()->nextInt(0, 5*t + 1);
}

16
examples/simple_sensor/SensorMesh.cpp

@ -313,12 +313,24 @@ int SensorMesh::calcRxDelay(float score, uint32_t air_time) const {
}
uint32_t SensorMesh::getRetransmitDelay(const mesh::Packet* packet) {
if (_radio->isAS923_1_JP()) {
// JP LBT: suppress txdelay to jitter-scale to avoid adding unnecessary
// latency on top of LBT backoff. A window equal to jitter_max gives
// ~33% collision reduction vs zero, scales naturally with airtime as
// CR changes, and keeps average added delay to ~56ms at SF12/BW125.
uint32_t jitter_max = _radio->getEstAirtimeFor(MAX_TRANS_UNIT) / RadioLibWrapper::JP_LBT_JITTER_DIVISOR;
return getRNG()->nextInt(0, jitter_max + 1);
}
uint32_t t = (_radio->getEstAirtimeFor(packet->getPathByteLen() + packet->payload_len + 2) * _prefs.tx_delay_factor);
return getRNG()->nextInt(0, 6)*t;
return getRNG()->nextInt(0, 5*t + 1);
}
uint32_t SensorMesh::getDirectRetransmitDelay(const mesh::Packet* packet) {
if (_radio->isAS923_1_JP()) {
uint32_t jitter_max = _radio->getEstAirtimeFor(MAX_TRANS_UNIT) / RadioLibWrapper::JP_LBT_JITTER_DIVISOR;
return getRNG()->nextInt(0, jitter_max + 1);
}
uint32_t t = (_radio->getEstAirtimeFor(packet->getPathByteLen() + packet->payload_len + 2) * _prefs.direct_tx_delay_factor);
return getRNG()->nextInt(0, 6)*t;
return getRNG()->nextInt(0, 5*t + 1);
}
int SensorMesh::getInterferenceThreshold() const {
return _prefs.interference_threshold;

8
src/helpers/radiolib/RadioLibWrappers.cpp

@ -209,8 +209,14 @@ bool RadioLibWrapper::isChannelActive() {
}
YIELD_TASK();
}
// Channel free: reset busy counter and add airtime-scaled jitter.
// JP_LBT_JITTER_DIVISOR controls jitter upper bound:
// /8 -> SF12/BW125 ~975ms, SF7/BW62.5 ~50ms
// /16 -> SF12/BW125 ~490ms, SF7/BW62.5 ~25ms
// /32 -> SF12/BW125 ~245ms, SF7/BW62.5 ~12ms (default)
_busy_count = 0;
uint32_t jitter_until = millis() + random(0, 500);
uint32_t airtime_ms = getEstAirtimeFor(MAX_TRANS_UNIT);
uint32_t jitter_until = millis() + random(0, airtime_ms / JP_LBT_JITTER_DIVISOR);
while (millis() < jitter_until) {
YIELD_TASK();
}

2
src/helpers/radiolib/RadioLibWrappers.h

@ -57,6 +57,8 @@ public:
virtual uint8_t getCodingRate() const { return 8; } // default CR4/8, override in subclass
virtual float getFreqMHz() const { return 0.0f; } // default unknown, override in subclass
static constexpr uint8_t JP_LBT_JITTER_DIVISOR = 32;
bool isAS923_1_JP() const override {
float freq = getFreqMHz();
return (fabsf(freq - 920.800f) < 0.05f ||

Loading…
Cancel
Save