Heroic Robotics / SD600A

Fork of SD600A by Heroic Robotics

Committer:
heroic
Date:
Mon Oct 08 20:47:32 2012 +0000
Revision:
5:c2579d6415e1
Parent:
LPD8806.cpp@4:0b75eb84a6d2
First cut of HL1606 driver.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
heroic 5:c2579d6415e1 1 // Mbed library to control HL1606-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 5:c2579d6415e1 10 #include "HL1606.h"
ehbmbed2 0:12e734116fea 11
heroic 5:c2579d6415e1 12 void idle_function(void const *argument) {
heroic 5:c2579d6415e1 13 while (1) {
heroic 5:c2579d6415e1 14 ((HL1606 *)argument)->threadlock.lock();
heroic 5:c2579d6415e1 15 ((HL1606 *)argument)->dat = 0;
heroic 5:c2579d6415e1 16 ((HL1606 *)argument)->clk = 1;
heroic 5:c2579d6415e1 17 ((HL1606 *)argument)->clk = 0;
heroic 5:c2579d6415e1 18 ((HL1606 *)argument)->clk = 1;
heroic 5:c2579d6415e1 19 ((HL1606 *)argument)->clk = 0;
heroic 5:c2579d6415e1 20 ((HL1606 *)argument)->threadlock.unlock();
heroic 5:c2579d6415e1 21 Thread::yield();
heroic 5:c2579d6415e1 22 }
heroic 5:c2579d6415e1 23 }
heroic 5:c2579d6415e1 24
heroic 5:c2579d6415e1 25 HL1606::HL1606(PinName dataPin, PinName clockPin, int n) :
heroic 2:af5af64e114d 26 dat(dataPin),
heroic 5:c2579d6415e1 27 clk(clockPin),
heroic 5:c2579d6415e1 28 idlethread(idle_function,this) {
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 5:c2579d6415e1 44 void HL1606::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 5:c2579d6415e1 54 void HL1606::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 5:c2579d6415e1 67 uint16_t HL1606::numPixels(void) {
ehbmbed2 0:12e734116fea 68 return numLEDs;
ehbmbed2 0:12e734116fea 69 }
ehbmbed2 0:12e734116fea 70
heroic 5:c2579d6415e1 71 void HL1606::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 5:c2579d6415e1 81 void HL1606::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 5:c2579d6415e1 89 void HL1606::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 5:c2579d6415e1 103 uint32_t HL1606::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 5:c2579d6415e1 110 void HL1606::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 5:c2579d6415e1 118 void HL1606::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 5:c2579d6415e1 124 void HL1606::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 5:c2579d6415e1 130 void HL1606::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 5:c2579d6415e1 136 void HL1606::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 }