Heroic Robotics / SD600A

Fork of SD600A by Heroic Robotics

SD600A.cpp

Committer:
heroic
Date:
2012-10-11
Revision:
22:222eff98e2af
Parent:
21:cdaee8674e2a
Child:
23:2e60470dd134

File content as of revision 22:222eff98e2af:

// 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"

/*
 * Soft SPI clockout routine.  Triggered every ten 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 SD600A::spi_isr(void) {
    clk = 1;
    dat = pixels[byte_index] & (0x80 >> bit_index);
    clk = 0;
    bit_index++;
    clk = 1;
    dat = pixels[byte_index] & (0x80 >> bit_index);
    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");
    NVIC_SetPriority(TIMER3_IRQn, 0);
    idletoggle.attach_us(this, &SD600A::spi_isr, INTERRUPT_INTERVAL);
}

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.
}

// 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;
}

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;
}