Optimised fork of bikeNomad's WS2811 LED control library. Supports KL25Z and KL46Z
Fork of Multi_WS2811 by
Optimised to use far less RAM than the original.
Capable of running up to 8 strings of 240 LEDs each with plenty of RAM to spare on the KL46Z.
Should run at least three strings of 240 LEDs on the KL25Z (RAM limited)
Revision 7:58623ad7f310, committed 2014-04-02
- Comitter:
- Tomo2k
- Date:
- Wed Apr 02 13:22:25 2014 +0000
- Parent:
- 6:3b5b8a367f40
- Commit message:
- Updated comments, parameter names and added example usage
Changed in this revision
diff -r 3b5b8a367f40 -r 58623ad7f310 LedStrip.cpp --- a/LedStrip.cpp Wed Apr 02 12:16:42 2014 +0000 +++ b/LedStrip.cpp Wed Apr 02 13:22:25 2014 +0000 @@ -1,9 +1,9 @@ #include "LedStrip.h" -LedStrip::LedStrip(int n) +LedStrip::LedStrip(uint16_t pixelCount) : + numLEDs(pixelCount) { - // Allocate 3 bytes per pixel: - numLEDs = n; + // Allocate 3 bytes per pixel: pixels = (uint8_t *)malloc(numPixelBytes()); if (pixels) { memset(pixels, 0x00, numPixelBytes()); // Init to RGB 'off' state @@ -14,8 +14,8 @@ { free(pixels); } - -uint32_t LedStrip::total_luminance(void) + +uint32_t LedStrip::total_luminance() { uint32_t running_total; running_total = 0; @@ -25,56 +25,53 @@ } // Convert R,G,B to combined 32-bit color -uint32_t LedStrip::Color(uint8_t r, uint8_t g, uint8_t b) +uint32_t LedStrip::Color(uint8_t red, uint8_t green, uint8_t blue) { - // Take the lowest 7 bits of each value and append them end to end - // We have the top bit set high (its a 'parity-like' bit in the protocol - // and must be set!) - return ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b; + return ((uint32_t)green << 16) | ((uint32_t)red << 8) | (uint32_t)blue; } -// store the rgb component in our array -void LedStrip::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) +// Store the rgb component in our array +void LedStrip::setPixelColor(uint16_t pixNum, uint8_t red, uint8_t green, uint8_t blue) { - if (n >= numLEDs) return; // '>=' because arrays are 0-indexed - - pixels[n*3 ] = g; - pixels[n*3+1] = r; - pixels[n*3+2] = b; + if (pixNum < numLEDs) { + pixels[pixNum*3 ] = green; + pixels[pixNum*3+1] = red; + pixels[pixNum*3+2] = blue; + } } -void LedStrip::setPixelR(uint16_t n, uint8_t r) +void LedStrip::setPixelR(uint16_t pixNum, uint8_t red) { - if (n >= numLEDs) return; // '>=' because arrays are 0-indexed - - pixels[n*3+1] = r; + if (pixNum < numLEDs) { + pixels[pixNum*3+1] = red; + } } -void LedStrip::setPixelG(uint16_t n, uint8_t g) +void LedStrip::setPixelG(uint16_t pixNum, uint8_t green) { - if (n >= numLEDs) return; // '>=' because arrays are 0-indexed - - pixels[n*3] = g; + if (pixNum < numLEDs) { + pixels[pixNum*3] = green; + } } -void LedStrip::setPixelB(uint16_t n, uint8_t b) +void LedStrip::setPixelB(uint16_t pixNum, uint8_t blue) { - if (n >= numLEDs) return; // '>=' because arrays are 0-indexed - - pixels[n*3+2] = b; + if (pixNum < numLEDs) { + pixels[pixNum*3+2] = blue; + } } -void LedStrip::setPackedPixels(uint8_t * buffer, uint32_t n) +void LedStrip::setPackedPixels(uint8_t * buffer, uint32_t count) { - if (n >= numLEDs) return; - memcpy(pixels, buffer, (size_t) (n*3)); + if (count > numLEDs) return; + memcpy(pixels, buffer, (size_t) (count*3)); } -void LedStrip::setPixelColor(uint16_t n, uint32_t c) +void LedStrip::setPixelColor(uint16_t pixNum, uint32_t color) { - if (n >= numLEDs) return; // '>=' because arrays are 0-indexed - - pixels[n*3 ] = (c >> 16); - pixels[n*3+1] = (c >> 8); - pixels[n*3+2] = c; + if (pixNum < numLEDs) { + pixels[pixNum*3 ] = (color >> 16); + pixels[pixNum*3+1] = (color >> 8); + pixels[pixNum*3+2] = color; + } }
diff -r 3b5b8a367f40 -r 58623ad7f310 LedStrip.h --- a/LedStrip.h Wed Apr 02 12:16:42 2014 +0000 +++ b/LedStrip.h Wed Apr 02 13:22:25 2014 +0000 @@ -20,66 +20,73 @@ { public: /** Create an LED strip - @param n Number of RGB LEDs on the strip + @param pixelCount Number of RGB LEDs on the strip */ - LedStrip(int n); + LedStrip(uint16_t pixelCount); ~LedStrip(); //! Initialise the LED strip virtual void begin(void)=0; - //! Display the LED strip + //! Apply the new LED strip values virtual void show(void)=0; //! Blank the LED strip virtual void blank(void)=0; /** Pack RGB Color data - @param r Amount of Red - @param g Amount of Green - @param b Amount of Blue + @param red Amount of Red + @param green Amount of Green + @param blue Amount of Blue + @returns Packed RGB color data for one pixel */ - static uint32_t Color(uint8_t r, uint8_t g, uint8_t b); + static uint32_t Color(uint8_t red, uint8_t green, uint8_t blue); //! Number of RGB pixels - uint16_t numPixels(void) { return numLEDs; } + uint16_t numPixels() { + return numLEDs; + } //! Number of bytes used for pixel colour data - uint16_t numPixelBytes(void) { return numLEDs * 3; } - //! Total brightness of all diodes\n - //! Use to check power budget - uint32_t total_luminance(void); + uint16_t numPixelBytes() { + return numLEDs * 3; + } + /** Total brightness of all diodes\n + * Use to check power budget + @returns Sum total of all diodes (red + green + blue) + */ + uint32_t total_luminance(); /** Set Blue level of pixel - @param n Pixel Number - @param b Amount of Blue + @param pixNum Pixel Number + @param blue Amount of Blue */ - void setPixelB(uint16_t n, uint8_t b); + void setPixelB(uint16_t pixNum, uint8_t blue); /** Set Green level of pixel - @param n Pixel Number - @param g Amount of Green + @param pixNum Pixel Number + @param green Amount of Green */ - void setPixelG(uint16_t n, uint8_t g); + void setPixelG(uint16_t pixNum, uint8_t green); /** Set Red level of pixel - @param n Pixel Number - @param r Amount of Red + @param pixNum Pixel Number + @param red Amount of Red */ - void setPixelR(uint16_t n, uint8_t r); - + void setPixelR(uint16_t pixNum, uint8_t red); + /** Set color of pixel - @param n Pixel Number - @param c Packed RGB color data + @param pixNum Pixel Number + @param color Packed RGB color data */ - void setPixelColor(uint16_t n, uint32_t c); + void setPixelColor(uint16_t pixNum, uint32_t color); /** Set color of pixel - @param n Pixel Number - @param r Amount of Red - @param g Amount of Green - @param b Amount of Blue + @param pixNum Pixel Number + @param red Amount of Red + @param green Amount of Green + @param blue Amount of Blue */ - void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b); + void setPixelColor(uint16_t pixNum, uint8_t red, uint8_t green, uint8_t blue); /** Set color of all pixels @param *buffer Packed pixel data - @param n number of pixels - */ - void setPackedPixels(uint8_t * buffer, uint32_t n); + @param count Number of pixels + */ + void setPackedPixels(uint8_t * buffer, uint32_t count); protected: uint8_t *pixels; // Holds LED color values
diff -r 3b5b8a367f40 -r 58623ad7f310 WS2811.cpp --- a/WS2811.cpp Wed Apr 02 12:16:42 2014 +0000 +++ b/WS2811.cpp Wed Apr 02 13:22:25 2014 +0000 @@ -212,8 +212,8 @@ NVIC_EnableIRQ(TPM0_IRQn); } -WS2811::WS2811(unsigned n, unsigned pinNumber) - : LedStrip(n) +WS2811::WS2811(uint16_t pixelCount, uint8_t pinNumber) + : LedStrip(pixelCount) , pinMask(1U << pinNumber) { enabledPins |= pinMask; @@ -224,7 +224,7 @@ void WS2811::startDMA() { hw_init(); - + wait_for_dma_done(); dma_done = false; @@ -386,7 +386,7 @@ extern "C" void TPM0_IRQHandler() { TPM0->SC = 0; // disable internal clocking - TPM0->SC = TPM_SC_TOF_MASK; + TPM0->SC = TPM_SC_TOF_MASK; RESET_DEBUG; WS2811::dma_done = true; }
diff -r 3b5b8a367f40 -r 58623ad7f310 WS2811.h --- a/WS2811.h Wed Apr 02 12:16:42 2014 +0000 +++ b/WS2811.h Wed Apr 02 13:22:25 2014 +0000 @@ -13,8 +13,8 @@ // Modified by Ned Konz, December 2013. // Using three-phase DMA ala Paul Stoffegren's version. // -// Modified by richard Thompson, Marhc 2014. -// Uses 8-bit DMA transfers instead of 32-bit, uses 1/4 of the RAM. +// Modified by richard Thompson, March 2014. +// Uses 8-bit DMA transfers instead of 32-bit, uses 1/4 of the RAM (static) // Now capable of running 240 LEDs on one pin #ifndef MBED_WS2811_H @@ -29,7 +29,7 @@ extern "C" void DMA0_IRQHandler(); extern "C" void TPM0_IRQHandler(); -/** +/** * WS2811/WS2812/WS2812B * LED Strip controller\n * For FRDM-KL25Z and FRDM-KL46Z @@ -49,22 +49,101 @@ Eight strings:\n 240*8 LEDs: 11520 + (240*3) * 8 = 17,280 bytes + +Example usage: +@code +#include "mbed.h" +#include "WS2811.h" +#include "Colors.h" + +static void showRainbow(WS2811 &strip, float startHue, float sat, float brite, float hueShift) +{ + unsigned nLEDs = strip.numPixels(); + float hue = startHue; + for (unsigned i = 0; i < nLEDs; i++) { + uint8_t r, g, b; + Colors::HSBtoRGB(hue, sat, brite, &r, &g, &b); + strip.setPixelColor(i, r, g, b); + hue += hueShift; + if (hue > 1.0) hue = 0.0; + } + strip.show(); +} + +static void showSolidColor(WS2811 &strip, uint8_t r, uint8_t g, uint8_t b) +{ + unsigned nLEDs = strip.numPixels(); + for (unsigned i = 0; i < nLEDs; i++) { + strip.setPixelColor(i, r, g, b); + } + strip.show(); +} + +int main(void) +{ + WS2811 lightStrip1(nLEDs, 2); + WS2811 lightStrip2(nLEDs, 3); + WS2811 lightStrip3(nLEDs, 4); + + lightStrip1.begin(); + lightStrip2.begin(); + lightStrip3.begin(); + + uint8_t r =0; + uint8_t g =0; + uint8_t b =0; + + bool fadeUp = true; + + float startHue = 0.0; + for (;;) { + startHue += 0.01; + if (startHue > 1.0) startHue = 0.0; + if (fadeUp) { + if (r == 255) fadeUp = false; + else { + ++r; + ++g; + ++b; + } + } else { + if (r == 0) fadeUp = true; + else { + --r; + --g; + --b; + } + } + + // Solid fading white + showSolidColor(lightStrip1, r, g, b); + // Maximum saturation rainbow + showRainbow(lightStrip2, startHue, 1.0, 1.0, 1.0/nLEDs); + // Pastel rainbow + showRainbow(lightStrip3, startHue, 0.5, 1.0, 1.0/nLEDs); + + WS2811::startDMA(); + wait_ms(25); + frames++; + } +} +@endcode */ class WS2811 : public LedStrip { public: /** Set up the LED strip - @param n Number of LEDs on the strip. Must be less than MAX_LEDS_PER_STRIP + @param pixelCount Number of RGB LEDs on the strip. No more than MAX_LEDS_PER_STRIP (240) @param pinNumber Pin number on PORTD. 0-7. */ - WS2811(unsigned n, unsigned pinNumber); + WS2811(uint16_t pixelCount, uint8_t pinNumber); virtual void begin(); virtual void show(); virtual void blank(); - /** Send a level update to all the WS2811 LED strips - * All updates happen in parallel, ensure all (max. 8) strips have complete data before calling this. + /** Send a level update to all the WS2811 LED strips\n + * All updates happen in parallel, ensure all (max 8) strips have complete data before calling this. */ static void startDMA(); @@ -78,17 +157,19 @@ static bool initialized; static uint32_t enabledPins; static volatile bool dma_done; - static void wait_for_dma_done() { while (!dma_done) __WFI(); } + static void wait_for_dma_done() { + while (!dma_done) __WFI(); + } static void writeByte(uint8_t byte, uint32_t mask, uint8_t *dest); static void hw_init(); - static void io_init(); - static void clock_init(); - static void dma_init(); - static void tpm_init(); - static void dma_data_init(); - + static void io_init(); + static void clock_init(); + static void dma_init(); + static void tpm_init(); + static void dma_data_init(); + friend void TPM0_IRQHandler(); };