151 lines
4.5 KiB
C
Executable File
151 lines
4.5 KiB
C
Executable File
#include "led_indicator.h"
|
|
#include "led_strip_encoder.h"
|
|
#include "device_config.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "driver/rmt_tx.h"
|
|
#include "esp_log.h"
|
|
#include <math.h>
|
|
|
|
static const char *TAG = "LED_INDICATOR";
|
|
|
|
#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000) // 10MHz resolution
|
|
|
|
static rmt_channel_handle_t led_channel = NULL;
|
|
static rmt_encoder_handle_t led_encoder = NULL;
|
|
static TaskHandle_t led_task_handle = NULL;
|
|
static led_state_t current_led_state = LED_OFF;
|
|
static gpio_num_t led_gpio = GPIO_NUM_NC;
|
|
|
|
typedef struct {
|
|
uint8_t green;
|
|
uint8_t red;
|
|
uint8_t blue;
|
|
} grb_t;
|
|
|
|
static void led_write(grb_t color) {
|
|
uint8_t led_data[3];
|
|
led_data[0] = color.green;
|
|
led_data[1] = color.red;
|
|
led_data[2] = color.blue;
|
|
|
|
rmt_transmit_config_t tx_config = {
|
|
.loop_count = 0,
|
|
};
|
|
|
|
ESP_ERROR_CHECK(rmt_enable(led_channel));
|
|
ESP_ERROR_CHECK(rmt_transmit(led_channel, led_encoder, led_data, sizeof(led_data), &tx_config));
|
|
ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_channel, portMAX_DELAY));
|
|
ESP_ERROR_CHECK(rmt_disable(led_channel));
|
|
}
|
|
|
|
static void led_indicator_task(void *arg) {
|
|
grb_t color;
|
|
uint32_t tick = 0;
|
|
|
|
while (1) {
|
|
switch (current_led_state) {
|
|
case LED_OFF:
|
|
color = (grb_t){0, 0, 0};
|
|
led_write(color);
|
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
break;
|
|
|
|
case LED_PAIRING:
|
|
// Azul piscando
|
|
color = (tick % 2 == 0) ? (grb_t){0, 0, 50} : (grb_t){0, 0, 0};
|
|
led_write(color);
|
|
vTaskDelay(pdMS_TO_TICKS(500));
|
|
tick++;
|
|
break;
|
|
|
|
case LED_CONNECTED:
|
|
// Verde fixo
|
|
color = (grb_t){30, 0, 0};
|
|
led_write(color);
|
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
break;
|
|
|
|
case LED_DISCONNECTED:
|
|
// Vermelho piscando
|
|
color = (tick % 2 == 0) ? (grb_t){0, 50, 0} : (grb_t){0, 0, 0};
|
|
led_write(color);
|
|
vTaskDelay(pdMS_TO_TICKS(300));
|
|
tick++;
|
|
break;
|
|
|
|
case LED_RELAY_ON:
|
|
// Verde brilhante
|
|
color = (grb_t){60, 0, 0};
|
|
led_write(color);
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
break;
|
|
|
|
case LED_RELAY_OFF:
|
|
// Verde escuro
|
|
color = (grb_t){10, 0, 0};
|
|
led_write(color);
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
break;
|
|
|
|
case LED_FACTORY_RESET:
|
|
// Arco-íris rotativo
|
|
{
|
|
float hue = (tick % 360) * 3.14159f / 180.0f;
|
|
color = (grb_t){
|
|
(uint8_t)(30 * (1 + sinf(hue))),
|
|
(uint8_t)(30 * (1 + sinf(hue + 2.0943f))),
|
|
(uint8_t)(30 * (1 + sinf(hue + 4.1888f)))
|
|
};
|
|
led_write(color);
|
|
vTaskDelay(pdMS_TO_TICKS(20));
|
|
tick++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
esp_err_t led_indicator_init(gpio_num_t gpio_num) {
|
|
esp_err_t ret;
|
|
led_gpio = gpio_num;
|
|
|
|
ESP_LOGI(TAG, "Inicializando LED RGB no GPIO %d", gpio_num);
|
|
|
|
// Configurar canal RMT TX
|
|
rmt_tx_channel_config_t tx_chan_config = {
|
|
.clk_src = RMT_CLK_SRC_DEFAULT,
|
|
.gpio_num = gpio_num,
|
|
.mem_block_symbols = 64,
|
|
.resolution_hz = LED_STRIP_RMT_RES_HZ,
|
|
.trans_queue_depth = 4,
|
|
};
|
|
|
|
ret = rmt_new_tx_channel(&tx_chan_config, &led_channel);
|
|
if (ret != ESP_OK) {
|
|
ESP_LOGE(TAG, "Falha ao criar canal RMT TX: %s", esp_err_to_name(ret));
|
|
return ret;
|
|
}
|
|
|
|
// Criar encoder customizado para LED strip
|
|
led_strip_encoder_config_t encoder_config = {
|
|
.resolution = LED_STRIP_RMT_RES_HZ,
|
|
};
|
|
|
|
ret = rmt_new_led_strip_encoder(&encoder_config, &led_encoder);
|
|
if (ret != ESP_OK) {
|
|
ESP_LOGE(TAG, "Falha ao criar encoder LED: %s", esp_err_to_name(ret));
|
|
return ret;
|
|
}
|
|
|
|
// Criar task para controlar LED
|
|
xTaskCreate(led_indicator_task, "led_indicator", 2048, NULL, 5, &led_task_handle);
|
|
|
|
ESP_LOGI(TAG, "LED RGB inicializado com sucesso");
|
|
return ESP_OK;
|
|
}
|
|
|
|
void led_indicator_set_state(led_state_t state) {
|
|
current_led_state = state;
|
|
}
|