my small LPD8806
Fork of LPD8806 by
LPD8806.cpp@0:12e734116fea, 2011-12-16 (annotated)
- Committer:
- ehbmbed2
- Date:
- Fri Dec 16 03:16:50 2011 +0000
- Revision:
- 0:12e734116fea
- Child:
- 1:6ebd3ac910b6
first revision, works, needs to be tested on long strands
Who changed what in which revision?
User | Revision | Line number | New 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 | 0:12e734116fea | 7 | |
ehbmbed2 | 0:12e734116fea | 8 | /*****************************************************************************/ |
ehbmbed2 | 0:12e734116fea | 9 | |
ehbmbed2 | 0:12e734116fea | 10 | #include "LPD8806.h" |
ehbmbed2 | 0:12e734116fea | 11 | |
ehbmbed2 | 0:12e734116fea | 12 | //Define SPI pins |
ehbmbed2 | 0:12e734116fea | 13 | SPI spi(p5, p6, p7); // mosi, miso, sclk |
ehbmbed2 | 0:12e734116fea | 14 | //SPI spi(p11, p12, p13); // mosi, miso, sclk |
ehbmbed2 | 0:12e734116fea | 15 | |
ehbmbed2 | 0:12e734116fea | 16 | LPD8806::LPD8806(uint16_t n) { |
ehbmbed2 | 0:12e734116fea | 17 | // Allocate 3 bytes per pixel: |
ehbmbed2 | 0:12e734116fea | 18 | if (NULL != (pixels = (uint8_t *)malloc(numLEDs * 3))) { |
ehbmbed2 | 0:12e734116fea | 19 | memset(pixels, 0x80, numLEDs * 3); // Init to RGB 'off' state |
ehbmbed2 | 0:12e734116fea | 20 | numLEDs = n; |
ehbmbed2 | 0:12e734116fea | 21 | } |
ehbmbed2 | 0:12e734116fea | 22 | } |
ehbmbed2 | 0:12e734116fea | 23 | |
ehbmbed2 | 0:12e734116fea | 24 | void LPD8806::begin(void) { |
ehbmbed2 | 0:12e734116fea | 25 | |
ehbmbed2 | 0:12e734116fea | 26 | // Setup the spi for 8 bit data, low steady state clock, |
ehbmbed2 | 0:12e734116fea | 27 | // first edge capture, with a 2MHz clock rate |
ehbmbed2 | 0:12e734116fea | 28 | spi.format(8,0); |
ehbmbed2 | 0:12e734116fea | 29 | spi.frequency(2000000); |
ehbmbed2 | 0:12e734116fea | 30 | |
ehbmbed2 | 0:12e734116fea | 31 | // Issue initial latch to 'wake up' strip (latch length varies w/numLEDs) |
ehbmbed2 | 0:12e734116fea | 32 | writezeros(3 * ((numLEDs + 63) / 64)); |
ehbmbed2 | 0:12e734116fea | 33 | } |
ehbmbed2 | 0:12e734116fea | 34 | |
ehbmbed2 | 0:12e734116fea | 35 | uint16_t LPD8806::numPixels(void) { |
ehbmbed2 | 0:12e734116fea | 36 | return numLEDs; |
ehbmbed2 | 0:12e734116fea | 37 | } |
ehbmbed2 | 0:12e734116fea | 38 | |
ehbmbed2 | 0:12e734116fea | 39 | void LPD8806::writezeros(uint16_t n) { |
ehbmbed2 | 0:12e734116fea | 40 | while (n--) spi.write(0x00); |
ehbmbed2 | 0:12e734116fea | 41 | } |
ehbmbed2 | 0:12e734116fea | 42 | |
ehbmbed2 | 0:12e734116fea | 43 | // This is how data is pushed to the strip. Unfortunately, the company |
ehbmbed2 | 0:12e734116fea | 44 | // that makes the chip didnt release the protocol document or you need |
ehbmbed2 | 0:12e734116fea | 45 | // to sign an NDA or something stupid like that, but we reverse engineered |
ehbmbed2 | 0:12e734116fea | 46 | // this from a strip controller and it seems to work very nicely! |
ehbmbed2 | 0:12e734116fea | 47 | void LPD8806::show(void) { |
ehbmbed2 | 0:12e734116fea | 48 | uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED |
ehbmbed2 | 0:12e734116fea | 49 | |
ehbmbed2 | 0:12e734116fea | 50 | for (i=0; i<nl3; i++ ) { |
ehbmbed2 | 0:12e734116fea | 51 | spi.write(pixels[i]); |
ehbmbed2 | 0:12e734116fea | 52 | } |
ehbmbed2 | 0:12e734116fea | 53 | |
ehbmbed2 | 0:12e734116fea | 54 | // Write latch at end of data; latch length varies with number of LEDs |
ehbmbed2 | 0:12e734116fea | 55 | writezeros(3 * ((numLEDs + 63) / 64)); |
ehbmbed2 | 0:12e734116fea | 56 | |
ehbmbed2 | 0:12e734116fea | 57 | // We need to have a delay here, a few ms seems to do the job |
ehbmbed2 | 0:12e734116fea | 58 | // shorter may be OK as well - need to experiment :( |
ehbmbed2 | 0:12e734116fea | 59 | // wait_ms(3); |
ehbmbed2 | 0:12e734116fea | 60 | } |
ehbmbed2 | 0:12e734116fea | 61 | |
ehbmbed2 | 0:12e734116fea | 62 | // Convert R,G,B to combined 32-bit color |
ehbmbed2 | 0:12e734116fea | 63 | uint32_t LPD8806::Color(uint8_t r, uint8_t g, uint8_t b) { |
ehbmbed2 | 0:12e734116fea | 64 | // Take the lowest 7 bits of each value and append them end to end |
ehbmbed2 | 0:12e734116fea | 65 | // We have the top bit set high (its a 'parity-like' bit in the protocol |
ehbmbed2 | 0:12e734116fea | 66 | // and must be set!) |
ehbmbed2 | 0:12e734116fea | 67 | return 0x808080 | ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b; |
ehbmbed2 | 0:12e734116fea | 68 | } |
ehbmbed2 | 0:12e734116fea | 69 | |
ehbmbed2 | 0:12e734116fea | 70 | // store the rgb component in our array |
ehbmbed2 | 0:12e734116fea | 71 | void LPD8806::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) { |
ehbmbed2 | 0:12e734116fea | 72 | if (n >= numLEDs) return; // '>=' because arrays are 0-indexed |
ehbmbed2 | 0:12e734116fea | 73 | |
ehbmbed2 | 0:12e734116fea | 74 | pixels[n*3 ] = g | 0x80; |
ehbmbed2 | 0:12e734116fea | 75 | pixels[n*3+1] = r | 0x80; |
ehbmbed2 | 0:12e734116fea | 76 | pixels[n*3+2] = b | 0x80; |
ehbmbed2 | 0:12e734116fea | 77 | } |
ehbmbed2 | 0:12e734116fea | 78 | |
ehbmbed2 | 0:12e734116fea | 79 | void LPD8806::setPixelColor(uint16_t n, uint32_t c) { |
ehbmbed2 | 0:12e734116fea | 80 | if (n >= numLEDs) return; // '>=' because arrays are 0-indexed |
ehbmbed2 | 0:12e734116fea | 81 | |
ehbmbed2 | 0:12e734116fea | 82 | pixels[n*3 ] = (c >> 16) | 0x80; |
ehbmbed2 | 0:12e734116fea | 83 | pixels[n*3+1] = (c >> 8) | 0x80; |
ehbmbed2 | 0:12e734116fea | 84 | pixels[n*3+2] = c | 0x80; |
ehbmbed2 | 0:12e734116fea | 85 | } |