Test program for my Multi_WS2811 library that started out as a fork of heroic/WS2811. My library uses hardware DMA on the FRDM-KL25Z to drive up to 16 strings of WS2811 or WS2812 LEDs in parallel.
Dependencies: Multi_WS2811 mbed MMA8451Q
Fork of WS2811 by
NOTE: I have accidentally pushed changes for another fork of this program that I used in the recent Georgetown Carnival Power Tool Races. When I get some time, I will restore the test program to its original glory.
You can see my power tool racer (Nevermore's Revenge) here

This tests my FRDM-KL25Z multi-string WS2811/WS2812 library. It uses the accelerometer to change the rainbow phase on two strings of LEDs as well as the touch sense to change brightness.
A video of this program in operation is here.
Here is the library that I developed to run the LEDs:
Import libraryMulti_WS2811
Library allowing up to 16 strings of 60 WS2811 or WS2812 LEDs to be driven from a single FRDM-KL25Z board. Uses hardware DMA to do a full 800 KHz rate without much CPU burden.
WS2811.cpp@17:b4e9d8f4baa9, 2013-12-05 (annotated)
- Committer:
- bikeNomad
- Date:
- Thu Dec 05 15:25:16 2013 +0000
- Revision:
- 17:b4e9d8f4baa9
- Parent:
- 16:5f75ea93f15d
- Child:
- 20:b9d76e567637
renamed ws2812.* to ws2811.*
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| heroic | 10:62368b801d16 | 1 | // 800 KHz 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> |
| bikeNomad | 17:b4e9d8f4baa9 | 5 | // Modified to use hard SPI by Ned Konz <ned@bike-nomad.com> |
| heroic | 8:e3249c2b7607 | 6 | /*****************************************************************************/ |
| heroic | 8:e3249c2b7607 | 7 | |
| heroic | 8:e3249c2b7607 | 8 | #include "LedStrip.h" |
| heroic | 8:e3249c2b7607 | 9 | #include "WS2811.h" |
| heroic | 8:e3249c2b7607 | 10 | |
| bikeNomad | 17:b4e9d8f4baa9 | 11 | WS2811::WS2811(int n, PinName mosi, PinName sclk) : |
| bikeNomad | 17:b4e9d8f4baa9 | 12 | LedStrip(n), |
| bikeNomad | 17:b4e9d8f4baa9 | 13 | spi(mosi, NC, sclk) |
| bikeNomad | 17:b4e9d8f4baa9 | 14 | { |
| bikeNomad | 17:b4e9d8f4baa9 | 15 | #ifdef TARGET_KL25Z |
| bikeNomad | 17:b4e9d8f4baa9 | 16 | spi.format(8, 3); |
| bikeNomad | 17:b4e9d8f4baa9 | 17 | #else |
| bikeNomad | 17:b4e9d8f4baa9 | 18 | spi.format(16, 3); |
| bikeNomad | 17:b4e9d8f4baa9 | 19 | #endif |
| bikeNomad | 17:b4e9d8f4baa9 | 20 | spi.frequency(800e3 * 16); // 12.8 MHz => 800KHz bit rate |
| heroic | 8:e3249c2b7607 | 21 | } |
| heroic | 8:e3249c2b7607 | 22 | |
| heroic | 8:e3249c2b7607 | 23 | /* |
| heroic | 8:e3249c2b7607 | 24 | * These chips use a one-wire protocol based on a sort of NRZ signalling- jas. |
| heroic | 8:e3249c2b7607 | 25 | */ |
| bikeNomad | 17:b4e9d8f4baa9 | 26 | |
| bikeNomad | 17:b4e9d8f4baa9 | 27 | inline void WS2811::writebit(bool bit) |
| bikeNomad | 17:b4e9d8f4baa9 | 28 | { |
| bikeNomad | 17:b4e9d8f4baa9 | 29 | if (bit) { |
| bikeNomad | 17:b4e9d8f4baa9 | 30 | #ifdef TARGET_KL25Z |
| bikeNomad | 17:b4e9d8f4baa9 | 31 | spi.write(0xff); // 8 high |
| bikeNomad | 17:b4e9d8f4baa9 | 32 | spi.write(0x00); // 8 low |
| bikeNomad | 17:b4e9d8f4baa9 | 33 | #else |
| bikeNomad | 17:b4e9d8f4baa9 | 34 | spi.write(0xff00); |
| bikeNomad | 17:b4e9d8f4baa9 | 35 | #endif |
| bikeNomad | 17:b4e9d8f4baa9 | 36 | } else { |
| bikeNomad | 17:b4e9d8f4baa9 | 37 | #ifdef TARGET_KL25Z |
| bikeNomad | 17:b4e9d8f4baa9 | 38 | spi.write(0xe0); // 3 high, 5 low |
| bikeNomad | 17:b4e9d8f4baa9 | 39 | spi.write(0x00); // +8 low |
| bikeNomad | 17:b4e9d8f4baa9 | 40 | #else |
| bikeNomad | 17:b4e9d8f4baa9 | 41 | spi.write(0xe000); |
| bikeNomad | 17:b4e9d8f4baa9 | 42 | #endif |
| heroic | 8:e3249c2b7607 | 43 | } |
| heroic | 8:e3249c2b7607 | 44 | } |
| heroic | 8:e3249c2b7607 | 45 | |
| bikeNomad | 17:b4e9d8f4baa9 | 46 | void WS2811::write(uint8_t byte) |
| bikeNomad | 17:b4e9d8f4baa9 | 47 | { |
| bikeNomad | 17:b4e9d8f4baa9 | 48 | writebit(byte & 0x80); |
| bikeNomad | 17:b4e9d8f4baa9 | 49 | writebit(byte & 0x40); |
| bikeNomad | 17:b4e9d8f4baa9 | 50 | writebit(byte & 0x20); |
| bikeNomad | 17:b4e9d8f4baa9 | 51 | writebit(byte & 0x10); |
| bikeNomad | 17:b4e9d8f4baa9 | 52 | writebit(byte & 0x08); |
| bikeNomad | 17:b4e9d8f4baa9 | 53 | writebit(byte & 0x04); |
| bikeNomad | 17:b4e9d8f4baa9 | 54 | writebit(byte & 0x02); |
| bikeNomad | 17:b4e9d8f4baa9 | 55 | writebit(byte & 0x01); |
| heroic | 8:e3249c2b7607 | 56 | } |
| heroic | 8:e3249c2b7607 | 57 | |
| bikeNomad | 17:b4e9d8f4baa9 | 58 | void WS2811::begin(void) |
| bikeNomad | 17:b4e9d8f4baa9 | 59 | { |
| heroic | 8:e3249c2b7607 | 60 | blank(); |
| heroic | 8:e3249c2b7607 | 61 | show(); |
| heroic | 8:e3249c2b7607 | 62 | } |
| heroic | 8:e3249c2b7607 | 63 | |
| bikeNomad | 17:b4e9d8f4baa9 | 64 | void WS2811::blank(void) |
| bikeNomad | 17:b4e9d8f4baa9 | 65 | { |
| bikeNomad | 17:b4e9d8f4baa9 | 66 | memset(pixels, 0x00, numPixelBytes()); |
| heroic | 8:e3249c2b7607 | 67 | } |
| heroic | 8:e3249c2b7607 | 68 | |
| bikeNomad | 17:b4e9d8f4baa9 | 69 | void WS2811::show(void) |
| bikeNomad | 17:b4e9d8f4baa9 | 70 | { |
| bikeNomad | 17:b4e9d8f4baa9 | 71 | uint16_t i, nl3 = numPixelBytes(); // 3 bytes per LED |
| heroic | 8:e3249c2b7607 | 72 | while (guardtime.read_us() < 50) |
| heroic | 8:e3249c2b7607 | 73 | /* spin */; |
| heroic | 13:1f65330abe92 | 74 | __disable_irq(); |
| heroic | 8:e3249c2b7607 | 75 | for (i=0; i<nl3; i++ ) { |
| heroic | 8:e3249c2b7607 | 76 | write(pixels[i]); |
| heroic | 8:e3249c2b7607 | 77 | } |
| heroic | 13:1f65330abe92 | 78 | __enable_irq(); |
| heroic | 8:e3249c2b7607 | 79 | guardtime.reset(); |
| heroic | 8:e3249c2b7607 | 80 | } |
| heroic | 8:e3249c2b7607 | 81 | |
| heroic | 8:e3249c2b7607 | 82 |
Ned Konz


Generic WS2811/WS2812