lib8tion  Math functions specifically designed for LED programming¶
Note
This library was ported from FastLED
 group lib8tion
A variety of functions for working with numbers.
Defines

GET_MILLIS()¶
Typedefs

typedef uint8_t fract8¶
ANSI unsigned short _Fract.
range is 0 to 0.99609375 in steps of 0.00390625 ANSI: unsigned short _Fract

typedef int8_t sfract7¶
ANSI: signed short _Fract.
range is 0.9921875 to 0.9921875 in steps of 0.0078125 ANSI: signed short _Fract

typedef uint16_t fract16¶
ANSI: unsigned _Fract.
range is 0 to 0.99998474121 in steps of 0.00001525878 ANSI: unsigned _Fract

typedef int16_t sfract15¶
ANSI: signed _Fract.
range is 0.99996948242 to 0.99996948242 in steps of 0.00003051757 ANSI: signed _Fract

typedef uint16_t accum88¶
ANSI: unsigned short _Accum. 8 bits int, 8 bits fraction.

typedef int16_t saccum78¶
ANSI: signed short _Accum. 7 bits int, 8 bits fraction.

typedef uint32_t accum1616¶
ANSI: signed _Accum. 16 bits int, 16 bits fraction.

typedef int32_t saccum1516¶
ANSI: signed _Accum. 15 bits int, 16 bits fraction.

typedef uint16_t accum124¶
no direct ANSI counterpart. 12 bits int, 4 bits fraction

typedef int32_t saccum114¶
no direct ANSI counterpart. 1 bit int, 14 bits fraction
Functions
 LIB8STATIC float sfract15ToFloat (sfract15 y)
sfract15ToFloat: conversion from sfract15 fixed point to IEEE754 32bit float.
 LIB8STATIC sfract15 floatToSfract15 (float f)
conversion from IEEE754 float in the range (1,1) to 16bit fixed point.
Note that the extremes of one and negative one are NOT representable. The representable range is basically
 LIB8STATIC uint8_t lerp8by8 (uint8_t a, uint8_t b, fract8 frac)
linear interpolation between two unsigned 8bit values, with 8bit fraction
 LIB8STATIC uint16_t lerp16by16 (uint16_t a, uint16_t b, fract16 frac)
linear interpolation between two unsigned 16bit values, with 16bit fraction
 LIB8STATIC uint16_t lerp16by8 (uint16_t a, uint16_t b, fract8 frac)
linear interpolation between two unsigned 16bit values, with 8bit fraction
 LIB8STATIC int16_t lerp15by8 (int16_t a, int16_t b, fract8 frac)
linear interpolation between two signed 15bit values, with 8bit fraction
 LIB8STATIC int16_t lerp15by16 (int16_t a, int16_t b, fract16 frac)
linear interpolation between two signed 15bit values, with 8bit fraction
 LIB8STATIC uint8_t map8 (uint8_t in, uint8_t rangeStart, uint8_t rangeEnd)
map8: map from one fullrange 8bit value into a narrower range of 8bit values, possibly a range of hues.
E.g. map myValue into a hue in the range blue..purple..pink..red hue = map8(myValue, HUE_BLUE, HUE_RED);
Combines nicely with the waveform functions (like sin8, etc) to produce continuous hue gradients back and forth:
hue = map8(sin8(myValue), HUE_BLUE, HUE_RED);
Mathematically simiar to lerp8by8, but arguments are more like Arduino’s “map”; this function is similar to
map(in, 0, 255, rangeStart, rangeEnd)
but faster and specifically designed for 8bit values.
 LIB8STATIC uint8_t ease8InOutQuad (uint8_t i)
ease8InOutQuad: 8bit quadratic easein / easeout function Takes around 13 cycles on AVR
 LIB8STATIC uint16_t ease16InOutQuad (uint16_t i)
ease16InOutQuad: 16bit quadratic easein / easeout function
 LIB8STATIC fract8 ease8InOutCubic (fract8 i)
ease8InOutCubic: 8bit cubic easein / easeout function Takes around 18 cycles on AVR
 LIB8STATIC fract8 ease8InOutApprox (fract8 i)
