board/main/light.c

263 lines
7.5 KiB
C

/* RMT example -- RGB LED Strip
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include "driver/rmt.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "led_strip.h"
#include "sdkconfig.h"
static const char *LIGHT_TAG = "ScreenBgLight_Light";
#define RMT_TX_CHANNEL RMT_CHANNEL_0
#define RMT_TX_GPIO 1
#define STRIP_LED_NUMBER CONFIG_NUMBER_OF_LEDS
#define EXAMPLE_CHASE_SPEED_MS (10)
typedef enum light_mode_e {
light_mode_init = 0,
light_mode_connection_wifi = 1,
light_mode_idle = 2,
light_mode_mqtt_connected = 3,
light_mode_desktop_online = 4,
light_mode_desktop_sending_colors = 5,
} light_mode_t;
led_strip_t *light_led_strip;
light_mode_t light_mode;
/**
* @brief Simple helper function, converting HSV color space to RGB color
* space
*
* Wiki: https://en.wikipedia.org/wiki/HSL_and_HSV
*
*/
void led_strip_hsv2rgb(uint32_t h, uint32_t s, uint32_t v, uint32_t *r,
uint32_t *g, uint32_t *b) {
h %= 360; // h -> [0,360]
uint32_t rgb_max = v * 2.55f;
uint32_t rgb_min = rgb_max * (100 - s) / 100.0f;
uint32_t i = h / 60;
uint32_t diff = h % 60;
// RGB adjustment amount by hue
uint32_t rgb_adj = (rgb_max - rgb_min) * diff / 60;
switch (i) {
case 0:
*r = rgb_max;
*g = rgb_min + rgb_adj;
*b = rgb_min;
break;
case 1:
*r = rgb_max - rgb_adj;
*g = rgb_max;
*b = rgb_min;
break;
case 2:
*r = rgb_min;
*g = rgb_max;
*b = rgb_min + rgb_adj;
break;
case 3:
*r = rgb_min;
*g = rgb_max - rgb_adj;
*b = rgb_max;
break;
case 4:
*r = rgb_min + rgb_adj;
*g = rgb_min;
*b = rgb_max;
break;
default:
*r = rgb_max;
*g = rgb_min;
*b = rgb_max - rgb_adj;
break;
}
}
void update_desktop_connection_state() {
static uint8_t tick = 0;
bool beat = tick / 10 % 2 ? 1 : 0;
switch (light_mode) {
case light_mode_desktop_online:
if (beat) {
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, 0, 77, 77, 77));
}
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, 1, 77, 77, 77));
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, 2, 77, 77, 77));
break;
case light_mode_mqtt_connected:
if (beat) {
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, 0, 77, 77, 77));
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, 1, 77, 77, 77));
}
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, 2, 77, 77, 77));
break;
case light_mode_idle:
if (beat) {
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, 0, 77, 77, 77));
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, 1, 77, 77, 77));
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, 2, 77, 77, 77));
}
break;
default:
break;
}
tick++;
}
void light_for_init() {
ESP_LOGI(LIGHT_TAG, "light_for_init");
ESP_ERROR_CHECK(light_led_strip->clear(light_led_strip, 100));
uint32_t red = 0, green = 0, blue = 0;
int8_t i = 0;
do {
for (; i < 100; i++) {
for (int j = 0; j < STRIP_LED_NUMBER; j++) {
led_strip_hsv2rgb(0, 0, i, &red, &green, &blue);
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, j, red, green, blue));
}
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100));
vTaskDelay(pdMS_TO_TICKS(10));
}
} while (light_mode == light_mode_init);
}
void light_for_connecting_wifi() {
ESP_LOGI(LIGHT_TAG, "light_for_connecting_wifi");
int8_t tick_tock = 0;
do {
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, tick_tock, 150, 150, 0));
ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip,
(tick_tock + 1) % 2, 0, 200, 0));
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100));
tick_tock = !tick_tock;
vTaskDelay(pdMS_TO_TICKS(200));
} while (light_mode == light_mode_connection_wifi);
}
void light_for_idle() {
ESP_LOGI(LIGHT_TAG, "light_for_idle");
ESP_ERROR_CHECK(light_led_strip->clear(light_led_strip, 100));
uint32_t red = 0, green = 0, blue = 0;
uint16_t step_length = 360 / STRIP_LED_NUMBER;
for (uint16_t offset = 0; light_mode == light_mode_idle ||
light_mode == light_mode_mqtt_connected ||
light_mode == light_mode_desktop_online;
offset = (offset + 1) % 360) {
for (uint16_t j = 0, hue = offset; j < STRIP_LED_NUMBER;
j++, hue += step_length) {
// Build RGB values
led_strip_hsv2rgb(hue, 100, 50, &red, &green, &blue);
// Write RGB values to strip driver
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, j, red, green, blue));
}
update_desktop_connection_state();
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100));
vTaskDelay(pdMS_TO_TICKS(10));
}
}
void light_strip_running_task(void *pv_parameters) {
while (true) {
if (!light_led_strip) {
ESP_LOGE(LIGHT_TAG, "install WS2812 driver failed 2");
}
switch (light_mode) {
case light_mode_init:
light_for_init();
break;
case light_mode_connection_wifi:
light_for_connecting_wifi();
break;
case light_mode_idle:
case light_mode_mqtt_connected:
case light_mode_desktop_online:
light_for_idle();
break;
default:
vTaskDelay(pdMS_TO_TICKS(100));
break;
}
}
vTaskDelete(NULL);
}
void light_init_strip() {
rmt_config_t config = RMT_DEFAULT_CONFIG_TX(RMT_TX_GPIO, RMT_TX_CHANNEL);
// set counter clock to 40MHz
config.clk_div = 2;
ESP_ERROR_CHECK(rmt_config(&config));
ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));
// install ws2812 driver
led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(
STRIP_LED_NUMBER, (led_strip_dev_t)config.channel);
light_led_strip = led_strip_new_rmt_ws2812(&strip_config);
if (!light_led_strip) {
ESP_LOGE(LIGHT_TAG, "install WS2812 driver failed");
}
// Clear LED strip (turn off all LEDs)
ESP_ERROR_CHECK(light_led_strip->clear(light_led_strip, 100));
// Show simple rainbow chasing pattern
ESP_LOGI(LIGHT_TAG, "LED Rainbow Chase Start");
light_mode = light_mode_init;
xTaskCreate(light_strip_running_task, "LIGHT_STRIP_RUNNING_TASK", 4096, NULL,
1, NULL);
}
void light_play_colors(uint16_t len, uint8_t *buffer) {
light_mode = light_mode_desktop_sending_colors;
printf("COLORS=%.*s\r\n", len, buffer);
for (uint16_t led_index = 0, buffer_cursor = 0;
led_index < STRIP_LED_NUMBER && buffer_cursor < len;
led_index++, buffer_cursor += 3) {
uint8_t r = buffer[buffer_cursor], g = buffer[buffer_cursor + 1],
b = buffer[buffer_cursor + 2];
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, led_index, r, g, b));
}
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100));
vTaskDelay(pdMS_TO_TICKS(10));
}
void light_play(light_mode_t mode) {
ESP_LOGI(LIGHT_TAG, "light_play: %d", mode);
light_mode = mode;
}