rsiot/drivers_i2c/pm_di16/tasks/
output.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::{sync::Arc, time::Duration};

use pm_firmware_lib::pm_di16_dc24sink_v0_0_2::{I2cRequest, I2cResponse};
use tokio::{
    sync::{mpsc::Sender, Mutex},
    time::sleep,
};
use tracing::warn;

use crate::{
    drivers_i2c::{I2cSlaveAddress, RsiotI2cDriverBase},
    message::{Message, MsgDataBound},
    serde_utils::postcard_serde,
};

use super::super::config::FnOutput;

pub struct Output<TMsg, TDriver>
where
    TMsg: MsgDataBound,
    TDriver: RsiotI2cDriverBase,
{
    pub output: Sender<Message<TMsg>>,
    pub address: I2cSlaveAddress,
    pub fn_output_a_0: FnOutput<TMsg>,
    pub fn_output_a_1: FnOutput<TMsg>,
    pub fn_output_a_2: FnOutput<TMsg>,
    pub fn_output_a_3: FnOutput<TMsg>,
    pub fn_output_a_4: FnOutput<TMsg>,
    pub fn_output_a_5: FnOutput<TMsg>,
    pub fn_output_a_6: FnOutput<TMsg>,
    pub fn_output_a_7: FnOutput<TMsg>,

    pub fn_output_b_0: FnOutput<TMsg>,
    pub fn_output_b_1: FnOutput<TMsg>,
    pub fn_output_b_2: FnOutput<TMsg>,
    pub fn_output_b_3: FnOutput<TMsg>,
    pub fn_output_b_4: FnOutput<TMsg>,
    pub fn_output_b_5: FnOutput<TMsg>,
    pub fn_output_b_6: FnOutput<TMsg>,
    pub fn_output_b_7: FnOutput<TMsg>,
    pub fn_output_period: Duration,
    pub driver: Arc<Mutex<TDriver>>,
}

impl<TMsg, TDriver> Output<TMsg, TDriver>
where
    TMsg: MsgDataBound,
    TDriver: RsiotI2cDriverBase,
{
    pub async fn spawn(self) -> super::Result<()> {
        loop {
            sleep(self.fn_output_period).await;
            let result = self.request().await;
            if let Err(err) = result {
                warn!("I2c request error: {err}");
            }
        }
    }

    async fn request(&self) -> super::Result<()> {
        let req = I2cRequest::GetInput;
        let req = postcard_serde::serialize_crc_deprecated(&req)?;

        let mut response = {
            let mut driver = self.driver.lock().await;
            driver
                .write_read(
                    self.address,
                    &req,
                    postcard_serde::MESSAGE_LEN,
                    Duration::from_millis(100),
                )
                .await
                .map_err(super::Error::I2c)?
        };

        let response: I2cResponse = postcard_serde::deserialize(&mut response)?;

        match response {
            I2cResponse::InputsState {
                a0,
                a1,
                a2,
                a3,
                a4,
                a5,
                a6,
                a7,
                b0,
                b1,
                b2,
                b3,
                b4,
                b5,
                b6,
                b7,
            } => {
                let mut msgs = vec![];
                msgs.push((self.fn_output_a_0)(a0));
                msgs.push((self.fn_output_a_1)(a1));
                msgs.push((self.fn_output_a_2)(a2));
                msgs.push((self.fn_output_a_3)(a3));
                msgs.push((self.fn_output_a_4)(a4));
                msgs.push((self.fn_output_a_5)(a5));
                msgs.push((self.fn_output_a_6)(a6));
                msgs.push((self.fn_output_a_7)(a7));
                msgs.push((self.fn_output_b_0)(b0));
                msgs.push((self.fn_output_b_1)(b1));
                msgs.push((self.fn_output_b_2)(b2));
                msgs.push((self.fn_output_b_3)(b3));
                msgs.push((self.fn_output_b_4)(b4));
                msgs.push((self.fn_output_b_5)(b5));
                msgs.push((self.fn_output_b_6)(b6));
                msgs.push((self.fn_output_b_7)(b7));

                for msg in msgs {
                    let Some(msg) = msg else { continue };
                    self.output
                        .send(msg)
                        .await
                        .map_err(|e| super::Error::TokioSyncMpscSender(e.to_string()))?;
                }
            }
        }

        Ok(())
    }
}