lib8tion: Math functions specifically designed for LED programming

Defines

LIB8STATIC
LIB8STATIC_ALWAYS_INLINE
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

inline float sfract15ToFloat(sfract15 y)

sfract15ToFloat: conversion from sfract15 fixed point to IEEE754 32-bit float.

inline sfract15 floatToSfract15(float f)

conversion from IEEE754 float in the range (-1,1) to 16-bit fixed point.

Note that the extremes of one and negative one are NOT representable. The representable range is basically

inline uint8_t lerp8by8(uint8_t a, uint8_t b, fract8 frac)

linear interpolation between two unsigned 8-bit values, with 8-bit fraction

inline uint16_t lerp16by16(uint16_t a, uint16_t b, fract16 frac)

linear interpolation between two unsigned 16-bit values, with 16-bit fraction

inline uint16_t lerp16by8(uint16_t a, uint16_t b, fract8 frac)

linear interpolation between two unsigned 16-bit values, with 8-bit fraction

inline int16_t lerp15by8(int16_t a, int16_t b, fract8 frac)

linear interpolation between two signed 15-bit values, with 8-bit fraction

inline int16_t lerp15by16(int16_t a, int16_t b, fract16 frac)

linear interpolation between two signed 15-bit values, with 8-bit fraction

inline 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 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 8-bit values.

inline uint8_t ease8InOutQuad(uint8_t i)

ease8InOutQuad: 8-bit quadratic ease-in / ease-out function Takes around 13 cycles on AVR

inline uint16_t ease16InOutQuad(uint16_t i)

ease16InOutQuad: 16-bit quadratic ease-in / ease-out function

inline fract8 ease8InOutCubic(fract8 i)

ease8InOutCubic: 8-bit cubic ease-in / ease-out function Takes around 18 cycles on AVR

inline fract8 ease8InOutApprox(fract8 i)

ease8InOutApprox: fast, rough 8-bit ease-in/ease-out function shaped approximately like ‘ease8InOutCubic’, it’s never off by more than a couple of percent from the actual cubic S-curve, 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.

inline uint8_t triwave8(uint8_t in)

triwave8: triangle (sawtooth) wave generator.

Useful for turning a one-byte ever-increasing value into a one-byte 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.

inline uint8_t quadwave8(uint8_t in)

quadwave8: quadratic waveform generator.

Spends just a little more time at the limits than ‘sine’ does.

inline uint8_t cubicwave8(uint8_t in)

cubicwave8: cubic waveform generator.

Spends visibly more time at the limits than ‘sine’ does.

inline uint8_t squarewave8(uint8_t in, uint8_t pulsewidth)

squarewave8: square wave generator.

Useful for turning a one-byte ever-increasing value into a one-byte 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              +--------(256-pulsewidth)--------
Parameters:
  • in

  • pulsewidth

Returns:

square wave output

inline uint16_t beat88(accum88 beats_per_minute_88, uint32_t timebase)

beat16 generates a 16-bit ‘sawtooth’ wave at a given BPM, with BPM specified in Q8.8 fixed-point 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.

inline uint16_t beat16(accum88 beats_per_minute, uint32_t timebase)

beat16 generates a 16-bit ‘sawtooth’ wave at a given BPM

inline uint8_t beat8(accum88 beats_per_minute, uint32_t timebase)

beat8 generates an 8-bit ‘sawtooth’ wave at a given BPM

inline uint16_t beatsin88(accum88 beats_per_minute_88, uint16_t lowest, uint16_t highest, uint32_t timebase, uint16_t phase_offset)

beatsin88 generates a 16-bit sine wave at a given BPM, that oscillates within a given range.

For this function, BPM MUST BE SPECIFIED as a Q8.8 fixed-point value; e.g. 120BPM must be specified as 120*256 = 30720. If you just want to specify “120”, use beatsin16 or beatsin8.

inline uint16_t beatsin16(accum88 beats_per_minute, uint16_t lowest, uint16_t highest, uint32_t timebase, uint16_t phase_offset)

beatsin16 generates a 16-bit sine wave at a given BPM, that oscillates within a given range.

inline uint8_t beatsin8(accum88 beats_per_minute, uint8_t lowest, uint8_t highest, uint32_t timebase, uint8_t phase_offset)

beatsin8 generates an 8-bit sine wave at a given BPM, that oscillates within a given range.

inline uint16_t seconds16()

Return the current seconds since boot in a 16-bit value.

Used as part of the “every N time-periods” mechanism

inline uint16_t minutes16()

Return the current minutes since boot in a 16-bit value.

Used as part of the “every N time-periods” mechanism

inline uint8_t hours8()

Return the current hours since boot in an 8-bit value.

Used as part of the “every N time-periods” mechanism

inline uint16_t div1024_32_16(uint32_t in32)

Helper routine to divide a 32-bit 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.

inline uint16_t bseconds16()

bseconds16 returns the current time-since-boot 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]