FastLED 3.9.15
Loading...
Searching...
No Matches
ease.cpp
Go to the documentation of this file.
1#ifndef FASTLED_INTERNAL
2#define FASTLED_INTERNAL
3#endif
4
5#include "FastLED.h"
6
7#include "fl/ease.h"
8#include "lib8tion.h" // This is the problematic header that's hard to include
9
10#include "fl/map_range.h"
11#include "lib8tion/intmap.h"
12#include "fl/sin32.h"
13#include "fl/int.h"
14
15namespace fl {
16
17// Gamma 2.8 lookup table for 8-bit to 16-bit gamma correction
18// This table converts linear 8-bit values to gamma-corrected 16-bit values
19// using a gamma curve of 2.8 (commonly used for LED brightness correction)
20const u16 gamma_2_8[256] FL_PROGMEM = {
21 0, 0, 0, 1, 1, 2, 4, 6, 8, 11,
22 14, 18, 23, 29, 35, 41, 49, 57, 67, 77,
23 88, 99, 112, 126, 141, 156, 173, 191, 210, 230,
24 251, 274, 297, 322, 348, 375, 404, 433, 464, 497,
25 531, 566, 602, 640, 680, 721, 763, 807, 853, 899,
26 948, 998, 1050, 1103, 1158, 1215, 1273, 1333, 1394, 1458,
27 1523, 1590, 1658, 1729, 1801, 1875, 1951, 2029, 2109, 2190,
28 2274, 2359, 2446, 2536, 2627, 2720, 2816, 2913, 3012, 3114,
29 3217, 3323, 3431, 3541, 3653, 3767, 3883, 4001, 4122, 4245,
30 4370, 4498, 4627, 4759, 4893, 5030, 5169, 5310, 5453, 5599,
31 5747, 5898, 6051, 6206, 6364, 6525, 6688, 6853, 7021, 7191,
32 7364, 7539, 7717, 7897, 8080, 8266, 8454, 8645, 8838, 9034,
33 9233, 9434, 9638, 9845, 10055, 10267, 10482, 10699, 10920, 11143,
34 11369, 11598, 11829, 12064, 12301, 12541, 12784, 13030, 13279, 13530,
35 13785, 14042, 14303, 14566, 14832, 15102, 15374, 15649, 15928, 16209,
36 16493, 16781, 17071, 17365, 17661, 17961, 18264, 18570, 18879, 19191,
37 19507, 19825, 20147, 20472, 20800, 21131, 21466, 21804, 22145, 22489,
38 22837, 23188, 23542, 23899, 24260, 24625, 24992, 25363, 25737, 26115,
39 26496, 26880, 27268, 27659, 28054, 28452, 28854, 29259, 29667, 30079,
40 30495, 30914, 31337, 31763, 32192, 32626, 33062, 33503, 33947, 34394,
41 34846, 35300, 35759, 36221, 36687, 37156, 37629, 38106, 38586, 39071,
42 39558, 40050, 40545, 41045, 41547, 42054, 42565, 43079, 43597, 44119,
43 44644, 45174, 45707, 46245, 46786, 47331, 47880, 48432, 48989, 49550,
44 50114, 50683, 51255, 51832, 52412, 52996, 53585, 54177, 54773, 55374,
45 55978, 56587, 57199, 57816, 58436, 59061, 59690, 60323, 60960, 61601,
46 62246, 62896, 63549, 64207, 64869, 65535};
47
48// 8-bit easing functions
50 // Simple quadratic ease-in: i^2 scaled to 8-bit range
51 // Using scale8(i, i) which computes (i * i) / 255
52 return scale8(i, i);
53}
54
56 constexpr u16 MAX = 0xFF; // 255
57 constexpr u16 HALF = (MAX + 1) >> 1; // 128
58 constexpr u16 DENOM = MAX; // divisor for scaling
59 constexpr u16 ROUND = DENOM >> 1; // for rounding
60
61 if (i < HALF) {
62 // first half: y = 2·(i/MAX)² → y_i = 2·i² / MAX
63 u32 t = i;
64 u32 num = 2 * t * t + ROUND; // 2*i², +half for rounding
65 return u8(num / DENOM);
66 } else {
67 // second half: y = 1 − 2·(1−i/MAX)²
68 // → y_i = MAX − (2·(MAX−i)² / MAX)
69 u32 d = MAX - i;
70 u32 num = 2 * d * d + ROUND; // 2*(MAX−i)², +half for rounding
71 return u8(MAX - (num / DENOM));
72 }
73}
74
76 constexpr u16 MAX = 0xFF; // 255
77 constexpr u16 HALF = (MAX + 1) >> 1; // 128
78 constexpr u32 DENOM = (u32)MAX * MAX; // 255*255 = 65025
79 constexpr u32 ROUND = DENOM >> 1; // for rounding
80
81 if (i < HALF) {
82 // first half: y = 4·(i/MAX)³ → y_i = 4·i³ / MAX²
83 u32 ii = i;
84 u32 cube = ii * ii * ii; // i³
85 u32 num = 4 * cube + ROUND; // 4·i³, +half denom for rounding
86 return u8(num / DENOM);
87 } else {
88 // second half: y = 1 − ((−2·t+2)³)/2
89 // where t = i/MAX; equivalently:
90 // y_i = MAX − (4·(MAX−i)³ / MAX²)
91 u32 d = MAX - i;
92 u32 cube = d * d * d; // (MAX−i)³
93 u32 num = 4 * cube + ROUND;
94 return u8(MAX - (num / DENOM));
95 }
96}
97
99 // ease-out is the inverse of ease-in: 1 - (1-t)²
100 // For 8-bit: y = MAX - (MAX-i)² / MAX
101 constexpr u16 MAX = 0xFF;
102 u32 d = MAX - i; // (MAX - i)
103 u32 num = d * d + (MAX >> 1); // (MAX-i)² + rounding
104 return u8(MAX - (num / MAX));
105}
106
108 // Simple cubic ease-in: i³ scaled to 8-bit range
109 // y = i³ / MAX²
110 constexpr u16 MAX = 0xFF;
111 constexpr u32 DENOM = (u32)MAX * MAX;
112 constexpr u32 ROUND = DENOM >> 1;
113
114 u32 ii = i;
115 u32 cube = ii * ii * ii; // i³
116 u32 num = cube + ROUND;
117 return u8(num / DENOM);
118}
119
121 // ease-out cubic: 1 - (1-t)³
122 // For 8-bit: y = MAX - (MAX-i)³ / MAX²
123 constexpr u16 MAX = 0xFF;
124 constexpr u32 DENOM = (u32)MAX * MAX;
125 constexpr u32 ROUND = DENOM >> 1;
126
127 u32 d = MAX - i; // (MAX - i)
128 u32 cube = d * d * d; // (MAX-i)³
129 u32 num = cube + ROUND;
130 return u8(MAX - (num / DENOM));
131}
132
134
135 static const u8 easeInSineTable[256] = {
136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
137 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4,
138 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8,
139 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14,
140 15, 16, 16, 17, 17, 18, 18, 19, 20, 20, 21, 21, 22, 23,
141 23, 24, 25, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 33,
142 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 42, 43, 44,
143 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 54, 55, 56, 57,
144 58, 59, 60, 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 72,
145 73, 74, 75, 76, 77, 79, 80, 81, 82, 83, 84, 86, 87, 88,
146 89, 90, 91, 93, 94, 95, 96, 98, 99, 100, 101, 103, 104, 105,
147 106, 108, 109, 110, 112, 113, 114, 115, 117, 118, 119, 121, 122, 123,
148 125, 126, 127, 129, 130, 132, 133, 134, 136, 137, 139, 140, 141, 143,
149 144, 146, 147, 148, 150, 151, 153, 154, 156, 157, 159, 160, 161, 163,
150 164, 166, 167, 169, 170, 172, 173, 175, 176, 178, 179, 181, 182, 184,
151 185, 187, 188, 190, 191, 193, 194, 196, 197, 199, 200, 202, 204, 205,
152 207, 208, 210, 211, 213, 214, 216, 217, 219, 221, 222, 224, 225, 227,
153 228, 230, 231, 233, 235, 236, 238, 239, 241, 242, 244, 246, 247, 249,
154 250, 252, 253, 255};
155
156 // ease-in sine: 1 - cos(t * π/2)
157 // Handle boundary conditions explicitly
158 return easeInSineTable[i];
159}
160
162 // ease-out sine: sin(t * π/2)
163 // Delegate to 16-bit version for consistency and accuracy
164 // Scale 8-bit input to 16-bit range, call 16-bit function, scale result back
165 u16 input16 = map8_to_16(i);
166 u16 result16 = easeOutSine16(input16);
167 return map16_to_8(result16);
168}
169
171 // ease-in-out sine: -(cos(π*t) - 1) / 2
172 // Delegate to 16-bit version for consistency and accuracy
173 // Scale 8-bit input to 16-bit range, call 16-bit function, scale result back
174 u16 input16 = map8_to_16(i);
175 u16 result16 = easeInOutSine16(input16);
176 return map16_to_8(result16);
177}
178
179// 16-bit easing functions
180u16 easeInQuad16(u16 i) {
181 // Simple quadratic ease-in: i^2 scaled to 16-bit range
182 // Using scale16(i, i) which computes (i * i) / 65535
183 return scale16(i, i);
184}
185
187 // 16-bit quadratic ease-in / ease-out function
188 constexpr u32 MAX = 0xFFFF; // 65535
189 constexpr u32 HALF = (MAX + 1) >> 1; // 32768
190 constexpr u32 DENOM = MAX; // divisor
191 constexpr u32 ROUND = DENOM >> 1; // for rounding
192
193 if (x < HALF) {
194 // first half: y = 2·(x/MAX)² → y_i = 2·x² / MAX
195 fl::u64 xi = x;
196 fl::u64 num = 2 * xi * xi + ROUND; // 2*x², +half for rounding
197 return u16(num / DENOM);
198 } else {
199 // second half: y = 1 − 2·(1−x/MAX)² → y_i = MAX − (2·(MAX−x)² / MAX)
200 fl::u64 d = MAX - x;
201 fl::u64 num = 2 * d * d + ROUND; // 2*(MAX−x)², +half for rounding
202 return u16(MAX - (num / DENOM));
203 }
204}
205
207 const u32 MAX = 0xFFFF; // 65535
208 const u32 HALF = (MAX + 1) >> 1; // 32768
209 const fl::u64 M2 = (fl::u64)MAX * MAX; // 65535² = 4 294 836 225
210
211 if (x < HALF) {
212 // first half: y = 4·(x/MAX)³ → y_i = 4·x³ / MAX²
213 fl::u64 xi = x;
214 fl::u64 cube = xi * xi * xi; // x³
215 // add M2/2 for rounding
216 fl::u64 num = 4 * cube + (M2 >> 1);
217 return (u16)(num / M2);
218 } else {
219 // second half: y = 1 − ((2·(1−x/MAX))³)/2
220 // → y_i = MAX − (4·(MAX−x)³ / MAX²)
221 fl::u64 d = MAX - x;
222 fl::u64 cube = d * d * d; // (MAX−x)³
223 fl::u64 num = 4 * cube + (M2 >> 1);
224 return (u16)(MAX - (num / M2));
225 }
226}
227
228u16 easeOutQuad16(u16 i) {
229 // ease-out quadratic: 1 - (1-t)²
230 // For 16-bit: y = MAX - (MAX-i)² / MAX
231 constexpr u32 MAX = 0xFFFF; // 65535
232 constexpr u32 ROUND = MAX >> 1; // for rounding
233
234 fl::u64 d = MAX - i; // (MAX - i)
235 fl::u64 num = d * d + ROUND; // (MAX-i)² + rounding
236 return u16(MAX - (num / MAX));
237}
238
239u16 easeInCubic16(u16 i) {
240 // Simple cubic ease-in: i³ scaled to 16-bit range
241 // y = i³ / MAX²
242 constexpr u32 MAX = 0xFFFF; // 65535
243 constexpr fl::u64 DENOM = (fl::u64)MAX * MAX; // 65535²
244 constexpr fl::u64 ROUND = DENOM >> 1; // for rounding
245
246 fl::u64 ii = i;
247 fl::u64 cube = ii * ii * ii; // i³
248 fl::u64 num = cube + ROUND;
249 return u16(num / DENOM);
250}
251
252u16 easeOutCubic16(u16 i) {
253 // ease-out cubic: 1 - (1-t)³
254 // For 16-bit: y = MAX - (MAX-i)³ / MAX²
255 constexpr u32 MAX = 0xFFFF; // 65535
256 constexpr fl::u64 DENOM = (fl::u64)MAX * MAX; // 65535²
257 constexpr fl::u64 ROUND = DENOM >> 1; // for rounding
258
259 fl::u64 d = MAX - i; // (MAX - i)
260 fl::u64 cube = d * d * d; // (MAX-i)³
261 fl::u64 num = cube + ROUND;
262 return u16(MAX - (num / DENOM));
263}
264
265u16 easeInSine16(u16 i) {
266 // ease-in sine: 1 - cos(t * π/2)
267 // Handle boundary conditions explicitly
268 if (i == 0)
269 return 0;
270 // Remove the hard-coded boundary for 65535 and let math handle it
271
272 // For 16-bit: use cos32 for efficiency and accuracy
273 // Map i from [0,65535] to [0,4194304] in cos32 space (zero to quarter wave)
274 // Formula: 1 - cos(t * π/2) where t goes from 0 to 1
275 // sin32/cos32 quarter cycle is 16777216/4 = 4194304
276 u32 angle = ((fl::u64)i * 4194304ULL) / 65535ULL;
277 i32 cos_result = fl::cos32(angle);
278
279 // Convert cos32 output and apply easing formula: 1 - cos(t * π/2)
280 // cos32 output range is [-2147418112, 2147418112]
281 // At t=0: cos(0) = 2147418112, result should be 0
282 // At t=1: cos(π/2) = 0, result should be 65535
283
284 const fl::i64 MAX_COS32 = 2147418112LL;
285
286 // Calculate: (MAX_COS32 - cos_result) and scale to [0, 65535]
287 fl::i64 adjusted = MAX_COS32 - (fl::i64)cos_result;
288
289 // Scale from [0, 2147418112] to [0, 65535]
290 fl::u64 result = (fl::u64)adjusted * 65535ULL + (MAX_COS32 >> 1); // Add half for rounding
291 u16 final_result = (u16)(result / (fl::u64)MAX_COS32);
292
293 return final_result;
294}
295
296u16 easeOutSine16(u16 i) {
297 // ease-out sine: sin(t * π/2)
298 // Handle boundary conditions explicitly
299 if (i == 0)
300 return 0;
301 if (i == 65535)
302 return 65535;
303
304 // For 16-bit: use sin32 for efficiency and accuracy
305 // Map i from [0,65535] to [0,4194304] in sin32 space (zero to quarter wave)
306 // Formula: sin(t * π/2) where t goes from 0 to 1
307 // sin32 quarter cycle is 16777216/4 = 4194304
308 u32 angle = ((fl::u64)i * 4194304ULL) / 65535ULL;
309 i32 sin_result = fl::sin32(angle);
310
311 // Convert sin32 output range [-2147418112, 2147418112] to [0, 65535]
312 // sin32 output is in range -32767*65536 to +32767*65536
313 // For ease-out sine, we only use positive portion [0, 2147418112] -> [0, 65535]
314 return (u16)((fl::u64)sin_result * 65535ULL / 2147418112ULL);
315}
316
317u16 easeInOutSine16(u16 i) {
318 // ease-in-out sine: -(cos(π*t) - 1) / 2
319 // Handle boundary conditions explicitly
320 if (i == 0)
321 return 0;
322 if (i == 65535)
323 return 65535;
324
325 // For 16-bit: use cos32 for efficiency and accuracy
326 // Map i from [0,65535] to [0,8388608] in cos32 space (0 to half wave)
327 // Formula: (1 - cos(π*t)) / 2 where t goes from 0 to 1
328 // sin32/cos32 half cycle is 16777216/2 = 8388608
329 u32 angle = ((fl::u64)i * 8388608ULL) / 65535ULL;
330 i32 cos_result = fl::cos32(angle);
331
332 // Convert cos32 output and apply easing formula: (1 - cos(π*t)) / 2
333 // cos32 output range is [-2147418112, 2147418112]
334 // We want: (2147418112 - cos_result) / 2, then scale to [0, 65535]
335 fl::i64 adjusted = (2147418112LL - (fl::i64)cos_result) / 2;
336 return (u16)((fl::u64)adjusted * 65535ULL / 2147418112ULL);
337}
338
339} // namespace fl
int x
Definition simple.h:92
central include file for FastLED, defines the CFastLED class/object
Result type for promise operations.
static uint32_t t
Definition Luminova.h:54
#define FL_PROGMEM
PROGMEM keyword for storage.
LIB8STATIC uint16_t scale16(uint16_t i, fract16 scale)
Scale a 16-bit unsigned value by an 16-bit value, which is treated as the numerator of a fraction who...
Definition scale8.h:551
LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale)
Scale one byte by a second one, which is treated as the numerator of a fraction whose denominator is ...
Definition scale8.h:44
LIB8STATIC_ALWAYS_INLINE uint8_t map16_to_8(uint16_t x)
Definition intmap.h:35
LIB8STATIC_ALWAYS_INLINE uint16_t map8_to_16(uint8_t x)
Definition intmap.h:25
Defines integer mapping functions.
Fast, efficient 8-bit math functions specifically designed for high-performance LED programming.
#define MAX(a, b)
Definition math_macros.h:37
unsigned char u8
Definition int.h:17
u16 easeInOutSine16(u16 i)
16-bit sine ease-in/ease-out function Takes an input value 0-65535 and returns an eased value 0-65535
Definition ease.cpp:317
u8 easeInCubic8(u8 i)
8-bit cubic ease-in function Takes an input value 0-255 and returns an eased value 0-255 More pronoun...
Definition ease.cpp:107
u8 easeInOutSine8(u8 i)
8-bit sine ease-in/ease-out function Takes an input value 0-255 and returns an eased value 0-255 Smoo...
Definition ease.cpp:170
u8 easeOutSine8(u8 i)
8-bit sine ease-out function Takes an input value 0-255 and returns an eased value 0-255 Smooth sinus...
Definition ease.cpp:161
u8 easeOutCubic8(u8 i)
8-bit cubic ease-out function Takes an input value 0-255 and returns an eased value 0-255 More pronou...
Definition ease.cpp:120
u16 easeOutQuad16(u16 i)
16-bit quadratic ease-out function Takes an input value 0-65535 and returns an eased value 0-65535
Definition ease.cpp:228
u8 easeInSine8(u8 i)
8-bit sine ease-in function Takes an input value 0-255 and returns an eased value 0-255 Smooth sinuso...
Definition ease.cpp:133
u16 easeInSine16(u16 i)
16-bit sine ease-in function Takes an input value 0-65535 and returns an eased value 0-65535
Definition ease.cpp:265
static FASTLED_FORCE_INLINE i32 cos32(u32 angle)
Definition sin32.h:45
u8 easeOutQuad8(u8 i)
8-bit quadratic ease-out function Takes an input value 0-255 and returns an eased value 0-255 The cur...
Definition ease.cpp:98
u8 easeInQuad8(u8 i)
8-bit quadratic ease-in function Takes an input value 0-255 and returns an eased value 0-255 The curv...
Definition ease.cpp:49
static FASTLED_FORCE_INLINE i32 sin32(u32 angle)
Definition sin32.h:36
u16 easeOutSine16(u16 i)
16-bit sine ease-out function Takes an input value 0-65535 and returns an eased value 0-65535
Definition ease.cpp:296
const u16 gamma_2_8[256]
Definition ease.cpp:20
u16 easeInOutCubic16(u16 x)
16-bit cubic ease-in/ease-out function Takes an input value 0-65535 and returns an eased value 0-6553...
Definition ease.cpp:206
u16 easeOutCubic16(u16 i)
16-bit cubic ease-out function Takes an input value 0-65535 and returns an eased value 0-65535
Definition ease.cpp:252
u8 easeInOutCubic8(u8 i)
8-bit cubic ease-in/ease-out function Takes an input value 0-255 and returns an eased value 0-255 Mor...
Definition ease.cpp:75
u16 easeInCubic16(u16 i)
16-bit cubic ease-in function Takes an input value 0-65535 and returns an eased value 0-65535
Definition ease.cpp:239
u16 easeInOutQuad16(u16 x)
16-bit quadratic ease-in/ease-out function Takes an input value 0-65535 and returns an eased value 0-...
Definition ease.cpp:186
u16 easeInQuad16(u16 i)
16-bit quadratic ease-in function Takes an input value 0-65535 and returns an eased value 0-65535
Definition ease.cpp:180
u8 easeInOutQuad8(u8 i)
8-bit quadratic ease-in/ease-out function Takes an input value 0-255 and returns an eased value 0-255...
Definition ease.cpp:55
IMPORTANT!
Definition crgb.h:20