Skip to content

Commit

Permalink
WIP on async variant with help of maybe-async-cfg
Browse files Browse the repository at this point in the history
  • Loading branch information
sirhcel committed Oct 13, 2024
1 parent 5051836 commit 7017fef
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 22 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ exclude = [
defmt = { version = "0.3.2", optional = true }
embedded-hal = "1.0.0"
fixed = "1.20.0"
sensirion-i2c = "0.3.0"
maybe-async-cfg = "0.2.4"
sensirion-i2c = "0.4.0"

[features]
defmt = ["dep:defmt"]
use_sync = []
use_async = ["sensirion-i2c/embedded-hal-async"]
59 changes: 38 additions & 21 deletions src/sht4x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ use crate::{
use core::marker::PhantomData;

Check warning on line 6 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused import: `core::marker::PhantomData`

Check warning on line 6 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Check

unused import: `core::marker::PhantomData`

Check failure on line 6 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Clippy

unused import: `core::marker::PhantomData`
use embedded_hal::{delay::DelayNs, i2c::I2c};

Check warning on line 7 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused imports: `delay::DelayNs` and `i2c::I2c`

Check warning on line 7 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Check

unused imports: `delay::DelayNs` and `i2c::I2c`

Check failure on line 7 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Clippy

unused imports: `delay::DelayNs` and `i2c::I2c`
use sensirion_i2c::i2c;

Check warning on line 8 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused import: `sensirion_i2c::i2c`

Check warning on line 8 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Check

unused import: `sensirion_i2c::i2c`

Check failure on line 8 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Clippy

unused import: `sensirion_i2c::i2c`
use sensirion_i2c::i2c_async;

Check failure on line 9 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unresolved import `sensirion_i2c::i2c_async`

Check failure on line 9 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Check

unresolved import `sensirion_i2c::i2c_async`

Check failure on line 9 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Clippy

unresolved import `sensirion_i2c::i2c_async`

Check failure on line 9 in src/sht4x.rs

View workflow job for this annotation

GitHub Actions / Docs

unresolved import `sensirion_i2c::i2c_async`

const RESPONSE_LEN: usize = 6;

/// Driver for STH4x sensors.
#[maybe_async_cfg::maybe(
sync(feature="use_sync"),
async(feature="use_async")
)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Eq, Hash, PartialEq)]
pub struct Sht4x<I, D> {
Expand Down Expand Up @@ -43,6 +48,10 @@ impl From<Precision> for Command {
}
}

#[maybe_async_cfg::maybe(
sync(feature="use_sync"),
async(feature="use_async")
)]
impl<I, D> Sht4x<I, D>
where
I: I2c,
Expand Down Expand Up @@ -81,13 +90,13 @@ where
/// check the
/// [datasheet](https://sensirion.com/media/documents/33FD6951/624C4357/Datasheet_SHT4x.pdf),
/// section 4.9 _Heater Operation_ for details.
pub fn heat_and_measure(
pub async fn heat_and_measure(
&mut self,
power: HeatingPower,
duration: HeatingDuration,
delay: &mut D,
) -> Result<Measurement, Error<I::Error>> {
let raw = self.heat_and_measure_raw(power, duration, delay)?;
let raw = self.heat_and_measure_raw(power, duration, delay).await?;

Ok(Measurement::from(raw))
}
Expand All @@ -98,50 +107,50 @@ where
/// check the
/// [datasheet](https://sensirion.com/media/documents/33FD6951/624C4357/Datasheet_SHT4x.pdf),
/// section 4.9 _Heater Operation_ for details.
pub fn heat_and_measure_raw(
pub async fn heat_and_measure_raw(
&mut self,
power: HeatingPower,
duration: HeatingDuration,
delay: &mut D,
) -> Result<SensorData, Error<I::Error>> {
let command = Command::from((power, duration));

self.write_command_and_delay_for_execution(command, delay)?;
let response = self.read_response()?;
self.write_command_and_delay_for_execution(command, delay).await?;
let response = self.read_response().await?;
let raw = self.sensor_data_from_response(&response);

Ok(raw)
}

/// Performs a measurement returning measurands in SI units.
pub fn measure(
pub async fn measure(
&mut self,
precision: Precision,
delay: &mut D,
) -> Result<Measurement, Error<I::Error>> {
let raw = self.measure_raw(precision, delay)?;
let raw = self.measure_raw(precision, delay).await?;
Ok(Measurement::from(raw))
}

/// Performs a measurement returning raw sensor data.
pub fn measure_raw(
pub async fn measure_raw(
&mut self,
precision: Precision,
delay: &mut D,
) -> Result<SensorData, Error<I::Error>> {
let command = Command::from(precision);

self.write_command_and_delay_for_execution(command, delay)?;
let response = self.read_response()?;
self.write_command_and_delay_for_execution(command, delay).await?;
let response = self.read_response().await?;
let raw = self.sensor_data_from_response(&response);

Ok(raw)
}

/// Reads the sensor's serial number.
pub fn serial_number(&mut self, delay: &mut D) -> Result<u32, Error<I::Error>> {
self.write_command_and_delay_for_execution(Command::SerialNumber, delay)?;
let response = self.read_response()?;
pub async fn serial_number(&mut self, delay: &mut D) -> Result<u32, Error<I::Error>> {
self.write_command_and_delay_for_execution(Command::SerialNumber, delay).await?;
let response = self.read_response().await?;

Ok(u32::from_be_bytes([
response[0],
Expand All @@ -152,14 +161,18 @@ where
}

/// Performs a soft reset of the sensor.
pub fn soft_reset(&mut self, delay: &mut D) -> Result<(), Error<I::Error>> {
self.write_command_and_delay_for_execution(Command::SoftReset, delay)
pub async fn soft_reset(&mut self, delay: &mut D) -> Result<(), Error<I::Error>> {
self.write_command_and_delay_for_execution(Command::SoftReset, delay).await
}

fn read_response(&mut self) -> Result<[u8; RESPONSE_LEN], Error<I::Error>> {
let mut response = [0; RESPONSE_LEN];
async fn read_response(&mut self) -> Result<[u8; RESPONSE_LEN], Error<I::Error>> {
#[maybe_async_cfg::only_if(sync)]
use sensirion_i2c::i2c as si2c;
#[maybe_async_cfg::only_if(async)]
use sensirion_i2c::i2c_async as si2c;

i2c::read_words_with_crc(&mut self.i2c, self.address.into(), &mut response)?;
let mut response = [0; RESPONSE_LEN];
si2c::read_words_with_crc(&mut self.i2c, self.address.into(), &mut response).await?;

Ok(response)
}
Expand All @@ -171,14 +184,18 @@ where
}
}

fn write_command_and_delay_for_execution(
async fn write_command_and_delay_for_execution(
&mut self,
command: Command,
delay: &mut D,
) -> Result<(), Error<I::Error>> {
let code = command.code();
#[maybe_async_cfg::only_if(sync)]
use sensirion_i2c::i2c as si2c;
#[maybe_async_cfg::only_if(async)]
use sensirion_i2c::i2c_async as si2c;

i2c::write_command_u8(&mut self.i2c, self.address.into(), code).map_err(Error::I2c)?;
let code = command.code();
si2c::write_command_u8(&mut self.i2c, self.address.into(), code).map_err(Error::I2c).await?;
delay.delay_ms(command.duration_ms());

Ok(())
Expand Down

0 comments on commit 7017fef

Please sign in to comment.