thread_delay/lib.rs
1//! This crate provides a blocking implementation of DelayNs from
2//! [`embedded_hal`] that can be used on Linux systems using the
3//! Linux standard library. It is intended to be a drop-in replacement
4//! for application using libraries that were written for embedded
5//! devices but have access to the standard library, such as a single
6//! board computer (SBC) running Linux.
7//!
8//! The Delay implementation is like the one from [`linux_embedded_hal`] but
9//! provides all the `delay_*` functions defined by the trait.
10//!
11//! The functions are:
12//!
13//! 1. `delay_ns` for nanosecond delays
14//! 2. `delay_us` for microsecond delays
15//! 3. `delay_ms` for milliseconds delays
16//!
17//! ## Example
18//!
19//! This example is an application running on a Raspberry Pi Zero 2 W
20//! that takes readings from a `bme280` atmospheric sensor.
21//!
22//! ```rust,ignore
23//! use thread_delay::Delay;
24//!
25//! use bme280::i2c::BME280;
26//! use rppal::i2c::I2c;
27//! use std::time::Instant;
28//!
29//! enum LoopState {
30//! Waiting,
31//! Measuring,
32//! }
33//!
34//! fn main() -> ! {
35//! let i2c = I2c::with_bus(1).expect("failed to find i2c bus 1");
36//! assert!(i2c.bus() == 1_u8);
37//!
38//! let mut delay = Delay {};
39//!
40//! let mut bme280 = BME280::new_primary(i2c);
41//!
42//! bme280.init(&mut delay).expect("failed to initialize bme280 sensor");
43//!
44//! let mut state = LoopState::Waiting;
45//!
46//! let delay_millis: u128 = 1_000;
47//!
48//! let mut last_update = Instant::now();
49//!
50//! loop {
51//! let elapsed = last_update.elapsed();
52//!
53//! match state {
54//! LoopState::Waiting => {
55//! if elapsed.as_millis() >= delay_millis {
56//! state = LoopState::Measuring
57//! }
58//! }
59//!
60//! LoopState::Measuring => {
61//! let measurements = bme280
62//! .measure(&mut delay)
63//! .expect("failed to read measurements from bme280");
64//!
65//! println!("Temp: |{:-10.3} C |", measurements.temperature);
66//! println!("Humidity: |{:-10.3} % |", measurements.humidity);
67//! println!("Pressure: |{:-10.3} Pa|", measurements.pressure);
68//! println!("-----");
69//!
70//! last_update = Instant::now();
71//! state = LoopState::Waiting;
72//! }
73//! }
74//! }
75//! }
76//! ```
77use std::{thread::sleep, time::Duration};
78
79use embedded_hal::delay::DelayNs;
80
81#[allow(unused)]
82/// Empty struct that implements the `DelayNs` trait using `std::thread::sleep`
83pub struct ThreadDelay;
84
85#[allow(unused)]
86/// A convienvce alias for keeping the `Delay` struct name
87pub type Delay = ThreadDelay;
88
89/// `DelayNs` trait from [`embedded_hal`] implemented using sleep.
90/// The thread may sleep longer than the duration specified due to
91/// scheduling specifics or platform-dependent functionality.
92/// It will never sleep less.
93///
94/// This function is blocking, and should not be used in async functions.
95impl DelayNs for ThreadDelay {
96 /// Pauses execution for at minimum `ns` nanoseconds.
97 fn delay_ns(&mut self, ns: u32) {
98 sleep(Duration::from_nanos(ns as u64));
99 }
100
101 /// Pauses execution for at minimum `us` microseconds.
102 fn delay_us(&mut self, us: u32) {
103 sleep(Duration::from_micros(us as u64));
104 }
105
106 /// Pauses execution for at minimum `ms` milliseconds.
107 fn delay_ms(&mut self, ms: u32) {
108 sleep(Duration::from_millis(ms as u64));
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use std::time::Instant;
115
116 use super::*;
117
118 #[test]
119 fn test_delay_ms() {
120 let millis = [500_u32, 127, 0, 1];
121 let mut delay = Delay {};
122
123 for milli in millis {
124 let start = Instant::now();
125 delay.delay_ms(milli);
126 let elapsed = start.elapsed();
127 assert!(elapsed.as_millis() >= milli as u128);
128 }
129 }
130
131 #[test]
132 fn test_delay_ns() {
133 let nanos = [500_u32, 127, 0, 454];
134 let mut delay = Delay {};
135
136 for nano in nanos {
137 let start = Instant::now();
138 delay.delay_ns(nano);
139 assert!(start.elapsed().as_nanos() >= nano as u128);
140 }
141 }
142
143 #[test]
144 fn test_delay_us() {
145 let micros = [250_u32, 128, 324, 98123];
146 let mut delay = Delay {};
147
148 for micro in micros {
149 let start = Instant::now();
150 delay.delay_us(micro);
151 assert!(start.elapsed().as_micros() >= micro as u128);
152 }
153 }
154}