Ned Konz / Multi_WS2811

Dependents:   Multi_WS2811_test

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?

UserRevisionLine numberNew 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