#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define buttonPin 2
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
RTC_DS1307 rtc;
String displayTime;
DateTime timerStart;
int mode = 0;
int hour, minute, second, pauseSecond;
bool timerToggle = false;
bool buttonPressed = false;
void setup() {
Serial.begin(9600);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(0, buttonPress, FALLING);
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
while (true);
}
delay(1000);
oled.clearDisplay();
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(0, 10);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
while (true);
}
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
timerStart = rtc.now();
Serial.println("----Serial Open----\n");
Serial.println("Clock/Timer Instructions : ");
Serial.println(" -- Hold Button for >1s to change mode");
Serial.println(" -- Short press to start/stop timer\n");
}
void loop() {
if (buttonPressed) {
int count = 0;
bool buttonState = 0;
Serial.println("(Start Press)");
while (!buttonState){
count += 1;
buttonState = digitalRead(buttonPin);
delay(20);
}
float duration = count*20.00/1000;
Serial.print("(End press. Press time: ");
Serial.print(duration);
Serial.println(" s)");
if (count >= 50){
timerToggle = false;
changeMode();
}
else if (count < 50 && mode == 1) {
pauseTimer();
if (timerToggle) { Serial.println(">> Timer Start"); }
else { Serial.println(">> Timer Pause"); }
}
else { Serial.println(">> Cannot stop time... :(");}
delay(200);
interrupts();
buttonPressed = false;
}
displayTime = getTime(mode);
oledDisplayCenter(displayTime);
}
//Function to display text in centre of OLED
void oledDisplayCenter(String text) {
int16_t x1;
int16_t y1;
uint16_t width;
uint16_t height;
oled.getTextBounds(text, 0, 0, &x1, &y1, &width, &height);
oled.clearDisplay();
oled.setCursor((SCREEN_WIDTH - width) / 2, (SCREEN_HEIGHT - height) / 2);
oled.println(text);
oled.display();
}
//Function to register interrupt button press
void buttonPress(){
buttonPressed = true;
delay(20);
//Stops interrupts to prevent interference during hold
noInterrupts();
}
//Function to calculate and return time/timer output as String
String getTime(int mode){
DateTime now = rtc.now();
String time;
//Change output depending on mode setting. 0 = Clock, 1 = Timer
switch (mode) {
case 0:
hour = now.hour();
minute = now.minute();
second = now.second();
break;
case 1:
//Calculate seconds passed since timer started (timerToggle = true)
if (timerToggle){
second = now.second()-timerStart.second()+pauseSecond;
//Add to minutes at 60 seconds, reset seconds
if (second < 0) { second += 60; }
if (second > 59) {
timerStart = rtc.now();
pauseSecond = 0;
minute += 1;
}
//Add to hours at 60 minutes, reset minutes
if (minute < 0) { minute += 60; }
if (minute > 59) {
minute = 0;
hour += 1;
}
}
//If paused (timerToggle = false), do nothing
else if (!timerToggle){
break;
}
break;
}
//Create string from time values
time = "";
time += hour;
time += ':';
time += minute;
time += ':';
time += second;
return time;
}
//Function to iterate through modes
void changeMode() {
mode += 1;
if (mode > 1) { mode = 0; }
delay(50);
if (mode == 0 ){
oledDisplayCenter("Mode Changed: Clock");
Serial.println("Mode Changed: Clock");
}
if (mode == 1 ){
oledDisplayCenter("Mode Changed: Timer");
Serial.println("Mode Changed: Timer");
}
delay(100);
resetTimer();
}
//Function to pause timer
void pauseTimer() {
if (timerToggle) {
pauseSecond = second;
timerToggle = false;
}
else { timerToggle = true; }
timerStart = rtc.now();
}
//Function to reset timer
void resetTimer() {
hour = 0;
minute = 0;
second = 0;
pauseSecond = 0;
}