1use embedded_hal::{
10 delay::DelayNs,
11 digital::{InputPin, OutputPin},
12 spi::SpiDevice,
13};
14
15use crate::color::Color;
16use crate::interface::DisplayInterface;
17use crate::prelude::{TriColor, WaveshareDisplay, WaveshareThreeColorDisplay};
18use crate::traits::{InternalWiAdditions, RefreshLut};
19
20pub(crate) mod command;
21use self::command::Command;
22use crate::buffer_len;
23
24#[cfg(feature = "graphics")]
26pub type Display5in83 = crate::graphics::Display<
27 WIDTH,
28 HEIGHT,
29 false,
30 { buffer_len(WIDTH as usize, HEIGHT as usize * 2) },
31 TriColor,
32>;
33
34pub const WIDTH: u32 = 648;
36pub const HEIGHT: u32 = 480;
38pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White;
40const IS_BUSY_LOW: bool = true;
41const NUM_DISPLAY_BITS: u32 = WIDTH / 8 * HEIGHT;
42const SINGLE_BYTE_WRITE: bool = true;
43
44pub struct Epd5in83<SPI, BUSY, DC, RST, DELAY> {
47 interface: DisplayInterface<SPI, BUSY, DC, RST, DELAY, SINGLE_BYTE_WRITE>,
49 color: Color,
51}
52
53impl<SPI, BUSY, DC, RST, DELAY> InternalWiAdditions<SPI, BUSY, DC, RST, DELAY>
54 for Epd5in83<SPI, BUSY, DC, RST, DELAY>
55where
56 SPI: SpiDevice,
57 BUSY: InputPin,
58 DC: OutputPin,
59 RST: OutputPin,
60 DELAY: DelayNs,
61{
62 fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
63 self.interface.reset(delay, 10_000, 10_000);
65
66 self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x1e, 0x17])?;
68
69 self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F])?;
71
72 self.command(spi, Command::PowerOn)?;
74 delay.delay_us(5000);
75 self.wait_until_idle(spi, delay)?;
76
77 self.cmd_with_data(spi, Command::PanelSetting, &[0x0F])?;
79
80 self.send_resolution(spi)?;
82
83 self.cmd_with_data(spi, Command::DualSPI, &[0x00])?;
85
86 self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x11, 0x07])?;
88
89 self.cmd_with_data(spi, Command::TconSetting, &[0x22])?;
91
92 self.wait_until_idle(spi, delay)?;
93 Ok(())
94 }
95}
96
97impl<SPI, BUSY, DC, RST, DELAY> WaveshareThreeColorDisplay<SPI, BUSY, DC, RST, DELAY>
98 for Epd5in83<SPI, BUSY, DC, RST, DELAY>
99where
100 SPI: SpiDevice,
101 BUSY: InputPin,
102 DC: OutputPin,
103 RST: OutputPin,
104 DELAY: DelayNs,
105{
106 fn update_color_frame(
107 &mut self,
108 spi: &mut SPI,
109 delay: &mut DELAY,
110 black: &[u8],
111 chromatic: &[u8],
112 ) -> Result<(), SPI::Error> {
113 self.update_achromatic_frame(spi, delay, black)?;
114 self.update_chromatic_frame(spi, delay, chromatic)?;
115 Ok(())
116 }
117
118 fn update_achromatic_frame(
119 &mut self,
120 spi: &mut SPI,
121 delay: &mut DELAY,
122 black: &[u8],
123 ) -> Result<(), SPI::Error> {
124 self.wait_until_idle(spi, delay)?;
125 self.cmd_with_data(spi, Command::DataStartTransmission1, black)?;
126 Ok(())
127 }
128
129 fn update_chromatic_frame(
130 &mut self,
131 spi: &mut SPI,
132 delay: &mut DELAY,
133 chromatic: &[u8],
134 ) -> Result<(), SPI::Error> {
135 self.wait_until_idle(spi, delay)?;
136 self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic)?;
137 Ok(())
138 }
139}
140
141impl<SPI, BUSY, DC, RST, DELAY> WaveshareDisplay<SPI, BUSY, DC, RST, DELAY>
142 for Epd5in83<SPI, BUSY, DC, RST, DELAY>
143where
144 SPI: SpiDevice,
145 BUSY: InputPin,
146 DC: OutputPin,
147 RST: OutputPin,
148 DELAY: DelayNs,
149{
150 type DisplayColor = Color;
151 fn new(
152 spi: &mut SPI,
153 busy: BUSY,
154 dc: DC,
155 rst: RST,
156 delay: &mut DELAY,
157 delay_us: Option<u32>,
158 ) -> Result<Self, SPI::Error> {
159 let interface = DisplayInterface::new(busy, dc, rst, delay_us);
160 let color = DEFAULT_BACKGROUND_COLOR;
161
162 let mut epd = Epd5in83 { interface, color };
163
164 epd.init(spi, delay)?;
165
166 Ok(epd)
167 }
168
169 fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
170 self.wait_until_idle(spi, delay)?;
171 self.command(spi, Command::PowerOff)?;
172 self.wait_until_idle(spi, delay)?;
173 self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?;
174 Ok(())
175 }
176
177 fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
178 self.init(spi, delay)
179 }
180
181 fn set_background_color(&mut self, color: Color) {
182 self.color = color;
183 }
184
185 fn background_color(&self) -> &Color {
186 &self.color
187 }
188
189 fn width(&self) -> u32 {
190 WIDTH
191 }
192
193 fn height(&self) -> u32 {
194 HEIGHT
195 }
196
197 fn update_frame(
198 &mut self,
199 spi: &mut SPI,
200 buffer: &[u8],
201 delay: &mut DELAY,
202 ) -> Result<(), SPI::Error> {
203 self.wait_until_idle(spi, delay)?;
204 self.update_achromatic_frame(spi, delay, buffer)?;
205 let color = self.color.get_byte_value();
206 self.command(spi, Command::DataStartTransmission2)?;
207 self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
208 Ok(())
209 }
210
211 fn update_partial_frame(
212 &mut self,
213 spi: &mut SPI,
214 delay: &mut DELAY,
215 buffer: &[u8],
216 x: u32,
217 y: u32,
218 width: u32,
219 height: u32,
220 ) -> Result<(), SPI::Error> {
221 self.wait_until_idle(spi, delay)?;
222 if buffer.len() as u32 != width / 8 * height {
223 }
225
226 let hrst_upper = (x / 8) as u8 >> 6;
227 let hrst_lower = ((x / 8) << 3) as u8;
228 let hred_upper = ((x + width) / 8) as u8 >> 6;
229 let hred_lower = (((x + width) / 8) << 3) as u8 & 0b111;
230 let vrst_upper = (y >> 8) as u8;
231 let vrst_lower = y as u8;
232 let vred_upper = ((y + height) >> 8) as u8;
233 let vred_lower = (y + height) as u8;
234 let pt_scan = 0x01; self.command(spi, Command::PartialIn)?;
237 self.command(spi, Command::PartialWindow)?;
238 self.send_data(
239 spi,
240 &[
241 hrst_upper, hrst_lower, hred_upper, hred_lower, vrst_upper, vrst_lower, vred_upper,
242 vred_lower, pt_scan,
243 ],
244 )?;
245 self.command(spi, Command::DataStartTransmission1)?;
246 self.send_data(spi, buffer)?;
247
248 let color = TriColor::Black.get_byte_value(); self.command(spi, Command::DataStartTransmission2)?;
250 self.interface
251 .data_x_times(spi, color, width * height / 8)?;
252
253 self.command(spi, Command::DisplayRefresh)?;
254 self.wait_until_idle(spi, delay)?;
255
256 self.command(spi, Command::PartialOut)?;
257 Ok(())
258 }
259
260 fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
261 self.command(spi, Command::DisplayRefresh)?;
262 self.wait_until_idle(spi, delay)?;
263 Ok(())
264 }
265
266 fn update_and_display_frame(
267 &mut self,
268 spi: &mut SPI,
269 buffer: &[u8],
270 delay: &mut DELAY,
271 ) -> Result<(), SPI::Error> {
272 self.update_frame(spi, buffer, delay)?;
273 self.display_frame(spi, delay)?;
274 Ok(())
275 }
276
277 fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
278 self.wait_until_idle(spi, delay)?;
279
280 self.command(spi, Command::DataStartTransmission1)?;
282 self.interface.data_x_times(spi, 0xFF, NUM_DISPLAY_BITS)?;
283
284 self.command(spi, Command::DataStartTransmission2)?;
285 self.interface.data_x_times(spi, 0x00, NUM_DISPLAY_BITS)?;
286
287 Ok(())
288 }
289
290 fn set_lut(
291 &mut self,
292 _spi: &mut SPI,
293 _delay: &mut DELAY,
294 _refresh_rate: Option<RefreshLut>,
295 ) -> Result<(), SPI::Error> {
296 unimplemented!();
297 }
298
299 fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
300 self.interface.wait_until_idle(delay, IS_BUSY_LOW);
301 Ok(())
302 }
303}
304
305impl<SPI, BUSY, DC, RST, DELAY> Epd5in83<SPI, BUSY, DC, RST, DELAY>
306where
307 SPI: SpiDevice,
308 BUSY: InputPin,
309 DC: OutputPin,
310 RST: OutputPin,
311 DELAY: DelayNs,
312{
313 fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> {
314 self.interface.cmd(spi, command)
315 }
316
317 fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> {
318 self.interface.data(spi, data)
319 }
320
321 fn cmd_with_data(
322 &mut self,
323 spi: &mut SPI,
324 command: Command,
325 data: &[u8],
326 ) -> Result<(), SPI::Error> {
327 self.interface.cmd_with_data(spi, command, data)
328 }
329
330 fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
331 let w = self.width();
332 let h = self.height();
333
334 self.command(spi, Command::TconResolution)?;
335 self.send_data(spi, &[(w >> 8) as u8])?;
336 self.send_data(spi, &[w as u8])?;
337 self.send_data(spi, &[(h >> 8) as u8])?;
338 self.send_data(spi, &[h as u8])
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use super::*;
345
346 #[test]
347 fn epd_size() {
348 assert_eq!(WIDTH, 648);
349 assert_eq!(HEIGHT, 480);
350 assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::White);
351 }
352}