#include "led_manager.h" #include static const char *TAG = "LED_MANAGER"; static led_strip_handle_t led_strip = NULL; static bool is_initialized = false; // Blinking functionality static TaskHandle_t blink_task_handle = NULL; static bool is_blinking = false; static uint8_t current_red = 0; static uint8_t current_green = 0; static uint8_t current_blue = 0; static uint32_t blink_rate_ms = 500; static bool blink_state = false; // Forward declaration for blink task static void led_blink_task(void *pvParameter); // RGB color definitions static const struct { uint8_t red; uint8_t green; uint8_t blue; const char *name; led_color_t enum_val; } rgb_colors[] = { {200, 0, 0, "Red", LED_COLOR_RED}, {200, 40, 0, "Orange", LED_COLOR_ORANGE}, {200, 160, 0, "Yellow", LED_COLOR_YELLOW}, {0, 180, 0, "Green", LED_COLOR_GREEN}, {0, 0, 160, "Blue", LED_COLOR_BLUE}, }; // LED blink task static void led_blink_task(void *pvParameter) { while (is_blinking) { if (blink_state) { // Turn on with current color led_strip_set_pixel(led_strip, 0, current_red, current_green, current_blue); led_strip_refresh(led_strip); } else { // Turn off led_strip_set_pixel(led_strip, 0, 0, 0, 0); led_strip_refresh(led_strip); } blink_state = !blink_state; vTaskDelay(pdMS_TO_TICKS(blink_rate_ms)); } // Clean exit - restore solid color led_strip_set_pixel(led_strip, 0, current_red, current_green, current_blue); led_strip_refresh(led_strip); blink_task_handle = NULL; vTaskDelete(NULL); } esp_err_t led_manager_init(int gpio_pin) { if (is_initialized) { ESP_LOGW(TAG, "LED manager already initialized"); return ESP_OK; } ESP_LOGI(TAG, "Initializing LED manager on GPIO %d", gpio_pin); // Configure GPIO gpio_reset_pin(gpio_pin); gpio_set_direction(gpio_pin, GPIO_MODE_OUTPUT); gpio_set_level(gpio_pin, 0); // LED strip general configuration led_strip_config_t strip_config = { .strip_gpio_num = gpio_pin, .max_leds = 1, .led_model = LED_MODEL_WS2812, .color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB, .flags = { .invert_out = false, }}; // LED strip RMT configuration led_strip_rmt_config_t rmt_config = { #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) .rmt_channel = 0, #else .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 10 * 1000 * 1000, // 10MHz resolution .mem_block_symbols = 64, #endif .flags = { .with_dma = false, }}; // Create the LED strip esp_err_t ret = led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to create LED strip: %s", esp_err_to_name(ret)); return ret; } // Clear the LED strip ret = led_strip_clear(led_strip); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to clear LED strip: %s", esp_err_to_name(ret)); led_strip_del(led_strip); led_strip = NULL; return ret; } is_initialized = true; ESP_LOGI(TAG, "LED manager initialized successfully"); return ESP_OK; } esp_err_t led_manager_set_color_by_name(const char *color_name, bool blink) { if (!is_initialized || led_strip == NULL) { ESP_LOGE(TAG, "LED manager not initialized"); return ESP_ERR_INVALID_STATE; } if (color_name == NULL) { ESP_LOGE(TAG, "Color name is NULL"); return ESP_ERR_INVALID_ARG; } int color_index = -1; // Find the color index by name for (int i = 0; i < sizeof(rgb_colors) / sizeof(rgb_colors[0]); i++) { if (strcmp(rgb_colors[i].name, color_name) == 0) { color_index = i; break; } } // If color not found, default to first color (Red) if (color_index == -1) { ESP_LOGW(TAG, "Color '%s' not found, defaulting to Red", color_name); color_index = 0; } // Stop any existing blinking if (is_blinking) { led_manager_stop_blinking(); } // Set the color esp_err_t ret = led_manager_set_rgb(rgb_colors[color_index].red, rgb_colors[color_index].green, rgb_colors[color_index].blue); if (ret != ESP_OK) { return ret; } if (blink) { // Start blinking is_blinking = true; blink_state = true; if (blink_task_handle == NULL) { xTaskCreate(led_blink_task, "led_blink", 2048, NULL, 5, &blink_task_handle); } } return ESP_OK; } esp_err_t led_manager_set_color(led_color_t color, bool blink) { if (!is_initialized || led_strip == NULL) { ESP_LOGE(TAG, "LED manager not initialized"); return ESP_ERR_INVALID_STATE; } // Find the color by enum value for (int i = 0; i < sizeof(rgb_colors) / sizeof(rgb_colors[0]); i++) { if (rgb_colors[i].enum_val == color) { // Stop any existing blinking if (is_blinking) { led_manager_stop_blinking(); } esp_err_t ret = led_manager_set_rgb(rgb_colors[i].red, rgb_colors[i].green, rgb_colors[i].blue); if (ret != ESP_OK) { return ret; } if (blink) { // Start blinking is_blinking = true; blink_state = true; if (blink_task_handle == NULL) { xTaskCreate(led_blink_task, "led_blink", 2048, NULL, 5, &blink_task_handle); } } return ESP_OK; } } ESP_LOGW(TAG, "Invalid color enum %d, defaulting to Red", color); return led_manager_set_color(LED_COLOR_RED, blink); } esp_err_t led_manager_set_rgb(uint8_t red, uint8_t green, uint8_t blue) { if (!is_initialized || led_strip == NULL) { ESP_LOGE(TAG, "LED manager not initialized"); return ESP_ERR_INVALID_STATE; } ESP_LOGD(TAG, "Setting LED color: R=%d, G=%d, B=%d", red, green, blue); // Set the LED pixel using RGB color esp_err_t ret = led_strip_set_pixel(led_strip, 0, red, green, blue); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to set LED pixel: %s", esp_err_to_name(ret)); return ret; } // Refresh the strip to send data ret = led_strip_refresh(led_strip); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to refresh LED strip: %s", esp_err_to_name(ret)); return ret; } // Store current color for blinking current_red = red; current_green = green; current_blue = blue; return ESP_OK; } esp_err_t led_manager_stop_blinking(void) { if (is_blinking) { is_blinking = false; // Task will clean itself up vTaskDelay(pdMS_TO_TICKS(100)); // Allow task to finish } return ESP_OK; } esp_err_t led_manager_set_blink_rate(uint32_t rate_ms) { if (rate_ms < 50) { ESP_LOGW(TAG, "Blink rate too fast, minimum is 50ms"); rate_ms = 50; } blink_rate_ms = rate_ms; ESP_LOGI(TAG, "Blink rate set to %lu ms", rate_ms); return ESP_OK; } esp_err_t led_manager_clear(void) { if (!is_initialized || led_strip == NULL) { ESP_LOGE(TAG, "LED manager not initialized"); return ESP_ERR_INVALID_STATE; } ESP_LOGD(TAG, "Clearing LED"); esp_err_t ret = led_strip_clear(led_strip); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to clear LED strip: %s", esp_err_to_name(ret)); return ret; } return ESP_OK; } esp_err_t led_manager_deinit(void) { if (!is_initialized) { ESP_LOGW(TAG, "LED manager not initialized"); return ESP_OK; } ESP_LOGI(TAG, "Deinitializing LED manager"); // Stop blinking task if running if (blink_task_handle != NULL) { is_blinking = false; vTaskDelay(pdMS_TO_TICKS(100)); // Allow task to finish if (blink_task_handle != NULL) { vTaskDelete(blink_task_handle); blink_task_handle = NULL; } } if (led_strip != NULL) { led_strip_clear(led_strip); esp_err_t ret = led_strip_del(led_strip); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to delete LED strip: %s", esp_err_to_name(ret)); } led_strip = NULL; } is_initialized = false; ESP_LOGI(TAG, "LED manager deinitialized"); return ESP_OK; }