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:
Thu Oct 11 08:34:21 2012 +0000
Revision:
6:7aebe547f0f0
Parent:
LPD8806.cpp@5:70ded6500cd3
Child:
7:3025f0e0d70a
Initial commit of WS2801 driver library.

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"
heroic 6:7aebe547f0f0 13 #include "WS2801.h"
ehbmbed2 0:12e734116fea 14
heroic 6:7aebe547f0f0 15 WS2801::WS2801(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))) {
heroic 6:7aebe547f0f0 21 memset(pixels, 0x00, numLEDs * 3); // Init to RGB 'off' state
ehbmbed2 0:12e734116fea 22 }
heroic 6:7aebe547f0f0 23 guardtime.start();
ehbmbed2 0:12e734116fea 24 }
ehbmbed2 0:12e734116fea 25
heroic 2:af5af64e114d 26 /*
heroic 2:af5af64e114d 27 * Soft SPI clock-out implementation (CPOL = 0, CPHA = 0).
heroic 2:af5af64e114d 28 * Certainly not the fastest in the world but it'll do.
heroic 2:af5af64e114d 29 * Gets about 3.6 MHz; could get several times as much
heroic 2:af5af64e114d 30 * using the bitbands directly - jas.
heroic 2:af5af64e114d 31 */
heroic 2:af5af64e114d 32
heroic 6:7aebe547f0f0 33 void WS2801::write(uint8_t byte) {
heroic 2:af5af64e114d 34 for (int i=0; i<8; i++) {
heroic 2:af5af64e114d 35 clk = 0;
heroic 6:7aebe547f0f0 36 wait_us(WS2801_DELAY);
heroic 2:af5af64e114d 37 dat = (byte & 0x80);
heroic 2:af5af64e114d 38 clk = 1;
heroic 6:7aebe547f0f0 39 wait_us(WS2801_DELAY);
heroic 2:af5af64e114d 40 byte <<= 1;
heroic 2:af5af64e114d 41 }
heroic 2:af5af64e114d 42 clk = 0;
heroic 2:af5af64e114d 43 }
ehbmbed2 0:12e734116fea 44
heroic 6:7aebe547f0f0 45 void WS2801::begin(void) {
heroic 5:70ded6500cd3 46 blank();
heroic 5:70ded6500cd3 47 show();
ehbmbed2 0:12e734116fea 48 }
ehbmbed2 0:12e734116fea 49
heroic 6:7aebe547f0f0 50 uint16_t WS2801::numPixels(void) {
ehbmbed2 0:12e734116fea 51 return numLEDs;
ehbmbed2 0:12e734116fea 52 }
ehbmbed2 0:12e734116fea 53
heroic 6:7aebe547f0f0 54 void WS2801::blank(void) {
heroic 6:7aebe547f0f0 55 memset(pixels, 0x00, numLEDs * 3);
ehbmbed2 0:12e734116fea 56 }
ehbmbed2 0:12e734116fea 57
ehbmbed2 0:12e734116fea 58 // This is how data is pushed to the strip. Unfortunately, the company
ehbmbed2 0:12e734116fea 59 // that makes the chip didnt release the protocol document or you need
ehbmbed2 0:12e734116fea 60 // to sign an NDA or something stupid like that, but we reverse engineered
ehbmbed2 0:12e734116fea 61 // this from a strip controller and it seems to work very nicely!
heroic 6:7aebe547f0f0 62 void WS2801::show(void) {
ehbmbed2 0:12e734116fea 63 uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED
heroic 6:7aebe547f0f0 64 while (guardtime.read_us() < 500)
heroic 6:7aebe547f0f0 65 /* spin */;
ehbmbed2 0:12e734116fea 66 for (i=0; i<nl3; i++ ) {
heroic 2:af5af64e114d 67 write(pixels[i]);
ehbmbed2 0:12e734116fea 68 }
ehbmbed2 0:12e734116fea 69
heroic 6:7aebe547f0f0 70 guardtime.reset();
ehbmbed2 0:12e734116fea 71 }
ehbmbed2 0:12e734116fea 72
ehbmbed2 0:12e734116fea 73 // Convert R,G,B to combined 32-bit color
heroic 6:7aebe547f0f0 74 uint32_t WS2801::Color(uint8_t r, uint8_t g, uint8_t b) {
ehbmbed2 0:12e734116fea 75 // Take the lowest 7 bits of each value and append them end to end
ehbmbed2 0:12e734116fea 76 // We have the top bit set high (its a 'parity-like' bit in the protocol
ehbmbed2 0:12e734116fea 77 // and must be set!)
heroic 6:7aebe547f0f0 78 return ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b;
ehbmbed2 0:12e734116fea 79 }
ehbmbed2 0:12e734116fea 80
ehbmbed2 0:12e734116fea 81 // store the rgb component in our array
heroic 6:7aebe547f0f0 82 void WS2801::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
ehbmbed2 0:12e734116fea 83 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
ehbmbed2 0:12e734116fea 84
heroic 6:7aebe547f0f0 85 pixels[n*3 ] = g;
heroic 6:7aebe547f0f0 86 pixels[n*3+1] = r;
heroic 6:7aebe547f0f0 87 pixels[n*3+2] = b;
ehbmbed2 0:12e734116fea 88 }
ehbmbed2 0:12e734116fea 89
heroic 6:7aebe547f0f0 90 void WS2801::setPixelR(uint16_t n, uint8_t r) {
heroic 2:af5af64e114d 91 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 2:af5af64e114d 92
heroic 6:7aebe547f0f0 93 pixels[n*3+1] = r;
heroic 2:af5af64e114d 94 }
heroic 2:af5af64e114d 95
heroic 6:7aebe547f0f0 96 void WS2801::setPixelG(uint16_t n, uint8_t g) {
heroic 2:af5af64e114d 97 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 2:af5af64e114d 98
heroic 6:7aebe547f0f0 99 pixels[n*3] = g;
heroic 2:af5af64e114d 100 }
heroic 2:af5af64e114d 101
heroic 6:7aebe547f0f0 102 void WS2801::setPixelB(uint16_t n, uint8_t b) {
heroic 2:af5af64e114d 103 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 2:af5af64e114d 104
heroic 6:7aebe547f0f0 105 pixels[n*3+2] = b;
heroic 2:af5af64e114d 106 }
heroic 2:af5af64e114d 107
heroic 6:7aebe547f0f0 108 void WS2801::setPixelColor(uint16_t n, uint32_t c) {
ehbmbed2 0:12e734116fea 109 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
ehbmbed2 0:12e734116fea 110
heroic 6:7aebe547f0f0 111 pixels[n*3 ] = (c >> 16);
heroic 6:7aebe547f0f0 112 pixels[n*3+1] = (c >> 8);
heroic 6:7aebe547f0f0 113 pixels[n*3+2] = c;
ehbmbed2 0:12e734116fea 114 }