#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub struct Alarm {
pub minute: Option<u8>,
pub hour: Option<u8>,
pub weekday: Option<u8>,
pub day: Option<u8>,
}
impl Alarm {
pub const fn daily_at(hour: u8, minute: u8) -> Alarm {
Alarm { minute: Some(minute), hour: Some(hour), weekday: None, day: None }
}
pub const fn hourly_at(minute: u8) -> Alarm {
Alarm { minute: Some(minute), hour: None, weekday: None, day: None }
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum AlarmError {
MinuteOutOfRange,
HourOutOfRange,
WeekdayOutOfRange,
DayOutOfRange,
NoFieldEnabled,
}
pub(crate) const AE: u8 = 0x80;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct AlarmRegs {
pub minute: u8,
pub hour: u8,
pub weekday: u8,
pub day: u8,
}
pub(crate) fn encode_alarm(alarm: &Alarm) -> Result<AlarmRegs, AlarmError> {
if alarm.minute.is_none()
&& alarm.hour.is_none()
&& alarm.weekday.is_none()
&& alarm.day.is_none()
{
return Err(AlarmError::NoFieldEnabled);
}
Ok(AlarmRegs {
minute: encode_field(alarm.minute, 0, 59, AlarmError::MinuteOutOfRange)?,
hour: encode_field(alarm.hour, 0, 23, AlarmError::HourOutOfRange)?,
weekday: encode_field(alarm.weekday, 0, 6, AlarmError::WeekdayOutOfRange)?,
day: encode_field(alarm.day, 1, 31, AlarmError::DayOutOfRange)?,
})
}
fn encode_field(value: Option<u8>, lo: u8, hi: u8, err: AlarmError) -> Result<u8, AlarmError> {
match value {
None => Ok(0),
Some(v) if v >= lo && v <= hi => Ok(AE | v),
Some(_) => Err(err),
}
}
pub fn alarm_matches(alarm: &Alarm, minute: u8, hour: u8, weekday: u8, day: u8) -> bool {
let any_enabled = alarm.minute.is_some()
|| alarm.hour.is_some()
|| alarm.weekday.is_some()
|| alarm.day.is_some();
any_enabled
&& alarm.minute.map_or(true, |m| m == minute)
&& alarm.hour.map_or(true, |h| h == hour)
&& alarm.weekday.map_or(true, |w| w == weekday)
&& alarm.day.map_or(true, |d| d == day)
}