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 Heroic Robotics

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

/media/uploads/bikeNomad/img_0482.jpg

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.

Committer:
heroic
Date:
Wed Oct 10 05:43:58 2012 +0000
Revision:
5:70ded6500cd3
Parent:
4:0b75eb84a6d2
Remove dead comment

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ehbmbed2 0:12e734116fea 1 // Mbed library to control LPD8806-based RGB LED Strips
ehbmbed2 0:12e734116fea 2 // (c) 2011 Jelmer Tiete
ehbmbed2 0:12e734116fea 3 // This library is ported from the Arduino implementation of Adafruit Industries
ehbmbed2 0:12e734116fea 4 // found at: http://github.com/adafruit/LPD8806
ehbmbed2 0:12e734116fea 5 // and their strips: http://www.adafruit.com/products/306
ehbmbed2 0:12e734116fea 6 // Released under the MIT License: http://mbed.org/license/mit
ehbmbed2 1:6ebd3ac910b6 7 //
heroic 2:af5af64e114d 8 // Parameterized and modified to use soft SPI.
heroic 2:af5af64e114d 9 // Jas Strong <jasmine@electronpusher.org>
ehbmbed2 0:12e734116fea 10 /*****************************************************************************/
ehbmbed2 0:12e734116fea 11
heroic 4:0b75eb84a6d2 12 #include "LedStrip.h"
ehbmbed2 0:12e734116fea 13 #include "LPD8806.h"
ehbmbed2 0:12e734116fea 14
heroic 2:af5af64e114d 15 LPD8806::LPD8806(PinName dataPin, PinName clockPin, int n) :
heroic 2:af5af64e114d 16 dat(dataPin),
heroic 2:af5af64e114d 17 clk(clockPin) {
ehbmbed2 0:12e734116fea 18 // Allocate 3 bytes per pixel:
heroic 2:af5af64e114d 19 numLEDs = n;
heroic 3:a415f73507c9 20 if ((pixels = (uint8_t *)malloc(numLEDs * 3))) {
ehbmbed2 0:12e734116fea 21 memset(pixels, 0x80, numLEDs * 3); // Init to RGB 'off' state
ehbmbed2 0:12e734116fea 22 }
ehbmbed2 0:12e734116fea 23 }
ehbmbed2 0:12e734116fea 24
heroic 2:af5af64e114d 25 /*
heroic 2:af5af64e114d 26 * Soft SPI clock-out implementation (CPOL = 0, CPHA = 0).
heroic 2:af5af64e114d 27 * Certainly not the fastest in the world but it'll do.
heroic 2:af5af64e114d 28 * Gets about 3.6 MHz; could get several times as much
heroic 2:af5af64e114d 29 * using the bitbands directly - jas.
heroic 2:af5af64e114d 30 */
heroic 2:af5af64e114d 31
heroic 2:af5af64e114d 32 void LPD8806::write(uint8_t byte) {
heroic 2:af5af64e114d 33 for (int i=0; i<8; i++) {
heroic 2:af5af64e114d 34 clk = 0;
heroic 2:af5af64e114d 35 dat = (byte & 0x80);
heroic 2:af5af64e114d 36 clk = 1;
heroic 2:af5af64e114d 37 byte <<= 1;
heroic 2:af5af64e114d 38 }
heroic 2:af5af64e114d 39 clk = 0;
heroic 2:af5af64e114d 40 }
ehbmbed2 0:12e734116fea 41
heroic 2:af5af64e114d 42 void LPD8806::begin(void) {
ehbmbed2 0:12e734116fea 43
ehbmbed2 0:12e734116fea 44 // Issue initial latch to 'wake up' strip (latch length varies w/numLEDs)
ehbmbed2 0:12e734116fea 45 writezeros(3 * ((numLEDs + 63) / 64));
heroic 5:70ded6500cd3 46 blank();
heroic 5:70ded6500cd3 47 show();
ehbmbed2 0:12e734116fea 48 }
ehbmbed2 0:12e734116fea 49
ehbmbed2 0:12e734116fea 50 uint16_t LPD8806::numPixels(void) {
ehbmbed2 0:12e734116fea 51 return numLEDs;
ehbmbed2 0:12e734116fea 52 }
ehbmbed2 0:12e734116fea 53
ehbmbed2 0:12e734116fea 54 void LPD8806::writezeros(uint16_t n) {
heroic 2:af5af64e114d 55 while (n--) write(0x00);
heroic 2:af5af64e114d 56 }
heroic 2:af5af64e114d 57
heroic 2:af5af64e114d 58 void LPD8806::blank(void) {
heroic 2:af5af64e114d 59 memset(pixels, 0x80, numLEDs * 3);
ehbmbed2 0:12e734116fea 60 }
ehbmbed2 0:12e734116fea 61
ehbmbed2 0:12e734116fea 62 // This is how data is pushed to the strip. Unfortunately, the company
ehbmbed2 0:12e734116fea 63 // that makes the chip didnt release the protocol document or you need
ehbmbed2 0:12e734116fea 64 // to sign an NDA or something stupid like that, but we reverse engineered
ehbmbed2 0:12e734116fea 65 // this from a strip controller and it seems to work very nicely!
ehbmbed2 0:12e734116fea 66 void LPD8806::show(void) {
ehbmbed2 0:12e734116fea 67 uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED
ehbmbed2 0:12e734116fea 68
ehbmbed2 0:12e734116fea 69 for (i=0; i<nl3; i++ ) {
heroic 2:af5af64e114d 70 write(pixels[i]);
ehbmbed2 0:12e734116fea 71 }
ehbmbed2 0:12e734116fea 72
ehbmbed2 0:12e734116fea 73 // Write latch at end of data; latch length varies with number of LEDs
ehbmbed2 0:12e734116fea 74 writezeros(3 * ((numLEDs + 63) / 64));
ehbmbed2 0:12e734116fea 75 }
ehbmbed2 0:12e734116fea 76
ehbmbed2 0:12e734116fea 77 // Convert R,G,B to combined 32-bit color
ehbmbed2 0:12e734116fea 78 uint32_t LPD8806::Color(uint8_t r, uint8_t g, uint8_t b) {
ehbmbed2 0:12e734116fea 79 // Take the lowest 7 bits of each value and append them end to end
ehbmbed2 0:12e734116fea 80 // We have the top bit set high (its a 'parity-like' bit in the protocol
ehbmbed2 0:12e734116fea 81 // and must be set!)
ehbmbed2 0:12e734116fea 82 return 0x808080 | ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b;
ehbmbed2 0:12e734116fea 83 }
ehbmbed2 0:12e734116fea 84
ehbmbed2 0:12e734116fea 85 // store the rgb component in our array
ehbmbed2 0:12e734116fea 86 void LPD8806::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
ehbmbed2 0:12e734116fea 87 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
ehbmbed2 0:12e734116fea 88
ehbmbed2 0:12e734116fea 89 pixels[n*3 ] = g | 0x80;
ehbmbed2 0:12e734116fea 90 pixels[n*3+1] = r | 0x80;
ehbmbed2 0:12e734116fea 91 pixels[n*3+2] = b | 0x80;
ehbmbed2 0:12e734116fea 92 }
ehbmbed2 0:12e734116fea 93
heroic 2:af5af64e114d 94 void LPD8806::setPixelR(uint16_t n, uint8_t r) {
heroic 2:af5af64e114d 95 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 2:af5af64e114d 96
heroic 2:af5af64e114d 97 pixels[n*3+1] = r | 0x80;
heroic 2:af5af64e114d 98 }
heroic 2:af5af64e114d 99
heroic 2:af5af64e114d 100 void LPD8806::setPixelG(uint16_t n, uint8_t g) {
heroic 2:af5af64e114d 101 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 2:af5af64e114d 102
heroic 2:af5af64e114d 103 pixels[n*3] = g | 0x80;
heroic 2:af5af64e114d 104 }
heroic 2:af5af64e114d 105
heroic 2:af5af64e114d 106 void LPD8806::setPixelB(uint16_t n, uint8_t b) {
heroic 2:af5af64e114d 107 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 2:af5af64e114d 108
heroic 2:af5af64e114d 109 pixels[n*3+2] = b | 0x80;
heroic 2:af5af64e114d 110 }
heroic 2:af5af64e114d 111
ehbmbed2 0:12e734116fea 112 void LPD8806::setPixelColor(uint16_t n, uint32_t c) {
ehbmbed2 0:12e734116fea 113 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
ehbmbed2 0:12e734116fea 114
ehbmbed2 0:12e734116fea 115 pixels[n*3 ] = (c >> 16) | 0x80;
ehbmbed2 0:12e734116fea 116 pixels[n*3+1] = (c >> 8) | 0x80;
ehbmbed2 0:12e734116fea 117 pixels[n*3+2] = c | 0x80;
ehbmbed2 0:12e734116fea 118 }