From 89f1b382cecae1a916392a88be9be4465bf8a60a Mon Sep 17 00:00:00 2001 From: Bob Date: Mon, 8 Dec 2025 17:10:45 -0800 Subject: [PATCH] refactor for csi_manager component --- components/csi_manager/CMakeLists.txt | 4 + components/csi_manager/csi_manager.c | 114 ++++++++++++++++++++++++++ components/csi_manager/csi_manager.h | 46 +++++++++++ main/CMakeLists.txt | 1 + main/main.c | 95 ++++----------------- 5 files changed, 183 insertions(+), 77 deletions(-) create mode 100644 components/csi_manager/CMakeLists.txt create mode 100644 components/csi_manager/csi_manager.c create mode 100644 components/csi_manager/csi_manager.h diff --git a/components/csi_manager/CMakeLists.txt b/components/csi_manager/CMakeLists.txt new file mode 100644 index 0000000..42b581a --- /dev/null +++ b/components/csi_manager/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "csi_manager.c" + INCLUDE_DIRS "." + REQUIRES esp_wifi freertos + PRIV_REQUIRES csi_log log) diff --git a/components/csi_manager/csi_manager.c b/components/csi_manager/csi_manager.c new file mode 100644 index 0000000..2b4825c --- /dev/null +++ b/components/csi_manager/csi_manager.c @@ -0,0 +1,114 @@ +#include "csi_manager.h" +#include "csi_log.h" +#include "esp_wifi.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +static const char *TAG = "CSI_MGR"; + +static bool s_csi_enabled = false; +static uint32_t s_csi_packet_count = 0; + +// --- Callback --- +static void csi_cb(void *ctx, wifi_csi_info_t *info) { + if (!info || !s_csi_enabled) return; + + csi_log_append_record(info); + s_csi_packet_count++; + + if ((s_csi_packet_count % 100) == 0) { + ESP_LOGI(TAG, "Captured %lu CSI packets", (unsigned long)s_csi_packet_count); + } +} + +// --- Tasks --- + +static void enable_task(void *arg) { + // Wait for connection to stabilize + vTaskDelay(pdMS_TO_TICKS(2000)); + + if (s_csi_enabled) { + vTaskDelete(NULL); + return; + } + + wifi_csi_config_t csi_cfg = { 0 }; + +#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) + // Detailed config for Xtensa chips + csi_cfg.lltf_en = true; + csi_cfg.htltf_en = true; + csi_cfg.stbc_htltf2_en = true; + csi_cfg.ltf_merge_en = true; + csi_cfg.channel_filter_en = true; + csi_cfg.manu_scale = false; + csi_cfg.shift = false; +#endif + + ESP_LOGI(TAG, "Configuring CSI..."); + if (esp_wifi_set_csi_config(&csi_cfg) != ESP_OK) { + ESP_LOGE(TAG, "Failed to set CSI config"); + vTaskDelete(NULL); + return; + } + + if (esp_wifi_set_csi_rx_cb(csi_cb, NULL) != ESP_OK) { + ESP_LOGE(TAG, "Failed to set CSI callback"); + vTaskDelete(NULL); + return; + } + + if (esp_wifi_set_csi(true) != ESP_OK) { + ESP_LOGE(TAG, "Failed to enable CSI"); + vTaskDelete(NULL); + return; + } + + s_csi_enabled = true; + ESP_LOGI(TAG, "CSI enabled!"); + vTaskDelete(NULL); +} + +static void dump_task(void *arg) { + // Wait before dumping (per your original logic) + vTaskDelay(pdMS_TO_TICKS(20000)); + + ESP_LOGI(TAG, "Dumping CSI data..."); + csi_log_dump_over_uart(); + ESP_LOGI(TAG, "CSI dump complete"); + vTaskDelete(NULL); +} + +// --- API --- + +void csi_mgr_init(void) { + s_csi_enabled = false; + s_csi_packet_count = 0; +} + +void csi_mgr_enable_async(void) { + if (s_csi_enabled) return; + xTaskCreate(enable_task, "csi_enable", 4096, NULL, 5, NULL); +} + +void csi_mgr_disable(void) { + if (!s_csi_enabled) return; + + ESP_LOGI(TAG, "Disabling CSI..."); + esp_wifi_set_csi(false); + s_csi_enabled = false; + ESP_LOGI(TAG, "CSI disabled"); +} + +void csi_mgr_schedule_dump(void) { + xTaskCreate(dump_task, "csi_dump", 4096, NULL, 5, NULL); +} + +bool csi_mgr_is_enabled(void) { + return s_csi_enabled; +} + +uint32_t csi_mgr_get_packet_count(void) { + return s_csi_packet_count; +} diff --git a/components/csi_manager/csi_manager.h b/components/csi_manager/csi_manager.h new file mode 100644 index 0000000..2c02f1a --- /dev/null +++ b/components/csi_manager/csi_manager.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize CSI Manager state + */ +void csi_mgr_init(void); + +/** + * @brief Enable CSI capture asynchronously + * Spawns a task to wait 2 seconds (to let connection settle) then enables CSI. + * Safe to call from Event Handlers. + */ +void csi_mgr_enable_async(void); + +/** + * @brief Disable CSI capture immediately + */ +void csi_mgr_disable(void); + +/** + * @brief Dump collected CSI data to UART asynchronously + * Spawns a task that waits 20s then dumps data (simulating your original logic). + */ +void csi_mgr_schedule_dump(void); + +/** + * @brief Check if CSI is currently enabled + */ +bool csi_mgr_is_enabled(void); + +/** + * @brief Get total packet count (stats) + */ +uint32_t csi_mgr_get_packet_count(void); + +#ifdef __cplusplus +} +#endif diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 8d4f9e9..ed2054c 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -15,4 +15,5 @@ idf_component_register( gps_sync led_strip status_led + csi_manager ) diff --git a/main/main.c b/main/main.c index 6dd237d..3e28d1e 100644 --- a/main/main.c +++ b/main/main.c @@ -23,6 +23,7 @@ #include "gps_sync.h" #include "status_led.h" #include "board_config.h" +#include "csi_manager.h" // <--- New Component static const char *TAG = "MAIN"; @@ -43,85 +44,18 @@ static void auto_monitor_task(void *arg); // --- GPS Logging Helper --- void log_collapse_event(float nav_duration_us, int rssi, int retry) { gps_timestamp_t ts = gps_get_timestamp(); - // Format: COLLAPSE,MonoMS,GpsMS,Synced,Duration,RSSI,Retry printf("COLLAPSE,%" PRIi64 ",%" PRIi64 ",%d,%.2f,%d,%d\n", - ts.monotonic_ms, - ts.gps_ms, - ts.synced ? 1 : 0, - nav_duration_us, - rssi, - retry); -} - -// --- CSI Support --------------------------------------------------- -static bool s_csi_enabled = false; -static uint32_t s_csi_packet_count = 0; - -static void csi_cb(void *ctx, wifi_csi_info_t *info) { - csi_log_append_record(info); - s_csi_packet_count++; - if ((s_csi_packet_count % 100) == 0) { - ESP_LOGI("CSI", "Captured %lu CSI packets", (unsigned long)s_csi_packet_count); - } -} - -static void wifi_enable_csi_once(void) { - if (s_csi_enabled) return; - vTaskDelay(pdMS_TO_TICKS(2000)); - - wifi_csi_config_t csi_cfg = { 0 }; - -#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32) - csi_cfg.lltf_en = true; - csi_cfg.htltf_en = true; - csi_cfg.stbc_htltf2_en = true; - csi_cfg.ltf_merge_en = true; - csi_cfg.channel_filter_en = true; - csi_cfg.manu_scale = false; - csi_cfg.shift = false; -#endif - - ESP_LOGI("CSI", "Configuring CSI..."); - if (esp_wifi_set_csi_config(&csi_cfg) != ESP_OK) { - ESP_LOGE("CSI", "Failed to set CSI config"); return; - } - if (esp_wifi_set_csi_rx_cb(csi_cb, NULL) != ESP_OK) { - ESP_LOGE("CSI", "Failed to set CSI callback"); return; - } - if (esp_wifi_set_csi(true) != ESP_OK) { - ESP_LOGE("CSI", "Failed to enable CSI"); return; - } - ESP_LOGI("CSI", "CSI enabled!"); - s_csi_enabled = true; -} - -static void wifi_disable_csi(void) { - if (!s_csi_enabled) return; - ESP_LOGI("CSI", "Disabling CSI..."); - esp_wifi_set_csi(false); - s_csi_enabled = false; -} - -static void csi_dump_task(void *arg) { - vTaskDelay(pdMS_TO_TICKS(20000)); - ESP_LOGI("CSI", "Dumping CSI data..."); - csi_log_dump_over_uart(); - ESP_LOGI("CSI", "CSI dump complete"); - vTaskDelete(NULL); + ts.monotonic_ms, ts.gps_ms, ts.synced ? 1 : 0, nav_duration_us, rssi, retry); } // --- WiFi Monitor Mode Support ------------------------------------- static bool s_monitor_enabled = false; -static uint32_t s_monitor_frame_count = 0; static TaskHandle_t s_monitor_stats_task_handle = NULL; static void monitor_frame_callback(const wifi_frame_info_t *frame, const uint8_t *payload, uint16_t len) { - s_monitor_frame_count++; - // Check for Collapse if (frame->retry && frame->duration_id > 5000) { log_collapse_event((float)frame->duration_id, frame->rssi, frame->retry); } - // Warn on extremely high NAV if (frame->duration_id > 30000) { ESP_LOGW("MONITOR", "⚠️ VERY HIGH NAV: %u us", frame->duration_id); } @@ -146,12 +80,14 @@ static void monitor_stats_task(void *arg) { esp_err_t switch_to_monitor_mode(uint8_t channel, wifi_bandwidth_t bandwidth) { if (current_wifi_mode == WIFI_MODE_MONITOR) return ESP_OK; - if (bandwidth != WIFI_BW_HT20) bandwidth = WIFI_BW_HT20; // Forced for monitor mode + if (bandwidth != WIFI_BW_HT20) bandwidth = WIFI_BW_HT20; ESP_LOGI(TAG, "Switching to MONITOR MODE (Ch %d)", channel); iperf_stop(); vTaskDelay(pdMS_TO_TICKS(500)); - wifi_disable_csi(); + + // Disable CSI using Manager + csi_mgr_disable(); esp_wifi_disconnect(); esp_wifi_stop(); @@ -195,8 +131,6 @@ esp_err_t switch_to_sta_mode(wifi_band_mode_t band_mode) { esp_wifi_get_config(WIFI_IF_STA, &wifi_config); wifi_config.sta.channel = 0; - // Auto band selection logic can be refined here - esp_wifi_set_config(WIFI_IF_STA, &wifi_config); esp_wifi_start(); vTaskDelay(pdMS_TO_TICKS(500)); @@ -221,8 +155,7 @@ static int cmd_mode_monitor(int argc, char **argv) { } static int cmd_mode_sta(int argc, char **argv) { - wifi_band_mode_t band_mode = WIFI_BAND_MODE_AUTO; - if (switch_to_sta_mode(band_mode) != ESP_OK) { + if (switch_to_sta_mode(WIFI_BAND_MODE_AUTO) != ESP_OK) { printf("Failed to switch to STA mode\n"); return 1; } @@ -235,6 +168,11 @@ static int cmd_mode_status(int argc, char **argv) { printf("Current mode: %s\n", current_wifi_mode == WIFI_MODE_STA_CSI ? "STA" : "MONITOR"); printf("LED state: %d\n", status_led_get_state()); printf("GPS synced: %s\n", gps_is_synced() ? "Yes" : "No"); + + if (current_wifi_mode == WIFI_MODE_STA_CSI) { + printf("CSI Enabled: %s\n", csi_mgr_is_enabled() ? "Yes" : "No"); + printf("CSI Packets: %lu\n", (unsigned long)csi_mgr_get_packet_count()); + } return 0; } @@ -242,12 +180,12 @@ static int cmd_csi_dump(int argc, char **argv) { if (current_wifi_mode != WIFI_MODE_STA_CSI) { printf("Error: CSI only available in STA mode\n"); return 1; } + // Uses the new manager to dump csi_log_dump_over_uart(); return 0; } static void register_mode_commands(void) { - // Uses designated initializers to avoid missing field errors const esp_console_cmd_t cmds[] = { { .command = "mode_monitor", .help = "Switch to monitor mode", .func = &cmd_mode_monitor }, { .command = "mode_sta", .help = "Switch to STA mode", .func = &cmd_mode_sta }, @@ -279,12 +217,14 @@ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_ wifi_connected = true; status_led_set_state(LED_STATE_CONNECTED); - wifi_enable_csi_once(); + // Start CSI Manager (Async) + csi_mgr_enable_async(); iperf_cfg_t cfg = { .flag = IPERF_FLAG_SERVER | IPERF_FLAG_TCP, .sport = 5001 }; iperf_start(&cfg); - xTaskCreate(csi_dump_task, "csi_dump_task", 4096, NULL, 5, NULL); + // Schedule dump if needed (or rely on CLI) + csi_mgr_schedule_dump(); } } @@ -297,6 +237,7 @@ void app_main(void) { // Init Subsystems ESP_ERROR_CHECK(csi_log_init()); status_led_init(RGB_LED_GPIO, HAS_RGB_LED); + csi_mgr_init(); // New Init // Init GPS const gps_sync_config_t gps_cfg = {