Only update of BurstSPI-Library
Dependents: WordClock TI_NEOPIXEL_SPI
Fork of PixelArray by
Diff: neopixel.h
- Revision:
- 2:3c3c41774cdf
- Child:
- 3:6f392fcb1d3b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/neopixel.h Fri Aug 01 22:17:23 2014 +0000 @@ -0,0 +1,146 @@ +#ifndef NEOPIXEL_H +#define NEOPIXEL_H + +#include <stdint.h> +#include "mbed.h" +#include "BurstSPI.h" + +namespace neopixel +{ + +/** Represent the value of a single pixel. + * + * Each channel uses the full 8 bits: 0x00 is fully off and 0xff is fully on. + */ +struct Pixel { + uint8_t red; + uint8_t green; + uint8_t blue; +}; + +/** Control the byte order used by the connected pixels. + * + * The vast majority of NeoPixels use a GRB byte order, so this is the default. + * A few use a RGB byte order. + * + * In principle, the WS281x controllers could be connected with _any_ byte + * ordering, but only GRB and RGB are supported at the moment. + */ +enum ByteOrder { + BYTE_ORDER_GRB, + BYTE_ORDER_RGB, +}; + +typedef void (*PixelGenerator)(Pixel* out, uint32_t index, uintptr_t extra); + +/** 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, as + * long as they support the fast-mode (800kHz) interface. + * + * 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. + * + * @note SPI peripherals will tend to leave the output pin ('MOSI') floating + * after a packet is sent. This will confuse the connected pixels, which expect + * the line to be driven low when idle. One way to fix this is to add a 10k + * resistor between 'MOSI' and ground so that it drops to '0' when not driven. + * Another method is to enable the on-chip pull-down resistor on the output pin. + * However, the mbed API only exposes this function through the DigitalIn and + * DigitalInOut classes. If you want to use the on-chip pull-down, you'll have + * to temporarily connect a DigitalIn peripheral _before_ creating instantiating + * the PixelArray. + * + * @code + * // Sample generator: Cycle through each colour combination, increasing the + * // brightness each time. `extra` is used as an iteration counter. + * void generate(neopixel::Pixel * out, uint32_t index, uintptr_t extra) { + * uint32_t brightness = (index + extra) >> 3; + * out->red = ((index + extra) & 0x1) ? brightness : 0; + * out->green = ((index + extra) & 0x2) ? brightness : 0; + * out->blue = ((index + extra) & 0x4) ? brightness : 0; + * } + * + * int main() { + * // Create a temporary DigitalIn so we can configure the pull-down resistor. + * // (The mbed API doesn't provide any other way to do this.) + * // An alternative is to connect an external pull-down resistor. + * DigitalIn(p5, PullDown); + * + * // The pixel array control class. + * neopixel::PixelArray array(p5); + * + * uint32_t offset = 0; + * while (1) { + * array.update(generate, 100, offset++); + * wait_ms(250); + * } + * } + * @endcode + */ +class PixelArray +{ +public: + /** Initialize a PixelArray. + * + * @param out Output (SPI MOSI) pin. + * @param byte_order The order in which to transmit colour channels. + */ + PixelArray(PinName out, + ByteOrder byte_order = BYTE_ORDER_GRB); + + /** Update the pixel display from a buffer. + * + * This update method is good in the following situations: + * - You want to make incremental changes to a fixed frame pattern. + * - The frame is hard (or impossible) to generate procedurally. + * - The frame requires a lot of time to generate. + * + * @param buffer Pixel data to be written. + * @param length The number of pixels to write. + * + * buffer[0] is written to the pixel nearest the mbed. + * buffer[length-1] is written to the pixel furthest from the mbed. + */ + void update(Pixel buffer[], uint32_t length); + + /** Update a pixel chain using the callback to generate the value for each + * pixel. + * + * This update method is good in the following situations: + * - You have a lot of pixels to drive and don't have enough RAM to buffer + * them all. + * - You want to display a frame pattern that can be generated procedurally + * generated without intensive processing. + * + * @param generator A callback which is called to generate a value for each + * pixel on demand. This function must be fairly fast: if it takes more + * than about 8-9us, the interface will reset and the display will be + * corrupted. The exact time limits will vary between WS281x variants. As a + * rough guide, an LPC1768 at 96MHz can (conservatively) execute about 750 + * instructions in that time. + * + * @param length The number of pixels to write. + * + * @param extra An arbitrary value to pass into the generator function. For + * example, this is a good way to pass an animation time index to the + * generator function. + */ + void update(PixelGenerator generator, uint32_t length, uintptr_t extra); + +private: + BurstSPI spi_; + ByteOrder byte_order_; + + static int const latch_time_us_ = 50; + + void send_pixel(Pixel& pixel); +}; + +} + +#endif \ No newline at end of file