embedded_flight_scheduler/
task.rs

1use crate::Error;
2use embedded_time::duration::Microseconds;
3
4/// An event containing the current time, available time, and state for a task.
5pub struct Event<'a, T> {
6    /// The state of the system running the scheduler.
7    pub state: &'a mut T,
8
9    /// The current time in microseconds.
10    pub now: Microseconds<u32>,
11
12    /// The available to run this task time (in microseconds).
13    pub available: Microseconds<u32>,
14}
15
16type TaskFn<T, E> = fn(Event<'_, T>) -> Result<(), E>;
17
18/// A task to run at specific frequency
19pub struct Task<T, E = Error> {
20    /// The function to run.
21    pub f: TaskFn<T, E>,
22
23    /// The desired frequency (in hz) to run the task.
24    pub hz: f32,
25
26    /// The max time for this task (in microseconds).
27    pub max_time_micros: u16,
28
29    /// Determines if this task should be run every time the scheduler loops.
30    pub is_high_priority: bool,
31
32    /// The last tick this task was ran.
33    pub last_run: u16,
34}
35
36impl<T, E> Task<T, E> {
37    /// Create a new task from the function to run.
38    pub fn new(f: TaskFn<T, E>) -> Self {
39        Self {
40            f,
41            hz: 0.,
42            max_time_micros: 0,
43            is_high_priority: false,
44            last_run: 0,
45        }
46    }
47
48    /// Create a new high priority task from the function to run.
49    pub fn high_priority(f: TaskFn<T, E>) -> Self {
50        Self::new(f).with_high_priority(true)
51    }
52
53    /// Builder method to set `hz` and return `self`
54    pub fn with_hz(mut self, hz: f32) -> Self {
55        self.hz = hz;
56        self
57    }
58
59    /// Builder method to set `max_time_micros` and return `self`
60    pub fn with_max_time(mut self, micros: u16) -> Self {
61        self.max_time_micros = micros;
62        self
63    }
64
65    /// Builder method to set `is_high_priority` and return `self`
66    pub fn with_high_priority(mut self, is_high_priority: bool) -> Self {
67        self.is_high_priority = is_high_priority;
68        self
69    }
70
71    /// Calculate the desired ticks between each run of the task
72    pub fn ticks(&self, loop_rate_hz: i16) -> i16 {
73        // A 0hz task should be ran at the rate of the scheduler loop
74        loop_rate_hz.checked_div(self.hz as i16).unwrap_or(1)
75    }
76
77    /// If this task is ready returns the ticks elapsed since the last run.
78    /// Otherwise this returns `None`.
79    pub fn ready(&self, current_tick: u16, ticks: i16) -> Option<u16> {
80        let dt = current_tick - self.last_run;
81
82        if (dt as i16) >= ticks {
83            Some(dt)
84        } else {
85            None
86        }
87    }
88
89    /// Run this task at the current tick.
90    pub fn run(&mut self, state: Event<'_, T>, tick: u16) -> Result<(), E> {
91        (self.f)(state)?;
92
93        // Record the tick counter when we ran
94        // This determines when we next run the event
95        self.last_run = tick;
96
97        Ok(())
98    }
99}