Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: WS2812_Example WS2812_Example_fade Lamp_03 Lamp_04 ... more
WS2812.cpp@0:0b79cafcb387, 2015-02-12 (annotated)
- Committer:
- bridadan
- Date:
- Thu Feb 12 19:17:10 2015 +0000
- Revision:
- 0:0b79cafcb387
- Child:
- 1:aadbf08c62a2
Driver for the WS2812 LED driver. Uses bit banging and relies on nops for timing. Number of nops can be varied to potentially accommodate different platforms. Currently tested on the K64F.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| bridadan | 0:0b79cafcb387 | 1 | #include "WS2812.h" |
| bridadan | 0:0b79cafcb387 | 2 | |
| bridadan | 0:0b79cafcb387 | 3 | WS2812::WS2812(PinName d, int size) : __gpo(d) |
| bridadan | 0:0b79cafcb387 | 4 | { |
| bridadan | 0:0b79cafcb387 | 5 | __size = size; |
| bridadan | 0:0b79cafcb387 | 6 | __transmitBuf = new bool[size * FRAME_SIZE]; |
| bridadan | 0:0b79cafcb387 | 7 | __use_II = 0; // 0=off,1=use global,2=per pixel |
| bridadan | 0:0b79cafcb387 | 8 | __II = 0xFF; // set global intensity to full |
| bridadan | 0:0b79cafcb387 | 9 | __outPin = d; |
| bridadan | 0:0b79cafcb387 | 10 | |
| bridadan | 0:0b79cafcb387 | 11 | // Default values designed for K64f. Assumes GPIO toggle takes ~0.4us |
| bridadan | 0:0b79cafcb387 | 12 | setDelays(0, 5, 5, 0); |
| bridadan | 0:0b79cafcb387 | 13 | } |
| bridadan | 0:0b79cafcb387 | 14 | |
| bridadan | 0:0b79cafcb387 | 15 | |
| bridadan | 0:0b79cafcb387 | 16 | WS2812::~WS2812() |
| bridadan | 0:0b79cafcb387 | 17 | { |
| bridadan | 0:0b79cafcb387 | 18 | delete[] __transmitBuf; |
| bridadan | 0:0b79cafcb387 | 19 | } |
| bridadan | 0:0b79cafcb387 | 20 | |
| bridadan | 0:0b79cafcb387 | 21 | void WS2812::setDelays(int zeroHigh, int zeroLow, int oneHigh, int oneLow) { |
| bridadan | 0:0b79cafcb387 | 22 | __zeroHigh = zeroHigh; |
| bridadan | 0:0b79cafcb387 | 23 | __zeroLow = zeroLow; |
| bridadan | 0:0b79cafcb387 | 24 | __oneHigh = oneHigh; |
| bridadan | 0:0b79cafcb387 | 25 | __oneLow = oneLow; |
| bridadan | 0:0b79cafcb387 | 26 | } |
| bridadan | 0:0b79cafcb387 | 27 | |
| bridadan | 0:0b79cafcb387 | 28 | void WS2812::__loadBuf(int buf[],int r_offset, int g_offset, int b_offset) { |
| bridadan | 0:0b79cafcb387 | 29 | for (int i = 0; i < __size; i++) { |
| bridadan | 0:0b79cafcb387 | 30 | int color = 0; |
| bridadan | 0:0b79cafcb387 | 31 | |
| bridadan | 0:0b79cafcb387 | 32 | color |= ((buf[(i+g_offset)%__size] & 0x0000FF00)); |
| bridadan | 0:0b79cafcb387 | 33 | color |= ((buf[(i+r_offset)%__size] & 0x00FF0000)); |
| bridadan | 0:0b79cafcb387 | 34 | color |= (buf[(i+b_offset)%__size] & 0x000000FF); |
| bridadan | 0:0b79cafcb387 | 35 | color |= (buf[i] & 0xFF000000); |
| bridadan | 0:0b79cafcb387 | 36 | |
| bridadan | 0:0b79cafcb387 | 37 | // Outut format : GGRRBB |
| bridadan | 0:0b79cafcb387 | 38 | // Inout format : IIRRGGBB |
| bridadan | 0:0b79cafcb387 | 39 | unsigned char agrb[4] = {0x0, 0x0, 0x0, 0x0}; |
| bridadan | 0:0b79cafcb387 | 40 | |
| bridadan | 0:0b79cafcb387 | 41 | unsigned char sf; // scaling factor for II |
| bridadan | 0:0b79cafcb387 | 42 | |
| bridadan | 0:0b79cafcb387 | 43 | // extract colour fields from incoming |
| bridadan | 0:0b79cafcb387 | 44 | // 0 = green, 1 = red, 2 = blue, 3 = brightness |
| bridadan | 0:0b79cafcb387 | 45 | agrb[0] = (color & 0x0000FF00) >> 8; |
| bridadan | 0:0b79cafcb387 | 46 | agrb[1] = (color & 0x00FF0000) >> 16; |
| bridadan | 0:0b79cafcb387 | 47 | agrb[2] = color & 0x000000FF; |
| bridadan | 0:0b79cafcb387 | 48 | agrb[3] = (color & 0xFF000000) >> 24; |
| bridadan | 0:0b79cafcb387 | 49 | |
| bridadan | 0:0b79cafcb387 | 50 | // set and intensity scaling factor (global, per pixel, none) |
| bridadan | 0:0b79cafcb387 | 51 | if (__use_II == 1) { |
| bridadan | 0:0b79cafcb387 | 52 | sf = __II; |
| bridadan | 0:0b79cafcb387 | 53 | } else if (__use_II == 2) { |
| bridadan | 0:0b79cafcb387 | 54 | sf = agrb[3]; |
| bridadan | 0:0b79cafcb387 | 55 | } else { |
| bridadan | 0:0b79cafcb387 | 56 | sf = 0xFF; |
| bridadan | 0:0b79cafcb387 | 57 | } |
| bridadan | 0:0b79cafcb387 | 58 | |
| bridadan | 0:0b79cafcb387 | 59 | // Apply the scaling factor to each othe colour components |
| bridadan | 0:0b79cafcb387 | 60 | for (int clr = 0; clr < 3; clr++) { |
| bridadan | 0:0b79cafcb387 | 61 | agrb[clr] = ((agrb[clr] * sf) >> 8); |
| bridadan | 0:0b79cafcb387 | 62 | |
| bridadan | 0:0b79cafcb387 | 63 | for (int j = 0; j < 8; j++) { |
| bridadan | 0:0b79cafcb387 | 64 | if (((agrb[clr] << j) & 0x80) == 0x80) { |
| bridadan | 0:0b79cafcb387 | 65 | // Bit is set (checks MSB fist) |
| bridadan | 0:0b79cafcb387 | 66 | __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 1; |
| bridadan | 0:0b79cafcb387 | 67 | } else { |
| bridadan | 0:0b79cafcb387 | 68 | // Bit is clear |
| bridadan | 0:0b79cafcb387 | 69 | __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 0; |
| bridadan | 0:0b79cafcb387 | 70 | } |
| bridadan | 0:0b79cafcb387 | 71 | } |
| bridadan | 0:0b79cafcb387 | 72 | } |
| bridadan | 0:0b79cafcb387 | 73 | } |
| bridadan | 0:0b79cafcb387 | 74 | } |
| bridadan | 0:0b79cafcb387 | 75 | |
| bridadan | 0:0b79cafcb387 | 76 | void WS2812::write(int buf[]) { |
| bridadan | 0:0b79cafcb387 | 77 | write_offsets(buf, 0, 0, 0); |
| bridadan | 0:0b79cafcb387 | 78 | } |
| bridadan | 0:0b79cafcb387 | 79 | |
| bridadan | 0:0b79cafcb387 | 80 | void WS2812::write_offsets (int buf[],int r_offset, int g_offset, int b_offset) { |
| bridadan | 0:0b79cafcb387 | 81 | int i, j; |
| bridadan | 0:0b79cafcb387 | 82 | |
| bridadan | 0:0b79cafcb387 | 83 | __loadBuf(buf, r_offset, g_offset, b_offset); |
| bridadan | 0:0b79cafcb387 | 84 | |
| bridadan | 0:0b79cafcb387 | 85 | for (i = 0; i < FRAME_SIZE * __size; i++) { |
| bridadan | 0:0b79cafcb387 | 86 | j = 0; |
| bridadan | 0:0b79cafcb387 | 87 | if (__transmitBuf[i]){ |
| bridadan | 0:0b79cafcb387 | 88 | __gpo = 1; |
| bridadan | 0:0b79cafcb387 | 89 | for (; j < __oneHigh; j++) { |
| bridadan | 0:0b79cafcb387 | 90 | __nop(); |
| bridadan | 0:0b79cafcb387 | 91 | } |
| bridadan | 0:0b79cafcb387 | 92 | __gpo = 0; |
| bridadan | 0:0b79cafcb387 | 93 | for (; j < __oneLow; j++) { |
| bridadan | 0:0b79cafcb387 | 94 | __nop(); |
| bridadan | 0:0b79cafcb387 | 95 | } |
| bridadan | 0:0b79cafcb387 | 96 | } else { |
| bridadan | 0:0b79cafcb387 | 97 | __gpo = 1; |
| bridadan | 0:0b79cafcb387 | 98 | for (; j < __zeroHigh; j++) { |
| bridadan | 0:0b79cafcb387 | 99 | __nop(); |
| bridadan | 0:0b79cafcb387 | 100 | } |
| bridadan | 0:0b79cafcb387 | 101 | __gpo = 0; |
| bridadan | 0:0b79cafcb387 | 102 | for (; j < __zeroLow; j++) { |
| bridadan | 0:0b79cafcb387 | 103 | __nop(); |
| bridadan | 0:0b79cafcb387 | 104 | } |
| bridadan | 0:0b79cafcb387 | 105 | } |
| bridadan | 0:0b79cafcb387 | 106 | } |
| bridadan | 0:0b79cafcb387 | 107 | } |
| bridadan | 0:0b79cafcb387 | 108 | |
| bridadan | 0:0b79cafcb387 | 109 | |
| bridadan | 0:0b79cafcb387 | 110 | void WS2812::useII(int d) |
| bridadan | 0:0b79cafcb387 | 111 | { |
| bridadan | 0:0b79cafcb387 | 112 | if (d > 0) { |
| bridadan | 0:0b79cafcb387 | 113 | __use_II = d; |
| bridadan | 0:0b79cafcb387 | 114 | } else { |
| bridadan | 0:0b79cafcb387 | 115 | __use_II = 0; |
| bridadan | 0:0b79cafcb387 | 116 | } |
| bridadan | 0:0b79cafcb387 | 117 | } |
| bridadan | 0:0b79cafcb387 | 118 | |
| bridadan | 0:0b79cafcb387 | 119 | void WS2812::setII(unsigned char II) |
| bridadan | 0:0b79cafcb387 | 120 | { |
| bridadan | 0:0b79cafcb387 | 121 | __II = II; |
| bridadan | 0:0b79cafcb387 | 122 | } |
| bridadan | 0:0b79cafcb387 | 123 | |
| bridadan | 0:0b79cafcb387 | 124 | |
| bridadan | 0:0b79cafcb387 | 125 | |
| bridadan | 0:0b79cafcb387 | 126 | |
| bridadan | 0:0b79cafcb387 | 127 | |
| bridadan | 0:0b79cafcb387 | 128 |
Generic WS2812 Driver