JP LBT: prevent forced TX during backoff, no CAD timeout in Japan mode

Dispatcher's default 4-second getCADFailMaxDuration() would trigger
forced transmission before JP LBT backoff completes (max 16s), violating
ARIB STD-T108 which prohibits TX while channel is busy.

- Add isJapanMode() virtual method to Radio base class (Dispatcher.h)
- Override getCADFailMaxDuration() in all Mesh subclasses to return
  UINT32_MAX in Japan mode — no forced TX, channel must be free
- Default non-JP behavior unchanged (4000ms)

If ambient noise exceeds -80dBm, TX is blocked indefinitely. Users can
monitor noise floor via companion app: menu (⋮) -> Tools -> Noise Floor.
This commit is contained in:
jirogit 2026-04-17 01:02:05 -07:00
parent 9e03dc6366
commit e01c6a5a29
5 changed files with 18 additions and 0 deletions

View file

@ -150,6 +150,10 @@ protected:
uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const override;
uint32_t calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t path_len) const override;
uint32_t getCADFailMaxDuration() const override {
if (_radio->isJapanMode()) return UINT32_MAX; // JP LBT: no forced TX — channel must be free per ARIB STD-T108
return Dispatcher::getCADFailMaxDuration();
}
void onSendTimeout() override;
// DataStoreHost methods

View file

@ -142,6 +142,10 @@ protected:
void logTx(mesh::Packet* pkt, int len) override;
void logTxFail(mesh::Packet* pkt, int len) override;
int calcRxDelay(float score, uint32_t air_time) const override;
uint32_t getCADFailMaxDuration() const override {
if (_radio->isJapanMode()) return UINT32_MAX; // JP LBT: no forced TX — channel must be free per ARIB STD-T108
return Dispatcher::getCADFailMaxDuration();
}
uint32_t getRetransmitDelay(const mesh::Packet* packet) override;
uint32_t getDirectRetransmitDelay(const mesh::Packet* packet) override;

View file

@ -130,6 +130,11 @@ protected:
void logTxFail(mesh::Packet* pkt, int len) override;
int calcRxDelay(float score, uint32_t air_time) const override;
uint32_t getCADFailMaxDuration() const override {
if (_radio->isJapanMode()) return UINT32_MAX; // JP LBT: no forced TX — channel must be free per ARIB STD-T108
return Dispatcher::getCADFailMaxDuration();
}
const char* getLogDateTime() override;
uint32_t getRetransmitDelay(const mesh::Packet* packet) override;
uint32_t getDirectRetransmitDelay(const mesh::Packet* packet) override;

View file

@ -116,6 +116,10 @@ protected:
float getAirtimeBudgetFactor() const override;
bool allowPacketForward(const mesh::Packet* packet) override;
int calcRxDelay(float score, uint32_t air_time) const override;
uint32_t getCADFailMaxDuration() const override {
if (_radio->isJapanMode()) return UINT32_MAX; // JP LBT: no forced TX — channel must be free per ARIB STD-T108
return Dispatcher::getCADFailMaxDuration();
}
uint32_t getRetransmitDelay(const mesh::Packet* packet) override;
uint32_t getDirectRetransmitDelay(const mesh::Packet* packet) override;
int getInterferenceThreshold() const override;

View file

@ -40,6 +40,7 @@ public:
virtual int getMaxTextLen() const { return 10 * 16; } // default: non-JP
virtual int getMaxGroupTextLen() const { return 10 * 16; } // default: non-JP
virtual bool isJapanMode() const { return false; } // default: non-JP
/**
* \brief starts the raw packet send. (no wait)