// Binary Clock Prototype on the Arduino UNO
//
// Full Binary Clock functionality on the Arduino UNO
//  using the DS3231 Real-Time Clock



//#include <ds3231.h>

#include <Wire.h>
#define DS1307_ADDR 0x68

uint8_t seconds, minutes, hours;

#define DISPLAY_REFRESH_RATE 100

#define NUM_LEDS 13

// hour MSD
#define h_MSD_1 12
#define h_MSD_2 11

// hour LSD
#define h_LSD_1 10
#define h_LSD_2 9
#define h_LSD_4 8
#define h_LSD_8 7

// second MSB
#define s_MSB_4 6
#define s_MSB_2 7
#define s_MSB_1 8

// second LSB
#define s_LSB_8 2
#define s_LSB_4 3
#define s_LSB_2 4
#define s_LSB_1 5

uint8_t leds[NUM_LEDS] = {
  h_MSD_1,
  h_MSD_2,
  h_LSD_1,
  h_LSD_2,
  h_LSD_4,
  h_LSD_8,
  s_MSB_1,
  s_MSB_2,
  s_MSB_4,
  s_LSB_1,
  s_LSB_2,
  s_LSB_4,
  s_LSB_8
};



void setup() {
  Serial.begin(115200);
  Wire.begin();

  // Set-Time by writing to DS3231
  Wire.beginTransmission(DS1307_ADDR); // start communication using DS3231 hex address
  Wire.write(0x00);
  Wire.write(dectoBcd(seconds)); // write seconds in BCD format, 0100(MSB) and 0111(LSB)
  // Wire.write(0x01); // Not required for next address
  Wire.write(dectoBcd(minutes));
  Wire.endTransmission();

  // Configure ALL led pins to be a digital OUTPUT
  for (uint8_t i = 0; i < NUM_LEDS; i++)
    pinMode(leds[i],OUTPUT);
}



void loop() {
  Wire.beginTransmission(DS1307_ADDR);
  Wire.write(0);  // Start reading from address 0 (seconds)
  Wire.endTransmission();
  Wire.requestFrom(DS1307_ADDR, 3);  // Request seconds, minutes, hours, day, date, month, year

  if (Wire.available()) { // Also works when 'if' statement removed
    seconds = bcdToDec(Wire.read() & 0x7F);  // Mask the high bit of seconds
    minutes = bcdToDec(Wire.read() & 0x7F);

    // Print to Serial Monitor
    if (minutes < 10) Serial.print("0");
    Serial.print(minutes);
    Serial.print(":");
    if (seconds < 10) Serial.print("0"); // Add a '0' to seconds
    Serial.print(seconds);
    Serial.println();

    // Get hour and minute from DS3231

    uint8_t h = minutes;

  // Obtain LSD of hour and minute
  uint8_t sLSB = seconds % 10;
  uint8_t hLSD = h % 10;

  Serial.print("sLSB: "); Serial.println(sLSB);
  //Serial.print("hLSD: "); Serial.println(hLSD);



  // Toggle LEDs for hour MSD
  if (h >= 10 && h < 20)
    digitalWrite(h_MSD_1,HIGH);
  else
    digitalWrite(h_MSD_1,LOW);
  if (h >= 20 && h < 24)
    digitalWrite(h_MSD_2,HIGH);
  else
    digitalWrite(h_MSD_2,LOW);

  // Toggle LEDs for hour LSD
  if (hLSD == 1 || hLSD == 3 || hLSD == 5 || hLSD == 7 || hLSD == 9)
    digitalWrite(h_LSD_1,HIGH);
  else
    digitalWrite(h_LSD_1,LOW);
  if (hLSD == 2 || hLSD == 3 || hLSD == 6 || hLSD == 7)
    digitalWrite(h_LSD_2,HIGH);
  else
    digitalWrite(h_LSD_2,LOW);
  if (hLSD == 4 || hLSD == 5 || hLSD == 6 || hLSD == 7)
    digitalWrite(h_LSD_4,HIGH);
  else
    digitalWrite(h_LSD_4,LOW);
  if (hLSD == 8 || hLSD == 9)
    digitalWrite(h_LSD_8,HIGH);
  else
    digitalWrite(h_LSD_8,LOW);


  
  // Toggle LEDs for minute MSB
  if ((seconds >= 10 & seconds < 20) | (seconds >= 30 & seconds < 40) | (seconds >= 50 & seconds < 60)) { // if seconds = 10 - 19 or 30 - 39 or 50 - 59
    digitalWrite(s_MSB_1, HIGH);
  }
  else {
    digitalWrite(s_MSB_1, LOW);
  }
  if (seconds >= 20 & seconds < 40) { // if seconds = 20 - 39
    digitalWrite(s_MSB_2, HIGH);
  }
  else {
    digitalWrite(s_MSB_2, LOW);
  }
  if (seconds >= 40 & seconds < 60) { // if s = 40 - 59
    digitalWrite(s_MSB_4, HIGH);
  }
  else {
    digitalWrite(s_MSB_4, LOW);
  }

  // Toggle LEDs for minutes LSB
  if (sLSB == 1 | sLSB == 3 | sLSB == 5 | sLSB == 7 | sLSB == 9) {
    digitalWrite(s_LSB_1, HIGH);
  }
  else {
    digitalWrite(s_LSB_1,LOW);
  }
  if (sLSB == 2 | sLSB == 3 | sLSB == 6 | sLSB == 7) {
    digitalWrite(s_LSB_2,HIGH);
  }
  else {
    digitalWrite(s_LSB_2,LOW);
  }
  if (sLSB == 4 | sLSB == 5 | sLSB == 6 | sLSB == 7) {
    digitalWrite(s_LSB_4,HIGH);
  }
  else {
    digitalWrite(s_LSB_4,LOW);
  }
  if (sLSB == 8 | sLSB == 9) {
    digitalWrite(s_LSB_8,HIGH);
  }
  else {
    digitalWrite(s_LSB_8,LOW);
  }
}

  delay(DISPLAY_REFRESH_RATE);
}

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

byte dectoBcd(byte val) {
  return ((val / 10 * 16) + (val % 10)); // This works the same as below
  //return ((val / 10 << 4) + (val % 10)); // This works the same as above
}
GND5VSDASCLSQWRTCDS1307+