WS2812

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WS2812.cpp Source File

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