Heroic Robotics / SD600A

Fork of SD600A by Heroic Robotics

SD600A.cpp

Committer:
heroic
Date:
2013-04-11
Revision:
27:6667543f3b28
Parent:
26:98163818a82e
Child:
28:a905a4738dd4

File content as of revision 27:6667543f3b28:

// Mbed library to control SD600A-based RGB LED Strips
// Partially based on work (c) 2011 Jelmer Tiete
//
// Ported from Arduino by
// Jas Strong <jasmine@electronpusher.org>
/*****************************************************************************/

#include "rtos.h"
#include "LedStrip.h"
#include "SD600A.h"

SD600ASupervisor::SD600ASupervisor(void) {
    numstrips = 0;
    byte_index = 0;
    bit_index = 0;
}

void SD600ASupervisor::add(SD600A *strip) {
    strips[numstrips] = strip;
    numstrips++;
    if (numstrips == 1) { // this is the first one, set up the interrupt.
        data_length = strip->data_length;
        NVIC_SetPriority(TIMER3_IRQn, 0);
        idletoggle.attach_us(this, &SD600ASupervisor::spi_isr, INTERRUPT_INTERVAL);
    }
}

/*
 * Soft SPI clockout routine.  Triggered every few microseconds,
 * repeatedly clocks out the strip contents.  Since each update function
 * actually updates a byte at a time, and the C-m3 peeks the write buffer,
 * there is no need to lock the buffer.
 */

void SD600ASupervisor::spi_isr(void) {
    int i;
    SD600A *curstrip;
    for (i=0; i<numstrips; i++) {
        curstrip = strips[i];
        curstrip->clk = 1;
        curstrip->dat = curstrip->pixels[byte_index] & (0x80 >> bit_index);
    }
    for (i=0; i<numstrips; i++) 
        strips[i]->clk = 0;
    bit_index++;
    for (i=0; i<numstrips; i++) 
        strips[i]->clk = 1;
    for (i=0; i<numstrips; i++) {
        curstrip = strips[i];
        curstrip->dat = curstrip->pixels[byte_index] & (0x80 >> bit_index);
    }
    for (i=0; i<numstrips; i++) 
        strips[i]->clk = 0;
    bit_index++;
    if (bit_index == 8) {
        byte_index++;
        bit_index = 0;
    }
    if (byte_index == data_length)
        byte_index = 0;
}



SD600A::SD600A(PinName dataPin, PinName clockPin, int n) :
    dat(dataPin),
    clk(clockPin)  {
    // Allocate 3 bytes per pixel:
    numLEDs = n;
    if ((pixels = (uint8_t *)malloc(4+ numLEDs * 3))) {
        memset(pixels, 0, numLEDs * 3); // Init to RGB 'off' state
        pixels[numLEDs*3] = 0x7f;
        pixels[numLEDs*3+1] = 0xff;
        pixels[numLEDs*3+2] = 0xff;
        pixels[numLEDs*3+3] = 0x80;
        data_length = numLEDs*3 +4;
        byte_index = 0;
        bit_index = 0;
    } else error("SD600A could not allocate memory!\r\n");
}

void SD600A::begin(void) {
 // Null stub.
}

uint16_t SD600A::numPixels(void) {
    return numLEDs;
}

void SD600A::blank(void) {
    memset(pixels, 0x00, numLEDs * 3);
}

void SD600A::show(void) {
   // Null stub, since shows continuously.
}

uint32_t SD600A::total_luminance(void) {
    uint32_t running_total;
    running_total = 0;
    for (int i=0; i<numLEDs*3; i++)
        running_total += pixels[i];
    return running_total;
}

// Convert R,G,B to combined 32-bit color
uint32_t SD600A::Color(uint8_t r, uint8_t g, uint8_t b) {
    // Take 23 bits of the value and append them end to end
    // We cannot drive all ones or it will make the part latch if the previous word ended in one!
    return 0xfefefe & ((uint32_t)b << 16) | ((uint32_t)r << 8) | (uint32_t)g;
}

// store the rgb component in our array
void SD600A::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
    n=numLEDs-(n+1);

    pixels[n*3  ] = g & 0xfe;
    pixels[n*3+1] = b & 0xfe;
    pixels[n*3+2] = r & 0xfe;
}

void SD600A::setPixelR(uint16_t n, uint8_t r) {
    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
    n=numLEDs-(n+1);
    pixels[n*3+2] = r & 0xfe;
}

// Set all in one function call, assuming GRB ordering
void SD600A::setPackedPixels(uint8_t * buffer, uint32_t n) {
    if (n >= numLEDs) return;
    for (int i=0; i<n*3; i++)
        buffer[i] &= 0xfe;
    memcpy(pixels, buffer, (size_t) (n*3));
}


void SD600A::setPixelG(uint16_t n, uint8_t g) {
    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
    n=numLEDs-(n+1);
    pixels[n*3+1] = g & 0xfe;
}

void SD600A::setPixelB(uint16_t n, uint8_t b) {
    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
    n=numLEDs-(n+1);
    pixels[n*3] = b & 0xfe;
}

void SD600A::setPixelColor(uint16_t n, uint32_t c) {
    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
    n=numLEDs-(n+1);
    pixels[n*3  ] = (c >> 16) & 0xfe;
    pixels[n*3+1] = (c >>  8) & 0xfe;
    pixels[n*3+2] =  c        & 0xfe;
}