#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DS1307RTC.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define BUZZER_PIN 2
#define BUTTON_PIN_SET 3
#define BUTTON_PIN_HOUR 4
#define BUTTON_PIN_MIN 5
#define BUTTON_PIN_STOP 6
#define SHORT_PRESS_TIME 1000; // 500 milliseconds
#define LONG_PRESS_TIME 2000; // 3000 milliseconds
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int alarmHour = 1;
int alarmMinute = 00;
int alarmSecond = 00;
String alarmAMPM = "AM";
bool buzzerActive = false;
bool alarmEnabled = true;
bool alarmSetMode = false;
bool hourEditMode = false;
bool minuteEditMode = false;
int lastState = LOW; // the previous state from the input pin
int currentState; // the current reading from the input pin
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
void setup() {
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
pinMode(BUZZER_PIN, OUTPUT);
pinMode(BUTTON_PIN_SET, INPUT_PULLUP);
pinMode(BUTTON_PIN_HOUR, INPUT_PULLUP);
pinMode(BUTTON_PIN_MIN, INPUT_PULLUP);
pinMode(BUTTON_PIN_STOP, INPUT_PULLUP);
delay(100);
display.clearDisplay();
display.setTextColor(WHITE);
}
void printDateTime(tmElements_t tm, bool showAMPM = true) {
// Print date and time
int hour12 = (tm.Hour % 12 == 0) ? 12 : tm.Hour % 12;
String ampm = (tm.Hour < 12) ? "AM" : "PM";
display.print(tm.Month);
display.print("/");
display.print(tm.Day);
display.print("/");
display.print((tmYearToCalendar(tm.Year)) % 100);
display.print(" ");
display.print(hour12);
display.print(":");
if (tm.Minute < 10) display.print("0");
display.print(tm.Minute);
display.print(":");
if (tm.Second < 10) display.print("0");
display.print(tm.Second);
if (showAMPM) {
display.print(" ");
display.println(ampm);
}
}
void printAlarmTime() {
// Print alarm time
display.print("Alarm Time: ");
display.print(alarmHour);
display.print(":");
if (alarmMinute < 10) display.print("0");
display.print(alarmMinute);
display.print(" ");
display.println(alarmAMPM);
}
void printSetAlarmTime() {
// Print set alarm time
display.print("Set Alarm: ");
// Introduce a flag to track AM/PM change
static bool ampmChangeDone = false;
if (hourEditMode) {
if (alarmHour == 12 && !ampmChangeDone) {
if (alarmAMPM == "AM") {
alarmAMPM = "PM";
} else {
alarmAMPM = "AM";
}
// Set the flag to indicate AM/PM change is done
ampmChangeDone = true;
} else if (alarmHour != 12) {
// Reset the flag when the hour is not 12
ampmChangeDone = false;
}
if (alarmHour < 10) {
display.print(" ");
}
display.print(alarmHour);
display.print(":");
} else {
if (alarmHour < 10) {
display.print(" ");
}
display.print(alarmHour);
display.print(":");
}
if (alarmMinute < 10) display.print("0");
display.print(alarmMinute);
display.print(" ");
display.println(alarmAMPM);
}
void loop() {
// Read current time
tmElements_t tm;
RTC.read(tm);
// Display date and time
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
int hour12 = (tm.Hour % 12 == 0) ? 12 : tm.Hour % 12;
String ampm = (tm.Hour < 12) ? "AM" : "PM";
printDateTime(tm);
display.setCursor(0, 20);
if (alarmSetMode) {
printSetAlarmTime();
} else {
printAlarmTime();
}
int currentState = digitalRead(BUTTON_PIN_SET);
if (lastState == HIGH && currentState == LOW) { // button is pressed
pressedTime = millis();
}
else if (lastState == LOW && currentState == HIGH) { // button is released
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if (pressDuration < 1000)
alarmSetMode = !alarmSetMode;
if(pressDuration > 1000)
alarmEnabled = !alarmEnabled;
}
// save the last state
lastState = currentState;
if (!alarmEnabled) {
display.setCursor(0, 50);
display.print("Alarm Off");
} else {
display.setCursor(0, 50);
display.print("Alarm On");
}
// Handle alarm set mode button presses
if (alarmSetMode) {
if (digitalRead(BUTTON_PIN_HOUR) == LOW) {
hourEditMode = !hourEditMode;
if (hourEditMode) {
alarmHour = (alarmHour + 1) % 13;
if (alarmHour == 0) alarmHour = 1;
delay(50);
}
}
if (digitalRead(BUTTON_PIN_MIN) == LOW) {
minuteEditMode = !minuteEditMode;
if (minuteEditMode) {
alarmMinute = (alarmMinute + 1) % 60;
delay(50); // Debounce delay
}
}
}
if (hour12 == alarmHour && tm.Minute == alarmMinute && tm.Second == alarmSecond && ampm == alarmAMPM && alarmEnabled == true) {
if (!buzzerActive) {
tone(BUZZER_PIN, 1000);
buzzerActive = true;
}
}
// Check if the button is pressed to stop the alarm
if (digitalRead(BUTTON_PIN_STOP) == LOW && alarmEnabled == true) {
// Turn off the buzzer and keep it off
noTone(BUZZER_PIN);
buzzerActive = false;
delay(50); // Debounce delay
pinMode(BUTTON_PIN_STOP, INPUT_PULLUP);
}
display.display();
delay(50);
}