embedded_hal_mock/eh0/
timer.rs1use std::{
31 convert::Infallible,
32 sync::{
33 atomic::{AtomicU64, Ordering},
34 Arc,
35 },
36};
37
38use eh0 as embedded_hal;
39use embedded_hal::timer::{Cancel, CountDown, Periodic};
40pub use embedded_time::Clock;
41use embedded_time::{clock, duration::*, fraction::Fraction, Instant};
42use void::Void;
43
44#[derive(Clone, Debug)]
46pub struct MockClock {
47 ticks: Arc<AtomicU64>,
48}
49
50impl Clock for MockClock {
51 type T = u64;
52 const SCALING_FACTOR: Fraction = Fraction::new(1, 1_000_000_000);
53
54 fn try_now(&self) -> Result<Instant<Self>, clock::Error> {
55 let ticks: u64 = self.ticks.load(Ordering::Relaxed);
56 Ok(Instant::<Self>::new(ticks))
57 }
58}
59
60impl Default for MockClock {
61 fn default() -> Self {
62 MockClock {
63 ticks: Arc::new(AtomicU64::new(0)),
64 }
65 }
66}
67
68impl MockClock {
69 pub fn new() -> Self {
71 Self::default()
72 }
73
74 pub fn elapsed(&self) -> Nanoseconds<u64> {
76 Nanoseconds(self.ticks.load(Ordering::Relaxed))
77 }
78
79 pub fn tick<T>(&mut self, ticks: T)
81 where
82 T: Into<Nanoseconds<u64>>,
83 {
84 self.ticks.fetch_add(ticks.into().0, Ordering::Relaxed);
85 }
86
87 pub fn get_timer(&self) -> MockTimer {
89 let clock = self.clone();
90 let duration = Nanoseconds(1);
91 let expiration = clock.try_now().unwrap();
92 MockTimer {
93 clock: self.clone(),
94 duration,
95 expiration,
96 started: false,
97 }
98 }
99}
100
101pub struct MockTimer {
103 clock: MockClock,
104 duration: Nanoseconds<u64>,
105 expiration: Instant<MockClock>,
106 started: bool,
107}
108
109impl CountDown for MockTimer {
110 type Time = Nanoseconds<u64>;
111
112 fn start<T>(&mut self, count: T)
113 where
114 T: Into<Self::Time>,
115 {
116 let now = self.clock.try_now().unwrap();
117 self.duration = count.into();
118 self.expiration = now + self.duration;
119 self.started = true;
120 }
121
122 fn wait(&mut self) -> nb::Result<(), Void> {
123 let now = self.clock.try_now().unwrap();
124 if self.started && now >= self.expiration {
125 self.expiration = now + self.duration;
126 Ok(())
127 } else {
128 Err(nb::Error::WouldBlock)
129 }
130 }
131}
132
133impl Periodic for MockTimer {}
134
135impl Cancel for MockTimer {
136 type Error = Infallible;
137
138 fn cancel(&mut self) -> Result<(), Self::Error> {
139 self.started = false;
140 Ok(())
141 }
142}
143
144#[cfg(test)]
145mod test {
146 use super::*;
147
148 #[test]
149 fn count_down() {
150 let mut clock = MockClock::new();
151 let mut timer = clock.get_timer();
152 timer.start(100.nanoseconds());
153 clock.tick(50.nanoseconds());
154 assert_eq!(timer.wait(), Err(nb::Error::WouldBlock));
155 clock.tick(50.nanoseconds());
156 assert_eq!(timer.wait(), Ok(()));
157 clock.tick(50.nanoseconds());
158 assert_eq!(timer.wait(), Err(nb::Error::WouldBlock));
159 clock.tick(50.nanoseconds());
160 assert_eq!(timer.wait(), Ok(()));
161 }
162}