From 63cb99769230bdff14fea099235443ede4917817 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 10 Dec 2025 15:24:53 -0800 Subject: [PATCH] better clocking --- components/iperf/CMakeLists.txt | 2 +- components/iperf/iperf.c | 45 +++++++++++++++++++++++++-------- components/iperf/iperf.h | 16 ++++++++++-- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/components/iperf/CMakeLists.txt b/components/iperf/CMakeLists.txt index 27e72cc..c905447 100644 --- a/components/iperf/CMakeLists.txt +++ b/components/iperf/CMakeLists.txt @@ -2,7 +2,7 @@ idf_component_register( SRCS "iperf.c" INCLUDE_DIRS "." # Only if iperf.h needs types from these (unlikely based on your code): - REQUIRES lwip + REQUIRES lwip led_strip # Internal implementation details only: PRIV_REQUIRES esp_event esp_timer nvs_flash esp_netif esp_wifi ) diff --git a/components/iperf/iperf.c b/components/iperf/iperf.c index 7e073e7..f45f842 100644 --- a/components/iperf/iperf.c +++ b/components/iperf/iperf.c @@ -21,13 +21,29 @@ static const char *TAG = "iperf"; +// --- LED Handle (Private Static) --- +// This solves the linker error. We set this via iperf_init_led() +static led_strip_handle_t s_led_strip = NULL; + +// --- Init Function --- +void iperf_init_led(led_strip_handle_t handle) { + s_led_strip = handle; +} + +// --- LED State --- typedef enum { LED_OFF, LED_BLUE_SOLID, LED_RED_FLASH, LED_AMBER_SOLID, LED_GREEN_SOLID, LED_PURPLE_SOLID, LED_PURPLE_FLASH } led_state_t; -static led_state_t s_led_state = LED_RED_FLASH; -static void iperf_set_physical_led(uint8_t r, uint8_t g, uint8_t b) {} +static volatile led_state_t s_led_state = LED_RED_FLASH; + +static void iperf_set_physical_led(uint8_t r, uint8_t g, uint8_t b) { + if (s_led_strip) { + led_strip_set_pixel(s_led_strip, 0, r, g, b); + led_strip_refresh(s_led_strip); + } +} static void status_led_task(void *arg) { bool toggle = false; @@ -64,11 +80,18 @@ static esp_event_handler_instance_t instance_got_ip; static void iperf_network_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (s_iperf_event_group == NULL) return; - if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) s_led_state = LED_AMBER_SOLID; + + // Only update state if we are NOT currently running the test (Purple) + bool is_running = (s_led_state == LED_PURPLE_SOLID || s_led_state == LED_PURPLE_FLASH); + + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) { + if (!is_running) s_led_state = LED_AMBER_SOLID; + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { xEventGroupSetBits(s_iperf_event_group, IPERF_IP_READY_BIT); - if (s_led_state != LED_PURPLE_SOLID && s_led_state != LED_PURPLE_FLASH) s_led_state = LED_GREEN_SOLID; - } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (!is_running) s_led_state = LED_GREEN_SOLID; + } + else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { xEventGroupClearBits(s_iperf_event_group, IPERF_IP_READY_BIT); s_led_state = LED_RED_FLASH; } @@ -84,7 +107,7 @@ static bool iperf_wait_for_ip(void) { esp_netif_ip_info_t ip_info; if (esp_netif_get_ip_info(netif, &ip_info) == ESP_OK && ip_info.ip.addr != 0) { xEventGroupSetBits(s_iperf_event_group, IPERF_IP_READY_BIT); - s_led_state = LED_GREEN_SOLID; + // Don't set Green here, let the loop handle the transition } } ESP_LOGI(TAG, "Waiting for IP address..."); @@ -107,7 +130,7 @@ static void iperf_read_nvs_config(iperf_cfg_t *cfg) { uint32_t val = 0; size_t required_size; - // --- DEFAULTS --- + // Defaults cfg->pacing_period_us = 10000; cfg->burst_count = 1; cfg->send_len = IPERF_UDP_TX_LEN; @@ -121,7 +144,6 @@ static void iperf_read_nvs_config(iperf_cfg_t *cfg) { if (nvs_get_u32(my_handle, NVS_KEY_IPERF_BURST, &val) == ESP_OK && val > 0) cfg->burst_count = val; if (nvs_get_u32(my_handle, NVS_KEY_IPERF_LEN, &val) == ESP_OK && val > 0) cfg->send_len = val; - // READ PORT if (nvs_get_u32(my_handle, NVS_KEY_IPERF_PORT, &val) == ESP_OK && val > 0) { cfg->dport = (uint16_t)val; ESP_LOGI(TAG, "NVS Port: %d", val); @@ -178,12 +200,12 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sockfd < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); - s_led_state = LED_PURPLE_FLASH; + s_led_state = LED_RED_FLASH; return ESP_FAIL; } addr.sin_family = AF_INET; - addr.sin_port = htons(ctrl->cfg.dport); + addr.sin_port = htons(ctrl->cfg.dport > 0 ? ctrl->cfg.dport : 5001); addr.sin_addr.s_addr = ctrl->cfg.dip; char ip_str[INET_ADDRSTRLEN]; @@ -197,7 +219,9 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) double total_mbps = (double)((uint64_t)burst_count * payload_len * 8 * (1000000.0 / pacing_period_us)) / 1000000.0; ESP_LOGI(TAG, "Pacing: %" PRIu32 " pkts every %" PRIu32 " us (Approx %.2f Mbps)", burst_count, pacing_period_us, total_mbps); + // --- FORCE PURPLE (TRANSMITTING) --- s_led_state = LED_PURPLE_SOLID; + iperf_set_physical_led(64, 0, 64); // Immediate feedback uint64_t total_len = 0; uint32_t packet_count = 0; @@ -285,6 +309,7 @@ void iperf_start(iperf_cfg_t *cfg) { } nvs_close(my_handle); } + if (enabled == 0) return; if (s_iperf_task_handle != NULL) return; diff --git a/components/iperf/iperf.h b/components/iperf/iperf.h index 66b50f0..fde4c6a 100644 --- a/components/iperf/iperf.h +++ b/components/iperf/iperf.h @@ -3,12 +3,15 @@ #include #include +#include "led_strip.h" // Needed for the handle type +// --- Configuration Flags --- #define IPERF_FLAG_CLIENT (1 << 0) #define IPERF_FLAG_SERVER (1 << 1) #define IPERF_FLAG_TCP (1 << 2) #define IPERF_FLAG_UDP (1 << 3) +// --- Defaults --- #define IPERF_DEFAULT_PORT 5001 #define IPERF_DEFAULT_INTERVAL 3 #define IPERF_DEFAULT_TIME 30 @@ -18,17 +21,18 @@ #define IPERF_SOCKET_RX_TIMEOUT 10 #define IPERF_SOCKET_ACCEPT_TIMEOUT 5 +// --- Buffer Sizes --- #define IPERF_UDP_TX_LEN (1470) #define IPERF_UDP_RX_LEN (16 << 10) #define IPERF_TCP_TX_LEN (16 << 10) #define IPERF_TCP_RX_LEN (16 << 10) -// NVS Keys +// --- NVS Keys --- #define NVS_KEY_IPERF_ENABLE "iperf_enabled" #define NVS_KEY_IPERF_PERIOD "iperf_period" #define NVS_KEY_IPERF_ROLE "iperf_role" #define NVS_KEY_IPERF_DST_IP "iperf_dst_ip" -#define NVS_KEY_IPERF_PORT "iperf_port" // <--- NEW +#define NVS_KEY_IPERF_PORT "iperf_port" #define NVS_KEY_IPERF_PROTO "iperf_proto" #define NVS_KEY_IPERF_BURST "iperf_burst" #define NVS_KEY_IPERF_LEN "iperf_len" @@ -79,6 +83,14 @@ typedef struct { #define HEADER_VERSION1 0x80000000 +// --- Public API --- + +/** + * @brief Initialize the LED for Iperf status indication. + * @param handle The LED strip handle (created in main/status_led). + */ +void iperf_init_led(led_strip_handle_t handle); + void iperf_start(iperf_cfg_t *cfg); void iperf_stop(void);