jars121
Posts: 119
Joined: Tue Jun 25, 2013 8:35 pm

Sending data to a device register with c++ (Linux)

Fri May 18, 2018 2:09 am

I'm attempting to interface with a TLC5971 RGB LED driver, the datasheet for which is here.

I've used this Arduino example as a guide, but I'm unable to make it work on my RPi2. I have 3 LED drivers in series, but am trying to communicate with a single driver to start with.

Below is what I have so far.

ledRegister.h:

Code: Select all

class ledRegister : public QObject
{
    Q_OBJECT
public:
    ledRegister();

    int data = 5;
    int clock = 6;
    int bytes = 28;
    int registers = 1;

    char packets[28];

    std::string export = "/sys/class/gpio/export";
    std::string direction = "out";

    int setup();
    int writeLEDRegister(QVariantList array, unsigned char brightness);

signals:

private:
    int header(unsigned char brightness);
    int data(QVariantList array);
    int writeregister();

public slots:
};
ledRegister.cpp:

Code: Select all

ledRegister::ledRegister()
{

}

int ledRegister::setup()
{
    //Export clock pin
    int openexport = open(this->export.c_str(), O_WRONLY|O_SYNC);
    write(openexport, std::to_string(this->clock).c_str(), std::to_string(this->clock).length());
    close(openexport);

    //Set clock pin direction
    string clockdirection = "/sys/class/gpio/gpio" + std::to_string(this->clock) + "/direction";
    int openclockdirection = open(clockdirection.c_str(), O_WRONLY|O_SYNC);
    write(openclockdirection, this->direction.c_str(), this->direction.length());
    close(openclockdirection);

    //Export data pin
    int openexport = open(this->export.c_str(), O_WRONLY|O_SYNC);
    write(openexport, std::to_string(this->data).c_str(), std::to_string(this->data).length());
    close(openexport);

    //Set data pin direction
    string datadirection = "/sys/class/gpio/gpio" + std::to_string(this->data) + "/direction";
    int opendatadirection = open(datadirection.c_str(), O_WRONLY|O_SYNC);
    write(opendatadirection, this->direction.c_str(), this->direction.length());
    close(opendatadirection);

}

ledRegister::header(unsigned char brightness)
{
    long packetheader = 0b100101011000 << 21;

    //packetheader = 'start' command bits (1001010) and
    //header bits: 1: rising edge timing
                 //1: external clock
                 //0: counter not reset
                 //0: auto repeater off
                 //0: blank off

    brightness >>= 1;
    packetheader |= brightness;
    packetheader |= (long)brightness << 7;
    packetheader |= (long)brightness << 7*2;

    this->packets[0] = packetheader >> 8*3;
    this->packets[1] = packetheader >> 8*2;
    this->packets[2] = packetheader >> 8;
    this->packets[3] = packetheader;
}

ledRegister::data(QVariantList array)
{
    //MSB -> LSB of the colour register is B3, G3, R3, ... , B0, G0, R0
    for (int i(0); i < 12; i++) {
        int ledref;
        int rgbref;

        if (i == 0 || i == 1 || i == 2) {
            ledref = 3;
            rgbref = 2 - i;
        } else if (i == 3 || i == 4 || i == 5) {
            ledref = 2;
            rgbref = 5 - i;
        } else if (i == 6 || i == 7 || i == 8) {
            ledref = 1;
            rgbref = 9 - i;
        } else {
            ledref = 0;
            rgbref = 11 - i;
        }

        //array is structured as [(R0, G0, B0), ... ,(R3, G3, B3)]
        //which is why the above code swaps the order so that the MSB
        //of the data starts with B3, with the LSB being R0
        int val = array.at(ledref).toStringList().at(rgbref).toInt();

        this->packets[i*2 + 4] = val >> 8;
        this->packets[i*2 + 5] = val;
    }
}

ledRegister::writeregister()
{
    for (int i(0); i < this->bytes; i++) {
        for (int j(0); j < 8; j++) {

            string datadirectory = "/sys/class/gpio/gpio" + std::to_string(this->data) + "/value";

            int opendatavalue = open(datadirectory.c_str(), O_WRONLY|O_SYNC);

            int bitdata = !!(this->packets[i] & (1 << (7 - j)));
            write(opendatavalue, std::to_string(bitData).c_str(), std::to_string(bitData).length());
            close(opendatavalue);

            //Toggle clock HIGH then LOW;
            string clockdirectory = "/sys/class/gpio/gpio" + std::to_string(this->clock) + "/value";

            int openclockvalue = open(clockdirectory.c_str(), O_WRONLY|O_SYNC);
            write(openclockvalue, std::to_string(1).c_str(), std::to_string(1).length());
            close(openclockvalue);

            openclockvalue = open(clockdirectory.c_str(), O_WRONLY|O_SYNC);
            write(openclockvalue, std::to_string(0).c_str(), std::to_string(0).length());
            close(openclockvalue);
        }
    }
}

ledRegister::writeLEDRegister(QVariantList array, unsigned char brightness)
{
    for (int i(0); i < this->registers; i++) {
        header(brightness);
        data(array);
    }

    for (int i(0); i < this->registers; i++) {
        writeregister();
    }
}
As you can see, the approach is as follows:
  1. Set the data and clock GPIO pins as outputs
  2. Package the 224 bits (32 bit header, 192 bit data)
  3. For each bit, set the data pin as either HIGH (1) or LOW (0)
  4. After each bit is set, toggle the clock pin as HIGH (1) then LOW (0)
At this stage I'm not receiving any errors in my code. I have confirmed power at the common anode of each LED, and can activate each colour of each LED manually, so I don't believe there's any issue with the circuit. It would appear that my code is erroneous, and is not enabling the TLC5971 to sink the required current for each cathode of each LED. I.e. the TLC5971 should be 'switching' the GND for each LED, which it is not doing.

Any guidance, input or otherwise would be most appreciated; I've been pouring over this for the last day and a half, and can't think of what else to try at this point.

jars121
Posts: 119
Joined: Tue Jun 25, 2013 8:35 pm

Re: Sending data to a device register with c++ (Linux)

Fri May 18, 2018 3:12 am

Never mind, I had an additional bit in the header by mistake!

Return to “Interfacing (DSI, CSI, I2C, etc.)”

Who is online

Users browsing this forum: No registered users and 6 guests