Driver for WS2812

Dependents:   ChrisRGB-Ring

WS2812.cpp

Committer:
chris
Date:
2014-08-18
Revision:
5:a07522fe36d4
Parent:
4:b230e85fc5e7

File content as of revision 5:a07522fe36d4:

#include "WS2812.h"

WS2812::WS2812(PinName d, int size) : __spi(d, NC, NC)
{
    __size = size;
    __spi.format(SPIBPF,0);
    __spi.frequency(SPICLK);
    __use_II = 0; // 0=off,1=use global,2=per pixel
    __II = 0xFF; // set global intensity to full
}


WS2812::~WS2812()
{

}


void WS2812::write(int buf[])
{
    // for each of the data points in the buffer
    for (int i = 0; i < __size ; i++) {
        __write(buf[i]);
    }
}


void WS2812::write_offsets(int buf[], int r_offset, int g_offset, int b_offset)
{
    // for each of the data points in the buffer
    for (int i = 0; i < __size ; i++) {

        unsigned int argb = 0x0;
        // index and extract colour fields from IIRRGGBB buf[]
        // 0 = blue, 1 = green, 2 = red, 3 = brightness
        argb |=  (buf[(i+b_offset)%__size] & 0x000000FF);
        argb |= ((buf[(i+g_offset)%__size] & 0x0000FF00));
        argb |= ((buf[(i+r_offset)%__size] & 0x00FF0000));
        argb |= (buf[i] & 0xFF000000);
        __write(argb);
    }
}




void WS2812::setAll(int colour)
{
    // for each of the data points in the buffer
    for (int i = 0; i < __size ; i++) {
        __write(colour);
    }
}


void WS2812::useII(int d)
{
    if (d > 0) {
        __use_II = d;
    } else {
        __use_II = 0;
    }
}


void WS2812::setII(unsigned char II)
{
    __II = II;
}



void WS2812::__write(int color)
{

    // Outut format : GGRRBB
    // Inout format : IIRRGGBB
    unsigned char agrb[4] = {0x0, 0x0, 0x0, 0x0};

    unsigned char sf; // scaling factor for  II

    // extract colour fields from incoming
    // 0 = blue, 1 = red, 2 = green, 3 = brightness
    agrb[0] = color & 0x000000FF;
    agrb[1] = (color & 0x00FF0000) >> 16;
    agrb[2] = (color & 0x0000FF00) >> 8;
    agrb[3] = (color & 0xFF000000) >> 24;

    // set and intensity scaling factor (global, per pixel, none)
    if (__use_II == 1) {
        sf = __II;
    } else if (__use_II == 2) {
        sf = agrb[3];
    } else {
        sf = 0xFF;
    }

    // Apply the scaling factor to each othe colour components
    for (int clr = 2; clr >= 0; clr--) {
        agrb[clr] = ((agrb[clr] * sf) >> 8);
    }

    // For each colour component G,R,B
    // shift out the data 7..0, writing a SPI frame per bit
    // green=2,red=1,blue=0,
    for (int clr = 2; clr >= 0; clr--) {
        for (int bit = 7 ; bit >= 0 ; bit--) {
            if (agrb[clr] & (0x1 << bit)) {
                __spi.write(WS1);
            } else {
                __spi.write(WS0);
            }
        }
    }
}