Control an array or chain of NeoPixel-compatible RGB LEDs. "NeoPixel" is Adafruit's name for WS2812- and WS2811-based addressable RGB LEDs. This library should work with any WS2811- or WS2812-based devices. Both the 400kHz and 800kHz protocols are supported. Most example code uses bit-banging to generate the timed signal precisely. This library uses an SPI peripheral instead. The main advantage of this is that the chip can service interrupts and the like without disrupting the signal (as long as the interrupts don't take _too_ long). The main disadvantage is that it requires the use of an SPI peripheral.
Dependents: mbed_ws2812b easyNeo WS2811_Solidarite blip_rainbow ... more
neopixel.cpp
00001 #include <stdint.h> 00002 #include "mbed.h" 00003 #include "neopixel.h" 00004 00005 namespace neopixel 00006 { 00007 00008 PixelArray::PixelArray(PinName out, ByteOrder byte_order, Protocol protocol) 00009 : spi_(out, NC, NC), byte_order_(byte_order), protocol_(protocol) 00010 { 00011 if (protocol_ == PROTOCOL_800KHZ) { 00012 // 800kHz bit encodings: 00013 // '0': ----________ 00014 // '1': --------____ 00015 // The period is 1.25us, giving a basic frequency of 800kHz. 00016 // Getting the mark-space ratio right is trickier, though. There are a number 00017 // of different timings, and the correct (documented) values depend on the 00018 // controller chip. 00019 // 00020 // The _real_ timing restrictions are much simpler though, and someone has 00021 // published a lovely analysis here: 00022 // http://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/ 00023 // 00024 // In summary: 00025 // - The period should be at least 1.25us. 00026 // - The '0' high time can be anywhere from 0.0625us to 0.5us. 00027 // - The '1' high time should be longer than 0.625us. 00028 // 00029 // These constraints are easy to meet by splitting each bit into three and packing them into SPI packets. 00030 // '0': 100 mark: 0.42us, space: 0.83us 00031 // '1': 110 mark: 0.83us, space: 0.42us 00032 spi_.frequency(2400000); // 800kHz * 3 00033 spi_.format(12); // Send four NeoPixel bits in each packet. 00034 } else { 00035 // 400kHz bit encodings: 00036 // '0': --________ 00037 // '1': -----_____ 00038 // 00039 // Timing requirements are derived from this document: 00040 // http://www.adafruit.com/datasheets/WS2811.pdf 00041 // 00042 // The period is 2.5us, and we use a 10-bit packet for this encoding: 00043 // '0': 1100000000 mark: 0.5us, space: 2us 00044 // '1': 1111100000 mark: 1.25us, space: 1.25us 00045 spi_.frequency(4000000); // 400kHz * 10 00046 spi_.format(10); // Send one NeoPixel bit in each packet. 00047 } 00048 } 00049 00050 static void SendFourBits(BurstSPI& spi, uint32_t bits) 00051 { 00052 // Encode '0' bits as 100 and '1' bits as 110. 00053 // We have this bit pattern: 00000000abcd 00054 // We want this bit pattern: 1a01b01c01d0 00055 uint32_t ac = (bits * 0x088) & // 0abcdabcd000 00056 0x410; // 0a00000c0000 00057 00058 uint32_t bd = (bits * 0x022) & // 000abcdabcd0 00059 0x082; // 0000b00000d0 00060 00061 static uint32_t const base = 04444; // 100100100100 00062 00063 spi.fastWrite(base | ac | bd); // 1a01b01c01d0 00064 } 00065 00066 static void SendEightBits(BurstSPI& spi, uint8_t bits) 00067 { 00068 int zero = 0x300; // Encode zero as 0b1100000000 00069 int one = 0x3e0; // Encode one as 0b1111100000 00070 for (int i = 128; i >= 1; i >>= 1) { 00071 spi.fastWrite((bits & i) ? one : zero); 00072 } 00073 } 00074 00075 void PixelArray::send_pixel(Pixel& pixel) 00076 { 00077 // Pixels are sent as follows: 00078 // - The first transmitted pixel is the pixel closest to the transmitter. 00079 // - The most significant bit is always sent first. 00080 // 00081 // g7,g6,g5,g4,g3,g2,g1,g0,r7,r6,r5,r4,r3,r2,r1,r0,b7,b6,b5,b4,b3,b2,b1,b0 00082 // \_____________________________________________________________________/ 00083 // | _________________... 00084 // | / __________________... 00085 // | / / ___________________... 00086 // | / / / 00087 // GRB,GRB,GRB,GRB,... 00088 // 00089 // For BYTE_ORDER_RGB, the order of the first two bytes are reversed. 00090 00091 uint8_t byte0 = (byte_order_ == BYTE_ORDER_RGB) ? pixel.red : pixel.green; 00092 uint8_t byte1 = (byte_order_ == BYTE_ORDER_RGB) ? pixel.green : pixel.red; 00093 00094 if (protocol_ == PROTOCOL_800KHZ) { 00095 SendFourBits(spi_, (byte0 >> 4) & 0xf); 00096 SendFourBits(spi_, (byte0 >> 0) & 0xf); 00097 SendFourBits(spi_, (byte1 >> 4) & 0xf); 00098 SendFourBits(spi_, (byte1 >> 0) & 0xf); 00099 SendFourBits(spi_, (pixel.blue >> 4) & 0xf); 00100 SendFourBits(spi_, (pixel.blue >> 0) & 0xf); 00101 } else { 00102 SendEightBits(spi_, byte0); 00103 SendEightBits(spi_, byte1); 00104 SendEightBits(spi_, pixel.blue); 00105 } 00106 } 00107 00108 void PixelArray::update(Pixel buffer[], uint32_t length) 00109 { 00110 for (size_t i = 0; i < length; i++) { 00111 send_pixel(buffer[i]); 00112 } 00113 00114 wait_us(latch_time_us_); 00115 } 00116 00117 void PixelArray::update(PixelGenerator generator, uint32_t length, uintptr_t extra) 00118 { 00119 for (size_t i = 0; i < length; i++) { 00120 Pixel out; 00121 generator(&out, i, extra); 00122 send_pixel(out); 00123 } 00124 00125 wait_us(latch_time_us_); 00126 } 00127 00128 }
Generated on Tue Jul 12 2022 16:16:27 by 1.7.2