Library for LPD8806 (and probably LPD8803/LPD8809) PWM LED driver chips, strips and pixels. Standard connected to 1st hardware SPI module. Data -> p5 and Clock -> p7 use a fixed sized buffer rather than malloc - if we use malloc rtos is unhappy...

Fork of LPD8806 by Jelmer Tiete

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LPD8806.cpp Source File

LPD8806.cpp

00001 // Mbed library to control LPD8806-based RGB LED Strips
00002 // (c) 2011 Jelmer Tiete
00003 // This library is ported from the Arduino implementation of Adafruit Industries
00004 // found at: http://github.com/adafruit/LPD8806
00005 // and their strips: http://www.adafruit.com/products/306
00006 // Released under the MIT License: http://mbed.org/license/mit
00007 //
00008 // standard connected to 1st hardware SPI
00009 // LPD8806  <> MBED
00010 // DATA     -> P5
00011 // CLOCK    -> p7
00012 /*****************************************************************************/
00013 
00014 #include "LPD8806.h"
00015 
00016 //Define SPI pins
00017 //Connected to first SPI module
00018 SPI spi(p5, p6, p7); // mosi, miso, sclk
00019 //SPI spi(p11, p12, p13); // mosi, miso, sclk
00020 
00021 LPD8806::LPD8806(uint16_t n) {
00022     // Allocate 3 bytes per pixel:
00023 //    if (NULL != (pixels = (uint8_t *)malloc(numLEDs * 3))) {
00024         memset(pixels, 0x80, numLEDs * 3); // Init to RGB 'off' state
00025         numLEDs     = n;
00026 //    }
00027 }
00028 
00029 int LPD8806::pixels_ok(void) {
00030     if (pixels != NULL)
00031         return 1;
00032     else
00033         return 0;
00034 }
00035 
00036 void LPD8806::begin(void) {
00037 
00038     // Setup the spi for 8 bit data, low steady state clock,
00039     // first edge capture, with a 2MHz clock rate
00040     spi.format(8,0);
00041     spi.frequency(2000000);
00042 
00043     // Issue initial latch to 'wake up' strip (latch length varies w/numLEDs)
00044     writezeros(3 * ((numLEDs + 63) / 64));
00045 }
00046 
00047 uint16_t LPD8806::numPixels(void) {
00048     return numLEDs;
00049 }
00050 
00051 void LPD8806::writezeros(uint16_t n) {
00052     while (n--) spi.write(0x00);
00053 }
00054 
00055 // This is how data is pushed to the strip.  Unfortunately, the company
00056 // that makes the chip didnt release the  protocol document or you need
00057 // to sign an NDA or something stupid like that, but we reverse engineered
00058 // this from a strip controller and it seems to work very nicely!
00059 void LPD8806::show(void) {
00060     uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED
00061 
00062     for (i=0; i<nl3; i++ ) {
00063         spi.write(pixels[i]);
00064     }
00065 
00066     // Write latch at end of data; latch length varies with number of LEDs
00067     writezeros(3 * ((numLEDs + 63) / 64));
00068 
00069     // We need to have a delay here, a few ms seems to do the job
00070     // shorter may be OK as well - need to experiment :(
00071     wait_ms(3);
00072 }
00073 
00074 // Convert R,G,B to combined 32-bit color
00075 uint32_t LPD8806::Color(uint8_t r, uint8_t g, uint8_t b) {
00076     // Take the lowest 7 bits of each value and append them end to end
00077     // We have the top bit set high (its a 'parity-like' bit in the protocol
00078     // and must be set!)
00079     return 0x808080 | ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b;
00080 }
00081 
00082 // store the rgb component in our array
00083 void LPD8806::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
00084     if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
00085 
00086     pixels[(n * 3)    ] = g | 0x80;
00087     pixels[(n * 3) +1 ] = r | 0x80;
00088     pixels[(n * 3) +2 ] = b | 0x80;
00089 }
00090 
00091 void LPD8806::setPixelColor(uint16_t n, uint32_t c) {
00092     if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
00093 
00094     pixels[(n * 3)    ] = ((c >> 16) & 0xff)| 0x80;
00095     pixels[(n * 3) + 1] = ((c >>  8) & 0xff)| 0x80;
00096     pixels[(n * 3) + 2] = ( c        & 0xff)| 0x80;
00097 }