frclib_core/hal/rt/notifier.rs
1//! Real Time Notifier HAL Driver
2
3use crate::units::time::Microsecond;
4
5/// The type of update to perform on the alarm
6#[derive(Debug, Clone, Copy)]
7pub enum NotifierUpdateType {
8 /// Will set alarm to trigger every X microseconds.
9 /// If canceled the alarm will stop re-priming and the current alarm will be removed
10 Periodic {
11 /// The period to trigger at
12 period: Microsecond,
13 /// If true, if an entire alarm is missed it will be ignored.
14 /// If false, missed alarms will build up and trigger as soon as possible until caught up.
15 skip_missed: bool,
16 },
17 /// Will set alarm to trigger at the specified time.
18 /// If canceled the current alarm will be removed
19 OneShot {
20 /// The time to trigger at
21 trigger_time: Microsecond,
22 },
23 /// Will set alarm to trigger at the specified time relative to the current time.
24 /// If canceled the current alarm will be removed
25 RelativeOneShot {
26 /// The time from now to trigger at
27 trigger_offset_time: Microsecond,
28 },
29}
30
31/// A trait that represents a platform specific alarm notifier handle.
32pub trait Notifier: Send + Sync {
33 /// Returns the name of the notifier for debugging purposes
34 fn get_name(&self) -> &str;
35
36 /// Updates the alarm to trigger according to the specified update type
37 fn update_alarm(&mut self, update: NotifierUpdateType);
38 /// Cancels the alarm
39 fn cancel_alarm(&mut self);
40 /// Returns the time the alarm was triggered
41 fn wait_for_alarm(&mut self) -> Microsecond;
42}
43type NotifierHandle = Box<dyn Notifier>;
44
45/// A platform specific alarm notifier driver.
46///
47/// # Implementation
48/// Most of the work for this driver involves setting up the interrupt logic.
49/// It's reccomended for the notifier thread to be created on first use of the driver
50/// and have the thread be high priority.
51///
52/// # Safety
53/// ## Thread Safety
54/// It's up to the driver developer to ensure that the driver is thread safe.
55///
56/// # Development Resources
57/// - [WPILib Rio Notifier](https://github.com/wpilibsuite/allwpilib/blob/main/hal/src/main/native/athena/Notifier.cpp)
58/// - [WPILib Sim Notifier](https://github.com/wpilibsuite/allwpilib/blob/main/hal/src/main/native/sim/Notifier.cpp)
59/// - [Spin Sleep](https://github.com/alexheretic/spin-sleep)
60/// - [Condition Variable](`std::sync::Condvar`)
61pub trait NotifierDriver: 'static {
62 /// Creates a new notifier
63 fn new_notifier() -> impl Notifier;
64}
65
66/// A platform specific alarm notifier driver vtable.
67#[derive(Debug, Clone, Copy)]
68pub struct NotifierVTable {
69 pub(crate) new_notifier: fn() -> NotifierHandle,
70}
71impl NotifierVTable {
72 pub(crate) fn from_driver<T: NotifierDriver>() -> Self {
73 assert!(
74 std::mem::size_of::<T>() == 0,
75 "Notifier Driver must be zero sized"
76 );
77 Self {
78 new_notifier: || Box::new(T::new_notifier()),
79 }
80 }
81 /// Creates a new notifier
82 #[must_use]
83 pub fn new_notifier(&self) -> NotifierHandle {
84 (self.new_notifier)()
85 }
86}