#include #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "esp_system.h" #include "esp_event.h" #include "esp_log.h" #include "esp_wifi.h" #include "nvs_flash.h" #include "esp_netif.h" #include "lwip/inet.h" #include "led_strip.h" #include "iperf.h" #include "wifi_cfg.h" #include "csi_log.h" static const char *TAG = "main"; // RGB LED GPIO pin configuration #if CONFIG_IDF_TARGET_ESP32S3 #define RGB_LED_GPIO 48 #elif CONFIG_IDF_TARGET_ESP32C5 #define RGB_LED_GPIO 27 #elif CONFIG_IDF_TARGET_ESP32C6 #define RGB_LED_GPIO 8 #elif CONFIG_IDF_TARGET_ESP32C3 #define RGB_LED_GPIO 8 #elif CONFIG_IDF_TARGET_ESP32S2 #define RGB_LED_GPIO 18 #elif CONFIG_IDF_TARGET_ESP32 #define RGB_LED_GPIO 2 #else #error "Unsupported target - define RGB_LED_GPIO for your board" #endif static led_strip_handle_t led_strip; // WiFi connection status static bool wifi_connected = false; static bool has_config = false; // LED states typedef enum { LED_STATE_NO_CONFIG, LED_STATE_WAITING, LED_STATE_CONNECTED, LED_STATE_FAILED } led_state_t; static led_state_t current_led_state = LED_STATE_NO_CONFIG; static void rgb_led_init(void) { led_strip_config_t strip_config = { .strip_gpio_num = RGB_LED_GPIO, .max_leds = 1, }; led_strip_rmt_config_t rmt_config = { .resolution_hz = 10 * 1000 * 1000, }; ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip)); led_strip_clear(led_strip); ESP_LOGI(TAG, "WS2812 RGB LED initialized on GPIO %d", RGB_LED_GPIO); } static void set_led_color(uint8_t r, uint8_t g, uint8_t b) { led_strip_set_pixel(led_strip, 0, r, g, b); led_strip_refresh(led_strip); } static void led_task(void *arg) { int blink_state = 0; while(1) { switch(current_led_state) { case LED_STATE_NO_CONFIG: set_led_color(255, 255, 0); vTaskDelay(pdMS_TO_TICKS(1000)); break; case LED_STATE_WAITING: if (blink_state) { set_led_color(0, 0, 255); } else { set_led_color(0, 0, 0); } blink_state = !blink_state; vTaskDelay(pdMS_TO_TICKS(1000)); break; case LED_STATE_CONNECTED: set_led_color(0, 255, 0); vTaskDelay(pdMS_TO_TICKS(1000)); break; case LED_STATE_FAILED: if (blink_state) { set_led_color(255, 0, 0); } else { set_led_color(0, 0, 0); } blink_state = !blink_state; vTaskDelay(pdMS_TO_TICKS(200)); break; } } } // --- CSI support --------------------------------------------------- static bool s_csi_enabled = false; static uint32_t s_csi_packet_count = 0; static void csi_dump_task(void *arg) { vTaskDelay(pdMS_TO_TICKS(20000)); csi_log_dump_over_uart(); vTaskDelete(NULL); } 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; } esp_err_t err; // Wait for WiFi to stabilize ESP_LOGI("CSI", "Waiting 500ms for WiFi to stabilize..."); vTaskDelay(pdMS_TO_TICKS(500)); // Disable power save for CSI err = esp_wifi_set_ps(WIFI_PS_NONE); if (err != ESP_OK) { ESP_LOGW("CSI", "Failed to disable power save: %s", esp_err_to_name(err)); } else { ESP_LOGI("CSI", "WiFi power save disabled"); } wifi_csi_config_t csi_cfg; #if CONFIG_IDF_TARGET_ESP32C5 memset(&csi_cfg, 0, sizeof(csi_cfg)); csi_cfg.enable = true; #elif CONFIG_IDF_TARGET_ESP32S3 memset(&csi_cfg, 0, sizeof(csi_cfg)); 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 = false; csi_cfg.manu_scale = false; csi_cfg.shift = 0; #else #warning "CSI not supported for this target" return; #endif err = esp_wifi_set_csi_config(&csi_cfg); if (err != ESP_OK) { ESP_LOGE("CSI", "esp_wifi_set_csi_config failed: %s (0x%x)", esp_err_to_name(err), err); return; } ESP_LOGI("CSI", "CSI config applied successfully"); err = esp_wifi_set_csi_rx_cb(csi_cb, NULL); if (err != ESP_OK) { ESP_LOGE("CSI", "esp_wifi_set_csi_rx_cb failed: %s", esp_err_to_name(err)); return; } ESP_LOGI("CSI", "CSI callback registered"); err = esp_wifi_set_csi(true); if (err != ESP_OK) { ESP_LOGE("CSI", "esp_wifi_set_csi(true) failed: %s", esp_err_to_name(err)); return; } ESP_LOGI("CSI", "CSI capture enabled"); ESP_LOGI("CSI", "CSI fully enabled and capturing!"); s_csi_enabled = true; } static void csi_init_task(void *arg) { vTaskDelay(pdMS_TO_TICKS(1000)); ESP_LOGI("CSI", "Starting CSI initialization..."); wifi_enable_csi_once(); vTaskDelete(NULL); } static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT) { switch (event_id) { case WIFI_EVENT_STA_START: ESP_LOGI(TAG, "WiFi started, attempting connection..."); if (has_config) { current_led_state = LED_STATE_WAITING; } break; case WIFI_EVENT_STA_DISCONNECTED: wifi_event_sta_disconnected_t* event = (wifi_event_sta_disconnected_t*) event_data; ESP_LOGW(TAG, "WiFi disconnected, reason: %d", event->reason); if (!wifi_connected && has_config) { current_led_state = LED_STATE_FAILED; ESP_LOGE(TAG, "WiFi connection FAILED - RED LED blinking"); } break; } } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, "got ip:" IPSTR " gw:" IPSTR " netmask:" IPSTR, IP2STR(&event->ip_info.ip), IP2STR(&event->ip_info.gw), IP2STR(&event->ip_info.netmask)); wifi_connected = true; current_led_state = LED_STATE_CONNECTED; ESP_LOGI(TAG, "WiFi CONNECTED - BLUE LED solid"); // Enable CSI in separate task xTaskCreate(csi_init_task, "csi_init", 4096, NULL, 5, NULL); // Auto-start iperf server vTaskDelay(pdMS_TO_TICKS(1000)); iperf_cfg_t cfg; memset(&cfg, 0, sizeof(cfg)); cfg.flag = IPERF_FLAG_SERVER | IPERF_FLAG_TCP; cfg.sport = 5001; iperf_start(&cfg); ESP_LOGI(TAG, "iperf TCP server started on port 5001"); // Schedule CSI dump xTaskCreate(csi_dump_task, "csi_dump_task", 4096, NULL, 5, NULL); } } void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(csi_log_init()); rgb_led_init(); xTaskCreate(led_task, "led_task", 4096, NULL, 5, NULL); ESP_ERROR_CHECK(esp_event_handler_instance_register( WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL)); ESP_ERROR_CHECK(esp_event_handler_instance_register( IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, NULL)); wifi_cfg_init(); if (wifi_cfg_apply_from_nvs()) { has_config = true; current_led_state = LED_STATE_WAITING; ESP_LOGI(TAG, "WiFi config loaded from NVS"); } else { has_config = false; current_led_state = LED_STATE_NO_CONFIG; ESP_LOGI(TAG, "No WiFi config - YELLOW LED"); } ESP_LOGI(TAG, "LED Status:"); ESP_LOGI(TAG, " YELLOW solid = NO CONFIG (send CFG/END)"); ESP_LOGI(TAG, " BLUE slow blink = Connecting"); ESP_LOGI(TAG, " BLUE solid = Connected ✓"); ESP_LOGI(TAG, " RED fast blink = Failed ✗"); while(1) { vTaskDelay(pdMS_TO_TICKS(1000)); } }