// DSP-0401B TEST PROGRAM - EVENT COUNTER USING MILLIS FUNCTION

// pin definitions, using the shiftOut function to communicate with the display

const int SIN = 12;     
const int CLK = 11;   
const int LAT = 10;   
const int BLK = 9;

// character map for numbers 0-9, could be stored in PROGMEM if desired
                            
const word numbers[10] = { 0xAEAE, 0x2A00, 0x9C9C, 0xBC94, 0x3830, 0xB4B4, 0xB4BC, 0x2C80, 0xBCBC, 0xBCB4 };

int counter = 0;                             

void setup () {

// set all display control pins to output
  
  pinMode(SIN, OUTPUT);    
  pinMode(CLK, OUTPUT);
  pinMode(LAT, OUTPUT);
  pinMode(BLK, OUTPUT);
  digitalWrite(BLK, HIGH); // blank display during clearing period

  // clear out contents of TLC5926 shift registers by sending empty bytes
  // this prevents any "nonsense" characters from displaying on startup
  
  for(int i = 0; i < 9; i++) {
  digitalWrite(LAT, LOW);
  shiftOut(SIN, CLK, MSBFIRST, 0x00);
  digitalWrite(LAT, HIGH);
  }
    
  analogWrite(BLK, 127); // PWM dimming to reduce current consumption (from over 500mA at full brightness, to under 300mA peak!)
}


void loop () {
  
 // increment a counter every second and write it's value to the display
 // similar methods can be used for outputting any integer value
 // use this timekeeping method instead of calls to delay for multi-tasking programs
 
 static unsigned long system_time = 0; // declare some variables for storing values returned by the millis() function
 if (millis() - system_time >= 1000) {  // increment once per second
   system_time = millis();
   counter++;
   update_display();
 }  
}

void update_display () {
  
  int D0, D1, D2, D3 = 0; // these represent our display digits and will point to an element in the character array
  int display_number = counter; // copy the value held by our counter
  int working = 0; // store our working-out here
  
  // use some division and modulo to obtain four separate digits, explained in write-up
  
  D0 = display_number / 1000;
  working = display_number / 100;
  D1 = working % 10;
  working = display_number / 10;
  D2 = working % 10;
  D3 = display_number % 10;
  
  // shift out data to the display in 8-bit chunks
  
  digitalWrite(LAT, LOW);
  shiftOut(SIN, CLK, MSBFIRST, numbers[D0] >> 8);
  shiftOut(SIN, CLK, MSBFIRST, numbers[D0]);
  shiftOut(SIN, CLK, MSBFIRST, numbers[D1] >> 8);
  shiftOut(SIN, CLK, MSBFIRST, numbers[D1]);
  shiftOut(SIN, CLK, MSBFIRST, numbers[D2] >> 8);
  shiftOut(SIN, CLK, MSBFIRST, numbers[D2]);
  shiftOut(SIN, CLK, MSBFIRST, numbers[D3] >> 8);
  shiftOut(SIN, CLK, MSBFIRST, numbers[D3]);
  digitalWrite(LAT, HIGH);
}

