WS2812 LED driver

Dependents:   WS2812-Example WS2812-Example WS2812-Example

Revision:
0:f1e39d76fbca
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WS2812.cpp	Wed Nov 18 14:00:44 2015 +0000
@@ -0,0 +1,77 @@
+#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);
+        }
+    }
+}