1#ifndef __INC_LIB8TION_H
2#define __INC_LIB8TION_H
5#include "lib8tion/types.h"
7#ifndef __INC_LED_SYSDEFS_H
8#error WTH? led_sysdefs needs to be included first
16#include "lib8tion/lib8static.h"
27#if defined(FASTLED_TEENSY3)
31#define QADD8_ARM_DSP_ASM 1
32#define QADD7_ARM_DSP_ASM 1
59#elif defined(ARDUINO_ARCH_APOLLO3)
101#define QADD8_AVRASM 1
102#define QADD7_AVRASM 1
103#define QSUB8_AVRASM 1
108#define AVG8R_AVRASM 1
110#define AVG16_AVRASM 1
111#define AVG16R_AVRASM 1
112#define AVG15_AVRASM 1
116#if !defined(LIB8_ATTINY)
118#define SCALE16BY8_C 0
124#define SCALE8_AVRASM 1
125#define SCALE16BY8_AVRASM 1
126#define SCALE16_AVRASM 1
128#define QMUL8_AVRASM 1
129#define EASE8_AVRASM 1
130#define CLEANUP_R1_AVRASM 1
131#define BLEND8_AVRASM 1
135#define SCALE16BY8_C 1
141#define SCALE8_AVRASM 0
142#define SCALE16BY8_AVRASM 0
143#define SCALE16_AVRASM 0
145#define QMUL8_AVRASM 0
146#define EASE8_AVRASM 0
147#define BLEND8_AVRASM 0
163#define SCALE16BY8_C 1
387FASTLED_NAMESPACE_BEGIN
422#if defined(__AVR__) || defined(FASTLED_DOXYGEN)
424void *
memmove8(
void * dst,
const void * src, uint16_t num );
425void *
memcpy8 (
void * dst,
const void * src, uint16_t num ) __attribute__ ((noinline));
426void *
memset8 (
void * ptr, uint8_t value, uint16_t num ) __attribute__ ((noinline)) ;
430#define memmove8 memmove
431#define memcpy8 memcpy
432#define memset8 memset
459 uint8_t delta = b - a;
460 uint8_t scaled =
scale8( delta, frac);
463 uint8_t delta = a - b;
464 uint8_t scaled =
scale8( delta, frac);
476 uint16_t delta = b - a;
477 uint16_t scaled =
scale16(delta, frac);
480 uint16_t delta = a - b;
481 uint16_t scaled =
scale16( delta, frac);
493 uint16_t delta = b - a;
497 uint16_t delta = a - b;
510 uint16_t delta = b - a;
514 uint16_t delta = a - b;
527 uint16_t delta = b - a;
528 uint16_t scaled =
scale16( delta, frac);
531 uint16_t delta = a - b;
532 uint16_t scaled =
scale16( delta, frac);
559LIB8STATIC uint8_t
map8( uint8_t in, uint8_t rangeStart, uint8_t rangeEnd)
561 uint8_t rangeWidth = rangeEnd - rangeStart;
562 uint8_t out =
scale8( in, rangeWidth);
579#if (EASE8_C == 1) || defined(FASTLED_DOXYGEN)
586 uint8_t jj =
scale8( j, j);
587 uint8_t jj2 = jj << 1;
594#elif EASE8_AVRASM == 1
611 "clr __zero_reg__ \n"
620#error "No implementation for ease8InOutQuad available."
632 uint16_t jj2 = jj << 1;
647 uint16_t r1 = (3 * (uint16_t)(ii)) - ( 2 * (uint16_t)(iii));
670#if (EASE8_C == 1) || defined(FASTLED_DOXYGEN)
676 }
else if( i > (255 - 64)) {
691#elif EASE8_AVRASM == 1
696 " subi %[i], 64 \n\t"
697 " cpi %[i], 128 \n\t"
698 " brcc Lshift_%= \n\t"
701 " mov __tmp_reg__, %[i] \n\t"
702 " lsr __tmp_reg__ \n\t"
703 " add %[i], __tmp_reg__ \n\t"
704 " subi %[i], 224 \n\t"
705 " rjmp Ldone_%= \n\t"
710 " subi %[i], 96 \n\t"
721#error "No implementation for ease8 available."
751 uint8_t out = in << 1;
802LIB8STATIC uint8_t
squarewave8( uint8_t in, uint8_t pulsewidth=128)
804 if( in < pulsewidth || (pulsewidth == 255)) {
828#if ((defined(ARDUINO) || defined(SPARK) || defined(FASTLED_HAS_MILLIS)) && !defined(USE_GET_MILLISECOND_TIMER)) || defined(FASTLED_DOXYGEN)
842#define GET_MILLIS millis
844uint32_t get_millisecond_timer();
845#define GET_MILLIS get_millisecond_timer
902LIB8STATIC uint16_t
beat88(
accum88 beats_per_minute_88, uint32_t timebase = 0)
912 return (((
GET_MILLIS()) - timebase) * beats_per_minute_88 * 280) >> 16;
921 if( beats_per_minute < 256) beats_per_minute <<= 8;
922 return beat88(beats_per_minute, timebase);
928LIB8STATIC uint8_t
beat8(
accum88 beats_per_minute, uint32_t timebase = 0)
930 return beat16( beats_per_minute, timebase) >> 8;
944LIB8STATIC uint16_t
beatsin88(
accum88 beats_per_minute_88, uint16_t lowest = 0, uint16_t highest = 65535,
945 uint32_t timebase = 0, uint16_t phase_offset = 0)
947 uint16_t beat =
beat88( beats_per_minute_88, timebase);
948 uint16_t beatsin = (
sin16( beat + phase_offset) + 32768);
949 uint16_t rangewidth = highest - lowest;
950 uint16_t scaledbeat =
scale16( beatsin, rangewidth);
951 uint16_t result = lowest + scaledbeat;
962LIB8STATIC uint16_t
beatsin16(
accum88 beats_per_minute, uint16_t lowest = 0, uint16_t highest = 65535,
963 uint32_t timebase = 0, uint16_t phase_offset = 0)
965 uint16_t beat =
beat16( beats_per_minute, timebase);
966 uint16_t beatsin = (
sin16( beat + phase_offset) + 32768);
967 uint16_t rangewidth = highest - lowest;
968 uint16_t scaledbeat =
scale16( beatsin, rangewidth);
969 uint16_t result = lowest + scaledbeat;
980LIB8STATIC uint8_t
beatsin8(
accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255,
981 uint32_t timebase = 0, uint8_t phase_offset = 0)
983 uint8_t beat =
beat8( beats_per_minute, timebase);
984 uint8_t beatsin =
sin8( beat + phase_offset);
985 uint8_t rangewidth = highest - lowest;
986 uint8_t scaledbeat =
scale8( beatsin, rangewidth);
987 uint8_t result = lowest + scaledbeat;
1017 m16 = (ms / (60000L)) & 0xFFFF;
1027 h8 = (ms / (3600000L)) & 0xFF;
1056 " mov %B[out],%C[in] \n\t"
1057 " mov %A[out],%B[in] \n\t"
1062 out16 = (in32 >> 10) & 0xFFFF;
1082#define INSTANTIATE_EVERY_N_TIME_PERIODS(NAME,TIMETYPE,TIMEGETTER) \
1085 TIMETYPE mPrevTrigger; \
1088 NAME() { reset(); mPeriod = 1; }; \
1089 NAME(TIMETYPE period) { reset(); setPeriod(period); }; \
1090 void setPeriod( TIMETYPE period) { mPeriod = period; }; \
1091 TIMETYPE getTime() { return (TIMETYPE)(TIMEGETTER()); }; \
1092 TIMETYPE getPeriod() { return mPeriod; }; \
1093 TIMETYPE getElapsed() { return getTime() - mPrevTrigger; } \
1094 TIMETYPE getRemaining() { return mPeriod - getElapsed(); } \
1095 TIMETYPE getLastTriggerTime() { return mPrevTrigger; } \
1097 bool isReady = (getElapsed() >= mPeriod); \
1098 if( isReady ) { reset(); } \
1101 void reset() { mPrevTrigger = getTime(); }; \
1102 void trigger() { mPrevTrigger = getTime() - mPeriod; }; \
1104 operator bool() { return ready(); } \
1112#if defined(FASTLED_DOXYGEN)
1140 TIMETYPE
getTime() {
return (TIMETYPE)(TIMEGETTER()); };
1157 if( isReady ) {
reset(); }
1188#define CEveryNMilliseconds CEveryNMillis
1193 uint32_t mPrevTrigger;
1198 uint32_t getPeriod()
const {
return mPeriod; };
1199 uint32_t getElapsed() {
return getTime() - mPrevTrigger; }
1200 uint32_t getRemaining() {
return getPeriod() - getElapsed(); }
1201 uint32_t getLastTriggerTime() {
return mPrevTrigger; }
1203 bool isReady = (getElapsed() >= getPeriod());
1204 if( isReady ) { reset(); }
1207 void reset() { mPrevTrigger = getTime(); };
1208 void trigger() { mPrevTrigger = getTime() - getPeriod(); };
1209 void setPeriod(uint32_t period) { mPeriod = period; }
1211 operator bool() {
return ready(); }
1224template<
typename timeType,timeType (*timeGetter)()>
1225class CEveryNTimePeriods {
1227 timeType mPrevTrigger;
1230 CEveryNTimePeriods() { reset(); mPeriod = 1; };
1231 CEveryNTimePeriods(timeType period) { reset(); setPeriod(period); };
1232 void setPeriod( timeType period) { mPeriod = period; };
1233 timeType getTime() {
return (timeType)(timeGetter()); };
1234 timeType getPeriod() {
return mPeriod; };
1235 timeType getElapsed() {
return getTime() - mPrevTrigger; }
1236 timeType getRemaining() {
return mPeriod - getElapsed(); }
1237 timeType getLastTriggerTime() {
return mPrevTrigger; }
1239 bool isReady = (getElapsed() >= mPeriod);
1240 if( isReady ) { reset(); }
1243 void reset() { mPrevTrigger = getTime(); };
1244 void trigger() { mPrevTrigger = getTime() - mPeriod; };
1246 operator bool() {
return ready(); }
1248typedef CEveryNTimePeriods<uint16_t,seconds16> CEveryNSeconds;
1249typedef CEveryNTimePeriods<uint16_t,bseconds16> CEveryNBSeconds;
1250typedef CEveryNTimePeriods<uint32_t,millis> CEveryNMillis;
1251typedef CEveryNTimePeriods<uint16_t,minutes16> CEveryNMinutes;
1252typedef CEveryNTimePeriods<uint8_t,hours8> CEveryNHours;
1272#define CONCAT_HELPER( x, y ) x##y
1273#define CONCAT_MACRO( x, y ) CONCAT_HELPER( x, y )
1279#define EVERY_N_MILLIS(N) EVERY_N_MILLIS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
1283#define EVERY_N_MILLIS_I(NAME,N) static CEveryNMillis NAME(N); if( NAME )
1288#define EVERY_N_SECONDS(N) EVERY_N_SECONDS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
1292#define EVERY_N_SECONDS_I(NAME,N) static CEveryNSeconds NAME(N); if( NAME )
1297#define EVERY_N_BSECONDS(N) EVERY_N_BSECONDS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
1301#define EVERY_N_BSECONDS_I(NAME,N) static CEveryNBSeconds NAME(N); if( NAME )
1306#define EVERY_N_MINUTES(N) EVERY_N_MINUTES_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
1310#define EVERY_N_MINUTES_I(NAME,N) static CEveryNMinutes NAME(N); if( NAME )
1315#define EVERY_N_HOURS(N) EVERY_N_HOURS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
1319#define EVERY_N_HOURS_I(NAME,N) static CEveryNHours NAME(N); if( NAME )
1323#define EVERY_N_MILLISECONDS(N) EVERY_N_MILLIS(N)
1325#define EVERY_N_MILLISECONDS_I(NAME,N) EVERY_N_MILLIS_I(NAME,N)
1328#define EVERY_N_MILLISECONDS_DYNAMIC(PERIOD_FUNC) EVERY_N_MILLISECONDS_DYNAMIC_I(CONCAT_MACRO(__dynamic_millis_timer, __COUNTER__ ), (PERIOD_FUNC))
1331#define EVERY_N_MILLISECONDS_DYNAMIC_I(NAME, PERIOD_FUNC) \
1332 static CEveryNMillisDynamic NAME(1); \
1333 NAME.setPeriod(PERIOD_FUNC); \
1342#ifdef FASTLED_DOXYGEN
1346#define USE_GET_MILLISECOND_TIMER
1349FASTLED_NAMESPACE_END
central include file for FastLED, defines the CFastLED class/object
Create the CEveryNMillisDynamic class for dynamic millisecond intervals.
Time interval checking class.
void trigger()
Reset the timestamp so it is ready() on next call.
TIMETYPE mPeriod
Timing interval to check.
CEveryNTime(TIMETYPE period)
Constructor.
TIMETYPE getLastTriggerTime()
Get the timestamp of the most recent trigger event.
CEveryNTime()
Default constructor.
TIMETYPE getTime()
Get the current time according to the class' timekeeper.
TIMETYPE getElapsed()
Get the time elapsed since the last trigger event.
void setPeriod(TIMETYPE period)
Set the time interval between triggers.
bool ready()
Check if the time interval has elapsed.
void reset()
Reset the timestamp to the current time.
TIMETYPE getPeriod()
Get the time interval between triggers.
TIMETYPE mPrevTrigger
Timestamp of the last time the class was "ready".
TIMETYPE getRemaining()
Get the time until the next trigger event.
LIB8STATIC uint8_t beat8(accum88 beats_per_minute, uint32_t timebase=0)
Generates an 8-bit "sawtooth" wave at a given BPM.
LIB8STATIC uint16_t beat88(accum88 beats_per_minute_88, uint32_t timebase=0)
Generates a 16-bit "sawtooth" wave at a given BPM, with BPM specified in Q8.8 fixed-point format.
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)
Generates a 16-bit sine wave at a given BPM that oscillates within a given range.
LIB8STATIC uint16_t beat16(accum88 beats_per_minute, uint32_t timebase=0)
Generates a 16-bit "sawtooth" wave at a given BPM.
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)
Generates an 8-bit sine wave at a given BPM that oscillates within a given range.
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)
Generates a 16-bit sine wave at a given BPM that oscillates within a given range.
LIB8STATIC uint16_t ease16InOutQuad(uint16_t i)
16-bit quadratic ease-in / ease-out function.
LIB8STATIC fract8 ease8InOutApprox(fract8 i)
Fast, rough 8-bit ease-in/ease-out function.
LIB8STATIC uint8_t ease8InOutQuad(uint8_t i)
8-bit quadratic ease-in / ease-out function.
LIB8STATIC fract8 ease8InOutCubic(fract8 i)
8-bit cubic ease-in / ease-out function.
void * memcpy8(void *dst, const void *src, uint16_t num)
Faster alternative to memcpy() on AVR.
void * memset8(void *ptr, uint8_t value, uint16_t num)
Faster alternative to memset() on AVR.
void * memmove8(void *dst, const void *src, uint16_t num)
Faster alternative to memmove() on AVR.
LIB8STATIC sfract15 floatToSfract15(float f)
Conversion from IEEE754 float in the range (-1,1) to 16-bit fixed point (sfract15).
LIB8STATIC float sfract15ToFloat(sfract15 y)
Conversion from 16-bit fixed point (sfract15) to IEEE754 32-bit float.
int16_t sfract15
ANSI: signed _Fract.
uint16_t accum88
ANSI: unsigned short _Accum. 8 bits int, 8 bits fraction.
uint8_t fract8
ANSI: unsigned short _Fract.
uint16_t fract16
ANSI: unsigned _Fract.
LIB8STATIC uint8_t lerp8by8(uint8_t a, uint8_t b, fract8 frac)
Linear interpolation between two unsigned 8-bit values, with 8-bit fraction.
LIB8STATIC uint16_t lerp16by16(uint16_t a, uint16_t b, fract16 frac)
Linear interpolation between two unsigned 16-bit values, with 16-bit fraction.
LIB8STATIC uint16_t lerp16by8(uint16_t a, uint16_t b, fract8 frac)
Linear interpolation between two unsigned 16-bit values, with 8-bit fraction.
LIB8STATIC int16_t lerp15by8(int16_t a, int16_t b, fract8 frac)
Linear interpolation between two signed 15-bit values, with 8-bit fraction.
LIB8STATIC int16_t lerp15by16(int16_t a, int16_t b, fract16 frac)
Linear interpolation between two signed 15-bit values, with 8-bit fraction.
LIB8STATIC uint8_t map8(uint8_t in, uint8_t rangeStart, uint8_t rangeEnd)
Map from one full-range 8-bit value into a narrower range of 8-bit values, possibly a range of hues.
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.
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...
LIB8STATIC_ALWAYS_INLINE uint16_t scale16by8(uint16_t i, fract8 scale)
Scale a 16-bit unsigned value by an 8-bit value, which is treated as the numerator of a fraction whos...
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 ...
#define INSTANTIATE_EVERY_N_TIME_PERIODS(NAME, TIMETYPE, TIMEGETTER)
Preprocessor-based class "template" for CEveryNTime, used with EVERY_N_TIME timekeepers.
LIB8STATIC uint16_t minutes16()
Return the current minutes since boot in a 16-bit value.
LIB8STATIC uint16_t bseconds16()
Returns the current time-since-boot in "binary seconds", which are actually 1024/1000 of a second lon...
#define GET_MILLIS
The a number of functions need access to a millisecond counter in order to keep time.
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.
LIB8STATIC uint8_t hours8()
Return the current hours since boot in an 8-bit value.
LIB8STATIC uint16_t seconds16()
Return the current seconds since boot in a 16-bit value.
#define sin16
Platform-independent alias of the fast sin implementation.
#define sin8
Platform-independent alias of the fast sin implementation.
Fast, efficient 8-bit math functions specifically designed for high-performance LED programming.
Fast, efficient random number generators specifically designed for high-performance LED programming.
Fast, efficient 8-bit scaling functions specifically designed for high-performance LED programming.
Fast, efficient 8-bit trigonometry functions specifically designed for high-performance LED programmi...