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.
Dependencies: Multi_WS2811 mbed MMA8451Q
Fork of WS2811 by
WS2811.cpp@8:e3249c2b7607, 2012-11-10 (annotated)
- Committer:
- heroic
- Date:
- Sat Nov 10 05:58:14 2012 +0000
- Revision:
- 8:e3249c2b7607
- Child:
- 9:dd524af149e6
Initial commit for first cut of WS2811 driver. These are one-wire style devices, so we do some timing mojo.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| heroic | 8:e3249c2b7607 | 1 | // WS2811 driver, kinda. |
| heroic | 8:e3249c2b7607 | 2 | // |
| heroic | 8:e3249c2b7607 | 3 | // Parameterized and modified to use soft SPI. |
| heroic | 8:e3249c2b7607 | 4 | // Jas Strong <jasmine@electronpusher.org> |
| heroic | 8:e3249c2b7607 | 5 | /*****************************************************************************/ |
| heroic | 8:e3249c2b7607 | 6 | |
| heroic | 8:e3249c2b7607 | 7 | #include "LedStrip.h" |
| heroic | 8:e3249c2b7607 | 8 | #include "WS2811.h" |
| heroic | 8:e3249c2b7607 | 9 | |
| heroic | 8:e3249c2b7607 | 10 | WS2811::WS2811(PinName dataPin, PinName clockPin, int n) : |
| heroic | 8:e3249c2b7607 | 11 | dat(dataPin), |
| heroic | 8:e3249c2b7607 | 12 | clk(clockPin) { |
| heroic | 8:e3249c2b7607 | 13 | // Allocate 3 bytes per pixel: |
| heroic | 8:e3249c2b7607 | 14 | numLEDs = n; |
| heroic | 8:e3249c2b7607 | 15 | if ((pixels = (uint8_t *)malloc(numLEDs * 3))) { |
| heroic | 8:e3249c2b7607 | 16 | memset(pixels, 0x00, numLEDs * 3); // Init to RGB 'off' state |
| heroic | 8:e3249c2b7607 | 17 | } |
| heroic | 8:e3249c2b7607 | 18 | // calibrate delay loops for NRZ |
| heroic | 8:e3249c2b7607 | 19 | int i; |
| heroic | 8:e3249c2b7607 | 20 | guardtime.start(); |
| heroic | 8:e3249c2b7607 | 21 | for (i=0; i<1000; i++) |
| heroic | 8:e3249c2b7607 | 22 | /* do nothing */; |
| heroic | 8:e3249c2b7607 | 23 | i=guardtime.read_us(); |
| heroic | 8:e3249c2b7607 | 24 | printf("ws2811: 1000 iters took %d usec.\n", i); |
| heroic | 8:e3249c2b7607 | 25 | bogocal = (1000 / (i*2.4)); // iterations per bitcell (417 nsec) |
| heroic | 8:e3249c2b7607 | 26 | printf("ws2811: calibrating to %d bogojiffies.\n", bogocal); |
| heroic | 8:e3249c2b7607 | 27 | } |
| heroic | 8:e3249c2b7607 | 28 | |
| heroic | 8:e3249c2b7607 | 29 | /* |
| heroic | 8:e3249c2b7607 | 30 | * These chips use a one-wire protocol based on a sort of NRZ signalling- jas. |
| heroic | 8:e3249c2b7607 | 31 | */ |
| heroic | 8:e3249c2b7607 | 32 | |
| heroic | 8:e3249c2b7607 | 33 | void WS2811::write(uint8_t byte) { |
| heroic | 8:e3249c2b7607 | 34 | for (int i=0; i<8; i++) { |
| heroic | 8:e3249c2b7607 | 35 | if (byte & 0x80) |
| heroic | 8:e3249c2b7607 | 36 | writebit(1); |
| heroic | 8:e3249c2b7607 | 37 | else |
| heroic | 8:e3249c2b7607 | 38 | writebit(0); |
| heroic | 8:e3249c2b7607 | 39 | byte <<= 1; |
| heroic | 8:e3249c2b7607 | 40 | } |
| heroic | 8:e3249c2b7607 | 41 | } |
| heroic | 8:e3249c2b7607 | 42 | |
| heroic | 8:e3249c2b7607 | 43 | inline void WS2811::celldelay(void) { |
| heroic | 8:e3249c2b7607 | 44 | for (int i = 0; i<bogocal; i++) |
| heroic | 8:e3249c2b7607 | 45 | /* do nothing */ ; |
| heroic | 8:e3249c2b7607 | 46 | } |
| heroic | 8:e3249c2b7607 | 47 | |
| heroic | 8:e3249c2b7607 | 48 | void WS2811::writebit(bool bit) { |
| heroic | 8:e3249c2b7607 | 49 | // first cell is always 1 |
| heroic | 8:e3249c2b7607 | 50 | dat = 1; |
| heroic | 8:e3249c2b7607 | 51 | celldelay(); |
| heroic | 8:e3249c2b7607 | 52 | if (bit) { |
| heroic | 8:e3249c2b7607 | 53 | celldelay(); |
| heroic | 8:e3249c2b7607 | 54 | } else { |
| heroic | 8:e3249c2b7607 | 55 | dat=0; |
| heroic | 8:e3249c2b7607 | 56 | celldelay(); |
| heroic | 8:e3249c2b7607 | 57 | } |
| heroic | 8:e3249c2b7607 | 58 | // last cell is always 0 |
| heroic | 8:e3249c2b7607 | 59 | dat=0; |
| heroic | 8:e3249c2b7607 | 60 | celldelay(); |
| heroic | 8:e3249c2b7607 | 61 | } |
| heroic | 8:e3249c2b7607 | 62 | |
| heroic | 8:e3249c2b7607 | 63 | void WS2811::begin(void) { |
| heroic | 8:e3249c2b7607 | 64 | blank(); |
| heroic | 8:e3249c2b7607 | 65 | show(); |
| heroic | 8:e3249c2b7607 | 66 | } |
| heroic | 8:e3249c2b7607 | 67 | |
| heroic | 8:e3249c2b7607 | 68 | uint16_t WS2811::numPixels(void) { |
| heroic | 8:e3249c2b7607 | 69 | return numLEDs; |
| heroic | 8:e3249c2b7607 | 70 | } |
| heroic | 8:e3249c2b7607 | 71 | |
| heroic | 8:e3249c2b7607 | 72 | void WS2811::blank(void) { |
| heroic | 8:e3249c2b7607 | 73 | memset(pixels, 0x00, numLEDs * 3); |
| heroic | 8:e3249c2b7607 | 74 | } |
| heroic | 8:e3249c2b7607 | 75 | |
| heroic | 8:e3249c2b7607 | 76 | void WS2811::show(void) { |
| heroic | 8:e3249c2b7607 | 77 | uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED |
| heroic | 8:e3249c2b7607 | 78 | while (guardtime.read_us() < 50) |
| heroic | 8:e3249c2b7607 | 79 | /* spin */; |
| heroic | 8:e3249c2b7607 | 80 | for (i=0; i<nl3; i++ ) { |
| heroic | 8:e3249c2b7607 | 81 | write(pixels[i]); |
| heroic | 8:e3249c2b7607 | 82 | } |
| heroic | 8:e3249c2b7607 | 83 | |
| heroic | 8:e3249c2b7607 | 84 | guardtime.reset(); |
| heroic | 8:e3249c2b7607 | 85 | } |
| heroic | 8:e3249c2b7607 | 86 | |
| heroic | 8:e3249c2b7607 | 87 | |
| heroic | 8:e3249c2b7607 | 88 | uint32_t WS2811::total_luminance(void) { |
| heroic | 8:e3249c2b7607 | 89 | uint32_t running_total; |
| heroic | 8:e3249c2b7607 | 90 | running_total = 0; |
| heroic | 8:e3249c2b7607 | 91 | for (int i=0; i<numLEDs*3; i++) |
| heroic | 8:e3249c2b7607 | 92 | running_total += pixels[i]; |
| heroic | 8:e3249c2b7607 | 93 | return running_total; |
| heroic | 8:e3249c2b7607 | 94 | } |
| heroic | 8:e3249c2b7607 | 95 | |
| heroic | 8:e3249c2b7607 | 96 | // Convert R,G,B to combined 32-bit color |
| heroic | 8:e3249c2b7607 | 97 | uint32_t WS2811::Color(uint8_t r, uint8_t g, uint8_t b) { |
| heroic | 8:e3249c2b7607 | 98 | // Take the lowest 7 bits of each value and append them end to end |
| heroic | 8:e3249c2b7607 | 99 | // We have the top bit set high (its a 'parity-like' bit in the protocol |
| heroic | 8:e3249c2b7607 | 100 | // and must be set!) |
| heroic | 8:e3249c2b7607 | 101 | return ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b; |
| heroic | 8:e3249c2b7607 | 102 | } |
| heroic | 8:e3249c2b7607 | 103 | |
| heroic | 8:e3249c2b7607 | 104 | // store the rgb component in our array |
| heroic | 8:e3249c2b7607 | 105 | void WS2811::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) { |
| heroic | 8:e3249c2b7607 | 106 | if (n >= numLEDs) return; // '>=' because arrays are 0-indexed |
| heroic | 8:e3249c2b7607 | 107 | |
| heroic | 8:e3249c2b7607 | 108 | pixels[n*3 ] = g; |
| heroic | 8:e3249c2b7607 | 109 | pixels[n*3+1] = r; |
| heroic | 8:e3249c2b7607 | 110 | pixels[n*3+2] = b; |
| heroic | 8:e3249c2b7607 | 111 | } |
| heroic | 8:e3249c2b7607 | 112 | |
| heroic | 8:e3249c2b7607 | 113 | void WS2811::setPixelR(uint16_t n, uint8_t r) { |
| heroic | 8:e3249c2b7607 | 114 | if (n >= numLEDs) return; // '>=' because arrays are 0-indexed |
| heroic | 8:e3249c2b7607 | 115 | |
| heroic | 8:e3249c2b7607 | 116 | pixels[n*3+1] = r; |
| heroic | 8:e3249c2b7607 | 117 | } |
| heroic | 8:e3249c2b7607 | 118 | |
| heroic | 8:e3249c2b7607 | 119 | void WS2811::setPixelG(uint16_t n, uint8_t g) { |
| heroic | 8:e3249c2b7607 | 120 | if (n >= numLEDs) return; // '>=' because arrays are 0-indexed |
| heroic | 8:e3249c2b7607 | 121 | |
| heroic | 8:e3249c2b7607 | 122 | pixels[n*3] = g; |
| heroic | 8:e3249c2b7607 | 123 | } |
| heroic | 8:e3249c2b7607 | 124 | |
| heroic | 8:e3249c2b7607 | 125 | void WS2811::setPixelB(uint16_t n, uint8_t b) { |
| heroic | 8:e3249c2b7607 | 126 | if (n >= numLEDs) return; // '>=' because arrays are 0-indexed |
| heroic | 8:e3249c2b7607 | 127 | |
| heroic | 8:e3249c2b7607 | 128 | pixels[n*3+2] = b; |
| heroic | 8:e3249c2b7607 | 129 | } |
| heroic | 8:e3249c2b7607 | 130 | |
| heroic | 8:e3249c2b7607 | 131 | void WS2811::setPixelColor(uint16_t n, uint32_t c) { |
| heroic | 8:e3249c2b7607 | 132 | if (n >= numLEDs) return; // '>=' because arrays are 0-indexed |
| heroic | 8:e3249c2b7607 | 133 | |
| heroic | 8:e3249c2b7607 | 134 | pixels[n*3 ] = (c >> 16); |
| heroic | 8:e3249c2b7607 | 135 | pixels[n*3+1] = (c >> 8); |
| heroic | 8:e3249c2b7607 | 136 | pixels[n*3+2] = c; |
| heroic | 8:e3249c2b7607 | 137 | } |

Generic WS2811/WS2812