Skip to content

F2: BB-dbgport reader framework + dead-end documentation (DEVOURER_RX_DUMP_CSI)#92

Merged
josephnef merged 1 commit into
masterfrom
bb-dbgport-csi
Jun 7, 2026
Merged

F2: BB-dbgport reader framework + dead-end documentation (DEVOURER_RX_DUMP_CSI)#92
josephnef merged 1 commit into
masterfrom
bb-dbgport-csi

Conversation

@josephnef

Copy link
Copy Markdown
Collaborator

Summary

Ships the framework for per-subcarrier IQ capture via the BB debug port — but not the capture itself, because the per-subcarrier selector is missing from the vendored sources. Documents the dead-end and the path that would unblock it.

This is the "acceptable case" the plan called out for F2:

Acceptable case: the dbgport sequence is documented but the chip doesn't expose per-subcarrier IQ → the PR ships the framework + a tools/precoder/README.md section explaining the dead-end, no behaviour change in demo/main.cpp (default off).

What works

src/BbDbgportReader.{h,cpp} wraps the canonical dbgport pattern from the only in-tree user (hal/rtl8814a/rtl8814a_phycfg.c:460-545, phy_ADC_CLK_8814A on A-cut 8814A):

saved = rtw_read32(0x8FC);
rtw_write32(0x8FC, selector);
value = rtw_read32(0xFA0);
rtw_write32(0x8FC, saved);
if (!is_chip_alive()) wedge();

is_chip_alive() reads REG_SYS_CFG and bails if poisoned. Once wedged, the reader refuses further writes — loud failure rather than silently corrupting samples.

DEVOURER_RX_DUMP_CSI=hex,hex,... drives a selector sweep on the first 8 canonical-SA RX frames in demo/main.cpp:

<devourer-csi>hit=N selector=0x.... value=0x........
<devourer-csi-wedged>after selector=0x....    # only on wedge

tools/precoder/csi_dump.py parses the log and classifies each selector as STATIC / SINGLE-BIT (flag) / PARTIAL (counter) / DYNAMIC (wide-bit bus — IQ candidate).

What doesn't work, and why

The selector that routes post-FFT per-subcarrier IQ to 0xFA0 is in Realtek's phydm source (phydm_dbgport_sel and friends), which is NOT vendored in this tree — hal/phydm/ carries only BB/AGC/RF init tables.

Without the selector catalogue, sweeping random selectors gives raw BB internals (status flags, clock-domain bits, MAC_Active markers) but not IQ samples.

Hardware verification (chip survives, framework live, no IQ found)

TX = RTL8812AU (0bda:8812), RX = TP-Link RTL8821AU (2357:0120), channel 6. DEVOURER_RX_DUMP_CSI=0x0,0x1,0x10,0x40,0xa0.

40 <devourer-csi> lines emitted (8 frames × 5 selectors)
0  <devourer-csi-wedged> events
300 additional RX frames after the sweep completed (save/restore on 0x8FC kept the RX path intact)

csi_dump.py classification:

selector    n  unique        mean       toggle/32  classification
0x00000000  8       2  2085650432               1  SINGLE-BIT (flag/clock)
0x00000001  8       1   127926273               0  STATIC (status flag / const)
0x00000010  8       2  2081456128               1  SINGLE-BIT (flag/clock)
0x00000040  8       2  2082504704               1  SINGLE-BIT (flag/clock)
0x000000a0  8       2  2082504704               1  SINGLE-BIT (flag/clock)

All 5 selectors return values dominated by a static 0x7c008000 pattern with just one bit toggling — classic status-flag signal. No wide-bit bus among them. Exactly the framework-in-tree-but-IQ-out-of-reach state the plan called the "acceptable case".

What would unblock real capture (separate, future work)

  1. Vendoring (or rediscovering) Realtek's phydm dbgport selector catalogue — typically dumped via rtwpriv on a reference platform.
  2. Or: implementing the 0x95C ADC-DMA path (rDMA_trigger_Jaguar2). Raw ADC samples at full bandwidth + off-chip 64-point FFT recovers per-subcarrier IQ. Bigger scope (FW mailbox + DMA buffer readout), separate PR.

Until one of those lands, this tier stays framework in tree, capture out of reach. Both BbDbgportReader.h and the new tools/precoder/README.md "Tier 4 — current status" section carry the same warning.

What ships

  • src/BbDbgportReader.{h,cpp} — save/restore wrapper + chip-alive check + self-wedging.
  • src/RtlJaguarDevice.{h,cpp}read_bb_dbgport(selector) + bb_dbgport_wedged() accessors.
  • demo/main.cppDEVOURER_RX_DUMP_CSI=hex,hex,... selector-sweep on first 8 canonical-SA frames.
  • tools/precoder/csi_dump.py — log parser + classifier.
  • tools/precoder/README.md — "Tier 4 — current status" section documenting the dead-end and the unblocking paths.
  • CMakeLists.txtWiFiDriver includes BbDbgportReader.cpp.

