minitel_esp/
lib.rs

1#[doc(inline)]
2pub use esp::*;
3
4#[cfg(feature = "esp")]
5mod esp {
6    use esp_idf_hal::{
7        gpio::AnyIOPin,
8        io::Write,
9        sys::{EspError, TickType_t},
10        uart,
11        units::Hertz,
12    };
13    use minitel_stum::{Minitel, MinitelBaudrateControl, MinitelRead, MinitelWrite};
14    use std::io::{Error, ErrorKind, Result};
15
16    /// Minitel instance using the ESP32 UART.
17    pub type ESPMinitel<'a> = Minitel<ESPPort<'a>>;
18
19    /// Create a new Minitel instance using the ESP32 UART.
20    pub fn esp_minitel(uart: uart::UartDriver, read_timeout: TickType_t) -> ESPMinitel {
21        ESPMinitel::new(ESPPort::new(uart, read_timeout))
22    }
23
24    /// Serial port configuration when the minitel starts
25    pub fn default_uart_config() -> uart::UartConfig {
26        uart::UartConfig::default()
27            .baudrate(Hertz(1200))
28            .stop_bits(uart::config::StopBits::STOP1)
29            .data_bits(uart::config::DataBits::DataBits7)
30            .parity_even()
31    }
32
33    /// Create a new Minitel instance using the port UART 2.
34    ///
35    /// This is the port used in the ESP32 minitel development board from iodeo.
36    pub fn esp_minitel_uart2() -> core::result::Result<ESPMinitel<'static>, EspError> {
37        let peripherals = esp_idf_hal::peripherals::Peripherals::take()?;
38        let pins = peripherals.pins;
39
40        let uart: uart::UartDriver = uart::UartDriver::new(
41            peripherals.uart2,
42            pins.gpio17,
43            pins.gpio16,
44            Option::<AnyIOPin>::None,
45            Option::<AnyIOPin>::None,
46            &default_uart_config(),
47        )?;
48
49        Ok(esp_minitel(uart, 50))
50    }
51
52    /// Implemenation of the minitel traits for the ESP32 UART.
53    pub struct ESPPort<'a> {
54        pub uart: uart::UartDriver<'a>,
55        pub read_timeout: TickType_t,
56    }
57
58    impl<'a> ESPPort<'a> {
59        pub fn new(uart: uart::UartDriver<'a>, read_timeout: TickType_t) -> Self {
60            Self { uart, read_timeout }
61        }
62    }
63
64    impl<'a> MinitelWrite for ESPPort<'a> {
65        fn send(&mut self, data: &[u8]) -> Result<()> {
66            self.uart
67                .write_all(data)
68                .map_err(|e| Error::new(ErrorKind::Other, e))
69        }
70
71        fn flush(&mut self) -> Result<()> {
72            self.uart
73                .flush()
74                .map_err(|e| Error::new(ErrorKind::Other, e))
75        }
76    }
77
78    impl<'a> MinitelRead for ESPPort<'a> {
79        fn read(&mut self, data: &mut [u8]) -> Result<()> {
80            let read = self
81                .uart
82                .read(data, self.read_timeout)
83                .map_err(|e| Error::new(ErrorKind::Other, e))?;
84            if read != data.len() {
85                return Err(Error::new(ErrorKind::TimedOut, "Read timeout"));
86            }
87            Ok(())
88        }
89    }
90
91    impl<'a> MinitelBaudrateControl for ESPPort<'a> {
92        fn set_baudrate(&mut self, baudrate: minitel_stum::protocol::Baudrate) -> Result<()> {
93            self.uart
94                .change_baudrate(baudrate.hertz())
95                .map_err(|e| Error::new(ErrorKind::Other, e))?;
96            Ok(())
97        }
98    }
99}
100
101/// Doc shenanigans: stubs for ESP32 integration documentation when the ESP toolchain is not available
102#[cfg(not(feature = "esp"))]
103mod esp {
104    use minitel_stum::{Minitel, MinitelBaudrateControl, MinitelRead, MinitelWrite};
105    use std::io::{Error, ErrorKind, Result};
106
107    /// Minitel instance using the ESP32 UART.
108    pub type ESPMinitel<'a> = Minitel<ESPPort<'a>>;
109
110    /// Stub for doc only
111    #[doc(hidden)]
112    mod uart {
113        /// Stub for doc only
114        pub struct UartDriver<'a> {
115            _phantom: std::marker::PhantomData<&'a ()>,
116        }
117
118        /// Stub for doc only
119        pub struct UartConfig;
120
121        /// Stub for doc only
122        #[allow(non_camel_case_types)]
123        pub type TickType_t = u32;
124
125        /// Stub for doc only
126        pub struct EspError;
127    }
128
129    use uart::*;
130
131    /// Create a new Minitel instance using the ESP32 UART.
132    pub fn esp_minitel<'a>(uart: uart::UartDriver<'a>, read_timeout: TickType_t) -> ESPMinitel<'a> {
133        unimplemented!()
134    }
135
136    /// Serial port configuration when the minitel starts
137    pub fn default_uart_config() -> uart::UartConfig {
138        unimplemented!()
139    }
140
141    /// Create a new Minitel instance using the port UART 2.
142    ///
143    /// This is the port used in the ESP32 minitel development board from iodeo.
144    pub fn esp_minitel_uart2() -> core::result::Result<ESPMinitel<'static>, EspError> {
145        unimplemented!()
146    }
147
148    /// Implemenation of the minitel traits for the ESP32 UART.
149    pub struct ESPPort<'a> {
150        _phantom: std::marker::PhantomData<&'a ()>,
151    }
152
153    impl<'a> MinitelWrite for ESPPort<'a> {
154        fn send(&mut self, data: &[u8]) -> Result<()> {
155            unimplemented!()
156        }
157
158        fn flush(&mut self) -> Result<()> {
159            unimplemented!()
160        }
161    }
162
163    impl<'a> MinitelRead for ESPPort<'a> {
164        fn read(&mut self, data: &mut [u8]) -> Result<()> {
165            unimplemented!()
166        }
167    }
168
169    impl<'a> MinitelBaudrateControl for ESPPort<'a> {
170        fn set_baudrate(&mut self, baudrate: minitel_stum::protocol::Baudrate) -> Result<()> {
171            unimplemented!()
172        }
173    }
174}