#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "Button.h"
#include "Clock.h"
#include "config.h"
const int COLON_PIN = 13;
const int SIGNAL_PIN = A3;
Button hourButton(A0);
Button minuteButton(A1);
Button alarmButton(A2);
Clock clock;
Adafruit_SSD1306 display(128, 64, &Wire);
// 'Monoline Tech Owl Logo (10)', 500x161px
const unsigned char logo [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x80, 0x00, 0x00, 0x32, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x23, 0x60, 0x00, 0x00, 0x48, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0xd8, 0x00, 0x01, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x36, 0x20, 0x04, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x11, 0xf9, 0x80, 0x93, 0xf1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x14, 0xbe, 0x59, 0x4f, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x11, 0xcf, 0x69, 0x4e, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x56, 0x8a, 0xa2, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0xce, 0xb7, 0x86, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0xc4, 0xa9, 0x16, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0e, 0x3c, 0xbb, 0x95, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x09, 0x80, 0xce, 0x75, 0x12, 0x3e, 0xf9, 0xf1, 0x8c, 0x60, 0xfb, 0x63, 0x8f, 0x3e, 0x00,
0x00, 0x04, 0x42, 0xfd, 0xf5, 0x44, 0x3e, 0xf9, 0xe1, 0x8e, 0x60, 0xfb, 0x63, 0x8f, 0xbe, 0x00,
0x00, 0x03, 0x1b, 0xd9, 0xf9, 0x88, 0x36, 0xc9, 0x03, 0xce, 0x60, 0x9b, 0x63, 0x89, 0xb2, 0x00,
0x00, 0x00, 0xc9, 0xae, 0xd2, 0x20, 0x36, 0xc9, 0x03, 0xce, 0xe0, 0x83, 0x62, 0x89, 0xb2, 0x00,
0x00, 0x00, 0x34, 0xd1, 0x64, 0x80, 0x36, 0xc9, 0xe2, 0xce, 0xe0, 0x9b, 0x66, 0x89, 0xb2, 0x00,
0x00, 0x00, 0x0e, 0x54, 0xee, 0x00, 0x36, 0xf9, 0xe2, 0x4f, 0xe0, 0x9b, 0x66, 0xcf, 0xb2, 0x00,
0x00, 0x00, 0x03, 0x56, 0xfc, 0x00, 0x36, 0xf9, 0x07, 0xcf, 0xa0, 0x9b, 0x67, 0xcf, 0x32, 0x00,
0x00, 0x00, 0x00, 0xd1, 0x70, 0x00, 0x36, 0xd9, 0x07, 0xed, 0xa0, 0x9b, 0x67, 0xcb, 0x32, 0x00,
0x00, 0x00, 0x00, 0x6e, 0x40, 0x00, 0x3e, 0xd9, 0xe6, 0x6d, 0xa0, 0xfb, 0xe4, 0x49, 0x3e, 0x00,
0x00, 0x00, 0x00, 0x71, 0xe0, 0x00, 0x3c, 0xc9, 0xf4, 0x6d, 0x20, 0xf1, 0xe4, 0x49, 0xbc, 0x00,
0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7b, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x35, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x54, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x44, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x04, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xa4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x11, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const int epd_bitmap_allArray_LEN = 1;
const unsigned char* epd_bitmap_allArray[1] = {
logo
};
enum DisplayState {
DisplayClock,
DisplayAlarmStatus,
DisplayAlarmTime,
DisplayAlarmActive,
};
DisplayState displayState = DisplayClock;
long lastStateChange = 0;
bool isAlarmTriggered = false;
void changeDisplayState(DisplayState newValue) {
displayState = newValue;
lastStateChange = millis();
}
long millisSinceStateChange() {
return millis() - lastStateChange;
}
void setColon(bool value) {
digitalWrite(COLON_PIN, value ? LOW : HIGH);
}
void displayTime() {
DateTime now = clock.now();
bool blinkState = now.second() % 2 == 0;
display.clearDisplay();
display.setTextSize(3);
display.setTextColor(SSD1306_WHITE);
int16_t x = (display.width() - (5 * 2 * 2)) / 5;
int16_t y = (display.height() - (7 * 2)) / 2;
String formattedHourNow = String(now.hour(), DEC).length() < 2 ? "0" + String(now.hour(), DEC) : String(now.hour(), DEC);
String formattedMinuteNow = String(now.minute(), DEC).length() < 2 ? "0" + String(now.minute(), DEC) : String(now.minute(), DEC);
display.setCursor(x, y);
display.print(formattedHourNow);
display.print(":");
display.print(formattedMinuteNow);
display.display();
setColon(blinkState);
}
void clockState() {
displayTime();
if (alarmButton.read() == Button::RELEASED && clock.alarmActive()) {
alarmButton.has_changed();
changeDisplayState(DisplayAlarmActive);
return;
}
if (hourButton.pressed()) {
clock.incrementHour();
}
if (minuteButton.pressed()) {
clock.incrementMinute();
}
if (alarmButton.pressed()) {
clock.toggleAlarm();
changeDisplayState(DisplayAlarmStatus);
}
DateTime now = clock.now();
DateTime alarm = clock.alarmTime();
if (now.hour() == alarm.hour() && now.minute() == alarm.minute()) {
isAlarmTriggered = true;
} else {
isAlarmTriggered = false;
}
}
void alarmStatusState() {
setColon(false);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(24, 4);
display.println("Inducer");
display.setCursor(56, 32);
display.println(clock.alarmEnabled() ? "On" : "Off");
display.display();
if (millisSinceStateChange() > ALARM_STATUS_DISPLAY_TIME) {
changeDisplayState(clock.alarmEnabled() ? DisplayAlarmTime : DisplayClock);
return;
}
}
void alarmTimeState() {
DateTime alarm = clock.alarmTime();
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
int16_t x = (display.width() - 23) / 2;
display.setCursor(16, 4);
display.print("Set Timer");
String formattedHour = String(alarm.hour(), DEC).length() < 2 ? "0" + String(alarm.hour(), DEC) : String(alarm.hour(), DEC);
String formattedMinute = String(alarm.minute(), DEC).length() < 2 ? "0" + String(alarm.minute(), DEC) : String(alarm.minute(), DEC);
display.setTextSize(2);
display.setCursor(32, 32);
display.print(formattedHour);
display.print(":");
display.print(formattedMinute);
display.println(" H");
display.display();
if (millisSinceStateChange() > ALARM_HOUR_DISPLAY_TIME || alarmButton.pressed()) {
changeDisplayState(DisplayClock);
return;
}
if (hourButton.pressed()) {
clock.incrementAlarmHour();
lastStateChange = millis();
}
if (minuteButton.pressed()) {
clock.incrementAlarmMinute();
lastStateChange = millis();
}
if (alarmButton.pressed()) {
changeDisplayState(DisplayClock);
isAlarmTriggered = false;
}
}
void alarmState() {
displayTime();
if (clock.alarmActive()) {
isAlarmTriggered = true;
clock.toggleAlarm();
changeDisplayState(DisplayAlarmStatus);
return;
}
}
void setup() {
Serial.begin(115200);
clock.begin();
hourButton.begin();
hourButton.set_repeat(500, 200);
minuteButton.begin();
minuteButton.set_repeat(500, 200);
alarmButton.begin();
alarmButton.set_repeat(1000, -1);
pinMode(COLON_PIN, OUTPUT);
pinMode(SIGNAL_PIN, OUTPUT);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.drawBitmap(0, 0, logo, 128, 64, WHITE);
display.display();
delay(1500);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(24, 24);
display.print("Welcome!");
display.display();
delay(1500);
display.clearDisplay();
display.display();
}
void loop() {
bool state = clock.alarmEnabled();
switch (displayState) {
case DisplayClock:
clockState();
break;
case DisplayAlarmStatus:
alarmStatusState();
break;
case DisplayAlarmTime:
alarmTimeState();
break;
case DisplayAlarmActive:
alarmState();
break;
}
if (!isAlarmTriggered && state) {
digitalWrite(SIGNAL_PIN, HIGH);
delay(74);
digitalWrite(SIGNAL_PIN, LOW);
delay(34);
}
}