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:
4:c3b314df3dfe
test

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
mcapewel 3:6f392fcb1d3b 8 PixelArray::PixelArray(PinName out, ByteOrder byte_order, Protocol protocol)
mcapewel 3:6f392fcb1d3b 9 : spi_(out, NC, NC), byte_order_(byte_order), protocol_(protocol)
JacobBramley 2:3c3c41774cdf 10 {
mcapewel 3:6f392fcb1d3b 11 if (protocol_ == PROTOCOL_800KHZ) {
mcapewel 3:6f392fcb1d3b 12 // 800kHz bit encodings:
mcapewel 3:6f392fcb1d3b 13 // '0': ----________
mcapewel 3:6f392fcb1d3b 14 // '1': --------____
mcapewel 3:6f392fcb1d3b 15 // The period is 1.25us, giving a basic frequency of 800kHz.
mcapewel 3:6f392fcb1d3b 16 // Getting the mark-space ratio right is trickier, though. There are a number
mcapewel 3:6f392fcb1d3b 17 // of different timings, and the correct (documented) values depend on the
mcapewel 3:6f392fcb1d3b 18 // controller chip.
mcapewel 3:6f392fcb1d3b 19 //
mcapewel 3:6f392fcb1d3b 20 // The _real_ timing restrictions are much simpler though, and someone has
mcapewel 3:6f392fcb1d3b 21 // published a lovely analysis here:
mcapewel 3:6f392fcb1d3b 22 // http://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/
mcapewel 3:6f392fcb1d3b 23 //
mcapewel 3:6f392fcb1d3b 24 // In summary:
mcapewel 3:6f392fcb1d3b 25 // - The period should be at least 1.25us.
mcapewel 3:6f392fcb1d3b 26 // - The '0' high time can be anywhere from 0.0625us to 0.5us.
mcapewel 3:6f392fcb1d3b 27 // - The '1' high time should be longer than 0.625us.
mcapewel 3:6f392fcb1d3b 28 //
mcapewel 3:6f392fcb1d3b 29 // These constraints are easy to meet by splitting each bit into three and packing them into SPI packets.
mcapewel 3:6f392fcb1d3b 30 // '0': 100 mark: 0.42us, space: 0.83us
mcapewel 3:6f392fcb1d3b 31 // '1': 110 mark: 0.83us, space: 0.42us
mcapewel 3:6f392fcb1d3b 32 spi_.frequency(2400000); // 800kHz * 3
mcapewel 3:6f392fcb1d3b 33 spi_.format(12); // Send four NeoPixel bits in each packet.
mcapewel 3:6f392fcb1d3b 34 } else {
mcapewel 3:6f392fcb1d3b 35 // 400kHz bit encodings:
mcapewel 3:6f392fcb1d3b 36 // '0': --________
mcapewel 3:6f392fcb1d3b 37 // '1': -----_____
mcapewel 3:6f392fcb1d3b 38 //
mcapewel 3:6f392fcb1d3b 39 // Timing requirements are derived from this document:
mcapewel 3:6f392fcb1d3b 40 // http://www.adafruit.com/datasheets/WS2811.pdf
mcapewel 3:6f392fcb1d3b 41 //
mcapewel 3:6f392fcb1d3b 42 // The period is 2.5us, and we use a 10-bit packet for this encoding:
mcapewel 3:6f392fcb1d3b 43 // '0': 1100000000 mark: 0.5us, space: 2us
mcapewel 3:6f392fcb1d3b 44 // '1': 1111100000 mark: 1.25us, space: 1.25us
mcapewel 3:6f392fcb1d3b 45 spi_.frequency(4000000); // 400kHz * 10
mcapewel 3:6f392fcb1d3b 46 spi_.format(10); // Send one NeoPixel bit in each packet.
mcapewel 3:6f392fcb1d3b 47 }
JacobBramley 2:3c3c41774cdf 48 }
JacobBramley 2:3c3c41774cdf 49
JacobBramley 2:3c3c41774cdf 50 static void SendFourBits(BurstSPI& spi, uint32_t bits)
JacobBramley 2:3c3c41774cdf 51 {
JacobBramley 2:3c3c41774cdf 52 // Encode '0' bits as 100 and '1' bits as 110.
JacobBramley 2:3c3c41774cdf 53 // We have this bit pattern: 00000000abcd
JacobBramley 2:3c3c41774cdf 54 // We want this bit pattern: 1a01b01c01d0
JacobBramley 2:3c3c41774cdf 55 uint32_t ac = (bits * 0x088) & // 0abcdabcd000
JacobBramley 2:3c3c41774cdf 56 0x410; // 0a00000c0000
JacobBramley 2:3c3c41774cdf 57
JacobBramley 2:3c3c41774cdf 58 uint32_t bd = (bits * 0x022) & // 000abcdabcd0
JacobBramley 2:3c3c41774cdf 59 0x082; // 0000b00000d0
JacobBramley 2:3c3c41774cdf 60
JacobBramley 2:3c3c41774cdf 61 static uint32_t const base = 04444; // 100100100100
JacobBramley 2:3c3c41774cdf 62
JacobBramley 2:3c3c41774cdf 63 spi.fastWrite(base | ac | bd); // 1a01b01c01d0
JacobBramley 2:3c3c41774cdf 64 }
JacobBramley 2:3c3c41774cdf 65
mcapewel 3:6f392fcb1d3b 66 static void SendEightBits(BurstSPI& spi, uint8_t bits)
mcapewel 3:6f392fcb1d3b 67 {
mcapewel 3:6f392fcb1d3b 68 int zero = 0x300; // Encode zero as 0b1100000000
mcapewel 3:6f392fcb1d3b 69 int one = 0x3e0; // Encode one as 0b1111100000
mcapewel 4:c3b314df3dfe 70 for (int i = 128; i >= 1; i >>= 1) {
mcapewel 3:6f392fcb1d3b 71 spi.fastWrite((bits & i) ? one : zero);
mcapewel 3:6f392fcb1d3b 72 }
mcapewel 3:6f392fcb1d3b 73 }
mcapewel 3:6f392fcb1d3b 74
JacobBramley 2:3c3c41774cdf 75 void PixelArray::send_pixel(Pixel& pixel)
JacobBramley 2:3c3c41774cdf 76 {
JacobBramley 2:3c3c41774cdf 77 // Pixels are sent as follows:
JacobBramley 2:3c3c41774cdf 78 // - The first transmitted pixel is the pixel closest to the transmitter.
JacobBramley 2:3c3c41774cdf 79 // - The most significant bit is always sent first.
JacobBramley 2:3c3c41774cdf 80 //
JacobBramley 2:3c3c41774cdf 81 // 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 82 // \_____________________________________________________________________/
JacobBramley 2:3c3c41774cdf 83 // | _________________...
JacobBramley 2:3c3c41774cdf 84 // | / __________________...
JacobBramley 2:3c3c41774cdf 85 // | / / ___________________...
JacobBramley 2:3c3c41774cdf 86 // | / / /
JacobBramley 2:3c3c41774cdf 87 // GRB,GRB,GRB,GRB,...
mcapewel 3:6f392fcb1d3b 88 //
mcapewel 3:6f392fcb1d3b 89 // For BYTE_ORDER_RGB, the order of the first two bytes are reversed.
JacobBramley 2:3c3c41774cdf 90
mcapewel 3:6f392fcb1d3b 91 uint8_t byte0 = (byte_order_ == BYTE_ORDER_RGB) ? pixel.red : pixel.green;
mcapewel 3:6f392fcb1d3b 92 uint8_t byte1 = (byte_order_ == BYTE_ORDER_RGB) ? pixel.green : pixel.red;
mcapewel 3:6f392fcb1d3b 93
mcapewel 3:6f392fcb1d3b 94 if (protocol_ == PROTOCOL_800KHZ) {
mcapewel 3:6f392fcb1d3b 95 SendFourBits(spi_, (byte0 >> 4) & 0xf);
mcapewel 3:6f392fcb1d3b 96 SendFourBits(spi_, (byte0 >> 0) & 0xf);
mcapewel 3:6f392fcb1d3b 97 SendFourBits(spi_, (byte1 >> 4) & 0xf);
mcapewel 3:6f392fcb1d3b 98 SendFourBits(spi_, (byte1 >> 0) & 0xf);
JacobBramley 2:3c3c41774cdf 99 SendFourBits(spi_, (pixel.blue >> 4) & 0xf);
JacobBramley 2:3c3c41774cdf 100 SendFourBits(spi_, (pixel.blue >> 0) & 0xf);
JacobBramley 2:3c3c41774cdf 101 } else {
mcapewel 3:6f392fcb1d3b 102 SendEightBits(spi_, byte0);
mcapewel 3:6f392fcb1d3b 103 SendEightBits(spi_, byte1);
mcapewel 3:6f392fcb1d3b 104 SendEightBits(spi_, pixel.blue);
JacobBramley 2:3c3c41774cdf 105 }
JacobBramley 2:3c3c41774cdf 106 }
JacobBramley 2:3c3c41774cdf 107
JacobBramley 2:3c3c41774cdf 108 void PixelArray::update(Pixel buffer[], uint32_t length)
JacobBramley 2:3c3c41774cdf 109 {
JacobBramley 2:3c3c41774cdf 110 for (size_t i = 0; i < length; i++) {
JacobBramley 2:3c3c41774cdf 111 send_pixel(buffer[i]);
JacobBramley 2:3c3c41774cdf 112 }
JacobBramley 2:3c3c41774cdf 113
JacobBramley 2:3c3c41774cdf 114 wait_us(latch_time_us_);
JacobBramley 2:3c3c41774cdf 115 }
JacobBramley 2:3c3c41774cdf 116
JacobBramley 2:3c3c41774cdf 117 void PixelArray::update(PixelGenerator generator, uint32_t length, uintptr_t extra)
JacobBramley 2:3c3c41774cdf 118 {
JacobBramley 2:3c3c41774cdf 119 for (size_t i = 0; i < length; i++) {
JacobBramley 2:3c3c41774cdf 120 Pixel out;
JacobBramley 2:3c3c41774cdf 121 generator(&out, i, extra);
JacobBramley 2:3c3c41774cdf 122 send_pixel(out);
JacobBramley 2:3c3c41774cdf 123 }
JacobBramley 2:3c3c41774cdf 124
JacobBramley 2:3c3c41774cdf 125 wait_us(latch_time_us_);
JacobBramley 2:3c3c41774cdf 126 }
JacobBramley 2:3c3c41774cdf 127
JacobBramley 2:3c3c41774cdf 128 }