vex_rt/rtos/
loop.rs

1use core::time::Duration;
2
3use super::{time_since_start, GenericSleep, Instant, Selectable, Task};
4
5/// Provides a constant-period looping construct.
6pub struct Loop {
7    delta: Duration,
8    next: Instant,
9    cycle: usize,
10}
11
12impl Loop {
13    #[inline]
14    /// Creates a new loop object with a given period.
15    pub fn new(delta: Duration) -> Self {
16        Loop {
17            delta,
18            next: time_since_start() + delta,
19            cycle: 0,
20        }
21    }
22
23    /// Delays until the next loop cycle.
24    pub fn delay(&mut self) {
25        if let Some(d) = self.next.checked_sub_instant(time_since_start()) {
26            Task::delay(d);
27        }
28        self.next += self.delta;
29        self.cycle += 1;
30    }
31
32    #[inline]
33    /// Returns the current cycle index.
34    ///
35    /// This is initially 0 and increments each cycle (i.e., when
36    /// [`delay()`](Self::delay()) returns or `select` successfully
37    /// completes).
38    pub fn cycle(&self) -> usize {
39        self.cycle
40    }
41
42    #[inline]
43    /// Helper function to check whether the cycle index (see
44    /// [`cycle()`](Self::cycle())) is a multiple of `modulus`.
45    pub fn is_mod(&self, modulus: usize) -> bool {
46        self.cycle % modulus == 0
47    }
48
49    #[inline]
50    /// A [`Selectable`] event which occurs at the next loop cycle.
51    pub fn select(&'_ mut self) -> impl Selectable + '_ {
52        struct LoopSelect<'a>(&'a mut Loop);
53
54        impl<'a> Selectable for LoopSelect<'a> {
55            fn poll(self) -> Result<(), Self> {
56                if time_since_start() >= self.0.next {
57                    self.0.next += self.0.delta;
58                    self.0.cycle += 1;
59                    Ok(())
60                } else {
61                    Err(self)
62                }
63            }
64            fn sleep(&self) -> GenericSleep {
65                GenericSleep::Timestamp(self.0.next)
66            }
67        }
68
69        LoopSelect(self)
70    }
71}