WS2812 LED driver

Dependents:   WS2812-Example WS2812-Example WS2812-Example

WS2812.cpp

Committer:
fastestoffer
Date:
2015-11-18
Revision:
0:f1e39d76fbca

File content as of revision 0:f1e39d76fbca:

#include "WS2812.h"

#define WS2812_ONE (3<<2)
#define WS2812_ZERO (1<<3)

typedef struct {
  uint8_t g[4];
  uint8_t r[4];
  uint8_t b[4];
} led_pixel_wire_data;

WS2812::WS2812(SPI &spi, event_callback_t led_update_strip_finished):
    _spi(spi), 
    _led_data_size(WS2812_LED_NUM_LEDS*12 + WS2812_LED_NUM_RESET_BYTES), 
    _led_update_strip_finished(led_update_strip_finished) 
{
    //Setup SPI for WS2812
    _spi.format(8,0);
    _spi.frequency(3000000);
    _spi.set_dma_usage(DMA_USAGE_ALWAYS);

    //Initialize led data buffer to zero
    memset(_led_data, 0, _led_data_size);
}

void WS2812::update_strip() {
    //Initiate transfer of led data buffer through SPI
    this->_spi.transfer(this->_led_data, this->_led_data_size, (uint8_t *)NULL, 0, this->_led_update_strip_finished);
}

//Write same color to all leds
void WS2812::set_all(Color *c) {
        for(int i=0; i<WS2812_LED_NUM_LEDS; i++)
        {
            this->set_led(i, c);
        }
}

//Write color to led_number (a single led on the strip)
//led_number range is [0,WS2812_LED_NUM_LEDS - 1]
void WS2812::set_led(int led_number, Color *c)
{
    uint8_t *ledptr;
    uint32_t offset;
    led_pixel_wire_data *led_pixel_data_ptr;
    
    offset = led_number * 12;
    ledptr = &(this->_led_data[offset]);
    led_pixel_data_ptr = (led_pixel_wire_data*)ledptr;
    
    /*************** GREEN value first (see datasheet) **********************/
    _write_color_to_memory(led_pixel_data_ptr->g, c->g);
    
    /*************** RED value second (see datasheet) ***********************/
    _write_color_to_memory(led_pixel_data_ptr->r, c->r);
    
    /*************** BLUE value last (see datasheet) ************************/
    _write_color_to_memory(led_pixel_data_ptr->b, c->b);
    
}

//Write one channel of the color (R, G or B) to its in-memory representation
void WS2812::_write_color_to_memory(uint8_t tuple[], uint8_t color_value)
{
    uint8_t byte = 0, nibble = 0, bitval = 0;
    
    /* For each bit in the color value, convert it to a corresponding one or a zero in-memory value */
    for(byte = 0; byte < 4; byte++) {
        tuple[3-byte] = 0;
        for(nibble = 0; nibble < 2; nibble++) {
            bitval = (color_value >> ((byte*2)+nibble)) & 0x1;
            bitval = bitval ? WS2812_ONE : WS2812_ZERO;
            
            tuple[3-byte] |= bitval << (nibble*4);
        }
    }
}