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)]
273pub trait CounterOverflow<'a>: Counter<'a> {
274 fn set_overflow_client(&self, client: &'a dyn OverflowClient);
275}
276
277/// Callback handler for when an Alarm fires (a `Counter` reaches a specific
278/// value).
279pub trait AlarmClient {
280 /// Callback indicating the alarm time has been reached. The alarm
281 /// MUST be disabled when this is called. If a new alarm is needed,
282 /// the client can call `Alarm::set_alarm`.
283 fn alarm(&self);
284}
285
286/// Interface for receiving notification when a particular time
287/// (`Counter` value) is reached.
288///
289/// Clients use the [`AlarmClient`](trait.AlarmClient.html) trait to
290/// signal when the counter has reached a pre-specified value set in
291/// [`set_alarm`](#tymethod.set_alarm). Alarms are intended for
292/// low-level time needs that require precision (i.e., firing on a
293/// precise clock tick). Software that needs more functionality but
294/// can tolerate some jitter should use the `Timer` trait instead.
295pub trait Alarm<'a>: Time {
296 /// Specify the callback for when the counter reaches the alarm
297 /// value. If there was a previously installed callback this call
298 /// replaces it.
299 fn set_alarm_client(&self, client: &'a dyn AlarmClient);
300
301 /// Specify when the callback should be called and enable it. The
302 /// callback will be enqueued when `Time::now() == reference + dt`. The
303 /// callback itself may not run exactly at this time, due to delays.
304 /// However, it it assured to execute *after* `reference + dt`: it can
305 /// be delayed but will never fire early. The method takes `reference`
306 /// and `dt` rather than a single value denoting the counter value so it
307 /// can distinguish between alarms which have very recently already
308 /// passed and those in the far far future (see #1651).
309 fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks);
310
311 /// Return the current alarm value. This is undefined at boot and
312 /// otherwise returns `now + dt` from the last call to `set_alarm`.
313 fn get_alarm(&self) -> Self::Ticks;
314
315 /// Disable the alarm and stop it from firing in the future.
316 /// Valid `Result<(), ErrorCode>` codes are:
317 /// - `Ok(())` the alarm has been disarmed and will not invoke
318 /// the callback in the future
319 /// - `Err(ErrorCode::FAIL)` the alarm could not be disarmed and will invoke
320 /// the callback in the future
321 fn disarm(&self) -> Result<(), ErrorCode>;
322
323 /// Returns whether the alarm is currently armed. Note that this
324 /// does not reliably indicate whether there will be a future
325 /// callback: it is possible that the alarm has triggered (and
326 /// disarmed) and a callback is pending and has not been called yet.
327 /// In this case it possible for `is_armed` to return false yet to
328 /// receive a callback.
329 fn is_armed(&self) -> bool;
330
331 /// Return the minimum dt value that is supported. Any dt smaller than
332 /// this will automatically be increased to this minimum value.
333 fn minimum_dt(&self) -> Self::Ticks;
334}
335
336/// Callback handler for when a timer fires.
337pub trait TimerClient {
338 fn timer(&self);
339}
340
341/// Interface for controlling callbacks when an interval has passed.
342///
343/// This interface is intended for software that requires repeated
344/// and/or one-shot timers and is willing to experience some jitter or
345/// imprecision in return for a simpler API that doesn't require
346/// actual calculation of counter values. Software that requires more
347/// precisely timed callbacks should use the `Alarm` trait instead.
348pub trait Timer<'a>: Time {
349 /// Specify the callback to invoke when the timer interval expires.
350 /// If there was a previously installed callback this call replaces it.
351 fn set_timer_client(&self, client: &'a dyn TimerClient);
352
353 /// Start a one-shot timer that will invoke the callback at least
354 /// `interval` ticks in the future. If there is a timer currently pending,
355 /// calling this cancels that previous timer. After a callback is invoked
356 /// for a one shot timer, the timer MUST NOT invoke the callback again
357 /// unless a new timer is started (either with repeating or one shot).
358 /// Returns the actual interval for the timer that was registered.
359 /// This MUST NOT be smaller than `interval` but MAY be larger.
360 fn oneshot(&self, interval: Self::Ticks) -> Self::Ticks;
361
362 /// Start a repeating timer that will invoke the callback every
363 /// `interval` ticks in the future. If there is a timer currently
364 /// pending, calling this cancels that previous timer.
365 /// Returns the actual interval for the timer that was registered.
366 /// This MUST NOT be smaller than `interval` but MAY be larger.
367 fn repeating(&self, interval: Self::Ticks) -> Self::Ticks;
368
369 /// Return the interval of the last requested timer.
370 fn interval(&self) -> Option<Self::Ticks>;
371
372 /// Return if the last requested timer is a one-shot timer.
373 fn is_oneshot(&self) -> bool;
374
375 /// Return if the last requested timer is a repeating timer.
376 fn is_repeating(&self) -> bool;
377
378 /// Return how many ticks are remaining until the next callback,
379 /// or None if the timer is disabled. This call is useful because
380 /// there may be non-negligible delays between when a timer was
381 /// requested and it was actually scheduled. Therefore, since a
382 /// timer's start might be delayed slightly, the time remaining
383 /// might be slightly higher than one would expect if one
384 /// calculated it right before the call to start the timer.
385 fn time_remaining(&self) -> Option<Self::Ticks>;
386
387 /// Returns whether there is currently a timer enabled and so a callback
388 /// will be expected in the future. If `is_enabled` returns false then
389 /// the implementation MUST NOT invoke a callback until a call to `oneshot`
390 /// or `repeating` restarts the timer.
391 fn is_enabled(&self) -> bool;
392
393 /// Cancel the current timer, if any. Value `Result<(), ErrorCode>` values are:
394 /// - `Ok(())`: no callback will be invoked in the future.
395 /// - `Err(ErrorCode::FAIL)`: the timer could not be cancelled and a callback
396 /// will be invoked in the future.
397 fn cancel(&self) -> Result<(), ErrorCode>;
398}
399
400// The following "frequencies" are represented as variant-less enums. Because
401// they can never be constructed, it forces them to be used purely as
402// type-markers which are guaranteed to be elided at runtime.
403
404/// 600MHz `Frequency`
405#[derive(Debug)]
406pub enum Freq600MHz {}
407impl Frequency for Freq600MHz {
408 fn frequency() -> u32 {
409 600_000_000
410 }
411}
412
413/// 100MHz `Frequency`
414#[derive(Debug)]
415pub enum Freq100MHz {}
416impl Frequency for Freq100MHz {
417 fn frequency() -> u32 {
418 100_000_000
419 }
420}
421
422/// 16MHz `Frequency`
423#[derive(Debug)]
424pub enum Freq16MHz {}
425impl Frequency for Freq16MHz {
426 fn frequency() -> u32 {
427 16_000_000
428 }
429}
430
431/// 10MHz `Frequency`
432pub enum Freq10MHz {}
433impl Frequency for Freq10MHz {
434 fn frequency() -> u32 {
435 10_000_000
436 }
437}
438
439/// 1MHz `Frequency`
440#[derive(Debug)]
441pub enum Freq1MHz {}
442impl Frequency for Freq1MHz {
443 fn frequency() -> u32 {
444 1_000_000
445 }
446}
447
448/// 32.768KHz `Frequency`
449#[derive(Debug)]
450pub enum Freq32KHz {}
451impl Frequency for Freq32KHz {
452 fn frequency() -> u32 {
453 32_768
454 }
455}
456
457/// 16KHz `Frequency`
458#[derive(Debug)]
459pub enum Freq16KHz {}
460impl Frequency for Freq16KHz {
461 fn frequency() -> u32 {
462 16_000
463 }
464}
465
466/// 1KHz `Frequency`
467#[derive(Debug)]
468pub enum Freq1KHz {}
469impl Frequency for Freq1KHz {
470 fn frequency() -> u32 {
471 1_000
472 }
473}
474
475/// u32 `Ticks`
476#[derive(Clone, Copy, Debug)]
477pub struct Ticks32(u32);
478
479impl From<u32> for Ticks32 {
480 fn from(val: u32) -> Self {
481 Ticks32(val)
482 }
483}
484
485impl Ticks for Ticks32 {
486 fn width() -> u32 {
487 32
488 }
489
490 fn into_usize(self) -> usize {
491 self.0 as usize
492 }
493
494 fn into_u32(self) -> u32 {
495 self.0
496 }
497
498 fn wrapping_add(self, other: Self) -> Self {
499 Ticks32(self.0.wrapping_add(other.0))
500 }
501
502 fn wrapping_sub(self, other: Self) -> Self {
503 Ticks32(self.0.wrapping_sub(other.0))
504 }
505
506 fn within_range(self, start: Self, end: Self) -> bool {
507 self.wrapping_sub(start).0 < end.wrapping_sub(start).0
508 }
509
510 /// Returns the maximum value of this type, which should be (2^width)-1.
511 fn max_value() -> Self {
512 Ticks32(0xFFFFFFFF)
513 }
514
515 /// Returns the half the maximum value of this type, which should be (2^width-1).
516 fn half_max_value() -> Self {
517 Self(1 + (Self::max_value().0 / 2))
518 }
519
520 #[inline]
521 fn from_or_max(val: u64) -> Self {
522 if val < Self::max_value().0 as u64 {
523 Self::from(val as u32)
524 } else {
525 Self::max_value()
526 }
527 }
528
529 #[inline]
530 fn saturating_scale(self, numerator: u32, denominator: u32) -> u32 {
531 let scaled = self.0 as u64 * numerator as u64 / denominator as u64;
532 if scaled < u32::MAX as u64 {
533 scaled as u32
534 } else {
535 u32::MAX
536 }
537 }
538}
539
540impl PartialOrd for Ticks32 {
541 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
542 Some(self.cmp(other))
543 }
544}
545
546impl Ord for Ticks32 {
547 fn cmp(&self, other: &Self) -> Ordering {
548 self.0.cmp(&other.0)
549 }
550}
551
552impl PartialEq for Ticks32 {
553 fn eq(&self, other: &Self) -> bool {
554 self.0 == other.0
555 }
556}
557
558impl Eq for Ticks32 {}
559
560/// 24-bit `Ticks`
561#[derive(Clone, Copy, Debug)]
562pub struct Ticks24(u32);
563
564impl Ticks24 {
565 pub const MASK: u32 = 0x00FFFFFF;
566}
567
568impl From<u32> for Ticks24 {
569 fn from(val: u32) -> Self {
570 Ticks24(val & Self::MASK)
571 }
572}
573
574impl Ticks for Ticks24 {
575 fn width() -> u32 {
576 24
577 }
578
579 fn into_usize(self) -> usize {
580 self.0 as usize
581 }
582
583 fn into_u32(self) -> u32 {
584 self.0
585 }
586
587 fn wrapping_add(self, other: Self) -> Self {
588 Ticks24(self.0.wrapping_add(other.0) & Self::MASK)
589 }
590
591 fn wrapping_sub(self, other: Self) -> Self {
592 Ticks24(self.0.wrapping_sub(other.0) & Self::MASK)
593 }
594
595 fn within_range(self, start: Self, end: Self) -> bool {
596 self.wrapping_sub(start).0 < end.wrapping_sub(start).0
597 }
598
599 /// Returns the maximum value of this type, which should be (2^width)-1.
600 fn max_value() -> Self {
601 Ticks24(Self::MASK)
602 }
603
604 /// Returns the half the maximum value of this type, which should be (2^width-1).
605 fn half_max_value() -> Self {
606 Self(1 + (Self::max_value().0 / 2))
607 }
608
609 #[inline]
610 fn from_or_max(val: u64) -> Self {
611 if val < Self::max_value().0 as u64 {
612 Self::from(val as u32)
613 } else {
614 Self::max_value()
615 }
616 }
617
618 #[inline]
619 fn saturating_scale(self, numerator: u32, denominator: u32) -> u32 {
620 let scaled = self.0 as u64 * numerator as u64 / denominator as u64;
621 if scaled < u32::MAX as u64 {
622 scaled as u32
623 } else {
624 u32::MAX
625 }
626 }
627}
628
629impl PartialOrd for Ticks24 {
630 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
631 Some(self.cmp(other))
632 }
633}
634
635impl Ord for Ticks24 {
636 fn cmp(&self, other: &Self) -> Ordering {
637 self.0.cmp(&other.0)
638 }
639}
640
641impl PartialEq for Ticks24 {
642 fn eq(&self, other: &Self) -> bool {
643 self.0 == other.0
644 }
645}
646
647impl Eq for Ticks24 {}
648
649/// 16-bit `Ticks`
650#[derive(Clone, Copy, Debug)]
651pub struct Ticks16(u16);
652
653impl From<u16> for Ticks16 {
654 fn from(val: u16) -> Self {
655 Ticks16(val)
656 }
657}
658
659impl From<u32> for Ticks16 {
660 fn from(val: u32) -> Self {
661 Ticks16((val & 0xffff) as u16)
662 }
663}
664
665impl Ticks16 {
666 pub fn into_u16(self) -> u16 {
667 self.0
668 }
669}
670
671impl Ticks for Ticks16 {
672 fn width() -> u32 {
673 16
674 }
675
676 fn into_usize(self) -> usize {
677 self.0 as usize
678 }
679
680 fn into_u32(self) -> u32 {
681 self.0 as u32
682 }
683
684 fn wrapping_add(self, other: Self) -> Self {
685 Ticks16(self.0.wrapping_add(other.0))
686 }
687
688 fn wrapping_sub(self, other: Self) -> Self {
689 Ticks16(self.0.wrapping_sub(other.0))
690 }
691
692 fn within_range(self, start: Self, end: Self) -> bool {
693 self.wrapping_sub(start).0 < end.wrapping_sub(start).0
694 }
695
696 /// Returns the maximum value of this type, which should be (2^width)-1.
697 fn max_value() -> Self {
698 Ticks16(0xFFFF)
699 }
700
701 /// Returns the half the maximum value of this type, which should be (2^width-1).
702 fn half_max_value() -> Self {
703 Self(1 + (Self::max_value().0 / 2))
704 }
705
706 #[inline]
707 fn from_or_max(val: u64) -> Self {
708 if val < Self::max_value().0 as u64 {
709 Self::from(val as u32)
710 } else {
711 Self::max_value()
712 }
713 }
714
715 #[inline]
716 fn saturating_scale(self, numerator: u32, denominator: u32) -> u32 {
717 let scaled = self.0 as u64 * numerator as u64 / denominator as u64;
718 if scaled < u32::MAX as u64 {
719 scaled as u32
720 } else {
721 u32::MAX
722 }
723 }
724}
725
726impl PartialOrd for Ticks16 {
727 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
728 Some(self.cmp(other))
729 }
730}
731
732impl Ord for Ticks16 {
733 fn cmp(&self, other: &Self) -> Ordering {
734 self.0.cmp(&other.0)
735 }
736}
737
738impl PartialEq for Ticks16 {
739 fn eq(&self, other: &Self) -> bool {
740 self.0 == other.0
741 }
742}
743
744impl Eq for Ticks16 {}
745
746/// 64-bit `Ticks`
747#[derive(Clone, Copy, Debug)]
748pub struct Ticks64(u64);
749
750impl Ticks64 {
751 pub fn into_u64(self) -> u64 {
752 self.0
753 }
754}
755
756impl From<u32> for Ticks64 {
757 fn from(val: u32) -> Self {
758 Ticks64(val as u64)
759 }
760}
761
762impl From<u64> for Ticks64 {
763 fn from(val: u64) -> Self {
764 Ticks64(val)
765 }
766}
767
768impl Ticks for Ticks64 {
769 fn width() -> u32 {
770 64
771 }
772
773 fn into_usize(self) -> usize {
774 self.0 as usize
775 }
776
777 fn into_u32(self) -> u32 {
778 self.0 as u32
779 }
780
781 fn wrapping_add(self, other: Self) -> Self {
782 Ticks64(self.0.wrapping_add(other.0))
783 }
784
785 fn wrapping_sub(self, other: Self) -> Self {
786 Ticks64(self.0.wrapping_sub(other.0))
787 }
788
789 fn within_range(self, start: Self, end: Self) -> bool {
790 self.wrapping_sub(start).0 < end.wrapping_sub(start).0
791 }
792
793 /// Returns the maximum value of this type, which should be (2^width)-1.
794 fn max_value() -> Self {
795 Ticks64(!0u64)
796 }
797
798 /// Returns the half the maximum value of this type, which should be (2^width-1).
799 fn half_max_value() -> Self {
800 Self(1 + (Self::max_value().0 / 2))
801 }
802
803 #[inline]
804 fn from_or_max(val: u64) -> Self {
805 Self(val)
806 }
807
808 #[inline]
809 fn saturating_scale(self, num: u32, den: u32) -> u32 {
810 let scaled = self.0.saturating_mul(num as u64) / den as u64;
811 if scaled < u32::MAX as u64 {
812 scaled as u32
813 } else {
814 u32::MAX
815 }
816 }
817}
818
819impl PartialOrd for Ticks64 {
820 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
821 Some(self.cmp(other))
822 }
823}
824
825impl Ord for Ticks64 {
826 fn cmp(&self, other: &Self) -> Ordering {
827 self.0.cmp(&other.0)
828 }
829}
830
831impl PartialEq for Ticks64 {
832 fn eq(&self, other: &Self) -> bool {
833 self.0 == other.0
834 }
835}
836
837impl Eq for Ticks64 {}
838
839#[cfg(test)]
840mod tests {
841 use super::*;
842
843 struct Test1MHz64();
844 impl Time for Test1MHz64 {
845 type Frequency = Freq1MHz;
846 type Ticks = Ticks64;
847
848 fn now(&self) -> Self::Ticks {
849 0u32.into()
850 }
851 }
852
853 #[test]
854 fn test_from_ticks64() {
855 let s = Test1MHz64().ticks_to_seconds(1_000_000u32.into());
856 assert_eq!(s, 1);
857
858 let ms = Test1MHz64().ticks_to_ms(1_000_000u32.into());
859 assert_eq!(ms, 1_000);
860
861 let us = Test1MHz64().ticks_to_us(1_000_000u32.into());
862 assert_eq!(us, 1_000_000);
863
864 let s = Test1MHz64().ticks_to_seconds((1_000_000u64 << 31).into());
865 assert_eq!(s, 1 << 31);
866
867 let ms = Test1MHz64().ticks_to_ms((1_000_000u64 << 31).into());
868 assert_eq!(ms, !0u32);
869
870 let us = Test1MHz64().ticks_to_us((1_000_000u64 << 31).into());
871 assert_eq!(us, !0u32);
872 }
873
874 #[test]
875 fn test_to_ticks64() {
876 let t = Test1MHz64().ticks_from_seconds(1);
877 assert_eq!(t.into_u32(), 1_000_000);
878
879 let t = Test1MHz64().ticks_from_ms(1);
880 assert_eq!(t.into_u32(), 1_000);
881
882 let t = Test1MHz64().ticks_from_us(1);
883 assert_eq!(t.into_u32(), 1);
884
885 let t = Test1MHz64().ticks_from_seconds(1 << 31);
886 assert_eq!(t.into_u64(), 1_000_000u64 << 31);
887 }
888
889 struct Test1KHz16();
890 impl Time for Test1KHz16 {
891 type Frequency = Freq1KHz;
892 type Ticks = Ticks16;
893
894 fn now(&self) -> Self::Ticks {
895 0u32.into()
896 }
897 }
898
899 #[test]
900 fn test_from_ticks16() {
901 let s = Test1KHz16().ticks_to_seconds(1_000u32.into());
902 assert_eq!(s, 1);
903
904 let ms = Test1KHz16().ticks_to_ms(1_000u32.into());
905 assert_eq!(ms, 1_000);
906
907 let us = Test1KHz16().ticks_to_us(1_000u32.into());
908 assert_eq!(us, 1_000_000);
909 }
910
911 #[test]
912 fn test_to_ticks16() {
913 let t = Test1KHz16().ticks_from_seconds(1);
914 assert_eq!(t.into_u32(), 1_000);
915
916 let t = Test1KHz16().ticks_from_seconds(u32::MAX);
917 assert_eq!(t.into_u32(), u16::MAX as u32);
918
919 let t = Test1KHz16().ticks_from_seconds(66);
920 assert_eq!(t.into_u32(), u16::MAX as u32);
921
922 let t = Test1KHz16().ticks_from_seconds(65);
923 assert_eq!(t.into_u32(), 65_000);
924
925 let t = Test1KHz16().ticks_from_ms(1);
926 assert_eq!(t.into_u32(), 1);
927
928 let t = Test1KHz16().ticks_from_us(1);
929 assert_eq!(t.into_u32(), 0);
930 }
931
932 struct Test1KHz24();
933 impl Time for Test1KHz24 {
934 type Frequency = Freq1KHz;
935 type Ticks = Ticks24;
936
937 fn now(&self) -> Self::Ticks {
938 0u32.into()
939 }
940 }
941
942 #[test]
943 fn test_ticks24() {
944 let s = Test1KHz24().ticks_to_seconds(5_000_000u32.into());
945 assert_eq!(s, 5_000);
946
947 let ms = Test1KHz24().ticks_to_ms(5_000_000u32.into());
948 assert_eq!(ms, 5_000_000);
949
950 let us = Test1KHz24().ticks_to_us(5_000_000u32.into());
951 assert_eq!(us, u32::MAX);
952 }
953
954 #[test]
955 fn test_dyn_object() {
956 let time: &dyn Time<Frequency = Freq1KHz, Ticks = Ticks24> = &Test1KHz24();
957
958 let s = time.ticks_to_seconds(5_000_000u32.into());
959 assert_eq!(s, 5_000);
960
961 let ms = time.ticks_to_ms(5_000_000u32.into());
962 assert_eq!(ms, 5_000_000);
963
964 let us = time.ticks_to_us(5_000_000u32.into());
965 assert_eq!(us, u32::MAX);
966 }
967}