Optimised fork of bikeNomad's WS2811 LED control library. Supports KL25Z and KL46Z

Dependents:   CubicHand

Fork of Multi_WS2811 by Ned Konz

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)

Committer:
Tomo2k
Date:
Wed Apr 02 13:22:25 2014 +0000
Revision:
7:58623ad7f310
Parent:
6:3b5b8a367f40
Updated comments, parameter names and added example usage

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bikeNomad 0:a8535703f23b 1 // Mbed library to control WS2801-based RGB LED Strips
bikeNomad 0:a8535703f23b 2 // some portions (c) 2011 Jelmer Tiete
bikeNomad 0:a8535703f23b 3 // This library is ported from the Arduino implementation of Adafruit Industries
bikeNomad 0:a8535703f23b 4 // found at: http://github.com/adafruit/LPD8806
bikeNomad 0:a8535703f23b 5 // and their strips: http://www.adafruit.com/products/306
bikeNomad 0:a8535703f23b 6 // Released under the MIT License: http://mbed.org/license/mit
bikeNomad 0:a8535703f23b 7 //
bikeNomad 0:a8535703f23b 8 /*****************************************************************************/
bikeNomad 0:a8535703f23b 9
bikeNomad 0:a8535703f23b 10 // Heavily modified by Jas Strong, 2012-10-04
bikeNomad 0:a8535703f23b 11 // Changed to use a virtual base class and to use software SPI.
bikeNomad 0:a8535703f23b 12 //
bikeNomad 0:a8535703f23b 13 // Modified by Ned Konz, December 2013.
bikeNomad 0:a8535703f23b 14 // Using three-phase DMA ala Paul Stoffegren's version.
Tomo2k 3:2b5b03a3c0a5 15 //
Tomo2k 7:58623ad7f310 16 // Modified by richard Thompson, March 2014.
Tomo2k 7:58623ad7f310 17 // Uses 8-bit DMA transfers instead of 32-bit, uses 1/4 of the RAM (static)
Tomo2k 3:2b5b03a3c0a5 18 // Now capable of running 240 LEDs on one pin
bikeNomad 0:a8535703f23b 19
bikeNomad 0:a8535703f23b 20 #ifndef MBED_WS2811_H
bikeNomad 0:a8535703f23b 21 #define MBED_WS2811_H
bikeNomad 0:a8535703f23b 22
bikeNomad 0:a8535703f23b 23 #include "mbed.h"
bikeNomad 0:a8535703f23b 24 #include "LedStrip.h"
bikeNomad 0:a8535703f23b 25
Tomo2k 4:586d20c99dbf 26 //! Maximum number of LEDs per strip
Tomo2k 2:1c2c9c8788a8 27 #define MAX_LEDS_PER_STRIP 240
bikeNomad 0:a8535703f23b 28
bikeNomad 0:a8535703f23b 29 extern "C" void DMA0_IRQHandler();
bikeNomad 0:a8535703f23b 30 extern "C" void TPM0_IRQHandler();
bikeNomad 0:a8535703f23b 31
Tomo2k 7:58623ad7f310 32 /**
Tomo2k 5:7e40afd8d533 33 * WS2811/WS2812/WS2812B
Tomo2k 5:7e40afd8d533 34 * LED Strip controller\n
Tomo2k 5:7e40afd8d533 35 * For FRDM-KL25Z and FRDM-KL46Z
Tomo2k 6:3b5b8a367f40 36
Tomo2k 6:3b5b8a367f40 37 RAM usage:\n
Tomo2k 6:3b5b8a367f40 38 Per individual LED: 3 bytes (malloc'd) for RGB data
Tomo2k 6:3b5b8a367f40 39
Tomo2k 6:3b5b8a367f40 40 Strip length per LED:\n
Tomo2k 6:3b5b8a367f40 41 24 bytes (static) for bit data\n
Tomo2k 6:3b5b8a367f40 42 + 24 bytes (static) for ones data\n
Tomo2k 6:3b5b8a367f40 43 = 48 bytes
Tomo2k 6:3b5b8a367f40 44
Tomo2k 6:3b5b8a367f40 45 240 LEDs max per string = 11,520 bytes static
Tomo2k 6:3b5b8a367f40 46
Tomo2k 6:3b5b8a367f40 47 One string:\n
Tomo2k 6:3b5b8a367f40 48 240 LEDs : 11520 + 240*3 = 12,240 bytes
Tomo2k 6:3b5b8a367f40 49
Tomo2k 6:3b5b8a367f40 50 Eight strings:\n
Tomo2k 6:3b5b8a367f40 51 240*8 LEDs: 11520 + (240*3) * 8 = 17,280 bytes
Tomo2k 7:58623ad7f310 52
Tomo2k 7:58623ad7f310 53 Example usage:
Tomo2k 7:58623ad7f310 54 @code
Tomo2k 7:58623ad7f310 55 #include "mbed.h"
Tomo2k 7:58623ad7f310 56 #include "WS2811.h"
Tomo2k 7:58623ad7f310 57 #include "Colors.h"
Tomo2k 7:58623ad7f310 58
Tomo2k 7:58623ad7f310 59 static void showRainbow(WS2811 &strip, float startHue, float sat, float brite, float hueShift)
Tomo2k 7:58623ad7f310 60 {
Tomo2k 7:58623ad7f310 61 unsigned nLEDs = strip.numPixels();
Tomo2k 7:58623ad7f310 62 float hue = startHue;
Tomo2k 7:58623ad7f310 63 for (unsigned i = 0; i < nLEDs; i++) {
Tomo2k 7:58623ad7f310 64 uint8_t r, g, b;
Tomo2k 7:58623ad7f310 65 Colors::HSBtoRGB(hue, sat, brite, &r, &g, &b);
Tomo2k 7:58623ad7f310 66 strip.setPixelColor(i, r, g, b);
Tomo2k 7:58623ad7f310 67 hue += hueShift;
Tomo2k 7:58623ad7f310 68 if (hue > 1.0) hue = 0.0;
Tomo2k 7:58623ad7f310 69 }
Tomo2k 7:58623ad7f310 70 strip.show();
Tomo2k 7:58623ad7f310 71 }
Tomo2k 7:58623ad7f310 72
Tomo2k 7:58623ad7f310 73 static void showSolidColor(WS2811 &strip, uint8_t r, uint8_t g, uint8_t b)
Tomo2k 7:58623ad7f310 74 {
Tomo2k 7:58623ad7f310 75 unsigned nLEDs = strip.numPixels();
Tomo2k 7:58623ad7f310 76 for (unsigned i = 0; i < nLEDs; i++) {
Tomo2k 7:58623ad7f310 77 strip.setPixelColor(i, r, g, b);
Tomo2k 7:58623ad7f310 78 }
Tomo2k 7:58623ad7f310 79 strip.show();
Tomo2k 7:58623ad7f310 80 }
Tomo2k 7:58623ad7f310 81
Tomo2k 7:58623ad7f310 82 int main(void)
Tomo2k 7:58623ad7f310 83 {
Tomo2k 7:58623ad7f310 84 WS2811 lightStrip1(nLEDs, 2);
Tomo2k 7:58623ad7f310 85 WS2811 lightStrip2(nLEDs, 3);
Tomo2k 7:58623ad7f310 86 WS2811 lightStrip3(nLEDs, 4);
Tomo2k 7:58623ad7f310 87
Tomo2k 7:58623ad7f310 88 lightStrip1.begin();
Tomo2k 7:58623ad7f310 89 lightStrip2.begin();
Tomo2k 7:58623ad7f310 90 lightStrip3.begin();
Tomo2k 7:58623ad7f310 91
Tomo2k 7:58623ad7f310 92 uint8_t r =0;
Tomo2k 7:58623ad7f310 93 uint8_t g =0;
Tomo2k 7:58623ad7f310 94 uint8_t b =0;
Tomo2k 7:58623ad7f310 95
Tomo2k 7:58623ad7f310 96 bool fadeUp = true;
Tomo2k 7:58623ad7f310 97
Tomo2k 7:58623ad7f310 98 float startHue = 0.0;
Tomo2k 7:58623ad7f310 99 for (;;) {
Tomo2k 7:58623ad7f310 100 startHue += 0.01;
Tomo2k 7:58623ad7f310 101 if (startHue > 1.0) startHue = 0.0;
Tomo2k 7:58623ad7f310 102 if (fadeUp) {
Tomo2k 7:58623ad7f310 103 if (r == 255) fadeUp = false;
Tomo2k 7:58623ad7f310 104 else {
Tomo2k 7:58623ad7f310 105 ++r;
Tomo2k 7:58623ad7f310 106 ++g;
Tomo2k 7:58623ad7f310 107 ++b;
Tomo2k 7:58623ad7f310 108 }
Tomo2k 7:58623ad7f310 109 } else {
Tomo2k 7:58623ad7f310 110 if (r == 0) fadeUp = true;
Tomo2k 7:58623ad7f310 111 else {
Tomo2k 7:58623ad7f310 112 --r;
Tomo2k 7:58623ad7f310 113 --g;
Tomo2k 7:58623ad7f310 114 --b;
Tomo2k 7:58623ad7f310 115 }
Tomo2k 7:58623ad7f310 116 }
Tomo2k 7:58623ad7f310 117
Tomo2k 7:58623ad7f310 118 // Solid fading white
Tomo2k 7:58623ad7f310 119 showSolidColor(lightStrip1, r, g, b);
Tomo2k 7:58623ad7f310 120 // Maximum saturation rainbow
Tomo2k 7:58623ad7f310 121 showRainbow(lightStrip2, startHue, 1.0, 1.0, 1.0/nLEDs);
Tomo2k 7:58623ad7f310 122 // Pastel rainbow
Tomo2k 7:58623ad7f310 123 showRainbow(lightStrip3, startHue, 0.5, 1.0, 1.0/nLEDs);
Tomo2k 7:58623ad7f310 124
Tomo2k 7:58623ad7f310 125 WS2811::startDMA();
Tomo2k 7:58623ad7f310 126 wait_ms(25);
Tomo2k 7:58623ad7f310 127 frames++;
Tomo2k 7:58623ad7f310 128 }
Tomo2k 7:58623ad7f310 129 }
Tomo2k 7:58623ad7f310 130 @endcode
Tomo2k 3:2b5b03a3c0a5 131 */
bikeNomad 0:a8535703f23b 132 class WS2811 : public LedStrip
bikeNomad 0:a8535703f23b 133 {
bikeNomad 0:a8535703f23b 134 public:
Tomo2k 3:2b5b03a3c0a5 135 /** Set up the LED strip
Tomo2k 7:58623ad7f310 136 @param pixelCount Number of RGB LEDs on the strip. No more than MAX_LEDS_PER_STRIP (240)
Tomo2k 3:2b5b03a3c0a5 137 @param pinNumber Pin number on PORTD. 0-7.
Tomo2k 3:2b5b03a3c0a5 138 */
Tomo2k 7:58623ad7f310 139 WS2811(uint16_t pixelCount, uint8_t pinNumber);
bikeNomad 0:a8535703f23b 140
bikeNomad 0:a8535703f23b 141 virtual void begin();
bikeNomad 0:a8535703f23b 142 virtual void show();
bikeNomad 0:a8535703f23b 143 virtual void blank();
bikeNomad 0:a8535703f23b 144
Tomo2k 7:58623ad7f310 145 /** Send a level update to all the WS2811 LED strips\n
Tomo2k 7:58623ad7f310 146 * All updates happen in parallel, ensure all (max 8) strips have complete data before calling this.
Tomo2k 3:2b5b03a3c0a5 147 */
bikeNomad 0:a8535703f23b 148 static void startDMA();
bikeNomad 0:a8535703f23b 149
bikeNomad 0:a8535703f23b 150 private:
bikeNomad 0:a8535703f23b 151 uint32_t pinMask;
bikeNomad 0:a8535703f23b 152
bikeNomad 0:a8535703f23b 153 void writePixel(unsigned n, uint8_t *p);
bikeNomad 0:a8535703f23b 154
bikeNomad 0:a8535703f23b 155 // Class Static:
bikeNomad 0:a8535703f23b 156
bikeNomad 0:a8535703f23b 157 static bool initialized;
bikeNomad 0:a8535703f23b 158 static uint32_t enabledPins;
bikeNomad 0:a8535703f23b 159 static volatile bool dma_done;
Tomo2k 7:58623ad7f310 160 static void wait_for_dma_done() {
Tomo2k 7:58623ad7f310 161 while (!dma_done) __WFI();
Tomo2k 7:58623ad7f310 162 }
bikeNomad 0:a8535703f23b 163
Tomo2k 2:1c2c9c8788a8 164 static void writeByte(uint8_t byte, uint32_t mask, uint8_t *dest);
bikeNomad 0:a8535703f23b 165
bikeNomad 0:a8535703f23b 166 static void hw_init();
Tomo2k 7:58623ad7f310 167 static void io_init();
Tomo2k 7:58623ad7f310 168 static void clock_init();
Tomo2k 7:58623ad7f310 169 static void dma_init();
Tomo2k 7:58623ad7f310 170 static void tpm_init();
Tomo2k 7:58623ad7f310 171 static void dma_data_init();
Tomo2k 7:58623ad7f310 172
bikeNomad 0:a8535703f23b 173 friend void TPM0_IRQHandler();
bikeNomad 0:a8535703f23b 174 };
bikeNomad 0:a8535703f23b 175
bikeNomad 0:a8535703f23b 176 #endif
bikeNomad 0:a8535703f23b 177