Modified library of Pixel Array showing main.cpp code implementing buffer/array of pixels method of updating pixel chain.

Dependencies:   BurstSPI

Dependents:   NeoPixel-DemoBuffer Final_project Final_project

Fork of PixelArray by Jacob Bramley

Committer:
ben_ceron
Date:
Tue Mar 10 06:21:35 2015 +0000
Revision:
8:df8daeaa3d87
Parent:
6:1d8c73d4c7e6
Update PixelArray using buffer method.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JacobBramley 2:3c3c41774cdf 1 #ifndef NEOPIXEL_H
JacobBramley 2:3c3c41774cdf 2 #define NEOPIXEL_H
JacobBramley 2:3c3c41774cdf 3
JacobBramley 2:3c3c41774cdf 4 #include <stdint.h>
JacobBramley 2:3c3c41774cdf 5 #include "mbed.h"
JacobBramley 2:3c3c41774cdf 6 #include "BurstSPI.h"
JacobBramley 2:3c3c41774cdf 7
JacobBramley 2:3c3c41774cdf 8 namespace neopixel
JacobBramley 2:3c3c41774cdf 9 {
JacobBramley 2:3c3c41774cdf 10
JacobBramley 2:3c3c41774cdf 11 /** Represent the value of a single pixel.
JacobBramley 2:3c3c41774cdf 12 *
JacobBramley 2:3c3c41774cdf 13 * Each channel uses the full 8 bits: 0x00 is fully off and 0xff is fully on.
JacobBramley 2:3c3c41774cdf 14 */
JacobBramley 2:3c3c41774cdf 15 struct Pixel {
JacobBramley 2:3c3c41774cdf 16 uint8_t red;
JacobBramley 2:3c3c41774cdf 17 uint8_t green;
JacobBramley 2:3c3c41774cdf 18 uint8_t blue;
JacobBramley 2:3c3c41774cdf 19 };
JacobBramley 2:3c3c41774cdf 20
ben_ceron 6:1d8c73d4c7e6 21
JacobBramley 2:3c3c41774cdf 22 /** Control the byte order used by the connected pixels.
JacobBramley 2:3c3c41774cdf 23 *
JacobBramley 2:3c3c41774cdf 24 * The vast majority of NeoPixels use a GRB byte order, so this is the default.
JacobBramley 2:3c3c41774cdf 25 * A few use a RGB byte order.
JacobBramley 2:3c3c41774cdf 26 *
JacobBramley 2:3c3c41774cdf 27 * In principle, the WS281x controllers could be connected with _any_ byte
JacobBramley 2:3c3c41774cdf 28 * ordering, but only GRB and RGB are supported at the moment.
JacobBramley 2:3c3c41774cdf 29 */
JacobBramley 2:3c3c41774cdf 30 enum ByteOrder {
JacobBramley 2:3c3c41774cdf 31 BYTE_ORDER_GRB,
JacobBramley 2:3c3c41774cdf 32 BYTE_ORDER_RGB,
JacobBramley 2:3c3c41774cdf 33 };
JacobBramley 2:3c3c41774cdf 34
mcapewel 3:6f392fcb1d3b 35 /** Set the protocol mode.
mcapewel 3:6f392fcb1d3b 36 *
mcapewel 3:6f392fcb1d3b 37 * The protocol is named after the clock, as though WS8211 supports only the
mcapewel 3:6f392fcb1d3b 38 * 400kHz clock, WS8212 supports both.
mcapewel 3:6f392fcb1d3b 39 */
mcapewel 3:6f392fcb1d3b 40 enum Protocol {
mcapewel 3:6f392fcb1d3b 41 PROTOCOL_800KHZ,
mcapewel 3:6f392fcb1d3b 42 PROTOCOL_400KHZ,
mcapewel 3:6f392fcb1d3b 43 };
mcapewel 3:6f392fcb1d3b 44
JacobBramley 2:3c3c41774cdf 45 typedef void (*PixelGenerator)(Pixel* out, uint32_t index, uintptr_t extra);
JacobBramley 2:3c3c41774cdf 46
JacobBramley 2:3c3c41774cdf 47 /** Control an array or chain of NeoPixel-compatible RGB LEDs.
JacobBramley 2:3c3c41774cdf 48 *
JacobBramley 2:3c3c41774cdf 49 * "NeoPixel" is Adafruit's name for WS2812- and WS2811-based addressable RGB
JacobBramley 2:3c3c41774cdf 50 * LEDs. This library should work with any WS2811- or WS2812-based devices, as
JacobBramley 2:3c3c41774cdf 51 * long as they support the fast-mode (800kHz) interface.
JacobBramley 2:3c3c41774cdf 52 *
JacobBramley 2:3c3c41774cdf 53 * Most example code uses bit-banging to generate the timed signal precisely.
JacobBramley 2:3c3c41774cdf 54 * This library uses an SPI peripheral instead. The main advantage of this is
JacobBramley 2:3c3c41774cdf 55 * that the chip can service interrupts and the like without disrupting the
JacobBramley 2:3c3c41774cdf 56 * signal (as long as the interrupts don't take _too_ long). The main
JacobBramley 2:3c3c41774cdf 57 * disadvantage is that it requires the use of an SPI peripheral.
JacobBramley 2:3c3c41774cdf 58 *
JacobBramley 2:3c3c41774cdf 59 * @note SPI peripherals will tend to leave the output pin ('MOSI') floating
JacobBramley 2:3c3c41774cdf 60 * after a packet is sent. This will confuse the connected pixels, which expect
JacobBramley 2:3c3c41774cdf 61 * the line to be driven low when idle. One way to fix this is to add a 10k
JacobBramley 2:3c3c41774cdf 62 * resistor between 'MOSI' and ground so that it drops to '0' when not driven.
JacobBramley 2:3c3c41774cdf 63 * Another method is to enable the on-chip pull-down resistor on the output pin.
JacobBramley 2:3c3c41774cdf 64 * However, the mbed API only exposes this function through the DigitalIn and
JacobBramley 2:3c3c41774cdf 65 * DigitalInOut classes. If you want to use the on-chip pull-down, you'll have
JacobBramley 2:3c3c41774cdf 66 * to temporarily connect a DigitalIn peripheral _before_ creating instantiating
JacobBramley 2:3c3c41774cdf 67 * the PixelArray.
JacobBramley 2:3c3c41774cdf 68 *
JacobBramley 2:3c3c41774cdf 69 * @code
JacobBramley 2:3c3c41774cdf 70 * // Sample generator: Cycle through each colour combination, increasing the
JacobBramley 2:3c3c41774cdf 71 * // brightness each time. `extra` is used as an iteration counter.
JacobBramley 2:3c3c41774cdf 72 * void generate(neopixel::Pixel * out, uint32_t index, uintptr_t extra) {
JacobBramley 2:3c3c41774cdf 73 * uint32_t brightness = (index + extra) >> 3;
JacobBramley 2:3c3c41774cdf 74 * out->red = ((index + extra) & 0x1) ? brightness : 0;
JacobBramley 2:3c3c41774cdf 75 * out->green = ((index + extra) & 0x2) ? brightness : 0;
JacobBramley 2:3c3c41774cdf 76 * out->blue = ((index + extra) & 0x4) ? brightness : 0;
JacobBramley 2:3c3c41774cdf 77 * }
JacobBramley 2:3c3c41774cdf 78 *
JacobBramley 2:3c3c41774cdf 79 * int main() {
JacobBramley 2:3c3c41774cdf 80 * // Create a temporary DigitalIn so we can configure the pull-down resistor.
JacobBramley 2:3c3c41774cdf 81 * // (The mbed API doesn't provide any other way to do this.)
JacobBramley 2:3c3c41774cdf 82 * // An alternative is to connect an external pull-down resistor.
JacobBramley 2:3c3c41774cdf 83 * DigitalIn(p5, PullDown);
JacobBramley 2:3c3c41774cdf 84 *
JacobBramley 2:3c3c41774cdf 85 * // The pixel array control class.
JacobBramley 2:3c3c41774cdf 86 * neopixel::PixelArray array(p5);
JacobBramley 2:3c3c41774cdf 87 *
JacobBramley 2:3c3c41774cdf 88 * uint32_t offset = 0;
JacobBramley 2:3c3c41774cdf 89 * while (1) {
JacobBramley 2:3c3c41774cdf 90 * array.update(generate, 100, offset++);
JacobBramley 2:3c3c41774cdf 91 * wait_ms(250);
JacobBramley 2:3c3c41774cdf 92 * }
JacobBramley 2:3c3c41774cdf 93 * }
JacobBramley 2:3c3c41774cdf 94 * @endcode
JacobBramley 2:3c3c41774cdf 95 */
JacobBramley 2:3c3c41774cdf 96 class PixelArray
JacobBramley 2:3c3c41774cdf 97 {
JacobBramley 2:3c3c41774cdf 98 public:
JacobBramley 2:3c3c41774cdf 99 /** Initialize a PixelArray.
JacobBramley 2:3c3c41774cdf 100 *
JacobBramley 2:3c3c41774cdf 101 * @param out Output (SPI MOSI) pin.
JacobBramley 2:3c3c41774cdf 102 * @param byte_order The order in which to transmit colour channels.
JacobBramley 2:3c3c41774cdf 103 */
JacobBramley 2:3c3c41774cdf 104 PixelArray(PinName out,
ben_ceron 6:1d8c73d4c7e6 105 ByteOrder byte_order = BYTE_ORDER_RGB,
mcapewel 3:6f392fcb1d3b 106 Protocol protocol = PROTOCOL_800KHZ);
JacobBramley 2:3c3c41774cdf 107
JacobBramley 2:3c3c41774cdf 108 /** Update the pixel display from a buffer.
JacobBramley 2:3c3c41774cdf 109 *
JacobBramley 2:3c3c41774cdf 110 * This update method is good in the following situations:
JacobBramley 2:3c3c41774cdf 111 * - You want to make incremental changes to a fixed frame pattern.
JacobBramley 2:3c3c41774cdf 112 * - The frame is hard (or impossible) to generate procedurally.
JacobBramley 2:3c3c41774cdf 113 * - The frame requires a lot of time to generate.
JacobBramley 2:3c3c41774cdf 114 *
JacobBramley 2:3c3c41774cdf 115 * @param buffer Pixel data to be written.
JacobBramley 2:3c3c41774cdf 116 * @param length The number of pixels to write.
JacobBramley 2:3c3c41774cdf 117 *
JacobBramley 2:3c3c41774cdf 118 * buffer[0] is written to the pixel nearest the mbed.
JacobBramley 2:3c3c41774cdf 119 * buffer[length-1] is written to the pixel furthest from the mbed.
JacobBramley 2:3c3c41774cdf 120 */
JacobBramley 2:3c3c41774cdf 121 void update(Pixel buffer[], uint32_t length);
JacobBramley 2:3c3c41774cdf 122
JacobBramley 2:3c3c41774cdf 123 /** Update a pixel chain using the callback to generate the value for each
JacobBramley 2:3c3c41774cdf 124 * pixel.
JacobBramley 2:3c3c41774cdf 125 *
JacobBramley 2:3c3c41774cdf 126 * This update method is good in the following situations:
JacobBramley 2:3c3c41774cdf 127 * - You have a lot of pixels to drive and don't have enough RAM to buffer
JacobBramley 2:3c3c41774cdf 128 * them all.
JacobBramley 2:3c3c41774cdf 129 * - You want to display a frame pattern that can be generated procedurally
JacobBramley 2:3c3c41774cdf 130 * generated without intensive processing.
JacobBramley 2:3c3c41774cdf 131 *
JacobBramley 2:3c3c41774cdf 132 * @param generator A callback which is called to generate a value for each
JacobBramley 2:3c3c41774cdf 133 * pixel on demand. This function must be fairly fast: if it takes more
JacobBramley 2:3c3c41774cdf 134 * than about 8-9us, the interface will reset and the display will be
JacobBramley 2:3c3c41774cdf 135 * corrupted. The exact time limits will vary between WS281x variants. As a
JacobBramley 2:3c3c41774cdf 136 * rough guide, an LPC1768 at 96MHz can (conservatively) execute about 750
JacobBramley 2:3c3c41774cdf 137 * instructions in that time.
JacobBramley 2:3c3c41774cdf 138 *
JacobBramley 2:3c3c41774cdf 139 * @param length The number of pixels to write.
JacobBramley 2:3c3c41774cdf 140 *
JacobBramley 2:3c3c41774cdf 141 * @param extra An arbitrary value to pass into the generator function. For
JacobBramley 2:3c3c41774cdf 142 * example, this is a good way to pass an animation time index to the
JacobBramley 2:3c3c41774cdf 143 * generator function.
JacobBramley 2:3c3c41774cdf 144 */
JacobBramley 2:3c3c41774cdf 145 void update(PixelGenerator generator, uint32_t length, uintptr_t extra);
JacobBramley 2:3c3c41774cdf 146
JacobBramley 2:3c3c41774cdf 147 private:
JacobBramley 2:3c3c41774cdf 148 BurstSPI spi_;
JacobBramley 2:3c3c41774cdf 149 ByteOrder byte_order_;
mcapewel 3:6f392fcb1d3b 150 Protocol protocol_;
JacobBramley 2:3c3c41774cdf 151
JacobBramley 2:3c3c41774cdf 152 static int const latch_time_us_ = 50;
JacobBramley 2:3c3c41774cdf 153
JacobBramley 2:3c3c41774cdf 154 void send_pixel(Pixel& pixel);
JacobBramley 2:3c3c41774cdf 155 };
JacobBramley 2:3c3c41774cdf 156
JacobBramley 2:3c3c41774cdf 157 }
JacobBramley 2:3c3c41774cdf 158
JacobBramley 2:3c3c41774cdf 159 #endif