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