Migrate from hsmc 0.2 (local-patched) to hsmc 0.3.0 (crates.io, with embassy + trace-defmt features). Restructure radio chart and bundle several adjacent stability changes that need to land together for soak runs. Radio chart: - Booting (default, no handlers) -> Operational (default Unconfigured; super-state owning CmdPing/CmdGetInfo/Reset/WedgeDetected handlers + Recovering + CheckRecoveryBudget) -> Dead (terminal). - Cold init's during is structurally un-cancellable. - radio_task is a 30-line shim that panics if run() returns (chart is non-terminating). - Internal queue capacity bumped 8 -> 32 to cover action-emit bursts. Host chart: - Connected splits into WaitingForFirstFrame (default, no timer) + Active (chart-owned 1s inactivity timer via on(after) + self- transition on FrameReceived). Manual Timer::after + last_frame_at removed. Soak hardening: - ld/nrf52840-memory.x: app start 0x1000 -> 0x26000 to leave the factory s140 SoftDevice dormant in flash. - hal/nrf52840.rs: dump POWER.RESETREAS on boot -- WARN on DOG/LOCKUP, INFO on RESETPIN/SREQ/wake-from-OFF. - host/usb.rs: read_packet errors discriminated -- Disabled is debug (normal during USB enum), BufferOverflow stays warn. - COBS encode warns now carry type/tag/payload-length for diagnosis. - RADIO_THROTTLED static initializes to true (no proof of host drain at boot). - driver/sh1106.rs: init retries 3x with 100ms backoff (intermittent first-write race on power-up). - Cargo.toml: unexpected_cfgs allowlist for hsmc's journal/trace-* features. docs/semtech_lora_cad_lbt_guidebook.md: vendor the Semtech CAD/LBT reference for offline lookup.
34 KiB
Semtech LoRa CAD and LBT Guidebook
How to use Channel Activity Detection (CAD), RSSI, and CAD-to-TX modes on Semtech LoRa radios
Revision: 1.0 Prepared: 2026-04-27 Audience: embedded firmware engineers implementing carrier sense, channel assessment, or listen-before-talk behavior on Semtech LoRa transceivers.
1. Executive summary
Do not implement LoRa listen-before-talk (LBT) as a blind two-command sequence such as:
SetCAD();
SetTx(); // or Send(), Radio.Send(), start TX, etc.
That is not a reliable LBT implementation. It either ignores the CAD result, races the radio state machine, or cancels the CAD decision before the host has observed it.
There are only two defensible implementation patterns:
-
Host-controlled CAD then TX
Start CAD, wait for the
CadDoneindication, inspect whetherCadDetectedwas asserted, clear the IRQ flags, optionally perform an RSSI or energy check, and only then transmit. -
Documented CAD_LBT / CAD exit-to-TX
On radio families and driver stacks that explicitly support a CAD exit mode that enters TX when CAD finds no activity, configure that mode, preload the TX payload, and start CAD. In this model, the CAD operation substitutes for the normal TX command.
The important distinction is this:
Correct: configure CAD exit mode = TX/LBT, preload payload, then SetCAD()
Incorrect: SetCAD(), then immediately SetTx()/Send()
CAD is not a general-purpose RF energy detector. CAD answers a narrower question: whether the radio detected LoRa-like activity under its current LoRa and CAD configuration. For regulatory LBT or coexistence with non-LoRa interferers, CAD is often not sufficient by itself; combine it with RSSI or energy CCA when the applicable rule or product behavior requires that.
2. Scope and assumptions
This guide covers practical CAD and LBT sequencing for the following Semtech LoRa radio families:
- SX1272/SX1276/SX1277/SX1278/SX1279 style register-based LoRa radios
- SX1261/SX1262/SX1268 class command-based radios
- LR1110/LR1120/LR1121 / LR11xx family radios
- SX1280/SX1281 2.4 GHz LoRa radios
- LLCC68, at a high level, because it is SX126x-like but should be verified against the exact datasheet and driver in use
This document is not a regulatory certification opinion. For legal LBT compliance, use the current regional standard and your test lab's interpretation for threshold, observation time, channel bandwidth, timing between assessment and TX, and duty-cycle or dwell-time constraints.
3. Key definitions
CAD: Channel Activity Detection
CAD is a LoRa modem feature that attempts to detect LoRa activity with less energy and latency than fully entering continuous receive. Its exact behavior and configurability vary by radio family.
In most LoRa use cases, CAD is used to decide whether there appears to be another LoRa signal on the configured channel before entering RX or TX.
CadDone
CadDone means the CAD operation has finished. It does not by itself mean the channel is clear or busy.
CadDetected
CadDetected means the radio detected activity according to its CAD algorithm and current configuration.
A useful firmware rule is:
CadDone && CadDetected -> LoRa activity was detected
CadDone && !CadDetected -> CAD did not detect LoRa activity
The second case does not prove that the RF channel is free of all energy or interference.
LBT: Listen Before Talk
LBT is a policy or regulatory behavior: assess a channel before transmitting, transmit only when the channel is considered clear, and back off or retry when it is busy.
CAD can be part of an LBT implementation, but CAD alone is not always a complete LBT implementation.
CCA: Clear Channel Assessment
CCA is a broader channel-clear decision. It may be based on RSSI, energy detection, CAD, packet detection, or a combination of these.
CAD exit modes
Some Semtech command-based radios let CAD automatically transition to another mode after the CAD decision:
CAD_ONLY: perform CAD and return to standbyCAD_RX: enter RX if CAD detects activityCAD_LBT,CAD_TX, orCAD_EXIT_MODE_TX: enter TX if CAD does not detect activity
Names vary by radio family and driver.
4. The two correct CAD/LBT patterns
4.1 Pattern A: host-controlled CAD then TX
This is the portable pattern and the safe default.
Use it on:
- SX127x-class radios
- SX1280/SX1281
- SX126x when you are using only the CAD behavior documented in the public SX1261/2 Rev. 2.2 datasheet
- Any driver stack where CAD-to-TX support is uncertain
Sequence:
1. Configure LoRa PHY and packet settings.
2. Configure CAD settings, if the radio exposes them.
3. Clear stale CAD IRQ flags.
4. Start CAD.
5. Wait for CadDone.
6. Read IRQ/status.
7. Clear CAD IRQ flags.
8. If CadDetected is set:
treat the channel as LoRa-busy;
back off, retry later, or enter RX.
Else:
optionally perform RSSI/energy CCA;
transmit only if the final CCA policy says clear.
Generic pseudocode:
configure_lora_phy();
configure_packet_params();
configure_cad_params_if_available();
clear_irq(CAD_DONE | CAD_DETECTED);
start_cad();
wait_for_irq(CAD_DONE);
irq = get_irq_status();
clear_irq(CAD_DONE | CAD_DETECTED);
if (irq & CAD_DETECTED) {
backoff_or_enter_rx();
} else {
if (energy_cca_required()) {
if (energy_is_clear()) {
transmit();
} else {
backoff();
}
} else {
transmit();
}
}
4.2 Pattern B: documented CAD_LBT / CAD exit-to-TX
Use this only when the exact radio and driver document a CAD exit mode that enters TX after a clear CAD decision.
Sequence:
1. Configure LoRa PHY.
2. Configure TX parameters.
3. Configure packet parameters.
4. Configure buffer base addresses, where applicable.
5. Write the TX payload into the radio buffer.
6. Configure CAD exit mode = TX/LBT.
7. Start CAD.
8. Wait for TX done, timeout, or CAD-related IRQs according to the driver.
Generic pseudocode:
configure_lora_phy();
configure_tx_params();
configure_packet_params();
configure_buffer_base_addresses();
write_tx_payload(payload, len);
set_cad_params(
cad_symbols,
cad_det_peak,
cad_det_min,
CAD_EXIT_MODE_TX, // name depends on radio/driver
tx_timeout
);
start_cad(); // this substitutes for transmit()
wait_for_completion_irq();
handle_tx_done_timeout_or_cad_status();
Do not call the normal transmit command immediately after starting CAD in this mode. The CAD operation is the transmit gate.
5. Device-family decision matrix
| Radio family | Is blind CAD; SEND valid? |
Documented CAD-to-TX? | Correct method |
|---|---|---|---|
| SX1272/SX1276/SX1277/SX1278/SX1279 style | No | No documented CAD_LBT in the SX1276/77/78/79 register model | Host-controlled CAD, wait CadDone, inspect CadDetected, then TX only if clear |
| SX1261/SX1262/SX1268 class | No | Public SX1261/2 Rev. 2.2 datasheet documents CAD_ONLY and CAD_RX; Semtech SDK also documents SX126X_CAD_LBT |
Use host-controlled CAD for datasheet-portable code; use SDK CAD_LBT only when your exact stack supports it |
| LR1110/LR1120/LR1121 / LR11xx | No | LR1121 manual documents CAD_LBT; LR11xx SDK documents TX-exit CAD mode |
Use documented CAD exit-to-TX with payload preloaded, or host-controlled CAD |
| SX1280/SX1281 | No | No CAD_LBT in the SX1280/81 datasheet flow | Host-controlled CAD, wait CadDone, inspect CadDetected, then TX only if clear |
| LLCC68 | No | Verify exact datasheet/driver | Treat as SX126x-like, but confirm supported CAD exit modes before using CAD-to-TX |
6. CAD is not the same as RF energy detection
A common implementation error is treating this condition as a complete channel-clear proof:
CadDone && !CadDetected
That condition only means CAD did not detect LoRa activity according to the radio's current CAD and LoRa configuration.
It does not guarantee that:
- no other RF signal is present;
- no FSK, BLE, Wi-Fi leakage, CW interferer, jammer, or broadband noise is present;
- another LoRa signal using a different configuration is absent;
- the channel satisfies a regional energy-based LBT rule;
- the channel will remain clear by the time TX begins.
A robust CCA policy is often:
busy if CAD detects LoRa activity
busy if RSSI/energy is above the chosen threshold
clear only if both CAD and energy checks pass
For purely LoRa-network collision avoidance, CAD alone may be acceptable in some products. For regulatory LBT, do not assume CAD alone is enough unless your standard, certification plan, and test lab agree.
7. SX127x guide
This section applies to SX1272/SX1276/SX1277/SX1278/SX1279 style register-based LoRa radios. The exact register map differs somewhat by part, but the CAD control model is the same general style.
7.1 What the radio supports
SX127x-class radios expose CAD as a radio operating mode, separate from TX and RX. In the SX1276/77/78/79 datasheet model, TX, RX single, RX continuous, and CAD are different operating modes selected through the operation-mode register.
CAD completion is reported through CAD-related IRQ flags:
CadDone: CAD operation finishedCadDetected: CAD found activity
The CAD operation returns the radio to standby after completion.
There is no documented hardware CAD-to-TX exit mode in the SX1276/77/78/79 register model. Therefore, LBT must be host-controlled.
7.2 Correct SX127x host-controlled CAD/LBT sequence
// SX127x-style pseudocode.
// Symbol names are illustrative. Use the definitions from your driver.
// 1. Configure LoRa mode and modem parameters.
set_lora_mode();
set_frequency(freq_hz);
set_spreading_factor(sf);
set_bandwidth(bw);
set_coding_rate(cr);
set_preamble_length(preamble_len);
set_payload_params(payload_len, crc_on, explicit_header);
// 2. Optionally preload TX FIFO to reduce the gap between clear CAD and TX.
load_tx_fifo(payload, payload_len);
// 3. Clear stale CAD IRQ flags.
write_reg(REG_IRQ_FLAGS, IRQ_CAD_DONE | IRQ_CAD_DETECTED);
// 4. Start CAD.
write_reg(REG_OP_MODE, MODE_LORA | MODE_CAD);
// 5. Wait for CAD completion.
while ((read_reg(REG_IRQ_FLAGS) & IRQ_CAD_DONE) == 0) {
// Poll, sleep until DIO interrupt, or service other tasks.
}
uint8_t irq = read_reg(REG_IRQ_FLAGS);
// 6. Clear CAD flags by writing 1s to those bits.
write_reg(REG_IRQ_FLAGS, IRQ_CAD_DONE | IRQ_CAD_DETECTED);
// 7. Make the LBT decision.
if (irq & IRQ_CAD_DETECTED) {
// LoRa activity was detected.
schedule_random_backoff();
// or enter RX to receive the packet, depending on your MAC.
} else {
if (rssi_cca_required() && !rssi_energy_clear()) {
schedule_random_backoff();
} else {
// FIFO was preloaded above; otherwise load it here.
write_reg(REG_OP_MODE, MODE_LORA | MODE_TX);
}
}
7.3 SX127x notes
- Clear stale CAD IRQ flags before starting a new CAD operation.
- Do not read
CadDetectedbeforeCadDoneand treat it as final. - Do not issue TX until CAD has completed and the host has evaluated the result.
- Preloading the FIFO before CAD can reduce the time between clear CAD and TX, but it does not remove the need to wait for
CadDone. - If your LBT policy must detect non-LoRa interferers, add RSSI or energy CCA.
8. SX126x guide
This section applies to SX1261/SX1262/SX1268 style command-based radios.
8.1 Datasheet-portable behavior
The public SX1261/2 Rev. 2.2 datasheet documents CAD as a LoRa-only operation that searches for LoRa preamble activity. CAD reports:
CADdoneCadDetected, if a valid signal was detected
SetCadParams includes parameters such as:
- number of CAD symbols
- detection peak threshold
- detection minimum threshold
- CAD exit mode
- CAD timeout
The public Rev. 2.2 datasheet table documents at least these exit modes:
CAD_ONLY: perform CAD and return to standbyCAD_RX: if activity is detected, enter RX
For code that must be portable to the behavior described in that datasheet, use host-controlled CAD or CAD_RX, not an assumed CAD-to-TX path.
8.2 SX126x host-controlled LBT sequence
// SX126x-style pseudocode.
// Function names vary across drivers.
wait_while_busy();
SetStandby(STDBY_RC);
wait_while_busy();
SetPacketType(PACKET_TYPE_LORA);
wait_while_busy();
SetRfFrequency(freq_hz);
wait_while_busy();
SetModulationParams(sf, bw, cr, ldro);
wait_while_busy();
SetPacketParams(preamble_len,
header_type,
payload_len,
crc_on,
iq_inverted);
wait_while_busy();
SetTxParams(tx_power_dbm, ramp_time);
wait_while_busy();
SetBufferBaseAddress(tx_base, rx_base);
wait_while_busy();
WriteBuffer(tx_base, payload, payload_len); // optional preload
wait_while_busy();
SetDioIrqParams(IRQ_CAD_DONE | IRQ_CAD_DETECTED | IRQ_TX_DONE | IRQ_TIMEOUT,
dio1_mask,
dio2_mask,
dio3_mask);
wait_while_busy();
ClearIrqStatus(IRQ_CAD_DONE | IRQ_CAD_DETECTED);
wait_while_busy();
SetCadParams(cad_symbols,
cad_det_peak,
cad_det_min,
CAD_ONLY,
0);
wait_while_busy();
SetCAD();
wait_for_irq(IRQ_CAD_DONE);
wait_while_busy();
uint16_t irq = GetIrqStatus();
wait_while_busy();
ClearIrqStatus(IRQ_CAD_DONE | IRQ_CAD_DETECTED);
if (irq & IRQ_CAD_DETECTED) {
backoff_or_enter_rx();
} else if (energy_cca_required() && !energy_is_clear()) {
backoff();
} else {
wait_while_busy();
SetTx(tx_timeout);
}
8.3 SX126x SDK CAD_LBT behavior
Semtech's SWSD003 SX126x CAD example documents SX126X_CAD_LBT. In that mode, if no activity is detected, the chip goes to TX. The same example states that this mode is a substitute for TX and that payload data should be preloaded before entering the CAD LBT mode.
Use this only when your exact driver, chip, and integration expose and support it.
// SX126x SDK-style CAD_LBT pseudocode.
wait_while_busy();
SetStandby(STDBY_RC);
wait_while_busy();
SetPacketType(PACKET_TYPE_LORA);
wait_while_busy();
SetRfFrequency(freq_hz);
wait_while_busy();
SetModulationParams(sf, bw, cr, ldro);
wait_while_busy();
SetPacketParams(preamble_len,
header_type,
payload_len,
crc_on,
iq_inverted);
wait_while_busy();
SetTxParams(tx_power_dbm, ramp_time);
wait_while_busy();
SetBufferBaseAddress(tx_base, rx_base);
// Required before CAD_LBT, because CAD_LBT substitutes for SetTx().
wait_while_busy();
WriteBuffer(tx_base, payload, payload_len);
wait_while_busy();
SetDioIrqParams(IRQ_CAD_DONE | IRQ_CAD_DETECTED | IRQ_TX_DONE | IRQ_TIMEOUT,
dio1_mask,
dio2_mask,
dio3_mask);
wait_while_busy();
ClearIrqStatus(IRQ_CAD_DONE | IRQ_CAD_DETECTED | IRQ_TX_DONE | IRQ_TIMEOUT);
wait_while_busy();
SetCadParams(cad_symbols,
cad_det_peak,
cad_det_min,
SX126X_CAD_LBT,
tx_timeout);
wait_while_busy();
SetCAD(); // This is the gated TX attempt.
// Do not immediately call SetTx() here.
// Wait for the completion indication defined by your driver.
8.4 SX126x notes
- Always respect the
BUSYline before sending commands. - Treat
cadDetPeakandcadDetMinas parameters requiring validation for your SF, bandwidth, packet timing, and false-detection tolerance. - If using
CAD_LBT, preload the payload and TX configuration before starting CAD. - If using only the public Rev. 2.2 datasheet behavior, do not assume
CAD_LBTexists. - For regulatory LBT, add RSSI or energy assessment when required.
9. LR11xx / LR1121 guide
This section applies to LR1110/LR1120/LR1121 family radios at a high level, with the strongest direct documentation in this guide coming from the LR1121 user manual and the Semtech LR11xx SDK example.
9.1 What the radio supports
The LR1121 manual documents CAD as a LoRa operation that reports:
CADdoneCadDetected, when valid activity is found
Its CAD parameters include:
- number of symbols
- detection peak threshold
- detection minimum threshold
- CAD exit mode
- timeout
The LR1121 manual documents these CAD exit modes:
CAD_ONLY: after CAD, return to standbyCAD_RX: if activity is detected, stay in RX until packet or timeoutCAD_LBT: if no activity is detected, enter TX mode
For CAD_LBT, the timeout is interpreted as the TX timeout.
Semtech's LR11xx SDK CAD example similarly documents a TX-exit CAD mode and states that the payload should be preloaded because this mode substitutes for TX.
9.2 LR11xx CAD_LBT sequence
// LR11xx/LR1121-style pseudocode.
// Function and enum names vary by driver.
SetPacketType(PACKET_TYPE_LORA);
SetRfFrequency(freq_hz);
SetModulationParams(sf, bw, cr, ldro);
SetPacketParams(preamble_len,
header_type,
payload_len,
crc_on,
iq_inverted);
SetTxParams(tx_power_dbm, ramp_time);
SetBufferBaseAddress(tx_base, rx_base);
WriteBuffer(tx_base, payload, payload_len); // Required before CAD-to-TX
SetDioIrqParams(IRQ_CAD_DONE | IRQ_CAD_DETECTED | IRQ_TX_DONE | IRQ_TIMEOUT,
dio1_mask,
dio2_mask,
dio3_mask);
ClearIrqStatus(IRQ_CAD_DONE | IRQ_CAD_DETECTED | IRQ_TX_DONE | IRQ_TIMEOUT);
SetCadParams(cad_symbols,
cad_det_peak,
cad_det_min,
CAD_LBT,
tx_timeout);
SetCAD(); // If CAD is clear, the radio enters TX.
wait_for_completion_irq();
9.3 LR11xx notes
- Do not use
SetCAD(); SetTx();as a substitute forCAD_LBT. - Preload the payload before starting CAD_LBT.
- Verify the exact enum names and behavior for LR1110/LR1120/LR1121 in the driver version you ship.
- If certification matters, verify the behavior against the exact firmware, radio revision, and regional rules.
10. SX1280/SX1281 guide
This section applies to SX1280/SX1281 2.4 GHz LoRa radios.
10.1 What the radio supports
The SX1280/81 datasheet describes SetCAD() as a LoRa operation that searches for a LoRa signal. It returns to standby after the search and reports:
CadDoneCadDetected, if a valid signal was found
SetCadParams() for SX1280/SX1281 selects the number of CAD symbols. Supported values include 1, 2, 4, 8, and 16 symbols. The datasheet warns that using very small symbol counts, especially 1 or 2 symbols, increases false-detection risk.
The SX1280/81 datasheet flow does not document a CAD-to-TX exit mode analogous to LR1121 CAD_LBT.
10.2 Correct SX128x host-controlled sequence
// SX1280/SX1281-style pseudocode.
SetPacketType(PACKET_TYPE_LORA);
SetRfFrequency(freq_hz);
SetModulationParams(sf, bw, cr);
SetPacketParams(preamble_len,
header_type,
payload_len,
crc_on,
iq_inverted);
SetTxParams(tx_power_dbm, ramp_time);
SetBufferBaseAddress(tx_base, rx_base);
WriteBuffer(tx_base, payload, payload_len); // optional preload
SetCadParams(LORA_CAD_04_SYMBOLS); // choose based on robustness/latency
SetDioIrqParams(IRQ_CAD_DONE | IRQ_CAD_DETECTED | IRQ_TX_DONE | IRQ_TIMEOUT,
dio1_mask,
dio2_mask,
dio3_mask);
ClearIrqStatus(IRQ_CAD_DONE | IRQ_CAD_DETECTED);
SetCAD();
wait_for_irq(IRQ_CAD_DONE);
irq = GetIrqStatus();
ClearIrqStatus(IRQ_CAD_DONE | IRQ_CAD_DETECTED);
if (irq & IRQ_CAD_DETECTED) {
backoff_or_enter_rx();
} else if (energy_cca_required() && !energy_is_clear()) {
backoff();
} else {
SetTx(tx_timeout);
}
10.3 SX128x notes
- Use host-controlled CAD for LBT.
- Avoid relying on one-symbol or two-symbol CAD unless your testing shows the false-detection behavior is acceptable.
- Add an energy check when non-LoRa interferers or regulatory LBT matter.
11. LLCC68 note
LLCC68 is SX126x-like in its command structure, but this guide does not assert a universal LLCC68 CAD-to-TX behavior. Verify the exact LLCC68 datasheet and driver you are using.
Safe default:
Use host-controlled CAD:
SetCadParams(...)
SetCAD()
wait CadDone
inspect CadDetected
TX only if clear
Use CAD-to-TX only if your exact LLCC68 documentation and driver explicitly define it.
12. RSSI plus CAD
12.1 Why RSSI may still be needed
CAD is useful because LoRa signals can be difficult to assess with simple RSSI, especially when they are near or below the apparent receiver noise floor. However, CAD is not an energy detector for every possible interferer.
Use RSSI or energy CCA when you need to detect:
- non-LoRa transmitters;
- strong out-of-network interferers;
- continuous wave or broadband noise;
- signals using configurations your CAD settings may not detect;
- energy-based regulatory occupancy.
12.2 Conservative CCA decision
A conservative channel decision is:
bool channel_busy = false;
if (cad_detected) {
channel_busy = true;
}
if (energy_cca_required() && rssi_or_energy_above_threshold()) {
channel_busy = true;
}
if (channel_busy) {
backoff();
} else {
transmit();
}
Or, as a truth table:
| CAD result | RSSI/energy result | Conservative decision |
|---|---|---|
| CAD detected | Any | Busy |
| CAD clear | Energy high | Busy |
| CAD clear | Energy low | Clear |
| CAD clear | Energy not measured | Clear only if your policy allows CAD-only CCA |
12.3 RSSI during CAD
Semtech application note AN1200.21 describes reading RSSI during CAD on SX127x/SX1272-era radios. The idea is to start CAD, wait for the appropriate CAD startup and symbol timing point, read RSSI while the radio is effectively observing the channel, then wait for CAD completion.
This can combine a LoRa CAD decision and an RSSI sample with relatively low energy cost. Treat the timing and thresholds as implementation details that must be validated for the target radio, driver, bandwidth, spreading factor, and regional rule.
13. CAD parameter selection
13.1 CAD symbol count
Increasing the number of CAD symbols generally improves detection confidence and reduces false decisions, at the cost of more time and energy.
Lower symbol counts reduce latency and power but increase risk:
- missed detection;
- false detection;
- less reliable behavior at low SNR;
- poorer LBT decisions under marginal conditions.
For radios that expose symbol count, validate the chosen value under realistic network traffic and interference.
13.2 Detection thresholds
SX126x and LR11xx-style radios expose CAD detection threshold parameters such as detection peak and detection minimum.
Do not blindly copy threshold values across products. The correct operating point can depend on:
- spreading factor;
- bandwidth;
- expected SNR;
- preamble length;
- traffic timing;
- antenna and RF front-end behavior;
- false-alarm tolerance;
- missed-detection tolerance;
- whether CAD is used for RX wakeup, collision avoidance, or regulatory LBT support.
13.3 Time gap between CAD clear and TX
Host-controlled CAD always has a gap between CAD completion and transmit start. During that gap, another node may begin transmitting. Reduce the gap by:
- preloading the TX buffer before CAD;
- preconfiguring TX parameters before CAD;
- servicing the CAD IRQ promptly;
- using a documented CAD-to-TX mode where available;
- applying random backoff in multi-node networks.
Even CAD_LBT does not make collisions impossible. It only reduces the assessment-to-TX gap and lets the radio perform the transition according to its documented state machine.
14. Recommended implementation checklist
Before CAD:
- Put the radio in the required standby or command-ready state.
- Configure packet type to LoRa.
- Configure RF frequency.
- Configure LoRa modulation parameters: spreading factor, bandwidth, coding rate, and low-data-rate optimization where applicable.
- Configure packet parameters needed for the subsequent RX/TX path.
- Configure TX power, ramp, and PA settings if TX may follow CAD.
- Configure buffer base addresses where applicable.
- Preload TX payload if using CAD_LBT or if minimizing CAD-to-TX delay.
- Configure CAD parameters.
- Configure IRQ routing for
CadDone,CadDetected,TxDone, and timeout as needed. - Clear stale IRQ flags.
- Respect the
BUSYline on command-based radios.
During CAD:
- Do not issue TX until CAD is complete, unless the radio is in a documented CAD_LBT mode.
- Wait for
CadDoneor the driver's completion callback. - Do not treat intermediate IRQ state as the final CAD decision.
After CAD:
- Read IRQ/status.
- Clear CAD IRQ flags.
- If
CadDetected, back off or enter RX. - If not detected, optionally perform RSSI/energy CCA.
- Transmit only when your final CCA/LBT policy says clear.
- Wait for
TxDoneor timeout. - Clear TX-related IRQs.
For CAD_LBT:
- Confirm the exact chip and driver support TX-exit CAD.
- Preload the payload before starting CAD.
- Configure the CAD exit timeout as the TX timeout if required by the radio.
- Do not immediately call
SetTx()afterSetCAD(). - Handle the completion IRQs exactly as specified by the driver.
15. Common incorrect implementations
15.1 Blind CAD then send
Incorrect:
SetCAD();
Send(payload);
Why it is wrong:
- It does not wait for
CadDone. - It does not inspect
CadDetected. - It may cancel or override CAD.
- It does not implement channel assessment.
15.2 Polling CadDetected without waiting for CadDone
Incorrect:
SetCAD();
if (!(GetIrqStatus() & IRQ_CAD_DETECTED)) {
SetTx(timeout);
}
Why it is wrong:
CadDetectedis meaningful as a CAD result only after CAD has completed.- Before
CadDone, absence ofCadDetectedis not a final clear-channel indication.
15.3 Using CAD as a universal energy detector
Incorrect assumption:
No CadDetected means no RF energy is present.
Why it is wrong:
- CAD is LoRa-specific and configuration-dependent.
- Non-LoRa interferers may not be detected by CAD.
- Regulatory LBT may require energy measurement rather than LoRa activity detection.
15.4 Using CAD_LBT without preloading the payload
Incorrect:
SetCadParams(..., CAD_LBT, timeout);
SetCAD();
WriteBuffer(payload); // too late
Why it is wrong:
- In CAD-to-TX modes, CAD is the gated transmit attempt.
- The radio may enter TX immediately after a clear CAD decision.
- The payload and TX parameters must already be ready.
15.5 Assuming SX126x datasheet and SDK expose identical CAD modes
Incorrect assumption:
Every SX126x stack has CAD_LBT because a Semtech SDK example mentions it.
Why it is risky:
- The public SX1261/2 Rev. 2.2 datasheet table documents
CAD_ONLYandCAD_RX. - Semtech's SDK documents
SX126X_CAD_LBT. - Your product should verify the exact driver, silicon, and documentation you rely on.
16. Testing and validation plan
16.1 Functional tests
Test at minimum:
- CAD clear channel -> TX occurs
- CAD busy channel -> TX is suppressed
- CAD busy channel with random backoff -> retry later
- stale CAD IRQ flags cleared before CAD start
CadDonewithoutCadDetectedhandled correctlyCadDonewithCadDetectedhandled correctly- TX timeout handled correctly
- TX done handled correctly
- BUSY-line handling on command-based radios
16.2 RF tests
Test with:
- same SF/BW LoRa interferer;
- different SF or bandwidth LoRa interferer;
- short preamble packets;
- long preamble packets;
- packets already in progress;
- weak signals near sensitivity;
- strong adjacent-channel signals;
- non-LoRa interferers;
- noise or CW interference;
- multiple nodes attempting CAD/LBT simultaneously.
16.3 Parameter sweep
Sweep:
- CAD symbol count;
cadDetPeakandcadDetMin, where available;- RSSI threshold;
- RSSI observation time;
- random backoff window;
- time between CAD clear and TX;
- payload length and preamble length.
Measure:
- missed detection rate;
- false detection rate;
- collision rate;
- channel access latency;
- energy consumption;
- throughput;
- fairness between nodes.
16.4 Regulatory validation
For regulatory LBT, record:
- applicable region and rule version;
- required channel observation time;
- required energy threshold;
- bandwidth over which energy is assessed;
- maximum allowed delay between clear assessment and TX;
- random backoff requirements;
- maximum channel occupancy time;
- test-lab interpretation;
- final firmware version and radio driver commit.
17. Practical decision tree
Do you need to transmit only if LoRa activity is absent?
Yes:
Does your exact radio/driver document CAD_LBT or CAD exit-to-TX?
Yes:
Preload TX payload.
Configure CAD exit mode = TX/LBT.
Start CAD.
Do not call SetTx immediately after SetCAD.
No:
Start CAD.
Wait CadDone.
If CadDetected, back off.
If not CadDetected, transmit.
Do you need to satisfy energy-based LBT or detect non-LoRa interferers?
Yes:
Add RSSI/energy CCA.
Treat channel as busy if either CAD detects activity or energy is high.
No:
CAD-only may be acceptable for LoRa collision avoidance, after testing.
18. Final rules of thumb
- Never treat
SetCAD(); SetTx();as LBT. - Wait for
CadDonebefore using the CAD result. - Treat
CadDetectedas LoRa activity, not generic RF energy. - Use RSSI/energy CCA when non-LoRa interference or regulation matters.
- Preload the payload before using CAD_LBT or CAD exit-to-TX.
- Use CAD_LBT only when the exact chip and driver document it.
- Tune CAD thresholds and symbol counts with RF testing, not assumptions.
- Clear stale IRQs before and after CAD.
- Respect the command-radio
BUSYline. - Validate timing from clear assessment to TX.
Appendix A: Diffs from the initial informal answer
The initial informal answer was directionally correct but needed tightening. The final guidebook makes these changes:
- Replaces the broad statement "Semtech radios do not support single CAD then SEND" with the precise rule: blind
CAD; SENDis wrong, but documented CAD exit-to-TX modes exist on some families and stacks. - Separates host-controlled CAD from hardware/driver CAD_LBT.
- Clarifies that SX1261/2 Rev. 2.2 datasheet documentation and Semtech SDK examples are not identical: the datasheet table documents
CAD_ONLYandCAD_RX; the SDK documentsSX126X_CAD_LBT. - Clarifies that LR1121 explicitly documents
CAD_LBT, and LR11xx SDK examples document TX-exit CAD modes. - Removes the implication that configuring a sync word is part of CAD detection itself. Configure packet and sync settings for the RX/TX path, but CAD is not a full packet validation step.
- Strengthens the distinction between CAD and RSSI/energy CCA.
- Adds implementation checklists, wrong-pattern examples, and validation tests.
Appendix B: References
- Semtech SX1276/77/78/79 datasheet PDF mirror
- Semtech SX1261/2 Rev. 2.2 datasheet PDF mirror
- Semtech SWSD003 SX126x CAD example README
- Semtech LR1121 user manual mirror
- Semtech SWSD003 LR11xx CAD example README
- Semtech SX1280/SX1281 Rev. 3.2 datasheet PDF mirror
- Semtech AN1200.21, Reading Channel RSSI During a CAD
- Semtech LLCC68 datasheet section mirror: SetCadParams
Appendix C: Minimal one-page implementation recipe
Use this when you need the shortest practical firmware rule.
For SX127x/SX128x or portable SX126x code:
configure LoRa PHY and TX packet
optionally preload TX buffer
clear CAD IRQs
start CAD
wait CadDone
read IRQs
clear CAD IRQs
if CadDetected:
backoff or RX
else:
if RSSI/energy CCA required and energy is high:
backoff
else:
TX
For LR1121/LR11xx or supported SX126x CAD_LBT:
confirm exact driver/chip supports CAD exit-to-TX
configure LoRa PHY and TX packet
preload TX payload
configure CAD exit mode = TX/LBT
start CAD
do not issue SetTx immediately
let radio enter TX only if CAD is clear