From 8e5574ab497bac2f9793a6ddcf7c3fd8daf02d6c Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Sat, 4 Dec 2021 17:23:43 +0100 Subject: [PATCH] Move animation_solid from drivers to zmk/src/animation --- app/CMakeLists.txt | 4 +- app/Kconfig | 14 +++ app/drivers/Kconfig | 1 - app/drivers/animation/CMakeLists.txt | 6 -- app/drivers/animation/Kconfig | 9 -- app/drivers/animation/solid_color.c | 130 ------------------------ app/src/animation/animation_solid.c | 144 +++++++++++++++++++++++++++ 7 files changed, 161 insertions(+), 147 deletions(-) delete mode 100644 app/drivers/animation/CMakeLists.txt delete mode 100644 app/drivers/animation/Kconfig delete mode 100644 app/drivers/animation/solid_color.c create mode 100644 app/src/animation/animation_solid.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index d35ca3cb..3515dbf2 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -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) diff --git a/app/Kconfig b/app/Kconfig index 1537bd61..9762d6c8 100644 --- a/app/Kconfig +++ b/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 diff --git a/app/drivers/Kconfig b/app/drivers/Kconfig index 0c6431b2..c57ed334 100644 --- a/app/drivers/Kconfig +++ b/app/drivers/Kconfig @@ -2,7 +2,6 @@ # SPDX-License-Identifier: MIT rsource "gpio/Kconfig" -rsource "animation/Kconfig" rsource "kscan/Kconfig" rsource "sensor/Kconfig" rsource "display/Kconfig" diff --git a/app/drivers/animation/CMakeLists.txt b/app/drivers/animation/CMakeLists.txt deleted file mode 100644 index 8cb5a708..00000000 --- a/app/drivers/animation/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) 2020 The ZMK Contributors -# SPDX-License-Identifier: MIT - -zephyr_library() - -zephyr_library_sources(solid_color.c) diff --git a/app/drivers/animation/Kconfig b/app/drivers/animation/Kconfig deleted file mode 100644 index 2f1ac02a..00000000 --- a/app/drivers/animation/Kconfig +++ /dev/null @@ -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. diff --git a/app/drivers/animation/solid_color.c b/app/drivers/animation/solid_color.c deleted file mode 100644 index d86b77ed..00000000 --- a/app/drivers/animation/solid_color.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2020 The ZMK Contributors - * - * SPDX-License-Identifier: MIT - */ - -#define DT_DRV_COMPAT zmk_colors_animation - -#include - -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? diff --git a/app/src/animation/animation_solid.c b/app/src/animation/animation_solid.c new file mode 100644 index 00000000..6d485dce --- /dev/null +++ b/app/src/animation/animation_solid.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_animation_solid + +#include +#include +#include +#include + +#include + +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?