1#![no_std]
2
3use embedded_hal::digital::OutputPin;
4use embedded_hal_async::delay::DelayNs;
5
6use display_driver::bus::DisplayBus;
7use display_driver::panel::initseq::{sequenced_init, InitStep};
8use display_driver::panel::reset::{LCDResetHandler, LCDResetOption};
9use display_driver::panel::{Orientation, Panel, PanelSetBrightness};
10
11use display_driver::{ColorFormat, DisplayError};
12
13use display_driver_mipidcs as mipidcs;
14use display_driver_mipidcs::{AddressMode, GenericMipidcs};
15
16pub mod consts;
17pub mod spec;
18
19use consts::*;
20pub use spec::St7789Spec;
21
22pub struct St7789<Spec, RST, B>
24where
25 Spec: St7789Spec,
26 RST: OutputPin,
27 B: DisplayBus,
28{
29 inner: GenericMipidcs<B, Spec, RST>,
31}
32
33impl<Spec, RST, B> St7789<Spec, RST, B>
34where
35 Spec: St7789Spec,
36 RST: OutputPin,
37 B: DisplayBus,
38{
39 pub fn new(reset_pin: LCDResetOption<RST>) -> Self {
41 Self {
42 inner: GenericMipidcs::new(reset_pin),
43 }
44 }
45
46 delegate::delegate! {
47 to self.inner {
48 pub async fn set_invert_mode(
49 &mut self,
50 bus: &mut B,
51 invert: bool,
52 ) -> Result<(), B::Error>;
53
54 pub async fn set_address_mode(
55 &mut self,
56 bus: &mut B,
57 address_mode: AddressMode,
58 orientation_if_changed: Option<Orientation>,
59 ) -> Result<(), B::Error>;
60
61 pub async fn set_bgr_order(&mut self, bus: &mut B, bgr: bool) -> Result<(), B::Error>;
62 }
63 }
64
65 const INIT_STEPS: &'static [InitStep<'static>] = &[
67 InitStep::SingleCommand(mipidcs::EXIT_SLEEP_MODE),
69 InitStep::DelayMs(120),
70 InitStep::CommandWithParams(
72 mipidcs::SET_PIXEL_FORMAT,
73 &mipidcs::PixelFormat::dbi_and_dpi(mipidcs::PixelFormatType::Bits16).as_bytes(),
74 ),
75 InitStep::CommandWithParams(PORCTRL, &Spec::PORCTRL_PARAMS),
77 InitStep::CommandWithParams(GCTRL, &[Spec::GCTRL_PARAM]),
79 InitStep::CommandWithParams(VCOMS, &[Spec::VCOMS_PARAM]),
81 InitStep::CommandWithParams(LCMCTRL, &[Spec::LCMCTRL_PARAM]),
83 InitStep::CommandWithParams(VDVVRHEN, &[0x01, 0xFF]),
85 InitStep::CommandWithParams(VRHS, &[Spec::VRHS_PARAM]),
87 InitStep::CommandWithParams(VDVS, &[Spec::VDVS_PARAM]),
89 InitStep::CommandWithParams(FRCTRL2, &[Spec::FRCTRL2_PARAM]),
91 InitStep::CommandWithParams(PWCTRL1, &Spec::PWCTRL1_PARAMS),
93 InitStep::maybe_cmd_with(PWCTRL2, Spec::PWCTRL2_PARAMS),
95 InitStep::maybe_cmd_with(EQCTRL, Spec::EQCTRL_PARAMS),
97 InitStep::maybe_cmd_with(GATESEL, Spec::GATESEL_PARAMS),
99 InitStep::CommandWithParams(PVGAMCTRL, &Spec::PVGAMCTRL_PARAMS),
101 InitStep::CommandWithParams(NVGAMCTRL, &Spec::NVGAMCTRL_PARAMS),
102 InitStep::select_cmd(
104 Spec::INVERTED,
105 mipidcs::ENTER_INVERT_MODE,
106 mipidcs::EXIT_INVERT_MODE,
107 ),
108 InitStep::CommandWithParams(
109 mipidcs::SET_ADDRESS_MODE,
110 &[if Spec::BGR {
111 AddressMode::BGR.bits()
112 } else {
113 0u8
114 }],
115 ),
116 InitStep::SingleCommand(mipidcs::SET_DISPLAY_ON),
118 InitStep::DelayMs(120),
119 ];
120}
121
122impl<Spec, RST, B> Panel<B> for St7789<Spec, RST, B>
123where
124 Spec: St7789Spec,
125 RST: OutputPin,
126 B: DisplayBus,
127{
128 const CMD_LEN: usize = 1;
129 const PIXEL_WRITE_CMD: [u8; 4] = [mipidcs::WRITE_MEMORY_START, 0, 0, 0];
130
131 async fn init<D: DelayNs>(&mut self, bus: &mut B, mut delay: D) -> Result<(), B::Error> {
132 let mut reseter = LCDResetHandler::new(
134 &mut self.inner.reset_pin,
135 bus,
136 &mut delay,
137 10,
138 120,
139 Some(&[mipidcs::SOFT_RESET]),
140 );
141 reseter.reset().await?;
142
143 self.inner.address_mode.set(AddressMode::BGR, Spec::BGR);
145
146 sequenced_init(Self::INIT_STEPS.iter().copied(), &mut delay, bus).await
149 }
150
151 delegate::delegate! {
152 to self.inner {
153 fn width(&self) -> u16;
154
155 fn height(&self) -> u16;
156
157 fn size(&self) -> (u16, u16);
158
159 async fn set_window(
160 &mut self,
161 bus: &mut B,
162 x0: u16,
163 y0: u16,
164 x1: u16,
165 y1: u16,
166 ) -> Result<(), DisplayError<B::Error>>;
167
168 async fn set_color_format(
169 &mut self,
170 bus: &mut B,
171 color_format: ColorFormat,
172 ) -> Result<(), DisplayError<B::Error>>;
173
174 async fn set_orientation(
175 &mut self,
176 bus: &mut B,
177 orientation: Orientation,
178 ) -> Result<(), DisplayError<B::Error>>;
179 }
180 }
181}
182
183impl<Spec, RST, B> PanelSetBrightness<B> for St7789<Spec, RST, B>
184where
185 Spec: St7789Spec,
186 RST: OutputPin,
187 B: DisplayBus,
188{
189 async fn set_brightness(
190 &mut self,
191 bus: &mut B,
192 brightness: u8,
193 ) -> Result<(), DisplayError<B::Error>> {
194 bus.write_cmd_with_params(&[WRDISBV], &[brightness])
195 .await
196 .map_err(DisplayError::BusError)
197 }
198}