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

Dependents:   DARVIN-kletka

Revision:
0:0b79cafcb387
Child:
1:aadbf08c62a2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WS2812.cpp	Thu Feb 12 19:17:10 2015 +0000
@@ -0,0 +1,128 @@
+#include "WS2812.h"
+
+WS2812::WS2812(PinName d, int size) : __gpo(d)
+{
+    __size = size;
+    __transmitBuf = new bool[size * FRAME_SIZE];
+    __use_II = 0; // 0=off,1=use global,2=per pixel
+    __II = 0xFF; // set global intensity to full
+    __outPin = d;
+    
+    // Default values designed for K64f. Assumes GPIO toggle takes ~0.4us
+    setDelays(0, 5, 5, 0);
+}
+
+
+WS2812::~WS2812()
+{
+    delete[] __transmitBuf;
+}
+
+void WS2812::setDelays(int zeroHigh, int zeroLow, int oneHigh, int oneLow) {
+    __zeroHigh = zeroHigh;
+    __zeroLow = zeroLow;
+    __oneHigh = oneHigh;
+    __oneLow = oneLow;
+}
+
+void WS2812::__loadBuf(int buf[],int r_offset, int g_offset, int b_offset) {
+    for (int i = 0; i < __size; i++) {
+        int color = 0;
+               
+        color |= ((buf[(i+g_offset)%__size] & 0x0000FF00));
+        color |= ((buf[(i+r_offset)%__size] & 0x00FF0000));
+        color |=  (buf[(i+b_offset)%__size] & 0x000000FF);
+        color |= (buf[i] & 0xFF000000);
+        
+        // Outut format : GGRRBB
+        // Inout format : IIRRGGBB
+        unsigned char agrb[4] = {0x0, 0x0, 0x0, 0x0};
+    
+        unsigned char sf; // scaling factor for  II
+    
+        // extract colour fields from incoming
+        // 0 = green, 1 = red, 2 = blue, 3 = brightness        
+        agrb[0] = (color & 0x0000FF00) >> 8;
+        agrb[1] = (color & 0x00FF0000) >> 16;
+        agrb[2] = color  & 0x000000FF;
+        agrb[3] = (color & 0xFF000000) >> 24;
+    
+        // set and intensity scaling factor (global, per pixel, none)
+        if (__use_II == 1) {
+            sf = __II;
+        } else if (__use_II == 2) {
+            sf = agrb[3];
+        } else {
+            sf = 0xFF;
+        }
+        
+        // Apply the scaling factor to each othe colour components
+        for (int clr = 0; clr < 3; clr++) {
+            agrb[clr] = ((agrb[clr] * sf) >> 8);
+            
+            for (int j = 0; j < 8; j++) {
+                if (((agrb[clr] << j) & 0x80) == 0x80) {
+                    // Bit is set (checks MSB fist)
+                    __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 1;
+                } else {
+                    // Bit is clear
+                    __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 0;
+                }
+            }
+        }
+    }
+}
+
+void WS2812::write(int buf[]) {
+    write_offsets(buf, 0, 0, 0);
+}
+
+void WS2812::write_offsets (int buf[],int r_offset, int g_offset, int b_offset) {
+    int i, j;
+    
+    __loadBuf(buf, r_offset, g_offset, b_offset);
+
+    for (i = 0; i < FRAME_SIZE * __size; i++) {
+        j = 0;
+        if (__transmitBuf[i]){
+            __gpo = 1;
+            for (; j < __oneHigh; j++) {
+                __nop();
+            }
+            __gpo = 0;
+            for (; j < __oneLow; j++) {
+                __nop();
+            }
+        } else {
+            __gpo = 1;
+            for (; j < __zeroHigh; j++) {
+                __nop();
+            }
+            __gpo = 0;
+            for (; j < __zeroLow; j++) {
+                __nop();
+            }
+        }
+    }
+}
+
+
+void WS2812::useII(int d)
+{
+    if (d > 0) {
+        __use_II = d;
+    } else {
+        __use_II = 0;
+    }
+}
+
+void WS2812::setII(unsigned char II)
+{
+    __II = II;
+}
+
+
+
+
+
+