Control an array or chain of NeoPixel-compatible RGB LEDs. "NeoPixel" is Adafruit's name for WS2812- and WS2811-based addressable RGB LEDs. This library should work with any WS2811- or WS2812-based devices. Both the 400kHz and 800kHz protocols are supported. Most example code uses bit-banging to generate the timed signal precisely. This library uses an SPI peripheral instead. The main advantage of this is that the chip can service interrupts and the like without disrupting the signal (as long as the interrupts don't take _too_ long). The main disadvantage is that it requires the use of an SPI peripheral.
Dependents: mbed_ws2812b easyNeo WS2811_Solidarite blip_rainbow ... more
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
Generated on Tue Jul 12 2022 16:16:27 by 1.7.2