Move animation_solid from drivers to zmk/src/animation
This commit is contained in:
parent
105afca3d9
commit
8e5574ab49
7 changed files with 161 additions and 147 deletions
|
@ -80,14 +80,16 @@ target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/behaviors/behavior_bac
|
|||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/battery_state_changed.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/battery.c)
|
||||
|
||||
target_sources_ifdef(CONFIG_ZMK_ANIMATION app PRIVATE src/animation/animation.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_ANIMATION app PRIVATE src/animation/color.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_ANIMATION app PRIVATE src/animation/animation_solid.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_ANIMATION app PRIVATE src/animation/animation.c)
|
||||
|
||||
target_sources_ifdef(CONFIG_ZMK_SPLIT app PRIVATE src/events/split_peripheral_status_changed.c)
|
||||
add_subdirectory(src/split)
|
||||
|
||||
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/backlight.c)
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
|
|
14
app/Kconfig
14
app/Kconfig
|
@ -301,6 +301,20 @@ config ZMK_BACKLIGHT_AUTO_OFF_USB
|
|||
#ZMK_BACKLIGHT
|
||||
endif
|
||||
|
||||
config ZMK_ANIMATION
|
||||
bool "RGB Animations"
|
||||
select LED_STRIP
|
||||
|
||||
if ZMK_ANIMATION
|
||||
|
||||
config ZMK_ANIMATION_FPS
|
||||
int "Animation FPS"
|
||||
range 0 60
|
||||
default 30
|
||||
|
||||
#ZMK_ANIMATION
|
||||
endif
|
||||
|
||||
#Display/LED Options
|
||||
endmenu
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
|
||||
rsource "gpio/Kconfig"
|
||||
rsource "animation/Kconfig"
|
||||
rsource "kscan/Kconfig"
|
||||
rsource "sensor/Kconfig"
|
||||
rsource "display/Kconfig"
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(solid_color.c)
|
|
@ -1,9 +0,0 @@
|
|||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config ZMK_ANIMATION
|
||||
bool "RGB Animations"
|
||||
depends on I2C
|
||||
depends on LED_STRIP
|
||||
help
|
||||
Enable RGB animations.
|
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_colors_animation
|
||||
|
||||
#include <zephyr.h>
|
||||
|
||||
struct solid_color_animation_config config {
|
||||
zmk_color_hsl[] colors;
|
||||
uint8_t num_colors;
|
||||
uint16_t duration;
|
||||
uint16_t transition_duration;
|
||||
};
|
||||
|
||||
struct solid_color_animation_data data {
|
||||
bool has_changed;
|
||||
|
||||
uint16_t counter;
|
||||
|
||||
zmk_color_hsl current_hsl;
|
||||
zmk_color_rgb current_rgb;
|
||||
};
|
||||
|
||||
// or just colors array ? And if just one it stays the same otherwise it just chagnes color. genius
|
||||
|
||||
static void colors_animation_prep_next_frame(const struct device *dev) {
|
||||
const struct solid_color_animation_config *config = dev->config;
|
||||
const struct solid_color_animation_data *data = dev->data;
|
||||
|
||||
// Animation only contains a single color, nothing to do
|
||||
if (config->num_colors == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t from = data->counter / config->transition_duration;
|
||||
const size_t to = (from + 1) % config->num_colors;
|
||||
|
||||
struct zmk_color_hsl next_hsl;
|
||||
|
||||
zmk_interpolate_hsl(
|
||||
&config->colors[from],
|
||||
&config->colors[to],
|
||||
&next_hsl,
|
||||
(data->counter % config->transition_duration) / (float) config->transition_duration
|
||||
);
|
||||
|
||||
data->has_changed = !zmk_cmp_hsl(&data->current_hsl, &next_hsl);
|
||||
|
||||
data->current_hsl = next_hsl;
|
||||
zmk_hsl_to_rgb(data->current_rgb, data->current_hsl);
|
||||
|
||||
data->counter = (data->counter + 1) % config.duration;
|
||||
}
|
||||
|
||||
static void colors_animation_solid(const struct device *dev, animation_pixel *pixel) {
|
||||
const struct solid_color_animation_config config = dev->config;
|
||||
|
||||
pixel->rgb = data->current_rgb;
|
||||
}
|
||||
|
||||
static void animation_solid_color_init(const struct device *dev) {
|
||||
const struct solid_color_animation_config config = dev->config;
|
||||
|
||||
// Actually... I'm not sure fi there's anything to set up here, is there?
|
||||
// But I do need a public function for has_changed
|
||||
}
|
||||
|
||||
// #define ANIMATION_SOLID_COLOR_DEVICE(idx)
|
||||
//
|
||||
|
||||
|
||||
// use union type to cast from uint_32t to struct { uint16_t, uint8_t, uint8_t } ?
|
||||
|
||||
static const struct animation_api solid_color_animation_api = {
|
||||
.prep_next_frame = solid_color_animation_prep_next_frame,
|
||||
.get_pixel = solid_color_animation_get_pixel,
|
||||
};
|
||||
|
||||
static struct solid_color_animation_data solid_color_animation_##idx##_data;
|
||||
|
||||
static uint32_t solid_color_animation_##idx##_colors[DT_INST_PROP_LEN(idx, colors)] = DT_INST_PROP(idx, colors);
|
||||
|
||||
static struct solid_color_animation_config solid_color_animation_##idx##_config = {
|
||||
.colors = (struct zmk_color_hsl *) solid_color_animation_##idx##_colors,
|
||||
.num_colors = DT_INST_PROP_LEN(idx, colors),
|
||||
.duration = DT_INST_PROP(idx, duration),
|
||||
.transition_duration = DT_INST_PROP(idx, duration) / DT_INST_PROP_LEN(idx, colors),
|
||||
};
|
||||
|
||||
|
||||
|
||||
// To do:
|
||||
//
|
||||
// STEP 1: single animation
|
||||
// - Start with a single animation, just color
|
||||
// - Add layer for taking the output from here and putting it to the led strip
|
||||
// - Make it work
|
||||
//
|
||||
// STEP 2: areas, in fact, instead of defining them explicitly we can just use appropriate x,y coordinates and animation.
|
||||
// - Split keyboard in two independent areas
|
||||
// - Make it work
|
||||
//
|
||||
// STEP 3: add additional animation effects
|
||||
// - Basically, carry over rgb_underglow.
|
||||
// - Make it work
|
||||
//
|
||||
// STEP 4: add animation triggers
|
||||
// - Allow an animation to be triggered by behaviors or key-presses
|
||||
// - Make it work
|
||||
//
|
||||
// STEP 5: add animation layers and a MULTIPLY mode (again, opacity would be set on individual pixels so... that affects some optimizations I guess)
|
||||
// - Normal mode: overrides layers below
|
||||
// - Multiply mode: auguments whatever is below (opacity, whatever)
|
||||
//
|
||||
// Voila! Animation composition!
|
||||
//
|
||||
// STEP 6, BONUS!:
|
||||
// - Figure out a way to switch animations during runtime?
|
||||
//
|
||||
// Notes:
|
||||
// - Any animation settings go into 'driver' config & data, so they can be updated at runtime.
|
||||
// - Main limitation is space, so the amount of different animations one can have loaded
|
||||
//
|
||||
// More notes:
|
||||
// - Solid color would be one animation (just transitions between colors)
|
||||
// - Gradient (SPECTRUM) would be another, you choose how they're distributed accross the keys and if they move?
|
||||
// - Effects like 'breathe' can be implemented by specifying #000 as one of the colors or using a multiply layer?
|
144
app/src/animation/animation_solid.c
Normal file
144
app/src/animation/animation_solid.c
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_animation_solid
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <device.h>
|
||||
#include <drivers/animation.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
#include <zmk/animation.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct animation_solid_config {
|
||||
struct zmk_color_hsl *colors;
|
||||
uint8_t num_colors;
|
||||
uint16_t duration;
|
||||
uint16_t transition_duration;
|
||||
};
|
||||
|
||||
struct animation_solid_data {
|
||||
bool has_changed;
|
||||
|
||||
uint16_t counter;
|
||||
|
||||
struct zmk_color_hsl current_hsl;
|
||||
struct zmk_color_rgb current_rgb;
|
||||
};
|
||||
|
||||
static void animation_solid_prep_next_frame(const struct device *dev) {
|
||||
const struct animation_solid_config *config = dev->config;
|
||||
struct animation_solid_data *data = dev->data;
|
||||
|
||||
// Animation only contains a single color, nothing to do
|
||||
if (config->num_colors == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t from = data->counter / config->transition_duration;
|
||||
const size_t to = (from + 1) % config->num_colors;
|
||||
|
||||
struct zmk_color_hsl next_hsl;
|
||||
|
||||
zmk_interpolate_hsl(
|
||||
&config->colors[from],
|
||||
&config->colors[to],
|
||||
&next_hsl,
|
||||
(data->counter % config->transition_duration) / (float) config->transition_duration
|
||||
);
|
||||
|
||||
data->has_changed = !zmk_cmp_hsl(&data->current_hsl, &next_hsl);
|
||||
|
||||
data->current_hsl = next_hsl;
|
||||
zmk_hsl_to_rgb(&data->current_hsl, &data->current_rgb);
|
||||
|
||||
data->counter = (data->counter + 1) % config->duration;
|
||||
}
|
||||
|
||||
static void animation_solid_get_pixel(const struct device *dev, const struct animation_pixel_position *position,
|
||||
struct zmk_color_rgb *value) {
|
||||
const struct animation_solid_data *data = dev->data;
|
||||
|
||||
value->r = data->current_rgb.r;
|
||||
value->g = data->current_rgb.g;
|
||||
value->b = data->current_rgb.b;
|
||||
}
|
||||
|
||||
static int animation_solid_init(const struct device *dev) {
|
||||
const struct animation_solid_config *config = dev->config;
|
||||
struct animation_solid_data *data = dev->data;
|
||||
|
||||
data->counter = 0;
|
||||
data->current_hsl = config->colors[0];
|
||||
|
||||
zmk_hsl_to_rgb(&data->current_hsl, &data->current_rgb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct animation_api animation_solid_api = {
|
||||
.prep_next_frame = animation_solid_prep_next_frame,
|
||||
.get_pixel = animation_solid_get_pixel,
|
||||
};
|
||||
|
||||
#define ANIMATION_SOLID_DEVICE(idx) \
|
||||
\
|
||||
static struct animation_solid_data animation_solid_##idx##_data; \
|
||||
\
|
||||
static uint32_t animation_solid_##idx##_colors[DT_INST_PROP_LEN(idx, colors)] = DT_INST_PROP(idx, colors); \
|
||||
\
|
||||
static struct animation_solid_config animation_solid_##idx##_config = { \
|
||||
.colors = (struct zmk_color_hsl *) animation_solid_##idx##_colors, \
|
||||
.num_colors = DT_INST_PROP_LEN(idx, colors), \
|
||||
.duration = DT_INST_PROP(idx, duration) * CONFIG_ZMK_ANIMATION_FPS, \
|
||||
.transition_duration = (DT_INST_PROP(idx, duration) * CONFIG_ZMK_ANIMATION_FPS) / DT_INST_PROP_LEN(idx, colors), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(idx, &animation_solid_init, NULL, &animation_solid_##idx##_data, \
|
||||
&animation_solid_##idx##_config, POST_KERNEL, CONFIG_LED_STRIP_INIT_PRIORITY, \
|
||||
&animation_solid_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(ANIMATION_SOLID_DEVICE);
|
||||
|
||||
|
||||
// To do:
|
||||
//
|
||||
// STEP 1: single animation
|
||||
// - Start with a single animation, just color
|
||||
// - Add layer for taking the output from here and putting it to the led strip
|
||||
// - Make it work
|
||||
//
|
||||
// STEP 2: areas, in fact, instead of defining them explicitly we can just use appropriate x,y coordinates and animation.
|
||||
// - Split keyboard in two independent areas
|
||||
// - Make it work
|
||||
//
|
||||
// STEP 3: add additional animation effects
|
||||
// - Basically, carry over rgb_underglow.
|
||||
// - Make it work
|
||||
//
|
||||
// STEP 4: add animation triggers
|
||||
// - Allow an animation to be triggered by behaviors or key-presses
|
||||
// - Make it work
|
||||
//
|
||||
// STEP 5: add animation layers and a MULTIPLY mode (again, opacity would be set on individual pixels so... that affects some optimizations I guess)
|
||||
// - Normal mode: overrides layers below
|
||||
// - Multiply mode: auguments whatever is below (opacity, whatever)
|
||||
//
|
||||
// Voila! Animation composition!
|
||||
//
|
||||
// STEP 6, BONUS!:
|
||||
// - Figure out a way to switch animations during runtime?
|
||||
//
|
||||
// Notes:
|
||||
// - Any animation settings go into 'driver' config & data, so they can be updated at runtime.
|
||||
// - Main limitation is space, so the amount of different animations one can have loaded
|
||||
//
|
||||
// More notes:
|
||||
// - Solid color would be one animation (just transitions between colors)
|
||||
// - Gradient (SPECTRUM) would be another, you choose how they're distributed accross the keys and if they move?
|
||||
// - Effects like 'breathe' can be implemented by specifying #000 as one of the colors or using a multiply layer?
|
Loading…
Add table
Reference in a new issue