SHOHEI FUJIMOTO / LPD8806

Dependents:   LineLedControl LineLedControl2

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