Skip to main content

display_driver/panel/
reset.rs

1use embedded_hal::digital::OutputPin;
2use embedded_hal_async::delay::DelayNs;
3
4use crate::{DisplayBus, DisplayError};
5
6/// Option for LCD reset control.
7pub enum LCDResetOption<P: OutputPin> {
8    /// Reset via a GPIO pin (active high).
9    PinHigh(P),
10    /// Reset via a GPIO pin (active low).
11    PinLow(P),
12    /// Reset via the display bus.
13    Bus,
14    /// Reset via software command (e.g. 0x01).
15    Software,
16    /// No hardware reset.
17    None,
18}
19
20impl<P: OutputPin> LCDResetOption<P> {
21    /// Creates a new PinLow reset option.
22    pub fn new_pin(pin: P) -> Self {
23        Self::PinLow(pin)
24    }
25
26    /// Creates a new reset option with specified active level.
27    pub fn new_pin_with_level(pin: P, reset_level: bool) -> Self {
28        if reset_level {
29            Self::PinHigh(pin)
30        } else {
31            Self::PinLow(pin)
32        }
33    }
34
35    /// Releases the pin if held.
36    pub fn release(self) -> Option<P> {
37        match self {
38            Self::PinHigh(pin) => Some(pin),
39            Self::PinLow(pin) => Some(pin),
40            Self::Bus => None,
41            Self::Software => None,
42            Self::None => None,
43        }
44    }
45
46    pub fn is_none(&self) -> bool {
47        matches!(self, Self::None)
48    }
49}
50
51impl LCDResetOption<NoResetPin> {
52    /// Creates a Bus reset option.
53    pub fn new_bus() -> Self {
54        Self::Bus
55    }
56
57    /// Creates a Software reset option.
58    pub fn new_software() -> Self {
59        Self::Software
60    }
61
62    /// Creates a None reset option.
63    pub fn none() -> Self {
64        Self::None
65    }
66}
67
68/// Helper to handle LCD hardware reset.
69pub struct LCDResetHandler<'a, P: OutputPin, B: DisplayBus, D: DelayNs> {
70    option: &'a mut LCDResetOption<P>,
71    bus: &'a mut B,
72    delay: &'a mut D,
73    gap_ms: u8,
74    wait_ms: u8,
75    software_reset_cmd: Option<&'a [u8]>,
76}
77
78impl<'a, P: OutputPin, B: DisplayBus, D: DelayNs> LCDResetHandler<'a, P, B, D> {
79    /// Creates a new LCDResetHandler.
80    pub fn new(
81        option: &'a mut LCDResetOption<P>,
82        bus: &'a mut B,
83        delay: &'a mut D,
84        gap_ms: u8,
85        wait_ms: u8,
86        software_reset_cmd: Option<&'a [u8]>,
87    ) -> Self {
88        Self {
89            option,
90            bus,
91            delay,
92            gap_ms,
93            wait_ms,
94            software_reset_cmd,
95        }
96    }
97
98    /// Sets the reset state.
99    pub fn set_reset(&mut self, reset: bool) -> Result<(), B::Error> {
100        match *self.option {
101            LCDResetOption::PinHigh(ref mut pin) => {
102                if reset {
103                    pin.set_high().map_err(|_| unreachable!())
104                } else {
105                    pin.set_low().map_err(|_| unreachable!())
106                }
107            }
108            LCDResetOption::PinLow(ref mut pin) => {
109                if reset {
110                    pin.set_low().map_err(|_| unreachable!())
111                } else {
112                    pin.set_high().map_err(|_| unreachable!())
113                }
114            }
115            LCDResetOption::Bus => self.bus.set_reset(reset).map_err(|err| match err {
116                DisplayError::BusError(e) => e,
117                DisplayError::Unsupported => panic!("Bus cannot reset"),
118                _ => unreachable!(),
119            }),
120            LCDResetOption::Software => Ok(()),
121            LCDResetOption::None => unreachable!(),
122        }
123    }
124
125    /// Performs the reset sequence: assert -> wait -> release -> wait.
126    pub async fn reset(&mut self) -> Result<(), B::Error> {
127        if matches!(self.option, LCDResetOption::Software) {
128            if let Some(cmd) = self.software_reset_cmd {
129                self.bus.write_cmd(cmd).await?;
130                self.delay.delay_ms(self.wait_ms as u32).await;
131            }
132            return Ok(());
133        }
134
135        if !self.option.is_none() {
136            self.set_reset(false)?;
137            self.delay.delay_ms(self.gap_ms as u32).await;
138            self.set_reset(true)?;
139            self.delay.delay_ms(self.gap_ms as u32).await;
140            self.set_reset(false)?;
141            self.delay.delay_ms(self.wait_ms as u32).await;
142        }
143        Ok(())
144    }
145}
146
147/// Dummy pin implementation for when no reset pin is used.
148pub struct NoResetPin {}
149impl embedded_hal::digital::ErrorType for NoResetPin {
150    type Error = core::convert::Infallible;
151}
152
153impl embedded_hal::digital::OutputPin for NoResetPin {
154    fn set_low(&mut self) -> Result<(), Self::Error> {
155        Ok(())
156    }
157
158    fn set_high(&mut self) -> Result<(), Self::Error> {
159        Ok(())
160    }
161}