From 9b26dc0d6386bb035c8b020f9ba3d636e6b8e8d2 Mon Sep 17 00:00:00 2001 From: Mark Kriegsman Date: Fri, 24 Oct 2014 06:46:36 -0400 Subject: Fixing sin8 and sin16 keywords --- keywords.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keywords.txt b/keywords.txt index c652466f..e1aaebec 100644 --- a/keywords.txt +++ b/keywords.txt @@ -91,9 +91,9 @@ random16_set_seed KEYWORD2 random16_get_seed KEYWORD2 random16_add_entropy KEYWORD2 sin16_avr KEYWORD2 -sin16_C KEYWORD2 +sin16 KEYWORD2 cos16 KEYWORD2 -sin8_C KEYWORD2 +sin8 KEYWORD2 cos8 KEYWORD2 lerp8by8 KEYWORD2 lerp16by16 KEYWORD2 -- cgit v1.2.3 From 50f3c8579c54cedc98ed141b433d345842efe8af Mon Sep 17 00:00:00 2001 From: Mark Kriegsman Date: Fri, 24 Oct 2014 11:46:46 -0400 Subject: Added beat (BPM) generators. --- lib8tion.h | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/lib8tion.h b/lib8tion.h index 272d33cc..228fe8f9 100644 --- a/lib8tion.h +++ b/lib8tion.h @@ -140,6 +140,18 @@ memcpy8( dest, src, bytecount) memset8( buf, value, bytecount) + - Beat generators which return sine or sawtooth + waves in a specified number of Beats Per Minute. + Sine wave beat generators can specify a low and + high range for the output. Sawtooth wave beat + generators always range 0-255 or 0-65535. + beatsin8( BPM, low8, high8) + = (sine(beatphase) * (high8-low8)) + low8 + beatsin16( BPM, low16, high16) + = (sine(beatphase) * (high16-low16)) + low16 + beat8( BPM) = 8-bit repeating sawtooth wave + beat16( BPM) = 16-bit repeating sawtooth wave + Lib8tion is pronounced like 'libation': lie-BAY-shun @@ -1669,4 +1681,112 @@ typedef q q62; typedef q q88; typedef q q124; + + +// Beat generators - These functions produce waves at a given +// number of 'beats per minute'. Internally, they use +// the Arduino function 'millis' to track elapsed time. +// Accuracy is a bit better than one part in a thousand. +// +// beat8( BPM ) returns an 8-bit value that cycles 'BPM' times +// per minute, rising from 0 to 255, resetting to zero, +// rising up again, etc.. The output of this function +// is suitable for feeding directly into sin8, and cos8, +// triwave8, quadwave8, and cubicwave8. +// beat16( BPM ) returns a 16-bit value that cycles 'BPM' times +// per minute, rising from 0 to 65535, resetting to zero, +// rising up again, etc. The output of this function is +// suitable for feeding directly into sin16 and cos16. +// +// beatsin8( BPM, uint8_t low, uint8_t high) returns an 8-bit value that +// rises and falls in a sine wave, 'BPM' times per minute, +// between the values of 'low' and 'high'. +// beatsin16( BPM, uint16_t low, uint16_t high) returns a 16-bit value +// that rises and falls in a sine wave, 'BPM' times per +// minute, between the values of 'low' and 'high'. +// +// BPM can be supplied two ways. The simpler way of specifying BPM is as +// a simple 8-bit integer from 1-255, (e.g., "120"). +// The more sophisticated way of specifying BPM allows for fractional +// "Q8.8" fixed point number (an 'accum88') with an 8-bit integer part and +// an 8-bit fractional part. The easiest way to construct this is to multiply +// a floating point BPM value (e.g. 120.3) by 256, (e.g. resulting in 30796 +// in this case), and pass that as the 16-bit BPM argument. +// +// Originally designed to make an entire animation project pulse with brightness. +// For that effect, add this line just above your existing call to "FastLED.show()": +// +// uint8_t bright = beatsin8( 60 /*BPM*/, 192 /*dimmest*/, 255 /*brightest*/ )); +// FastLED.setBrightness( bright ); +// FastLED.show(); +// +// The entire animation will now pulse between brightness 192 and 255 once per second. + + +// The beat generators need access to a millisecond counter. +// On Arduino, this is "millis()". On other platforms, you'll +// need to provide a function with this signature: +// uint32_t get_millisecond_timer(); +// that provides similar functionality. +// You can also force use of the get_millisecond_timer function +// by #defining USE_GET_MILLISECOND_TIMER. +#if defined(ARDUINO) && !defined(USE_GET_MILLISECOND_TIMER) +// Forward declaration of Arduino function 'millis'. +uint32_t millis(); +#define GET_MILLIS (millis()) +#else +uint32_t get_millisecond_timer(); +#define GET_MILLIS (get_millisecond_timer()) +#endif + +// beat16 generates a 16-bit 'sawtooth' wave at a given BPM +LIB8STATIC uint16_t beat16( accum88 beats_per_minute) +{ + // Convert simple 8-bit BPM's to full Q8.8 accum88's if needed + if( beats_per_minute < 256) beats_per_minute <<= 8; + + // BPM is 'beats per minute', or 'beats per 60000ms'. + // To avoid using the (slower) division operator, we + // want to convert 'beats per 60000ms' to 'beats per 65536ms', + // and then use a simple, fast bit-shift to divide by 65536. + // + // The ratio 65536:60000 is 279.620266667:256; we'll call it 280:256. + // The conversion is accurate to about 0.05%, more or less, + // e.g. if you ask for "120 BPM", you'll get about "119.93". + // If you need more precision than that, you can specify a + // sixteen-bit BPM value in Q8.8 fixed-point (an 'accum88'). + return ((GET_MILLIS) * beats_per_minute * 280) >> 16; +} + +// beat8 generates an 8-bit 'sawtooth' wave at a given BPM +LIB8STATIC uint8_t beat8( accum88 beats_per_minute) +{ + return beat16( beats_per_minute) >> 8; +} + +// beatsin16 generates a 16-bit sine wave at a given BPM, +// that oscillates within a given range. +LIB8STATIC uint16_t beatsin16( accum88 beats_per_minute, uint16_t lowest = 0, uint16_t highest = 65535) +{ + uint16_t beat = beat16( beats_per_minute); + uint16_t beatsin = (sin16( beat) + 32768); + uint16_t rangewidth = highest - lowest; + uint16_t scaledbeat = scale16( beatsin, rangewidth); + uint16_t result = lowest + scaledbeat; + return result; +} + +// beatsin8 generates an 8-bit sine wave at a given BPM, +// that oscillates within a given range. +LIB8STATIC uint8_t beatsin8( accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255) +{ + uint8_t beat = beat8( beats_per_minute); + uint8_t beatsin = sin8( beat); + uint8_t rangewidth = highest - lowest; + uint8_t scaledbeat = scale8( beatsin, rangewidth); + uint8_t result = lowest + scaledbeat; + return result; +} + + #endif -- cgit v1.2.3