1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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,
}
}
}
|