Skip to content

dis_cca: disable primary CCA (0x520[14]), not just EDCCA; streamtx default-on (#199)#303

Merged
josephnef merged 1 commit into
masterfrom
dis-cca-primary-cca-199
Jul 18, 2026
Merged

dis_cca: disable primary CCA (0x520[14]), not just EDCCA; streamtx default-on (#199)#303
josephnef merged 1 commit into
masterfrom
dis-cca-primary-cca-199

Conversation

@josephnef

Copy link
Copy Markdown
Collaborator

Summary

Resolves the TX-side question in #199. The prior measurement (#198) was RX-side (decode-through-noise → null), but the knob gates TX deferral. This adds the TX-side test #199 asked for and follows the mechanism to the effective register.

Monitor injection is not CCA-free. On-air, devourer's injection defers 40-60% of its submit rate to a co-channel 802.11 transmitter. The current DEVOURER_DIS_CCA disabled only EDCCA (0x520[15], energy detect), which is null against a decodable preamble — the gate that actually defers is primary CCA (0x520[14]), which the vendor dis_cca recipe and devourer never touched.

Measurement

Method: a co-channel RTL flooder (8812AU) as the carrier-sense trigger, with a far-channel flooder as a USB-hub-contention control. (The B210 AWGN path is too weakly coupled to the RTL front ends on the bench to trip a TX gate even at max gain — the same near-field limit #198 hit; the co-channel RTL flooder couples strongly and is rig-independent.) Metric = tx.stats submitted frames over a fixed window. tests/dis_cca_tx_onair.sh.

DUT alone co-chan, CCA on co-chan, CCA off far-chan (USB ctrl) recovery
8812EU (Jaguar3) @ 5 GHz 68344 40170 (−41%) 60562 65847 (−4%) 1.51×
8812CU (Jaguar3) @ 5 GHz 68030 25623 (−62%) 57707 64056 (−6%) 2.25×
8822BU (Jaguar2) @ 5 GHz 28004 17964 (−36%) 31043 1.73×

The far-channel control isolates USB contention (~5%), so the co-channel drop is real RF carrier-sense deferral; clearing 0x520[14] recovers it. A pure CW-tone energy source (no preamble) does not defer injection at all, confirming EDCCA was never the inject-path gate.

Changes

  • SetCcaMode (Jaguar2/3) now clears both 0x520[14] (primary CCA) and [15] (EDCCA), so injected/beacon TX punches through a busy channel instead of deferring.
  • Jaguar2 gains the disable_cca bring-up wiring it was missingDEVOURER_DIS_CCA was silently ignored on Jaguar2 injectors before (the knob only landed via the timesync runtime call).
  • streamtx (the FPV downlink) defaults it on; DEVOURER_DIS_CCA=0 opts out. The link owns the channel, so CSMA backoff only stutters it.
  • The vendor BB CCA-off writes (which deafen RX) are still not applied — the RX-decode side remains a separate null (tests/dis_cca_onair.sh).
  • Corrected the "monitor inject bypasses CCA" premise in comments and docs; new harness tests/dis_cca_tx_onair.sh.

Full build + ctest (27/27) green.

🤖 Generated with Claude Code

…fault-on (#199)

Monitor injection is not CCA-free. On-air (co-channel RTL flooder vs a
far-channel USB-contention control, tests/dis_cca_tx_onair.sh) the DUT defers
40-60% of its submit rate to a co-channel 802.11 transmitter:

  8812EU @ 5 GHz   -41%  ->  +1.51x with dis_cca
  8812CU @ 5 GHz   -62%  ->  +2.25x
  8822BU @ 5 GHz   -36%  ->  +1.73x

The existing DEVOURER_DIS_CCA disabled only EDCCA (0x520[15], energy detect),
which is null against a decodable preamble; the gate that actually defers is
primary CCA (0x520[14]). A pure CW-tone energy source does not defer injection
at all, so EDCCA was never the inject-path gate. This refutes the prior premise
that "monitor inject already bypasses the CSMA/CCA backoff."

- SetCcaMode (Jaguar2/3) now clears both 0x520[14] and [15].
- Jaguar2 gains the disable_cca bring-up wiring it was missing (the knob only
  landed via the timesync runtime call before; DEVOURER_DIS_CCA was silently
  ignored on Jaguar2 injectors).
- streamtx (FPV downlink) defaults it on; DEVOURER_DIS_CCA=0 opts out. The link
  owns the channel, so CSMA backoff only stutters it.
- The vendor BB CCA-off writes (which deafen RX) are still not applied; the RX
  decode side remains a separate null (tests/dis_cca_onair.sh).
- New TX-side harness tests/dis_cca_tx_onair.sh; corrected the "bypasses CCA"
  premise in comments and docs (IRtlDevice, DeviceConfig, CLAUDE, scheduled-mac,
  time-distribution, 8822e-quirks).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@josephnef
josephnef merged commit 0edadca into master Jul 18, 2026
18 checks passed
@josephnef
josephnef deleted the dis-cca-primary-cca-199 branch July 18, 2026 19:09
josephnef added a commit that referenced this pull request Jul 19, 2026
## Summary

Brings the `SetCcaMode`/`dis_cca` lever (#199) and the noise-floor
sensing (#201/#202) to the Wi-Fi 6 **Kestrel** HAL (RTL8852BU/8852CU) —
the generation both were left out of — and drops the
issue-number/"parity" boilerplate from the earlier #303/#304 comments
(git already records provenance).

## Kestrel features

- **`SetCcaMode` (#199)** — RMW `R_AX_CCA_CFG_0` all-CCA-EN (primary +
sec20/40/80 + EDCCA). Injection is already CCA-off by default on Kestrel
(`EnableTxScheduler` clears the gates, the ~103-stall fix), so this is
the runtime toggle rather than the co-channel-deferral fix it is on
Jaguar. `DEVOURER_DIS_CCA` wired at `InitWrite`.
- **Active absolute noise floor (#202)** — the halbb **NHM env-monitor**
via a new glue call + `GetRxEnergy` override. Frame-free, BB-driven,
**no clock-stop → no wedge** (the cleanest of any generation). Two fixes
were needed: `bb->cr_type = BB_CLIENT` (the env-monitor CR-init switch
was falling through, leaving the NHM ready-bit address 0) and a link
stub for the BE-only `halbb_get_prim_sb` (dead 11BE branch).
- **Passive `rssi−snr` floor + LinkHealth (#201)** — parse physts IE_01
SNR alongside the header RSSI, feed an `RxQualityAccumulator`,
`GetRxQuality` override.

## On-air validation

| | 8852BU (C8852B) | 8832CU (C8852C) |
|---|---|---|
| SetCcaMode | ✅ lever fires | ✅ same code |
| Active NHM floor | ✅ **−93 dBm**, frame-free (−93 on a 0-frame idle
channel), no wedge | gated null |
| Passive floor | ✅ **−94 dBm** — cross-matches NHM within ~1 dB,
HEALTHY | null |

**8852C** is gated to emit null rather than wrong values — its NHM reads
~25 dB high (idle ch149 −68 vs the 8852B's −93) and the physts IE layout
differs (16-byte drv_info) so SNR is unparsed. Both are documented
follow-ups (`docs/rx-spectrum-sensing.md`).

Build all + `ctest` 28/28 green.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant