According to the TLC5947 datasheet it has a single 288-bit grayscale register used to control the brightness (and a shadow register, that is actually used for the brightness control).
Now for the 24 channels, each 12 bits you get 288 bits in total.
The spi can only transfer 8 bits, so divide the 288 by 8 and you get 36 bytes.
That being said, create an array of 36 bytes and put your brightness data into that. Following the first 12 bits, you directly append the next 12 bits and so on (not aligned to a byte boundary).
Then you can send the 36 byte array over to the TLC and pull the latch line to latch the new values in.
EDIT:
I don't own a TLC5947, so I couldn't test it with real hardware. I changed the latch pin to pin 10, because that is the slave select pin which has to be an output anyways (not sure, if the spi library does this automatically).
TLC5947 tlc(15000000, 10);
Create a new instance of the tlc device with a speed of 15MHz and the latch pin on pin 10.
tlc.begin();
Initialize the tlc device.
tlc.selectBrightness(23, 4095);
Set the brightness of channel 23 (channel numbers are from 0-23) to 4095 (maximum value). The allowed value range for the brightness is 0-4095.
tlc.updateBrightness();
Send the brightness values to the TLC5947 via spi.
Full working example:
#include <SPI.h>
class TLC5947
{
private:
uint8_t tlcGrayscaleData[36];
SPISettings spiSettings;
uint8_t latchPin;
public:
// Constructor. Needed for initializing the SPISettings instance
TLC5947(uint32_t speed, uint8_t latchPin) : spiSettings(speed, MSBFIRST, SPI_MODE0), latchPin(latchPin) {
}
// Initializes the tlc
void begin()
{
// Initialize the brightness to zero
for(uint8_t i = 0; i < 36; i++) {
tlcGrayscaleData[i] = 0;
}
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin, LOW);
SPI.begin();
}
// Selects a brightness for the provided channel (0-23).
// Brightness values can range from 0-4095 (12 bit)
void selectBrightness(uint8_t channel, uint16_t brightness)
{
// Get the bit position of the channel
uint16_t bitPosition = channel * 12;
// Get the index of the channel in the tlc grayscale array
uint8_t tlcGSArrayIndex = bitPosition / 8;
// put the brightness in the array.
// For this, check if the channel is an even or uneven number
if((channel & 0x1) == 0) {
tlcGrayscaleData[tlcGSArrayIndex] = brightness & 0xFF;
uint8_t temp = tlcGrayscaleData[tlcGSArrayIndex+1];
temp &= 0xF0;
temp |= (brightness >> 8) & 0x0F;
tlcGrayscaleData[tlcGSArrayIndex+1] = temp;
} else {
uint8_t temp = tlcGrayscaleData[tlcGSArrayIndex];
temp &= 0x0F;
temp |= (brightness & 0x0F) << 4;
tlcGrayscaleData[tlcGSArrayIndex] = temp;
tlcGrayscaleData[tlcGSArrayIndex+1] = (brightness >> 4) & 0xFF;
}
}
void updateBrightness()
{
SPI.beginTransaction(spiSettings);
for(int8_t i = 35; i >= 0; i--){
SPI.transfer(tlcGrayscaleData[i]);
}
digitalWrite(latchPin, HIGH);
digitalWrite(latchPin, LOW);
}
};
TLC5947 tlc(15000000, 10);
void setup() {
// put your setup code here, to run once:
tlc.begin();
tlc.selectBrightness(23, 4095);
tlc.selectBrightness(15, 2047);
tlc.updateBrightness();
}
void loop() {
// put your main code here, to run repeatedly:
}