LED bus driver on any GPIO pin for addressable RGB LEDs (like NeoPixels or other WS2812 based LEDs)

LEDBus.cpp

Committer:
koengroener
Date:
2017-06-14
Revision:
3:67e68c46daef
Parent:
2:735bb1b9cfc2

File content as of revision 3:67e68c46daef:

#include "LEDBus.h"

LEDBus::LEDBus(PinName wirePin, ColorByteOrder byteOrder, float t0h_us, float t0l_us, float t1h_us, float t1l_us, float tReset_us) : _wire(wirePin)
{
    float ticksPerMicroSecond = SystemCoreClock/MICRO_SECOND;

    _byteOrder = byteOrder;

    _delayT1H = ticksPerMicroSecond * t1h_us;
    _delayT0H = ticksPerMicroSecond * t0h_us;
    _delayT1L = ticksPerMicroSecond * t1l_us;
    _delayT0L = ticksPerMicroSecond * t0l_us;

    _delayReset = ticksPerMicroSecond * tReset_us;

    // Uncomment to see micro controller frequency and delays
//    Serial pc(USBTX, USBRX);
//    pc.printf("%d Hz\n\r", SystemCoreClock);
//    pc.printf("%f ticks/us\n\r", ticksPerMicroSecond);
//    pc.printf("T0H: %d ticks\n\r", _delayT0H);
//    pc.printf("T1H: %d ticks\n\r", _delayT1H);
//    pc.printf("T0L: %d ticks\n\r", _delayT0L);
//    pc.printf("T1L: %d ticks\n\r", _delayT1L);
//    pc.printf("Reset: %d ticks\n\r", _delayReset);
    
}

LEDBus::~LEDBus()
{
}

void LEDBus::write(uint8_t byte)
{
    for (int b = 7; b >= 0; b--) {
        bool bit = byte & (1 << b);

        _wire = 1;

        if (bit) {
            delay(_delayT1H);
        } else {
            delay(_delayT0H);
        }

        _wire = 0;

        if (bit) {
            delay(_delayT1L);
        } else {
            delay(_delayT0L);
        }
    }
}

void LEDBus::delay(unsigned const int ticks)
{
    //loop_ticks is empirically determined (aka: works on my machine...)
    const int loop_ticks = 8;
    for (unsigned volatile int i = 0; i <= ticks-(loop_ticks/2); i+=loop_ticks) {
        /* nop */
    }
}

void LEDBus::write(uint8_t* buffer, unsigned int size)
{
    for (int i = 0; i < size; i++) {
        write(buffer[i]);
    }

    delay(_delayReset);
}

void LEDBus::write(Color** buffer, unsigned int size)
{
    for (int i = 0; i < size; i++) {
        switch(_byteOrder) {
            case RGB:
                write(buffer[i]->red);
                write(buffer[i]->green);
                write(buffer[i]->blue);
                break;
            case RBG:
                write(buffer[i]->red);
                write(buffer[i]->blue);
                write(buffer[i]->green);
                break;
            case GRB:
                write(buffer[i]->green);
                write(buffer[i]->red);
                write(buffer[i]->blue);
                break;
            case GBR:
                write(buffer[i]->green);
                write(buffer[i]->blue);
                write(buffer[i]->red);
                break;
            case BRG:
                write(buffer[i]->blue);
                write(buffer[i]->red);
                write(buffer[i]->green);
            case BGR:
                write(buffer[i]->blue);
                write(buffer[i]->green);
                write(buffer[i]->red);
                break;
        }

    }

    delay(_delayReset);
}


void LEDBus::update(ColorGenerator generator, unsigned int numberOfLEDs)
{
    unsigned char buffer[numberOfLEDs*3];

    for (int i = 0; i < numberOfLEDs; i++) {
        Color* color = new Color();
        generator(color, i);

        int ir,ig,ib;

        switch(_byteOrder) {
            case RGB:
                ir = 0;
                ig = 1;
                ib = 2;
                break;
            case RBG:
                ir = 0;
                ig = 2;
                ib = 1;
                break;
            case GRB:
                ir = 1;
                ig = 0;
                ib = 2;
                break;
            case GBR:
                ir = 2;
                ig = 0;
                ib = 1;
                break;
            case BRG:
                ir = 1;
                ig = 2;
                ib = 0;
            case BGR:
                ir = 2;
                ig = 1;
                ib = 0;
                break;
        }

        buffer[i*3 +ir] = color->red;
        buffer[i*3 +ig] = color->green;
        buffer[i*3 +ib] = color->blue;

        delete color;
    }

    write(buffer, numberOfLEDs*3);
}