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::{LCDResetOption, LCDResetHandler};
9use display_driver::panel::{Orientation, Panel};
10
11use display_driver::{ColorFormat, DisplayError};
12
13use display_driver_mipidcs as mipidcs;
14use display_driver_mipidcs::{dcs_types::AddressMode, GenericMipidcs};
15
16pub mod consts;
17pub mod spec;
18
19use consts::*;
20pub use spec::St7735Spec;
21
22pub struct St7735<Spec, RST, B>
24where
25 Spec: St7735Spec,
26 RST: OutputPin,
27 B: DisplayBus,
28{
29 inner: GenericMipidcs<B, Spec, RST>,
31}
32
33impl<Spec, RST, B> St7735<Spec, RST, B>
34where
35 Spec: St7735Spec,
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(FRMCTR1, &Spec::FRMCTR1_PARAMS),
72 InitStep::CommandWithParams(FRMCTR2, &Spec::FRMCTR2_PARAMS),
73 InitStep::CommandWithParams(FRMCTR3, &Spec::FRMCTR3_PARAMS),
74 InitStep::CommandWithParams(INVCTR, &[Spec::INVCTR_PARAM]),
75 InitStep::CommandWithParams(PWCTR1, &Spec::PWCTR1_PARAMS),
77 InitStep::CommandWithParams(PWCTR2, &[Spec::PWCTR2_PARAM]),
78 InitStep::CommandWithParams(PWCTR3, &Spec::PWCTR3_PARAMS),
79 InitStep::CommandWithParams(PWCTR4, &Spec::PWCTR4_PARAMS),
80 InitStep::CommandWithParams(PWCTR5, &Spec::PWCTR5_PARAMS),
81 InitStep::CommandWithParams(VMCTR1, &[Spec::VMCTR1_PARAM]),
82 InitStep::select_cmd(
84 Spec::INVERTED,
85 mipidcs::ENTER_INVERT_MODE,
86 mipidcs::EXIT_INVERT_MODE,
87 ),
88 InitStep::CommandWithParams(
89 mipidcs::SET_ADDRESS_MODE,
90 &[if Spec::BGR {
91 AddressMode::BGR.bits()
92 } else {
93 0u8
94 }],
95 ),
96 InitStep::maybe_cmd_with(GMCTRP1, Spec::GMCTRP1_PARAMS),
98 InitStep::maybe_cmd_with(GMCTRN1, Spec::GMCTRN1_PARAMS),
99 InitStep::SingleCommand(mipidcs::SET_DISPLAY_ON),
101 InitStep::DelayMs(20), ];
103}
104
105impl<Spec, RST, B> Panel<B> for St7735<Spec, RST, B>
106where
107 Spec: St7735Spec,
108 RST: OutputPin,
109 B: DisplayBus,
110{
111 const CMD_LEN: usize = 1;
112 const PIXEL_WRITE_CMD: [u8; 4] = [mipidcs::WRITE_MEMORY_START, 0, 0, 0];
113
114 async fn init<D: DelayNs>(&mut self, bus: &mut B, mut delay: D) -> Result<(), B::Error> {
115 let mut reseter = LCDResetHandler::new(
117 &mut self.inner.reset_pin,
118 bus,
119 &mut delay,
120 10,
121 120,
122 Some(&[mipidcs::SOFT_RESET]),
123 );
124 reseter.reset().await?;
125
126 self.inner.address_mode.set(AddressMode::BGR, Spec::BGR);
127
128 sequenced_init(Self::INIT_STEPS.iter().copied(), &mut delay, bus).await
131 }
132
133 delegate::delegate! {
134 to self.inner {
135 fn width(&self) -> u16;
136
137 fn height(&self) -> u16;
138
139 fn size(&self) -> (u16, u16);
140
141 async fn set_window(
142 &mut self,
143 bus: &mut B,
144 x0: u16,
145 y0: u16,
146 x1: u16,
147 y1: u16,
148 ) -> Result<(), DisplayError<B::Error>>;
149
150 async fn set_color_format(
151 &mut self,
152 bus: &mut B,
153 color_format: ColorFormat,
154 ) -> Result<(), DisplayError<B::Error>>;
155
156 async fn set_orientation(
157 &mut self,
158 bus: &mut B,
159 orientation: Orientation,
160 ) -> Result<(), DisplayError<B::Error>>;
161 }
162 }
163}