Deluge Firmware 1.3.0
Build date: 2026.08.23
Loading...
Searching...
No Matches
rainfall.h
1/*
2 * Copyright © 2026 Synthstrom Audible Limited
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include <array>
21#include <cstddef>
22#include <cstdint>
23
24namespace deluge::hid::display {
25
34class Rainfall {
35public:
40 static constexpr int32_t kWidth = 128;
41 static constexpr int32_t kHeight = 48;
42 static constexpr int32_t kTopmost = 5;
43 static constexpr int32_t kVisibleHeight = kHeight - kTopmost;
45
48
50 static constexpr size_t kNumDrops = 34;
52 static constexpr float kSpeedFar = 0.5f;
61 static constexpr float kSpeedNear = 1.5f;
62
68 static constexpr float kSpeedStep = 0.25f;
69
75 static constexpr float kSpawnFromTop = static_cast<float>(kWidth) / static_cast<float>(kWidth + kVisibleHeight);
76
78 static constexpr int32_t kSpawnAttempts = 6;
79
82
84 static constexpr size_t kLogoCells = 25;
85 static constexpr int32_t kLogoGridWidth = 11;
86 static constexpr int32_t kLogoGridHeight = 10;
87
93 static constexpr int32_t kLogoIntervalMinFrames = 2400;
94 static constexpr int32_t kLogoIntervalMaxFrames = 7200;
96
102 static constexpr float kLogoSmallScaleChance = 0.10f;
103
105
112 [[nodiscard]] static constexpr float minGapFor(int32_t size) {
113 return (size == 3) ? 5.0f : ((size == 2) ? 4.0f : 3.0f);
114 }
115
117
121 struct Block {
122 int32_t x;
123 int32_t y;
124 int32_t size;
125 };
126
129 struct Streak {
130 float x;
131 float y;
132 int32_t size;
133 int32_t length;
134 };
135
145 [[nodiscard]] static float separationSquared(const Streak& a, const Streak& b);
146
150
154 void scatter();
155
157 void advance();
158
163 [[nodiscard]] size_t lengthOf(size_t drop) const { return drops_[drop].length; }
164
170 [[nodiscard]] Block cellAt(size_t drop, size_t cell) const;
171
176 [[nodiscard]] float speedOf(size_t drop) const { return drops_[drop].speed; }
177
185
187 [[nodiscard]] bool logoActive() const { return logo_.active; }
188
194 [[nodiscard]] Block logoCellAt(size_t cell) const;
195
199 [[nodiscard]] int32_t logoScale() const { return logo_.active ? logo_.size : 0; }
200
204 [[nodiscard]] float logoSpeed() const { return logo_.active ? logo_.speed : 0.0f; }
205
210 void forceLogo() { logoCountdown_ = 0; }
211
213
214private:
215 struct Drop {
216 float x{};
217 float y{};
218 int32_t axisOffset{};
219 float speed{};
220 uint8_t size{};
221 uint8_t length{};
222 };
223
229 [[nodiscard]] static constexpr float reachOf(int32_t size, int32_t length) {
230 return static_cast<float>((length - 1) * size);
231 }
232
237 [[nodiscard]] static Streak streakOf(const Drop& drop) {
238 return {.x = drop.x, .y = drop.y, .size = drop.size, .length = drop.length};
239 }
240
244 uint32_t nextRandom();
245
249 float nextRandomFloat();
250
254 void roll(Drop& drop);
255
260 void place(Drop& drop, bool seeded);
261
267 struct Logo {
268 float x{};
269 float y{};
270 int32_t axisOffset{};
271 float speed{};
272 uint8_t size{};
273 bool active{};
274 };
275
277 void emitLogo();
278
280 void advanceLogo();
281
283 int32_t nextLogoInterval();
284
289 void spawn(size_t index, bool seeded);
290
291 std::array<Drop, kNumDrops> drops_{};
292 Logo logo_{};
296 uint32_t rngState_{0x1EAF7A11};
297};
298
299} // namespace deluge::hid::display
int32_t logoCountdown_
Definition rainfall.h:295
uint32_t nextRandom()
Step the linear congruential generator.
Definition rainfall.cpp:65
static constexpr float reachOf(int32_t size, int32_t length)
Distance a streak's tail trails behind its head, on each axis, in pixels.
Definition rainfall.h:229
static constexpr float kSpeedFar
Speed of the most distant drops, px per frame, applied to both axes. On the kSpeedStep grid.
Definition rainfall.h:52
float speedOf(size_t drop) const
Speed of a drop, px per frame. Exposed for tests.
Definition rainfall.h:176
static constexpr float minGapFor(int32_t size)
Minimum distance allowed between two live drops of the same block size, px.
Definition rainfall.h:112
Block cellAt(size_t drop, size_t cell) const
One block of a drop's streak.
Definition rainfall.cpp:270
bool logoActive() const
Definition rainfall.h:187
void spawn(size_t index, bool seeded)
Replace drops_[index], honouring the minimum-spacing rule.
Definition rainfall.cpp:124
static constexpr int32_t kSpawnAttempts
Candidate positions tried per spawn before settling for the roomiest one found.
Definition rainfall.h:78
static constexpr size_t kLogoCells
Cells in the logo's grid, and the width and height of that grid in cells.
Definition rainfall.h:84
void emitLogo()
Start a logo falling, picking its scale, speed and entry edge.
Definition rainfall.cpp:160
static Streak streakOf(const Drop &drop)
Extract a drop's shape and position as a Streak, for spacing checks.
Definition rainfall.h:237
static constexpr float kSpeedStep
Granularity every drop's speed is snapped to, px per frame.
Definition rainfall.h:68
static constexpr float kSpeedNear
Speed of the nearest drops, px per frame, applied to both axes. On the kSpeedStep grid.
Definition rainfall.h:61
Block logoCellAt(size_t cell) const
One cell of the logo.
Definition rainfall.cpp:257
void place(Drop &drop, bool seeded)
Position a drop, either scattered across the panel or entering an edge.
Definition rainfall.cpp:94
float logoSpeed() const
Speed of the live logo, px per frame. Exposed for tests.
Definition rainfall.h:204
static constexpr int32_t kLogoIntervalMinFrames
Shortest and longest wait between logo emissions, in frames.
Definition rainfall.h:93
size_t lengthOf(size_t drop) const
Cells in a drop's streak.
Definition rainfall.h:163
void advance()
Advance every drop one frame, respawning any whose tail has left the panel.
Definition rainfall.cpp:239
int32_t logoScale() const
Cell scale of the live logo, in pixels. Exposed for tests.
Definition rainfall.h:199
int32_t nextLogoInterval()
Definition rainfall.cpp:220
static constexpr float kSpawnFromTop
Chance that a respawning drop enters through the top edge rather than the left.
Definition rainfall.h:75
static constexpr float kLogoSmallScaleChance
Chance a logo is emitted at the smallest cell scale.
Definition rainfall.h:102
float nextRandomFloat()
Step the linear congruential generator, mapped to [0, 1).
Definition rainfall.cpp:70
void advanceLogo()
Move the live logo, retire it once clear, and run the emission countdown.
Definition rainfall.cpp:200
static constexpr size_t kNumDrops
Drops in the field at once.
Definition rainfall.h:50
Rainfall()
Construct a field that is already populated, so the first rendered frame is not empty.
Definition rainfall.h:149
static float separationSquared(const Streak &a, const Streak &b)
Squared distance between two streaks, px squared.
Definition rainfall.cpp:45
void scatter()
Re-seed every drop across the panel.
Definition rainfall.cpp:225
void roll(Drop &drop)
Give a drop a fresh depth, and the size, speed and length that follow from it.
Definition rainfall.cpp:74
void forceLogo()
Emit a logo on the next advance(), whatever the countdown says.
Definition rainfall.h:210
A single square block of a streak.
Definition rainfall.h:121
int32_t size
1, 2 or 3, pixels square
Definition rainfall.h:124
int32_t x
left edge, pixels
Definition rainfall.h:122
int32_t y
top edge, pixels
Definition rainfall.h:123
Definition rainfall.h:215
float speed
px per frame, applied to both axes
Definition rainfall.h:219
float y
leading cell, top edge; derived as x - axisOffset
Definition rainfall.h:217
uint8_t size
1, 2 or 3; zero marks a slot not yet placed
Definition rainfall.h:220
float x
leading cell, left edge; the only axis that is integrated
Definition rainfall.h:216
int32_t axisOffset
whole pixels, x - y; fixed for the drop's life
Definition rainfall.h:218
uint8_t length
3 or 4 cells
Definition rainfall.h:221
The whole logo, as one object.
Definition rainfall.h:267
int32_t axisOffset
whole pixels, x - y; fixed for the emission
Definition rainfall.h:270
uint8_t size
cell scale in pixels: 1, 2 or 3
Definition rainfall.h:272
float speed
px per frame, native to size, on the kSpeedStep grid
Definition rainfall.h:271
float x
grid origin, left edge; the only axis that is integrated
Definition rainfall.h:268
float y
grid origin, top edge; derived as x - axisOffset
Definition rainfall.h:269
A streak's shape and position, without its motion. Exposed so the spacing rule can be unit-tested aga...
Definition rainfall.h:129
float x
leading cell, left edge
Definition rainfall.h:130
float y
leading cell, top edge
Definition rainfall.h:131
int32_t size
1, 2 or 3
Definition rainfall.h:132
int32_t length
3 or 4 cells
Definition rainfall.h:133