Lamp-Da 0.1
A compact lantern project
Loading...
Searching...
No Matches
brightness_modes.hpp
Go to the documentation of this file.
1#ifndef BRIGHTNESS_MODES_H
2#define BRIGHTNESS_MODES_H
3
5
6#include "src/system/ext/random8.h"
7#include "src/system/ext/math8.h"
8
10
11namespace lampda::modes::brightness {
14{
15 static constexpr void loop(auto& ctx)
16 {
17 if constexpr (ctx.lamp.flavor == hardware::LampTypes::indexable)
18 ctx.lamp.fill(colors::Candle);
19 }
20};
21
24
26template<size_t N> struct Pulses : public BasicMode
27{
28 static constexpr uint32_t pulseSizeMs = 100;
29 static constexpr uint32_t periodMs = 1000 + N * pulseSizeMs * 2;
30 static constexpr brightness_t minScaling = 50;
31 static constexpr float scaleFactor = 1.40;
32
33 static constexpr void loop(auto& ctx)
34 {
35 auto& lamp = ctx.lamp;
36
37 brightness_t base = lamp.getSavedBrightness();
38 brightness_t scaled = std::max<brightness_t>(base * scaleFactor, base + minScaling);
39
40 // overflow check
41 if (scaled > lamp.getMaxBrightness())
43
44 auto period = lamp.now % periodMs;
45 // first part of the anim : pulse
46 if (period < pulseSizeMs * N * 2)
47 {
48 uint32_t flipflop = period / pulseSizeMs;
49 if (flipflop % 2)
50 lamp.restoreBrightness();
51 else
52 lamp.tempBrightness(scaled);
53 }
54 // second part: just stay at the saved brightness level
55 else
56 lamp.restoreBrightness();
57 }
58};
59
64struct Candle : public BasicMode
65{
66 static const uint8_t CANDLE_AMPLITUDE = 33;
67 static const uint8_t CANDLE_WAVE1_MAXDEPTH = 30;
68 static const uint8_t CANDLE_WAVE2_MAXDEPTH = 45;
69 static const uint8_t CANDLE_WAVE3_MAXDEPTH = 25;
70
71 struct StateTy
72 {
73 uint8_t candle_wave1;
74 uint8_t candle_wave2;
75 uint8_t candle_wave3;
77
81 };
82
83 static void on_enter_mode(auto& ctx)
84 {
85 ctx.state.candle_wave1 = 0;
86 ctx.state.candle_wave2 = 0;
87 ctx.state.candle_wave3 = 0;
88 ctx.state.candle_wave2_speed = 0;
89
90 ctx.state.candle_wave1_depth = CANDLE_WAVE1_MAXDEPTH * CANDLE_AMPLITUDE / 100;
91 ctx.state.candle_wave2_depth = CANDLE_WAVE2_MAXDEPTH * CANDLE_AMPLITUDE / 100;
92 ctx.state.candle_wave3_depth = CANDLE_WAVE3_MAXDEPTH * CANDLE_AMPLITUDE / 100;
93 }
94
95 static void loop(auto& ctx)
96 {
97 auto& lamp = ctx.lamp;
98
99 const auto maxBrightness = lamp.getMaxBrightness();
100 const float brightnessCorrection = maxBrightness / 255.0;
101
102 // limit max brightness
103 const brightness_t base = std::min<brightness_t>(
104 lamp.getSavedBrightness(),
105 maxBrightness - std::min<int>(maxBrightness, (CANDLE_AMPLITUDE + 15) * brightnessCorrection));
106
107 // 3-oscillator synth for a relatively organic pattern
108 const uint8_t add = ((triwave8(ctx.state.candle_wave1) * ctx.state.candle_wave1_depth) >> 8) +
109 ((triwave8(ctx.state.candle_wave2) * ctx.state.candle_wave2_depth) >> 8) +
110 ((triwave8(ctx.state.candle_wave3) * ctx.state.candle_wave3_depth) >> 8);
111 const brightness_t brightness = base + add * brightnessCorrection;
112
113 // update brightness
114 lamp.setBrightness(brightness);
115
116 // update candle parameters
117 // wave1: slow random LFO
118 // TODO: make wave slower and more erratic?
119 ctx.state.candle_wave1 += random8() & 1;
120 // wave2: medium-speed erratic LFO
121 ctx.state.candle_wave2 += ctx.state.candle_wave2_speed;
122 // wave3: erratic fast wave
123 ctx.state.candle_wave3 += random8() % 37;
124 // S&H on wave2 frequency to make it more erratic
125 if ((random8() & 0b00111111) == 0)
126 ctx.state.candle_wave2_speed = random8() % 13;
127 // downward sawtooth on wave2 depth to simulate stabilizing
128 if ((ctx.state.candle_wave2_depth > 0) && ((random8() & 0b00111111) == 0))
129 ctx.state.candle_wave2_depth--;
130 // random sawtooth retrigger
131 if (random8() == 0)
132 {
133 // random amplitude
134 // candle_wave2_depth = 2 + (random8() % ((CANDLE_WAVE2_MAXDEPTH * CANDLE_AMPLITUDE / 100) - 2));
135 ctx.state.candle_wave2_depth = random8() % (CANDLE_WAVE2_MAXDEPTH * CANDLE_AMPLITUDE / 100);
136 // candle_wave3_depth = 5;
137 ctx.state.candle_wave2 = 0;
138 }
139 // downward sawtooth on wave3 depth to simulate stabilizing
140 if ((ctx.state.candle_wave3_depth > 2) && ((random8() & 0b00011111) == 0))
141 ctx.state.candle_wave3_depth--;
142 if ((random8() & 0b01111111) == 0)
143 // random amplitude
144 // candle_wave3_depth = 2 + (random8() % ((CANDLE_WAVE3_MAXDEPTH * CANDLE_AMPLITUDE / 100) - 2));
145 ctx.state.candle_wave3_depth = random8() % (CANDLE_WAVE3_MAXDEPTH * CANDLE_AMPLITUDE / 100);
146 }
147};
148
153{
155 static constexpr bool hasCustomRamp = true;
157 static constexpr uint32_t stroboMaxFreq = 1000 * (1 / 30.0f);
159 static constexpr uint32_t stroboMinFreq = 1000 * (1 / 7.0f);
160
161 struct StateTy
162 {
164 uint32_t lastCall;
167 };
168
169 static void on_enter_mode(auto& ctx)
170 {
171 ctx.state.lastCall = 0;
172 ctx.template set_config_bool<ConfigKeys::rampSaturates>(true);
173 ctx.template set_config_bool<ConfigKeys::customRampAnimEffect>(false);
174
175 custom_ramp_update(ctx, ctx.get_active_custom_ramp());
176 }
177
179 static void custom_ramp_update(auto& ctx, uint8_t rampValue)
180 {
181 ctx.state.pulseDuration = lmpd_map<uint32_t>(rampValue, 0, 255, stroboMinFreq, stroboMaxFreq);
182 }
183
184 static void loop(auto& ctx)
185 {
186 const auto pulseDuration = ctx.state.pulseDuration;
187
189 static constexpr uint32_t onTime = 5;
190 if (ctx.lamp.now - ctx.state.lastCall >= pulseDuration)
191 {
192 ctx.blip(pulseDuration - onTime);
193 ctx.state.lastCall = ctx.lamp.now;
194 }
195 }
196};
197
203{
205 static constexpr bool hasBrightCallback = true;
206
207 struct StateTy
208 {
216 uint32_t stepdown;
217 };
218
219 static void on_enter_mode(auto& ctx)
220 { //
221 ctx.state.lastBrightnessHandleCall = 0;
222 ctx.state.isWaitingTurnOn = true;
223 ctx.state.lastBrightness = ctx.lamp.getSavedBrightness();
224 ctx.state.stepdown = 0;
225 }
226
228 static void brightness_update(auto& ctx, brightness_t brightness)
229 {
230 auto& lamp = ctx.lamp;
231 lamp.cancel_blip();
232 ctx.state.lastBrightnessHandleCall = lamp.now;
233 }
234
235 static void loop(auto& ctx)
236 {
237 // update brightness
238 auto& lamp = ctx.lamp;
239
240 // no update when ramp is active
241 if (lamp.now - ctx.state.lastBrightnessHandleCall < 100)
242 return;
243
244 // decrease brightness
245
246 if (not ctx.is_bliping())
247 {
248 brightness_t currentBrightness = ctx.state.lastBrightness;
249
250 // lampe is still on, decrease brightess
251 if (ctx.state.isWaitingTurnOn)
252 {
253 const brightness_t savedBrightness = lamp.getSavedBrightness();
254
255 // from anduril
256 uint8_t n_brightness = 1 << (random8() % 7); // 1, 2, 4, 8, 16, 32, 64
257 n_brightness += 1 << (random8() % 5); // 2 to 80 now
258 n_brightness += random8() % n_brightness; // 2 to 159 now (w/ low bias)
259
260 const brightness_t newBrightness = std::min<brightness_t>(
261 savedBrightness, lmpd_map<brightness_t>(n_brightness, 2, 159, 0, savedBrightness));
262 // prepare next brightness
263 lamp.tempBrightness(newBrightness);
264 ctx.state.lastBrightness = newBrightness;
265
266 ctx.state.stepdown = std::max<uint32_t>(1, newBrightness >> 4);
267
268 ctx.state.isWaitingTurnOn = false;
269 }
270 else if (currentBrightness > ctx.state.stepdown)
271 {
272 // bleed flash down
273 if (ctx.state.stepdown > 0)
274 {
275 if (random8() & 0x11 != 0)
276 {
277 currentBrightness >>= 1;
278 }
279 else
280 {
281 currentBrightness -= ctx.state.stepdown;
282 ctx.state.lastBrightness = currentBrightness;
283 }
284 }
285 else
286 {
287 currentBrightness = 0;
288 ctx.state.lastBrightness = 0;
289 }
290
291 lamp.tempBrightness(currentBrightness);
292 }
293 else
294 {
295 currentBrightness = 0;
296
297 // from anduril
298 // for a random amount of time between 1ms and 8192ms
299 uint32_t rand_time = 1 << (random8() % 13);
300 rand_time += random8() % rand_time;
301
302 // turn off for a time
303 ctx.blip(rand_time);
304 ctx.state.isWaitingTurnOn = true;
305 }
306 }
307 // else: we are in a waiting time
308 }
309};
310
315
316} // namespace lampda::modes::brightness
317
318#endif
GroupFor< StaticLightMode > StaticLightOnly
One mode, alone in its group, for static lightning.
Definition: brightness_modes.hpp:23
GroupFor< Candle, LightningMode > CalmGroup
Group for calm modes.
Definition: brightness_modes.hpp:312
GroupFor< StroboscopeMode, Pulses< 1 >, Pulses< 2 > > FlashesGroup
Group for flashing modes.
Definition: brightness_modes.hpp:314
@ Candle
1900 Kelvin
Definition: palettes.hpp:38
@ indexable
Equivalent to LMBD_LAMP_TYPE__INDEXABLE.
GroupTy< std::tuple< Modes... > > GroupFor
Group together many different modes::BasicMode.
Definition: group_type.hpp:335
uint16_t brightness_t
Define the type of the brightness parameters.
Definition: constants.h:147
Parent object for all custom user modes.
Definition: mode_type.hpp:53
Definition: brightness_modes.hpp:72
uint8_t candle_wave2_depth
Control the wave 2 depth.
Definition: brightness_modes.hpp:79
uint8_t candle_wave3_depth
Control the wave 3 depth.
Definition: brightness_modes.hpp:80
uint8_t candle_wave3
triangular wave 3 amplitude
Definition: brightness_modes.hpp:75
uint8_t candle_wave1_depth
Control the wave 1 depth.
Definition: brightness_modes.hpp:78
uint8_t candle_wave2_speed
second wave speed (candle flicker)
Definition: brightness_modes.hpp:76
uint8_t candle_wave2
triangular wave 2 amplitude
Definition: brightness_modes.hpp:74
uint8_t candle_wave1
triangular wave 1 amplitude
Definition: brightness_modes.hpp:73
Based on the candle animation from Anduril. candle-mode.c: Candle mode for Anduril....
Definition: brightness_modes.hpp:65
static const uint8_t CANDLE_AMPLITUDE
amplitude of the candle light
Definition: brightness_modes.hpp:66
static const uint8_t CANDLE_WAVE1_MAXDEPTH
Wave depth parameters.
Definition: brightness_modes.hpp:67
static const uint8_t CANDLE_WAVE3_MAXDEPTH
Wave depth parameters.
Definition: brightness_modes.hpp:69
static const uint8_t CANDLE_WAVE2_MAXDEPTH
Wave depth parameters.
Definition: brightness_modes.hpp:68
Definition: brightness_modes.hpp:208
uint32_t stepdown
Brigthness ramp down index.
Definition: brightness_modes.hpp:216
uint32_t lastBrightnessHandleCall
prevent updates when the user ramp is rolling
Definition: brightness_modes.hpp:210
bool isWaitingTurnOn
Is off and waiting to turn on.
Definition: brightness_modes.hpp:212
brightness_t lastBrightness
last brigthness before going dark
Definition: brightness_modes.hpp:214
Emulate lightning in the distance Inspired by Anduril implementation.
Definition: brightness_modes.hpp:203
static constexpr bool hasBrightCallback
Hint manager that we need a brightness callback.
Definition: brightness_modes.hpp:205
static void brightness_update(auto &ctx, brightness_t brightness)
If user update the brighness, do not update the animation.
Definition: brightness_modes.hpp:228
Pulse N times then pause one second.
Definition: brightness_modes.hpp:27
static constexpr uint32_t pulseSizeMs
lenght of a pulse, in milliseconds
Definition: brightness_modes.hpp:28
static constexpr uint32_t periodMs
period of the animation, in milliseconds
Definition: brightness_modes.hpp:29
static constexpr brightness_t minScaling
scaling of the brightness of a pulse
Definition: brightness_modes.hpp:30
static constexpr float scaleFactor
scale of the brigthness
Definition: brightness_modes.hpp:31
Basic lightning mode (does nothing, brightness may be adjusted)
Definition: brightness_modes.hpp:14
Definition: brightness_modes.hpp:162
uint32_t pulseDuration
duration of the off pulse
Definition: brightness_modes.hpp:166
uint32_t lastCall
last off pulse set
Definition: brightness_modes.hpp:164
Very fast on pulse followed by longer off pulses. Make a stroboscopic effect.
Definition: brightness_modes.hpp:153
static void custom_ramp_update(auto &ctx, uint8_t rampValue)
User ramp controls the strob frequency.
Definition: brightness_modes.hpp:179
static constexpr uint32_t stroboMinFreq
minimum allowed stroboscopic frequency in hertz
Definition: brightness_modes.hpp:159
static constexpr bool hasCustomRamp
regulate stroboscopic speed
Definition: brightness_modes.hpp:155
static constexpr uint32_t stroboMaxFreq
maximum allowed stroboscopic frequency in Hertz
Definition: brightness_modes.hpp:157
static void loop(auto &ctx)
Definition: brightness_modes.hpp:184
brightness_t LMBD_INLINE getMaxBrightness() const
Return the actual allowed maximum brightness.
Definition: lamp_type.hpp:655
void LMBD_INLINE restoreBrightness()
Reset brightness to internal saved brightness, skip callbacks.
Definition: lamp_type.hpp:706
void LMBD_INLINE setBrightness(const brightness_t newBrightness, const bool skipCallbacks=true, const bool skipUpdateBrightness=false, const bool updateSavedBrightess=false)
Set brightness of the lamp.
Definition: lamp_type.hpp:553
void LMBD_INLINE tempBrightness(const brightness_t brightness)
Temporarily set brightness, without affecting brightness navigation.
Definition: lamp_type.hpp:668
void LMBD_INLINE jumpBrightness(const brightness_t brightness)
Jump to brightness, affecting the next brightness navigation.
Definition: lamp_type.hpp:686
volatile const uint32_t now
(physical) The "now" on milliseconds, updated just before loop.
Definition: lamp_type.hpp:1075
brightness_t LMBD_INLINE getSavedBrightness()
Alias for getBrightness(true)
Definition: lamp_type.hpp:703
void LMBD_INLINE cancel_blip() const
Cancel the ongoing blip, if any.
Definition: lamp_type.hpp:526
Define useful functions.