use std::time::{Duration, Instant}; macro_rules! now { () => { time::OffsetDateTime::now_local() .unwrap_or_else(|_| time::OffsetDateTime::now_utc()) };} macro_rules! to_ticks { ($duration:expr) => {($duration.as_millis() / 4) as u16}; } macro_rules! from_ticks { ($ticks:expr) => {Duration::from_millis(($ticks * 4).into())}; } /// Create a method to set the instant of a timer. macro_rules! generate_set_timer_method { ($i:tt) => { mini_paste::item!{ pub fn [< set_timer_ $i >] (&mut self) { let ticks = &mut self. [< timer_ $i >]; let instant = &mut self. [< timer_ $i _instant >]; *instant = Instant::now() + from_ticks!(*ticks); } }}; } /// Create a method to update the value of a timer. macro_rules! generate_update_timer_method { ($i:tt) => { mini_paste::item!{ pub fn [< update_timer_ $i >] (&mut self) -> u16 { let ticks = &mut self. [< timer_ $i >]; let instant = &mut self. [< timer_ $i _instant >]; if *ticks > 0 { *ticks = to_ticks!(instant.duration_since(Instant::now())); if *ticks == 0 { self.wake_flag = true; } } *ticks } }}; } pub struct ClockDevice { pub wake_flag: bool, pub boot_time: Instant, pub cumulative_timer: u16, pub timer_1_instant: Instant, pub timer_2_instant: Instant, pub timer_3_instant: Instant, pub timer_4_instant: Instant, pub timer_1: u16, pub timer_2: u16, pub timer_3: u16, pub timer_4: u16, } impl ClockDevice { pub fn new() -> Self { Self { wake_flag: false, boot_time: Instant::now(), cumulative_timer: 0, timer_1_instant: Instant::now(), timer_2_instant: Instant::now(), timer_3_instant: Instant::now(), timer_4_instant: Instant::now(), timer_1: 0, timer_2: 0, timer_3: 0, timer_4: 0, } } generate_set_timer_method!{1} generate_set_timer_method!{2} generate_set_timer_method!{3} generate_set_timer_method!{4} generate_update_timer_method!{1} generate_update_timer_method!{2} generate_update_timer_method!{3} generate_update_timer_method!{4} pub fn update_cumulative_timer(&mut self) -> u16 { self.cumulative_timer = to_ticks!(self.boot_time.elapsed()); return self.cumulative_timer; } pub fn year(&self) -> u8 { now!().year().saturating_sub(2000).try_into().unwrap_or(u8::MAX) } pub fn month(&self) -> u8 { now!().month() as u8 - 1 } pub fn day(&self) -> u8 { now!().day() as u8 - 1 } pub fn hour(&self) -> u8 { now!().hour() } pub fn minute(&self) -> u8 { now!().minute() } pub fn second(&self) -> u8 { now!().second() } pub fn shortest_active_timer(&self) -> Option { [self.timer_1, self.timer_2, self.timer_3, self.timer_4] .iter() .filter(|t| **t > 0) .min() .and_then(|t| Some(from_ticks!(t))) } }