/**
Arduino Digital Alarm Clock (Adaptado para LCD 16x2)
Copyright (C) 2020, Uri Shaked.
Released under the MIT License.
*/
#include <LiquidCrystal.h> // Inclui a biblioteca para o LCD
#include "Button.h"
#include "AlarmTone.h"
#include "Clock.h"
#include "config.h"
// Define os pinos do LCD (RS, E, D4, D5, D6, D7)
// Ajuste estes pinos de acordo com sua conexão
const int LCD_RS = 12;
const int LCD_EN = 11;
const int LCD_D4 = 10;
const int LCD_D5 = 9;
const int LCD_D6 = 8;
const int LCD_D7 = 7;
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
const int SPEAKER_PIN = A3;
Button hourButton(A0);
Button minuteButton(A1);
Button alarmButton(A2);
AlarmTone alarmTone;
Clock clock;
enum DisplayState {
DisplayClock,
DisplayAlarmStatus,
DisplayAlarmTime,
DisplayAlarmActive,
DisplaySnooze,
};
DisplayState displayState = DisplayClock;
long lastStateChange = 0;
void changeDisplayState(DisplayState newValue) {
displayState = newValue;
lastStateChange = millis();
lcd.clear(); // Limpa o LCD ao mudar de estado
}
long millisSinceStateChange() {
return millis() - lastStateChange;
}
void displayTime() {
DateTime now = clock.now();
char buffer[17]; // Buffer para formatar a string
sprintf(buffer, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
lcd.setCursor(0, 0);
lcd.print(buffer);
}
void clockState() {
displayTime();
lcd.setCursor(0, 1);
lcd.print(" "); // Limpa a segunda linha
if (alarmButton.read() == Button::RELEASED && clock.alarmActive()) {
// Read alarmButton has_changed() to clear its state
alarmButton.has_changed();
changeDisplayState(DisplayAlarmActive);
return;
}
if (hourButton.pressed()) {
clock.incrementHour();
}
if (minuteButton.pressed()) {
clock.incrementMinute();
}
if (alarmButton.pressed()) {
clock.toggleAlarm();
changeDisplayState(DisplayAlarmStatus);
}
}
void alarmStatusState() {
lcd.setCursor(0, 0);
lcd.print("Alarme:");
lcd.setCursor(0, 1);
lcd.print(clock.alarmEnabled() ? "ON" : "OFF");
if (millisSinceStateChange() > ALARM_STATUS_DISPLAY_TIME) {
changeDisplayState(clock.alarmEnabled() ? DisplayAlarmTime : DisplayClock);
return;
}
}
void alarmTimeState() {
DateTime alarm = clock.alarmTime();
char buffer[17];
sprintf(buffer, "Alarme: %02d:%02d", alarm.hour(), alarm.minute());
lcd.setCursor(0, 0);
lcd.print(buffer);
lcd.setCursor(0, 1);
lcd.print("Set Hor/Min");
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);
}
}
void alarmState() {
displayTime(); // Mostra a hora atual
lcd.setCursor(0, 1);
lcd.print("ALARME TOCANDO!");
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) {
clock.stopAlarm();
changeDisplayState(DisplayClock);
} else {
clock.snooze();
changeDisplayState(DisplaySnooze);
}
}
}
void snoozeState() {
lcd.setCursor(0, 0);
lcd.print("Soneca...");
lcd.setCursor(0, 1);
lcd.print("zzZzZzZzZz");
if (millisSinceStateChange() > SNOOZE_DISPLAY_TIME) {
changeDisplayState(DisplayClock);
return;
}
}
void setup() {
Serial.begin(115200);
lcd.begin(16, 2); // Inicializa o LCD com 16 colunas e 2 linhas
lcd.print("Iniciando...");
delay(2000);
lcd.clear();
clock.begin();
hourButton.begin();
hourButton.set_repeat(500, 200);
minuteButton.begin();
minuteButton.set_repeat(500, 200);
alarmButton.begin();
alarmButton.set_repeat(1000, -1);
alarmTone.begin(SPEAKER_PIN);
}
void loop() {
// Para LCD, não precisamos de sevseg.refreshDisplay();
// A atualização é feita diretamente nas funções de estado
switch (displayState) {
case DisplayClock:
clockState();
break;
case DisplayAlarmStatus:
alarmStatusState();
break;
case DisplayAlarmTime:
alarmTimeState();
break;
case DisplayAlarmActive:
alarmState();
break;
case DisplaySnooze:
snoozeState();
break;
}
}