rsiot/components/cmp_esp_gpio/
fn_process.rs

1use esp_idf_svc::hal::gpio::{Level, PinDriver};
2use tokio::task::JoinSet;
3
4use crate::{executor::CmpInOut, message::MsgDataBound};
5
6use super::{Config, ConfigGpioInput, ConfigGpioOutput};
7
8pub async fn fn_process<TMsg>(config: Config<TMsg>, in_out: CmpInOut<TMsg>) -> super::Result<()>
9where
10    TMsg: MsgDataBound + 'static,
11{
12    let mut task_set = JoinSet::new();
13    for config_input in config.inputs {
14        task_set.spawn_local(gpio_input(config_input, in_out.clone()));
15    }
16    for config_output in config.outputs {
17        task_set.spawn_local(gpio_output(config_output, in_out.clone()));
18    }
19
20    while let Some(res) = task_set.join_next().await {
21        res.unwrap();
22    }
23    Ok(())
24}
25
26/// Функция чтения одного входа
27async fn gpio_input<TMsg>(config_input: ConfigGpioInput<TMsg>, in_out: CmpInOut<TMsg>)
28where
29    TMsg: MsgDataBound,
30{
31    let mut pin = PinDriver::input(config_input.peripherals).unwrap();
32    pin.set_pull(config_input.pull).unwrap();
33
34    loop {
35        let level = pin.get_level();
36        let level = gpio_level_to_bool(&level);
37        let msg = (config_input.fn_output)(level);
38        in_out.send_output(msg).await.unwrap();
39        pin.wait_for_any_edge().await.unwrap();
40    }
41}
42
43/// Функция записи одного выхода
44async fn gpio_output<TMsg>(config_output: ConfigGpioOutput<TMsg>, mut in_out: CmpInOut<TMsg>)
45where
46    TMsg: MsgDataBound,
47{
48    let mut pin = PinDriver::output(config_output.peripherals).unwrap();
49
50    // Значение по-умолчанию
51    if config_output.is_low_triggered {
52        pin.set_high().unwrap();
53    } else {
54        pin.set_low().unwrap();
55    }
56
57    while let Ok(msg) = in_out.recv_input().await {
58        let level = (config_output.fn_input)(msg);
59        let Some(level) = level else { continue };
60        if config_output.is_low_triggered ^ level {
61            pin.set_high().unwrap();
62        } else {
63            pin.set_low().unwrap();
64        }
65    }
66}
67
68fn gpio_level_to_bool(level: &Level) -> bool {
69    match level {
70        Level::Low => true,
71        Level::High => false,
72    }
73}