Skip to main content

display_driver/panel/
mod.rs

1use embedded_hal_async::delay::DelayNs;
2
3use crate::{bus::BusRead, ColorFormat, DisplayBus, DisplayError};
4
5pub mod initseq;
6pub mod reset;
7
8/// Display orientation.
9#[derive(Clone, Copy, PartialEq, Eq)]
10pub enum Orientation {
11    Deg0,
12    Deg90,
13    Deg180,
14    Deg270,
15}
16
17impl Orientation {
18    /// Returns true if the orientation is 90° or 270°.
19    pub fn is_transposed(&self) -> bool {
20        matches!(self, Orientation::Deg90 | Orientation::Deg270)
21    }
22
23    /// Returns true if the orientation is 180° or 270°.
24    pub fn is_inverted(&self) -> bool {
25        matches!(self, Orientation::Deg180 | Orientation::Deg270)
26    }
27}
28
29/// A trait representing a specific display panel model (e.g., ST7789, ILI9341).
30///
31/// While [`DisplayBus`] handles *how* data is sent to the screen, this `Panel` trait handles *what*
32/// is sent. It encapsulates the specific command set and initialization sequence required by the
33/// display controller IC.
34#[allow(async_fn_in_trait)]
35pub trait Panel<B: DisplayBus> {
36    const CMD_LEN: usize;
37
38    /// The specific command byte(s) used to initiate a pixel write operation to the display's RAM.
39    /// For many MIPI DCS compliant displays, this is `0x2C` (RAMWR).
40    ///
41    /// Note: We can't use `[u8; Self::CMD_LEN]` in stable Rust constants yet, so we use a reference 
42    /// slice `&PIXEL_WRITE_CMD[0..P::CMD_LEN]` when using this.
43    const PIXEL_WRITE_CMD: [u8; 4];
44
45    /// Returns the display width, accounting for orientation.
46    fn width(&self) -> u16;
47
48    /// Returns the display height, accounting for orientation.
49    fn height(&self) -> u16;
50
51    /// Returns the display size (width, height), accounting for orientation.
52    fn size(&self) -> (u16, u16) {
53        (self.width(), self.height())
54    }
55
56    /// Returns the X coordinate alignment requirements for this panel.
57    fn x_alignment(&self) -> u16 {
58        1
59    }
60
61    /// Returns the Y coordinate alignment requirements for this panel.
62    fn y_alignment(&self) -> u16 {
63        1
64    }
65
66    /// Initializes the panel.
67    async fn init<D: DelayNs>(&mut self, bus: &mut B, delay: D) -> Result<(), B::Error>;
68
69    /// Sets the active drawing window on the display.
70    ///
71    /// This method translates the abstract coordinates (x0, y0, x1, y1) into the specific "Column
72    /// Address Set" and "Page Address Set" commands understood by the display controller.
73    ///
74    /// Note: For some monochrome displays or AMOLED panels, coordinates must be aligned to 
75    /// `self.x_alignment()` and `self.y_alignment()`.
76    async fn set_window(
77        &mut self,
78        bus: &mut B,
79        x0: u16,
80        y0: u16,
81        x1: u16,
82        y1: u16,
83    ) -> Result<(), DisplayError<B::Error>>;
84
85    /// Sets the window to the full screen size.
86    async fn set_full_window(&mut self, bus: &mut B) -> Result<(), DisplayError<B::Error>> {
87        self.set_window(bus, 0, 0, self.width() - 1, self.height() - 1)
88            .await
89    }
90
91    /// Check the panel ID (if supported).
92    async fn check_id(&mut self, bus: &mut B) -> Result<bool, DisplayError<B::Error>>
93    where
94        B: BusRead,
95    {
96        let _ = bus;
97        Err(DisplayError::Unsupported)
98    }
99
100    /// Sets the display orientation.
101    async fn set_orientation(
102        &mut self,
103        bus: &mut B,
104        orientation: Orientation,
105    ) -> Result<(), DisplayError<B::Error>> {
106        let _ = (bus, orientation);
107        Err(DisplayError::Unsupported)
108    }
109
110    /// Configures the pixel color format (e.g., RGB565, RGB888).
111    ///
112    /// This updates the display controller's interface pixel format setting to match the data being
113    /// sent.
114    async fn set_color_format(
115        &mut self,
116        bus: &mut B,
117        color_format: ColorFormat,
118    ) -> Result<(), DisplayError<B::Error>>;
119}
120
121
122/// An optional trait for setting the panel’s own brightness via commands.
123///
124/// Note: Using a PWM pin to implement this trait is not recommended.
125#[allow(async_fn_in_trait)]
126pub trait PanelSetBrightness<B: DisplayBus>: Panel<B> {
127    /// Sets the panel’s own brightness.
128    ///
129    /// The brightness is represented as a value between 0 and 255, where 0 is the minimum
130    /// brightness and 255 is the maximum brightness.
131    async fn set_brightness(
132        &mut self,
133        bus: &mut B,
134        brightness: u8,
135    ) -> Result<(), DisplayError<B::Error>>;
136}