Refactor the animation api to allow for pre- and post-frame hooks

This commit is contained in:
Kuba Birecki 2021-12-11 17:57:46 +01:00
parent 2dfec75038
commit cc70d75238
4 changed files with 62 additions and 46 deletions

View file

@ -9,6 +9,7 @@
#include <zephyr/types.h> #include <zephyr/types.h>
#include <device.h> #include <device.h>
#include <drivers/led_strip.h> #include <drivers/led_strip.h>
#include <zmk/animation.h> #include <zmk/animation.h>
/** /**
@ -19,17 +20,33 @@
* for various types of 2D animations. * for various types of 2D animations.
*/ */
struct animation_pixel {
const size_t id;
const uint8_t position_x;
const uint8_t position_y;
const struct device *animation;
};
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** /**
* @typedef animation_api_prep_next_frame * @typedef animation_api_prep_next_frame
* @brief Callback API for generating the next animation frame * @brief Callback run before every frame is rendered.
* *
* @see animation_prep_next_frame() for argument descriptions. * @see animation_api_before_frame() for argument descriptions.
*/ */
typedef void (*animation_api_prep_next_frame)(const struct device *dev); typedef void (*animation_api_on_before_frame)(const struct device *dev);
/**
* @typedef animation_api_prep_next_frame
* @brief Callback run after every frame is rendered.
*
* @see animation_api_before_frame() for argument descriptions.
*/
typedef void (*animation_api_on_after_frame)(const struct device *dev);
/** /**
* @typedef animation_api_prep_next_frame * @typedef animation_api_prep_next_frame
@ -37,36 +54,42 @@ typedef void (*animation_api_prep_next_frame)(const struct device *dev);
* *
* @see animation_prep_next_frame() for argument descriptions. * @see animation_prep_next_frame() for argument descriptions.
*/ */
typedef void (*animation_api_get_pixel)(const struct device *dev, typedef void (*animation_api_render_pixel)(const struct device *dev,
const struct animation_pixel_position *pixel_position, const struct animation_pixel *pixel,
struct zmk_color_rgb *value); struct zmk_color_rgb *value);
struct animation_api { struct animation_api {
animation_api_prep_next_frame prep_next_frame; animation_api_on_before_frame on_before_frame;
animation_api_get_pixel get_pixel; animation_api_on_after_frame on_after_frame;
animation_api_render_pixel render_pixel;
}; };
/** static inline void animation_on_before_frame(const struct device *dev) {
* [animation_prep_next_frame description]
* @param dev [description]
*/
static inline void animation_prep_next_frame(const struct device *dev) {
const struct animation_api *api = (const struct animation_api *)dev->api; const struct animation_api *api = (const struct animation_api *)dev->api;
return api->prep_next_frame(dev); if (api->on_before_frame == NULL) {
return;
}
api->on_before_frame(dev);
} }
/** static inline void animation_on_after_frame(const struct device *dev) {
* [animation_get_pixel description] const struct animation_api *api = (const struct animation_api *)dev->api;
* @param dev [description]
* @param pixel [description] if (api->on_after_frame == NULL) {
*/ return;
static inline void animation_get_pixel(const struct device *dev, }
const struct animation_pixel_position *pixel_position,
api->on_after_frame(dev);
}
static inline void animation_render_pixel(const struct device *dev,
const struct animation_pixel *pixel,
struct zmk_color_rgb *value) { struct zmk_color_rgb *value) {
const struct animation_api *api = (const struct animation_api *)dev->api; const struct animation_api *api = (const struct animation_api *)dev->api;
return api->get_pixel(dev, pixel_position, value); return api->render_pixel(dev, pixel, value);
} }
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -9,16 +9,6 @@
#include <device.h> #include <device.h>
#include <drivers/led_strip.h> #include <drivers/led_strip.h>
struct animation_pixel_position {
const uint8_t x;
const uint8_t y;
};
struct animation_pixel {
const struct device *animation;
const struct animation_pixel_position position;
};
struct zmk_color_rgb { struct zmk_color_rgb {
float r; float r;
float g; float g;

View file

@ -32,12 +32,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#define PHANDLE_TO_PIXEL(idx, node_id, prop) \ #define PHANDLE_TO_PIXEL(idx, node_id, prop) \
{ \ { \
.id = idx, \
.position_x = DT_PHA_BY_IDX(node_id, prop, idx, position_x), \
.position_y = DT_PHA_BY_IDX(node_id, prop, idx, position_y), \
.animation = DEVICE_DT_GET(DT_PHANDLE_BY_IDX(node_id, prop, idx)), \ .animation = DEVICE_DT_GET(DT_PHANDLE_BY_IDX(node_id, prop, idx)), \
.position = \
{ \
.x = DT_PHA_BY_IDX(node_id, prop, idx, position_x), \
.y = DT_PHA_BY_IDX(node_id, prop, idx, position_y), \
}, \
}, },
/** /**
@ -86,7 +84,7 @@ static struct led_rgb px_buffer[DT_INST_PROP_LEN(0, pixels)];
static void zmk_animation_tick(struct k_work *work) { static void zmk_animation_tick(struct k_work *work) {
for (size_t i = 0; i < animations_size; ++i) { for (size_t i = 0; i < animations_size; ++i) {
animation_prep_next_frame(animations[i]); animation_on_before_frame(animations[i]);
} }
for (size_t i = 0; i < pixels_size; ++i) { for (size_t i = 0; i < pixels_size; ++i) {
@ -96,7 +94,7 @@ static void zmk_animation_tick(struct k_work *work) {
.b = 0, .b = 0,
}; };
animation_get_pixel(pixels[i].animation, &pixels[i].position, &rgb); animation_render_pixel(pixels[i].animation, &pixels[i], &rgb);
zmk_rgb_to_led_rgb(&rgb, &px_buffer[i]); zmk_rgb_to_led_rgb(&rgb, &px_buffer[i]);
} }
@ -108,6 +106,10 @@ static void zmk_animation_tick(struct k_work *work) {
pixels_updated += (size_t)pixels_per_driver; pixels_updated += (size_t)pixels_per_driver;
} }
for (size_t i = 0; i < animations_size; ++i) {
animation_on_after_frame(animations[i]);
}
} }
K_WORK_DEFINE(animation_work, zmk_animation_tick); K_WORK_DEFINE(animation_work, zmk_animation_tick);

View file

@ -31,7 +31,7 @@ struct animation_solid_data {
struct zmk_color_rgb current_rgb; struct zmk_color_rgb current_rgb;
}; };
static void animation_solid_prep_next_frame(const struct device *dev) { static void animation_solid_on_before_frame(const struct device *dev) {
const struct animation_solid_config *config = dev->config; const struct animation_solid_config *config = dev->config;
struct animation_solid_data *data = dev->data; struct animation_solid_data *data = dev->data;
@ -57,8 +57,8 @@ static void animation_solid_prep_next_frame(const struct device *dev) {
data->counter = (data->counter + 1) % config->duration; data->counter = (data->counter + 1) % config->duration;
} }
static void animation_solid_get_pixel(const struct device *dev, static void animation_solid_render_pixel(const struct device *dev,
const struct animation_pixel_position *position, const struct animation_pixel *pixel,
struct zmk_color_rgb *value) { struct zmk_color_rgb *value) {
const struct animation_solid_data *data = dev->data; const struct animation_solid_data *data = dev->data;
@ -80,8 +80,9 @@ static int animation_solid_init(const struct device *dev) {
} }
static const struct animation_api animation_solid_api = { static const struct animation_api animation_solid_api = {
.prep_next_frame = animation_solid_prep_next_frame, .on_before_frame = animation_solid_on_before_frame,
.get_pixel = animation_solid_get_pixel, .on_after_frame = NULL,
.render_pixel = animation_solid_render_pixel,
}; };
#define ANIMATION_SOLID_DEVICE(idx) \ #define ANIMATION_SOLID_DEVICE(idx) \