Heroic Robotics / SD600A

Fork of SD600A by Heroic Robotics

Committer:
heroic
Date:
Wed Oct 10 05:41:32 2012 +0000
Revision:
11:97ef14b4c4de
Parent:
10:d2dd5c752f7b
Child:
12:08d02c0aaa67
Fix colour ordering and strip addressing to match LPD8806.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
heroic 11:97ef14b4c4de 1 // Mbed library to control SD600A-based RGB LED Strips
heroic 11:97ef14b4c4de 2 // Partially based on work (c) 2011 Jelmer Tiete
heroic 11:97ef14b4c4de 3 //
heroic 11:97ef14b4c4de 4 // Ported from Arduino by
heroic 11:97ef14b4c4de 5 // Jas Strong <jasmine@electronpusher.org>
heroic 11:97ef14b4c4de 6 /*****************************************************************************/
heroic 11:97ef14b4c4de 7
heroic 11:97ef14b4c4de 8 #include "rtos.h"
heroic 11:97ef14b4c4de 9 #include "LedStrip.h"
heroic 11:97ef14b4c4de 10 #include "SD600A.h"
heroic 11:97ef14b4c4de 11
heroic 11:97ef14b4c4de 12 void SD600A::idle_function(void) {
heroic 11:97ef14b4c4de 13 dat = 0;
heroic 11:97ef14b4c4de 14 clk = !clk;
heroic 11:97ef14b4c4de 15 }
heroic 11:97ef14b4c4de 16
heroic 11:97ef14b4c4de 17 SD600A::SD600A(PinName dataPin, PinName clockPin, int n) :
heroic 11:97ef14b4c4de 18 dat(dataPin),
heroic 11:97ef14b4c4de 19 clk(clockPin) {
heroic 11:97ef14b4c4de 20 // Allocate 3 bytes per pixel:
heroic 11:97ef14b4c4de 21 numLEDs = n;
heroic 11:97ef14b4c4de 22 if ((pixels = (uint8_t *)malloc(numLEDs * 3))) {
heroic 11:97ef14b4c4de 23 memset(pixels, 0, numLEDs * 3); // Init to RGB 'off' state
heroic 11:97ef14b4c4de 24 }
heroic 11:97ef14b4c4de 25 idletoggle.attach_us(this, &SD600A::idle_function, IDLE_INTERVAL);
heroic 11:97ef14b4c4de 26 }
heroic 11:97ef14b4c4de 27
heroic 11:97ef14b4c4de 28 /*
heroic 11:97ef14b4c4de 29 * Soft SPI clock-out implementation (CPOL = 0, CPHA = 1).
heroic 11:97ef14b4c4de 30 * Certainly not the fastest in the world but it'll do.
heroic 11:97ef14b4c4de 31 * Gets about 3.6 MHz; could get several times as much
heroic 11:97ef14b4c4de 32 * using the bitbands directly - jas.
heroic 11:97ef14b4c4de 33 */
heroic 11:97ef14b4c4de 34
heroic 11:97ef14b4c4de 35 void SD600A::write(uint8_t byte) {
heroic 11:97ef14b4c4de 36 clk=1;
heroic 11:97ef14b4c4de 37 for (int i=0; i<8; i++) {
heroic 11:97ef14b4c4de 38 dat = !!(byte & (1 << (7 - i)));
heroic 11:97ef14b4c4de 39
heroic 11:97ef14b4c4de 40 clk = 0;
heroic 11:97ef14b4c4de 41 // dat = (byte & 0x80);
heroic 11:97ef14b4c4de 42 #ifdef DELAY_PERIOD
heroic 11:97ef14b4c4de 43 wait_us(DELAY_PERIOD);
heroic 11:97ef14b4c4de 44 #endif
heroic 11:97ef14b4c4de 45 clk = 1;
heroic 11:97ef14b4c4de 46 #ifdef DELAY_PERIOD
heroic 11:97ef14b4c4de 47 wait_us(DELAY_PERIOD);
heroic 11:97ef14b4c4de 48 #endif
heroic 11:97ef14b4c4de 49 //byte <<= 1;
heroic 11:97ef14b4c4de 50 }
heroic 11:97ef14b4c4de 51 }
heroic 11:97ef14b4c4de 52
heroic 11:97ef14b4c4de 53 void SD600A::begin(void) {
heroic 11:97ef14b4c4de 54 // Issue initial latch to 'wake up' strip (latch length varies w/numLEDs)
heroic 11:97ef14b4c4de 55 idletoggle.detach();
heroic 11:97ef14b4c4de 56 for (int i=0; i<numLEDs; i++) {
heroic 11:97ef14b4c4de 57 write(0);
heroic 11:97ef14b4c4de 58 write(0);
heroic 11:97ef14b4c4de 59 write(0);
heroic 11:97ef14b4c4de 60 }
heroic 11:97ef14b4c4de 61 writeguard();
heroic 11:97ef14b4c4de 62 idletoggle.attach_us(this, &SD600A::idle_function, IDLE_INTERVAL);
heroic 11:97ef14b4c4de 63 }
heroic 11:97ef14b4c4de 64
heroic 11:97ef14b4c4de 65 uint16_t SD600A::numPixels(void) {
heroic 11:97ef14b4c4de 66 return numLEDs;
heroic 11:97ef14b4c4de 67 }
heroic 11:97ef14b4c4de 68
heroic 11:97ef14b4c4de 69 void SD600A::writeguard(void) {
heroic 11:97ef14b4c4de 70 // generate a 25-bit word of ones
heroic 11:97ef14b4c4de 71 clk = 0;
heroic 11:97ef14b4c4de 72 #ifdef DELAY_PERIOD
heroic 11:97ef14b4c4de 73 wait_us(DELAY_PERIOD);
heroic 11:97ef14b4c4de 74 #endif
heroic 11:97ef14b4c4de 75 dat = 1;
heroic 11:97ef14b4c4de 76 #ifdef DELAY_PERIOD
heroic 11:97ef14b4c4de 77 wait_us(DELAY_PERIOD);
heroic 11:97ef14b4c4de 78 #endif
heroic 11:97ef14b4c4de 79 clk = 1;
heroic 11:97ef14b4c4de 80 #ifdef DELAY_PERIOD
heroic 11:97ef14b4c4de 81 wait_us(DELAY_PERIOD);
heroic 11:97ef14b4c4de 82 #endif
heroic 11:97ef14b4c4de 83 write(0xff);
heroic 11:97ef14b4c4de 84 write(0xff);
heroic 11:97ef14b4c4de 85 write(0xff);
heroic 11:97ef14b4c4de 86 }
heroic 11:97ef14b4c4de 87
heroic 11:97ef14b4c4de 88 void SD600A::blank(void) {
heroic 11:97ef14b4c4de 89 memset(pixels, 0x00, numLEDs * 3);
heroic 11:97ef14b4c4de 90 }
heroic 11:97ef14b4c4de 91
heroic 11:97ef14b4c4de 92 // This is how data is pushed to the strip. Unfortunately, the company
heroic 11:97ef14b4c4de 93 // that makes the chip didnt release the protocol document or you need
heroic 11:97ef14b4c4de 94 // to sign an NDA or something stupid like that, but we reverse engineered
heroic 11:97ef14b4c4de 95 // this from a strip controller and it seems to work very nicely!
heroic 11:97ef14b4c4de 96 void SD600A::show(void) {
heroic 11:97ef14b4c4de 97 uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED
heroic 11:97ef14b4c4de 98 idletoggle.detach();
heroic 11:97ef14b4c4de 99
heroic 11:97ef14b4c4de 100 for (i=nl3; i; i-- ) {
heroic 11:97ef14b4c4de 101 write(pixels[i]);
heroic 11:97ef14b4c4de 102 }
heroic 11:97ef14b4c4de 103
heroic 11:97ef14b4c4de 104 // Write guard word
heroic 11:97ef14b4c4de 105 writeguard();
heroic 11:97ef14b4c4de 106 idletoggle.attach_us(this, &SD600A::idle_function, IDLE_INTERVAL);
heroic 11:97ef14b4c4de 107 }
heroic 11:97ef14b4c4de 108
heroic 11:97ef14b4c4de 109 // Convert R,G,B to combined 32-bit color
heroic 11:97ef14b4c4de 110 uint32_t SD600A::Color(uint8_t r, uint8_t g, uint8_t b) {
heroic 11:97ef14b4c4de 111 // Take 23 bits of the value and append them end to end
heroic 11:97ef14b4c4de 112 // We cannot drive all ones or it will make the part latch if the previous word ended in one!
heroic 11:97ef14b4c4de 113 return 0xfefefe & ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b;
heroic 11:97ef14b4c4de 114 }
heroic 11:97ef14b4c4de 115
heroic 11:97ef14b4c4de 116 // store the rgb component in our array
heroic 11:97ef14b4c4de 117 void SD600A::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
heroic 11:97ef14b4c4de 118 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 11:97ef14b4c4de 119
heroic 11:97ef14b4c4de 120 pixels[n*3 ] = b & 0xfe;
heroic 11:97ef14b4c4de 121 pixels[n*3+1] = g & 0xfe;
heroic 11:97ef14b4c4de 122 pixels[n*3+2] = r & 0xfe;
heroic 11:97ef14b4c4de 123 }
heroic 11:97ef14b4c4de 124
heroic 11:97ef14b4c4de 125 void SD600A::setPixelR(uint16_t n, uint8_t r) {
heroic 11:97ef14b4c4de 126 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 11:97ef14b4c4de 127
heroic 11:97ef14b4c4de 128 pixels[n*3+2] = r & 0xfe;
heroic 11:97ef14b4c4de 129 }
heroic 11:97ef14b4c4de 130
heroic 11:97ef14b4c4de 131 void SD600A::setPixelG(uint16_t n, uint8_t g) {
heroic 11:97ef14b4c4de 132 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 11:97ef14b4c4de 133
heroic 11:97ef14b4c4de 134 pixels[n*3+1] = g & 0xfe;
heroic 11:97ef14b4c4de 135 }
heroic 11:97ef14b4c4de 136
heroic 11:97ef14b4c4de 137 void SD600A::setPixelB(uint16_t n, uint8_t b) {
heroic 11:97ef14b4c4de 138 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 11:97ef14b4c4de 139
heroic 11:97ef14b4c4de 140 pixels[n*3] = b & 0xfe;
heroic 11:97ef14b4c4de 141 }
heroic 11:97ef14b4c4de 142
heroic 11:97ef14b4c4de 143 void SD600A::setPixelColor(uint16_t n, uint32_t c) {
heroic 11:97ef14b4c4de 144 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 11:97ef14b4c4de 145
heroic 11:97ef14b4c4de 146 pixels[n*3 ] = (c >> 16) & 0xfe;
heroic 11:97ef14b4c4de 147 pixels[n*3+1] = (c >> 8) & 0xfe;
heroic 11:97ef14b4c4de 148 pixels[n*3+2] = c & 0xfe;
heroic 11:97ef14b4c4de 149 }