wifi-densepose/firmware/esp32-csi-node/main
rUv 872d7593bb
fix: IDF v6.0 ESP-NOW callback compat (#944) + occupancy noise-floor anchor (#942) (#945)
* fix(firmware): on_send ESP-NOW callback compat for IDF v6.0 (closes #944)

ESP-IDF v6.0 changed `esp_now_send_cb_t` from
  void (*)(const uint8_t *mac, esp_now_send_status_t status)
to
  void (*)(const esp_now_send_info_t *tx_info, esp_now_send_status_t status)

The C6 sync ESP-NOW path's `on_recv` was already version-guarded with
`#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)` (lines 102-112)
but the `on_send` sibling missed the equivalent guard. CI runs against
IDF v5.4 so the regression slipped through; the reporter on IDF v6.0.1
with xtensa-esp-elf esp-15.2.0_20251204 hit:

  c6_sync_espnow.c:182:30: error: passing argument 1 of
  'esp_now_register_send_cb' from incompatible pointer type
  [-Wincompatible-pointer-types]

Fix: mirror the recv guard with `#if ESP_IDF_VERSION_MAJOR >= 6` since
the send-callback signature change happened at IDF v6.0 (not v5.x like
the recv-callback). Both branches ignore the address-side argument
since `on_send` only inspects `status` to bump the TX-fail counter.

Adds `#include "esp_idf_version.h"` so the macro is in scope.

Closes #944

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(signal): anchor estimate_occupancy noise floor to calibration (closes #942)

`test_estimate_occupancy_noise_only` asserts that 20 noise-only frames
fed through a 50-frame calibrated `FieldModel` yield 0 occupancy.
Failure reported on the upstream Linux + BLAS build.

Root cause

Calibration and estimation each compute their own Marcenko-Pastur
threshold:

  threshold = noise_var · (1 + sqrt(p / N))²

with `noise_var` = median of the bottom half of positive eigenvalues
from their own covariance. The MP ratio differs across the two phases:

  calibration  (50 frames, p=8): ratio = 0.16, factor ≈ 1.96
  estimation   (20 frames, p=8): ratio = 0.40, factor ≈ 2.66

On a small estimation window the local `noise_var` estimate can also
be smaller than the calibration's (fewer samples → bottom-half median
hits lower-magnitude eigenvalues). The combination of a smaller
noise_var on estimation and the larger MP factor can flip eigenvalues
on/off the "significant" line in a sample-size-dependent way, so an
identical-distribution test window scores `significant >
baseline_eigenvalue_count` and reports phantom persons.

Fix

Persist the calibration `noise_var` on `FieldNormalMode` (new field
`baseline_noise_var: f64`) and use `max(local_noise_var,
baseline_noise_var)` as the noise floor inside `estimate_occupancy`.
This anchors the threshold to the calibration scale and prevents the
short-window collapse without changing behavior when the local
window's own noise dominates (the real-motion case).

`baseline_noise_var` defaults to 0.0 in the diagonal-fallback paths;
the estimation code treats 0.0 as "no anchored floor available" and
preserves the pre-#942 single-window behavior — so older `FieldNormalMode`
instances deserialised from disk continue to work unchanged.

Test results

  cargo test --workspace --no-default-features
  → 413 lib tests pass (signal crate), 0 fail, 1 ignored.

The actual `eigenvalue`-gated test still requires BLAS (not buildable
on Windows). Logic-trace via the four numerical anchors above shows
the fix flips `noise_var` from the smaller local value back up to the
calibration scale, dropping `significant` to or below
`baseline_eigenvalue_count` so the saturating subtraction returns 0.

Closes #942

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-04 08:17:37 +02:00
..
lp_core ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
CMakeLists.txt ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
Kconfig.projbuild ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
adaptive_controller.c ADR-081: Implement 5-layer adaptive CSI mesh firmware kernel (#404) 2026-04-20 10:38:23 -04:00
adaptive_controller.h ADR-081: Implement 5-layer adaptive CSI mesh firmware kernel (#404) 2026-04-20 10:38:23 -04:00
adaptive_controller_decide.c ADR-081: Implement 5-layer adaptive CSI mesh firmware kernel (#404) 2026-04-20 10:38:23 -04:00
c6_lp_core.c ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
c6_lp_core.h ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
c6_softap_he.c ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
c6_softap_he.h ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
c6_sync_espnow.c fix: IDF v6.0 ESP-NOW callback compat (#944) + occupancy noise-floor anchor (#942) (#945) 2026-06-04 08:17:37 +02:00
c6_sync_espnow.h ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
c6_timesync.c ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
c6_timesync.h ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
c6_twt.c ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
c6_twt.h ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
csi_collector.c fix(firmware): capture DATA frames on display-less boards — #893/#866/#897 2026-06-02 09:57:19 +02:00
csi_collector.h fix(firmware): capture DATA frames on display-less boards — #893/#866/#897 2026-06-02 09:57:19 +02:00
display_hal.c docs: update README with ADR-045–048, Observatory, adaptive classifier, AMOLED display 2026-03-05 10:20:48 -05:00
display_hal.h docs: update README with ADR-045–048, Observatory, adaptive classifier, AMOLED display 2026-03-05 10:20:48 -05:00
display_task.c fix(firmware): capture DATA frames on display-less boards — #893/#866/#897 2026-06-02 09:57:19 +02:00
display_task.h fix(firmware): capture DATA frames on display-less boards — #893/#866/#897 2026-06-02 09:57:19 +02:00
display_ui.c fix(firmware): defensive node_id capture prevents runtime clobber (#390) 2026-04-15 13:47:34 -04:00
display_ui.h docs: update README with ADR-045–048, Observatory, adaptive classifier, AMOLED display 2026-03-05 10:20:48 -05:00
edge_processing.c fix(firmware): add vTaskDelay(1) yields in process_frame() at tier>=2 to fix WDT storm (#683) 2026-05-21 09:20:21 -04:00
edge_processing.h feat: ADR-069 ESP32 CSI → Cognitum Seed RVF pipeline (v0.5.4-esp32) 2026-04-02 19:32:18 -04:00
idf_component.yml fix(led): disable onboard WS2812 LED during CSI collection (#273) 2026-05-17 18:18:10 -04:00
lv_conf.h docs: update README with ADR-045–048, Observatory, adaptive classifier, AMOLED display 2026-03-05 10:20:48 -05:00
main.c fix(firmware): capture DATA frames on display-less boards — #893/#866/#897 2026-06-02 09:57:19 +02:00
mmwave_sensor.c refactor(mmwave): use sizeof() in mr60_process_frame bounds checks (#414) 2026-05-17 18:15:01 -04:00
mmwave_sensor.h feat: ADR-063/064 mmWave sensor fusion + multimodal ambient intelligence (#269) 2026-03-15 16:10:10 -04:00
mock_csi.c feat: QEMU ESP32-S3 testing platform + swarm configurator (ADR-061/062) (#260) 2026-03-14 13:39:51 -04:00
mock_csi.h feat: QEMU ESP32-S3 testing platform + swarm configurator (ADR-061/062) (#260) 2026-03-14 13:39:51 -04:00
nvs_config.c feat: happiness scoring pipeline + ESP32 swarm with Cognitum Seed (#285) 2026-03-20 18:46:34 -04:00
nvs_config.h feat: happiness scoring pipeline + ESP32 swarm with Cognitum Seed (#285) 2026-03-20 18:46:34 -04:00
ota_update.c release: ESP32-S3 firmware v0.6.5 — Tmr Svc stack + OTA init refactor (#628) 2026-05-18 17:05:35 -04:00
ota_update.h feat: complete vendor repos, add edge intelligence and WASM modules 2026-03-02 23:53:25 -05:00
power_mgmt.c feat: complete vendor repos, add edge intelligence and WASM modules 2026-03-02 23:53:25 -05:00
power_mgmt.h feat: complete vendor repos, add edge intelligence and WASM modules 2026-03-02 23:53:25 -05:00
rv_feature_state.c ADR-081: Implement 5-layer adaptive CSI mesh firmware kernel (#404) 2026-04-20 10:38:23 -04:00
rv_feature_state.h fix(protocol): resolve 0xC511_0004 magic collision (closes #928) (#931) 2026-06-03 11:56:35 +02:00
rv_mesh.c ADR-081: Implement 5-layer adaptive CSI mesh firmware kernel (#404) 2026-04-20 10:38:23 -04:00
rv_mesh.h ADR-081: Implement 5-layer adaptive CSI mesh firmware kernel (#404) 2026-04-20 10:38:23 -04:00
rv_radio_ops.h ADR-081: Implement 5-layer adaptive CSI mesh firmware kernel (#404) 2026-04-20 10:38:23 -04:00
rv_radio_ops_esp32.c ADR-081: Implement 5-layer adaptive CSI mesh firmware kernel (#404) 2026-04-20 10:38:23 -04:00
rv_radio_ops_mock.c ADR-081: Implement 5-layer adaptive CSI mesh firmware kernel (#404) 2026-04-20 10:38:23 -04:00
rvf_parser.c firmware/esp32-csi-node: IDF 6 build, HE CSI config, unicore DSP, provision chip detect (#522) 2026-05-17 18:00:40 -04:00
rvf_parser.h feat: complete vendor repos, add edge intelligence and WASM modules 2026-03-02 23:53:25 -05:00
stream_sender.c fix: rate-limit CSI sends and add ENOMEM backoff to prevent crash (#132) 2026-03-03 16:00:40 -05:00
stream_sender.h fix(docker): Update Dockerfile paths from src/ to v1/src/ 2026-02-28 13:38:21 -05:00
swarm_bridge.c ADR-110: ESP32-C6 firmware extension (#764) 2026-05-23 15:34:48 -04:00
swarm_bridge.h feat: happiness scoring pipeline + ESP32 swarm with Cognitum Seed (#285) 2026-03-20 18:46:34 -04:00
wasm_runtime.c fix(firmware): defensive node_id capture prevents runtime clobber (#390) 2026-04-15 13:47:34 -04:00
wasm_runtime.h fix(protocol): resolve 0xC511_0004 magic collision (closes #928) (#931) 2026-06-03 11:56:35 +02:00
wasm_upload.c fix: security hardening — replace fake HMAC, add path traversal protection, OTA auth (ADR-050) 2026-03-06 13:11:04 -05:00
wasm_upload.h feat: complete vendor repos, add edge intelligence and WASM modules 2026-03-02 23:53:25 -05:00