Add WS2812 status module and config
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
"dcdc_controller.c"
|
||||
"usb_cdc_cli.c"
|
||||
"ws2812_status.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/esp_tinyusb: "^1"
|
||||
espressif/led_strip: "^2"
|
||||
|
||||
12
main/main.c
12
main/main.c
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "dcdc_controller.h"
|
||||
#include "usb_cdc_cli.h"
|
||||
#include "ws2812_status.h"
|
||||
|
||||
static const char *TAG = "watch-watch";
|
||||
|
||||
@@ -13,9 +14,17 @@ void app_main(void)
|
||||
{
|
||||
if (dcdc_init() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Помилка ініціалізації DCDC контролера");
|
||||
ws2812_status_init();
|
||||
ws2812_status_set_error(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ws2812_status_init() == ESP_OK) {
|
||||
ws2812_status_refresh_from_dcdc();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WS2812 статусний індикатор недоступний");
|
||||
}
|
||||
|
||||
if (usb_cdc_cli_init() != ESP_OK) {
|
||||
ESP_LOGW(TAG, "USB CDC CLI недоступний");
|
||||
} else {
|
||||
@@ -30,10 +39,13 @@ void app_main(void)
|
||||
for (size_t ch = 0; ch < dcdc_channel_count(); ++ch) {
|
||||
if (prev_channel != ch) {
|
||||
dcdc_disable(prev_channel);
|
||||
ws2812_status_set_channel_state(prev_channel, false);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "-> Ввімкнення каналу %d", (int)ch);
|
||||
dcdc_enable(ch);
|
||||
ws2812_status_set_channel_state(ch, true);
|
||||
ws2812_status_mark_active(ch);
|
||||
vTaskDelay(on_time);
|
||||
|
||||
prev_channel = ch;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "tinyusb.h"
|
||||
#include "tusb_cdc_acm.h"
|
||||
#include "ws2812_status.h"
|
||||
|
||||
#define CLI_LINE_MAX_LEN 128
|
||||
#define CLI_QUEUE_LEN 8
|
||||
@@ -140,8 +141,9 @@ static void usb_cli_handle_switch(const char *cmd, char *args)
|
||||
if (err != ESP_OK) {
|
||||
usb_cli_printf("\r\nПомилка керування каналом: %s\r\n", esp_err_to_name(err));
|
||||
} else {
|
||||
usb_cli_printf("\r\nКанал %d -> %s\r\n", channel,
|
||||
dcdc_get_state(channel) ? "ON" : "OFF");
|
||||
bool state = dcdc_get_state(channel);
|
||||
usb_cli_printf("\r\nКанал %d -> %s\r\n", channel, state ? "ON" : "OFF");
|
||||
ws2812_status_set_channel_state(channel, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
134
main/ws2812_status.c
Normal file
134
main/ws2812_status.c
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "ws2812_status.h"
|
||||
|
||||
#include "dcdc_controller.h"
|
||||
#include "led_strip.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifndef CONFIG_WATCH_WS2812_LED_COUNT
|
||||
#define CONFIG_WATCH_WS2812_LED_COUNT 5
|
||||
#endif
|
||||
#ifndef CONFIG_WATCH_WS2812_GPIO
|
||||
#define CONFIG_WATCH_WS2812_GPIO 8
|
||||
#endif
|
||||
#ifndef CONFIG_WATCH_WS2812_RMT_RESOLUTION
|
||||
#define CONFIG_WATCH_WS2812_RMT_RESOLUTION (10 * 1000 * 1000)
|
||||
#endif
|
||||
|
||||
#define WS2812_STATUS_GPIO ((gpio_num_t)CONFIG_WATCH_WS2812_GPIO)
|
||||
#define WS2812_STATUS_RESOLUTION_HZ CONFIG_WATCH_WS2812_RMT_RESOLUTION
|
||||
|
||||
static const char *TAG = "ws2812";
|
||||
|
||||
static led_strip_handle_t s_strip;
|
||||
static bool s_led_state[WS2812_STATUS_LED_COUNT];
|
||||
static bool s_error_state;
|
||||
static size_t s_active_channel = SIZE_MAX;
|
||||
|
||||
static esp_err_t ws2812_status_apply(void)
|
||||
{
|
||||
if (!s_strip) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < WS2812_STATUS_LED_COUNT; ++i) {
|
||||
uint8_t r = 0, g = 0, b = 0;
|
||||
if (s_error_state) {
|
||||
r = 40;
|
||||
} else if (s_active_channel == i) {
|
||||
g = 60;
|
||||
} else if (s_led_state[i]) {
|
||||
g = 18;
|
||||
} else {
|
||||
b = 10;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(led_strip_set_pixel(s_strip, i, r, g, b), TAG,
|
||||
"led pixel set failed");
|
||||
}
|
||||
|
||||
return led_strip_refresh(s_strip);
|
||||
}
|
||||
|
||||
esp_err_t ws2812_status_init(void)
|
||||
{
|
||||
if (s_strip) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
led_strip_config_t strip_config = {
|
||||
.strip_gpio_num = WS2812_STATUS_GPIO,
|
||||
.max_leds = WS2812_STATUS_LED_COUNT,
|
||||
.led_model = LED_MODEL_WS2812,
|
||||
.flags.invert_out = false,
|
||||
};
|
||||
|
||||
led_strip_rmt_config_t rmt_cfg = {
|
||||
.clk_src = RMT_CLK_SRC_DEFAULT,
|
||||
.resolution_hz = WS2812_STATUS_RESOLUTION_HZ,
|
||||
.flags.with_dma = false,
|
||||
};
|
||||
|
||||
ESP_RETURN_ON_ERROR(
|
||||
led_strip_new_rmt_device(&strip_config, &rmt_cfg, &s_strip),
|
||||
TAG,
|
||||
"Не вдалося створити RMT пристрій для WS2812");
|
||||
ESP_RETURN_ON_ERROR(led_strip_clear(s_strip), TAG, "clear fail");
|
||||
|
||||
for (size_t i = 0; i < WS2812_STATUS_LED_COUNT; ++i) {
|
||||
s_led_state[i] = false;
|
||||
}
|
||||
s_active_channel = SIZE_MAX;
|
||||
s_error_state = false;
|
||||
|
||||
return ws2812_status_apply();
|
||||
}
|
||||
|
||||
esp_err_t ws2812_status_set_channel_state(size_t channel, bool enabled)
|
||||
{
|
||||
if (channel >= WS2812_STATUS_LED_COUNT) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
s_led_state[channel] = enabled;
|
||||
return ws2812_status_apply();
|
||||
}
|
||||
|
||||
esp_err_t ws2812_status_mark_active(size_t channel)
|
||||
{
|
||||
if (channel >= WS2812_STATUS_LED_COUNT) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
s_active_channel = channel;
|
||||
return ws2812_status_apply();
|
||||
}
|
||||
|
||||
esp_err_t ws2812_status_clear_active(void)
|
||||
{
|
||||
s_active_channel = SIZE_MAX;
|
||||
return ws2812_status_apply();
|
||||
}
|
||||
|
||||
esp_err_t ws2812_status_set_error(bool has_error)
|
||||
{
|
||||
s_error_state = has_error;
|
||||
if (has_error) {
|
||||
s_active_channel = SIZE_MAX;
|
||||
}
|
||||
return ws2812_status_apply();
|
||||
}
|
||||
|
||||
esp_err_t ws2812_status_refresh_from_dcdc(void)
|
||||
{
|
||||
const size_t available_channels = dcdc_channel_count();
|
||||
const size_t count = available_channels < WS2812_STATUS_LED_COUNT
|
||||
? available_channels
|
||||
: WS2812_STATUS_LED_COUNT;
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
s_led_state[i] = dcdc_get_state(i);
|
||||
}
|
||||
for (size_t i = count; i < WS2812_STATUS_LED_COUNT; ++i) {
|
||||
s_led_state[i] = false;
|
||||
}
|
||||
return ws2812_status_apply();
|
||||
}
|
||||
20
main/ws2812_status.h
Normal file
20
main/ws2812_status.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifndef CONFIG_WATCH_WS2812_LED_COUNT
|
||||
#define CONFIG_WATCH_WS2812_LED_COUNT 5
|
||||
#endif
|
||||
|
||||
#define WS2812_STATUS_LED_COUNT CONFIG_WATCH_WS2812_LED_COUNT
|
||||
|
||||
esp_err_t ws2812_status_init(void);
|
||||
esp_err_t ws2812_status_set_channel_state(size_t channel, bool enabled);
|
||||
esp_err_t ws2812_status_mark_active(size_t channel);
|
||||
esp_err_t ws2812_status_clear_active(void);
|
||||
esp_err_t ws2812_status_set_error(bool has_error);
|
||||
esp_err_t ws2812_status_refresh_from_dcdc(void);
|
||||
Reference in New Issue
Block a user