aboutsummaryrefslogtreecommitdiff
path: root/rtic-time/src/monotonic
diff options
context:
space:
mode:
Diffstat (limited to 'rtic-time/src/monotonic')
-rw-r--r--rtic-time/src/monotonic/embedded_hal_macros.rs77
-rw-r--r--rtic-time/src/monotonic/timer_queue_based_monotonic.rs113
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)
+ }
+}