Skip to content

Commit 3fec676

Browse files
authored
Merge pull request #906 from ruvnet/fix/893-csi-data-frame-capture
fix(firmware): capture DATA frames on display-less boards — #893/#866/#897 (yield=0pps root cause)
2 parents 9c9b137 + 898c536 commit 3fec676

5 files changed

Lines changed: 64 additions & 0 deletions

File tree

firmware/esp32-csi-node/main/csi_collector.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,23 @@ static void hop_timer_cb(void *arg)
637637
csi_hop_next_channel();
638638
}
639639

640+
void csi_collector_enable_data_capture(void)
641+
{
642+
/* MGMT-only (RuView#396) starves the CSI callback on display-less boards
643+
* (RuView#521/#893): beacons alone are sparse, yield collapses to 0 pps.
644+
* Without a display there is no QSPI/SPI-flash cache contention with the
645+
* DATA-frame interrupt load, so capture DATA frames too. */
646+
wifi_promiscuous_filter_t filt = {
647+
.filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT | WIFI_PROMIS_FILTER_MASK_DATA,
648+
};
649+
esp_err_t err = esp_wifi_set_promiscuous_filter(&filt);
650+
if (err == ESP_OK) {
651+
ESP_LOGI(TAG, "CSI filter upgraded to MGMT+DATA (no display, RuView#893)");
652+
} else {
653+
ESP_LOGW(TAG, "Failed to enable DATA-frame CSI capture: %s", esp_err_to_name(err));
654+
}
655+
}
656+
640657
void csi_collector_start_hop_timer(void)
641658
{
642659
if (s_hop_count <= 1) {

firmware/esp32-csi-node/main/csi_collector.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,19 @@ void csi_hop_next_channel(void);
9090
*/
9191
void csi_collector_start_hop_timer(void);
9292

93+
/**
94+
* Upgrade the promiscuous filter to capture DATA frames in addition to MGMT
95+
* (RuView#893/#521).
96+
*
97+
* Called on display-less boards: the MGMT-only filter (the #396 display-crash
98+
* workaround set in csi_collector_init) only fires the CSI callback on sparse
99+
* management frames, so yield collapses to 0 pps under real traffic and the
100+
* node looks dead. A board with no AMOLED panel has no QSPI/SPI-flash cache
101+
* contention, so it can safely capture DATA frames — restoring abundant CSI.
102+
* Display boards keep MGMT-only to avoid the #396 crash.
103+
*/
104+
void csi_collector_enable_data_capture(void);
105+
93106
/**
94107
* Inject an NDP (Null Data Packet) frame for sensing.
95108
*

firmware/esp32-csi-node/main/display_task.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
#include "display_task.h"
1010
#include "sdkconfig.h"
1111

12+
/* Set true once an AMOLED panel is detected and the display task starts.
13+
* Defined outside the CONFIG_DISPLAY_ENABLE guard so display_is_active()
14+
* exists on headless builds too (where it stays false → CSI captures DATA
15+
* frames; see RuView#893). */
16+
static bool s_display_active = false;
17+
18+
bool display_is_active(void) { return s_display_active; }
19+
1220
#if CONFIG_DISPLAY_ENABLE
1321

1422
#include <string.h>
@@ -162,6 +170,7 @@ esp_err_t display_task_start(void)
162170

163171
ESP_LOGI(TAG, "Display task started (Core %d, priority %d, %d fps)",
164172
DISP_TASK_CORE, DISP_TASK_PRIORITY, DISP_FPS_LIMIT);
173+
s_display_active = true;
165174
return ESP_OK;
166175
}
167176

firmware/esp32-csi-node/main/display_task.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define DISPLAY_TASK_H
88

99
#include "esp_err.h"
10+
#include <stdbool.h>
1011

1112
#ifdef __cplusplus
1213
extern "C" {
@@ -22,6 +23,15 @@ extern "C" {
2223
*/
2324
esp_err_t display_task_start(void);
2425

26+
/**
27+
* @return true once an AMOLED panel has been detected and the display task
28+
* is running; false on headless boards (no panel, or built without display
29+
* support). Used to choose the CSI promiscuous filter (RuView#893): a board
30+
* with no display has no QSPI/SPI-flash contention, so it can safely capture
31+
* DATA frames for proper CSI yield instead of starving on MGMT-only.
32+
*/
33+
bool display_is_active(void);
34+
2535
#ifdef __cplusplus
2636
}
2737
#endif

firmware/esp32-csi-node/main/main.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,21 @@ void app_main(void)
410410
}
411411
#endif
412412

413+
/* RuView#893/#521: the MGMT-only promiscuous filter (set in
414+
* csi_collector_init as the #396 display-crash workaround) starves the CSI
415+
* callback on display-less boards — yield collapses to 0 pps and the node
416+
* looks dead despite being on the network. Now that the display probe has
417+
* run, boards with no AMOLED panel (no QSPI/SPI-flash cache contention)
418+
* upgrade the filter to capture DATA frames too, restoring CSI yield. */
419+
#ifdef CONFIG_DISPLAY_ENABLE
420+
bool has_display = display_is_active(); /* runtime panel probe result */
421+
#else
422+
bool has_display = false; /* display support not compiled in */
423+
#endif
424+
if (!has_display) {
425+
csi_collector_enable_data_capture();
426+
}
427+
413428
ESP_LOGI(TAG, "CSI streaming active → %s:%d (edge_tier=%u, OTA=%s, WASM=%s, mmWave=%s, swarm=%s, adapt=%s)",
414429
g_nvs_config.target_ip, g_nvs_config.target_port,
415430
g_nvs_config.edge_tier,

0 commit comments

Comments
 (0)