ease8InOutApprox: fast, rough 8bit easein/easeout function shaped approximately like ‘ease8InOutCubic’, it’s never off by more than a couple of percent from the actual cubic Scurve, and it executes more than twice as fast.
Use when the cycles are more important than visual smoothness. Asm version takes around 7 cycles on AVR.
 LIB8STATIC uint8_t triwave8 (uint8_t in)
triwave8: triangle (sawtooth) wave generator.
Useful for turning a onebyte everincreasing value into a onebyte value that oscillates up and down.
input output 0..127 0..254 (positive slope) 128..255 254..0 (negative slope)
On AVR this function takes just three cycles.
 LIB8STATIC uint8_t quadwave8 (uint8_t in)
quadwave8: quadratic waveform generator.
Spends just a little more time at the limits than ‘sine’ does.
 LIB8STATIC uint8_t cubicwave8 (uint8_t in)
cubicwave8: cubic waveform generator.
Spends visibly more time at the limits than ‘sine’ does.
 LIB8STATIC uint8_t squarewave8 (uint8_t in, uint8_t pulsewidth)
squarewave8: square wave generator.
Useful for turning a onebyte everincreasing value into a onebyte value that is either 0 or 255. The width of the output ‘pulse’ is determined by the pulsewidth argument:
If pulsewidth is 255, output is always 255. If pulsewidth < 255, then if input < pulsewidth then output is 255 if input >= pulsewidth then output is 0
the output looking like:
255 +pulsewidth+ .   0 0 +(256pulsewidth)
 Parameters
in –
pulsewidth –
 Returns
square wave output
 LIB8STATIC uint16_t beat88 (accum88 beats_per_minute_88, uint32_t timebase)
beat16 generates a 16bit ‘sawtooth’ wave at a given BPM, with BPM specified in Q8.8 fixedpoint format; e.g.
for this function, 120 BPM MUST BE specified as 120*256 = 30720. If you just want to specify “120”, use beat16 or beat8.
 LIB8STATIC uint16_t beat16 (accum88 beats_per_minute, uint32_t timebase)
beat16 generates a 16bit ‘sawtooth’ wave at a given BPM
 LIB8STATIC uint8_t beat8 (accum88 beats_per_minute, uint32_t timebase)
beat8 generates an 8bit ‘sawtooth’ wave at a given BPM
 LIB8STATIC uint16_t beatsin88 (accum88 beats_per_minute_88, uint16_t lowest, uint16_t highest, uint32_t timebase, uint16_t phase_offset)
beatsin88 generates a 16bit sine wave at a given BPM, that oscillates within a given range.
For this function, BPM MUST BE SPECIFIED as a Q8.8 fixedpoint value; e.g. 120BPM must be specified as 120*256 = 30720. If you just want to specify “120”, use beatsin16 or beatsin8.
 LIB8STATIC uint16_t beatsin16 (accum88 beats_per_minute, uint16_t lowest, uint16_t highest, uint32_t timebase, uint16_t phase_offset)
beatsin16 generates a 16bit sine wave at a given BPM, that oscillates within a given range.
 LIB8STATIC uint8_t beatsin8 (accum88 beats_per_minute, uint8_t lowest, uint8_t highest, uint32_t timebase, uint8_t phase_offset)
beatsin8 generates an 8bit sine wave at a given BPM, that oscillates within a given range.
 LIB8STATIC uint16_t seconds16 ()
Return the current seconds since boot in a 16bit value.
Used as part of the “every N timeperiods” mechanism
 LIB8STATIC uint16_t minutes16 ()
Return the current minutes since boot in a 16bit value.
Used as part of the “every N timeperiods” mechanism
 LIB8STATIC uint8_t hours8 ()
Return the current hours since boot in an 8bit value.
Used as part of the “every N timeperiods” mechanism
 LIB8STATIC uint16_t div1024_32_16 (uint32_t in32)
Helper routine to divide a 32bit value by 1024, returning only the low 16 bits.
You’d think this would be just result = (in32 >> 10) & 0xFFFF; and on ARM, that’s what you want and all is well. Used to convert millis to ‘binary seconds’ aka bseconds: one bsecond == 1024 millis.
 LIB8STATIC uint16_t bseconds16 ()
bseconds16 returns the current timesinceboot in “binary seconds”, which are actually 1024/1000 of a second long.

