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:
Fri Oct 12 04:16:40 2012 +0000
Revision:
7:3025f0e0d70a
Parent:
6:7aebe547f0f0
Add logic to compute total luminance and hence current.

Who changed what in which revision?

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