Library for the WS2812 LED Driver. Uses bit banging and nops for precise timing. Number of nops executed are configurable at run time.
WS2812.cpp
- Committer:
- bridadan
- Date:
- 2015-02-12
- Revision:
- 0:0b79cafcb387
- Child:
- 1:aadbf08c62a2
File content as of revision 0:0b79cafcb387:
#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; }