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 <device.h>
#include <drivers/led_strip.h>
#include <zmk/animation.h>
/**
@ -19,17 +20,33 @@
* 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
extern "C" {
#endif
/**
* @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
@ -37,36 +54,42 @@ typedef void (*animation_api_prep_next_frame)(const struct device *dev);
*
* @see animation_prep_next_frame() for argument descriptions.
*/
typedef void (*animation_api_get_pixel)(const struct device *dev,
const struct animation_pixel_position *pixel_position,
struct zmk_color_rgb *value);
typedef void (*animation_api_render_pixel)(const struct device *dev,
const struct animation_pixel *pixel,
struct zmk_color_rgb *value);
struct animation_api {
animation_api_prep_next_frame prep_next_frame;
animation_api_get_pixel get_pixel;
animation_api_on_before_frame on_before_frame;
animation_api_on_after_frame on_after_frame;
animation_api_render_pixel render_pixel;
};
/**
* [animation_prep_next_frame description]
* @param dev [description]
*/
static inline void animation_prep_next_frame(const struct device *dev) {
static inline void animation_on_before_frame(const struct device *dev) {
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);
}
/**
* [animation_get_pixel description]
* @param dev [description]
* @param pixel [description]
*/
static inline void animation_get_pixel(const struct device *dev,
const struct animation_pixel_position *pixel_position,
struct zmk_color_rgb *value) {
static inline void animation_on_after_frame(const struct device *dev) {
const struct animation_api *api = (const struct animation_api *)dev->api;
return api->get_pixel(dev, pixel_position, value);
if (api->on_after_frame == NULL) {
return;
}
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) {
const struct animation_api *api = (const struct animation_api *)dev->api;
return api->render_pixel(dev, pixel, value);
}
#ifdef __cplusplus

View file

@ -9,16 +9,6 @@
#include <device.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 {
float r;
float g;

View file

@ -32,12 +32,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#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)), \
.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) {
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) {
@ -96,7 +94,7 @@ static void zmk_animation_tick(struct k_work *work) {
.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]);
}
@ -108,6 +106,10 @@ static void zmk_animation_tick(struct k_work *work) {
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);

View file

@ -31,7 +31,7 @@ struct animation_solid_data {
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;
struct animation_solid_data *data = dev->data;
@ -57,9 +57,9 @@ static void animation_solid_prep_next_frame(const struct device *dev) {
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) {
static void animation_solid_render_pixel(const struct device *dev,
const struct animation_pixel *pixel,
struct zmk_color_rgb *value) {
const struct animation_solid_data *data = dev->data;
value->r = data->current_rgb.r;
@ -80,8 +80,9 @@ static int animation_solid_init(const struct device *dev) {
}
static const struct animation_api animation_solid_api = {
.prep_next_frame = animation_solid_prep_next_frame,
.get_pixel = animation_solid_get_pixel,
.on_before_frame = animation_solid_on_before_frame,
.on_after_frame = NULL,
.render_pixel = animation_solid_render_pixel,
};
#define ANIMATION_SOLID_DEVICE(idx) \