rsiot/drivers_i2c/pcf8575/
device.rs

1use std::sync::Arc;
2
3use tokio::{sync::Mutex, task::JoinSet};
4use tracing::warn;
5
6use crate::{executor::CmpInOut, message::MsgDataBound};
7
8use super::{
9    super::{I2cSlaveAddress, RsiotI2cDriverBase},
10    state::State,
11    task_read_inputs::TaskReadInputs,
12    task_write_output::TaskWriteOutput,
13    PCF8575PinMode, TPinFnOutput,
14};
15
16pub struct PCF8575<TMsg>
17where
18    TMsg: MsgDataBound,
19{
20    pub address: I2cSlaveAddress,
21    pub pins: Vec<PCF8575PinMode<TMsg>>,
22}
23
24impl<TMsg> PCF8575<TMsg>
25where
26    TMsg: MsgDataBound + 'static,
27{
28    pub async fn fn_process(
29        &self,
30        in_out: CmpInOut<TMsg>,
31        driver: Arc<Mutex<impl RsiotI2cDriverBase + 'static>>,
32    ) {
33        loop {
34            let mut state = State::new();
35            let mut task_set: JoinSet<Result<(), String>> = JoinSet::new();
36
37            // Определяем начальную конфигурацию входов / выходов
38            let mut input_pins: TPinFnOutput<TMsg> = vec![];
39            for (index, pin) in self.pins.iter().enumerate() {
40                match pin {
41                    PCF8575PinMode::Disabled => {}
42
43                    PCF8575PinMode::Input { fn_output } => {
44                        state.set_input(index).await;
45                        input_pins.push((index, *fn_output))
46                    }
47
48                    PCF8575PinMode::Output { fn_input } => {
49                        state.set_output_low(index).await;
50                        let mut task_output = TaskWriteOutput {
51                            in_out: in_out.clone(),
52                            fn_input: *fn_input,
53                            state: state.clone(),
54                            driver: driver.clone(),
55                            address: self.address,
56                            pin: index,
57                        };
58                        task_set.spawn(async move { task_output.spawn().await });
59                    }
60                }
61            }
62
63            let task_input = TaskReadInputs {
64                in_out: in_out.clone(),
65                driver: driver.clone(),
66                address: self.address,
67                pin_and_fn_output: input_pins,
68                state: state.clone(),
69            };
70            task_set.spawn(async move { task_input.spawn().await });
71
72            // задачи не должны заканчиваться. Если закончилась хоть одна - отменяем все остальные и
73            // запускам все сначала
74            while let Some(res) = task_set.join_next().await {
75                warn!("{res:?}");
76                task_set.abort_all()
77            }
78        }
79    }
80}