FastLED  3.1
lib8tion.h
1 #ifndef __INC_LIB8TION_H
2 #define __INC_LIB8TION_H
3 
4 #include "FastLED.h"
5 
6 #ifndef __INC_LED_SYSDEFS_H
7 #error WTH? led_sysdefs needs to be included first
8 #endif
9 
10 FASTLED_NAMESPACE_BEGIN
11 
12 /*
13 
14  Fast, efficient 8-bit math functions specifically
15  designed for high-performance LED programming.
16 
17  Because of the AVR(Arduino) and ARM assembly language
18  implementations provided, using these functions often
19  results in smaller and faster code than the equivalent
20  program using plain "C" arithmetic and logic.
21 
22 
23  Included are:
24 
25 
26  - Saturating unsigned 8-bit add and subtract.
27  Instead of wrapping around if an overflow occurs,
28  these routines just 'clamp' the output at a maxumum
29  of 255, or a minimum of 0. Useful for adding pixel
30  values. E.g., qadd8( 200, 100) = 255.
31 
32  qadd8( i, j) == MIN( (i + j), 0xFF )
33  qsub8( i, j) == MAX( (i - j), 0 )
34 
35  - Saturating signed 8-bit ("7-bit") add.
36  qadd7( i, j) == MIN( (i + j), 0x7F)
37 
38 
39  - Scaling (down) of unsigned 8- and 16- bit values.
40  Scaledown value is specified in 1/256ths.
41  scale8( i, sc) == (i * sc) / 256
42  scale16by8( i, sc) == (i * sc) / 256
43 
44  Example: scaling a 0-255 value down into a
45  range from 0-99:
46  downscaled = scale8( originalnumber, 100);
47 
48  A special version of scale8 is provided for scaling
49  LED brightness values, to make sure that they don't
50  accidentally scale down to total black at low
51  dimming levels, since that would look wrong:
52  scale8_video( i, sc) = ((i * sc) / 256) +? 1
53 
54  Example: reducing an LED brightness by a
55  dimming factor:
56  new_bright = scale8_video( orig_bright, dimming);
57 
58 
59  - Fast 8- and 16- bit unsigned random numbers.
60  Significantly faster than Arduino random(), but
61  also somewhat less random. You can add entropy.
62  random8() == random from 0..255
63  random8( n) == random from 0..(N-1)
64  random8( n, m) == random from N..(M-1)
65 
66  random16() == random from 0..65535
67  random16( n) == random from 0..(N-1)
68  random16( n, m) == random from N..(M-1)
69 
70  random16_set_seed( k) == seed = k
71  random16_add_entropy( k) == seed += k
72 
73 
74  - Absolute value of a signed 8-bit value.
75  abs8( i) == abs( i)
76 
77 
78  - 8-bit math operations which return 8-bit values.
79  These are provided mostly for completeness,
80  not particularly for performance.
81  mul8( i, j) == (i * j) & 0xFF
82  add8( i, j) == (i + j) & 0xFF
83  sub8( i, j) == (i - j) & 0xFF
84 
85 
86  - Fast 16-bit approximations of sin and cos.
87  Input angle is a uint16_t from 0-65535.
88  Output is a signed int16_t from -32767 to 32767.
89  sin16( x) == sin( (x/32768.0) * pi) * 32767
90  cos16( x) == cos( (x/32768.0) * pi) * 32767
91  Accurate to more than 99% in all cases.
92 
93  - Fast 8-bit approximations of sin and cos.
94  Input angle is a uint8_t from 0-255.
95  Output is an UNsigned uint8_t from 0 to 255.
96  sin8( x) == (sin( (x/128.0) * pi) * 128) + 128
97  cos8( x) == (cos( (x/128.0) * pi) * 128) + 128
98  Accurate to within about 2%.
99 
100 
101  - Fast 8-bit "easing in/out" function.
102  ease8InOutCubic(x) == 3(x^i) - 2(x^3)
103  ease8InOutApprox(x) ==
104  faster, rougher, approximation of cubic easing
105  ease8InOutQuad(x) == quadratic (vs cubic) easing
106 
107  - Cubic, Quadratic, and Triangle wave functions.
108  Input is a uint8_t representing phase withing the wave,
109  similar to how sin8 takes an angle 'theta'.
110  Output is a uint8_t representing the amplitude of
111  the wave at that point.
112  cubicwave8( x)
113  quadwave8( x)
114  triwave8( x)
115 
116  - Square root for 16-bit integers. About three times
117  faster and five times smaller than Arduino's built-in
118  generic 32-bit sqrt routine.
119  sqrt16( uint16_t x ) == sqrt( x)
120 
121  - Dimming and brightening functions for 8-bit
122  light values.
123  dim8_video( x) == scale8_video( x, x)
124  dim8_raw( x) == scale8( x, x)
125  dim8_lin( x) == (x<128) ? ((x+1)/2) : scale8(x,x)
126  brighten8_video( x) == 255 - dim8_video( 255 - x)
127  brighten8_raw( x) == 255 - dim8_raw( 255 - x)
128  brighten8_lin( x) == 255 - dim8_lin( 255 - x)
129  The dimming functions in particular are suitable
130  for making LED light output appear more 'linear'.
131 
132 
133  - Linear interpolation between two values, with the
134  fraction between them expressed as an 8- or 16-bit
135  fixed point fraction (fract8 or fract16).
136  lerp8by8( fromU8, toU8, fract8 )
137  lerp16by8( fromU16, toU16, fract8 )
138  lerp15by8( fromS16, toS16, fract8 )
139  == from + (( to - from ) * fract8) / 256)
140  lerp16by16( fromU16, toU16, fract16 )
141  == from + (( to - from ) * fract16) / 65536)
142  map8( in, rangeStart, rangeEnd)
143  == map( in, 0, 255, rangeStart, rangeEnd);
144 
145  - Optimized memmove, memcpy, and memset, that are
146  faster than standard avr-libc 1.8.
147  memmove8( dest, src, bytecount)
148  memcpy8( dest, src, bytecount)
149  memset8( buf, value, bytecount)
150 
151  - Beat generators which return sine or sawtooth
152  waves in a specified number of Beats Per Minute.
153  Sine wave beat generators can specify a low and
154  high range for the output. Sawtooth wave beat
155  generators always range 0-255 or 0-65535.
156  beatsin8( BPM, low8, high8)
157  = (sine(beatphase) * (high8-low8)) + low8
158  beatsin16( BPM, low16, high16)
159  = (sine(beatphase) * (high16-low16)) + low16
160  beatsin88( BPM88, low16, high16)
161  = (sine(beatphase) * (high16-low16)) + low16
162  beat8( BPM) = 8-bit repeating sawtooth wave
163  beat16( BPM) = 16-bit repeating sawtooth wave
164  beat88( BPM88) = 16-bit repeating sawtooth wave
165  BPM is beats per minute in either simple form
166  e.g. 120, or Q8.8 fixed-point form.
167  BPM88 is beats per minute in ONLY Q8.8 fixed-point
168  form.
169 
170 Lib8tion is pronounced like 'libation': lie-BAY-shun
171 
172 */
173 
174 
175 
176 #include <stdint.h>
177 
178 #define LIB8STATIC __attribute__ ((unused)) static inline
179 #define LIB8STATIC_ALWAYS_INLINE __attribute__ ((always_inline)) static inline
180 
181 #if !defined(__AVR__)
182 #include <string.h>
183 // for memmove, memcpy, and memset if not defined here
184 #endif
185 
186 #if defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny87__)
187 #define LIB8_ATTINY 1
188 #endif
189 
190 
191 #if defined(__arm__)
192 
193 #if defined(FASTLED_TEENSY3)
194 // Can use Cortex M4 DSP instructions
195 #define QADD8_C 0
196 #define QADD7_C 0
197 #define QADD8_ARM_DSP_ASM 1
198 #define QADD7_ARM_DSP_ASM 1
199 #else
200 // Generic ARM
201 #define QADD8_C 1
202 #define QADD7_C 1
203 #endif
204 
205 #define QSUB8_C 1
206 #define SCALE8_C 1
207 #define SCALE16BY8_C 1
208 #define SCALE16_C 1
209 #define ABS8_C 1
210 #define MUL8_C 1
211 #define QMUL8_C 1
212 #define ADD8_C 1
213 #define SUB8_C 1
214 #define EASE8_C 1
215 #define AVG8_C 1
216 #define AVG7_C 1
217 #define AVG16_C 1
218 #define AVG15_C 1
219 
220 
221 #elif defined(__AVR__)
222 
223 // AVR ATmega and friends Arduino
224 
225 #define QADD8_C 0
226 #define QADD7_C 0
227 #define QSUB8_C 0
228 #define ABS8_C 0
229 #define ADD8_C 0
230 #define SUB8_C 0
231 #define AVG8_C 0
232 #define AVG7_C 0
233 #define AVG16_C 0
234 #define AVG15_C 0
235 
236 #define QADD8_AVRASM 1
237 #define QADD7_AVRASM 1
238 #define QSUB8_AVRASM 1
239 #define ABS8_AVRASM 1
240 #define ADD8_AVRASM 1
241 #define SUB8_AVRASM 1
242 #define AVG8_AVRASM 1
243 #define AVG7_AVRASM 1
244 #define AVG16_AVRASM 1
245 #define AVG15_AVRASM 1
246 
247 // Note: these require hardware MUL instruction
248 // -- sorry, ATtiny!
249 #if !defined(LIB8_ATTINY)
250 #define SCALE8_C 0
251 #define SCALE16BY8_C 0
252 #define SCALE16_C 0
253 #define MUL8_C 0
254 #define QMUL8_C 0
255 #define EASE8_C 0
256 #define SCALE8_AVRASM 1
257 #define SCALE16BY8_AVRASM 1
258 #define SCALE16_AVRASM 1
259 #define MUL8_AVRASM 1
260 #define QMUL8_AVRASM 1
261 #define EASE8_AVRASM 1
262 #define CLEANUP_R1_AVRASM 1
263 #else
264 // On ATtiny, we just use C implementations
265 #define SCALE8_C 1
266 #define SCALE16BY8_C 1
267 #define SCALE16_C 1
268 #define MUL8_C 1
269 #define QMUL8_C 1
270 #define EASE8_C 1
271 #define SCALE8_AVRASM 0
272 #define SCALE16BY8_AVRASM 0
273 #define SCALE16_AVRASM 0
274 #define MUL8_AVRASM 0
275 #define QMUL8_AVRASM 0
276 #define EASE8_AVRASM 0
277 #endif
278 
279 #else
280 
281 // unspecified architecture, so
282 // no ASM, everything in C
283 #define QADD8_C 1
284 #define QADD7_C 1
285 #define QSUB8_C 1
286 #define SCALE8_C 1
287 #define SCALE16BY8_C 1
288 #define SCALE16_C 1
289 #define ABS8_C 1
290 #define MUL8_C 1
291 #define QMUL8_C 1
292 #define ADD8_C 1
293 #define SUB8_C 1
294 #define EASE8_C 1
295 #define AVG8_C 1
296 #define AVG7_C 1
297 #define AVG16_C 1
298 #define AVG15_C 1
299 
300 #endif
301 
305 
306 
308 //
309 // typdefs for fixed-point fractional types.
310 //
311 // sfract7 should be interpreted as signed 128ths.
312 // fract8 should be interpreted as unsigned 256ths.
313 // sfract15 should be interpreted as signed 32768ths.
314 // fract16 should be interpreted as unsigned 65536ths.
315 //
316 // Example: if a fract8 has the value "64", that should be interpreted
317 // as 64/256ths, or one-quarter.
318 //
319 //
320 // fract8 range is 0 to 0.99609375
321 // in steps of 0.00390625
322 //
323 // sfract7 range is -0.9921875 to 0.9921875
324 // in steps of 0.0078125
325 //
326 // fract16 range is 0 to 0.99998474121
327 // in steps of 0.00001525878
328 //
329 // sfract15 range is -0.99996948242 to 0.99996948242
330 // in steps of 0.00003051757
331 //
332 
335 typedef uint8_t fract8;
336 
339 typedef int8_t sfract7;
340 
343 typedef uint16_t fract16;
344 
347 typedef int16_t sfract15;
348 
349 
350 // accumXY types should be interpreted as X bits of integer,
351 // and Y bits of fraction.
352 // E.g., accum88 has 8 bits of int, 8 bits of fraction
353 
354 typedef uint16_t accum88;
355 typedef int16_t saccum78;
356 typedef uint32_t accum1616;
357 typedef int32_t saccum1516;
358 typedef uint16_t accum124;
359 typedef int32_t saccum114;
360 
361 
363 typedef union {
364  uint32_t i;
365  float f;
366  struct {
367  uint32_t mantissa: 23;
368  uint32_t exponent: 8;
369  uint32_t signbit: 1;
370  };
371  struct {
372  uint32_t mant7 : 7;
373  uint32_t mant16: 16;
374  uint32_t exp_ : 8;
375  uint32_t sb_ : 1;
376  };
377  struct {
378  uint32_t mant_lo8 : 8;
379  uint32_t mant_hi16_exp_lo1 : 16;
380  uint32_t sb_exphi7 : 8;
381  };
383 
384 #include "lib8tion/math8.h"
385 #include "lib8tion/scale8.h"
386 #include "lib8tion/random8.h"
387 #include "lib8tion/trig8.h"
388 
390 
391 
392 
393 
394 
395 
396 
398 //
399 // float-to-fixed and fixed-to-float conversions
400 //
401 // Note that anything involving a 'float' on AVR will be slower.
402 
405 LIB8STATIC float sfract15ToFloat( sfract15 y)
406 {
407  return y / 32768.0;
408 }
409 
414 LIB8STATIC sfract15 floatToSfract15( float f)
415 {
416  return f * 32768.0;
417 }
418 
419 
420 
422 //
423 // memmove8, memcpy8, and memset8:
424 // alternatives to memmove, memcpy, and memset that are
425 // faster on AVR than standard avr-libc 1.8
426 
427 #if defined(__AVR__)
428 extern "C" {
429 void * memmove8( void * dst, const void * src, uint16_t num );
430 void * memcpy8 ( void * dst, const void * src, uint16_t num ) __attribute__ ((noinline));
431 void * memset8 ( void * ptr, uint8_t value, uint16_t num ) __attribute__ ((noinline)) ;
432 }
433 #else
434 // on non-AVR platforms, these names just call standard libc.
435 #define memmove8 memmove
436 #define memcpy8 memcpy
437 #define memset8 memset
438 #endif
439 
440 
442 //
443 // linear interpolation, such as could be used for Perlin noise, etc.
444 //
445 
446 // A note on the structure of the lerp functions:
447 // The cases for b>a and b<=a are handled separately for
448 // speed: without knowing the relative order of a and b,
449 // the value (a-b) might be overflow the width of a or b,
450 // and have to be promoted to a wider, slower type.
451 // To avoid that, we separate the two cases, and are able
452 // to do all the math in the same width as the arguments,
453 // which is much faster and smaller on AVR.
454 
457 LIB8STATIC uint8_t lerp8by8( uint8_t a, uint8_t b, fract8 frac)
458 {
459  uint8_t result;
460  if( b > a) {
461  uint8_t delta = b - a;
462  uint8_t scaled = scale8( delta, frac);
463  result = a + scaled;
464  } else {
465  uint8_t delta = a - b;
466  uint8_t scaled = scale8( delta, frac);
467  result = a - scaled;
468  }
469  return result;
470 }
471 
474 LIB8STATIC uint16_t lerp16by16( uint16_t a, uint16_t b, fract16 frac)
475 {
476  uint16_t result;
477  if( b > a ) {
478  uint16_t delta = b - a;
479  uint32_t scaled = scale16(delta, frac);
480  result = a + scaled;
481  } else {
482  uint16_t delta = a - b;
483  uint16_t scaled = scale16( delta, frac);
484  result = a - scaled;
485  }
486  return result;
487 }
488 
491 LIB8STATIC uint16_t lerp16by8( uint16_t a, uint16_t b, fract8 frac)
492 {
493  uint16_t result;
494  if( b > a) {
495  uint16_t delta = b - a;
496  uint16_t scaled = scale16by8( delta, frac);
497  result = a + scaled;
498  } else {
499  uint16_t delta = a - b;
500  uint16_t scaled = scale16by8( delta, frac);
501  result = a - scaled;
502  }
503  return result;
504 }
505 
508 LIB8STATIC int16_t lerp15by8( int16_t a, int16_t b, fract8 frac)
509 {
510  int16_t result;
511  if( b > a) {
512  uint16_t delta = b - a;
513  uint16_t scaled = scale16by8( delta, frac);
514  result = a + scaled;
515  } else {
516  uint16_t delta = a - b;
517  uint16_t scaled = scale16by8( delta, frac);
518  result = a - scaled;
519  }
520  return result;
521 }
522 
525 LIB8STATIC int16_t lerp15by16( int16_t a, int16_t b, fract16 frac)
526 {
527  int16_t result;
528  if( b > a) {
529  uint16_t delta = b - a;
530  uint16_t scaled = scale16( delta, frac);
531  result = a + scaled;
532  } else {
533  uint16_t delta = a - b;
534  uint16_t scaled = scale16( delta, frac);
535  result = a - scaled;
536  }
537  return result;
538 }
539 
557 LIB8STATIC uint8_t map8( uint8_t in, uint8_t rangeStart, uint8_t rangeEnd)
558 {
559  uint8_t rangeWidth = rangeEnd - rangeStart;
560  uint8_t out = scale8( in, rangeWidth);
561  out += rangeStart;
562  return out;
563 }
564 
565 
567 //
568 // easing functions; see http://easings.net
569 //
570 
573 LIB8STATIC uint8_t ease8InOutQuad( uint8_t i)
574 {
575  uint8_t j = i;
576  if( j & 0x80 ) {
577  j = 255 - j;
578  }
579  uint8_t jj = scale8( j, (j+1));
580  uint8_t jj2 = jj << 1;
581  if( i & 0x80 ) {
582  jj2 = 255 - jj2;
583  }
584  return jj2;
585 }
586 
587 
591 {
592  uint8_t ii = scale8_LEAVING_R1_DIRTY( i, i);
593  uint8_t iii = scale8_LEAVING_R1_DIRTY( ii, i);
594 
595  uint16_t r1 = (3 * (uint16_t)(ii)) - ( 2 * (uint16_t)(iii));
596 
597  /* the code generated for the above *'s automatically
598  cleans up R1, so there's no need to explicitily call
599  cleanup_R1(); */
600 
601  uint8_t result = r1;
602 
603  // if we got "256", return 255:
604  if( r1 & 0x100 ) {
605  result = 255;
606  }
607  return result;
608 }
609 
617 
618 #if EASE8_C == 1
620 {
621  if( i < 64) {
622  // start with slope 0.5
623  i /= 2;
624  } else if( i > (255 - 64)) {
625  // end with slope 0.5
626  i = 255 - i;
627  i /= 2;
628  i = 255 - i;
629  } else {
630  // in the middle, use slope 192/128 = 1.5
631  i -= 64;
632  i += (i / 2);
633  i += 32;
634  }
635 
636  return i;
637 }
638 
639 #elif EASE8_AVRASM == 1
640 LIB8STATIC uint8_t ease8InOutApprox( fract8 i)
641 {
642  // takes around 7 cycles on AVR
643  asm volatile (
644  " subi %[i], 64 \n\t"
645  " cpi %[i], 128 \n\t"
646  " brcc Lshift_%= \n\t"
647 
648  // middle case
649  " mov __tmp_reg__, %[i] \n\t"
650  " lsr __tmp_reg__ \n\t"
651  " add %[i], __tmp_reg__ \n\t"
652  " subi %[i], 224 \n\t"
653  " rjmp Ldone_%= \n\t"
654 
655  // start or end case
656  "Lshift_%=: \n\t"
657  " lsr %[i] \n\t"
658  " subi %[i], 96 \n\t"
659 
660  "Ldone_%=: \n\t"
661 
662  : [i] "+a" (i)
663  :
664  : "r0", "r1"
665  );
666  return i;
667 }
668 #else
669 #error "No implementation for ease8 available."
670 #endif
671 
672 
673 
684 LIB8STATIC uint8_t triwave8(uint8_t in)
685 {
686  if( in & 0x80) {
687  in = 255 - in;
688  }
689  uint8_t out = in << 1;
690  return out;
691 }
692 
693 
694 // quadwave8 and cubicwave8: S-shaped wave generators (like 'sine').
695 // Useful for turning a one-byte 'counter' value into a
696 // one-byte oscillating value that moves smoothly up and down,
697 // with an 'acceleration' and 'deceleration' curve.
698 //
699 // These are even faster than 'sin8', and have
700 // slightly different curve shapes.
701 //
702 
705 LIB8STATIC uint8_t quadwave8(uint8_t in)
706 {
707  return ease8InOutQuad( triwave8( in));
708 }
709 
712 LIB8STATIC uint8_t cubicwave8(uint8_t in)
713 {
714  return ease8InOutCubic( triwave8( in));
715 }
716 
741 LIB8STATIC uint8_t squarewave8( uint8_t in, uint8_t pulsewidth=128)
742 {
743  if( in < pulsewidth || (pulsewidth == 255)) {
744  return 255;
745  } else {
746  return 0;
747  }
748 }
749 
750 
751 
752 
754 template<class T, int F, int I> class q {
755  T i:I;
756  T f:F;
757 public:
758  q(float fx) { i = fx; f = (fx-i) * (1<<F); }
759  q(uint8_t _i, uint8_t _f) {i=_i; f=_f; }
760  uint32_t operator*(uint32_t v) { return (v*i) + ((v*f)>>F); }
761  uint16_t operator*(uint16_t v) { return (v*i) + ((v*f)>>F); }
762  int32_t operator*(int32_t v) { return (v*i) + ((v*f)>>F); }
763  int16_t operator*(int16_t v) { return (v*i) + ((v*f)>>F); }
764 #ifdef FASTLED_ARM
765  int operator*(int v) { return (v*i) + ((v*f)>>F); }
766 #endif
767 };
768 
769 template<class T, int F, int I> static uint32_t operator*(uint32_t v, q<T,F,I> & q) { return q * v; }
770 template<class T, int F, int I> static uint16_t operator*(uint16_t v, q<T,F,I> & q) { return q * v; }
771 template<class T, int F, int I> static int32_t operator*(int32_t v, q<T,F,I> & q) { return q * v; }
772 template<class T, int F, int I> static int16_t operator*(int16_t v, q<T,F,I> & q) { return q * v; }
773 #ifdef FASTLED_ARM
774 template<class T, int F, int I> static int operator*(int v, q<T,F,I> & q) { return q * v; }
775 #endif
776 
785 
786 
787 
788 // Beat generators - These functions produce waves at a given
789 // number of 'beats per minute'. Internally, they use
790 // the Arduino function 'millis' to track elapsed time.
791 // Accuracy is a bit better than one part in a thousand.
792 //
793 // beat8( BPM ) returns an 8-bit value that cycles 'BPM' times
794 // per minute, rising from 0 to 255, resetting to zero,
795 // rising up again, etc.. The output of this function
796 // is suitable for feeding directly into sin8, and cos8,
797 // triwave8, quadwave8, and cubicwave8.
798 // beat16( BPM ) returns a 16-bit value that cycles 'BPM' times
799 // per minute, rising from 0 to 65535, resetting to zero,
800 // rising up again, etc. The output of this function is
801 // suitable for feeding directly into sin16 and cos16.
802 // beat88( BPM88) is the same as beat16, except that the BPM88 argument
803 // MUST be in Q8.8 fixed point format, e.g. 120BPM must
804 // be specified as 120*256 = 30720.
805 // beatsin8( BPM, uint8_t low, uint8_t high) returns an 8-bit value that
806 // rises and falls in a sine wave, 'BPM' times per minute,
807 // between the values of 'low' and 'high'.
808 // beatsin16( BPM, uint16_t low, uint16_t high) returns a 16-bit value
809 // that rises and falls in a sine wave, 'BPM' times per
810 // minute, between the values of 'low' and 'high'.
811 // beatsin88( BPM88, ...) is the same as beatsin16, except that the
812 // BPM88 argument MUST be in Q8.8 fixed point format,
813 // e.g. 120BPM must be specified as 120*256 = 30720.
814 //
815 // BPM can be supplied two ways. The simpler way of specifying BPM is as
816 // a simple 8-bit integer from 1-255, (e.g., "120").
817 // The more sophisticated way of specifying BPM allows for fractional
818 // "Q8.8" fixed point number (an 'accum88') with an 8-bit integer part and
819 // an 8-bit fractional part. The easiest way to construct this is to multiply
820 // a floating point BPM value (e.g. 120.3) by 256, (e.g. resulting in 30796
821 // in this case), and pass that as the 16-bit BPM argument.
822 // "BPM88" MUST always be specified in Q8.8 format.
823 //
824 // Originally designed to make an entire animation project pulse with brightness.
825 // For that effect, add this line just above your existing call to "FastLED.show()":
826 //
827 // uint8_t bright = beatsin8( 60 /*BPM*/, 192 /*dimmest*/, 255 /*brightest*/ ));
828 // FastLED.setBrightness( bright );
829 // FastLED.show();
830 //
831 // The entire animation will now pulse between brightness 192 and 255 once per second.
832 
833 
834 // The beat generators need access to a millisecond counter.
835 // On Arduino, this is "millis()". On other platforms, you'll
836 // need to provide a function with this signature:
837 // uint32_t get_millisecond_timer();
838 // that provides similar functionality.
839 // You can also force use of the get_millisecond_timer function
840 // by #defining USE_GET_MILLISECOND_TIMER.
841 #if (defined(ARDUINO) || defined(SPARK) || defined(FASTLED_HAS_MILLIS)) && !defined(USE_GET_MILLISECOND_TIMER)
842 // Forward declaration of Arduino function 'millis'.
843 //uint32_t millis();
844 #define GET_MILLIS millis
845 #else
846 uint32_t get_millisecond_timer();
847 #define GET_MILLIS get_millisecond_timer
848 #endif
849 
850 // beat16 generates a 16-bit 'sawtooth' wave at a given BPM,
855 LIB8STATIC uint16_t beat88( accum88 beats_per_minute_88, uint32_t timebase = 0)
856 {
857  // BPM is 'beats per minute', or 'beats per 60000ms'.
858  // To avoid using the (slower) division operator, we
859  // want to convert 'beats per 60000ms' to 'beats per 65536ms',
860  // and then use a simple, fast bit-shift to divide by 65536.
861  //
862  // The ratio 65536:60000 is 279.620266667:256; we'll call it 280:256.
863  // The conversion is accurate to about 0.05%, more or less,
864  // e.g. if you ask for "120 BPM", you'll get about "119.93".
865  return (((GET_MILLIS()) - timebase) * beats_per_minute_88 * 280) >> 16;
866 }
867 
869 LIB8STATIC uint16_t beat16( accum88 beats_per_minute, uint32_t timebase = 0)
870 {
871  // Convert simple 8-bit BPM's to full Q8.8 accum88's if needed
872  if( beats_per_minute < 256) beats_per_minute <<= 8;
873  return beat88(beats_per_minute, timebase);
874 }
875 
877 LIB8STATIC uint8_t beat8( accum88 beats_per_minute, uint32_t timebase = 0)
878 {
879  return beat16( beats_per_minute, timebase) >> 8;
880 }
881 
888 LIB8STATIC uint16_t beatsin88( accum88 beats_per_minute_88, uint16_t lowest = 0, uint16_t highest = 65535,
889  uint32_t timebase = 0, uint16_t phase_offset = 0)
890 {
891  uint16_t beat = beat88( beats_per_minute_88, timebase);
892  uint16_t beatsin = (sin16( beat + phase_offset) + 32768);
893  uint16_t rangewidth = highest - lowest;
894  uint16_t scaledbeat = scale16( beatsin, rangewidth);
895  uint16_t result = lowest + scaledbeat;
896  return result;
897 }
898 
901 LIB8STATIC uint16_t beatsin16( accum88 beats_per_minute, uint16_t lowest = 0, uint16_t highest = 65535,
902  uint32_t timebase = 0, uint16_t phase_offset = 0)
903 {
904  uint16_t beat = beat16( beats_per_minute, timebase);
905  uint16_t beatsin = (sin16( beat + phase_offset) + 32768);
906  uint16_t rangewidth = highest - lowest;
907  uint16_t scaledbeat = scale16( beatsin, rangewidth);
908  uint16_t result = lowest + scaledbeat;
909  return result;
910 }
911 
914 LIB8STATIC uint8_t beatsin8( accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255,
915  uint32_t timebase = 0, uint8_t phase_offset = 0)
916 {
917  uint8_t beat = beat8( beats_per_minute, timebase);
918  uint8_t beatsin = sin8( beat + phase_offset);
919  uint8_t rangewidth = highest - lowest;
920  uint8_t scaledbeat = scale8( beatsin, rangewidth);
921  uint8_t result = lowest + scaledbeat;
922  return result;
923 }
924 
925 
928 LIB8STATIC uint16_t seconds16()
929 {
930  uint32_t ms = GET_MILLIS();
931  uint16_t s16;
932  s16 = ms / 1000;
933  return s16;
934 }
935 
938 LIB8STATIC uint16_t minutes16()
939 {
940  uint32_t ms = GET_MILLIS();
941  uint16_t m16;
942  m16 = (ms / (60000L)) & 0xFFFF;
943  return m16;
944 }
945 
948 LIB8STATIC uint8_t hours8()
949 {
950  uint32_t ms = GET_MILLIS();
951  uint8_t h8;
952  h8 = (ms / (3600000L)) & 0xFF;
953  return h8;
954 }
955 
956 
967 LIB8STATIC uint16_t div1024_32_16( uint32_t in32)
968 {
969  uint16_t out16;
970 #if defined(__AVR__)
971  asm volatile (
972  " lsr %D[in] \n\t"
973  " ror %C[in] \n\t"
974  " ror %B[in] \n\t"
975  " lsr %D[in] \n\t"
976  " ror %C[in] \n\t"
977  " ror %B[in] \n\t"
978  " mov %B[out],%C[in] \n\t"
979  " mov %A[out],%B[in] \n\t"
980  : [in] "+r" (in32),
981  [out] "=r" (out16)
982  );
983 #else
984  out16 = (in32 >> 10) & 0xFFFF;
985 #endif
986  return out16;
987 }
988 
992 LIB8STATIC uint16_t bseconds16()
993 {
994  uint32_t ms = GET_MILLIS();
995  uint16_t s16;
996  s16 = div1024_32_16( ms);
997  return s16;
998 }
999 
1000 
1001 // Classes to implement "Every N Milliseconds", "Every N Seconds",
1002 // "Every N Minutes", "Every N Hours", and "Every N BSeconds".
1003 #if 1
1004 #define INSTANTIATE_EVERY_N_TIME_PERIODS(NAME,TIMETYPE,TIMEGETTER) \
1005 class NAME { \
1006 public: \
1007  TIMETYPE mPrevTrigger; \
1008  TIMETYPE mPeriod; \
1009  \
1010  NAME() { reset(); mPeriod = 1; }; \
1011  NAME(TIMETYPE period) { reset(); setPeriod(period); }; \
1012  void setPeriod( TIMETYPE period) { mPeriod = period; }; \
1013  TIMETYPE getTime() { return (TIMETYPE)(TIMEGETTER()); }; \
1014  TIMETYPE getPeriod() { return mPeriod; }; \
1015  TIMETYPE getElapsed() { return getTime() - mPrevTrigger; } \
1016  TIMETYPE getRemaining() { return mPeriod - getElapsed(); } \
1017  TIMETYPE getLastTriggerTime() { return mPrevTrigger; } \
1018  bool ready() { \
1019  bool isReady = (getElapsed() >= mPeriod); \
1020  if( isReady ) { reset(); } \
1021  return isReady; \
1022  } \
1023  void reset() { mPrevTrigger = getTime(); }; \
1024  void trigger() { mPrevTrigger = getTime() - mPeriod; }; \
1025  \
1026  operator bool() { return ready(); } \
1027 };
1028 INSTANTIATE_EVERY_N_TIME_PERIODS(CEveryNMillis,uint32_t,GET_MILLIS);
1029 INSTANTIATE_EVERY_N_TIME_PERIODS(CEveryNSeconds,uint16_t,seconds16);
1030 INSTANTIATE_EVERY_N_TIME_PERIODS(CEveryNBSeconds,uint16_t,bseconds16);
1031 INSTANTIATE_EVERY_N_TIME_PERIODS(CEveryNMinutes,uint16_t,minutes16);
1032 INSTANTIATE_EVERY_N_TIME_PERIODS(CEveryNHours,uint8_t,hours8);
1033 #else
1034 
1035 // Under C++11 rules, we would be allowed to use not-external
1036 // -linkage-type symbols as template arguments,
1037 // e.g., LIB8STATIC seconds16, and we'd be able to use these
1038 // templates as shown below.
1039 // However, under C++03 rules, we cannot do that, and thus we
1040 // have to resort to the preprocessor to 'instantiate' 'templates',
1041 // as handled above.
1042 template<typename timeType,timeType (*timeGetter)()>
1044 public:
1045  timeType mPrevTrigger;
1046  timeType mPeriod;
1047 
1048  CEveryNTimePeriods() { reset(); mPeriod = 1; };
1049  CEveryNTimePeriods(timeType period) { reset(); setPeriod(period); };
1050  void setPeriod( timeType period) { mPeriod = period; };
1051  timeType getTime() { return (timeType)(timeGetter()); };
1052  timeType getPeriod() { return mPeriod; };
1053  timeType getElapsed() { return getTime() - mPrevTrigger; }
1054  timeType getRemaining() { return mPeriod - getElapsed(); }
1055  timeType getLastTriggerTime() { return mPrevTrigger; }
1056  bool ready() {
1057  bool isReady = (getElapsed() >= mPeriod);
1058  if( isReady ) { reset(); }
1059  return isReady;
1060  }
1061  void reset() { mPrevTrigger = getTime(); };
1062  void trigger() { mPrevTrigger = getTime() - mPeriod; };
1063 
1064  operator bool() { return ready(); }
1065 };
1071 #endif
1072 
1073 
1074 #define CONCAT_HELPER( x, y ) x##y
1075 #define CONCAT_MACRO( x, y ) CONCAT_HELPER( x, y )
1076 #define EVERY_N_MILLIS(N) EVERY_N_MILLIS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
1077 #define EVERY_N_MILLIS_I(NAME,N) static CEveryNMillis NAME(N); if( NAME )
1078 #define EVERY_N_SECONDS(N) EVERY_N_SECONDS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
1079 #define EVERY_N_SECONDS_I(NAME,N) static CEveryNSeconds NAME(N); if( NAME )
1080 #define EVERY_N_BSECONDS(N) EVERY_N_BSECONDS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
1081 #define EVERY_N_BSECONDS_I(NAME,N) static CEveryNBSeconds NAME(N); if( NAME )
1082 #define EVERY_N_MINUTES(N) EVERY_N_MINUTES_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
1083 #define EVERY_N_MINUTES_I(NAME,N) static CEveryNMinutes NAME(N); if( NAME )
1084 #define EVERY_N_HOURS(N) EVERY_N_HOURS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
1085 #define EVERY_N_HOURS_I(NAME,N) static CEveryNHours NAME(N); if( NAME )
1086 
1087 #define CEveryNMilliseconds CEveryNMillis
1088 #define EVERY_N_MILLISECONDS(N) EVERY_N_MILLIS(N)
1089 #define EVERY_N_MILLISECONDS_I(NAME,N) EVERY_N_MILLIS_I(NAME,N)
1090 
1091 FASTLED_NAMESPACE_END
1093 
1094 #endif
LIB8STATIC uint8_t hours8()
Return the current hours since boot in an 8-bit value.
Definition: lib8tion.h:948
LIB8STATIC uint16_t lerp16by8(uint16_t a, uint16_t b, fract8 frac)
linear interpolation between two unsigned 16-bit values, with 8-bit fraction
Definition: lib8tion.h:491
LIB8STATIC uint16_t beat16(accum88 beats_per_minute, uint32_t timebase=0)
beat16 generates a 16-bit 'sawtooth' wave at a given BPM
Definition: lib8tion.h:869
int16_t saccum78
ANSI: signed short _Accum. 7 bits int, 8 bits fraction.
Definition: lib8tion.h:355
LIB8STATIC uint8_t ease8InOutQuad(uint8_t i)
ease8InOutQuad: 8-bit quadratic ease-in / ease-out function Takes around 13 cycles on AVR ...
Definition: lib8tion.h:573
uint32_t accum1616
ANSI: signed _Accum. 16 bits int, 16 bits fraction.
Definition: lib8tion.h:356
LIB8STATIC uint16_t minutes16()
Return the current minutes since boot in a 16-bit value.
Definition: lib8tion.h:938
LIB8STATIC uint8_t lerp8by8(uint8_t a, uint8_t b, fract8 frac)
linear interpolation between two unsigned 8-bit values, with 8-bit fraction
Definition: lib8tion.h:457
uint16_t fract16
ANSI: unsigned _Fract.
Definition: lib8tion.h:343
LIB8STATIC uint16_t lerp16by16(uint16_t a, uint16_t b, fract16 frac)
linear interpolation between two unsigned 16-bit values, with 16-bit fraction
Definition: lib8tion.h:474
uint16_t accum88
ANSI: unsigned short _Accum. 8 bits int, 8 bits fraction.
Definition: lib8tion.h:354
typedef for IEEE754 "binary32" float type internals
Definition: lib8tion.h:363
int16_t sfract15
ANSI: signed _Fract.
Definition: lib8tion.h:347
LIB8STATIC uint16_t beatsin16(accum88 beats_per_minute, uint16_t lowest=0, uint16_t highest=65535, uint32_t timebase=0, uint16_t phase_offset=0)
beatsin16 generates a 16-bit sine wave at a given BPM, that oscillates within a given range...
Definition: lib8tion.h:901
q< uint16_t, 8, 8 > q88
A 8.8 integer (8 bits integer, 8 bits fraction)
Definition: lib8tion.h:782
LIB8STATIC int16_t lerp15by16(int16_t a, int16_t b, fract16 frac)
linear interpolation between two signed 15-bit values, with 8-bit fraction
Definition: lib8tion.h:525
int32_t saccum114
no direct ANSI counterpart. 1 bit int, 14 bits fraction
Definition: lib8tion.h:359
LIB8STATIC uint16_t scale16(uint16_t i, fract16 scale)
scale a 16-bit unsigned value by a 16-bit value, considered as numerator of a fraction whose denomina...
Definition: scale8.h:456
LIB8STATIC sfract15 floatToSfract15(float f)
conversion from IEEE754 float in the range (-1,1) to 16-bit fixed point.
Definition: lib8tion.h:414
LIB8STATIC uint16_t seconds16()
Return the current seconds since boot in a 16-bit value.
Definition: lib8tion.h:928
uint16_t accum124
no direct ANSI counterpart. 12 bits int, 4 bits fraction
Definition: lib8tion.h:358
LIB8STATIC uint16_t bseconds16()
bseconds16 returns the current time-since-boot in "binary seconds", which are actually 1024/1000 of a...
Definition: lib8tion.h:992
q< uint16_t, 12, 4 > q124
A 12.4 integer (12 bits integer, 4 bits fraction)
Definition: lib8tion.h:784
LIB8STATIC uint8_t quadwave8(uint8_t in)
quadwave8: quadratic waveform generator.
Definition: lib8tion.h:705
uint8_t fract8
ANSI unsigned short _Fract.
Definition: lib8tion.h:335
q< uint8_t, 4, 4 > q44
A 4.4 integer (4 bits integer, 4 bits fraction)
Definition: lib8tion.h:778
LIB8STATIC uint16_t beatsin88(accum88 beats_per_minute_88, uint16_t lowest=0, uint16_t highest=65535, uint32_t timebase=0, uint16_t phase_offset=0)
beatsin88 generates a 16-bit sine wave at a given BPM, that oscillates within a given range...
Definition: lib8tion.h:888
LIB8STATIC uint8_t cubicwave8(uint8_t in)
cubicwave8: cubic waveform generator.
Definition: lib8tion.h:712
central include file for FastLED, defines the CFastLED class/object
LIB8STATIC uint16_t beat88(accum88 beats_per_minute_88, uint32_t timebase=0)
with BPM specified in Q8.8 fixed-point format; e.g.
Definition: lib8tion.h:855
LIB8STATIC fract8 ease8InOutApprox(fract8 i)
ease8InOutApprox: fast, rough 8-bit ease-in/ease-out function shaped approximately like 'ease8InOutCu...
Definition: lib8tion.h:619
int8_t sfract7
ANSI: signed short _Fract.
Definition: lib8tion.h:339
LIB8STATIC fract8 ease8InOutCubic(fract8 i)
ease8InOutCubic: 8-bit cubic ease-in / ease-out function Takes around 18 cycles on AVR ...
Definition: lib8tion.h:590
LIB8STATIC uint8_t beat8(accum88 beats_per_minute, uint32_t timebase=0)
beat8 generates an 8-bit 'sawtooth' wave at a given BPM
Definition: lib8tion.h:877
__attribute__((always_inline)) inline void swapbits8(bitswap_type in
Do an 8byte by 8bit rotation.
Definition: fastled_delay.h:92
LIB8STATIC uint8_t triwave8(uint8_t in)
triwave8: triangle (sawtooth) wave generator.
Definition: lib8tion.h:684
LIB8STATIC_ALWAYS_INLINE uint16_t scale16by8(uint16_t i, fract8 scale)
scale a 16-bit unsigned value by an 8-bit value, considered as numerator of a fraction whose denomina...
Definition: scale8.h:416
LIB8STATIC uint8_t beatsin8(accum88 beats_per_minute, uint8_t lowest=0, uint8_t highest=255, uint32_t timebase=0, uint8_t phase_offset=0)
beatsin8 generates an 8-bit sine wave at a given BPM, that oscillates within a given range...
Definition: lib8tion.h:914
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:20
LIB8STATIC uint8_t squarewave8(uint8_t in, uint8_t pulsewidth=128)
squarewave8: square wave generator.
Definition: lib8tion.h:741
LIB8STATIC int16_t lerp15by8(int16_t a, int16_t b, fract8 frac)
linear interpolation between two signed 15-bit values, with 8-bit fraction
Definition: lib8tion.h:508
q< uint8_t, 6, 2 > q62
A 6.2 integer (6 bits integer, 2 bits fraction)
Definition: lib8tion.h:780
LIB8STATIC_ALWAYS_INLINE uint8_t scale8_LEAVING_R1_DIRTY(uint8_t i, fract8 scale)
This version of scale8 does not clean up the R1 register on AVR If you are doing several 'scale8's in...
Definition: scale8.h:146
Template class for represneting fractional ints.
Definition: lib8tion.h:754
LIB8STATIC uint8_t map8(uint8_t in, uint8_t rangeStart, uint8_t rangeEnd)
map8: map from one full-range 8-bit value into a narrower range of 8-bit values, possibly a range of ...
Definition: lib8tion.h:557
int32_t saccum1516
ANSI: signed _Accum. 15 bits int, 16 bits fraction.
Definition: lib8tion.h:357
LIB8STATIC uint16_t div1024_32_16(uint32_t in32)
Helper routine to divide a 32-bit value by 1024, returning only the low 16 bits.
Definition: lib8tion.h:967
LIB8STATIC float sfract15ToFloat(sfract15 y)
sfract15ToFloat: conversion from sfract15 fixed point to IEEE754 32-bit float.
Definition: lib8tion.h:405