//1.0 - initial release

#include <Wire.h>
#include <RTClib.h>

RTC_DS1307 RTC;

//time variables
int hh24;
int hh;
int mm;
int ss;

//I/O
int hoursButton = A0;
int minsButton = A1;

//segments
int segA = 2;
int segB = 3;
int segC = 4;
int segD = 5;
int segE = 6;
int segF = 7;
int segG = 8;
int colon_pm = 13;

//digits
int mmDigit1 = 9;  //digit 1 on display (pin 6)
int mmDigit2 = 10; //digit 2 on display (pin 3)
int hhDigit1 = 11; //digit 3 on display (pin 9)
int hhDigit2 = 12; //digit 4 on display (pin 12)

//time variables
//hours
byte digit1; //mmDigit1
byte digit2; //mmDigit2

//minutes
byte digit3; //hhDigit1
byte digit4; //hhDigit2

/*
//right side up
byte segArray[11][7] = {
  {0,0,0,0,0,0,1}, // 0
  {1,0,0,1,1,1,1}, // 1
  {0,0,1,0,0,1,0}, // 2
  {0,0,0,0,1,1,0}, // 3
  {1,0,0,1,1,0,0}, // 4
  {0,1,0,0,1,0,0}, // 5
  {0,1,0,0,0,0,0}, // 6
  {0,0,0,1,1,1,1}, // 7
  {0,0,0,0,0,0,0}, // 8
  {0,0,0,0,1,0,0}, // 9
  {1,1,1,1,1,1,1} // off
};
*/

//pins mapped upside down
//right side up
byte segArray[11][7] = {
  {0,0,0,0,0,0,1}, // 0
  {1,1,1,1,0,0,1}, // 1
  {0,0,1,0,0,1,0}, // 2
  {0,1,1,0,0,0,0}, // 3
  {1,1,0,1,0,0,0}, // 4
  {0,1,0,0,1,0,0}, // 5
  {0,0,0,0,1,0,0}, // 6
  {1,1,1,0,0,0,1}, // 7
  {0,0,0,0,0,0,0}, // 8
  {0,1,0,0,0,0,0}, // 9
  {1,1,1,1,1,1,1} // off
};

volatile byte multiplexer = 0;

void setup() {

  Wire.begin();
  RTC.begin();

  //set pin modes
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);
  pinMode(colon_pm, OUTPUT);

  pinMode(hhDigit2, OUTPUT);
  pinMode(hhDigit1, OUTPUT);
  pinMode(mmDigit2, OUTPUT);
  pinMode(mmDigit1, OUTPUT);

  pinMode(hoursButton, INPUT);
  pinMode(minsButton, INPUT);

  //set states
  digitalWrite(segA, LOW);
  digitalWrite(segB, LOW);
  digitalWrite(segC, LOW);
  digitalWrite(segD, LOW);
  digitalWrite(segE, LOW);
  digitalWrite(segF, LOW);
  digitalWrite(segG, LOW);

  digitalWrite(colon_pm, LOW);
}

void loop() {

  DateTime now = RTC.now(); //time from the RTC in 24 hour mode
  hh24 = now.hour(); //used for PM check
  mm = now.minute();
  ss = now.second(); 

  //pass RTC values into a new variable -
  //this way one variable stores time in 24 hour mode and another that can be converted to 12 hour mode
  //time is monitored 'in the background' in 24 hour mode using the RTC, but is displayed in an adjusted 12-hr format
  hh = hh24;

  //convert to 12 hr mode for display
  if (hh24 < 1) {
    hh = 12;
  }

  if ((hh24 > 12) && (hh24 < 24)) {
    hh = hh24 - 12;
  }

  //turn on PM light as appropriate
  if (hh24 > 11) {
    //digitalWrite(decimal, HIGH);
  } 
  else {
    // digitalWrite(decimal, LOW);
  }

  //calculate the number to be displayed on each digit by disecting the time from the RTC
  //hours
  digit4 = hh / 10;
  digit3 = hh % 10;

  //minutes
  digit2 = mm / 10;
  digit1 = mm % 10;

  //turn digits off
  digitalWrite(hhDigit1, HIGH); //1s of hours
  digitalWrite(hhDigit2, HIGH); //10s of hours
  digitalWrite(mmDigit1, HIGH); //1s of minutes
  digitalWrite(mmDigit2, HIGH); //10s of minutes
  digitalWrite(colon_pm, HIGH);

  multiplexer++;
  if (multiplexer == 9) multiplexer = 1;

  // 1 digit
  if (multiplexer == 1) {

    displayDigit(digit1);
    digitalWrite(mmDigit1, LOW);
    // digitalWrite(colon, HIGH);
  }

  // 2 digit
  if (multiplexer == 2) {

    displayDigit(digit2);
    digitalWrite(mmDigit2, LOW);
    //  digitalWrite(colon, HIGH);
  }

  // 3 digit
  if (multiplexer == 3) {

    displayDigit(digit3);
    digitalWrite(hhDigit1, LOW);
    // digitalWrite(colon, HIGH);
  }
  // 4 digit
  if (multiplexer == 4) {

    displayDigit(digit4);
    digitalWrite(hhDigit2, LOW);
    //  digitalWrite(colon, HIGH);
  }

  //colon - display for 2 cycl  es to increase brightness
  if ((multiplexer > 4) && (multiplexer < 7)) {
    digitalWrite(mmDigit2, LOW); //anode for colons
    digitalWrite(colon_pm , LOW); //low for colon on (cathode)
    digitalWrite(segA, HIGH); //turn segments off
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
  }

  //PM light
  if (multiplexer == 8) {
    
    //enable PM light as appropriate
    if (hh24 > 11) {
    digitalWrite(hhDigit2, LOW); //anode for DP
    digitalWrite(colon_pm , LOW); //low for colon on (cathode)
    digitalWrite(segA, HIGH); //turn segments off
    digitalWrite(segB, HIGH);
    digitalWrite(segC, HIGH);
    digitalWrite(segD, HIGH);
    digitalWrite(segE, HIGH);
    digitalWrite(segF, HIGH);
    digitalWrite(segG, HIGH);
   }
  } 

  //handle button presses for setting the time
  //hours button pressed
  if (digitalRead(hoursButton) == LOW) {

    //debounce
    delay(200);
    hh24++;

    if (hh24 > 23) {
      hh24 = 0;
    }

    updateRTC();
  } 

  //minutes button pressed
  if (digitalRead(minsButton) == LOW) {

    //debounce
    delay(200);

    mm++;
    ss = 0;

    if (mm >59) {
      mm = 0;
    }

    updateRTC();
  }
}

void displayDigit(byte seg) {

  digitalWrite(2, segArray[seg][0]); //A
  digitalWrite(3, segArray[seg][1]); //B
  digitalWrite(4, segArray[seg][2]); //C
  digitalWrite(5, segArray[seg][3]); //D
  digitalWrite(6, segArray[seg][4]); //E
  digitalWrite(7, segArray[seg][5]); //F
  digitalWrite(8, segArray[seg][6]); //G

}

byte decToBcd(byte val) {
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val) {
  return ( (val/16*10) + (val%16) );
}

void updateRTC() {
  Wire.beginTransmission(104);
  Wire.write(0);
  Wire.write(decToBcd(ss));
  Wire.write(decToBcd(mm));
  Wire.write(decToBcd(hh24));
  Wire.endTransmission();
}




