Files
WS2812B-LED-RC-Controller/main/control.c

226 lines
5.3 KiB
C

/**
* @file control.c
* @brief Control module implementation
*/
#include "control.h"
#include "led.h"
#include "rcsignal.h"
#include "localbtn.h"
#include "animation.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 <string.h>
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", &current_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", &current_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 &current_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(&current_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)
{
current_animation_mode = new_mode;
animation_set_mode((animation_mode_t)new_mode);
}
void control_set_animation_mode(uint8_t mode)
{
if (mode >= ANIM_MODE_COUNT)
{
mode = 0;
}
on_mode_change(mode);
}
uint8_t control_get_animation_mode(void)
{
return current_animation_mode;
}
void control_emulate_pwm_pulse(void)
{
rcsignal_trigger_mode_change();
}
// Main initialization
esp_err_t control_init(void)
{
esp_err_t ret;
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)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// Load configuration
load_config_from_nvs();
// 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);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "LED init failed: %s", esp_err_to_name(ret));
return ret;
}
// Initialize animation system
ret = animation_init();
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Animation init failed: %s", esp_err_to_name(ret));
return ret;
}
// Initialize RC signal
ret = rcsignal_init(current_config.pwm_pin);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "RC signal init failed: %s", esp_err_to_name(ret));
return ret;
}
// Initialize local BTN
ret = localbtn_init();
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Local BTN init failed: %s", esp_err_to_name(ret));
return ret;
}
// Register mode change callback
rcsignal_register_callback(on_mode_change);
localbtn_register_callback(on_mode_change);
ESP_LOGI(TAG, "Control system initialized successfully");
return ESP_OK;
}