Yet another WS2812 driver, uses the BusrtSPI library. Less features than the PixelArray library but I felt like making my own version.

Dependencies:   BurstSPI

Dependents:   WS2812Text cylon

An alternative WS2811/2812 (NeoPixel) driver using the BusrtSPI library.

Credit for the inspiration goes to Jacob Bramley for his pixelArray library that can be found here: http://developer.mbed.org/users/JacobBramley/code/PixelArray/

This version was written mainly to help me understand what was going on rather than to overcome any shortcomings in the other library and as such it lacks some features (800kHz only, no callback on each pixel etc...)

Connect the SPI output to the LED data input, other SPI pins are unused.

Note: The voltage thresholds between the LEDs and mbed devices are on paper incompatible. The datasheet for the WS2812 indicated that running at 5V it requires 4V on Din to count it as a high (the threshold is 0.8*the supply voltage). Most mbeds are lucky to output much over 3.1V. In reality things normally work OK but it depends on the mBed and batch to batch variations in the LEDs, I've seen some combinations that start to fail at an LED supply voltage of 4.4V or more. If something odd is going on try dropping the LED power supply voltage, they run fine down to 4V.

Committer:
AndyA
Date:
Wed Nov 12 16:43:33 2014 +0000
Revision:
3:3c48065d20ff
Parent:
0:b3665f91bedc
Added 16bit colour support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AndyA 0:b3665f91bedc 1 #include "wsDrive.h"
AndyA 0:b3665f91bedc 2
AndyA 0:b3665f91bedc 3 wsDrive::wsDrive(PinName mosi, PinName miso, PinName clk) : BurstSPI(mosi,miso,clk)
AndyA 0:b3665f91bedc 4 {
AndyA 0:b3665f91bedc 5 frequency(2400000);
AndyA 0:b3665f91bedc 6 format(12);
AndyA 0:b3665f91bedc 7 pixArray = NULL;
AndyA 3:3c48065d20ff 8 pixArray16 = NULL;
AndyA 0:b3665f91bedc 9 pixelLen = 0;
AndyA 0:b3665f91bedc 10 }
AndyA 0:b3665f91bedc 11
AndyA 0:b3665f91bedc 12 void wsDrive::setData(pixelInfo *dataStart, uint16_t dataLen)
AndyA 0:b3665f91bedc 13 {
AndyA 0:b3665f91bedc 14 pixArray = dataStart;
AndyA 0:b3665f91bedc 15 pixelLen = dataLen;
AndyA 3:3c48065d20ff 16 pixArray16 = NULL;
AndyA 3:3c48065d20ff 17 }
AndyA 3:3c48065d20ff 18
AndyA 3:3c48065d20ff 19 void wsDrive::setData(pixelInfo16 *dataStart, uint16_t dataLen)
AndyA 3:3c48065d20ff 20 {
AndyA 3:3c48065d20ff 21 pixArray16 = dataStart;
AndyA 3:3c48065d20ff 22 pixelLen = dataLen;
AndyA 3:3c48065d20ff 23 pixArray = NULL;
AndyA 0:b3665f91bedc 24 }
AndyA 0:b3665f91bedc 25
AndyA 0:b3665f91bedc 26 void wsDrive::sendData()
AndyA 0:b3665f91bedc 27 {
AndyA 0:b3665f91bedc 28 frequency(2400000);
AndyA 0:b3665f91bedc 29 format(12);
AndyA 0:b3665f91bedc 30 setFormat();
AndyA 0:b3665f91bedc 31
AndyA 0:b3665f91bedc 32
AndyA 0:b3665f91bedc 33 uint16_t pixIndex = 0;
AndyA 3:3c48065d20ff 34 if (pixArray) {
AndyA 3:3c48065d20ff 35 while (pixIndex < pixelLen) {
AndyA 3:3c48065d20ff 36 sendPixel(pixArray + pixIndex++);
AndyA 3:3c48065d20ff 37 }
AndyA 3:3c48065d20ff 38 } else if (pixArray16) {
AndyA 3:3c48065d20ff 39 while (pixIndex < pixelLen) {
AndyA 3:3c48065d20ff 40 sendPixel(pixArray16 + pixIndex++);
AndyA 3:3c48065d20ff 41 }
AndyA 3:3c48065d20ff 42 }
AndyA 0:b3665f91bedc 43 }
AndyA 0:b3665f91bedc 44
AndyA 0:b3665f91bedc 45 // each bytes sent as two 12 bit messages (3 bits of data per LED bit).
AndyA 0:b3665f91bedc 46 void wsDrive::sendByte(unsigned char value)
AndyA 0:b3665f91bedc 47 {
AndyA 3:3c48065d20ff 48
AndyA 0:b3665f91bedc 49 uint16_t dataToSend = 0;
AndyA 3:3c48065d20ff 50
AndyA 0:b3665f91bedc 51 uint8_t mask = 0x80;
AndyA 0:b3665f91bedc 52 while (mask) {
AndyA 0:b3665f91bedc 53 dataToSend += (value & mask)?0x06:0x4; // 100 for a 0 or 110 for a 1
AndyA 0:b3665f91bedc 54 if (mask & 0x11) { // trans
AndyA 3:3c48065d20ff 55 fastWrite(dataToSend);
AndyA 3:3c48065d20ff 56 dataToSend = 0;
AndyA 0:b3665f91bedc 57 }
AndyA 0:b3665f91bedc 58 dataToSend = dataToSend << 3;
AndyA 0:b3665f91bedc 59 mask = mask >> 1;
AndyA 0:b3665f91bedc 60 }
AndyA 0:b3665f91bedc 61 }
AndyA 0:b3665f91bedc 62
AndyA 0:b3665f91bedc 63 void wsDrive::sendPixel(pixelInfo *pixToSend)
AndyA 0:b3665f91bedc 64 {
AndyA 0:b3665f91bedc 65 sendByte(pixToSend->G);
AndyA 0:b3665f91bedc 66 sendByte(pixToSend->R);
AndyA 0:b3665f91bedc 67 sendByte(pixToSend->B);
AndyA 0:b3665f91bedc 68 }
AndyA 0:b3665f91bedc 69
AndyA 3:3c48065d20ff 70 void wsDrive::sendPixel(pixelInfo16 *pixToSend)
AndyA 3:3c48065d20ff 71 {
AndyA 3:3c48065d20ff 72 if (pixToSend->G > 0xff)
AndyA 3:3c48065d20ff 73 sendByte(0xff);
AndyA 3:3c48065d20ff 74 else if (pixToSend->G < 0)
AndyA 3:3c48065d20ff 75 sendByte(0xff);
AndyA 3:3c48065d20ff 76 else
AndyA 3:3c48065d20ff 77 sendByte((unsigned char)pixToSend->G);
AndyA 3:3c48065d20ff 78
AndyA 3:3c48065d20ff 79 if (pixToSend->R > 0xff)
AndyA 3:3c48065d20ff 80 sendByte(0xff);
AndyA 3:3c48065d20ff 81 else if (pixToSend->R < 0)
AndyA 3:3c48065d20ff 82 sendByte(0xff);
AndyA 3:3c48065d20ff 83 else
AndyA 3:3c48065d20ff 84 sendByte((unsigned char)pixToSend->R);
AndyA 3:3c48065d20ff 85
AndyA 3:3c48065d20ff 86 if (pixToSend->B > 0xff)
AndyA 3:3c48065d20ff 87 sendByte(0xff);
AndyA 3:3c48065d20ff 88 else if (pixToSend->B < 0)
AndyA 3:3c48065d20ff 89 sendByte(0xff);
AndyA 3:3c48065d20ff 90 else
AndyA 3:3c48065d20ff 91 sendByte((unsigned char)pixToSend->B);
AndyA 3:3c48065d20ff 92
AndyA 3:3c48065d20ff 93 }