Main Error

Dependencies:   BurstSPI

Fork of PixelArray by Jacob Bramley

Committer:
JacobBramley
Date:
Fri Aug 01 22:17:23 2014 +0000
Revision:
2:3c3c41774cdf
Child:
3:6f392fcb1d3b
v1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JacobBramley 2:3c3c41774cdf 1 #include <stdint.h>
JacobBramley 2:3c3c41774cdf 2 #include "mbed.h"
JacobBramley 2:3c3c41774cdf 3 #include "neopixel.h"
JacobBramley 2:3c3c41774cdf 4
JacobBramley 2:3c3c41774cdf 5 namespace neopixel
JacobBramley 2:3c3c41774cdf 6 {
JacobBramley 2:3c3c41774cdf 7
JacobBramley 2:3c3c41774cdf 8 PixelArray::PixelArray(PinName out, ByteOrder byte_order)
JacobBramley 2:3c3c41774cdf 9 : spi_(out, NC, NC), byte_order_(byte_order)
JacobBramley 2:3c3c41774cdf 10 {
JacobBramley 2:3c3c41774cdf 11 // WS281x bit encodings:
JacobBramley 2:3c3c41774cdf 12 // '0': ----________
JacobBramley 2:3c3c41774cdf 13 // '1': --------____
JacobBramley 2:3c3c41774cdf 14 // The period is 1.25us, giving a basic frequency of 800kHz.
JacobBramley 2:3c3c41774cdf 15 // Getting the mark-space ratio right is trickier, though. There are a number
JacobBramley 2:3c3c41774cdf 16 // of different timings, and the correct (documented) values depend on the
JacobBramley 2:3c3c41774cdf 17 // controller chip.
JacobBramley 2:3c3c41774cdf 18 //
JacobBramley 2:3c3c41774cdf 19 // The _real_ timing restrictions are much simpler though, and someone has
JacobBramley 2:3c3c41774cdf 20 // published a lovely analysis here:
JacobBramley 2:3c3c41774cdf 21 // http://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/
JacobBramley 2:3c3c41774cdf 22 //
JacobBramley 2:3c3c41774cdf 23 // In summary:
JacobBramley 2:3c3c41774cdf 24 // - The period should be at least 1.25us.
JacobBramley 2:3c3c41774cdf 25 // - The '0' high time can be anywhere from 0.0625us to 0.5us.
JacobBramley 2:3c3c41774cdf 26 // - The '1' high time should be longer than 0.625us.
JacobBramley 2:3c3c41774cdf 27 //
JacobBramley 2:3c3c41774cdf 28 // These constraints are easy to meet by splitting each bit into three and packing them into SPI packets.
JacobBramley 2:3c3c41774cdf 29 // '0': 100 mark: 0.42us, space: 0.83us
JacobBramley 2:3c3c41774cdf 30 // '1': 110 mark: 0.83us, space: 0.42us
JacobBramley 2:3c3c41774cdf 31
JacobBramley 2:3c3c41774cdf 32 spi_.frequency(2400000); // 800kHz * 3
JacobBramley 2:3c3c41774cdf 33 spi_.format(12); // Send four NeoPixel bits in each packet.
JacobBramley 2:3c3c41774cdf 34 }
JacobBramley 2:3c3c41774cdf 35
JacobBramley 2:3c3c41774cdf 36 static void SendFourBits(BurstSPI& spi, uint32_t bits)
JacobBramley 2:3c3c41774cdf 37 {
JacobBramley 2:3c3c41774cdf 38 // Encode '0' bits as 100 and '1' bits as 110.
JacobBramley 2:3c3c41774cdf 39 // We have this bit pattern: 00000000abcd
JacobBramley 2:3c3c41774cdf 40 // We want this bit pattern: 1a01b01c01d0
JacobBramley 2:3c3c41774cdf 41 uint32_t ac = (bits * 0x088) & // 0abcdabcd000
JacobBramley 2:3c3c41774cdf 42 0x410; // 0a00000c0000
JacobBramley 2:3c3c41774cdf 43
JacobBramley 2:3c3c41774cdf 44 uint32_t bd = (bits * 0x022) & // 000abcdabcd0
JacobBramley 2:3c3c41774cdf 45 0x082; // 0000b00000d0
JacobBramley 2:3c3c41774cdf 46
JacobBramley 2:3c3c41774cdf 47 static uint32_t const base = 04444; // 100100100100
JacobBramley 2:3c3c41774cdf 48
JacobBramley 2:3c3c41774cdf 49 spi.fastWrite(base | ac | bd); // 1a01b01c01d0
JacobBramley 2:3c3c41774cdf 50 }
JacobBramley 2:3c3c41774cdf 51
JacobBramley 2:3c3c41774cdf 52 void PixelArray::send_pixel(Pixel& pixel)
JacobBramley 2:3c3c41774cdf 53 {
JacobBramley 2:3c3c41774cdf 54 // Pixels are sent as follows:
JacobBramley 2:3c3c41774cdf 55 // - The first transmitted pixel is the pixel closest to the transmitter.
JacobBramley 2:3c3c41774cdf 56 // - The most significant bit is always sent first.
JacobBramley 2:3c3c41774cdf 57 //
JacobBramley 2:3c3c41774cdf 58 // g7,g6,g5,g4,g3,g2,g1,g0,r7,r6,r5,r4,r3,r2,r1,r0,b7,b6,b5,b4,b3,b2,b1,b0
JacobBramley 2:3c3c41774cdf 59 // \_____________________________________________________________________/
JacobBramley 2:3c3c41774cdf 60 // | _________________...
JacobBramley 2:3c3c41774cdf 61 // | / __________________...
JacobBramley 2:3c3c41774cdf 62 // | / / ___________________...
JacobBramley 2:3c3c41774cdf 63 // | / / /
JacobBramley 2:3c3c41774cdf 64 // GRB,GRB,GRB,GRB,...
JacobBramley 2:3c3c41774cdf 65
JacobBramley 2:3c3c41774cdf 66 if (byte_order_ == BYTE_ORDER_RGB) {
JacobBramley 2:3c3c41774cdf 67 SendFourBits(spi_, (pixel.red >> 4) & 0xf);
JacobBramley 2:3c3c41774cdf 68 SendFourBits(spi_, (pixel.red >> 0) & 0xf);
JacobBramley 2:3c3c41774cdf 69 SendFourBits(spi_, (pixel.green >> 4) & 0xf);
JacobBramley 2:3c3c41774cdf 70 SendFourBits(spi_, (pixel.green >> 0) & 0xf);
JacobBramley 2:3c3c41774cdf 71 SendFourBits(spi_, (pixel.blue >> 4) & 0xf);
JacobBramley 2:3c3c41774cdf 72 SendFourBits(spi_, (pixel.blue >> 0) & 0xf);
JacobBramley 2:3c3c41774cdf 73 } else {
JacobBramley 2:3c3c41774cdf 74 SendFourBits(spi_, (pixel.green >> 4) & 0xf);
JacobBramley 2:3c3c41774cdf 75 SendFourBits(spi_, (pixel.green >> 0) & 0xf);
JacobBramley 2:3c3c41774cdf 76 SendFourBits(spi_, (pixel.red >> 4) & 0xf);
JacobBramley 2:3c3c41774cdf 77 SendFourBits(spi_, (pixel.red >> 0) & 0xf);
JacobBramley 2:3c3c41774cdf 78 SendFourBits(spi_, (pixel.blue >> 4) & 0xf);
JacobBramley 2:3c3c41774cdf 79 SendFourBits(spi_, (pixel.blue >> 0) & 0xf);
JacobBramley 2:3c3c41774cdf 80 }
JacobBramley 2:3c3c41774cdf 81 }
JacobBramley 2:3c3c41774cdf 82
JacobBramley 2:3c3c41774cdf 83 void PixelArray::update(Pixel buffer[], uint32_t length)
JacobBramley 2:3c3c41774cdf 84 {
JacobBramley 2:3c3c41774cdf 85 for (size_t i = 0; i < length; i++) {
JacobBramley 2:3c3c41774cdf 86 send_pixel(buffer[i]);
JacobBramley 2:3c3c41774cdf 87 }
JacobBramley 2:3c3c41774cdf 88
JacobBramley 2:3c3c41774cdf 89 wait_us(latch_time_us_);
JacobBramley 2:3c3c41774cdf 90 }
JacobBramley 2:3c3c41774cdf 91
JacobBramley 2:3c3c41774cdf 92 void PixelArray::update(PixelGenerator generator, uint32_t length, uintptr_t extra)
JacobBramley 2:3c3c41774cdf 93 {
JacobBramley 2:3c3c41774cdf 94 for (size_t i = 0; i < length; i++) {
JacobBramley 2:3c3c41774cdf 95 Pixel out;
JacobBramley 2:3c3c41774cdf 96 generator(&out, i, extra);
JacobBramley 2:3c3c41774cdf 97 send_pixel(out);
JacobBramley 2:3c3c41774cdf 98 }
JacobBramley 2:3c3c41774cdf 99
JacobBramley 2:3c3c41774cdf 100 wait_us(latch_time_us_);
JacobBramley 2:3c3c41774cdf 101 }
JacobBramley 2:3c3c41774cdf 102
JacobBramley 2:3c3c41774cdf 103 }