Brick-risk caveats (in PR description for visibility)

  • Touching 0x8FC while RX is live can stall demod state machines (cf. MAC_Active busy-wait at rtl8814a_phycfg.c:475-479). The save/restore wrapper is the safest pattern but not a guarantee. On hardware, the 8821AU survived a 5-selector sweep cleanly — but treat new chips/selectors as destructive until proven otherwise.
  • Default off. No behaviour change when DEVOURER_RX_DUMP_CSI is unset.
  • Recovery ladder if a sweep wedges the chip: libusb_reset_deviceusbreset → power-cycle.

Test plan

  • cmake --build build -j clean across all 5 demo binaries
  • Hardware: 5-selector sweep on 8821AU → 40 <devourer-csi> lines, 0 wedge events, 300 follow-up RX frames (chip survived)
  • csi_dump.py reports the captured selectors honestly as STATIC / SINGLE-BIT (no IQ candidate among them, confirming the dead-end)
  • Default behaviour (env var unset) unchanged

🤖 Generated with Claude Code

…_DUMP_CSI)

Ships the *framework* for per-subcarrier IQ capture via the BB debug port,
but NOT the capture itself — the per-subcarrier selector is missing from
the vendored sources. Documents the dead-end and the path that would
unblock it.

What works:

  src/BbDbgportReader.{h,cpp} wraps the canonical dbgport pattern that
  the only in-tree user (hal/rtl8814a/rtl8814a_phycfg.c:460-545,
  phy_ADC_CLK_8814A on A-cut 8814A) follows:

    save  = rtw_read32(0x8FC)
    rtw_write32(0x8FC, selector)
    value = rtw_read32(0xFA0)
    rtw_write32(0x8FC, save)
    if !is_chip_alive(): wedge

  is_chip_alive() reads REG_SYS_CFG and bails if the chip is poisoned.
  Once wedged, the reader refuses further writes — loud failure rather
  than silently corrupting samples. RtlJaguarDevice exposes
  read_bb_dbgport(selector) and bb_dbgport_wedged().

  DEVOURER_RX_DUMP_CSI=hex,hex,... drives a selector sweep on the first
  8 canonical-SA RX frames in demo/main.cpp; output:

    <devourer-csi>hit=N selector=0x.... value=0x........
    <devourer-csi-wedged>after selector=0x....

  tools/precoder/csi_dump.py parses the log and classifies each
  selector as STATIC / SINGLE-BIT (flag) / PARTIAL (counter) / DYNAMIC
  (wide-bit bus — IQ candidate).

What doesn't work, and why:

  The selector that routes post-FFT per-subcarrier IQ to 0xFA0 is in
  Realtek's phydm source (phydm_dbgport_sel and friends), which is NOT
  vendored in this tree — hal/phydm/ carries only BB/AGC/RF init tables.

  Without the selector catalogue, sweeping random selectors gives raw
  BB internals (status flags, clock-domain bits, MAC_Active markers)
  but not the IQ samples the precoder README "Tier 4" wants.

  The 0x95C ADC-DMA path (rDMA_trigger_Jaguar2) stays on the to-do
  list — it gives raw ADC samples but needs an FW-mailbox dance and
  DMA-buffer readout that's also not in-tree.

Hardware verification:

  TX = RTL8812AU, RX = TP-Link RTL8821AU, channel 6.
  DEVOURER_RX_DUMP_CSI=0x0,0x1,0x10,0x40,0xa0 produced 40
  <devourer-csi> lines across 8 canonical-SA frames * 5 selectors.
  No wedge events; the chip received 300 additional RX frames after
  the sweep completed (save/restore on 0x8FC kept the RX path intact).

  csi_dump.py classified all 5 selectors as STATIC or SINGLE-BIT —
  no wide-bit IQ bus among them, exactly the framework-in-tree-but-
  IQ-out-of-reach state the plan called the "acceptable case".

What would unblock real capture (separate, future work):

  1. Vendoring (or rediscovering) Realtek's phydm dbgport selector
     catalogue — typically dumped via rtwpriv on a reference platform.
  2. Or: implementing the 0x95C ADC-DMA path. Raw ADC samples at full
     bandwidth + off-chip 64-point FFT recovers per-subcarrier IQ.

Until one of those lands, this tier stays "framework in tree, capture
out of reach." Both BbDbgportReader.h and tools/precoder/README.md
carry the same warning.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@josephnef josephnef merged commit e41f0b1 into master Jun 7, 2026
5 checks passed
@josephnef josephnef deleted the bb-dbgport-csi branch June 7, 2026 20:20
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