1use crate::spi::{InnerDelay, SpiBusWrapper, SpiDev, SpiInitError, make_device};
2use esp_hal::gpio::{DriveMode, Level, Output, OutputConfig, Pull};
3#[cfg(feature = "blocking")]
4use mipidsi::{
5 interface::SpiInterface,
6 models::ST7789,
7 options::{ColorInversion, Orientation, RefreshOrder, Rotation, TearingEffect},
8 Builder,
9 Display,
10 NoResetPin
11};
12#[cfg(feature = "async")]
13use lcd_async::{
14 interface::SpiInterface,
15 models::ST7789,
16 options::{ColorInversion, Orientation, RefreshOrder, Rotation, TearingEffect},
17 Builder,
18 Display,
19 NoResetPin
20};
21use static_cell::StaticCell;
22
23#[cfg(feature = "display_buffer_512")]
24static DISPLAY_BUFFER_CELL: StaticCell<[u8; 512]> = StaticCell::new();
25#[cfg(feature = "display_buffer_1024")]
26static DISPLAY_BUFFER_CELL: StaticCell<[u8; 1024]> = StaticCell::new();
27#[cfg(feature = "display_buffer_8192")]
28static DISPLAY_BUFFER_CELL: StaticCell<[u8; 8192]> = StaticCell::new();
29
30#[cfg(feature = "blocking")]
62pub type LilkaDisplay =
63 Display<SpiInterface<'static, SpiDev<'static>, Output<'static>>, ST7789, NoResetPin>;
64#[cfg(feature = "async")]
65pub type LilkaDisplay =
66 Display<SpiInterface<SpiDev<'static>, Output<'static>>, ST7789, NoResetPin>;
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub enum DisplayInitError {
73 SpiDevice(SpiInitError),
75 ControllerInitFailed,
77 TearingConfigFailed,
79}
80
81impl DisplayInitError {
82 pub const fn as_str(self) -> &'static str {
84 match self {
85 Self::SpiDevice(err) => err.as_str(),
86 Self::ControllerInitFailed => "Display init failed",
87 Self::TearingConfigFailed => "Display tearing config failed",
88 }
89 }
90}
91
92#[cfg(feature = "blocking")]
93pub fn init_display(
94 dp: esp_hal::peripherals::GPIO46<'static>,
95 dc: esp_hal::peripherals::GPIO15<'static>,
96 cs: esp_hal::peripherals::GPIO7<'static>,
97 spi_bus: &'static SpiBusWrapper,
98 mut delay: InnerDelay,
99 refresh_order: RefreshOrder,
100 rotation: Rotation,
101 tearing: TearingEffect,
102) -> Result<LilkaDisplay, DisplayInitError> {
103 let mut display_power = Output::new(
104 dp,
105 Level::High,
106 OutputConfig::default()
107 .with_drive_mode(DriveMode::PushPull)
108 .with_pull(Pull::Down),
109 );
110 display_power.set_high();
111 let dc: Output<'static> = Output::new(
112 dc,
113 Level::Low,
114 OutputConfig::default().with_drive_mode(DriveMode::PushPull),
115 );
116 let disp_cs: Output<'static> = Output::new(
117 cs,
118 Level::Low,
119 OutputConfig::default().with_drive_mode(DriveMode::PushPull),
120 );
121 let spi_dev =
122 make_device(spi_bus, disp_cs, delay.clone()).map_err(DisplayInitError::SpiDevice)?;
123 #[cfg(feature = "blocking")]
124 {
125 cfg_if::cfg_if! {
126 if #[cfg(feature = "display_buffer_512")] {
127 let di = SpiInterface::new(spi_dev, dc, DISPLAY_BUFFER_CELL.init([0_u8; 512]));
128 } else if #[cfg(feature = "display_buffer_1024")] {
129 let di = SpiInterface::new(spi_dev, dc, DISPLAY_BUFFER_CELL.init([0_u8; 1024]));
130 } else if #[cfg(feature = "display_buffer_8192")] {
131 let di = SpiInterface::new(spi_dev, dc, DISPLAY_BUFFER_CELL.init([0_u8; 8192]));
132 } else {
133 compile_error!("Один з display_buffer_512, display_buffer_1024, або display_buffer_8192 має бути активний");
134 }
135 }
136 let mut display = Builder::new(ST7789, di)
137 .refresh_order(refresh_order)
138 .invert_colors(ColorInversion::Inverted)
139 .display_size(240, 280)
140 .orientation(Orientation::new().rotate(rotation))
141 .display_offset(0, 20)
142 .color_order(mipidsi::options::ColorOrder::Rgb)
143 .init(&mut delay)
144 .map_err(|_| DisplayInitError::ControllerInitFailed)?;
145 display
146 .set_tearing_effect(tearing)
147 .map_err(|_| DisplayInitError::TearingConfigFailed)?;
148 return Ok(display);
149 }
150}
151
152#[cfg(feature = "async")]
153pub async fn init_display(
154 dp: esp_hal::peripherals::GPIO46<'static>,
155 dc: esp_hal::peripherals::GPIO15<'static>,
156 cs: esp_hal::peripherals::GPIO7<'static>,
157 spi_bus: &'static SpiBusWrapper,
158 mut delay: InnerDelay,
159 refresh_order: RefreshOrder,
160 rotation: Rotation,
161 tearing: TearingEffect,
162) -> Result<LilkaDisplay, DisplayInitError> {
163 let mut display_power = Output::new(
164 dp,
165 Level::High,
166 OutputConfig::default()
167 .with_drive_mode(DriveMode::PushPull)
168 .with_pull(Pull::Down),
169 );
170 display_power.set_high();
171 let dc: Output<'static> = Output::new(
172 dc,
173 Level::Low,
174 OutputConfig::default().with_drive_mode(DriveMode::PushPull),
175 );
176 let disp_cs: Output<'static> = Output::new(
177 cs,
178 Level::Low,
179 OutputConfig::default().with_drive_mode(DriveMode::PushPull),
180 );
181 let spi_dev =
182 make_device(spi_bus, disp_cs, delay.clone()).map_err(DisplayInitError::SpiDevice)?;
183 let di = SpiInterface::new(spi_dev, dc);
184 let mut display = Builder::new(ST7789, di)
185 .refresh_order(refresh_order)
186 .invert_colors(ColorInversion::Inverted)
187 .display_size(240, 280)
188 .orientation(Orientation::new().rotate(rotation))
189 .display_offset(0, 20)
190 .color_order(lcd_async::options::ColorOrder::Rgb)
191 .init(&mut delay)
192 .await
193 .map_err(|_| DisplayInitError::ControllerInitFailed)?;
194 display
195 .set_tearing_effect(tearing)
196 .await
197 .map_err(|_| DisplayInitError::TearingConfigFailed)?;
198
199 Ok(display)
200}