il0373/
display.rs

1use crate::command::{Command, DataInterval, DataPolarity};
2use crate::config::Config;
3use crate::interface::DisplayInterface;
4use hal;
5
6// Max display resolution is 160x296
7/// The maximum number of rows supported by the controller
8pub const MAX_GATE_OUTPUTS: u16 = 296;
9/// The maximum number of cols supported by the controller
10pub const MAX_SOURCE_OUTPUTS: u8 = 160;
11
12/// Represents the dimensions of the display.
13pub struct Dimensions {
14    /// The number of rows the display has.
15    ///
16    /// Must be less than or equal to MAX_GATE_OUTPUTS.
17    pub rows: u16,
18    /// The number of columns the display has.
19    ///
20    /// Must be less than or equal to MAX_SOURCE_OUTPUTS.
21    pub cols: u8,
22}
23
24/// Represents the physical rotation of the display relative to the native orientation.
25///
26/// For example the native orientation of the Inky pHAT display is a tall (portrait) 104x212
27/// display. `Rotate270` can be used to make it the right way up when attached to a Raspberry Pi
28/// Zero with the ports on the top.
29#[derive(Clone, Copy)]
30pub enum Rotation {
31    Rotate0,
32    Rotate90,
33    Rotate180,
34    Rotate270,
35}
36
37impl Default for Rotation {
38    /// Default is no rotation (`Rotate0`).
39    fn default() -> Self {
40        Rotation::Rotate0
41    }
42}
43
44/// A configured display with a hardware interface.
45pub struct Display<I>
46where
47    I: DisplayInterface,
48{
49    interface: I,
50    config: Config,
51}
52
53impl<I> Display<I>
54where
55    I: DisplayInterface,
56{
57    /// Create a new display instance from a DisplayInterface and Config.
58    ///
59    /// The `Config` is typically created with `config::Builder`.
60    pub fn new(interface: I, config: Config) -> Self {
61        Self { interface, config }
62    }
63
64    /// Perform a hardware reset
65    ///
66    /// This will wake a controller that has previously entered deep sleep.
67    pub fn reset<D: hal::delay::DelayNs>(&mut self, delay: &mut D) -> Result<(), I::Error> {
68        self.interface.reset(delay);
69        self.init(delay)
70    }
71
72    /// Initialize the controller
73    fn init<D: hal::delay::DelayNs>(&mut self, delay: &mut D) -> Result<(), I::Error> {
74        self.config.power_setting.execute(&mut self.interface)?;
75        self.config
76            .booster_soft_start
77            .execute(&mut self.interface)?;
78        Command::PowerOn.execute(&mut self.interface)?;
79        delay.delay_ms(200);
80        self.config.panel_setting.execute(&mut self.interface)?;
81        Command::VCOMDataIntervalSetting(0x0, DataPolarity::Both, DataInterval::V10)
82            .execute(&mut self.interface)?;
83        self.config.pll.execute(&mut self.interface)?;
84        Command::VCMDCSetting(0xA).execute(&mut self.interface)?;
85        delay.delay_ms(20);
86        Command::ResolutionSetting(self.config.dimensions.cols, self.config.dimensions.rows)
87            .execute(&mut self.interface)?;
88        Ok(())
89    }
90
91    /// Tell the hardware to update the display
92    pub fn signal_update(&mut self) -> Result<(), I::Error> {
93        // Kick off the display update
94        Command::DisplayRefresh.execute(&mut self.interface)
95    }
96
97    fn power_down(&mut self) -> Result<(), I::Error> {
98        self.interface.busy_wait();
99        Command::VCOMDataIntervalSetting(0x0, DataPolarity::BWOnly, DataInterval::V10)
100            .execute(&mut self.interface)?;
101        Command::VCMDCSetting(0).execute(&mut self.interface)?;
102        Command::PowerOff.execute(&mut self.interface)
103    }
104
105    /// Enter deep sleep mode.
106    ///
107    /// This puts the display controller into a low power mode. `reset` must be called to wake it
108    /// from sleep.
109    pub fn deep_sleep(&mut self) -> Result<(), I::Error> {
110        self.power_down()?;
111        Command::DeepSleep.execute(&mut self.interface)
112    }
113
114    /// Returns the number of rows the display has.
115    pub fn rows(&self) -> u16 {
116        self.config.dimensions.rows
117    }
118
119    /// Returns the number of columns the display has.
120    pub fn cols(&self) -> u8 {
121        self.config.dimensions.cols
122    }
123
124    /// Returns the rotation the display was configured with.
125    pub fn rotation(&self) -> Rotation {
126        self.config.rotation
127    }
128
129    /// returns the interface
130    pub fn interface(&mut self) -> &mut I {
131        &mut self.interface
132    }
133}