use std::time::{Duration, Instant}; macro_rules! now { () => { time::OffsetDateTime::now_local() .unwrap_or_else(|_| time::OffsetDateTime::now_utc()) };} macro_rules! time_from_ticks { ($ticks:expr) => { Instant::now() + Duration::from_millis(($ticks * 4).into()) }; } macro_rules! to_ticks { ($duration:expr) => {($duration.as_millis() / 4) as u16}; } macro_rules! from_ticks { ($ticks:expr) => {Duration::from_millis(($ticks * 4).into())}; } macro_rules! ticks_since_time { ($time:expr) => { ($time.duration_since(Instant::now()).as_millis() / 4) as u16 }; } /// 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) { self. [< timer_ $i _instant >] = time_from_ticks!(self. [< timer_ $i >]); } }}; } /// 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) { if self. [< timer_ $i >] > 0 { self. [< timer_ $i >] = ticks_since_time!(self.[< timer_ $i _instant >]); if self. [< timer_ $i >] == 0 { self.wake_flag = true; } } self. [< timer_ $i >] } }}; } 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 { let mut is_some = false; let mut value = u16::MAX; macro_rules! contribute_to_min { ($timer:expr) => { if $timer > 0 { is_some = true; value = std::cmp::min(value, $timer); } }; } contribute_to_min!(self.timer_1); contribute_to_min!(self.timer_2); contribute_to_min!(self.timer_3); contribute_to_min!(self.timer_4); match is_some { true => Some(Duration::from_millis((value*4).into())), false => None, } } }