Library for the WS2812 LED Driver. Uses bit banging and nops for precise timing. Number of nops executed are configurable at run time.

Dependents:   MIP

Committer:
bridadan
Date:
Thu Feb 12 19:17:10 2015 +0000
Revision:
0:0b79cafcb387
Child:
1:aadbf08c62a2
Driver for the WS2812 LED driver. Uses bit banging and relies on nops for timing. Number of nops can be varied to potentially accommodate different platforms. Currently tested on the K64F.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bridadan 0:0b79cafcb387 1 #include "WS2812.h"
bridadan 0:0b79cafcb387 2
bridadan 0:0b79cafcb387 3 WS2812::WS2812(PinName d, int size) : __gpo(d)
bridadan 0:0b79cafcb387 4 {
bridadan 0:0b79cafcb387 5 __size = size;
bridadan 0:0b79cafcb387 6 __transmitBuf = new bool[size * FRAME_SIZE];
bridadan 0:0b79cafcb387 7 __use_II = 0; // 0=off,1=use global,2=per pixel
bridadan 0:0b79cafcb387 8 __II = 0xFF; // set global intensity to full
bridadan 0:0b79cafcb387 9 __outPin = d;
bridadan 0:0b79cafcb387 10
bridadan 0:0b79cafcb387 11 // Default values designed for K64f. Assumes GPIO toggle takes ~0.4us
bridadan 0:0b79cafcb387 12 setDelays(0, 5, 5, 0);
bridadan 0:0b79cafcb387 13 }
bridadan 0:0b79cafcb387 14
bridadan 0:0b79cafcb387 15
bridadan 0:0b79cafcb387 16 WS2812::~WS2812()
bridadan 0:0b79cafcb387 17 {
bridadan 0:0b79cafcb387 18 delete[] __transmitBuf;
bridadan 0:0b79cafcb387 19 }
bridadan 0:0b79cafcb387 20
bridadan 0:0b79cafcb387 21 void WS2812::setDelays(int zeroHigh, int zeroLow, int oneHigh, int oneLow) {
bridadan 0:0b79cafcb387 22 __zeroHigh = zeroHigh;
bridadan 0:0b79cafcb387 23 __zeroLow = zeroLow;
bridadan 0:0b79cafcb387 24 __oneHigh = oneHigh;
bridadan 0:0b79cafcb387 25 __oneLow = oneLow;
bridadan 0:0b79cafcb387 26 }
bridadan 0:0b79cafcb387 27
bridadan 0:0b79cafcb387 28 void WS2812::__loadBuf(int buf[],int r_offset, int g_offset, int b_offset) {
bridadan 0:0b79cafcb387 29 for (int i = 0; i < __size; i++) {
bridadan 0:0b79cafcb387 30 int color = 0;
bridadan 0:0b79cafcb387 31
bridadan 0:0b79cafcb387 32 color |= ((buf[(i+g_offset)%__size] & 0x0000FF00));
bridadan 0:0b79cafcb387 33 color |= ((buf[(i+r_offset)%__size] & 0x00FF0000));
bridadan 0:0b79cafcb387 34 color |= (buf[(i+b_offset)%__size] & 0x000000FF);
bridadan 0:0b79cafcb387 35 color |= (buf[i] & 0xFF000000);
bridadan 0:0b79cafcb387 36
bridadan 0:0b79cafcb387 37 // Outut format : GGRRBB
bridadan 0:0b79cafcb387 38 // Inout format : IIRRGGBB
bridadan 0:0b79cafcb387 39 unsigned char agrb[4] = {0x0, 0x0, 0x0, 0x0};
bridadan 0:0b79cafcb387 40
bridadan 0:0b79cafcb387 41 unsigned char sf; // scaling factor for II
bridadan 0:0b79cafcb387 42
bridadan 0:0b79cafcb387 43 // extract colour fields from incoming
bridadan 0:0b79cafcb387 44 // 0 = green, 1 = red, 2 = blue, 3 = brightness
bridadan 0:0b79cafcb387 45 agrb[0] = (color & 0x0000FF00) >> 8;
bridadan 0:0b79cafcb387 46 agrb[1] = (color & 0x00FF0000) >> 16;
bridadan 0:0b79cafcb387 47 agrb[2] = color & 0x000000FF;
bridadan 0:0b79cafcb387 48 agrb[3] = (color & 0xFF000000) >> 24;
bridadan 0:0b79cafcb387 49
bridadan 0:0b79cafcb387 50 // set and intensity scaling factor (global, per pixel, none)
bridadan 0:0b79cafcb387 51 if (__use_II == 1) {
bridadan 0:0b79cafcb387 52 sf = __II;
bridadan 0:0b79cafcb387 53 } else if (__use_II == 2) {
bridadan 0:0b79cafcb387 54 sf = agrb[3];
bridadan 0:0b79cafcb387 55 } else {
bridadan 0:0b79cafcb387 56 sf = 0xFF;
bridadan 0:0b79cafcb387 57 }
bridadan 0:0b79cafcb387 58
bridadan 0:0b79cafcb387 59 // Apply the scaling factor to each othe colour components
bridadan 0:0b79cafcb387 60 for (int clr = 0; clr < 3; clr++) {
bridadan 0:0b79cafcb387 61 agrb[clr] = ((agrb[clr] * sf) >> 8);
bridadan 0:0b79cafcb387 62
bridadan 0:0b79cafcb387 63 for (int j = 0; j < 8; j++) {
bridadan 0:0b79cafcb387 64 if (((agrb[clr] << j) & 0x80) == 0x80) {
bridadan 0:0b79cafcb387 65 // Bit is set (checks MSB fist)
bridadan 0:0b79cafcb387 66 __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 1;
bridadan 0:0b79cafcb387 67 } else {
bridadan 0:0b79cafcb387 68 // Bit is clear
bridadan 0:0b79cafcb387 69 __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 0;
bridadan 0:0b79cafcb387 70 }
bridadan 0:0b79cafcb387 71 }
bridadan 0:0b79cafcb387 72 }
bridadan 0:0b79cafcb387 73 }
bridadan 0:0b79cafcb387 74 }
bridadan 0:0b79cafcb387 75
bridadan 0:0b79cafcb387 76 void WS2812::write(int buf[]) {
bridadan 0:0b79cafcb387 77 write_offsets(buf, 0, 0, 0);
bridadan 0:0b79cafcb387 78 }
bridadan 0:0b79cafcb387 79
bridadan 0:0b79cafcb387 80 void WS2812::write_offsets (int buf[],int r_offset, int g_offset, int b_offset) {
bridadan 0:0b79cafcb387 81 int i, j;
bridadan 0:0b79cafcb387 82
bridadan 0:0b79cafcb387 83 __loadBuf(buf, r_offset, g_offset, b_offset);
bridadan 0:0b79cafcb387 84
bridadan 0:0b79cafcb387 85 for (i = 0; i < FRAME_SIZE * __size; i++) {
bridadan 0:0b79cafcb387 86 j = 0;
bridadan 0:0b79cafcb387 87 if (__transmitBuf[i]){
bridadan 0:0b79cafcb387 88 __gpo = 1;
bridadan 0:0b79cafcb387 89 for (; j < __oneHigh; j++) {
bridadan 0:0b79cafcb387 90 __nop();
bridadan 0:0b79cafcb387 91 }
bridadan 0:0b79cafcb387 92 __gpo = 0;
bridadan 0:0b79cafcb387 93 for (; j < __oneLow; j++) {
bridadan 0:0b79cafcb387 94 __nop();
bridadan 0:0b79cafcb387 95 }
bridadan 0:0b79cafcb387 96 } else {
bridadan 0:0b79cafcb387 97 __gpo = 1;
bridadan 0:0b79cafcb387 98 for (; j < __zeroHigh; j++) {
bridadan 0:0b79cafcb387 99 __nop();
bridadan 0:0b79cafcb387 100 }
bridadan 0:0b79cafcb387 101 __gpo = 0;
bridadan 0:0b79cafcb387 102 for (; j < __zeroLow; j++) {
bridadan 0:0b79cafcb387 103 __nop();
bridadan 0:0b79cafcb387 104 }
bridadan 0:0b79cafcb387 105 }
bridadan 0:0b79cafcb387 106 }
bridadan 0:0b79cafcb387 107 }
bridadan 0:0b79cafcb387 108
bridadan 0:0b79cafcb387 109
bridadan 0:0b79cafcb387 110 void WS2812::useII(int d)
bridadan 0:0b79cafcb387 111 {
bridadan 0:0b79cafcb387 112 if (d > 0) {
bridadan 0:0b79cafcb387 113 __use_II = d;
bridadan 0:0b79cafcb387 114 } else {
bridadan 0:0b79cafcb387 115 __use_II = 0;
bridadan 0:0b79cafcb387 116 }
bridadan 0:0b79cafcb387 117 }
bridadan 0:0b79cafcb387 118
bridadan 0:0b79cafcb387 119 void WS2812::setII(unsigned char II)
bridadan 0:0b79cafcb387 120 {
bridadan 0:0b79cafcb387 121 __II = II;
bridadan 0:0b79cafcb387 122 }
bridadan 0:0b79cafcb387 123
bridadan 0:0b79cafcb387 124
bridadan 0:0b79cafcb387 125
bridadan 0:0b79cafcb387 126
bridadan 0:0b79cafcb387 127
bridadan 0:0b79cafcb387 128