diff options
Diffstat (limited to 'rtic-time/src/monotonic')
| -rw-r--r-- | rtic-time/src/monotonic/embedded_hal_macros.rs | 77 | ||||
| -rw-r--r-- | rtic-time/src/monotonic/timer_queue_based_monotonic.rs | 113 |
2 files changed, 190 insertions, 0 deletions
diff --git a/rtic-time/src/monotonic/embedded_hal_macros.rs b/rtic-time/src/monotonic/embedded_hal_macros.rs new file mode 100644 index 0000000..25ac791 --- /dev/null +++ b/rtic-time/src/monotonic/embedded_hal_macros.rs @@ -0,0 +1,77 @@ +//! Macros that implement embedded-hal traits for Monotonics + +/// Implements [`embedded_hal::delay::DelayNs`] for a given monotonic. +#[macro_export] +macro_rules! impl_embedded_hal_delay_fugit { + ($t:ty) => { + impl $crate::embedded_hal::delay::DelayNs for $t { + fn delay_ns(&mut self, ns: u32) { + let now = <Self as $crate::Monotonic>::now(); + let mut done = + now + <Self as $crate::Monotonic>::Duration::nanos_at_least(ns.into()); + if now != done { + // Compensate for sub-tick uncertainty + done = done + <Self as $crate::Monotonic>::Duration::from_ticks(1); + } + + while <Self as $crate::Monotonic>::now() < done {} + } + + fn delay_us(&mut self, us: u32) { + let now = <Self as $crate::Monotonic>::now(); + let mut done = + now + <Self as $crate::Monotonic>::Duration::micros_at_least(us.into()); + if now != done { + // Compensate for sub-tick uncertainty + done = done + <Self as $crate::Monotonic>::Duration::from_ticks(1); + } + + while <Self as $crate::Monotonic>::now() < done {} + } + + fn delay_ms(&mut self, ms: u32) { + let now = <Self as $crate::Monotonic>::now(); + let mut done = + now + <Self as $crate::Monotonic>::Duration::millis_at_least(ms.into()); + if now != done { + // Compensate for sub-tick uncertainty + done = done + <Self as $crate::Monotonic>::Duration::from_ticks(1); + } + + while <Self as $crate::Monotonic>::now() < done {} + } + } + }; +} + +/// Implements [`embedded_hal_async::delay::DelayNs`] for a given monotonic. +#[macro_export] +macro_rules! impl_embedded_hal_async_delay_fugit { + ($t:ty) => { + impl $crate::embedded_hal_async::delay::DelayNs for $t { + #[inline] + async fn delay_ns(&mut self, ns: u32) { + <Self as $crate::Monotonic>::delay( + <Self as $crate::Monotonic>::Duration::nanos_at_least(ns.into()), + ) + .await; + } + + #[inline] + async fn delay_us(&mut self, us: u32) { + <Self as $crate::Monotonic>::delay( + <Self as $crate::Monotonic>::Duration::micros_at_least(us.into()), + ) + .await; + } + + #[inline] + async fn delay_ms(&mut self, ms: u32) { + <Self as $crate::Monotonic>::delay( + <Self as $crate::Monotonic>::Duration::millis_at_least(ms.into()), + ) + .await; + } + } + }; +} diff --git a/rtic-time/src/monotonic/timer_queue_based_monotonic.rs b/rtic-time/src/monotonic/timer_queue_based_monotonic.rs new file mode 100644 index 0000000..699958b --- /dev/null +++ b/rtic-time/src/monotonic/timer_queue_based_monotonic.rs @@ -0,0 +1,113 @@ +use crate::{timer_queue::TimerQueueBackend, TimeoutError}; + +use crate::Monotonic; + +/// A [`Monotonic`] that is backed by the [`TimerQueue`](crate::timer_queue::TimerQueue). +pub trait TimerQueueBasedMonotonic { + /// The backend for the timer queue + type Backend: TimerQueueBackend; + + /// The type for instant, defining an instant in time. + /// + /// **Note:** In all APIs in RTIC that use instants from this monotonic, this type will be used. + type Instant: TimerQueueBasedInstant<Ticks = <Self::Backend as TimerQueueBackend>::Ticks> + + core::ops::Add<Self::Duration, Output = Self::Instant> + + core::ops::Sub<Self::Duration, Output = Self::Instant> + + core::ops::Sub<Self::Instant, Output = Self::Duration>; + + /// The type for duration, defining a duration of time. + /// + /// **Note:** In all APIs in RTIC that use duration from this monotonic, this type will be used. + type Duration: TimerQueueBasedDuration<Ticks = <Self::Backend as TimerQueueBackend>::Ticks>; +} + +impl<T: TimerQueueBasedMonotonic> Monotonic for T { + type Instant = T::Instant; + type Duration = T::Duration; + + fn now() -> Self::Instant { + Self::Instant::from_ticks(T::Backend::timer_queue().now()) + } + + async fn delay(duration: Self::Duration) { + T::Backend::timer_queue().delay(duration.ticks()).await + } + + async fn delay_until(instant: Self::Instant) { + T::Backend::timer_queue().delay_until(instant.ticks()).await + } + + async fn timeout_at<F: core::future::Future>( + instant: Self::Instant, + future: F, + ) -> Result<F::Output, TimeoutError> { + T::Backend::timer_queue() + .timeout_at(instant.ticks(), future) + .await + } + + async fn timeout_after<F: core::future::Future>( + duration: Self::Duration, + future: F, + ) -> Result<F::Output, TimeoutError> { + T::Backend::timer_queue() + .timeout_after(duration.ticks(), future) + .await + } +} + +/// An instant that can be used in [`TimerQueueBasedMonotonic`]. +pub trait TimerQueueBasedInstant: Ord + Copy { + /// The internal type of the instant + type Ticks; + /// Convert from ticks to the instant + fn from_ticks(ticks: Self::Ticks) -> Self; + /// Convert the instant to ticks + fn ticks(self) -> Self::Ticks; +} + +/// A duration that can be used in [`TimerQueueBasedMonotonic`]. +pub trait TimerQueueBasedDuration: Copy { + /// The internal type of the duration + type Ticks; + /// Convert the duration to ticks + fn ticks(self) -> Self::Ticks; +} + +impl<const NOM: u32, const DENOM: u32> TimerQueueBasedInstant for fugit::Instant<u64, NOM, DENOM> { + type Ticks = u64; + fn from_ticks(ticks: Self::Ticks) -> Self { + Self::from_ticks(ticks) + } + fn ticks(self) -> Self::Ticks { + Self::ticks(&self) + } +} + +impl<const NOM: u32, const DENOM: u32> TimerQueueBasedInstant for fugit::Instant<u32, NOM, DENOM> { + type Ticks = u32; + fn from_ticks(ticks: Self::Ticks) -> Self { + Self::from_ticks(ticks) + } + fn ticks(self) -> Self::Ticks { + Self::ticks(&self) + } +} + +impl<const NOM: u32, const DENOM: u32> TimerQueueBasedDuration + for fugit::Duration<u64, NOM, DENOM> +{ + type Ticks = u64; + fn ticks(self) -> Self::Ticks { + Self::ticks(&self) + } +} + +impl<const NOM: u32, const DENOM: u32> TimerQueueBasedDuration + for fugit::Duration<u32, NOM, DENOM> +{ + type Ticks = u32; + fn ticks(self) -> Self::Ticks { + Self::ticks(&self) + } +} |
