diff options
Diffstat (limited to 'src/devices/clock.rs')
-rw-r--r-- | src/devices/clock.rs | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/devices/clock.rs b/src/devices/clock.rs new file mode 100644 index 0000000..063c67b --- /dev/null +++ b/src/devices/clock.rs @@ -0,0 +1,130 @@ +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! 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; } + } + } + }}; +} + +pub struct ClockDevice { + pub wake_flag: bool, + + pub boot_time: Instant, + pub cumulative_seconds: 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_seconds: 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, + } + } + + pub fn update_cumulative_seconds(&mut self) { + self.cumulative_seconds = self.boot_time.elapsed().as_secs() as u16; + } + + 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 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<Duration> { + 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, + } + } +} |