/*Ti 5940 16-port LED driver
= overlapped fade across 16 LEDs at a low background level
* Peter Mackey June 2007 Pratt Digital Arts pmackey@pratt.edu
* smooth flickerless fading (thanks to Amp on the Arduino forum)
* additional logic from David Cuartielles's & Marcus Hannerstig's LEDdriver demo
*/
//using the pin codes on the TLC5940NT to name the Arduino ports
#define VPRG 2 //"chip pin 27 to Arduino pin 2"
#define SIN 3
#define SCLK 7
#define XLAT 4
#define BLANK 5
#define DCPRG 6
#define GSCLK 8 //note: but using PORTB method
#define FADEMIN 100 //lowest fade level LEDs will reach (min would be 0, max 4095)
#define FADEINCR 64 //determines how many steps it takes to run the desired range (lower=longer)
int fadeLevel[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //stores a level for each of 16 ports
int faderNdx = 0; //counter used in this fading sequence
int fadeState[] = {
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //stores the direction of fading for each port 1,0,-1
//start with first port
int word[] = {
0,0,0,0,0,0,0,0,0,0,0,0}; //temp storage for reversing bits in a word (for greyscale setting)
void setup() {
pinMode(VPRG, OUTPUT);
pinMode(SIN, OUTPUT);
pinMode(SCLK, OUTPUT);
pinMode(XLAT, OUTPUT);
pinMode(BLANK, OUTPUT);
pinMode(DCPRG, OUTPUT);
pinMode(GSCLK, OUTPUT); //could also set DDRB directly
preset(); //input “Dot Correction” data
}
void loop () {
setGreys();
feedPorts();
incrementFades();
}
}
void incrementFades() {
//uses two 16 item arrays
//fadeState stores -1,0,or1 to specify direction of fade
//fadeLevel stores current value of fade
//too long to post, sorry...
}
//=======5940 control
void setGreys() {
//data for each port (12 bit word * 16 ports =192 bits in this loop)...
//read the fadeLevel array
for (int i=15; i>=0; i--) { // ports, count DOWN
int datb = fadeLevel[i];
//load fade level bits into the temp array BACKWARDS
for (int j=11; j>=0; j--) {
word[j]=(datb & 1); //& bitwise AND
datb >>= 1; //shift right and assign
// (maybe there's a slicker way to do this!? but this works...)
}
//send the data to the 5940
for (int j=0; j<12; j++) {
digitalWrite(SIN,word[j]);
pulseSCLK();
}
}
digitalWrite(XLAT, HIGH);
digitalWrite(XLAT, LOW);
}
void feedPorts() {
//The actual sequencing of the PWM data into the LEDs, must do constantly...
digitalWrite(BLANK, HIGH);
digitalWrite(BLANK, LOW); //=all outputs ON, start PWM cycle
for (int i=0; i<4096; i++) {
pulseGSCLK();
}
}
////DOT CORRECTION...do once
void preset() {
//Input “DotCorrex” Data
//16 outputs, 64 posssible levels of adjustment, 6 bits/chan = 96 bits total
//[use if any LEDs in array are physically too bright]
digitalWrite(DCPRG, HIGH); //leaving it H is my arbitrary choice (="write to register not EEPROM")
digitalWrite(VPRG, HIGH); //=inputting data into dot correx register
digitalWrite(BLANK, HIGH); //=all outputs off, when this goes high it resets the greyscale counter
digitalWrite(SIN, LOW); //to start dot correction
digitalWrite(XLAT, LOW);
//begin loading in the dot correx data, most significant bit first...
//but here we are not correcting anything, so LSB is going first!
for (int i=0; i<16; i++) { //16 ports
for (int j=0; j<6; j++) { //6 bits of data for each port
digitalWrite(SIN, HIGH); //for now, 111111 for everybody
pulseSCLK();
digitalWrite(SIN, LOW);
}
}
//FIRST GREYSCALE SETTING
digitalWrite(XLAT, HIGH); //latch the dot data into the dot correx register
digitalWrite(XLAT, LOW);
digitalWrite(VPRG, LOW); //entering greyscale mode
for (int i=0; i<16; i++) { //16 ports
int datb = 4095; //using same fade level for all ports this first time
for (int j=0; j<12; j++) { //data for each port, all the same value to start
digitalWrite(SIN, datb & 01);
pulseSCLK();
datb>>=1;
}
}
digitalWrite(XLAT, HIGH); //latch the greyscale data
digitalWrite(XLAT, LOW);
pulseSCLK(); //193rd clock pulse only need to do the FIRST time after dot correx
digitalWrite(BLANK, LOW); //=all outputs ON, start PWM cycle... moved here
}
//SCLK used in dot correx and greyscale setting
void pulseSCLK() {
digitalWrite(SCLK, HIGH);
digitalWrite(SCLK, LOW);
}
void pulseGSCLK() {
//ultra fast pulse trick, using digitalWrite caused flickering
PORTB=0x01; //bring PORTB0 high (pin 8), other ports go low [0x01 does only pin 8, 0x21 also lifts pin 13]
//16nanosecs is the min pulse width for the 5940, but no pause seems needed here
PORTB=0x20; //keep pin13 high for oard LED [0x00 would be all low]
}
does not compile