Library for the WS2812 LED Driver. Uses bit banging and nops for precise timing. Number of nops executed are configurable at run time.
Dependents: WS2812_Example WS2812_Example_fade Lamp_03 Lamp_04 ... more
WS2812.cpp
00001 #include "WS2812.h" 00002 00003 WS2812::WS2812(PinName pin, int size, int zeroHigh, int zeroLow, int oneHigh, int oneLow) : __gpo(pin) 00004 { 00005 __size = size; 00006 __transmitBuf = new bool[size * FRAME_SIZE]; 00007 __use_II = OFF; 00008 __II = 0xFF; // set global intensity to full 00009 __outPin = pin; 00010 00011 // Default values designed for K64f. Assumes GPIO toggle takes ~0.4us 00012 setDelays(zeroHigh, zeroLow, oneHigh, oneLow); 00013 } 00014 00015 00016 WS2812::~WS2812 () 00017 { 00018 delete[] __transmitBuf; 00019 } 00020 00021 void WS2812::setDelays(int zeroHigh, int zeroLow, int oneHigh, int oneLow) { 00022 __zeroHigh = zeroHigh; 00023 __zeroLow = zeroLow; 00024 __oneHigh = oneHigh; 00025 __oneLow = oneLow; 00026 } 00027 00028 void WS2812::__loadBuf(int buf[],int r_offset, int g_offset, int b_offset) { 00029 for (int i = 0; i < __size; i++) { 00030 int color = 0; 00031 00032 color |= ((buf[(i+g_offset)%__size] & 0x0000FF00)); 00033 color |= ((buf[(i+r_offset)%__size] & 0x00FF0000)); 00034 color |= (buf[(i+b_offset)%__size] & 0x000000FF); 00035 color |= (buf[i] & 0xFF000000); 00036 00037 // Outut format : GGRRBB 00038 // Inout format : IIRRGGBB 00039 unsigned char agrb[4] = {0x0, 0x0, 0x0, 0x0}; 00040 00041 unsigned char sf; // scaling factor for II 00042 00043 // extract colour fields from incoming 00044 // 0 = green, 1 = red, 2 = blue, 3 = brightness 00045 agrb[0] = (color & 0x0000FF00) >> 8; 00046 agrb[1] = (color & 0x00FF0000) >> 16; 00047 agrb[2] = color & 0x000000FF; 00048 agrb[3] = (color & 0xFF000000) >> 24; 00049 00050 // set the intensity scaling factor (global, per pixel, none) 00051 if (__use_II == GLOBAL) { 00052 sf = __II; 00053 } else if (__use_II == PER_PIXEL) { 00054 sf = agrb[3]; 00055 } else { 00056 sf = 0xFF; 00057 } 00058 00059 // Apply the scaling factor to each othe colour components 00060 for (int clr = 0; clr < 3; clr++) { 00061 agrb[clr] = ((agrb[clr] * sf) >> 8); 00062 00063 for (int j = 0; j < 8; j++) { 00064 if (((agrb[clr] << j) & 0x80) == 0x80) { 00065 // Bit is set (checks MSB fist) 00066 __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 1; 00067 } else { 00068 // Bit is clear 00069 __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 0; 00070 } 00071 } 00072 } 00073 } 00074 } 00075 00076 void WS2812::write(int buf[]) { 00077 write_offsets(buf, 0, 0, 0); 00078 } 00079 00080 void WS2812::write_offsets (int buf[],int r_offset, int g_offset, int b_offset) { 00081 int i, j; 00082 00083 // Load the transmit buffer 00084 __loadBuf(buf, r_offset, g_offset, b_offset); 00085 00086 // Entering timing critical section, so disabling interrupts 00087 __disable_irq(); 00088 00089 // Begin bit-banging 00090 for (i = 0; i < FRAME_SIZE * __size; i++) { 00091 j = 0; 00092 if (__transmitBuf[i]){ 00093 __gpo = 1; 00094 for (; j < __oneHigh; j++) { 00095 __nop(); 00096 } 00097 __gpo = 0; 00098 for (; j < __oneLow; j++) { 00099 __nop(); 00100 } 00101 } else { 00102 __gpo = 1; 00103 for (; j < __zeroHigh; j++) { 00104 __nop(); 00105 } 00106 __gpo = 0; 00107 for (; j < __zeroLow; j++) { 00108 __nop(); 00109 } 00110 } 00111 } 00112 00113 // Exiting timing critical section, so enabling interrutps 00114 __enable_irq(); 00115 } 00116 00117 00118 void WS2812::useII(BrightnessControl bc) 00119 { 00120 if (bc > OFF) { 00121 __use_II = bc; 00122 } else { 00123 __use_II = OFF; 00124 } 00125 } 00126 00127 void WS2812::setII(unsigned char II) 00128 { 00129 __II = II; 00130 } 00131 00132 00133 00134 00135 00136
Generated on Tue Jul 12 2022 22:53:55 by 1.7.2