union IEEE754binary32_t¶
 #include <lib8tion.h>
typedef for IEEE754 “binary32” float type internals
Public Members

uint32_t i¶

float f¶

uint32_t mantissa¶

uint32_t exponent¶

uint32_t signbit¶

struct IEEE754binary32_t::[anonymous] [anonymous]¶

uint32_t mant7¶

uint32_t mant16¶

uint32_t exp_¶

uint32_t sb_¶

struct IEEE754binary32_t::[anonymous] [anonymous]¶

uint32_t mant_lo8¶

uint32_t mant_hi16_exp_lo1¶

uint32_t sb_exphi7¶

struct IEEE754binary32_t::[anonymous] [anonymous]¶

uint32_t i¶

GET_MILLIS()¶
 group Math
Fast, efficient 8bit math functions specifically designed for highperformance LED programming.
Because of the AVR(Arduino) and ARM assembly language implementations provided, using these functions often results in smaller and faster code than the equivalent program using plain “C” arithmetic and logic.
Functions
 LIB8STATIC_ALWAYS_INLINE uint8_t qadd8 (uint8_t i, uint8_t j)
add one byte to another, saturating at 0xFF
 Parameters
i –  first byte to add
j –  second byte to add
 Returns
the sum of i & j, capped at 0xFF
 LIB8STATIC_ALWAYS_INLINE int8_t qadd7 (int8_t i, int8_t j)
Add one byte to another, saturating at 0x7F.
 Parameters
i –  first byte to add
j –  second byte to add
 Returns
the sum of i & j, capped at 0xFF
 LIB8STATIC_ALWAYS_INLINE uint8_t qsub8 (uint8_t i, uint8_t j)
subtract one byte from another, saturating at 0x00
 Returns
i  j with a floor of 0
 LIB8STATIC_ALWAYS_INLINE uint8_t add8 (uint8_t i, uint8_t j)
add one byte to another, with one byte result
 LIB8STATIC_ALWAYS_INLINE uint16_t add8to16 (uint8_t i, uint16_t j)
add one byte to another, with one byte result
 LIB8STATIC_ALWAYS_INLINE uint8_t sub8 (uint8_t i, uint8_t j)
subtract one byte from another, 8bit result
 LIB8STATIC_ALWAYS_INLINE uint8_t avg8 (uint8_t i, uint8_t j)
Calculate an integer average of two unsigned 8bit integer values (uint8_t).
Fractional results are rounded down, e.g. avg8(20,41) = 30
 LIB8STATIC_ALWAYS_INLINE uint16_t avg16 (uint16_t i, uint16_t j)
Calculate an integer average of two unsigned 16bit integer values (uint16_t).
Fractional results are rounded down, e.g. avg16(20,41) = 30
 LIB8STATIC_ALWAYS_INLINE int8_t avg7 (int8_t i, int8_t j)
Calculate an integer average of two signed 7bit integers (int8_t) If the first argument is even, result is rounded down.
If the first argument is odd, result is result up.
 LIB8STATIC_ALWAYS_INLINE int16_t avg15 (int16_t i, int16_t j)
Calculate an integer average of two signed 15bit integers (int16_t) If the first argument is even, result is rounded down.
If the first argument is odd, result is result up.
 LIB8STATIC_ALWAYS_INLINE uint8_t mod8 (uint8_t a, uint8_t m)
Calculate the remainder of one unsigned 8bit value divided by anoter, aka A % M.
Implemented by repeated subtraction, which is very compact, and very fast if A is ‘probably’ less than M. If A is a large multiple of M, the loop has to execute multiple times. However, even in that case, the loop is only two instructions long on AVR, i.e., quick.
 LIB8STATIC uint8_t addmod8 (uint8_t a, uint8_t b, uint8_t m)
Add two numbers, and calculate the modulo of the sum and a third number, M.
In other words, it returns (A+B) % M. It is designed as a compact mechanism for incrementing a ‘mode’ switch and wrapping around back to ‘mode 0’ when the switch goes past the end of the available range. e.g. if you have seven modes, this switches to the next one and wraps around if needed: mode = addmod8( mode, 1, 7); LIB8STATIC_ALWAYS_INLINESee ‘mod8’ for notes on performance.
 LIB8STATIC uint8_t submod8 (uint8_t a, uint8_t b, uint8_t m)
