WS2812 LED driver

Dependents:   WS2812-Example WS2812-Example WS2812-Example

Files at this revision

API Documentation at this revision

Comitter:
fastestoffer
Date:
Wed Nov 18 14:00:44 2015 +0000
Commit message:
Initial commit of WS2812 LED driver

Changed in this revision

WS2812.cpp Show annotated file Show diff for this revision Revisions of this file
WS2812.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r f1e39d76fbca WS2812.cpp
--- /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);
+        }
+    }
+}
diff -r 000000000000 -r f1e39d76fbca WS2812.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WS2812.h	Wed Nov 18 14:00:44 2015 +0000
@@ -0,0 +1,37 @@
+#include "mbed.h"
+
+#ifndef WS2812_H
+#define WS2812_H
+
+#define WS2812_LED_NUM_LEDS 30
+#define WS2812_LED_NUM_RESET_BYTES 3
+
+typedef struct
+{
+  uint8_t r;
+  uint8_t g;
+  uint8_t b;
+} Color;
+ 
+class WS2812 {
+public:
+    WS2812(SPI &spi, event_callback_t led_update_strip_finished);
+    
+    void update_strip();
+    void set_led(int led_number, Color *c);
+    void set_all(Color *c);
+
+private:
+    SPI _spi;
+    int _led_data_size;
+    event_callback_t _led_update_strip_finished;
+    
+    void _write_color_to_memory(uint8_t* tuple, uint8_t color_value);
+    
+    // Each sent bit to the LED strip is represented by 4 bits in memory.
+    // Each LED requires 24 bits (8 bits per color).
+    // In addition, we need to allocate room to send enough zeros so that the strip latches
+    uint8_t _led_data[WS2812_LED_NUM_LEDS*12 + WS2812_LED_NUM_RESET_BYTES];
+};
+
+#endif
\ No newline at end of file