use std::fmt;
use std::ops::{Add, AddAssign, Sub, SubAssign};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AvrDuration {
clock_frequency: u32,
cycles: u64,
}
impl AvrDuration {
pub const fn new(clock_frequency: u32, cycles: u64) -> Self {
Self {
clock_frequency,
cycles,
}
}
pub const fn add_cycles(mut self, n: u64) -> Self {
self.cycles += n;
self
}
pub const fn add_micros(self, n: u64) -> Self {
self.add_cycles(n * (self.clock_frequency as u64 / 1_000_000))
}
pub const fn add_millis(self, millis: u64) -> Self {
self.add_cycles(millis * (self.clock_frequency as u64) / 1_000)
}
pub const fn add_secs(self, secs: u64) -> Self {
self.add_cycles(secs * (self.clock_frequency as u64))
}
pub const fn with_cycles(mut self, n: u64) -> Self {
self.cycles = n;
self
}
pub const fn with_micros(self, n: u64) -> Self {
self.with_cycles(0).add_micros(n)
}
pub const fn with_millis(self, n: u64) -> Self {
self.with_cycles(0).add_millis(n)
}
pub const fn with_secs(self, n: u64) -> Self {
self.with_cycles(0).add_secs(n)
}
pub const fn clock_frequency(self) -> u32 {
self.clock_frequency
}
pub const fn as_cycles(self) -> u64 {
self.cycles
}
pub fn as_micros(self) -> u64 {
self.as_micros_f64().round() as _
}
pub fn as_micros_f64(self) -> f64 {
(self.cycles as f64) / (self.clock_frequency as f64 / 1_000_000.0)
}
pub fn as_millis(self) -> u64 {
self.as_millis_f64().round() as _
}
pub fn as_millis_f64(self) -> f64 {
(self.cycles as f64) / (self.clock_frequency as f64 / 1_000.0)
}
pub fn as_secs(self) -> u64 {
self.as_secs_f64().round() as _
}
pub fn as_secs_f64(self) -> f64 {
(self.cycles as f64) / (self.clock_frequency as f64)
}
pub fn is_zero(self) -> bool {
self.as_cycles() == 0
}
}
impl Add for AvrDuration {
type Output = Self;
fn add(mut self, rhs: Self) -> Self::Output {
self += rhs;
self
}
}
impl AddAssign for AvrDuration {
fn add_assign(&mut self, rhs: Self) {
assert_eq!(
self.clock_frequency, rhs.clock_frequency,
"Cannot add durations with different clock frequencies ({} vs {})",
self.clock_frequency, rhs.clock_frequency
);
self.cycles += rhs.cycles;
}
}
impl Sub for AvrDuration {
type Output = Self;
fn sub(mut self, rhs: Self) -> Self::Output {
self -= rhs;
self
}
}
impl SubAssign for AvrDuration {
fn sub_assign(&mut self, rhs: Self) {
assert_eq!(
self.clock_frequency, rhs.clock_frequency,
"Cannot subtract durations with different clock frequencies ({} vs {})",
self.clock_frequency, rhs.clock_frequency
);
self.cycles = self.cycles.saturating_sub(rhs.cycles);
}
}
impl fmt::Display for AvrDuration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} µs", self.as_micros())
}
}