Nucleo-transfer

Dependencies:   BurstSPI

Dependents:   Nucleo-transfer Nucleo-transfer Nucleo-transfer

Fork of PixelArray by Jacob Bramley

Committer:
Ishy
Date:
Thu Nov 23 15:00:13 2017 +0000
Revision:
6:b995e738b29d
Parent:
3:6f392fcb1d3b
test

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