Heroic Robotics / SD600A

Fork of SD600A by Heroic Robotics

Committer:
heroic
Date:
Mon Aug 25 05:17:51 2014 +0000
Revision:
29:0200c63e1158
Parent:
28:a905a4738dd4
Add support for service() method.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
heroic 23:2e60470dd134 1 // Mbed library to control SD600A-based RGB LED Strips
heroic 23:2e60470dd134 2 // Partially based on work (c) 2011 Jelmer Tiete
heroic 23:2e60470dd134 3 //
heroic 23:2e60470dd134 4 // Ported from Arduino by
heroic 23:2e60470dd134 5 // Jas Strong <jasmine@electronpusher.org>
heroic 23:2e60470dd134 6 /*****************************************************************************/
heroic 23:2e60470dd134 7
heroic 23:2e60470dd134 8 #include "rtos.h"
heroic 23:2e60470dd134 9 #include "LedStrip.h"
heroic 23:2e60470dd134 10 #include "SD600A.h"
heroic 23:2e60470dd134 11
heroic 26:98163818a82e 12 SD600ASupervisor::SD600ASupervisor(void) {
heroic 26:98163818a82e 13 numstrips = 0;
heroic 26:98163818a82e 14 byte_index = 0;
heroic 26:98163818a82e 15 bit_index = 0;
heroic 26:98163818a82e 16 }
heroic 26:98163818a82e 17
heroic 26:98163818a82e 18 void SD600ASupervisor::add(SD600A *strip) {
heroic 26:98163818a82e 19 strips[numstrips] = strip;
heroic 26:98163818a82e 20 numstrips++;
heroic 26:98163818a82e 21 if (numstrips == 1) { // this is the first one, set up the interrupt.
heroic 26:98163818a82e 22 data_length = strip->data_length;
heroic 26:98163818a82e 23 NVIC_SetPriority(TIMER3_IRQn, 0);
heroic 26:98163818a82e 24 idletoggle.attach_us(this, &SD600ASupervisor::spi_isr, INTERRUPT_INTERVAL);
heroic 26:98163818a82e 25 }
heroic 26:98163818a82e 26 }
heroic 26:98163818a82e 27
heroic 23:2e60470dd134 28 /*
heroic 25:14e5984d3aae 29 * Soft SPI clockout routine. Triggered every few microseconds,
heroic 23:2e60470dd134 30 * repeatedly clocks out the strip contents. Since each update function
heroic 23:2e60470dd134 31 * actually updates a byte at a time, and the C-m3 peeks the write buffer,
heroic 23:2e60470dd134 32 * there is no need to lock the buffer.
heroic 23:2e60470dd134 33 */
heroic 23:2e60470dd134 34
heroic 26:98163818a82e 35 void SD600ASupervisor::spi_isr(void) {
heroic 26:98163818a82e 36 int i;
heroic 26:98163818a82e 37 SD600A *curstrip;
heroic 26:98163818a82e 38 for (i=0; i<numstrips; i++) {
heroic 26:98163818a82e 39 curstrip = strips[i];
heroic 26:98163818a82e 40 curstrip->clk = 1;
heroic 26:98163818a82e 41 curstrip->dat = curstrip->pixels[byte_index] & (0x80 >> bit_index);
heroic 26:98163818a82e 42 }
heroic 26:98163818a82e 43 for (i=0; i<numstrips; i++)
heroic 26:98163818a82e 44 strips[i]->clk = 0;
heroic 23:2e60470dd134 45 bit_index++;
heroic 26:98163818a82e 46 for (i=0; i<numstrips; i++)
heroic 26:98163818a82e 47 strips[i]->clk = 1;
heroic 26:98163818a82e 48 for (i=0; i<numstrips; i++) {
heroic 26:98163818a82e 49 curstrip = strips[i];
heroic 26:98163818a82e 50 curstrip->dat = curstrip->pixels[byte_index] & (0x80 >> bit_index);
heroic 26:98163818a82e 51 }
heroic 26:98163818a82e 52 for (i=0; i<numstrips; i++)
heroic 26:98163818a82e 53 strips[i]->clk = 0;
heroic 23:2e60470dd134 54 bit_index++;
heroic 23:2e60470dd134 55 if (bit_index == 8) {
heroic 23:2e60470dd134 56 byte_index++;
heroic 23:2e60470dd134 57 bit_index = 0;
heroic 23:2e60470dd134 58 }
heroic 23:2e60470dd134 59 if (byte_index == data_length)
heroic 23:2e60470dd134 60 byte_index = 0;
heroic 23:2e60470dd134 61 }
heroic 23:2e60470dd134 62
heroic 26:98163818a82e 63
heroic 26:98163818a82e 64
heroic 23:2e60470dd134 65 SD600A::SD600A(PinName dataPin, PinName clockPin, int n) :
heroic 23:2e60470dd134 66 dat(dataPin),
heroic 23:2e60470dd134 67 clk(clockPin) {
heroic 23:2e60470dd134 68 // Allocate 3 bytes per pixel:
heroic 23:2e60470dd134 69 numLEDs = n;
heroic 28:a905a4738dd4 70 pixels = (uint8_t *)malloc(4+ numLEDs * 3);
heroic 28:a905a4738dd4 71 if (pixels) {
heroic 23:2e60470dd134 72 memset(pixels, 0, numLEDs * 3); // Init to RGB 'off' state
heroic 23:2e60470dd134 73 pixels[numLEDs*3] = 0x7f;
heroic 23:2e60470dd134 74 pixels[numLEDs*3+1] = 0xff;
heroic 23:2e60470dd134 75 pixels[numLEDs*3+2] = 0xff;
heroic 23:2e60470dd134 76 pixels[numLEDs*3+3] = 0x80;
heroic 23:2e60470dd134 77 data_length = numLEDs*3 +4;
heroic 23:2e60470dd134 78 byte_index = 0;
heroic 23:2e60470dd134 79 bit_index = 0;
heroic 23:2e60470dd134 80 } else error("SD600A could not allocate memory!\r\n");
heroic 23:2e60470dd134 81 }
heroic 23:2e60470dd134 82
heroic 29:0200c63e1158 83 void SD600A::service(void) {
heroic 29:0200c63e1158 84 // nothing
heroic 29:0200c63e1158 85 }
heroic 29:0200c63e1158 86
heroic 23:2e60470dd134 87 void SD600A::begin(void) {
heroic 23:2e60470dd134 88 // Null stub.
heroic 23:2e60470dd134 89 }
heroic 23:2e60470dd134 90
heroic 23:2e60470dd134 91 uint16_t SD600A::numPixels(void) {
heroic 23:2e60470dd134 92 return numLEDs;
heroic 23:2e60470dd134 93 }
heroic 23:2e60470dd134 94
heroic 23:2e60470dd134 95 void SD600A::blank(void) {
heroic 23:2e60470dd134 96 memset(pixels, 0x00, numLEDs * 3);
heroic 23:2e60470dd134 97 }
heroic 23:2e60470dd134 98
heroic 23:2e60470dd134 99 void SD600A::show(void) {
heroic 23:2e60470dd134 100 // Null stub, since shows continuously.
heroic 23:2e60470dd134 101 }
heroic 23:2e60470dd134 102
heroic 23:2e60470dd134 103 uint32_t SD600A::total_luminance(void) {
heroic 23:2e60470dd134 104 uint32_t running_total;
heroic 23:2e60470dd134 105 running_total = 0;
heroic 23:2e60470dd134 106 for (int i=0; i<numLEDs*3; i++)
heroic 23:2e60470dd134 107 running_total += pixels[i];
heroic 23:2e60470dd134 108 return running_total;
heroic 23:2e60470dd134 109 }
heroic 23:2e60470dd134 110
heroic 23:2e60470dd134 111 // Convert R,G,B to combined 32-bit color
heroic 23:2e60470dd134 112 uint32_t SD600A::Color(uint8_t r, uint8_t g, uint8_t b) {
heroic 23:2e60470dd134 113 // Take 23 bits of the value and append them end to end
heroic 23:2e60470dd134 114 // We cannot drive all ones or it will make the part latch if the previous word ended in one!
heroic 23:2e60470dd134 115 return 0xfefefe & ((uint32_t)b << 16) | ((uint32_t)r << 8) | (uint32_t)g;
heroic 23:2e60470dd134 116 }
heroic 23:2e60470dd134 117
heroic 23:2e60470dd134 118 // store the rgb component in our array
heroic 23:2e60470dd134 119 void SD600A::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
heroic 23:2e60470dd134 120 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 23:2e60470dd134 121 n=numLEDs-(n+1);
heroic 23:2e60470dd134 122
heroic 23:2e60470dd134 123 pixels[n*3 ] = g & 0xfe;
heroic 23:2e60470dd134 124 pixels[n*3+1] = b & 0xfe;
heroic 23:2e60470dd134 125 pixels[n*3+2] = r & 0xfe;
heroic 23:2e60470dd134 126 }
heroic 23:2e60470dd134 127
heroic 23:2e60470dd134 128 void SD600A::setPixelR(uint16_t n, uint8_t r) {
heroic 23:2e60470dd134 129 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 23:2e60470dd134 130 n=numLEDs-(n+1);
heroic 23:2e60470dd134 131 pixels[n*3+2] = r & 0xfe;
heroic 23:2e60470dd134 132 }
heroic 23:2e60470dd134 133
heroic 27:6667543f3b28 134 // Set all in one function call, assuming GRB ordering
heroic 27:6667543f3b28 135 void SD600A::setPackedPixels(uint8_t * buffer, uint32_t n) {
heroic 27:6667543f3b28 136 if (n >= numLEDs) return;
heroic 27:6667543f3b28 137 for (int i=0; i<n*3; i++)
heroic 27:6667543f3b28 138 buffer[i] &= 0xfe;
heroic 27:6667543f3b28 139 memcpy(pixels, buffer, (size_t) (n*3));
heroic 27:6667543f3b28 140 }
heroic 27:6667543f3b28 141
heroic 27:6667543f3b28 142
heroic 23:2e60470dd134 143 void SD600A::setPixelG(uint16_t n, uint8_t g) {
heroic 23:2e60470dd134 144 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 23:2e60470dd134 145 n=numLEDs-(n+1);
heroic 23:2e60470dd134 146 pixels[n*3+1] = g & 0xfe;
heroic 23:2e60470dd134 147 }
heroic 23:2e60470dd134 148
heroic 23:2e60470dd134 149 void SD600A::setPixelB(uint16_t n, uint8_t b) {
heroic 23:2e60470dd134 150 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 23:2e60470dd134 151 n=numLEDs-(n+1);
heroic 23:2e60470dd134 152 pixels[n*3] = b & 0xfe;
heroic 23:2e60470dd134 153 }
heroic 23:2e60470dd134 154
heroic 23:2e60470dd134 155 void SD600A::setPixelColor(uint16_t n, uint32_t c) {
heroic 23:2e60470dd134 156 if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
heroic 23:2e60470dd134 157 n=numLEDs-(n+1);
heroic 23:2e60470dd134 158 pixels[n*3 ] = (c >> 16) & 0xfe;
heroic 23:2e60470dd134 159 pixels[n*3+1] = (c >> 8) & 0xfe;
heroic 23:2e60470dd134 160 pixels[n*3+2] = c & 0xfe;
heroic 23:2e60470dd134 161 }