Subtract two numbers, and calculate the modulo of the difference and a third number, M.
In other words, it returns (AB) % M. It is designed as a compact mechanism for incrementing a ‘mode’ switch and wrapping around back to ‘mode 0’ when the switch goes past the end of the available range. e.g. if you have seven modes, this switches to the next one and wraps around if needed: mode = addmod8( mode, 1, 7); LIB8STATIC_ALWAYS_INLINESee ‘mod8’ for notes on performance.
 LIB8STATIC_ALWAYS_INLINE uint8_t mul8 (uint8_t i, uint8_t j)
8x8 bit multiplication, with 8 bit result
 LIB8STATIC_ALWAYS_INLINE uint8_t qmul8 (uint8_t i, uint8_t j)
saturating 8x8 bit multiplication, with 8 bit result
 Returns
the product of i * j, capping at 0xFF
 LIB8STATIC_ALWAYS_INLINE int8_t abs8 (int8_t i)
take abs() of a signed 8bit uint8_t
 LIB8STATIC uint8_t sqrt16 (uint16_t x)
square root for 16bit integers About three times faster and five times smaller than Arduino’s general sqrt on AVR.
 LIB8STATIC uint8_t blend8 (uint8_t a, uint8_t b, uint8_t amountOfB)
blend a variable proproportion(0255) of one byte to another
 Parameters
a –  the starting byte value
b –  the byte value to blend toward
amountOfB –  the proportion (0255) of b to blend
 Returns
a byte value between a and b, inclusive
 group Scaling
Fast, efficient 8bit scaling functions specifically designed for highperformance LED programming.
Because of the AVR(Arduino) and ARM assembly language implementations provided, using these functions often results in smaller and faster code than the equivalent program using plain “C” arithmetic and logic.
Functions
 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 256 In other words, it computes i * (scale / 256) 4 clocks AVR with MUL, 2 clocks ARM
 LIB8STATIC_ALWAYS_INLINE uint8_t scale8_video (uint8_t i, fract8 scale)
The “video” version of scale8 guarantees that the output will be only be zero if one or both of the inputs are zero.
If both inputs are nonzero, the output is guaranteed to be nonzero. This makes for better ‘video’/LED dimming, at the cost of several additional cycles.
 LIB8STATIC void nscale8x3 (uint8_t *r, uint8_t *g, uint8_t *b, fract8 scale)
scale three one byte values by a fourth one, which is treated as the numerator of a fraction whose demominator is 256 In other words, it computes r,g,b * (scale / 256)
THIS FUNCTION ALWAYS MODIFIES ITS ARGUMENTS IN PLACE
 LIB8STATIC void nscale8x3_video (uint8_t *r, uint8_t *g, uint8_t *b, fract8 scale)
scale three one byte values by a fourth one, which is treated as the numerator of a fraction whose demominator is 256 In other words, it computes r,g,b * (scale / 256), ensuring that nonzero values passed in remain non zero, no matter how low the scale argument.
THIS FUNCTION ALWAYS MODIFIES ITS ARGUMENTS IN PLACE
 LIB8STATIC void nscale8x2 (uint8_t *i, uint8_t *j, fract8 scale)
scale two one byte values by a third one, which is treated as the numerator of a fraction whose demominator is 256 In other words, it computes i,j * (scale / 256)
THIS FUNCTION ALWAYS MODIFIES ITS ARGUMENTS IN PLACE
 LIB8STATIC void nscale8x2_video (uint8_t *i, uint8_t *j, fract8 scale)
scale two one byte values by a third one, which is treated as the numerator of a fraction whose demominator is 256 In other words, it computes i,j * (scale / 256), ensuring that nonzero values passed in remain non zero, no matter how low the scale argument.
THIS FUNCTION ALWAYS MODIFIES ITS ARGUMENTS IN PLACE
 LIB8STATIC_ALWAYS_INLINE uint16_t scale16by8 (uint16_t i, fract8 scale)
scale a 16bit unsigned value by an 8bit value, considered as numerator of a fraction whose denominator is 256.
In other words, it computes i * (scale / 256)
 LIB8STATIC uint16_t scale16 (uint16_t i, fract16 scale)
