1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
//! Time units
//!
//! See [`Hertz`], [`KiloHertz`] and [`MegaHertz`] for creating increasingly higher frequencies.
//!
//! The [`U32Ext`] trait adds various methods like `.hz()`, `.mhz()`, etc to the `u32` primitive type,
//! allowing it to be converted into frequencies.
//!
//! # Examples
//!
//! ## Create a 2 MHz frequency
//!
//! This example demonstrates various ways of creating a 2 MHz (2_000_000 Hz) frequency. They are
//! all equivalent, however the `2.mhz()` variant should be preferred for readability.
//!
//! ```rust
//! use stm32f1xx_hal::{
//!     time::Hertz,
//!     // Imports U32Ext trait
//!     prelude::*,
//! };
//!
//! let freq_hz = 2_000_000.hz();
//! let freq_khz = 2_000.khz();
//! let freq_mhz = 2.mhz();
//!
//! assert_eq!(freq_hz, freq_khz);
//! assert_eq!(freq_khz, freq_mhz);
//! ```

use core::ops;
use cortex_m::peripheral::{DCB, DWT};

use crate::rcc::Clocks;

/// Bits per second
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct Bps(pub u32);

/// Hertz
///
/// Create a frequency specified in [Hertz](https://en.wikipedia.org/wiki/Hertz).
///
/// See also [`KiloHertz`] and [`MegaHertz`] for semantically correct ways of creating higher
/// frequencies.
///
/// # Examples
///
/// ## Create an 60 Hz frequency
///
/// ```rust
/// use stm32f1xx_hal::time::Hertz;
///
/// let freq = 60.hz();
/// ```
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct Hertz(pub u32);

/// Kilohertz
///
/// Create a frequency specified in kilohertz.
///
/// See also [`Hertz`] and [`MegaHertz`] for semantically correct ways of creating lower or higher
/// frequencies.
///
/// # Examples
///
/// ## Create a 100 Khz frequency
///
/// This example creates a 100 KHz frequency. This could be used to set an I2C data rate or PWM
/// frequency, etc.
///
/// ```rust
/// use stm32f1xx_hal::time::Hertz;
///
/// let freq = 100.khz();
/// ```
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct KiloHertz(pub u32);

/// Megahertz
///
/// Create a frequency specified in megahertz.
///
/// See also [`Hertz`] and [`KiloHertz`] for semantically correct ways of creating lower
/// frequencies.
///
/// # Examples
///
/// ## Create a an 8 MHz frequency
///
/// This example creates an 8 MHz frequency that could be used to configure an SPI peripheral, etc.
///
/// ```rust
/// use stm32f1xx_hal::time::Hertz;
///
/// let freq = 8.mhz();
/// ```
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct MegaHertz(pub u32);

/// Time unit
#[derive(PartialEq, PartialOrd, Clone, Copy)]
pub struct MilliSeconds(pub u32);

#[derive(PartialEq, PartialOrd, Clone, Copy)]
pub struct MicroSeconds(pub u32);

/// Extension trait that adds convenience methods to the `u32` type
pub trait U32Ext {
    /// Wrap in `Bps`
    fn bps(self) -> Bps;

    /// Wrap in `Hertz`
    fn hz(self) -> Hertz;

    /// Wrap in `KiloHertz`
    fn khz(self) -> KiloHertz;

    /// Wrap in `MegaHertz`
    fn mhz(self) -> MegaHertz;

    /// Wrap in `MilliSeconds`
    fn ms(self) -> MilliSeconds;

    /// Wrap in `MicroSeconds`
    fn us(self) -> MicroSeconds;
}

impl U32Ext for u32 {
    fn bps(self) -> Bps {
        Bps(self)
    }

    fn hz(self) -> Hertz {
        Hertz(self)
    }

    fn khz(self) -> KiloHertz {
        KiloHertz(self)
    }

    fn mhz(self) -> MegaHertz {
        MegaHertz(self)
    }

    fn ms(self) -> MilliSeconds {
        MilliSeconds(self)
    }

    fn us(self) -> MicroSeconds {
        MicroSeconds(self)
    }
}

impl From<KiloHertz> for Hertz {
    fn from(val: KiloHertz) -> Self {
        Self(val.0 * 1_000)
    }
}

impl From<MegaHertz> for Hertz {
    fn from(val: MegaHertz) -> Self {
        Self(val.0 * 1_000_000)
    }
}

impl From<MegaHertz> for KiloHertz {
    fn from(val: MegaHertz) -> Self {
        Self(val.0 * 1_000)
    }
}

impl Into<Hertz> for MilliSeconds {
    fn into(self) -> Hertz {
        Hertz(1_000 / self.0)
    }
}

impl Into<Hertz> for MicroSeconds {
    fn into(self) -> Hertz {
        Hertz(1_000_000 / self.0)
    }
}

/// Macro to implement arithmetic operations (e.g. multiplication, division)
/// for wrapper types.
macro_rules! impl_arithmetic {
    ($wrapper:ty, $wrapped:ty) => {
        impl ops::Mul<$wrapped> for $wrapper {
            type Output = Self;
            fn mul(self, rhs: $wrapped) -> Self {
                Self(self.0 * rhs)
            }
        }

        impl ops::MulAssign<$wrapped> for $wrapper {
            fn mul_assign(&mut self, rhs: $wrapped) {
                self.0 *= rhs;
            }
        }

        impl ops::Div<$wrapped> for $wrapper {
            type Output = Self;
            fn div(self, rhs: $wrapped) -> Self {
                Self(self.0 / rhs)
            }
        }

        impl ops::Div<$wrapper> for $wrapper {
            type Output = $wrapped;
            fn div(self, rhs: $wrapper) -> $wrapped {
                self.0 / rhs.0
            }
        }

        impl ops::DivAssign<$wrapped> for $wrapper {
            fn div_assign(&mut self, rhs: $wrapped) {
                self.0 /= rhs;
            }
        }
    };
}

impl_arithmetic!(Hertz, u32);
impl_arithmetic!(KiloHertz, u32);
impl_arithmetic!(MegaHertz, u32);
impl_arithmetic!(Bps, u32);

/// A monotonic non-decreasing timer
///
/// This uses the timer in the debug watch trace peripheral. This means, that if the
/// core is stopped, the timer does not count up. This may be relevant if you are using
/// cortex_m_semihosting::hprintln for debugging in which case the timer will be stopped
/// while printing
#[derive(Clone, Copy)]
pub struct MonoTimer {
    frequency: Hertz,
}

impl MonoTimer {
    /// Creates a new `Monotonic` timer
    pub fn new(mut dwt: DWT, mut dcb: DCB, clocks: Clocks) -> Self {
        dcb.enable_trace();
        dwt.enable_cycle_counter();

        // now the CYCCNT counter can't be stopped or reset
        drop(dwt);

        MonoTimer {
            frequency: clocks.hclk(),
        }
    }

    /// Returns the frequency at which the monotonic timer is operating at
    pub fn frequency(self) -> Hertz {
        self.frequency
    }

    /// Returns an `Instant` corresponding to "now"
    pub fn now(self) -> Instant {
        Instant {
            now: DWT::get_cycle_count(),
        }
    }
}

/// A measurement of a monotonically non-decreasing clock
#[derive(Clone, Copy)]
pub struct Instant {
    now: u32,
}

impl Instant {
    /// Ticks elapsed since the `Instant` was created
    pub fn elapsed(self) -> u32 {
        DWT::get_cycle_count().wrapping_sub(self.now)
    }
}