RGB Sunglasses Animation Extension API fw-v3.8.1-1-geacf2f0
rgbx ABI + C++ wrapper for sandboxed .llext animations
Loading...
Searching...
No Matches
rgbx_animation.h
Go to the documentation of this file.
1
41#ifndef RGBX_ANIMATION_H_
42#define RGBX_ANIMATION_H_
43
44#ifndef __cplusplus
45#error "rgbx_animation.h is the C++ wrapper; C extensions should use rgbx_api.h directly"
46#endif
47
48#include <rgbx/rgbx_api.h>
49#include <zephyr/llext/symbol.h>
50
51#include <type_traits>
52
53namespace rgbx {
54
59class Animation {
60 public:
63 virtual void init() {}
64
72 virtual void tick(uint32_t dt_ms) = 0;
73
82 virtual bool goodMoment() const { return true; }
83
84 protected:
85 /* Non-virtual on purpose: instances are static and never deleted
86 * polymorphically, and a virtual destructor would drag in operator
87 * delete, which the sandbox does not provide. */
88 ~Animation() = default;
89
92 size_t width() const { return rgbx_manifest.width; }
95 size_t height() const { return rgbx_manifest.height; }
96
108 void setPixel(size_t x, size_t y, uint8_t r, uint8_t g, uint8_t b) {
109 if (x >= width() || y >= height()) {
110 return;
111 }
112 uint8_t *px = &rgbx_framebuffer[RGBX_PIXEL_INDEX(width(), x, y)];
113 px[0] = r;
114 px[1] = g;
115 px[2] = b;
116 }
117
123 void fill(uint8_t r, uint8_t g, uint8_t b) {
124 const size_t n = width() * height();
125 for (size_t i = 0; i < n; i++) {
126 uint8_t *px = &rgbx_framebuffer[i * 3u];
127 px[0] = r;
128 px[1] = g;
129 px[2] = b;
130 }
131 }
132
133 /* --- typed parameter accessors (manifest declaration order) ---------- */
134
138 uint32_t paramU32(size_t i) const {
139 return (i < RGBX_MAX_PARAMS) ? rgbx_inputs.params[i] : 0u;
140 }
141
145 uint32_t param(size_t i) const { return paramU32(i); }
146
150 uint32_t paramColor(size_t i) const { return paramU32(i) & 0x00FFFFFFu; }
151
155 bool paramBool(size_t i) const { return paramU32(i) != 0u; }
156
166 float paramF32(size_t i) const {
167 const uint32_t bits = paramU32(i);
168 float value;
169 __builtin_memcpy(&value, &bits, sizeof(value));
170 return value;
171 }
172
182 const char *paramString(size_t i) const {
183 if (i >= rgbx_manifest.param_count ||
185 return "";
186 }
187 size_t slot = 0;
188 for (size_t p = 0; p < i; p++) {
190 slot++;
191 }
192 }
193 return (slot < RGBX_MAX_STRING_PARAMS) ? rgbx_inputs.param_strings[slot] : "";
194 }
195
204 float accelX() const { return rgbx_inputs.accel[0]; }
206 float accelY() const { return rgbx_inputs.accel[1]; }
208 float accelZ() const { return rgbx_inputs.accel[2]; }
210 float gyroX() const { return rgbx_inputs.gyro[0]; }
212 float gyroY() const { return rgbx_inputs.gyro[1]; }
214 float gyroZ() const { return rgbx_inputs.gyro[2]; }
215
227 static constexpr size_t numBands() { return RGBX_AUDIO_NUM_BANDS; }
231 float bandEnergy(size_t b) const {
232 return (b < RGBX_AUDIO_NUM_BANDS) ? rgbx_inputs.audio_band_energy[b] : 0.0f;
233 }
237 bool isBeat(size_t b) const {
238 return (b < RGBX_AUDIO_NUM_BANDS) && rgbx_inputs.audio_beat[b] != 0u;
239 }
242 static constexpr size_t numDisplayBuckets() { return RGBX_AUDIO_NUM_DISPLAY_BUCKETS; }
252 float displayBucket(size_t i) const {
254 : 0.0f;
255 }
256
269 uint32_t buttonsPressed() const { return rgbx_inputs.buttons_pressed; }
273 bool buttonWasPressed(size_t id) const {
274 return id < 32 && (rgbx_inputs.buttons_pressed & (1u << id)) != 0u;
275 }
276
278};
279
280} // namespace rgbx
281
308#define RGBX_ANIMATION(ClassName, DisplayName, W, H, ...) \
309 static_assert(std::is_trivially_destructible_v<ClassName>, \
310 "extension animation classes must be trivially destructible (no atexit in " \
311 "the sandbox)"); \
312 extern "C" void __cxa_pure_virtual(void) { \
313 while (true) { \
314 } \
315 } \
316 /* Definitions below pick up C language linkage from the declarations in rgbx_api.h. */ \
317 struct rgbx_inputs rgbx_inputs; \
318 uint8_t rgbx_framebuffer[(size_t)(W) * (size_t)(H) * 3u]; \
319 __VA_OPT__(static const struct rgbx_param_desc rgbx_wrapper_params_[] = {__VA_ARGS__};) \
320 const struct rgbx_manifest rgbx_manifest = { \
321 RGBX_ABI_VERSION, \
322 (DisplayName), \
323 (W), \
324 (H), \
325 0u __VA_OPT__(+sizeof(rgbx_wrapper_params_) / sizeof(rgbx_wrapper_params_[0])), \
326 NULL __VA_OPT__(? NULL : rgbx_wrapper_params_), \
327 }; \
328 static ClassName rgbx_wrapper_instance_; \
329 uint8_t rgbx_good_moment; \
330 void rgbx_init(void) { rgbx_wrapper_instance_.init(); } \
331 void rgbx_tick(void) { \
332 rgbx_wrapper_instance_.tick(rgbx_inputs.dt_ms); \
333 rgbx_good_moment = rgbx_wrapper_instance_.goodMoment() ? 1u : 0u; \
334 } \
335 EXPORT_SYMBOL(rgbx_manifest); \
336 EXPORT_SYMBOL(rgbx_inputs); \
337 EXPORT_SYMBOL(rgbx_framebuffer); \
338 EXPORT_SYMBOL(rgbx_init); \
339 EXPORT_SYMBOL(rgbx_tick); \
340 EXPORT_SYMBOL(rgbx_good_moment)
341
342#endif /* RGBX_ANIMATION_H_ */
Extension-side analog of the firmware's BaseAnimation.
Definition rgbx_animation.h:59
static constexpr size_t numDisplayBuckets()
Number of fine-grained display buckets.
Definition rgbx_animation.h:242
static constexpr size_t numBands()
Number of coarse audio bands.
Definition rgbx_animation.h:227
float accelZ() const
Accelerometer Z for this tick.
Definition rgbx_animation.h:208
bool paramBool(size_t i) const
Value of BOOL parameter i.
Definition rgbx_animation.h:155
virtual bool goodMoment() const
Queried after every tick(): return true when the frame just rendered ended at a natural switch bounda...
Definition rgbx_animation.h:82
const char * paramString(size_t i) const
Value of STRING parameter i.
Definition rgbx_animation.h:182
void setPixel(size_t x, size_t y, uint8_t r, uint8_t g, uint8_t b)
Write one pixel (out-of-range coordinates are ignored).
Definition rgbx_animation.h:108
size_t height() const
Framebuffer height in pixels (manifest value).
Definition rgbx_animation.h:95
uint32_t param(size_t i) const
Alias of paramU32() kept for early extensions.
Definition rgbx_animation.h:145
float gyroY() const
Gyroscope Y for this tick.
Definition rgbx_animation.h:212
float displayBucket(size_t i) const
Energy of one fine-grained spectrum bucket, for bar-graph style visualisation.
Definition rgbx_animation.h:252
float paramF32(size_t i) const
Value of FLOAT parameter i.
Definition rgbx_animation.h:166
uint32_t paramColor(size_t i) const
Value of COLOR parameter i.
Definition rgbx_animation.h:150
void fill(uint8_t r, uint8_t g, uint8_t b)
Fill the whole framebuffer with one color.
Definition rgbx_animation.h:123
float bandEnergy(size_t b) const
Smoothed energy of one coarse band.
Definition rgbx_animation.h:231
bool buttonWasPressed(size_t id) const
Whether one button was pressed since the previous tick.
Definition rgbx_animation.h:273
float accelY() const
Accelerometer Y for this tick.
Definition rgbx_animation.h:206
virtual void tick(uint32_t dt_ms)=0
Called once per frame; render into the framebuffer via setPixel()/fill().
float accelX() const
Accelerometer X for this tick.
Definition rgbx_animation.h:204
uint32_t buttonsPressed() const
Raw pressed-since-last-tick bitmask.
Definition rgbx_animation.h:269
bool isBeat(size_t b) const
Whether a beat fired in one band this frame.
Definition rgbx_animation.h:237
float gyroX() const
Gyroscope X for this tick.
Definition rgbx_animation.h:210
uint32_t paramU32(size_t i) const
Value of UINT32 parameter i.
Definition rgbx_animation.h:138
size_t width() const
Framebuffer width in pixels (manifest value).
Definition rgbx_animation.h:92
virtual void init()
Called once, on the sandboxed thread, after every (re)load and before the first tick.
Definition rgbx_animation.h:63
float gyroZ() const
Gyroscope Z for this tick.
Definition rgbx_animation.h:214
SPDX-License-Identifier: MIT Copyright (c) 2026 Stuart Alldritt.
#define RGBX_MAX_PARAMS
Fixed capacity of the per-extension parameter block.
Definition rgbx_api.h:48
#define RGBX_PIXEL_INDEX(w, x, y)
Byte offset of pixel (x, y) in rgbx_framebuffer for a display w pixels wide.
Definition rgbx_api.h:237
#define RGBX_MAX_STRING_PARAMS
Maximum number of RGBX_PARAM_STRING parameters per extension.
Definition rgbx_api.h:51
#define RGBX_AUDIO_NUM_BANDS
Number of coarse audio bands (energy + beat flag each).
Definition rgbx_api.h:59
uint8_t rgbx_framebuffer[]
The scratch framebuffer the extension renders into, sized exactly width * height * 3 bytes (see RGBX_...
#define RGBX_AUDIO_NUM_DISPLAY_BUCKETS
Number of fine-grained audio display buckets (bar-graph style).
Definition rgbx_api.h:62
@ RGBX_PARAM_STRING
UTF-8 string, at most RGBX_PARAM_STRING_MAX-1 bytes (text field in the companion app)
Definition rgbx_api.h:74
Per-tick input snapshot.
Definition rgbx_api.h:152
float audio_display_bucket[RGBX_AUDIO_NUM_DISPLAY_BUCKETS]
fine-grained spectrum buckets for bar-graph visualisation, low frequencies first (62 Hz–3 kHz).
Definition rgbx_api.h:170
float gyro[3]
IMU gyroscope x/y/z, rad/s.
Definition rgbx_api.h:164
uint32_t buttons_pressed
bit i set = button i was pressed since the previous tick.
Definition rgbx_api.h:179
char param_strings[RGBX_MAX_STRING_PARAMS][RGBX_PARAM_STRING_MAX]
current string parameter values, always NUL-terminated; slot i = the i-th STRING-typed param in decla...
Definition rgbx_api.h:159
float audio_band_energy[RGBX_AUDIO_NUM_BANDS]
smoothed energy per coarse band, low frequencies first
Definition rgbx_api.h:166
uint8_t audio_beat[RGBX_AUDIO_NUM_BANDS]
1 if a beat was detected in that band this frame, else 0
Definition rgbx_api.h:168
uint32_t params[RGBX_MAX_PARAMS]
current scalar parameter values (UINT32/COLOR/BOOL), in manifest declaration order
Definition rgbx_api.h:155
float accel[3]
IMU accelerometer x/y/z, m/s^2.
Definition rgbx_api.h:163
Extension self-description.
Definition rgbx_api.h:128
uint32_t width
framebuffer width the extension renders at; must match the host display (40 on proto0)
Definition rgbx_api.h:131
const struct rgbx_param_desc * params
NULL iff param_count == 0.
Definition rgbx_api.h:137
uint32_t param_count
entries in params, <= RGBX_MAX_PARAMS; at most RGBX_MAX_STRING_PARAMS of them may be RGBX_PARAM_STRIN...
Definition rgbx_api.h:134
uint32_t height
framebuffer height (12 on proto0)
Definition rgbx_api.h:133
enum rgbx_param_type type
value type.
Definition rgbx_api.h:115