scale a 16bit unsigned value by a 16bit value, considered as numerator of a fraction whose denominator is 65536.
In other words, it computes i * (scale / 65536)
 group Dimming
Dimming and brightening functions.
The eye does not respond in a linear way to light. High speed PWM’d LEDs at 50% duty cycle appear far brighter then the ‘half as bright’ you might expect.
If you want your midpoint brightness leve (128) to appear half as bright as ‘full’ brightness (255), you have to apply a ‘dimming function’.
Functions
 LIB8STATIC uint8_t dim8_raw (uint8_t x)
Adjust a scaling value for dimming.
 LIB8STATIC uint8_t dim8_video (uint8_t x)
Adjust a scaling value for dimming for video (value will never go below 1)
 LIB8STATIC uint8_t dim8_lin (uint8_t x)
Linear version of the dimming function that halves for values < 128.
 LIB8STATIC uint8_t brighten8_raw (uint8_t x)
inverse of the dimming function, brighten a value
 LIB8STATIC uint8_t brighten8_video (uint8_t x)
inverse of the dimming function, brighten a value
 LIB8STATIC uint8_t brighten8_lin (uint8_t x)
inverse of the dimming function, brighten a value
 group Random
Fast 8 and 16 bit unsigned random numbers.
Significantly faster than Arduino random(), but also somewhat less random. You can add entropy.
Functions
 LIB8STATIC uint8_t random8 ()
Generate an 8bit random number.
 LIB8STATIC uint16_t random16 ()
Generate a 16 bit random number.
 LIB8STATIC uint8_t random8_to (uint8_t lim)
Generate an 8bit random number between 0 and lim.
 Parameters
lim – the upper bound for the result
 LIB8STATIC uint8_t random8_between (uint8_t min, uint8_t lim)
Generate an 8bit random number in the given range.
 Parameters
min – the lower bound for the random number
lim – the upper bound for the random number
 LIB8STATIC uint16_t random16_to (uint16_t lim)
Generate an 16bit random number between 0 and lim.
 Parameters
lim – the upper bound for the result
 LIB8STATIC uint16_t random16_between (uint16_t min, uint16_t lim)
Generate an 16bit random number in the given range.
 Parameters
min – the lower bound for the random number
lim – the upper bound for the random number
 LIB8STATIC void random16_set_seed (uint16_t seed)
Set the 16bit seed used for the random number generator.
 LIB8STATIC uint16_t random16_get_seed ()
Get the current seed value for the random number generator.
 LIB8STATIC void random16_add_entropy (uint16_t entropy)
Add entropy into the random number generator.
Variables

uint16_t rand16seed¶
random number seed
 group Trig
Fast 8 and 16bit approximations of sin(x) and cos(x).
Don’t use these approximations for calculating the trajectory of a rocket to Mars, but they’re great for art projects and LED displays.
On Arduino/AVR, the 16bit approximation is more than 10X faster than floating point sin(x) and cos(x), while the 8bit approximation is more than 20X faster.
Functions
 LIB8STATIC int16_t sin16 (uint16_t theta)
Fast 16bit approximation of sin(x).
This approximation never varies more than 0.69% from the floating point value you’d get by doing
float s = sin(x) * 32767.0;
 Parameters
theta – input angle from 065535
 Returns
sin of theta, value between 32767 to 32767.
 LIB8STATIC int16_t cos16 (uint16_t theta)
Fast 16bit approximation of cos(x).
This approximation never varies more than 0.69% from the floating point value you’d get by doing
float s = cos(x) * 32767.0;
 Parameters
theta – input angle from 065535
 Returns
sin of theta, value between 32767 to 32767.
 LIB8STATIC uint8_t sin8 (uint8_t theta)
Fast 8bit approximation of sin(x).
This approximation never varies more than 2% from the floating point value you’d get by doing
float s = (sin(x) * 128.0) + 128;
 Parameters
theta – input angle from 0255
 Returns
sin of theta, value between 0 and 255
 LIB8STATIC uint8_t cos8 (uint8_t theta)
Fast 8bit approximation of cos(x).
This approximation never varies more than 2% from the floating point value you’d get by doing
float s = (cos(x) * 128.0) + 128;
 Parameters
theta – input angle from 0255
 Returns
sin of theta, value between 0 and 255