use esp_idf_hal::delay::FreeRtos;
use esp_idf_hal::gpio::*;
use esp_idf_hal::i2c::*;
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::prelude::*;
use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306};
use embedded_graphics::{
mono_font::{ascii::FONT_6X10, MonoTextStyle},
pixelcolor::BinaryColor,
prelude::*,
text::Text,
};
use rtc_rs::DS3231;
fn main() -> anyhow::Result<()> {
// Initialize ESP32 peripherals
let peripherals = Peripherals::take()?;
let i2c = peripherals.i2c0;
let sda = peripherals.pins.gpio21;
let scl = peripherals.pins.gpio22;
let buzzer = PinDriver::output(peripherals.pins.gpio12)?;
let button_hour = PinDriver::input(peripherals.pins.gpio13)?;
let button_minute = PinDriver::input(peripherals.pins.gpio14)?;
let button_toggle = PinDriver::input(peripherals.pins.gpio15)?;
// Configure I2C for RTC & OLED
let config = I2cConfig::new().baudrate(100.kHz().into());
let i2c = I2cDriver::new(i2c, sda, scl, &config)?;
// Initialize OLED
let interface = I2CDisplayInterface::new(i2c);
let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
.into_buffered_graphics_mode();
display.init().unwrap();
// Initialize RTC
let mut rtc = DS3231::new(i2c);
let mut alarm_hour = 12;
let mut alarm_minute = 0;
let mut alarm_enabled = false;
let mut alarm_triggered = false;
loop {
// Read current time from RTC
let time = rtc.get_time()?;
// Handle button presses (with debouncing)
if button_hour.is_low() {
alarm_hour = (alarm_hour + 1) % 24;
FreeRtos::delay_ms(200);
}
if button_minute.is_low() {
alarm_minute = (alarm_minute + 1) % 60;
FreeRtos::delay_ms(200);
}
if button_toggle.is_low() {
alarm_enabled = !alarm_enabled;
FreeRtos::delay_ms(200);
}
// Trigger alarm if conditions are met
if alarm_enabled && time.hour == alarm_hour && time.minute == alarm_minute && !alarm_triggered {
alarm_triggered = true;
buzzer.set_high()?;
}
// Stop alarm after 1 minute
if alarm_triggered && time.minute != alarm_minute {
alarm_triggered = false;
buzzer.set_low()?;
}
// Update OLED display
display.clear(BinaryColor::Off)?;
let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On);
// Display current time
Text::new(
&format!("{:02}:{:02}:{:02}", time.hour, time.minute, time.second),
Point::new(10, 20),
text_style,
).draw(&mut display)?;
// Display alarm status
Text::new(
&format!("Alarm: {:02}:{:02} {}", alarm_hour, alarm_minute, if alarm_enabled { "ON" } else { "OFF" }),
Point::new(10, 40),
text_style,
).draw(&mut display)?;
display.flush()?;
FreeRtos::delay_ms(100);
}
}