WS2812 LED driver
Dependents: WS2812-Example WS2812-Example WS2812-Example
Revision 0:f1e39d76fbca, committed 2015-11-18
- 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