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}