Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
WS2811.h@5:2c3b76ea0b40, 2015-06-13 (annotated)
- Committer:
- Ned Konz
- Date:
- Sat Jun 13 00:18:32 2015 -0700
- Revision:
- 5:2c3b76ea0b40
- Parent:
- 4:990838718b51
Worked out flapping and color animation
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| Ned Konz |
3:df4319053bfa | 1 | //! @file WS2811.h |
| Ned Konz |
3:df4319053bfa | 2 | // Mbed library to control WS2801-based RGB LED Strips |
| Ned Konz |
3:df4319053bfa | 3 | // some portions (c) 2011 Jelmer Tiete |
| Ned Konz |
3:df4319053bfa | 4 | // This library is ported from the Arduino implementation of Adafruit Industries |
| Ned Konz |
3:df4319053bfa | 5 | // found at: http://github.com/adafruit/LPD8806 |
| Ned Konz |
3:df4319053bfa | 6 | // and their strips: http://www.adafruit.com/products/306 |
| Ned Konz |
3:df4319053bfa | 7 | // Released under the MIT License: http://mbed.org/license/mit |
| Ned Konz |
3:df4319053bfa | 8 | // |
| Ned Konz |
3:df4319053bfa | 9 | /*****************************************************************************/ |
| Ned Konz |
3:df4319053bfa | 10 | |
| Ned Konz |
3:df4319053bfa | 11 | // Heavily modified by Jas Strong, 2012-10-04 |
| Ned Konz |
3:df4319053bfa | 12 | // Changed to use a virtual base class and to use software SPI. |
| Ned Konz |
3:df4319053bfa | 13 | // |
| Ned Konz |
3:df4319053bfa | 14 | // Modified by Ned Konz, December 2013. |
| Ned Konz |
3:df4319053bfa | 15 | // Using three-phase DMA ala Paul Stoffegren's version. |
| Ned Konz |
3:df4319053bfa | 16 | // Example: |
| Ned Konz |
3:df4319053bfa | 17 | // @code |
| Ned Konz |
3:df4319053bfa | 18 | // #include <mbed.h> |
| Ned Konz |
3:df4319053bfa | 19 | // // In one file that includes this one, |
| Ned Konz |
3:df4319053bfa | 20 | // // #define INSTANTIATE_TEMPLATES as non-zero before including this file: |
| Ned Konz |
3:df4319053bfa | 21 | // #define INSTANTIATE_TEMPLATES 1 |
| Ned Konz |
3:df4319053bfa | 22 | // #include "WS2811.h" |
| Ned Konz |
3:df4319053bfa | 23 | // // Then declare a template class with the maximum number of LEDs per strip that you will need: |
| Ned Konz |
3:df4319053bfa | 24 | // unsigned const maxLEDs = 30; |
| Ned Konz |
3:df4319053bfa | 25 | // template class WS2811<maxLEDs>; |
| Ned Konz |
3:df4319053bfa | 26 | // // You can reduce typing using a typedef: |
| Ned Konz |
3:df4319053bfa | 27 | // typedef WS2811<maxLEDs> MyWS2811; |
| Ned Konz |
3:df4319053bfa | 28 | // // Later, define instances of this template class, each with up to the maximum number of LEDs: |
| Ned Konz |
3:df4319053bfa | 29 | // MyWS2811 lightStrip1(nLEDs, DATA_OUT_PIN1); |
| Ned Konz |
3:df4319053bfa | 30 | // MyWS2811 lightStrip2(nLEDs, DATA_OUT_PIN2); |
| Ned Konz |
3:df4319053bfa | 31 | // @endcode |
| Ned Konz |
3:df4319053bfa | 32 | |
| Ned Konz |
3:df4319053bfa | 33 | #ifndef MBED_WS2811_H |
| Ned Konz |
3:df4319053bfa | 34 | #define MBED_WS2811_H |
| Ned Konz |
3:df4319053bfa | 35 | |
| Ned Konz |
3:df4319053bfa | 36 | #include "LedStrip.h" |
| Ned Konz |
3:df4319053bfa | 37 | |
| Ned Konz |
3:df4319053bfa | 38 | // |
| Ned Konz |
3:df4319053bfa | 39 | // Configuration |
| Ned Konz |
3:df4319053bfa | 40 | // |
| Ned Konz |
3:df4319053bfa | 41 | |
| Ned Konz |
3:df4319053bfa | 42 | #ifndef WS2811_IO_PORT |
| Ned Konz |
3:df4319053bfa | 43 | #define WS2811_IO_PORT PORTD |
| Ned Konz |
3:df4319053bfa | 44 | #endif |
| Ned Konz |
3:df4319053bfa | 45 | |
| Ned Konz |
3:df4319053bfa | 46 | #ifndef WS2811_IO_GPIO |
| Ned Konz |
3:df4319053bfa | 47 | #define WS2811_IO_GPIO PTD |
| Ned Konz |
3:df4319053bfa | 48 | #endif |
| Ned Konz |
3:df4319053bfa | 49 | |
| Ned Konz |
3:df4319053bfa | 50 | // define WS2811_DEBUG_PIN to identify a pin in WS2811_IOPORT used for debug output |
| Ned Konz |
3:df4319053bfa | 51 | // #define WS2811_DEBUG_PIN 4 /* PTD4 debugOut */ |
| Ned Konz |
3:df4319053bfa | 52 | |
| Ned Konz |
3:df4319053bfa | 53 | // Define WS2811_MONITOR_TPM0_PWM as non-zero to monitor PWM timing on PTD0 and PTD1 |
| Ned Konz |
3:df4319053bfa | 54 | // PTD0 TPM0/CH0 PWM_1 J2/06 |
| Ned Konz |
3:df4319053bfa | 55 | // PTD1 TPM0/CH1 PWM_2 J2/12 (also LED_BLUE) |
| Ned Konz |
3:df4319053bfa | 56 | #define WS2811_MONITOR_TPM0_PWM 0 |
| Ned Konz |
3:df4319053bfa | 57 | |
| Ned Konz |
3:df4319053bfa | 58 | extern "C" void DMA0_IRQHandler(); |
| Ned Konz |
3:df4319053bfa | 59 | extern "C" void TPM0_IRQHandler(); |
| Ned Konz |
3:df4319053bfa | 60 | |
| Ned Konz |
3:df4319053bfa | 61 | template <unsigned MAX_LEDS_PER_STRIP> |
| Ned Konz |
3:df4319053bfa | 62 | class WS2811 : public LedStrip |
| Ned Konz |
3:df4319053bfa | 63 | { |
| Ned Konz |
5:2c3b76ea0b40 | 64 | public: |
| Ned Konz |
3:df4319053bfa | 65 | WS2811(unsigned n, unsigned pinNumber) |
| Ned Konz |
3:df4319053bfa | 66 | : LedStrip(n) |
| Ned Konz |
3:df4319053bfa | 67 | , pinMask(1U << pinNumber) |
| Ned Konz |
3:df4319053bfa | 68 | { |
| Ned Konz |
3:df4319053bfa | 69 | enabledPins |= pinMask; |
| Ned Konz |
5:2c3b76ea0b40 | 70 | initialized = false; |
| Ned Konz |
3:df4319053bfa | 71 | } |
| Ned Konz |
3:df4319053bfa | 72 | |
| Ned Konz |
3:df4319053bfa | 73 | virtual void show() |
| Ned Konz |
3:df4319053bfa | 74 | { |
| Ned Konz |
3:df4319053bfa | 75 | uint16_t i, n = numPixels(); // 3 bytes per LED |
| Ned Konz |
3:df4319053bfa | 76 | uint8_t *p = pixels; |
| Ned Konz |
5:2c3b76ea0b40 | 77 | |
| Ned Konz |
5:2c3b76ea0b40 | 78 | for (i=0; i<n; i++ ) |
| Ned Konz |
5:2c3b76ea0b40 | 79 | { |
| Ned Konz |
3:df4319053bfa | 80 | writePixel(i, p); |
| Ned Konz |
3:df4319053bfa | 81 | p += 3; |
| Ned Konz |
3:df4319053bfa | 82 | } |
| Ned Konz |
3:df4319053bfa | 83 | } |
| Ned Konz |
5:2c3b76ea0b40 | 84 | |
| Ned Konz |
3:df4319053bfa | 85 | virtual void begin() |
| Ned Konz |
3:df4319053bfa | 86 | { |
| Ned Konz |
3:df4319053bfa | 87 | blank(); |
| Ned Konz |
3:df4319053bfa | 88 | show(); |
| Ned Konz |
3:df4319053bfa | 89 | } |
| Ned Konz |
3:df4319053bfa | 90 | |
| Ned Konz |
3:df4319053bfa | 91 | virtual void blank() |
| Ned Konz |
3:df4319053bfa | 92 | { |
| Ned Konz |
3:df4319053bfa | 93 | std::memset(pixels, 0x00, numPixelBytes()); |
| Ned Konz |
5:2c3b76ea0b40 | 94 | |
| Ned Konz |
3:df4319053bfa | 95 | std::memset(dmaData.dmaWords, 0x00, sizeof(dmaData.dmaWords)); |
| Ned Konz |
3:df4319053bfa | 96 | } |
| Ned Konz |
3:df4319053bfa | 97 | |
| Ned Konz |
3:df4319053bfa | 98 | static void startDMA(); |
| Ned Konz |
3:df4319053bfa | 99 | static unsigned maxLEDsPerStrip() { return MAX_LEDS_PER_STRIP; } |
| Ned Konz |
3:df4319053bfa | 100 | static void wait_for_dma_done(); |
| Ned Konz |
3:df4319053bfa | 101 | |
| Ned Konz |
3:df4319053bfa | 102 | private: |
| Ned Konz |
3:df4319053bfa | 103 | uint32_t pinMask; |
| Ned Konz |
3:df4319053bfa | 104 | |
| Ned Konz |
3:df4319053bfa | 105 | void writePixel(unsigned n, uint8_t *p) |
| Ned Konz |
3:df4319053bfa | 106 | { |
| Ned Konz |
3:df4319053bfa | 107 | uint32_t *dest = dmaData.dmaWords + n * BITS_PER_RGB; |
| Ned Konz |
3:df4319053bfa | 108 | writeByte(*p++, pinMask, dest + 0); // G |
| Ned Konz |
3:df4319053bfa | 109 | writeByte(*p++, pinMask, dest + 8); // R |
| Ned Konz |
3:df4319053bfa | 110 | writeByte(*p, pinMask, dest + 16); // B |
| Ned Konz |
3:df4319053bfa | 111 | } |
| Ned Konz |
3:df4319053bfa | 112 | |
| Ned Konz |
3:df4319053bfa | 113 | // Class Static: |
| Ned Konz |
3:df4319053bfa | 114 | |
| Ned Konz |
3:df4319053bfa | 115 | static bool initialized; |
| Ned Konz |
3:df4319053bfa | 116 | static uint32_t enabledPins; |
| Ned Konz |
3:df4319053bfa | 117 | |
| Ned Konz |
3:df4319053bfa | 118 | static void writeByte(uint8_t byte, uint32_t mask, uint32_t *dest) |
| Ned Konz |
3:df4319053bfa | 119 | { |
| Ned Konz |
5:2c3b76ea0b40 | 120 | for (uint8_t bm = 0x80; bm; bm >>= 1) |
| Ned Konz |
5:2c3b76ea0b40 | 121 | { |
| Ned Konz |
3:df4319053bfa | 122 | // MSBit first |
| Ned Konz |
3:df4319053bfa | 123 | if (byte & bm) |
| Ned Konz |
3:df4319053bfa | 124 | *dest |= mask; |
| Ned Konz |
3:df4319053bfa | 125 | else |
| Ned Konz |
3:df4319053bfa | 126 | *dest &= ~mask; |
| Ned Konz |
3:df4319053bfa | 127 | dest++; |
| Ned Konz |
3:df4319053bfa | 128 | } |
| Ned Konz |
3:df4319053bfa | 129 | } |
| Ned Konz |
3:df4319053bfa | 130 | |
| Ned Konz |
3:df4319053bfa | 131 | static void hw_init(); |
| Ned Konz |
3:df4319053bfa | 132 | static void io_init(); |
| Ned Konz |
3:df4319053bfa | 133 | static void clock_init(); |
| Ned Konz |
3:df4319053bfa | 134 | static void dma_init(); |
| Ned Konz |
3:df4319053bfa | 135 | static void tpm_init(); |
| Ned Konz |
3:df4319053bfa | 136 | static void dma_data_init(); |
| Ned Konz |
5:2c3b76ea0b40 | 137 | |
| Ned Konz |
3:df4319053bfa | 138 | friend void TPM0_IRQHandler(); |
| Ned Konz |
5:2c3b76ea0b40 | 139 | |
| Ned Konz |
5:2c3b76ea0b40 | 140 | static const unsigned DMA_LEADING_ZEROS = 2; |
| Ned Konz |
5:2c3b76ea0b40 | 141 | static const unsigned BITS_PER_RGB = 24; |
| Ned Konz |
3:df4319053bfa | 142 | static const unsigned DMA_TRAILING_ZEROS = 1; |
| Ned Konz |
3:df4319053bfa | 143 | |
| Ned Konz |
5:2c3b76ea0b40 | 144 | struct DMALayout |
| Ned Konz |
5:2c3b76ea0b40 | 145 | { |
| Ned Konz |
3:df4319053bfa | 146 | uint32_t start_t1_low[ DMA_LEADING_ZEROS ]; |
| Ned Konz |
3:df4319053bfa | 147 | uint32_t dmaWords[ BITS_PER_RGB * MAX_LEDS_PER_STRIP ]; |
| Ned Konz |
3:df4319053bfa | 148 | uint32_t trailing_zeros_1[ DMA_TRAILING_ZEROS ]; |
| Ned Konz |
5:2c3b76ea0b40 | 149 | |
| Ned Konz |
3:df4319053bfa | 150 | uint32_t start_t0_high[ DMA_LEADING_ZEROS - 1 ]; |
| Ned Konz |
3:df4319053bfa | 151 | uint32_t allOnes[ BITS_PER_RGB * MAX_LEDS_PER_STRIP ]; |
| Ned Konz |
3:df4319053bfa | 152 | uint32_t trailing_zeros_2[ DMA_TRAILING_ZEROS + 1 ]; |
| Ned Konz |
3:df4319053bfa | 153 | }; |
| Ned Konz |
5:2c3b76ea0b40 | 154 | |
| Ned Konz |
3:df4319053bfa | 155 | static DMALayout dmaData; |
| Ned Konz |
3:df4319053bfa | 156 | }; |
| Ned Konz |
3:df4319053bfa | 157 | |
| Ned Konz |
3:df4319053bfa | 158 | #endif |
| Ned Konz |
3:df4319053bfa | 159 | |
| Ned Konz |
3:df4319053bfa | 160 | #if INSTANTIATE_TEMPLATES |
| Ned Konz |
3:df4319053bfa | 161 | #include "WS2811.cpp" |
| Ned Konz |
3:df4319053bfa | 162 | #endif |
| Ned Konz |
3:df4319053bfa | 163 |
Generic WS2811/WS2812