diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index e428543..39d1cfc 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -6,5 +6,6 @@ idf_component_register( "rcsignal.c" "animation.c" "localbtn.c" + "config.c" INCLUDE_DIRS "." ) diff --git a/main/config.c b/main/config.c new file mode 100644 index 0000000..3632401 --- /dev/null +++ b/main/config.c @@ -0,0 +1,177 @@ +/** + * @file config.c + * @brief Config module implementation + */ + +#include "config.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_system.h" +#include "nvs_flash.h" +#include "nvs.h" +#include "esp_timer.h" + +#include + +static const char *TAG = "CONFIG"; + +#define NVS_NAMESPACE "led_ctrl" +#define CONFIG_MAGIC 0xDEADBEEF + +#define HARDCODED_CONFIG +#define HARDCODED_CONFIG_LED_STRIP_A_PIN 12U +#define HARDCODED_CONFIG_LED_STRIP_B_PIN 14U +#define HARDCODED_CONFIG_LED_STRIP_A_COUNT 7U +#define HARDCODED_CONFIG_LED_STRIP_B_COUNT 7U +#define HARDCODED_CONFIG_PWM_PIN 13U + +// Global state +static config_t current_config = { + .led_pin_strip_a = -1, + .led_pin_strip_b = -1, + .led_count_strip_a = -1, + .led_count_strip_b = -1, + .pwm_pin = -1, + .magic = CONFIG_MAGIC}; + +// NVS Functions +static esp_err_t load_config_from_nvs(void) +{ + nvs_handle_t nvs_handle; + esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle); + if (err != ESP_OK) + { + ESP_LOGW(TAG, "NVS not found, using defaults"); + return ESP_ERR_NOT_FOUND; + } + + size_t required_size = sizeof(config_t); + err = nvs_get_blob(nvs_handle, "config", ¤t_config, &required_size); + nvs_close(nvs_handle); + + if (err != ESP_OK || current_config.magic != CONFIG_MAGIC) + { + ESP_LOGW(TAG, "Invalid config in NVS, using defaults"); + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGI(TAG, "Loaded config from NVS"); + ESP_LOGI(TAG, " Strip A: GPIO%d", current_config.led_pin_strip_a); + ESP_LOGI(TAG, " Strip B: GPIO%d", current_config.led_pin_strip_b); + ESP_LOGI(TAG, " PWM Pin: GPIO%d", current_config.pwm_pin); + + return ESP_OK; +} + +static esp_err_t save_config_to_nvs(void) +{ + nvs_handle_t nvs_handle; + esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle); + if (err != ESP_OK) + { + return err; + } + + current_config.magic = CONFIG_MAGIC; + err = nvs_set_blob(nvs_handle, "config", ¤t_config, sizeof(config_t)); + if (err == ESP_OK) + { + err = nvs_commit(nvs_handle); + } + + nvs_close(nvs_handle); + + if (err == ESP_OK) + { + ESP_LOGI(TAG, "Config saved to NVS"); + } + else + { + ESP_LOGE(TAG, "Failed to save config: %s", esp_err_to_name(err)); + } + + return err; +} + +esp_err_t config_reset_config(void) +{ + current_config.led_pin_strip_a = -1; + current_config.led_pin_strip_b = -1; + current_config.led_count_strip_a = -1; + current_config.led_count_strip_b = -1; + current_config.pwm_pin = -1; + current_config.magic = CONFIG_MAGIC; + + return save_config_to_nvs(); +} + +void config_get_config(config_t *const cnf) +{ + cnf->led_pin_strip_a = current_config.led_pin_strip_a; + cnf->led_pin_strip_b = current_config.led_pin_strip_b; + cnf->led_count_strip_a = current_config.led_count_strip_a; + cnf->led_count_strip_b = current_config.led_count_strip_b; + cnf->pwm_pin = current_config.pwm_pin; +} + +esp_err_t config_update_config(const config_t *config) +{ + if (!config) + { + return ESP_ERR_INVALID_ARG; + } + + // Reinitialize if pins changed + bool pins_changed = (current_config.led_pin_strip_a != config->led_pin_strip_a) || + (current_config.led_pin_strip_b != config->led_pin_strip_b) || + (current_config.pwm_pin != config->pwm_pin); + + memcpy(¤t_config, config, sizeof(config_t)); + esp_err_t err = save_config_to_nvs(); + + if (err == ESP_OK && pins_changed) + { + ESP_LOGI(TAG, "Restarting to apply new pin configuration..."); + vTaskDelay(pdMS_TO_TICKS(1000)); + esp_restart(); + } + + return err; +} + +// Main initialization +esp_err_t config_init(void) +{ + esp_err_t ret; + + ESP_LOGI(TAG, "Initializing Config Controller..."); + + // Initialize NVS + ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) + { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + +#ifdef HARDCODED_CONFIG + current_config.led_pin_strip_a = HARDCODED_CONFIG_LED_STRIP_A_PIN; + current_config.led_pin_strip_b = HARDCODED_CONFIG_LED_STRIP_B_PIN; + current_config.led_count_strip_a = HARDCODED_CONFIG_LED_STRIP_A_COUNT; + current_config.led_count_strip_b = HARDCODED_CONFIG_LED_STRIP_B_COUNT; + current_config.pwm_pin = HARDCODED_CONFIG_PWM_PIN; + current_config.magic = CONFIG_MAGIC; + + save_config_to_nvs(); +#endif + + // Load configuration + load_config_from_nvs(); + + ESP_LOGI(TAG, "Config system initialized successfully"); + + return ESP_OK; +} diff --git a/main/config.h b/main/config.h new file mode 100644 index 0000000..410e02a --- /dev/null +++ b/main/config.h @@ -0,0 +1,52 @@ +/** + * @file config.h + * @brief Config module for LED controller - handles read and store of persistent data + */ + +#ifndef CONFIG_H +#define CONFIG_H + +#include "esp_err.h" +#include +#include + +/** + * @brief Configuration structure stored in NVS + */ +typedef struct +{ + int8_t led_pin_strip_a; // GPIO pin for LED strip A (-1 = not configured) + int8_t led_pin_strip_b; // GPIO pin for LED strip B (-1 = not configured) + int8_t led_count_strip_a; // LED count for LED strip A (-1 = not configured) + int8_t led_count_strip_b; // LED count for LED strip B (-1 = not configured) + int8_t pwm_pin; // GPIO pin for PWM input (-1 = not configured) + uint32_t magic; // Magic number to validate config (0xDEADBEEF) //TODO: use sha256 +} config_t; + +/** + * @brief Initialize the config system + * Loads configuration from NVS and initializes subsystems + * @return ESP_OK on success + */ +esp_err_t config_init(void); + +/** + * @brief Get current configuration + * @param Pointer to current configuration (read-only) + */ +void config_get_config(config_t *const cnf); + +/** + * @brief Update configuration and save to NVS + * @param config New configuration + * @return ESP_OK on success + */ +esp_err_t config_update_config(const config_t *config); + +/** + * @brief Reset configuration to defaults + * @return ESP_OK on success + */ +esp_err_t config_reset_config(void); + +#endif // CONFIG_H diff --git a/main/control.c b/main/control.c index f1450b3..7cbb7f9 100644 --- a/main/control.c +++ b/main/control.c @@ -4,6 +4,7 @@ */ #include "control.h" +#include "config.h" #include "led.h" #include "rcsignal.h" #include "localbtn.h" @@ -13,130 +14,17 @@ #include "freertos/task.h" #include "esp_log.h" #include "esp_system.h" -#include "nvs_flash.h" -#include "nvs.h" #include "esp_timer.h" #include static const char *TAG = "CONTROL"; -#define NVS_NAMESPACE "led_ctrl" -#define CONFIG_MAGIC 0xDEADBEEF -#define DEFAULT_NUM_LEDS_A 7 -#define DEFAULT_NUM_LEDS_B 7 - -// Global state -static controller_config_t current_config = { - .led_pin_strip_a = -1, - .led_pin_strip_b = -1, - .pwm_pin = -1, - .magic = CONFIG_MAGIC}; - static uint8_t current_animation_mode = 0; // Forward declarations static void on_mode_change(uint8_t new_mode); -// NVS Functions -static esp_err_t load_config_from_nvs(void) -{ - nvs_handle_t nvs_handle; - esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle); - if (err != ESP_OK) - { - ESP_LOGW(TAG, "NVS not found, using defaults"); - return ESP_ERR_NOT_FOUND; - } - - size_t required_size = sizeof(controller_config_t); - err = nvs_get_blob(nvs_handle, "config", ¤t_config, &required_size); - nvs_close(nvs_handle); - - if (err != ESP_OK || current_config.magic != CONFIG_MAGIC) - { - ESP_LOGW(TAG, "Invalid config in NVS, using defaults"); - return ESP_ERR_INVALID_STATE; - } - - ESP_LOGI(TAG, "Loaded config from NVS"); - ESP_LOGI(TAG, " Strip A: GPIO%d", current_config.led_pin_strip_a); - ESP_LOGI(TAG, " Strip B: GPIO%d", current_config.led_pin_strip_b); - ESP_LOGI(TAG, " PWM Pin: GPIO%d", current_config.pwm_pin); - - return ESP_OK; -} - -static esp_err_t save_config_to_nvs(void) -{ - nvs_handle_t nvs_handle; - esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle); - if (err != ESP_OK) - { - return err; - } - - current_config.magic = CONFIG_MAGIC; - err = nvs_set_blob(nvs_handle, "config", ¤t_config, sizeof(controller_config_t)); - if (err == ESP_OK) - { - err = nvs_commit(nvs_handle); - } - - nvs_close(nvs_handle); - - if (err == ESP_OK) - { - ESP_LOGI(TAG, "Config saved to NVS"); - } - else - { - ESP_LOGE(TAG, "Failed to save config: %s", esp_err_to_name(err)); - } - - return err; -} - -esp_err_t control_reset_config(void) -{ - current_config.led_pin_strip_a = 12; - current_config.led_pin_strip_b = 14; - current_config.pwm_pin = 13; - current_config.magic = CONFIG_MAGIC; - - return save_config_to_nvs(); -} - -const controller_config_t *control_get_config(void) -{ - return ¤t_config; -} - -esp_err_t control_update_config(const controller_config_t *config) -{ - if (!config) - { - return ESP_ERR_INVALID_ARG; - } - - // Reinitialize if pins changed - bool pins_changed = (current_config.led_pin_strip_a != config->led_pin_strip_a) || - (current_config.led_pin_strip_b != config->led_pin_strip_b) || - (current_config.pwm_pin != config->pwm_pin); - - memcpy(¤t_config, config, sizeof(controller_config_t)); - esp_err_t err = save_config_to_nvs(); - - if (err == ESP_OK && pins_changed) - { - ESP_LOGI(TAG, "Restarting to apply new pin configuration..."); - vTaskDelay(pdMS_TO_TICKS(1000)); - esp_restart(); - } - - return err; -} - // Animation mode change callback static void on_mode_change(uint8_t new_mode) { @@ -170,21 +58,20 @@ esp_err_t control_init(void) ESP_LOGI(TAG, "Initializing LED Controller..."); - // Initialize NVS - ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) + // Initialize config + ret = config_init(); + if (ret != ESP_OK) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); + ESP_LOGE(TAG, "Config init failed: %s", esp_err_to_name(ret)); + return ret; } - ESP_ERROR_CHECK(ret); - // Load configuration - load_config_from_nvs(); + config_t current_config; + config_get_config(¤t_config); // Initialize LED strips ret = led_init(current_config.led_pin_strip_a, current_config.led_pin_strip_b, - DEFAULT_NUM_LEDS_A, DEFAULT_NUM_LEDS_B); + current_config.led_count_strip_a, current_config.led_count_strip_a); if (ret != ESP_OK) { ESP_LOGE(TAG, "LED init failed: %s", esp_err_to_name(ret)); diff --git a/main/control.h b/main/control.h index bb4da93..b4fc404 100644 --- a/main/control.h +++ b/main/control.h @@ -10,17 +10,6 @@ #include #include -/** - * @brief Configuration structure stored in NVS - */ -typedef struct -{ - int8_t led_pin_strip_a; // GPIO pin for LED strip A (-1 = not configured) - int8_t led_pin_strip_b; // GPIO pin for LED strip B (-1 = not configured) - int8_t pwm_pin; // GPIO pin for PWM input (-1 = not configured) - uint32_t magic; // Magic number to validate config (0xDEADBEEF) -} controller_config_t; - /** * @brief Initialize the control system * Loads configuration from NVS and initializes subsystems @@ -28,25 +17,6 @@ typedef struct */ esp_err_t control_init(void); -/** - * @brief Get current configuration - * @return Pointer to current configuration (read-only) - */ -const controller_config_t *control_get_config(void); - -/** - * @brief Update configuration and save to NVS - * @param config New configuration - * @return ESP_OK on success - */ -esp_err_t control_update_config(const controller_config_t *config); - -/** - * @brief Reset configuration to defaults - * @return ESP_OK on success - */ -esp_err_t control_reset_config(void); - /** * @brief Set animation mode manually * @param mode Animation mode (0-13) diff --git a/main/main.c b/main/main.c index a546c85..dda5a4f 100644 --- a/main/main.c +++ b/main/main.c @@ -56,8 +56,6 @@ void app_main(void) } } - control_reset_config(); - // Create animation update task BaseType_t task_ret = xTaskCreate( animation_task,