rsiot/drivers_i2c/pcf8575/
task_read_inputs.rs1use std::{sync::Arc, time::Duration};
2
3use bitvec::prelude::*;
4use tokio::{sync::Mutex, time::sleep};
5
6use crate::{
7 drivers_i2c::{I2cSlaveAddress, RsiotI2cDriverBase},
8 executor::CmpInOut,
9 message::MsgDataBound,
10};
11
12use super::{state::State, TPinFnOutput};
13
14pub struct TaskReadInputs<TMsg, Driver>
16where
17 TMsg: MsgDataBound,
18{
19 pub in_out: CmpInOut<TMsg>,
20 pub driver: Arc<Mutex<Driver>>,
21 pub address: I2cSlaveAddress,
22 pub pin_and_fn_output: TPinFnOutput<TMsg>,
23 pub state: State,
24}
25
26impl<TMsg, Driver> TaskReadInputs<TMsg, Driver>
27where
28 TMsg: MsgDataBound,
29 Driver: RsiotI2cDriverBase,
30{
31 pub async fn spawn(&self) -> Result<(), String> {
32 let mut status_saved = 0u16;
33 let status_saved_bits = status_saved.view_bits_mut::<Lsb0>();
34 let mut first_cycle = true;
35
36 loop {
37 let state = self.state.to_bytes().await;
38 let status_current = {
39 let mut driver = self.driver.lock().await;
40 driver
41 .write_read(self.address, &state, 2, Duration::from_secs(2))
42 .await
43 .map_err(String::from)?
44 };
45 let status_current_bits = status_current.view_bits::<Lsb0>();
46 for (pin, fn_output) in &self.pin_and_fn_output {
47 if (status_current_bits[*pin] != status_saved_bits[*pin]) || first_cycle {
48 let msg = fn_output(!status_current_bits[*pin]);
49 status_saved_bits.set(*pin, status_current_bits[*pin]);
50 let Some(msg) = msg else { continue };
51 self.in_out
52 .send_output(msg)
53 .await
54 .map_err(|e| e.to_string())?;
55 }
56 }
57 first_cycle = false;
58
59 sleep(Duration::from_millis(100)).await;
60 }
61 }
62}