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 23 09:41:48 2016 +0000
Revision:
5:6aa3e7de65f9
Parent:
4:8997e12da7c7
Update to fix issues with 16bit brightness 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 0:b3665f91bedc 8 pixelLen = 0;
AndyA 4:8997e12da7c7 9 pixArray16 = NULL;
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 4:8997e12da7c7 16 pixArray16 = NULL;
AndyA 4:8997e12da7c7 17 }
AndyA 4:8997e12da7c7 18
AndyA 4:8997e12da7c7 19 void wsDrive::setData(pixelInfo16 *dataStart, uint16_t dataLen)
AndyA 4:8997e12da7c7 20 {
AndyA 4:8997e12da7c7 21 pixArray16 = dataStart;
AndyA 4:8997e12da7c7 22 pixelLen = dataLen;
AndyA 4:8997e12da7c7 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 uint16_t pixIndex = 0;
AndyA 4:8997e12da7c7 33 if (pixArray)
AndyA 0:b3665f91bedc 34 while (pixIndex < pixelLen) {
AndyA 0:b3665f91bedc 35 sendPixel(pixArray + pixIndex++);
AndyA 0:b3665f91bedc 36 }
AndyA 4:8997e12da7c7 37 else
AndyA 4:8997e12da7c7 38 while (pixIndex < pixelLen) {
AndyA 4:8997e12da7c7 39 sendPixel(pixArray16 + pixIndex++);
AndyA 4:8997e12da7c7 40 }
AndyA 4:8997e12da7c7 41
AndyA 0:b3665f91bedc 42 }
AndyA 0:b3665f91bedc 43
AndyA 0:b3665f91bedc 44 // each bytes sent as two 12 bit messages (3 bits of data per LED bit).
AndyA 0:b3665f91bedc 45 void wsDrive::sendByte(unsigned char value)
AndyA 0:b3665f91bedc 46 {
AndyA 0:b3665f91bedc 47
AndyA 0:b3665f91bedc 48 uint16_t dataToSend = 0;
AndyA 0:b3665f91bedc 49
AndyA 0:b3665f91bedc 50 uint8_t mask = 0x80;
AndyA 0:b3665f91bedc 51 while (mask) {
AndyA 0:b3665f91bedc 52 dataToSend += (value & mask)?0x06:0x4; // 100 for a 0 or 110 for a 1
AndyA 0:b3665f91bedc 53 if (mask & 0x11) { // trans
AndyA 0:b3665f91bedc 54 fastWrite(dataToSend);
AndyA 0:b3665f91bedc 55 dataToSend = 0;
AndyA 0:b3665f91bedc 56 }
AndyA 0:b3665f91bedc 57 dataToSend = dataToSend << 3;
AndyA 0:b3665f91bedc 58 mask = mask >> 1;
AndyA 0:b3665f91bedc 59 }
AndyA 0:b3665f91bedc 60 }
AndyA 0:b3665f91bedc 61
AndyA 0:b3665f91bedc 62 void wsDrive::sendPixel(pixelInfo *pixToSend)
AndyA 0:b3665f91bedc 63 {
AndyA 0:b3665f91bedc 64 sendByte(pixToSend->G);
AndyA 0:b3665f91bedc 65 sendByte(pixToSend->R);
AndyA 0:b3665f91bedc 66 sendByte(pixToSend->B);
AndyA 0:b3665f91bedc 67 }
AndyA 0:b3665f91bedc 68
AndyA 4:8997e12da7c7 69 void wsDrive::sendPixel(pixelInfo16 *pixToSend)
AndyA 4:8997e12da7c7 70 {
AndyA 5:6aa3e7de65f9 71 sendByte(pixToSend->G<255?(unsigned char)pixToSend->G:255);
AndyA 5:6aa3e7de65f9 72 sendByte(pixToSend->R<255?(unsigned char)pixToSend->R:255);
AndyA 5:6aa3e7de65f9 73 sendByte(pixToSend->B<255?(unsigned char)pixToSend->B:255);
AndyA 4:8997e12da7c7 74 }
AndyA 4:8997e12da7c7 75
AndyA 4:8997e12da7c7 76