#include "Button.h"
#include "AlarmTone.h"
#include "Clock.h"
#include "config.h"
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
const int COLON_PIN = 13;
const int SPEAKER_PIN = A3;
Button alarmButton(A2);
AlarmTone alarmTone;
Clock clk;
// SevSeg sevseg;
enum DisplayState {
DisplayClock,
DisplayAlarmStatus,
DisplayAlarmTime,
DisplayAlarmActive,
DisplaySnooze,
};
DisplayState displayState = DisplayClock;
long lastStateChange = 0;
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 = clk.now();
bool blinkState = now.second() % 2 == 0;
///
lcd.setCursor(0, 0);
if(now.hour()<10){
lcd.print(0+String(now.hour()) + ":" + String(now.minute() / 10) + String(now.minute() % 10));
}
else{
lcd.print(String(now.hour()) + ":" + String(now.minute() / 10) + String(now.minute() % 10));
}
// sevseg.setNumber(now.hour() * 100 + now.minute());
setColon(blinkState);
}
void clockState() {
displayTime();
if (alarmButton.read() == Button::RELEASED && clk.alarmActive()) {
// Read alarmButton has_changed() to clear its state
alarmButton.has_changed();
changeDisplayState(DisplayAlarmActive);
return;
}
if (alarmButton.pressed()) {
clk.toggleAlarm();
changeDisplayState(DisplayAlarmStatus);
}
}
void alarmStatusState() {
setColon(false);
//////
// lcd.clear();
lcd.setCursor(0, 0);
lcd.print(clk.alarmEnabled() ? "on " : "off ");
if (millisSinceStateChange() > ALARM_STATUS_DISPLAY_TIME) {
changeDisplayState(clk.alarmEnabled() ? DisplayAlarmTime : DisplayClock);
return;
}
}
void alarmTimeState() {
DateTime alarm = clk.alarmTime();
lcd.setCursor(0, 0);
if(alarm.hour()<10){
lcd.print(0+String(alarm.hour()) + ":" + String(alarm.minute() / 10) + String(alarm.minute() % 10));
}
else{
lcd.print(String(alarm.hour()) + ":" + String(alarm.minute() / 10) + String(alarm.minute() % 10));
}
// sevseg.setNumber(alarm.hour() * 100 + alarm.minute(), -1);
if (millisSinceStateChange() > ALARM_HOUR_DISPLAY_TIME || alarmButton.pressed()) {
changeDisplayState(DisplayClock);
return;
}
int value = analogRead(A0);
value = map(value, 0, 1023, 0, 1440); // 60 * 24 = 1440(min)
delay(10);
clk.setAlarmTime(value);
lastStateChange = millis();
if (alarmButton.pressed()) {
changeDisplayState(DisplayClock);
}
}
void alarmState() {
displayTime();
if (alarmButton.read() == Button::RELEASED) {
alarmTone.play();
}
if (alarmButton.pressed()) {
alarmTone.stop();
}
if (alarmButton.released()) {
alarmTone.stop();
bool longPress = alarmButton.repeat_count() > 0;
if (longPress) {
clk.stopAlarm();
changeDisplayState(DisplayClock);
} else {
clk.snooze();
changeDisplayState(DisplaySnooze);
}
}
}
void snoozeState() {
// sevseg.setChars("****");
if (millisSinceStateChange() > SNOOZE_DISPLAY_TIME) {
changeDisplayState(DisplayClock);
return;
}
}
void setup() {
Serial.begin(115200);
pinMode(A0, INPUT);
clk.begin();
// lcd.begin(16, 2);
lcd.init();
lcd.backlight();
alarmButton.begin();
alarmButton.set_repeat(1000, -1);
alarmTone.begin(SPEAKER_PIN);
pinMode(COLON_PIN, OUTPUT);
byte digits = 4;
byte digitPins[] = {2, 3, 4, 5};
byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12};
bool resistorsOnSegments = false;
bool updateWithDelays = false;
bool leadingZeros = true;
bool disableDecPoint = true;
// sevseg.begin(DISPLAY_TYPE, digits, digitPins, segmentPins, resistorsOnSegments,
// updateWithDelays, leadingZeros, disableDecPoint);
// sevseg.setBrightness(90);
}
void loop() {
// sevseg.refreshDisplay();
switch (displayState) {
case DisplayClock:
clockState();
break;
case DisplayAlarmStatus:
alarmStatusState();
break;
case DisplayAlarmTime:
alarmTimeState();
break;
case DisplayAlarmActive:
alarmState();
break;
case DisplaySnooze:
snoozeState();
break;
}
}