rsiot/components/cmp_esp_gpio/
fn_process.rs1use 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
26async 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
43async 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 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}