Heroic Robotics / SD600A

Fork of SD600A by Heroic Robotics

Committer:
heroic
Date:
Mon Oct 08 23:41:38 2012 +0000
Revision:
7:cda3ca93e5a1
Parent:
6:aacceefab2ea
Child:
8:78ba2917bfd9
Reduce stack size of idler thread

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