#pragma GCC push_options
#pragma GCC optimize ("O1")

// I2C
#include <Wire.h>
// RTC
#include <DS3231.h>
// Use 74HC595 shift registers

// Init DS3231 RTC
DS3231 rtc;
bool h12;
bool hPM;

int btnHr = 10;
int btnMin = 9;
int btnTemp = 8;
int regData = 5;
int regClk = 6;
int regLatch = 7;

void setup() {
       // Buttons
       for(int i = 8; i < 11; i++)
               pinMode(i,INPUT);
       // Shift register
       for(int i = 5; i < 8; i++)
               pinMode(i,OUTPUT);
       // RTC
       Wire.begin();
       rtc.setClockMode(false); // 24 hour

       // Check RTC for problems
       if(!rtc.oscillatorCheck()) {
               // RTC NOT OK, set values to known ones
               rtc.setMinute(0);
               rtc.setHour(12);
       }
}

byte minute, hour, decTemp;
float temp;
const uint8_t seg[] = {
       //gfedcba.
       0b01111110, // 0
       0b00001100, // 1
       0b10110110, // 2
       0b10011110, // 3
       0b11001100, // 4
       0b11011010, // 5
       0b11111010, // 6
       0b00001110, // 7
       0b11111110, // 8
       0b11011110, // 9
       0b11000110, // degree
       0b01110010, // C
       0b10000000  // -
};

void loop() {
       // Get time from RTC
       minute = rtc.getMinute();
       hour = rtc.getHour(h12, hPM);

       digitalWrite(regLatch, LOW);
       shiftOut(regData, regClk, MSBFIRST, seg[minute%10]);
       shiftOut(regData, regClk, MSBFIRST, seg[minute/10]);
       shiftOut(regData, regClk, MSBFIRST, seg[hour%10]);
       shiftOut(regData, regClk, MSBFIRST, seg[hour/10]);
       digitalWrite(regLatch, HIGH);

       // Hour up
       if(digitalRead(10)) {
               if(rtc.getHour(h12, hPM) == 23) {
                       rtc.setHour(0);
               } else {
                       rtc.setHour(rtc.getHour(h12, hPM) + 1);
               }
               while(digitalRead(10));
       }

       // Minute up, set seconds to 0
       if(digitalRead(9)) {
               if(rtc.getMinute() == 59) {
                       rtc.setMinute(0);
               }
               rtc.setSecond(0);
               rtc.setMinute(rtc.getMinute() + 1);
               while(digitalRead(9));
       }

       // Show temperature reading from RTC
       while(digitalRead(8)) {
               temp = rtc.getTemperature();
               decTemp = (int)temp;
               if(temp > -9999) {
                       // OK
                       digitalWrite(regLatch, LOW);
                       shiftOut(regData, regClk, MSBFIRST, seg[11]);
                       shiftOut(regData, regClk, MSBFIRST, seg[10]);
                       shiftOut(regData, regClk, MSBFIRST, seg[decTemp%10]);
                       shiftOut(regData, regClk, MSBFIRST, seg[decTemp/10]);
                       digitalWrite(regLatch, HIGH);
               } else {
                       digitalWrite(regLatch, LOW);
                       shiftOut(regData, regClk, MSBFIRST, seg[11]);
                       shiftOut(regData, regClk, MSBFIRST, seg[10]);
                       shiftOut(regData, regClk, MSBFIRST, seg[12]);
                       shiftOut(regData, regClk, MSBFIRST, seg[12]);
                       digitalWrite(regLatch, HIGH);
               }
       }
}

#pragma GCC pop_options