Add Japan LoRa LBT compliance (ARIB STD-T108) with runtime frequency detection#2218
Open
jirogit wants to merge 13 commits intomeshcore-dev:devfrom
Open
Add Japan LoRa LBT compliance (ARIB STD-T108) with runtime frequency detection#2218jirogit wants to merge 13 commits intomeshcore-dev:devfrom
jirogit wants to merge 13 commits intomeshcore-dev:devfrom
Conversation
JP_STRICT limits MAX_TEXT_LEN to 1*CIPHER_BLOCK_SIZE (16 bytes) to keep TX time under 4 seconds on SF12/BW125/CR4-8 (Japan LoRa settings). SF12/BW125/CR4-8 airtime: 60 bytes total packet = ~3809ms (within 4s limit) packet overhead ~44 bytes, leaving 16 bytes for text payload Enabled only for WioTrackerL1 and RAK_WisMesh_Tag builds.
Under JP_STRICT mode, add energy-based carrier sensing loop before CAD:
- Sample RSSI continuously for >= 5ms before each TX attempt
- If RSSI exceeds threshold at any point, trigger random backoff
- ARIB STD-T108 requires energy-based sensing; LoRa CAD alone is
insufficient as it only detects LoRa preambles
This satisfies the minimum 5ms continuous sensing requirement for
the 920.6-922.2 MHz zone (specified low power radio, LBT mode).
Test results (JP LoRa SF12/BW125/CR4-8, simultaneous DM):
- 16-char: 2/2 success, delivered within 1:03-1:50
- 1-char: 3/4 success, delivered within 0:46-2:11
(shorter airtime reduces RSSI detection window)
Replace relative threshold (_noise_floor + _threshold) with absolute -80dBm as specified by ARIB STD-T108 for carrier sense detection. Previous relative threshold (~-99dBm) caused false busy detection from environmental noise. -80dBm matches the legal requirement and reduces spurious backoff.
MAX_TEXT_LEN is automatically selected based on the LORA_CR build flag defined in platformio.ini (e.g. -D LORA_CR=5). CR4/5: 48 bytes (~16 JP chars, TX ~3808ms) CR4/6: 32 bytes (~10 JP chars) CR4/7: 24 bytes (~8 JP chars) CR4/8: 16 bytes (~5 JP chars, default) To enable CR4/5 for Japan, add -D LORA_CR=5 to your board's build_flags in platformio.ini. Set LORA_CR=5 for WioTrackerL1 and RAK WisMesh Tag.
Instead of compile-time LORA_CR define, MAX_TEXT_LEN is now determined at runtime by reading the actual coding rate from the radio hardware. Added getMaxTextLen() to RadioLibWrapper and Dispatcher: - CR4/5: 48 bytes (~16 JP chars, TX ~3808ms) - CR4/6: 32 bytes (~10 JP chars) - CR4/7: 24 bytes (~8 JP chars) - CR4/8: 16 bytes (~5 JP chars, default) getCodingRate() added to CustomSX1262Wrapper to read codingRate from RadioLib PhysicalLayer at runtime. Tested: 48-byte limit with LORA_CR=5, 16-byte limit with LORA_CR=8.
Replace fixed random(8000-22000ms) backoff with exponential backoff: - 1st busy: 3-6s - 2nd busy: 6-12s - 3rd+ busy: 12-20s (capped) - Reset counter on channel free Results (48-byte simultaneous DM, JP SF12/BW125/CR4-5): - 3/3 success, delivered within 0:23-0:45 - Previous fixed backoff: 1:03-3:55
LR1110 has codingRate as protected field in LR_common.h, so getCodingRate() is implemented in CustomLR1110 class directly, and exposed via CustomLR1110Wrapper override. This enables dynamic MAX_TEXT_LEN calculation for T1000-E under JP_STRICT mode.
JP LBT mode now activates automatically based on operating frequency: - CH25: 920.800MHz - CH26: 921.000MHz - CH27: 921.200MHz (ARIB STD-T108, 200kHz grid) Changes: - Add isJapanMode() to RadioLibWrapper using getFreqMHz() - Add getFreqMHz() to CustomSX1262Wrapper and CustomLR1110Wrapper - Remove #ifdef JP_STRICT throughout, replaced by isJapanMode() - Remove -D JP_STRICT build flag from platformio.ini - MAX_TEXT_LEN dynamically determined by CR at runtime via getMaxTextLen() No build flags required: JP compliance activates automatically when device is configured to Japan 3 frequencies.
_tx_start_ms and TX duration logging were added for 4-second airtime verification and are no longer needed.
- Replace vTaskDelay(1) with YIELD_TASK() macro for platform compatibility (FreeRTOS: vTaskDelay, others: delay) - Make getCodingRate() and getFreqMHz() non-pure virtual with defaults (default CR4/8, default freq 0.0f for unknown platforms) - Add getCodingRate() and getFreqMHz() to CustomSTM32WLxWrapper All environments now build successfully.
…GroupTextLen() Measured actual TimeOnAir via RadioLib getTimeOnAir() on RAK WisMesh Tag (SF12/BW125, CR4/5-8) to verify ARIB STD-T108 4-second TX limit compliance. DM limits (getMaxTextLen): CR4/5: 64 bytes (3874ms) CR4/6: 48 bytes (3874ms) CR4/7: 32 bytes (3678ms) CR4/8: 24 bytes (3547ms) Channel message limits (getMaxGroupTextLen): CR4/5: 64 bytes (3710ms) CR4/6: 48 bytes (3678ms) CR4/7: 39 bytes (3907ms) CR4/8: 29 bytes (3809ms) DM and channel packets differ by 1 byte overhead, warranting separate limits for CR4/7 and CR4/8. Non-JP returns default 160 bytes unchanged. Also apply dynamic limit to sendCommandData() and sendGroupMessage() via getMaxTextLen()/getMaxGroupTextLen() instead of hardcoded MAX_TEXT_LEN.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2079
Summary
This PR implements Listen-Before-Talk (LBT) for Japan LoRa operation, as required by ARIB STD-T108 / Giteki (技適) certification. Activation is automatic based on operating frequency — no build flags required.
Changes
Radio accessor methods (RadioLibWrappers.h/cpp, Wrapper classes):
getCodingRate()— returns current LoRa coding rate at runtimegetFreqMHz()— returns operating frequency in MHzgetMaxTextLen()— returns dynamic DM message length limit based on CRgetMaxGroupTextLen()— returns dynamic channel message length limit based on CRisJapanMode()— returns true when operating on JP LoRa frequencies (920.800 / 921.000 / 921.200 MHz)Japan LBT (BaseChatMesh.cpp, RadioLibWrappers.cpp):
getTimeOnAir()on RAK WisMesh Tag (SF12/BW125):DM and channel packets differ by 1 byte overhead, warranting separate limits for CR4/7 and CR4/8. Non-JP returns default bytes unchanged.
Build:
YIELD_TASK()macro)Note on commit history
Early commits include CAD-based channel detection based on weebl2000's work (PR #1727). This was subsequently replaced with RSSI-based LBT, as ARIB STD-T108 requires energy detection, not LoRa preamble detection. The final code does not use CAD. The commit history reflects this exploration path.
Testing
Devices: RAK WisMesh Tag (SX1262), Wio Tracker L1 Pro (SX1262)
Settings: SF12 / BW125 / CR4-8 (JP standard)
16-byte simultaneous DM: 3/3 success
48-byte simultaneous DM: 3/3 success
Channel messages: all CR rates confirmed (CR4/5–CR4/8).
Effective text limit is (channel_limit - 2 - sender_name_length) bytes,
where 2 bytes are consumed by the ": " separator.
Example (8-byte sender name): CR4/5=54B, CR4/6=38B, CR4/7=29B, CR4/8=19B
Known limitations
getMaxTextLen()/getMaxGroupTextLen()to the UI layer and is left for a follow-up.