feat(led): 添加LED按键淡入淡出效果并重构LED条模块
添加了完整的LED效果系统架构,包括: - 新增主题颜色定义文件theme_color.h - 实现key fade LED效果算法,支持按键触发的渐变效果 - 创建LED效果注册机制和通用接口 - 配置17个LED像素与按键映射关系 - 将原有简单的周期性效果替换为基于按键事件的动态效果 CMakeLists.txt中添加了新的源文件路径和实现文件。 BREAKING CHANGE: LED效果从固定的周期性变化改为响应按键事件的动态效果。
This commit is contained in:
155
src/led_effect/effects/led_effect_key_fade.c
Normal file
155
src/led_effect/effects/led_effect_key_fade.c
Normal file
@@ -0,0 +1,155 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include "led_effect/led_effect.h"
|
||||
|
||||
#define KEY_FADE_LEVEL_MAX 255U
|
||||
#define KEY_FADE_STEP_PER_TICK 12U
|
||||
|
||||
struct led_effect_key_fade_state {
|
||||
const struct led_key_map *key_map;
|
||||
size_t key_map_len;
|
||||
size_t pixel_count;
|
||||
uint8_t default_brightness;
|
||||
uint8_t level[17];
|
||||
struct theme_rgb theme;
|
||||
};
|
||||
|
||||
static struct led_effect_key_fade_state key_fade_state;
|
||||
|
||||
static const struct led_key_map *find_key(const struct led_effect *effect,
|
||||
uint16_t key_id)
|
||||
{
|
||||
const struct led_effect_key_fade_state *state = effect->state;
|
||||
|
||||
for (size_t i = 0; i < state->key_map_len; i++) {
|
||||
if (state->key_map[i].key_id == key_id) {
|
||||
return &state->key_map[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int led_effect_key_fade_init(struct led_effect *effect,
|
||||
const struct led_effect_config *cfg)
|
||||
{
|
||||
struct led_effect_key_fade_state *state = effect->state;
|
||||
|
||||
if ((effect == NULL) || (cfg == NULL) || (cfg->key_map == NULL) ||
|
||||
(cfg->pixel_count > ARRAY_SIZE(state->level))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
state->key_map = cfg->key_map;
|
||||
state->key_map_len = cfg->key_map_len;
|
||||
state->pixel_count = cfg->pixel_count;
|
||||
state->default_brightness = cfg->default_brightness;
|
||||
state->theme.r = BLINKY_THEME_DEFAULT_R;
|
||||
state->theme.g = BLINKY_THEME_DEFAULT_G;
|
||||
state->theme.b = BLINKY_THEME_DEFAULT_B;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void led_effect_key_fade_reset(struct led_effect *effect)
|
||||
{
|
||||
struct led_effect_key_fade_state *state = effect->state;
|
||||
|
||||
memset(state->level, 0, sizeof(state->level));
|
||||
}
|
||||
|
||||
static void led_effect_key_fade_set_theme(struct led_effect *effect,
|
||||
const struct theme_rgb *theme)
|
||||
{
|
||||
struct led_effect_key_fade_state *state = effect->state;
|
||||
|
||||
if (theme == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->theme = *theme;
|
||||
}
|
||||
|
||||
static void led_effect_key_fade_on_key_press(struct led_effect *effect,
|
||||
uint16_t key_id)
|
||||
{
|
||||
struct led_effect_key_fade_state *state = effect->state;
|
||||
const struct led_key_map *map = find_key(effect, key_id);
|
||||
|
||||
if ((map == NULL) || (map->led_idx >= state->pixel_count)) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->level[map->led_idx] =
|
||||
(state->default_brightness == 0U) ? KEY_FADE_LEVEL_MAX :
|
||||
state->default_brightness;
|
||||
}
|
||||
|
||||
static bool led_effect_key_fade_tick(struct led_effect *effect, uint32_t dt_ms,
|
||||
struct led_rgb *pixels, size_t pixel_count)
|
||||
{
|
||||
struct led_effect_key_fade_state *state = effect->state;
|
||||
bool active = false;
|
||||
bool visible = false;
|
||||
uint8_t decay;
|
||||
|
||||
ARG_UNUSED(dt_ms);
|
||||
|
||||
if ((pixels == NULL) || (pixel_count < state->pixel_count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(pixels, 0, sizeof(*pixels) * pixel_count);
|
||||
decay = KEY_FADE_STEP_PER_TICK;
|
||||
|
||||
for (size_t i = 0; i < state->pixel_count; i++) {
|
||||
uint8_t level = state->level[i];
|
||||
|
||||
if (level == 0U) {
|
||||
continue;
|
||||
}
|
||||
|
||||
visible = true;
|
||||
pixels[i].r = (uint8_t)(((uint16_t)state->theme.r * level) / 255U);
|
||||
pixels[i].g = (uint8_t)(((uint16_t)state->theme.g * level) / 255U);
|
||||
pixels[i].b = (uint8_t)(((uint16_t)state->theme.b * level) / 255U);
|
||||
|
||||
state->level[i] = (level > decay) ? (uint8_t)(level - decay) : 0U;
|
||||
active = active || (state->level[i] > 0U);
|
||||
}
|
||||
|
||||
return visible || active;
|
||||
}
|
||||
|
||||
static bool led_effect_key_fade_is_active(const struct led_effect *effect)
|
||||
{
|
||||
const struct led_effect_key_fade_state *state = effect->state;
|
||||
|
||||
for (size_t i = 0; i < state->pixel_count; i++) {
|
||||
if (state->level[i] > 0U) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct led_effect_ops key_fade_ops = {
|
||||
.init = led_effect_key_fade_init,
|
||||
.reset = led_effect_key_fade_reset,
|
||||
.set_theme = led_effect_key_fade_set_theme,
|
||||
.on_key_press = led_effect_key_fade_on_key_press,
|
||||
.tick = led_effect_key_fade_tick,
|
||||
.is_active = led_effect_key_fade_is_active,
|
||||
};
|
||||
|
||||
struct led_effect led_effect_key_fade = {
|
||||
.ops = &key_fade_ops,
|
||||
.state = &key_fade_state,
|
||||
};
|
||||
Reference in New Issue
Block a user