diff --git a/Cargo.toml b/Cargo.toml index 7c81e71e..99a38f5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,11 @@ libc = "0.2.50" lazy_static = "1.3.0" nb = { version = "0.1.1", optional = true } embedded-hal = { version = "0.2.2", optional = true } +bitrate = "0.1.1" + +[dependencies.void] +default-features = false +version = "1.0.2" [dev-dependencies] simple-signal = "1.1.1" diff --git a/src/hal.rs b/src/hal.rs index a096a134..30b55288 100644 --- a/src/hal.rs +++ b/src/hal.rs @@ -27,9 +27,12 @@ //! flag is enabled. use std::thread; -use std::time::Duration; +use std::time::{Duration, Instant}; +use bitrate::Hertz; use embedded_hal::blocking::delay::{DelayMs, DelayUs}; +use embedded_hal::timer::CountDown; +use void::Void; /// Implements the `embedded-hal` `DelayMs` and `DelayUs` traits. #[derive(Debug, Default)] @@ -89,3 +92,74 @@ impl DelayUs for Delay { thread::sleep(Duration::from_micros(us)); } } + +/// Implements the `embedded-hal` `CountDown` trait. +#[derive(Debug, Copy, Clone)] +pub struct Timer { + now: Instant, + duration: Duration, +} + +impl Timer { + /// Constructs a new `Timer`. + pub fn new() -> Self { + Self { + now: Instant::now(), + duration: Duration::from_micros(0), + } + } +} + +pub struct Millisecond(pub u64); +pub struct MicroSecond(pub u64); +pub struct Second(pub u64); + +impl From> for MicroSecond { + fn from(item: Hertz) -> Self { + MicroSecond(item.0 * 1_000_000) + } +} + +impl From for MicroSecond { + fn from(item: Millisecond) -> Self { + MicroSecond(item.0 * 1_000) + } +} + +impl From for MicroSecond { + fn from(item: Second) -> Self { + MicroSecond(item.0 * 1_000_000) + } +} + +impl MicroSecond { + fn as_u64(&self) -> u64 { + let &MicroSecond(t) = self; + t + } +} + +impl CountDown for Timer { + type Time = MicroSecond; + + /// Start the timer with a `timeout` + fn start(&mut self, timeout: T) + where + T: Into, + { + self.duration = Duration::from_micros(timeout.into().as_u64()); + self.now = Instant::now(); + } + + /// Return `Ok` if the timer has wrapped + /// Automatically clears the flag and restarts the time + fn wait(&mut self) -> nb::Result<(), Void> { + if self.now.elapsed() >= self.duration { + let duration = Duration::from_micros(1); + thread::sleep(duration); + Ok(()) + } else { + Err(nb::Error::WouldBlock) + } + } +}