Stephen Legge / WS2812

Fork of WS2812 by Brian Daniels

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WS2812.cpp Source File

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         if (__transmitBuf[i]){
00092             __gpo = 1;
00093             for (j = 0; j < __oneHigh; j++) {
00094                 __nop();
00095             }
00096             __gpo = 0;
00097             for (j = 0; j < __oneLow; j++) {
00098                 __nop();
00099             }
00100         } else {
00101             __gpo = 1;
00102             for (j = 0; j < __zeroHigh; j++) {
00103                 __nop();
00104             }
00105             __gpo = 0;
00106             for (j = 0; j < __zeroLow; j++) {
00107                 __nop();
00108             }
00109         }
00110     }
00111     
00112     // Exiting timing critical section, so enabling interrutps
00113     __enable_irq();
00114 }
00115 
00116 
00117 void WS2812::useII(BrightnessControl bc)
00118 {
00119     if (bc > OFF) {
00120         __use_II = bc;
00121     } else {
00122         __use_II = OFF;
00123     }
00124 }
00125 
00126 void WS2812::setII(unsigned char II)
00127 {
00128     __II = II;
00129 }
00130 
00131 
00132 
00133 
00134 
00135