Heroic Robotics / SD600A

Fork of SD600A by Heroic Robotics

Committer:
heroic
Date:
Wed Oct 10 03:57:16 2012 +0000
Revision:
10:d2dd5c752f7b
Parent:
9:f90196d36597
Child:
11:97ef14b4c4de
Make the SD600A library kinda work.  The idle thread's too lumpy and it makes the strip flicker.  BAH.

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 10:d2dd5c752f7b 58 dat = !!(byte & (1 << (7 - i)));
heroic 10:d2dd5c752f7b 59
heroic 8:78ba2917bfd9 60 clk = 1;
heroic 10:d2dd5c752f7b 61 // dat = (byte & 0x80);
heroic 8:78ba2917bfd9 62 #ifdef DELAY_PERIOD
heroic 8:78ba2917bfd9 63 wait_us(DELAY_PERIOD);
heroic 8:78ba2917bfd9 64 #endif
heroic 8:78ba2917bfd9 65 clk = 0;
heroic 8:78ba2917bfd9 66 #ifdef DELAY_PERIOD
heroic 8:78ba2917bfd9 67 wait_us(DELAY_PERIOD);
heroic 8:78ba2917bfd9 68 #endif
heroic 10:d2dd5c752f7b 69 //byte <<= 1;
heroic 2:af5af64e114d 70 }
heroic 2:af5af64e114d 71 }
ehbmbed2 0:12e734116fea 72
heroic 6:aacceefab2ea 73 void SD600A::begin(void) {
ehbmbed2 0:12e734116fea 74 // Issue initial latch to 'wake up' strip (latch length varies w/numLEDs)
heroic 5:c2579d6415e1 75 threadlock.lock();
heroic 5:c2579d6415e1 76 for (int i=0; i<numLEDs; i++) {
heroic 5:c2579d6415e1 77 write(0);
heroic 5:c2579d6415e1 78 write(0);
heroic 5:c2579d6415e1 79 write(0);
heroic 5:c2579d6415e1 80 }
heroic 5:c2579d6415e1 81 writeguard();
heroic 5:c2579d6415e1 82 threadlock.unlock();
ehbmbed2 0:12e734116fea 83 }
ehbmbed2 0:12e734116fea 84
heroic 6:aacceefab2ea 85 uint16_t SD600A::numPixels(void) {
ehbmbed2 0:12e734116fea 86 return numLEDs;
ehbmbed2 0:12e734116fea 87 }
ehbmbed2 0:12e734116fea 88
heroic 6:aacceefab2ea 89 void SD600A::writeguard(void) {
heroic 10:d2dd5c752f7b 90 // generate a 25-bit word of ones
heroic 5:c2579d6415e1 91 clk = 1;
heroic 8:78ba2917bfd9 92 #ifdef DELAY_PERIOD
heroic 8:78ba2917bfd9 93 wait_us(DELAY_PERIOD);
heroic 8:78ba2917bfd9 94 #endif
heroic 10:d2dd5c752f7b 95 dat = 0;
heroic 8:78ba2917bfd9 96 #ifdef DELAY_PERIOD
heroic 8:78ba2917bfd9 97 wait_us(DELAY_PERIOD);
heroic 8:78ba2917bfd9 98 #endif
heroic 5:c2579d6415e1 99 clk = 0;
heroic 8:78ba2917bfd9 100 #ifdef DELAY_PERIOD
heroic 8:78ba2917bfd9 101 wait_us(DELAY_PERIOD);
heroic 8:78ba2917bfd9 102 #endif
heroic 8:78ba2917bfd9 103 write(0xff);
heroic 8:78ba2917bfd9 104 write(0xff);
heroic 8:78ba2917bfd9 105 write(0xff);
heroic 2:af5af64e114d 106 }
heroic 2:af5af64e114d 107
heroic 6:aacceefab2ea 108 void SD600A::blank(void) {
heroic 8:78ba2917bfd9 109 memset(pixels, 0x00, numLEDs * 3);
ehbmbed2 0:12e734116fea 110 }
ehbmbed2 0:12e734116fea 111
ehbmbed2 0:12e734116fea 112 // This is how data is pushed to the strip. Unfortunately, the company
ehbmbed2 0:12e734116fea 113 // that makes the chip didnt release the protocol document or you need
ehbmbed2 0:12e734116fea 114 // to sign an NDA or something stupid like that, but we reverse engineered
ehbmbed2 0:12e734116fea 115 // this from a strip controller and it seems to work very nicely!
heroic 6:aacceefab2ea 116 void SD600A::show(void) {
ehbmbed2 0:12e734116fea 117 uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED
heroic 5:c2579d6415e1 118 threadlock.lock();
ehbmbed2 0:12e734116fea 119
ehbmbed2 0:12e734116fea 120 for (i=0; i<nl3; i++ ) {
heroic 2:af5af64e114d 121 write(pixels[i]);
ehbmbed2 0:12e734116fea 122 }
ehbmbed2 0:12e734116fea 123
heroic 5:c2579d6415e1 124 // Write guard word
heroic 5:c2579d6415e1 125 writeguard();
heroic 5:c2579d6415e1 126 threadlock.unlock();
ehbmbed2 0:12e734116fea 127 }
ehbmbed2 0:12e734116fea 128
ehbmbed2 0:12e734116fea 129 // Convert R,G,B to combined 32-bit color
heroic 6:aacceefab2ea 130 uint32_t SD600A::Color(uint8_t r, uint8_t g, uint8_t b) {
heroic 5:c2579d6415e1 131 // Take 23 bits of the value and append them end to end
heroic 10:d2dd5c752f7b 132 // We cannot drive all ones or it will make the part latch if the previous word ended in one!
heroic 10:d2dd5c752f7b 133 return 0xfefefe & ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b;
ehbmbed2 0:12e734116fea 134 }
ehbmbed2 0:12e734116fea 135
ehbmbed2 0:12e734116fea 136 // store the rgb component in our array
heroic 6:aacceefab2ea 137 void SD600A::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
ehbmbed2 0:12e734116fea 138 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
ehbmbed2 0:12e734116fea 139
heroic 10:d2dd5c752f7b 140 pixels[n*3 ] = g & 0xfe;
heroic 10:d2dd5c752f7b 141 pixels[n*3+1] = r & 0xfe;
heroic 5:c2579d6415e1 142 pixels[n*3+2] = b & 0xfe;
ehbmbed2 0:12e734116fea 143 }
ehbmbed2 0:12e734116fea 144
heroic 6:aacceefab2ea 145 void SD600A::setPixelR(uint16_t n, uint8_t r) {
heroic 2:af5af64e114d 146 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 2:af5af64e114d 147
heroic 10:d2dd5c752f7b 148 pixels[n*3+1] = r & 0xfe;
heroic 2:af5af64e114d 149 }
heroic 2:af5af64e114d 150
heroic 6:aacceefab2ea 151 void SD600A::setPixelG(uint16_t n, uint8_t g) {
heroic 2:af5af64e114d 152 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 2:af5af64e114d 153
heroic 10:d2dd5c752f7b 154 pixels[n*3] = g & 0xfe;
heroic 2:af5af64e114d 155 }
heroic 2:af5af64e114d 156
heroic 6:aacceefab2ea 157 void SD600A::setPixelB(uint16_t n, uint8_t b) {
heroic 2:af5af64e114d 158 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 2:af5af64e114d 159
heroic 5:c2579d6415e1 160 pixels[n*3+2] = b & 0xfe;
heroic 2:af5af64e114d 161 }
heroic 2:af5af64e114d 162
heroic 6:aacceefab2ea 163 void SD600A::setPixelColor(uint16_t n, uint32_t c) {
ehbmbed2 0:12e734116fea 164 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
ehbmbed2 0:12e734116fea 165
heroic 10:d2dd5c752f7b 166 pixels[n*3 ] = (c >> 16) & 0xfe;
heroic 10:d2dd5c752f7b 167 pixels[n*3+1] = (c >> 8) & 0xfe;
heroic 5:c2579d6415e1 168 pixels[n*3+2] = c & 0xfe;
ehbmbed2 0:12e734116fea 169 }