Heroic Robotics / SD600A

Fork of SD600A by Heroic Robotics

Committer:
heroic
Date:
Wed Oct 10 03:21:16 2012 +0000
Revision:
9:f90196d36597
Parent:
8:78ba2917bfd9
Child:
10:d2dd5c752f7b
Really fix guard word, seriously this time.

Who changed what in which revision?

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