rs-dht-pio/src/dht.rs

103 lines
2.7 KiB
Rust
Raw Normal View History

2024-03-18 07:43:47 +00:00
use embassy_rp::pio::{
Common, Config, Instance, PioPin, ShiftConfig, ShiftDirection, StateMachine,
};
2024-03-13 15:46:52 +00:00
use embassy_time::Timer;
use fixed::traits::ToFixed;
2024-03-18 07:43:47 +00:00
use fixed_macro::types::U56F8;
2023-09-09 20:22:30 +00:00
2024-07-11 10:02:25 +00:00
use crate::{DhtError, DhtProgram};
2023-09-09 20:22:30 +00:00
2024-03-13 15:46:52 +00:00
pub struct DhtPio<'d, PIO: Instance, const SM: usize> {
sm: StateMachine<'d, PIO, SM>,
2023-09-09 20:22:30 +00:00
}
2024-03-13 15:46:52 +00:00
impl<'d, PIO: Instance, const SM: usize> DhtPio<'d, PIO, SM> {
pub fn new(
2024-07-11 10:02:25 +00:00
dht_program: &DhtProgram<'d, PIO>,
2024-03-13 15:46:52 +00:00
pio: &mut Common<'d, PIO>,
mut sm: StateMachine<'d, PIO, SM>,
dht_pin: impl PioPin,
2023-09-09 20:22:30 +00:00
) -> Self {
2024-03-13 15:46:52 +00:00
let pin = pio.make_pio_pin(dht_pin);
2023-09-09 20:22:30 +00:00
2024-03-13 15:46:52 +00:00
let mut config = Config::default();
2024-07-11 10:02:25 +00:00
config.use_program(dht_program.program(), &[]);
2024-03-13 15:46:52 +00:00
config.set_out_pins(&[&pin]);
config.set_set_pins(&[&pin]);
config.set_in_pins(&[&pin]);
2024-03-18 07:43:47 +00:00
config.shift_in = ShiftConfig {
threshold: 32,
direction: ShiftDirection::Left,
auto_fill: true,
};
config.shift_out = ShiftConfig {
threshold: 32,
direction: ShiftDirection::Left,
auto_fill: false,
};
config.clock_divider = (U56F8!(125_000_000) / 1_000_000).to_fixed();
2024-03-14 06:01:27 +00:00
sm.set_config(&config);
2023-09-09 20:22:30 +00:00
2024-03-13 15:46:52 +00:00
sm.set_pin_dirs(embassy_rp::pio::Direction::Out, &[&pin]);
sm.set_enable(true);
2023-09-09 20:22:30 +00:00
2024-03-13 15:46:52 +00:00
Self { sm }
2023-09-09 20:22:30 +00:00
}
2024-03-13 15:46:52 +00:00
pub async fn read_data(&mut self) -> Result<(u16, u16), DhtError> {
2023-09-09 20:22:30 +00:00
let mut timeout = 2000;
let mut raw: [Option<u32>; 2] = [None; 2];
2024-03-13 15:46:52 +00:00
self.sm.tx().wait_push(1).await;
2023-09-09 20:22:30 +00:00
while timeout > 0 && raw[1].is_none() {
2024-03-13 15:46:52 +00:00
match self.sm.rx().try_pull() {
2023-09-09 20:22:30 +00:00
Some(d) => {
if raw[0].is_none() {
raw[0] = Some(d);
} else {
raw[1] = Some(d);
}
}
None => (),
}
2024-03-13 15:46:52 +00:00
Timer::after_millis(1).await;
2023-09-09 20:22:30 +00:00
timeout -= 1;
}
if timeout <= 0 {
self.sm.restart();
return Err(DhtError::Timeout);
}
let data = raw[0].unwrap();
let crc = raw[1].unwrap();
if Self::compute_crc(data) != crc {
2024-03-18 07:43:47 +00:00
return Err(DhtError::CrcMismatch(data, crc));
2023-09-09 20:22:30 +00:00
}
2023-10-10 17:44:06 +00:00
Ok((
(data & 0x0000FFFF) as u16,
((data & 0xFFFF0000) >> 16) as u16,
))
2023-09-09 20:22:30 +00:00
}
fn compute_crc(data: u32) -> u32 {
let mut crc: u32 = 0;
crc += data & 0x000000FF;
crc += (data & 0x0000FF00) >> 8;
crc += (data & 0x00FF0000) >> 16;
crc += (data & 0xFF000000) >> 24;
crc % 256
}
}
2024-03-13 15:46:52 +00:00
impl<'d, PIO: Instance, const SM: usize> Drop for DhtPio<'d, PIO, SM> {
fn drop(&mut self) {
self.sm.set_enable(false);
}
}