Skip to main content

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}