WS2812 LED driver
Dependents: WS2812-Example WS2812-Example WS2812-Example
WS2812.cpp@0:f1e39d76fbca, 2015-11-18 (annotated)
- Committer:
- fastestoffer
- Date:
- Wed Nov 18 14:00:44 2015 +0000
- Revision:
- 0:f1e39d76fbca
Initial commit of WS2812 LED driver
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
fastestoffer | 0:f1e39d76fbca | 1 | #include "WS2812.h" |
fastestoffer | 0:f1e39d76fbca | 2 | |
fastestoffer | 0:f1e39d76fbca | 3 | #define WS2812_ONE (3<<2) |
fastestoffer | 0:f1e39d76fbca | 4 | #define WS2812_ZERO (1<<3) |
fastestoffer | 0:f1e39d76fbca | 5 | |
fastestoffer | 0:f1e39d76fbca | 6 | typedef struct { |
fastestoffer | 0:f1e39d76fbca | 7 | uint8_t g[4]; |
fastestoffer | 0:f1e39d76fbca | 8 | uint8_t r[4]; |
fastestoffer | 0:f1e39d76fbca | 9 | uint8_t b[4]; |
fastestoffer | 0:f1e39d76fbca | 10 | } led_pixel_wire_data; |
fastestoffer | 0:f1e39d76fbca | 11 | |
fastestoffer | 0:f1e39d76fbca | 12 | WS2812::WS2812(SPI &spi, event_callback_t led_update_strip_finished): |
fastestoffer | 0:f1e39d76fbca | 13 | _spi(spi), |
fastestoffer | 0:f1e39d76fbca | 14 | _led_data_size(WS2812_LED_NUM_LEDS*12 + WS2812_LED_NUM_RESET_BYTES), |
fastestoffer | 0:f1e39d76fbca | 15 | _led_update_strip_finished(led_update_strip_finished) |
fastestoffer | 0:f1e39d76fbca | 16 | { |
fastestoffer | 0:f1e39d76fbca | 17 | //Setup SPI for WS2812 |
fastestoffer | 0:f1e39d76fbca | 18 | _spi.format(8,0); |
fastestoffer | 0:f1e39d76fbca | 19 | _spi.frequency(3000000); |
fastestoffer | 0:f1e39d76fbca | 20 | _spi.set_dma_usage(DMA_USAGE_ALWAYS); |
fastestoffer | 0:f1e39d76fbca | 21 | |
fastestoffer | 0:f1e39d76fbca | 22 | //Initialize led data buffer to zero |
fastestoffer | 0:f1e39d76fbca | 23 | memset(_led_data, 0, _led_data_size); |
fastestoffer | 0:f1e39d76fbca | 24 | } |
fastestoffer | 0:f1e39d76fbca | 25 | |
fastestoffer | 0:f1e39d76fbca | 26 | void WS2812::update_strip() { |
fastestoffer | 0:f1e39d76fbca | 27 | //Initiate transfer of led data buffer through SPI |
fastestoffer | 0:f1e39d76fbca | 28 | this->_spi.transfer(this->_led_data, this->_led_data_size, (uint8_t *)NULL, 0, this->_led_update_strip_finished); |
fastestoffer | 0:f1e39d76fbca | 29 | } |
fastestoffer | 0:f1e39d76fbca | 30 | |
fastestoffer | 0:f1e39d76fbca | 31 | //Write same color to all leds |
fastestoffer | 0:f1e39d76fbca | 32 | void WS2812::set_all(Color *c) { |
fastestoffer | 0:f1e39d76fbca | 33 | for(int i=0; i<WS2812_LED_NUM_LEDS; i++) |
fastestoffer | 0:f1e39d76fbca | 34 | { |
fastestoffer | 0:f1e39d76fbca | 35 | this->set_led(i, c); |
fastestoffer | 0:f1e39d76fbca | 36 | } |
fastestoffer | 0:f1e39d76fbca | 37 | } |
fastestoffer | 0:f1e39d76fbca | 38 | |
fastestoffer | 0:f1e39d76fbca | 39 | //Write color to led_number (a single led on the strip) |
fastestoffer | 0:f1e39d76fbca | 40 | //led_number range is [0,WS2812_LED_NUM_LEDS - 1] |
fastestoffer | 0:f1e39d76fbca | 41 | void WS2812::set_led(int led_number, Color *c) |
fastestoffer | 0:f1e39d76fbca | 42 | { |
fastestoffer | 0:f1e39d76fbca | 43 | uint8_t *ledptr; |
fastestoffer | 0:f1e39d76fbca | 44 | uint32_t offset; |
fastestoffer | 0:f1e39d76fbca | 45 | led_pixel_wire_data *led_pixel_data_ptr; |
fastestoffer | 0:f1e39d76fbca | 46 | |
fastestoffer | 0:f1e39d76fbca | 47 | offset = led_number * 12; |
fastestoffer | 0:f1e39d76fbca | 48 | ledptr = &(this->_led_data[offset]); |
fastestoffer | 0:f1e39d76fbca | 49 | led_pixel_data_ptr = (led_pixel_wire_data*)ledptr; |
fastestoffer | 0:f1e39d76fbca | 50 | |
fastestoffer | 0:f1e39d76fbca | 51 | /*************** GREEN value first (see datasheet) **********************/ |
fastestoffer | 0:f1e39d76fbca | 52 | _write_color_to_memory(led_pixel_data_ptr->g, c->g); |
fastestoffer | 0:f1e39d76fbca | 53 | |
fastestoffer | 0:f1e39d76fbca | 54 | /*************** RED value second (see datasheet) ***********************/ |
fastestoffer | 0:f1e39d76fbca | 55 | _write_color_to_memory(led_pixel_data_ptr->r, c->r); |
fastestoffer | 0:f1e39d76fbca | 56 | |
fastestoffer | 0:f1e39d76fbca | 57 | /*************** BLUE value last (see datasheet) ************************/ |
fastestoffer | 0:f1e39d76fbca | 58 | _write_color_to_memory(led_pixel_data_ptr->b, c->b); |
fastestoffer | 0:f1e39d76fbca | 59 | |
fastestoffer | 0:f1e39d76fbca | 60 | } |
fastestoffer | 0:f1e39d76fbca | 61 | |
fastestoffer | 0:f1e39d76fbca | 62 | //Write one channel of the color (R, G or B) to its in-memory representation |
fastestoffer | 0:f1e39d76fbca | 63 | void WS2812::_write_color_to_memory(uint8_t tuple[], uint8_t color_value) |
fastestoffer | 0:f1e39d76fbca | 64 | { |
fastestoffer | 0:f1e39d76fbca | 65 | uint8_t byte = 0, nibble = 0, bitval = 0; |
fastestoffer | 0:f1e39d76fbca | 66 | |
fastestoffer | 0:f1e39d76fbca | 67 | /* For each bit in the color value, convert it to a corresponding one or a zero in-memory value */ |
fastestoffer | 0:f1e39d76fbca | 68 | for(byte = 0; byte < 4; byte++) { |
fastestoffer | 0:f1e39d76fbca | 69 | tuple[3-byte] = 0; |
fastestoffer | 0:f1e39d76fbca | 70 | for(nibble = 0; nibble < 2; nibble++) { |
fastestoffer | 0:f1e39d76fbca | 71 | bitval = (color_value >> ((byte*2)+nibble)) & 0x1; |
fastestoffer | 0:f1e39d76fbca | 72 | bitval = bitval ? WS2812_ONE : WS2812_ZERO; |
fastestoffer | 0:f1e39d76fbca | 73 | |
fastestoffer | 0:f1e39d76fbca | 74 | tuple[3-byte] |= bitval << (nibble*4); |
fastestoffer | 0:f1e39d76fbca | 75 | } |
fastestoffer | 0:f1e39d76fbca | 76 | } |
fastestoffer | 0:f1e39d76fbca | 77 | } |