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}