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)
WS2811.h@7:58623ad7f310, 2014-04-02 (annotated)
- 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?
User | Revision | Line number | New 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 |