156 lines
3.8 KiB
C
156 lines
3.8 KiB
C
|
|
#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,
|
||
|
|
};
|