#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "clock.h"
#include "button.h"
/* -------------------------------------------------------------------------- */
/* DEFINES */
/* -------------------------------------------------------------------------- */
#define SCREEN_WIDTH 128 // in px
#define SCREEN_HEIGHT 64 // in px
enum ClockMode {
CLOCK_MODE_MAIN,
CLOCK_MODE_STOPWATCH,
CLOCK_MODE_ALARM
};
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 4);
Clock clock(display);
RTC_DS1307 rtc;
Button button(14);
void setup() {
Serial.begin(9600);
// start the display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 init failed");
}
// start RTC
if (!rtc.begin()) {
Serial.println("RTC init failed");
}
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
setTimeRTC();
}
void loop() {
static uint8_t ss = 0; // to save previous time
static uint8_t clockMode = CLOCK_MODE_MAIN;
DateTime now = rtc.now();
button.updateState();
if (button.isPressedLong()) {
Serial.println("Switch mode...");
switchMode(clockMode);
}
// state machine
switch (clockMode) {
/* ------------------------------- Main clock ------------------------------- */
case CLOCK_MODE_MAIN:
// only update if time is different
if (now.second() != ss) {
ss = now.second();
display.clearDisplay();
clock.updateTime(now.hour(), now.minute(), now.second());
clock.updateDate(now.dayOfTheWeek(), now.month(), now.day());
clock.drawAnalogClock();
clock.drawDigitalClock();
clock.drawDate();
display.display();
}
break;
/* ------------------------------- Alarm clock ------------------------------ */
case CLOCK_MODE_STOPWATCH:
static bool swEnabled = false;
static uint8_t swSec = 0, swMin = 0, swHour = 0;
// start/stop when button is pressed
if (button.isPressed()) {
swEnabled = !swEnabled;
if (swEnabled) {
swSec = 0;
swMin = 0;
swHour = 0;
}
}
// display time
if (now.second() != ss) {
char time[20];
sprintf(time, "%02d:%02d:%02d", swHour, swMin, swSec);
display.clearDisplay();
display.setTextSize(2);
display.setCursor(18, 25);
display.print(time);
display.display();
}
// stopwatch counter
if (swEnabled && now.second() != ss) {
swSec++;
ss = now.second();
if (swSec == 60) {
swSec = 0;
swMin++;
}
if (swMin == 60) {
swMin = 0;
swHour++;
}
}
break;
}
}
void setTimeRTC() {
DateTime now = rtc.now();
// set initial time
Serial.println("Please enter start time in hh:mm:ss format (enter to skip): ");
while (Serial.available() == 0) {;}
uint8_t hh = Serial.parseInt();
uint8_t mm = Serial.parseInt();
uint8_t ss = Serial.parseInt();
if (hh != 0) {
rtc.adjust(DateTime(now.year(), now.month(), now.day(), hh, mm, ss));
}
}
void switchMode(uint8_t &mode) {
mode++;
if (mode > CLOCK_MODE_STOPWATCH) {
mode = 0;
}
}