Follow-up to #305, which shipped the Kestrel noise-floor sensing. On the C8852B (RTL8852BU) everything works and cross-validates; on the C8852C (RTL8852CU/8832CU) both floors are deliberately gated to emit null (never a wrong value) pending two 8852C-specific fixes.
On-air comparison, same idle channel (ch149, 0 frames, DEVOURER_RX_NOISE_FLOOR=1 DEVOURER_RXQUALITY=1):
|
8852BU (C8852B) |
8832CU (C8852C) |
| active NHM floor |
−93 dBm (correct) |
−68 dBm (~25 dB high) |
passive rssi−snr floor |
−94 dBm (HEALTHY) |
null (SNR unparsed) |
Gap 1 — active NHM floor reads ~25 dB high on the 8852C
The halbb NHM env-monitor triggers and returns on the 8852C (setting bb->cr_type = BB_CLIENT in kestrel_halbb_create populates the CR bank so nhm_rdy is valid — the same fix that made the 8852B work), but the reported nhm_pwr is ~25 dB too high: idle ch149 reads −68 dBm vs the 8852B's −93. The nhm_pwr − 110 conversion is chip-agnostic, so the raw nhm_pwr itself differs — likely an 8852C-specific NHM reference / nhm_method_sel / threshold difference in the halbb BB_CLIENT env-monitor path (or an 8852C power-report offset the vendor applies elsewhere).
- Where it's gated:
RtlKestrelDevice::GetRxEnergy() only trusts nhm_noise_floor when _variant == C8852B.
- Done looks like: the 8852C NHM floor reads a correct idle floor (~−90…−95 on a quiet channel, cross-matching the passive floor once Gap 2 lands), then drop the
C8852B-only gate.
Gap 2 — physts SNR unparsed on the 8852C (passive floor null)
The passive rssi − snr floor needs per-frame SNR. devourer hand-parses it from the PPDU-status physts report: after the 8-byte physts_hdr_info, IE_01 (physts_ie_1_info) carries avg_snr at IE byte 8 [5:0]; the parse self-validates on ie_hdr == 1 at payload offset 8 (RtlKestrelDevice.cpp, the RPKT_TYPE_PPDU handler). On the 8852C the physts payload layout differs (the C uses a 16-byte drv_info unit vs the B's 8), so IE_01 is not at offset 8 → the ie_hdr == 1 guard fails → snr stays 0 → the passive floor never populates and LinkHealth misclassifies (SATURATED at a weak RSSI). Per-frame RSSI parses fine on the 8852C.
- Done looks like: locate IE_01 for the 8852C physts layout (or route the buffer through the vendored
halbb_physts_parsing and read bb->bb_physts_i) so snr populates → the passive floor + LinkHealth work on the C.
Both paths currently emit null on the 8852C (no fake data), so this is a "make it work on the C" task, not a correctness regression. Context: docs/rx-spectrum-sensing.md (the per-generation noise-floor list).
Follow-up to #305, which shipped the Kestrel noise-floor sensing. On the C8852B (RTL8852BU) everything works and cross-validates; on the C8852C (RTL8852CU/8832CU) both floors are deliberately gated to emit
null(never a wrong value) pending two 8852C-specific fixes.On-air comparison, same idle channel (ch149, 0 frames,
DEVOURER_RX_NOISE_FLOOR=1 DEVOURER_RXQUALITY=1):rssi−snrfloornull(SNR unparsed)Gap 1 — active NHM floor reads ~25 dB high on the 8852C
The halbb NHM env-monitor triggers and returns on the 8852C (setting
bb->cr_type = BB_CLIENTinkestrel_halbb_createpopulates the CR bank sonhm_rdyis valid — the same fix that made the 8852B work), but the reportednhm_pwris ~25 dB too high: idle ch149 reads −68 dBm vs the 8852B's −93. Thenhm_pwr − 110conversion is chip-agnostic, so the rawnhm_pwritself differs — likely an 8852C-specific NHM reference /nhm_method_sel/ threshold difference in the halbbBB_CLIENTenv-monitor path (or an 8852C power-report offset the vendor applies elsewhere).RtlKestrelDevice::GetRxEnergy()only trustsnhm_noise_floorwhen_variant == C8852B.C8852B-only gate.Gap 2 — physts SNR unparsed on the 8852C (passive floor null)
The passive
rssi − snrfloor needs per-frame SNR. devourer hand-parses it from the PPDU-status physts report: after the 8-bytephysts_hdr_info, IE_01 (physts_ie_1_info) carriesavg_snrat IE byte 8[5:0]; the parse self-validates onie_hdr == 1at payload offset 8 (RtlKestrelDevice.cpp, theRPKT_TYPE_PPDUhandler). On the 8852C the physts payload layout differs (the C uses a 16-bytedrv_infounit vs the B's 8), so IE_01 is not at offset 8 → theie_hdr == 1guard fails →snrstays 0 → the passive floor never populates and LinkHealth misclassifies (SATURATED at a weak RSSI). Per-frame RSSI parses fine on the 8852C.halbb_physts_parsingand readbb->bb_physts_i) sosnrpopulates → the passive floor + LinkHealth work on the C.Both paths currently emit
nullon the 8852C (no fake data), so this is a "make it work on the C" task, not a correctness regression. Context:docs/rx-spectrum-sensing.md(the per-generation noise-floor list).