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

Revision:
2:3c3c41774cdf
Child:
3:6f392fcb1d3b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/neopixel.cpp	Fri Aug 01 22:17:23 2014 +0000
@@ -0,0 +1,103 @@
+#include <stdint.h>
+#include "mbed.h"
+#include "neopixel.h"
+
+namespace neopixel
+{
+
+PixelArray::PixelArray(PinName out, ByteOrder byte_order)
+    : spi_(out, NC, NC), byte_order_(byte_order)
+{
+    // WS281x bit encodings:
+    //  '0': ----________
+    //  '1': --------____
+    // The period is 1.25us, giving a basic frequency of 800kHz.
+    // Getting the mark-space ratio right is trickier, though. There are a number
+    // of different timings, and the correct (documented) values depend on the
+    // controller chip.
+    //
+    // The _real_ timing restrictions are much simpler though, and someone has
+    // published a lovely analysis here:
+    //   http://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/
+    //
+    // In summary:
+    // - The period should be at least 1.25us.
+    // - The '0' high time can be anywhere from 0.0625us to 0.5us.
+    // - The '1' high time should be longer than 0.625us.
+    //
+    // These constraints are easy to meet by splitting each bit into three and packing them into SPI packets.
+    //  '0': 100             mark: 0.42us, space: 0.83us
+    //  '1': 110             mark: 0.83us, space: 0.42us
+
+    spi_.frequency(2400000);  // 800kHz * 3
+    spi_.format(12);          // Send four NeoPixel bits in each packet.
+}
+
+static void SendFourBits(BurstSPI& spi, uint32_t bits)
+{
+    // Encode '0' bits as 100 and '1' bits as 110.
+    // We have this bit pattern: 00000000abcd
+    // We want this bit pattern: 1a01b01c01d0
+    uint32_t ac = (bits * 0x088) &        // 0abcdabcd000
+                  0x410; // 0a00000c0000
+
+    uint32_t bd = (bits * 0x022) &        // 000abcdabcd0
+                  0x082; // 0000b00000d0
+
+    static uint32_t const base = 04444;   // 100100100100
+
+    spi.fastWrite(base | ac | bd);        // 1a01b01c01d0
+}
+
+void PixelArray::send_pixel(Pixel& pixel)
+{
+    // Pixels are sent as follows:
+    // - The first transmitted pixel is the pixel closest to the transmitter.
+    // - The most significant bit is always sent first.
+    //
+    // g7,g6,g5,g4,g3,g2,g1,g0,r7,r6,r5,r4,r3,r2,r1,r0,b7,b6,b5,b4,b3,b2,b1,b0
+    // \_____________________________________________________________________/
+    //                           |      _________________...
+    //                           |     /   __________________...
+    //                           |    /   /   ___________________...
+    //                           |   /   /   /
+    //                          GRB,GRB,GRB,GRB,...
+
+    if (byte_order_ == BYTE_ORDER_RGB) {
+        SendFourBits(spi_, (pixel.red >> 4) & 0xf);
+        SendFourBits(spi_, (pixel.red >> 0) & 0xf);
+        SendFourBits(spi_, (pixel.green >> 4) & 0xf);
+        SendFourBits(spi_, (pixel.green >> 0) & 0xf);
+        SendFourBits(spi_, (pixel.blue >> 4) & 0xf);
+        SendFourBits(spi_, (pixel.blue >> 0) & 0xf);
+    } else {
+        SendFourBits(spi_, (pixel.green >> 4) & 0xf);
+        SendFourBits(spi_, (pixel.green >> 0) & 0xf);
+        SendFourBits(spi_, (pixel.red >> 4) & 0xf);
+        SendFourBits(spi_, (pixel.red >> 0) & 0xf);
+        SendFourBits(spi_, (pixel.blue >> 4) & 0xf);
+        SendFourBits(spi_, (pixel.blue >> 0) & 0xf);
+    }
+}
+
+void PixelArray::update(Pixel buffer[], uint32_t length)
+{
+    for (size_t i = 0; i < length; i++) {
+        send_pixel(buffer[i]);
+    }
+
+    wait_us(latch_time_us_);
+}
+
+void PixelArray::update(PixelGenerator generator, uint32_t length, uintptr_t extra)
+{
+    for (size_t i = 0; i < length; i++) {
+        Pixel out;
+        generator(&out, i, extra);
+        send_pixel(out);
+    }
+
+    wait_us(latch_time_us_);
+}
+
+}
\ No newline at end of file