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 -1
View File
@@ -7,7 +7,7 @@ Animations for the Arduino Uno Q's built-in **13×8 monochrome blue** LED matrix
| Sketch | What it does | | Sketch | What it does |
|--------|--------------| |--------|--------------|
| `matrix_rain/` | Digital "rain" — per-column drops (head + short trail) at staggered speeds. | | `matrix_rain/` | Digital "rain" — per-column drops (head + short trail) at staggered speeds. |
| `matrix_effects/` | Sampler that cycles rain → knight-rider sweep → comet → ripple → sparkle → wipe. | | `matrix_effects/` | Sampler that cycles rain → knight-rider → comet → ripple → bloom → breathe → sparkle → checker → wipe. |
## How they work ## How they work
@@ -1,6 +1,7 @@
// Matrix animation sampler for the Arduino Uno Q's 13x8 blue LED matrix. // Matrix animation sampler for the Arduino Uno Q's 13x8 blue LED matrix.
// Cycles through several frame-based effects: rain -> knight-rider sweep -> // 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). // 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 // 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() { void setup() {
matrix.begin(); matrix.begin();
randomSeed(micros()); randomSeed(micros());
@@ -149,6 +198,9 @@ void loop() {
knight(2); knight(2);
comet(120); comet(120);
ripple(2); ripple(2);
bloom(2);
breathe(2);
sparkle(40); sparkle(40);
checker(6);
wipe(2); wipe(2);
} }