2022-11-13 17:05:41 +08:00
|
|
|
/* 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 60
|
|
|
|
#define EXAMPLE_CHASE_SPEED_MS (10)
|
|
|
|
|
|
|
|
typedef enum light_mode_e {
|
|
|
|
light_mode_init = 0,
|
|
|
|
light_mode_connection_wifi = 1,
|
|
|
|
light_mode_idle = 2,
|
2022-11-21 00:22:37 +08:00
|
|
|
light_mode_mqtt_connected = 3,
|
|
|
|
light_mode_desktop_online = 4,
|
|
|
|
light_mode_desktop_sending_colors = 5,
|
2022-11-13 17:05:41 +08:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-21 00:22:37 +08:00
|
|
|
void update_desktop_connection_state() {
|
|
|
|
static uint8_t tick = 0;
|
|
|
|
|
|
|
|
uint8_t mask = tick / 10 % 2 ? 0xff : 0x00;
|
|
|
|
|
|
|
|
switch (light_mode) {
|
|
|
|
case light_mode_desktop_online:
|
|
|
|
ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 0, mask & 150,
|
|
|
|
mask & 50, mask & 0));
|
|
|
|
ESP_ERROR_CHECK(
|
|
|
|
light_led_strip->set_pixel(light_led_strip, 1, 30, 100, 0));
|
|
|
|
ESP_ERROR_CHECK(
|
|
|
|
light_led_strip->set_pixel(light_led_strip, 2, 30, 100, 0));
|
|
|
|
break;
|
|
|
|
case light_mode_mqtt_connected:
|
|
|
|
ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 0, mask & 100,
|
|
|
|
mask & 30, mask & 0));
|
|
|
|
ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 1, mask & 100,
|
|
|
|
mask & 30, mask & 0));
|
|
|
|
ESP_ERROR_CHECK(
|
|
|
|
light_led_strip->set_pixel(light_led_strip, 2, 50, 150, 0));
|
|
|
|
break;
|
|
|
|
case light_mode_idle:
|
|
|
|
ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 0, mask & 100,
|
|
|
|
mask & 30, mask & 0));
|
|
|
|
ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 1, mask & 100,
|
|
|
|
mask & 30, mask & 0));
|
|
|
|
ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, 2, mask & 100,
|
|
|
|
mask & 30, mask & 0));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
tick++;
|
|
|
|
}
|
|
|
|
|
2022-11-13 17:05:41 +08:00
|
|
|
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;
|
|
|
|
|
2022-11-21 00:22:37 +08:00
|
|
|
for (uint16_t offset = 0; light_mode == light_mode_idle ||
|
|
|
|
light_mode == light_mode_mqtt_connected ||
|
|
|
|
light_mode == light_mode_desktop_online;
|
2022-11-13 17:05:41 +08:00
|
|
|
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));
|
|
|
|
}
|
2022-11-21 00:22:37 +08:00
|
|
|
update_desktop_connection_state();
|
2022-11-13 17:05:41 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
// Show simple rainbow chasing pattern
|
2022-11-21 00:22:37 +08:00
|
|
|
ESP_LOGI(LIGHT_TAG, "light_strip_running_task: %d", light_mode);
|
2022-11-13 17:05:41 +08:00
|
|
|
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:
|
2022-11-21 00:22:37 +08:00
|
|
|
case light_mode_mqtt_connected:
|
|
|
|
case light_mode_desktop_online:
|
2022-11-13 17:05:41 +08:00
|
|
|
light_for_idle();
|
|
|
|
break;
|
|
|
|
default:
|
2022-11-21 00:22:37 +08:00
|
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
2022-11-13 17:05:41 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-11-21 00:22:37 +08:00
|
|
|
void light_play(light_mode_t mode) {
|
|
|
|
ESP_LOGI(LIGHT_TAG, "light_play: %d", mode);
|
|
|
|
light_mode = mode;
|
|
|
|
}
|