for SoundWS2812B-FFT

Dependencies:   BurstSPI

Fork of PixelArray by Jacob Bramley

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers neopixel.h Source File

neopixel.h

00001 #ifndef NEOPIXEL_H
00002 #define NEOPIXEL_H
00003 
00004 #include <stdint.h>
00005 #include "mbed.h"
00006 #include "BurstSPI.h"
00007 
00008 namespace neopixel
00009 {
00010 
00011 /** Represent the value of a single pixel.
00012  *
00013  * Each channel uses the full 8 bits: 0x00 is fully off and 0xff is fully on.
00014  */
00015 struct Pixel {
00016     uint8_t red;
00017     uint8_t green;
00018     uint8_t blue;
00019 };
00020 
00021 /** Control the byte order used by the connected pixels.
00022  *
00023  * The vast majority of NeoPixels use a GRB byte order, so this is the default.
00024  * A few use a RGB byte order.
00025  *
00026  * In principle, the WS281x controllers could be connected with _any_ byte
00027  * ordering, but only GRB and RGB are supported at the moment.
00028  */
00029 enum ByteOrder {
00030     BYTE_ORDER_GRB,
00031     BYTE_ORDER_RGB,
00032 };
00033 
00034 /** Set the protocol mode.
00035  *
00036  * The protocol is named after the clock, as though WS8211 supports only the
00037  * 400kHz clock, WS8212 supports both.
00038  */
00039 enum Protocol {
00040     PROTOCOL_800KHZ,
00041     PROTOCOL_400KHZ,
00042 };
00043 
00044 typedef void (*PixelGenerator)(Pixel* out, uint32_t index, uintptr_t extra);
00045 
00046 /** Control an array or chain of NeoPixel-compatible RGB LEDs.
00047  *
00048  * "NeoPixel" is Adafruit's name for WS2812- and WS2811-based addressable RGB
00049  * LEDs. This library should work with any WS2811- or WS2812-based devices, as
00050  * long as they support the fast-mode (800kHz) interface.
00051  *
00052  * Most example code uses bit-banging to generate the timed signal precisely.
00053  * This library uses an SPI peripheral instead. The main advantage of this is
00054  * that the chip can service interrupts and the like without disrupting the
00055  * signal (as long as the interrupts don't take _too_ long). The main
00056  * disadvantage is that it requires the use of an SPI peripheral.
00057  *
00058  * @note SPI peripherals will tend to leave the output pin ('MOSI') floating
00059  * after a packet is sent. This will confuse the connected pixels, which expect
00060  * the line to be driven low when idle. One way to fix this is to add a 10k
00061  * resistor between 'MOSI' and ground so that it drops to '0' when not driven.
00062  * Another method is to enable the on-chip pull-down resistor on the output pin.
00063  * However, the mbed API only exposes this function through the DigitalIn and
00064  * DigitalInOut classes. If you want to use the on-chip pull-down, you'll have
00065  * to temporarily connect a DigitalIn peripheral _before_ creating instantiating
00066  * the PixelArray.
00067  *
00068  * @code
00069  * // Sample generator: Cycle through each colour combination, increasing the
00070  * // brightness each time. `extra` is used as an iteration counter.
00071  * void generate(neopixel::Pixel * out, uint32_t index, uintptr_t extra) {
00072  *   uint32_t brightness = (index + extra) >> 3;
00073  *   out->red   = ((index + extra) & 0x1) ? brightness : 0;
00074  *   out->green = ((index + extra) & 0x2) ? brightness : 0;
00075  *   out->blue  = ((index + extra) & 0x4) ? brightness : 0;
00076  * }
00077  *
00078  * int main() {
00079  *   // Create a temporary DigitalIn so we can configure the pull-down resistor.
00080  *   // (The mbed API doesn't provide any other way to do this.)
00081  *   // An alternative is to connect an external pull-down resistor.
00082  *   DigitalIn(p5, PullDown);
00083  *
00084  *   // The pixel array control class.
00085  *   neopixel::PixelArray array(p5);
00086  *
00087  *   uint32_t offset = 0;
00088  *   while (1) {
00089  *     array.update(generate, 100, offset++);
00090  *     wait_ms(250);
00091  *   }
00092  * }
00093  * @endcode
00094  */
00095 class PixelArray
00096 {
00097 public:
00098     /** Initialize a PixelArray.
00099      *
00100      * @param out Output (SPI MOSI) pin.
00101      * @param byte_order The order in which to transmit colour channels.
00102      */
00103     PixelArray(PinName out,
00104                ByteOrder byte_order = BYTE_ORDER_GRB,
00105                Protocol protocol = PROTOCOL_800KHZ);
00106 
00107     /** Update the pixel display from a buffer.
00108      *
00109      * This update method is good in the following situations:
00110      * - You want to make incremental changes to a fixed frame pattern.
00111      * - The frame is hard (or impossible) to generate procedurally.
00112      * - The frame requires a lot of time to generate.
00113      *
00114      * @param buffer Pixel data to be written.
00115      * @param length The number of pixels to write.
00116      *
00117      * buffer[0] is written to the pixel nearest the mbed.
00118      * buffer[length-1] is written to the pixel furthest from the mbed.
00119      */
00120     void update(Pixel buffer[], uint32_t length);
00121 
00122     /** Update a pixel chain using the callback to generate the value for each
00123      * pixel.
00124      *
00125      * This update method is good in the following situations:
00126      * - You have a lot of pixels to drive and don't have enough RAM to buffer
00127      *   them all.
00128      * - You want to display a frame pattern that can be generated procedurally
00129      *   generated without intensive processing.
00130      *
00131      * @param generator A callback which is called to generate a value for each
00132      * pixel on demand. This function must be fairly fast: if it takes more
00133      * than about 8-9us, the interface will reset and the display will be
00134      * corrupted. The exact time limits will vary between WS281x variants. As a
00135      * rough guide, an LPC1768 at 96MHz can (conservatively) execute about 750
00136      * instructions in that time.
00137      *
00138      * @param length The number of pixels to write.
00139      *
00140      * @param extra An arbitrary value to pass into the generator function. For
00141      * example, this is a good way to pass an animation time index to the
00142      * generator function.
00143      */
00144     void update(PixelGenerator generator, uint32_t length, uintptr_t extra);
00145 
00146 private:
00147     BurstSPI spi_;
00148     ByteOrder byte_order_;
00149     Protocol protocol_;
00150     
00151     static int const latch_time_us_ = 50;
00152     
00153     void send_pixel(Pixel& pixel);
00154 };
00155 
00156 }
00157 
00158 #endif