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