feat(uno-q): add bloom, breathe, checker effects to the matrix sampler

Rounds out the sampler with the remaining effects:
- bloom   — a filled diamond grows from the centre to full, then collapses.
- breathe — a dithered shimmer that swells and fades (density ramp via a
            fixed per-pixel threshold, since the matrix can't truly fade).
- checker — a checkerboard that inverts on each beat.

Full cycle is now rain -> knight-rider -> comet -> ripple -> bloom ->
breathe -> sparkle -> checker -> wipe. Compiled + flashed E2E (2057 bytes).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Omar Sobh
2026-07-08 14:51:40 -07:00
co-authored by Claude Opus 4.8
parent 45a8feb8b4
commit 5f2456e5cb
2 changed files with 54 additions and 2 deletions
@@ -1,6 +1,7 @@
// Matrix animation sampler for the Arduino Uno Q's 13x8 blue LED matrix.
// Cycles through several frame-based effects: rain -> knight-rider sweep ->
// comet -> ripple -> sparkle -> wipe, then repeats. All monochrome (pixels are on/off;
// comet -> ripple -> bloom -> breathe -> sparkle -> checker -> wipe, then
// repeats. All monochrome (pixels are on/off;
// the LEDs are physically blue — there is no colour or brightness control).
//
// Shared pattern: each effect fills the 8x13 `grid`, then show() packs it into
@@ -139,6 +140,54 @@ void comet(uint16_t frames) {
}
}
// --- bloom: a filled diamond grows from the centre to full, then collapses ---
void bloom(uint8_t reps) {
const int cx = 6, cy = 3;
for (uint8_t r0 = 0; r0 < reps; r0++) {
for (uint8_t dir = 0; dir < 2; dir++) {
for (int r = 0; r <= 8; r++) {
int rad = dir ? (8 - r) : r;
clearGrid();
for (int y = 0; y < H; y++)
for (int x = 0; x < W; x++)
if (max(abs(x - cx), abs(y - cy)) <= rad) grid[y][x] = true;
show(80);
}
}
}
}
// --- breathe: a dithered shimmer whose density swells and fades (no true fade,
// so we ramp how many pixels are lit via a fixed per-pixel threshold) ---
void breathe(uint8_t breaths) {
static uint8_t thr[H][W];
for (uint8_t y = 0; y < H; y++)
for (uint8_t x = 0; x < W; x++) thr[y][x] = random(0, 100);
for (uint8_t b = 0; b < breaths; b++) {
for (uint8_t dir = 0; dir < 2; dir++) {
for (int s = 0; s <= 100; s += 8) {
int level = dir ? (100 - s) : s;
clearGrid();
for (uint8_t y = 0; y < H; y++)
for (uint8_t x = 0; x < W; x++)
if (thr[y][x] < level) grid[y][x] = true;
show(45);
}
}
}
}
// --- checker: a checkerboard that inverts on each beat ---
void checker(uint8_t flips) {
for (uint8_t p = 0; p < flips; p++) {
clearGrid();
for (uint8_t y = 0; y < H; y++)
for (uint8_t x = 0; x < W; x++)
if (((x + y + p) & 1) == 0) grid[y][x] = true;
show(250);
}
}
void setup() {
matrix.begin();
randomSeed(micros());
@@ -149,6 +198,9 @@ void loop() {
knight(2);
comet(120);
ripple(2);
bloom(2);
breathe(2);
sparkle(40);
checker(6);
wipe(2);
}