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