Skip to main content

kernel/hil/
time.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Hardware agnostic interfaces for time and timers within the Tock
6//! kernel.
7//!
8//! These traits are designed to be able encompass the wide
9//! variety of hardware counters in a general yet efficient way. They
10//! abstract the frequency of a counter through the `Frequency` trait
11//! and the width of a time value through the `Ticks`
12//! trait. Higher-level software abstractions should generally rely on
13//! standard and common implementations of these traits (e.g.. `u32`
14//! ticks and 16MHz frequency).  Hardware counter implementations and
15//! peripherals can represent the actual hardware units an translate
16//! into these more general ones.
17
18use crate::ErrorCode;
19use core::cmp::Ordering;
20use core::fmt;
21
22/// An integer type defining the width of a time value, which allows
23/// clients to know when wraparound will occur.
24pub trait Ticks: Clone + Copy + From<u32> + fmt::Debug + Ord + PartialOrd + Eq {
25    /// Width of the actual underlying timer in bits.
26    ///
27    /// The maximum value that *will* be attained by this timer should
28    /// be `(2 ** width) - 1`. In other words, the timer will wrap at
29    /// exactly `width` bits, and then continue counting at `0`.
30    ///
31    /// The return value is a `u32`, in accordance with the bit widths
32    /// specified using the BITS associated const on Rust integer
33    /// types.
34    fn width() -> u32;
35
36    /// Converts the type into a `usize`, stripping the higher bits
37    /// it if it is larger than `usize` and filling the higher bits
38    /// with 0 if it is smaller than `usize`.
39    fn into_usize(self) -> usize;
40
41    /// The amount of bits required to left-justify this ticks value
42    /// range (filling the lower bits with `0`) for it wrap at `(2 **
43    /// usize::BITS) - 1` bits. For timers with a `width` larger than
44    /// usize, this value will be `0` (i.e., they can simply be
45    /// truncated to usize::BITS bits).
46    fn usize_padding() -> u32 {
47        usize::BITS.saturating_sub(Self::width())
48    }
49
50    /// Converts the type into a `usize`, left-justified and
51    /// right-padded with `0` such that it is guaranteed to wrap at
52    /// `(2 ** usize::BITS) - 1`. If it is larger than usize::BITS
53    /// bits, any higher bits are stripped.
54    ///
55    /// The resulting tick rate will possibly be higher (multiplied by
56    /// `2 ** usize_padding()`). Use `usize_left_justified_scale_freq`
57    /// to convert the underlying timer's frequency into the padded
58    /// ticks frequency in Hertz.
59    fn into_usize_left_justified(self) -> usize {
60        self.into_usize() << Self::usize_padding()
61    }
62
63    /// Convert the generic [`Frequency`] argument into a frequency
64    /// (Hertz) describing a left-justified ticks value as returned by
65    /// [`Ticks::into_usize_left_justified`].
66    fn usize_left_justified_scale_freq<F: Frequency>() -> u32 {
67        F::frequency() << Self::usize_padding()
68    }
69
70    /// Converts the type into a `u32`, stripping the higher bits
71    /// it if it is larger than `u32` and filling the higher bits
72    /// with 0 if it is smaller than `u32`. Included as a simple
73    /// helper since Tock uses `u32` pervasively and most platforms
74    /// are 32 bits.
75    fn into_u32(self) -> u32;
76
77    /// The amount of bits required to left-justify this ticks value
78    /// range (filling the lower bits with `0`) for it wrap at `(2 **
79    /// 32) - 1` bits. For timers with a `width` larger than 32, this
80    /// value will be `0` (i.e., they can simply be truncated to
81    /// 32-bits).
82    ///
83    /// The return value is a `u32`, in accordance with the bit widths
84    /// specified using the BITS associated const on Rust integer
85    /// types.
86    fn u32_padding() -> u32 {
87        u32::BITS.saturating_sub(Self::width())
88    }
89
90    /// Converts the type into a `u32`, left-justified and
91    /// right-padded with `0` such that it is guaranteed to wrap at
92    /// `(2 ** 32) - 1`. If it is larger than 32-bits, any higher bits
93    /// are stripped.
94    ///
95    /// The resulting tick rate will possibly be higher (multiplied by
96    /// `2 ** u32_padding()`). Use `u32_left_justified_scale_freq` to
97    /// convert the underlying timer's frequency into the padded ticks
98    /// frequency in Hertz.
99    fn into_u32_left_justified(self) -> u32 {
100        self.into_u32() << Self::u32_padding()
101    }
102
103    /// Convert the generic [`Frequency`] argument into a frequency
104    /// (Hertz) describing a left-justified ticks value as returned by
105    /// [`Ticks::into_u32_left_justified`].
106    fn u32_left_justified_scale_freq<F: Frequency>() -> u32 {
107        F::frequency() << Self::u32_padding()
108    }
109
110    /// Add two values, wrapping around on overflow using standard
111    /// unsigned arithmetic.
112    fn wrapping_add(self, other: Self) -> Self;
113    /// Subtract two values, wrapping around on underflow using standard
114    /// unsigned arithmetic.
115    fn wrapping_sub(self, other: Self) -> Self;
116
117    /// Returns whether the value is in the range of [`start, `end`) using
118    /// unsigned arithmetic and considering wraparound. It returns `true`
119    /// if, incrementing from `start`, the value will be reached before `end`.
120    /// Put another way, it returns `(self - start) < (end - start)` in
121    /// unsigned arithmetic.
122    fn within_range(self, start: Self, end: Self) -> bool;
123
124    /// Returns the maximum value of this type, which should be (2^width)-1.
125    fn max_value() -> Self;
126
127    /// Returns the half the maximum value of this type, which should be (2^width-1).
128    fn half_max_value() -> Self;
129
130    /// Converts the specified val into this type if it fits otherwise the
131    /// `max_value()` is returned
132    fn from_or_max(val: u64) -> Self;
133
134    /// Scales the ticks by the specified numerator and denominator. If the resulting value would
135    /// be greater than u32,`u32::MAX` is returned instead
136    fn saturating_scale(self, numerator: u32, denominator: u32) -> u32;
137}
138
139/// Represents a clock's frequency in Hz, allowing code to transform
140/// between computer time units and wall clock time. It is typically
141/// an associated type for an implementation of the `Time` trait.
142pub trait Frequency {
143    /// Returns frequency in Hz.
144    fn frequency() -> u32;
145}
146
147/// Represents a moment in time, obtained by calling `now`.
148pub trait Time {
149    /// The number of ticks per second
150    type Frequency: Frequency;
151    /// The width of a time value
152    type Ticks: Ticks;
153
154    /// Returns a timestamp. Depending on the implementation of
155    /// Time, this could represent either a static timestamp or
156    /// a sample of a counter; if an implementation relies on
157    /// it being constant or changing it should use `Timestamp`
158    /// or `Counter`.
159    fn now(&self) -> Self::Ticks;
160}
161
162pub trait ConvertTicks<T: Ticks> {
163    /// Returns the number of ticks in the provided number of seconds,
164    /// rounding down any fractions. If the value overflows Ticks it
165    /// returns `Ticks::max_value()`.
166    fn ticks_from_seconds(&self, s: u32) -> T;
167
168    /// Returns the number of ticks in the provided number of milliseconds,
169    /// rounding down any fractions. If the value overflows Ticks it
170    /// returns `Ticks::max_value()`.
171    fn ticks_from_ms(&self, ms: u32) -> T;
172
173    /// Returns the number of ticks in the provided number of microseconds,
174    /// rounding down any fractions. If the value overflows Ticks it
175    /// returns `Ticks::max_value()`.
176    fn ticks_from_us(&self, us: u32) -> T;
177
178    /// Returns the number of seconds in the provided number of ticks,
179    /// rounding down any fractions. If the value overflows u32, `u32::MAX`
180    /// is returned,
181    fn ticks_to_seconds(&self, tick: T) -> u32;
182
183    /// Returns the number of milliseconds in the provided number of ticks,
184    /// rounding down any fractions. If the value overflows u32, `u32::MAX`
185    /// is returned,
186    fn ticks_to_ms(&self, tick: T) -> u32;
187
188    /// Returns the number of microseconds in the provided number of ticks,
189    /// rounding down any fractions. If the value overflows u32, `u32::MAX`
190    /// is returned,
191    fn ticks_to_us(&self, tick: T) -> u32;
192}
193
194impl<T: Time + ?Sized> ConvertTicks<<T as Time>::Ticks> for T {
195    #[inline]
196    fn ticks_from_seconds(&self, s: u32) -> <T as Time>::Ticks {
197        let val = <T as Time>::Frequency::frequency() as u64 * s as u64;
198        <T as Time>::Ticks::from_or_max(val)
199    }
200    #[inline]
201    fn ticks_from_ms(&self, ms: u32) -> <T as Time>::Ticks {
202        let val = <T as Time>::Frequency::frequency() as u64 * ms as u64;
203        <T as Time>::Ticks::from_or_max(val / 1_000)
204    }
205    #[inline]
206    fn ticks_from_us(&self, us: u32) -> <T as Time>::Ticks {
207        let val = <T as Time>::Frequency::frequency() as u64 * us as u64;
208        <T as Time>::Ticks::from_or_max(val / 1_000_000)
209    }
210
211    #[inline]
212    fn ticks_to_seconds(&self, tick: <T as Time>::Ticks) -> u32 {
213        tick.saturating_scale(1, <T as Time>::Frequency::frequency())
214    }
215    #[inline]
216    fn ticks_to_ms(&self, tick: <T as Time>::Ticks) -> u32 {
217        tick.saturating_scale(1_000, <T as Time>::Frequency::frequency())
218    }
219    #[inline]
220    fn ticks_to_us(&self, tick: <T as Time>::Ticks) -> u32 {
221        tick.saturating_scale(1_000_000, <T as Time>::Frequency::frequency())
222    }
223}
224
225/// Represents a static moment in time, that does not change over
226/// repeated calls to `Time::now`.
227pub trait Timestamp: Time {}
228
229/// Callback handler for when a counter has overflowed past its maximum
230/// value and returned to 0.
231pub trait OverflowClient {
232    fn overflow(&self);
233}
234
235/// Represents a free-running hardware counter that can be started and stopped.
236pub trait Counter<'a>: Time {
237    /// Starts the free-running hardware counter. Valid `Result<(), ErrorCode>` values are:
238    ///   - `Ok(())`: the counter is now running
239    ///   - `Err(ErrorCode::OFF)`: underlying clocks or other hardware resources
240    ///     are not on, such that the counter cannot start.
241    ///   - `Err(ErrorCode::FAIL)`: unidentified failure, counter is not running.
242    ///
243    /// After a successful call to `start`, `is_running` MUST return true.
244    fn start(&self) -> Result<(), ErrorCode>;
245
246    /// Stops the free-running hardware counter. Valid `Result<(), ErrorCode>` values are:
247    ///   - `Ok(())`: the counter is now stopped. No further
248    ///     overflow callbacks will be invoked.
249    ///   - `Err(ErrorCode::BUSY)`: the counter is in use in a way that means it
250    ///     cannot be stopped and is busy.
251    ///   - `Err(ErrorCode::FAIL)`: unidentified failure, counter is running.
252    ///
253    /// After a successful call to `stop`, `is_running` MUST return false.
254    fn stop(&self) -> Result<(), ErrorCode>;
255
256    /// Resets the counter to 0. This may introduce jitter on the counter.
257    /// Resetting the counter has no effect on any pending overflow callbacks.
258    /// If a client needs to reset and clear pending callbacks it should
259    /// call `stop` before `reset`.
260    /// Valid `Result<(), ErrorCode>` values are:
261    ///   - `Ok(())`: the counter was reset to 0.
262    ///   - `Err(ErrorCode::FAIL)`: the counter was not reset to 0.
263    fn reset(&self) -> Result<(), ErrorCode>;
264
265    /// Returns whether the counter is currently running.
266    fn is_running(&self) -> bool;
267}
268
269/// Extension trait for counters that support hardware overflow notifications.
270#[deprecated(
271    note = "set_overflow_client never used so moved to an independent trait. Set to be removed in future releases unless a concrete use case is raised.",
272    since = "2.3.0"
273)]
274pub trait CounterOverflow<'a>: Counter<'a> {
275    fn set_overflow_client(&self, client: &'a dyn OverflowClient);
276}
277
278/// Callback handler for when an Alarm fires (a `Counter` reaches a specific
279/// value).
280pub trait AlarmClient {
281    /// Callback indicating the alarm time has been reached. The alarm
282    /// MUST be disabled when this is called. If a new alarm is needed,
283    /// the client can call `Alarm::set_alarm`.
284    fn alarm(&self);
285}
286
287/// Interface for receiving notification when a particular time
288/// (`Counter` value) is reached.
289///
290/// Clients use the [`AlarmClient`] trait to
291/// signal when the counter has reached a pre-specified value set in
292/// [`set_alarm`](#tymethod.set_alarm). Alarms are intended for
293/// low-level time needs that require precision (i.e., firing on a
294/// precise clock tick). Software that needs more functionality but
295/// can tolerate some jitter should use the `Timer` trait instead.
296pub trait Alarm<'a>: Time {
297    /// Specify the callback for when the counter reaches the alarm
298    /// value. If there was a previously installed callback this call
299    /// replaces it.
300    fn set_alarm_client(&self, client: &'a dyn AlarmClient);
301
302    /// Specify when the callback should be called and enable it. The
303    /// callback will be enqueued when `Time::now() == reference + dt`. The
304    /// callback itself may not run exactly at this time, due to delays.
305    /// However, it it assured to execute *after* `reference + dt`: it can
306    /// be delayed but will never fire early. The method takes `reference`
307    /// and `dt` rather than a single value denoting the counter value so it
308    /// can distinguish between alarms which have very recently already
309    /// passed and those in the far far future (see #1651).
310    fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks);
311
312    /// Return the current alarm value. This is undefined at boot and
313    /// otherwise returns `now + dt` from the last call to `set_alarm`.
314    fn get_alarm(&self) -> Self::Ticks;
315
316    /// Disable the alarm and stop it from firing in the future.
317    /// Valid `Result<(), ErrorCode>` codes are:
318    ///   - `Ok(())` the alarm has been disarmed and will not invoke
319    ///     the callback in the future
320    ///   - `Err(ErrorCode::FAIL)` the alarm could not be disarmed and will invoke
321    ///     the callback in the future
322    fn disarm(&self) -> Result<(), ErrorCode>;
323
324    /// Returns whether the alarm is currently armed. Note that this
325    /// does not reliably indicate whether there will be a future
326    /// callback: it is possible that the alarm has triggered (and
327    /// disarmed) and a callback is pending and has not been called yet.
328    /// In this case it possible for `is_armed` to return false yet to
329    /// receive a callback.
330    fn is_armed(&self) -> bool;
331
332    /// Return the minimum dt value that is supported. Any dt smaller than
333    /// this will automatically be increased to this minimum value.
334    fn minimum_dt(&self) -> Self::Ticks;
335}
336
337/// Callback handler for when a timer fires.
338pub trait TimerClient {
339    fn timer(&self);
340}
341
342/// Interface for controlling callbacks when an interval has passed.
343///
344/// This interface is intended for software that requires repeated
345/// and/or one-shot timers and is willing to experience some jitter or
346/// imprecision in return for a simpler API that doesn't require
347/// actual calculation of counter values. Software that requires more
348/// precisely timed callbacks should use the `Alarm` trait instead.
349pub trait Timer<'a>: Time {
350    /// Specify the callback to invoke when the timer interval expires.
351    /// If there was a previously installed callback this call replaces it.
352    fn set_timer_client(&self, client: &'a dyn TimerClient);
353
354    /// Start a one-shot timer that will invoke the callback at least
355    /// `interval` ticks in the future. If there is a timer currently pending,
356    /// calling this cancels that previous timer. After a callback is invoked
357    /// for a one shot timer, the timer MUST NOT invoke the callback again
358    /// unless a new timer is started (either with repeating or one shot).
359    /// Returns the actual interval for the timer that was registered.
360    /// This MUST NOT be smaller than `interval` but MAY be larger.
361    fn oneshot(&self, interval: Self::Ticks) -> Self::Ticks;
362
363    /// Start a repeating timer that will invoke the callback every
364    /// `interval` ticks in the future. If there is a timer currently
365    /// pending, calling this cancels that previous timer.
366    /// Returns the actual interval for the timer that was registered.
367    /// This MUST NOT be smaller than `interval` but MAY be larger.
368    fn repeating(&self, interval: Self::Ticks) -> Self::Ticks;
369
370    /// Return the interval of the last requested timer.
371    fn interval(&self) -> Option<Self::Ticks>;
372
373    /// Return if the last requested timer is a one-shot timer.
374    fn is_oneshot(&self) -> bool;
375
376    /// Return if the last requested timer is a repeating timer.
377    fn is_repeating(&self) -> bool;
378
379    /// Return how many ticks are remaining until the next callback,
380    /// or None if the timer is disabled.  This call is useful because
381    /// there may be non-negligible delays between when a timer was
382    /// requested and it was actually scheduled. Therefore, since a
383    /// timer's start might be delayed slightly, the time remaining
384    /// might be slightly higher than one would expect if one
385    /// calculated it right before the call to start the timer.
386    fn time_remaining(&self) -> Option<Self::Ticks>;
387
388    /// Returns whether there is currently a timer enabled and so a callback
389    /// will be expected in the future. If `is_enabled` returns false then
390    /// the implementation MUST NOT invoke a callback until a call to `oneshot`
391    /// or `repeating` restarts the timer.
392    fn is_enabled(&self) -> bool;
393
394    /// Cancel the current timer, if any. Value `Result<(), ErrorCode>` values are:
395    ///  - `Ok(())`: no callback will be invoked in the future.
396    ///  - `Err(ErrorCode::FAIL)`: the timer could not be cancelled and a callback
397    ///    will be invoked in the future.
398    fn cancel(&self) -> Result<(), ErrorCode>;
399}
400
401// The following "frequencies" are represented as variant-less enums. Because
402// they can never be constructed, it forces them to be used purely as
403// type-markers which are guaranteed to be elided at runtime.
404
405/// 600MHz `Frequency`
406#[derive(Debug)]
407pub enum Freq600MHz {}
408impl Frequency for Freq600MHz {
409    fn frequency() -> u32 {
410        600_000_000
411    }
412}
413
414/// 100MHz `Frequency`
415#[derive(Debug)]
416pub enum Freq100MHz {}
417impl Frequency for Freq100MHz {
418    fn frequency() -> u32 {
419        100_000_000
420    }
421}
422
423/// 16MHz `Frequency`
424#[derive(Debug)]
425pub enum Freq16MHz {}
426impl Frequency for Freq16MHz {
427    fn frequency() -> u32 {
428        16_000_000
429    }
430}
431
432/// 10MHz `Frequency`
433pub enum Freq10MHz {}
434impl Frequency for Freq10MHz {
435    fn frequency() -> u32 {
436        10_000_000
437    }
438}
439
440/// 1MHz `Frequency`
441#[derive(Debug)]
442pub enum Freq1MHz {}
443impl Frequency for Freq1MHz {
444    fn frequency() -> u32 {
445        1_000_000
446    }
447}
448
449/// 32.768KHz `Frequency`
450#[derive(Debug)]
451pub enum Freq32KHz {}
452impl Frequency for Freq32KHz {
453    fn frequency() -> u32 {
454        32_768
455    }
456}
457
458/// 16KHz `Frequency`
459#[derive(Debug)]
460pub enum Freq16KHz {}
461impl Frequency for Freq16KHz {
462    fn frequency() -> u32 {
463        16_000
464    }
465}
466
467/// 1KHz `Frequency`
468#[derive(Debug)]
469pub enum Freq1KHz {}
470impl Frequency for Freq1KHz {
471    fn frequency() -> u32 {
472        1_000
473    }
474}
475
476/// u32 `Ticks`
477#[derive(Clone, Copy, Debug)]
478pub struct Ticks32(u32);
479
480impl From<u32> for Ticks32 {
481    fn from(val: u32) -> Self {
482        Ticks32(val)
483    }
484}
485
486impl Ticks for Ticks32 {
487    fn width() -> u32 {
488        32
489    }
490
491    fn into_usize(self) -> usize {
492        self.0 as usize
493    }
494
495    fn into_u32(self) -> u32 {
496        self.0
497    }
498
499    fn wrapping_add(self, other: Self) -> Self {
500        Ticks32(self.0.wrapping_add(other.0))
501    }
502
503    fn wrapping_sub(self, other: Self) -> Self {
504        Ticks32(self.0.wrapping_sub(other.0))
505    }
506
507    fn within_range(self, start: Self, end: Self) -> bool {
508        self.wrapping_sub(start).0 < end.wrapping_sub(start).0
509    }
510
511    /// Returns the maximum value of this type, which should be (2^width)-1.
512    fn max_value() -> Self {
513        Ticks32(0xFFFFFFFF)
514    }
515
516    /// Returns the half the maximum value of this type, which should be (2^width-1).
517    fn half_max_value() -> Self {
518        Self(1 + (Self::max_value().0 / 2))
519    }
520
521    #[inline]
522    fn from_or_max(val: u64) -> Self {
523        if val < Self::max_value().0 as u64 {
524            Self::from(val as u32)
525        } else {
526            Self::max_value()
527        }
528    }
529
530    #[inline]
531    fn saturating_scale(self, numerator: u32, denominator: u32) -> u32 {
532        let scaled = self.0 as u64 * numerator as u64 / denominator as u64;
533        if scaled < u32::MAX as u64 {
534            scaled as u32
535        } else {
536            u32::MAX
537        }
538    }
539}
540
541impl PartialOrd for Ticks32 {
542    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
543        Some(self.cmp(other))
544    }
545}
546
547impl Ord for Ticks32 {
548    fn cmp(&self, other: &Self) -> Ordering {
549        self.0.cmp(&other.0)
550    }
551}
552
553impl PartialEq for Ticks32 {
554    fn eq(&self, other: &Self) -> bool {
555        self.0 == other.0
556    }
557}
558
559impl Eq for Ticks32 {}
560
561/// 24-bit `Ticks`
562#[derive(Clone, Copy, Debug)]
563pub struct Ticks24(u32);
564
565impl Ticks24 {
566    pub const MASK: u32 = 0x00FFFFFF;
567}
568
569impl From<u32> for Ticks24 {
570    fn from(val: u32) -> Self {
571        Ticks24(val & Self::MASK)
572    }
573}
574
575impl Ticks for Ticks24 {
576    fn width() -> u32 {
577        24
578    }
579
580    fn into_usize(self) -> usize {
581        self.0 as usize
582    }
583
584    fn into_u32(self) -> u32 {
585        self.0
586    }
587
588    fn wrapping_add(self, other: Self) -> Self {
589        Ticks24(self.0.wrapping_add(other.0) & Self::MASK)
590    }
591
592    fn wrapping_sub(self, other: Self) -> Self {
593        Ticks24(self.0.wrapping_sub(other.0) & Self::MASK)
594    }
595
596    fn within_range(self, start: Self, end: Self) -> bool {
597        self.wrapping_sub(start).0 < end.wrapping_sub(start).0
598    }
599
600    /// Returns the maximum value of this type, which should be (2^width)-1.
601    fn max_value() -> Self {
602        Ticks24(Self::MASK)
603    }
604
605    /// Returns the half the maximum value of this type, which should be (2^width-1).
606    fn half_max_value() -> Self {
607        Self(1 + (Self::max_value().0 / 2))
608    }
609
610    #[inline]
611    fn from_or_max(val: u64) -> Self {
612        if val < Self::max_value().0 as u64 {
613            Self::from(val as u32)
614        } else {
615            Self::max_value()
616        }
617    }
618
619    #[inline]
620    fn saturating_scale(self, numerator: u32, denominator: u32) -> u32 {
621        let scaled = self.0 as u64 * numerator as u64 / denominator as u64;
622        if scaled < u32::MAX as u64 {
623            scaled as u32
624        } else {
625            u32::MAX
626        }
627    }
628}
629
630impl PartialOrd for Ticks24 {
631    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
632        Some(self.cmp(other))
633    }
634}
635
636impl Ord for Ticks24 {
637    fn cmp(&self, other: &Self) -> Ordering {
638        self.0.cmp(&other.0)
639    }
640}
641
642impl PartialEq for Ticks24 {
643    fn eq(&self, other: &Self) -> bool {
644        self.0 == other.0
645    }
646}
647
648impl Eq for Ticks24 {}
649
650/// 16-bit `Ticks`
651#[derive(Clone, Copy, Debug)]
652pub struct Ticks16(u16);
653
654impl From<u16> for Ticks16 {
655    fn from(val: u16) -> Self {
656        Ticks16(val)
657    }
658}
659
660impl From<u32> for Ticks16 {
661    fn from(val: u32) -> Self {
662        Ticks16((val & 0xffff) as u16)
663    }
664}
665
666impl Ticks16 {
667    pub fn into_u16(self) -> u16 {
668        self.0
669    }
670}
671
672impl Ticks for Ticks16 {
673    fn width() -> u32 {
674        16
675    }
676
677    fn into_usize(self) -> usize {
678        self.0 as usize
679    }
680
681    fn into_u32(self) -> u32 {
682        self.0 as u32
683    }
684
685    fn wrapping_add(self, other: Self) -> Self {
686        Ticks16(self.0.wrapping_add(other.0))
687    }
688
689    fn wrapping_sub(self, other: Self) -> Self {
690        Ticks16(self.0.wrapping_sub(other.0))
691    }
692
693    fn within_range(self, start: Self, end: Self) -> bool {
694        self.wrapping_sub(start).0 < end.wrapping_sub(start).0
695    }
696
697    /// Returns the maximum value of this type, which should be (2^width)-1.
698    fn max_value() -> Self {
699        Ticks16(0xFFFF)
700    }
701
702    /// Returns the half the maximum value of this type, which should be (2^width-1).
703    fn half_max_value() -> Self {
704        Self(1 + (Self::max_value().0 / 2))
705    }
706
707    #[inline]
708    fn from_or_max(val: u64) -> Self {
709        if val < Self::max_value().0 as u64 {
710            Self::from(val as u32)
711        } else {
712            Self::max_value()
713        }
714    }
715
716    #[inline]
717    fn saturating_scale(self, numerator: u32, denominator: u32) -> u32 {
718        let scaled = self.0 as u64 * numerator as u64 / denominator as u64;
719        if scaled < u32::MAX as u64 {
720            scaled as u32
721        } else {
722            u32::MAX
723        }
724    }
725}
726
727impl PartialOrd for Ticks16 {
728    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
729        Some(self.cmp(other))
730    }
731}
732
733impl Ord for Ticks16 {
734    fn cmp(&self, other: &Self) -> Ordering {
735        self.0.cmp(&other.0)
736    }
737}
738
739impl PartialEq for Ticks16 {
740    fn eq(&self, other: &Self) -> bool {
741        self.0 == other.0
742    }
743}
744
745impl Eq for Ticks16 {}
746
747/// 64-bit `Ticks`
748#[derive(Clone, Copy, Debug)]
749pub struct Ticks64(u64);
750
751impl Ticks64 {
752    pub fn into_u64(self) -> u64 {
753        self.0
754    }
755}
756
757impl From<u32> for Ticks64 {
758    fn from(val: u32) -> Self {
759        Ticks64(val as u64)
760    }
761}
762
763impl From<u64> for Ticks64 {
764    fn from(val: u64) -> Self {
765        Ticks64(val)
766    }
767}
768
769impl Ticks for Ticks64 {
770    fn width() -> u32 {
771        64
772    }
773
774    fn into_usize(self) -> usize {
775        self.0 as usize
776    }
777
778    fn into_u32(self) -> u32 {
779        self.0 as u32
780    }
781
782    fn wrapping_add(self, other: Self) -> Self {
783        Ticks64(self.0.wrapping_add(other.0))
784    }
785
786    fn wrapping_sub(self, other: Self) -> Self {
787        Ticks64(self.0.wrapping_sub(other.0))
788    }
789
790    fn within_range(self, start: Self, end: Self) -> bool {
791        self.wrapping_sub(start).0 < end.wrapping_sub(start).0
792    }
793
794    /// Returns the maximum value of this type, which should be (2^width)-1.
795    fn max_value() -> Self {
796        Ticks64(!0u64)
797    }
798
799    /// Returns the half the maximum value of this type, which should be (2^width-1).
800    fn half_max_value() -> Self {
801        Self(1 + (Self::max_value().0 / 2))
802    }
803
804    #[inline]
805    fn from_or_max(val: u64) -> Self {
806        Self(val)
807    }
808
809    #[inline]
810    fn saturating_scale(self, num: u32, den: u32) -> u32 {
811        let scaled = self.0.saturating_mul(num as u64) / den as u64;
812        if scaled < u32::MAX as u64 {
813            scaled as u32
814        } else {
815            u32::MAX
816        }
817    }
818}
819
820impl PartialOrd for Ticks64 {
821    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
822        Some(self.cmp(other))
823    }
824}
825
826impl Ord for Ticks64 {
827    fn cmp(&self, other: &Self) -> Ordering {
828        self.0.cmp(&other.0)
829    }
830}
831
832impl PartialEq for Ticks64 {
833    fn eq(&self, other: &Self) -> bool {
834        self.0 == other.0
835    }
836}
837
838impl Eq for Ticks64 {}
839
840#[cfg(test)]
841mod tests {
842    use super::*;
843
844    struct Test1MHz64();
845    impl Time for Test1MHz64 {
846        type Frequency = Freq1MHz;
847        type Ticks = Ticks64;
848
849        fn now(&self) -> Self::Ticks {
850            0u32.into()
851        }
852    }
853
854    #[test]
855    fn test_from_ticks64() {
856        let s = Test1MHz64().ticks_to_seconds(1_000_000u32.into());
857        assert_eq!(s, 1);
858
859        let ms = Test1MHz64().ticks_to_ms(1_000_000u32.into());
860        assert_eq!(ms, 1_000);
861
862        let us = Test1MHz64().ticks_to_us(1_000_000u32.into());
863        assert_eq!(us, 1_000_000);
864
865        let s = Test1MHz64().ticks_to_seconds((1_000_000u64 << 31).into());
866        assert_eq!(s, 1 << 31);
867
868        let ms = Test1MHz64().ticks_to_ms((1_000_000u64 << 31).into());
869        assert_eq!(ms, !0u32);
870
871        let us = Test1MHz64().ticks_to_us((1_000_000u64 << 31).into());
872        assert_eq!(us, !0u32);
873    }
874
875    #[test]
876    fn test_to_ticks64() {
877        let t = Test1MHz64().ticks_from_seconds(1);
878        assert_eq!(t.into_u32(), 1_000_000);
879
880        let t = Test1MHz64().ticks_from_ms(1);
881        assert_eq!(t.into_u32(), 1_000);
882
883        let t = Test1MHz64().ticks_from_us(1);
884        assert_eq!(t.into_u32(), 1);
885
886        let t = Test1MHz64().ticks_from_seconds(1 << 31);
887        assert_eq!(t.into_u64(), 1_000_000u64 << 31);
888    }
889
890    struct Test1KHz16();
891    impl Time for Test1KHz16 {
892        type Frequency = Freq1KHz;
893        type Ticks = Ticks16;
894
895        fn now(&self) -> Self::Ticks {
896            0u32.into()
897        }
898    }
899
900    #[test]
901    fn test_from_ticks16() {
902        let s = Test1KHz16().ticks_to_seconds(1_000u32.into());
903        assert_eq!(s, 1);
904
905        let ms = Test1KHz16().ticks_to_ms(1_000u32.into());
906        assert_eq!(ms, 1_000);
907
908        let us = Test1KHz16().ticks_to_us(1_000u32.into());
909        assert_eq!(us, 1_000_000);
910    }
911
912    #[test]
913    fn test_to_ticks16() {
914        let t = Test1KHz16().ticks_from_seconds(1);
915        assert_eq!(t.into_u32(), 1_000);
916
917        let t = Test1KHz16().ticks_from_seconds(u32::MAX);
918        assert_eq!(t.into_u32(), u16::MAX as u32);
919
920        let t = Test1KHz16().ticks_from_seconds(66);
921        assert_eq!(t.into_u32(), u16::MAX as u32);
922
923        let t = Test1KHz16().ticks_from_seconds(65);
924        assert_eq!(t.into_u32(), 65_000);
925
926        let t = Test1KHz16().ticks_from_ms(1);
927        assert_eq!(t.into_u32(), 1);
928
929        let t = Test1KHz16().ticks_from_us(1);
930        assert_eq!(t.into_u32(), 0);
931    }
932
933    struct Test1KHz24();
934    impl Time for Test1KHz24 {
935        type Frequency = Freq1KHz;
936        type Ticks = Ticks24;
937
938        fn now(&self) -> Self::Ticks {
939            0u32.into()
940        }
941    }
942
943    #[test]
944    fn test_ticks24() {
945        let s = Test1KHz24().ticks_to_seconds(5_000_000u32.into());
946        assert_eq!(s, 5_000);
947
948        let ms = Test1KHz24().ticks_to_ms(5_000_000u32.into());
949        assert_eq!(ms, 5_000_000);
950
951        let us = Test1KHz24().ticks_to_us(5_000_000u32.into());
952        assert_eq!(us, u32::MAX);
953    }
954
955    #[test]
956    fn test_dyn_object() {
957        let time: &dyn Time<Frequency = Freq1KHz, Ticks = Ticks24> = &Test1KHz24();
958
959        let s = time.ticks_to_seconds(5_000_000u32.into());
960        assert_eq!(s, 5_000);
961
962        let ms = time.ticks_to_ms(5_000_000u32.into());
963        assert_eq!(ms, 5_000_000);
964
965        let us = time.ticks_to_us(5_000_000u32.into());
966        assert_eq!(us, u32::MAX);
967    }
968}