1use embedded_hal::{
13 delay::DelayNs,
14 digital::{InputPin, OutputPin},
15 spi::SpiDevice,
16};
17
18use crate::color::Color;
19use crate::interface::DisplayInterface;
20use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay};
21
22pub(crate) mod command;
23use self::command::Command;
24use crate::buffer_len;
25
26#[cfg(feature = "graphics")]
28pub type Display7in5 = crate::graphics::Display<
29 WIDTH,
30 HEIGHT,
31 false,
32 { buffer_len(WIDTH as usize, HEIGHT as usize) },
33 Color,
34>;
35
36pub const WIDTH: u32 = 880;
38pub const HEIGHT: u32 = 528;
40pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false;
43const SINGLE_BYTE_WRITE: bool = false;
44
45pub struct Epd7in5<SPI, BUSY, DC, RST, DELAY> {
48 interface: DisplayInterface<SPI, BUSY, DC, RST, DELAY, SINGLE_BYTE_WRITE>,
50 color: Color,
52}
53
54impl<SPI, BUSY, DC, RST, DELAY> InternalWiAdditions<SPI, BUSY, DC, RST, DELAY>
55 for Epd7in5<SPI, BUSY, DC, RST, DELAY>
56where
57 SPI: SpiDevice,
58 BUSY: InputPin,
59 DC: OutputPin,
60 RST: OutputPin,
61 DELAY: DelayNs,
62{
63 fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
64 self.interface.reset(delay, 10_000, 2_000);
66
67 self.wait_until_idle(spi, delay)?;
73 self.command(spi, Command::SwReset)?;
74 self.wait_until_idle(spi, delay)?;
75
76 self.cmd_with_data(spi, Command::AutoWriteRed, &[0xF7])?;
77 self.wait_until_idle(spi, delay)?;
78 self.cmd_with_data(spi, Command::AutoWriteBw, &[0xF7])?;
79 self.wait_until_idle(spi, delay)?;
80
81 self.cmd_with_data(spi, Command::SoftStart, &[0xAE, 0xC7, 0xC3, 0xC0, 0x40])?;
82
83 self.cmd_with_data(spi, Command::DriverOutputControl, &[0xAF, 0x02, 0x01])?;
84
85 self.cmd_with_data(spi, Command::DataEntry, &[0x01])?;
86
87 self.cmd_with_data(spi, Command::SetRamXStartEnd, &[0x00, 0x00, 0x6F, 0x03])?;
88 self.cmd_with_data(spi, Command::SetRamYStartEnd, &[0xAF, 0x02, 0x00, 0x00])?;
89
90 self.cmd_with_data(spi, Command::VbdControl, &[0x05])?;
91
92 self.cmd_with_data(spi, Command::TemperatureSensorControl, &[0x80])?;
93
94 self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xB1])?;
95
96 self.command(spi, Command::MasterActivation)?;
97 self.wait_until_idle(spi, delay)?;
98
99 self.cmd_with_data(spi, Command::SetRamXAc, &[0x00, 0x00])?;
100 self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?;
101
102 Ok(())
103 }
104}
105
106impl<SPI, BUSY, DC, RST, DELAY> WaveshareDisplay<SPI, BUSY, DC, RST, DELAY>
107 for Epd7in5<SPI, BUSY, DC, RST, DELAY>
108where
109 SPI: SpiDevice,
110 BUSY: InputPin,
111 DC: OutputPin,
112 RST: OutputPin,
113 DELAY: DelayNs,
114{
115 type DisplayColor = Color;
116 fn new(
117 spi: &mut SPI,
118 busy: BUSY,
119 dc: DC,
120 rst: RST,
121 delay: &mut DELAY,
122 delay_us: Option<u32>,
123 ) -> Result<Self, SPI::Error> {
124 let interface = DisplayInterface::new(busy, dc, rst, delay_us);
125 let color = DEFAULT_BACKGROUND_COLOR;
126
127 let mut epd = Epd7in5 { interface, color };
128
129 epd.init(spi, delay)?;
130
131 Ok(epd)
132 }
133
134 fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
135 self.init(spi, delay)
136 }
137
138 fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
139 self.wait_until_idle(spi, delay)?;
140 self.cmd_with_data(spi, Command::DeepSleep, &[0x01])?;
141 Ok(())
142 }
143
144 fn update_frame(
145 &mut self,
146 spi: &mut SPI,
147 buffer: &[u8],
148 delay: &mut DELAY,
149 ) -> Result<(), SPI::Error> {
150 self.wait_until_idle(spi, delay)?;
151 self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?;
152 self.cmd_with_data(spi, Command::WriteRamBw, buffer)?;
153 self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?;
154 Ok(())
155 }
156
157 fn update_partial_frame(
158 &mut self,
159 _spi: &mut SPI,
160 _delay: &mut DELAY,
161 _buffer: &[u8],
162 _x: u32,
163 _y: u32,
164 _width: u32,
165 _height: u32,
166 ) -> Result<(), SPI::Error> {
167 unimplemented!();
168 }
169
170 fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
171 self.command(spi, Command::MasterActivation)?;
172 self.wait_until_idle(spi, delay)?;
173 Ok(())
174 }
175
176 fn update_and_display_frame(
177 &mut self,
178 spi: &mut SPI,
179 buffer: &[u8],
180 delay: &mut DELAY,
181 ) -> Result<(), SPI::Error> {
182 self.update_frame(spi, buffer, delay)?;
183 self.display_frame(spi, delay)?;
184 Ok(())
185 }
186
187 fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
188 let pixel_count = WIDTH / 8 * HEIGHT;
189 let background_color_byte = self.color.get_byte_value();
190
191 self.wait_until_idle(spi, delay)?;
192 self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?;
193
194 for cmd in &[Command::WriteRamBw, Command::WriteRamRed] {
195 self.command(spi, *cmd)?;
196 self.interface
197 .data_x_times(spi, background_color_byte, pixel_count)?;
198 }
199
200 self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?;
201 self.command(spi, Command::MasterActivation)?;
202 self.wait_until_idle(spi, delay)?;
203 Ok(())
204 }
205
206 fn set_background_color(&mut self, color: Color) {
207 self.color = color;
208 }
209
210 fn background_color(&self) -> &Color {
211 &self.color
212 }
213
214 fn width(&self) -> u32 {
215 WIDTH
216 }
217
218 fn height(&self) -> u32 {
219 HEIGHT
220 }
221
222 fn set_lut(
223 &mut self,
224 _spi: &mut SPI,
225 _delay: &mut DELAY,
226 _refresh_rate: Option<RefreshLut>,
227 ) -> Result<(), SPI::Error> {
228 unimplemented!();
229 }
230
231 fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
232 self.interface.wait_until_idle(delay, IS_BUSY_LOW);
233 Ok(())
234 }
235}
236
237impl<SPI, BUSY, DC, RST, DELAY> Epd7in5<SPI, BUSY, DC, RST, DELAY>
238where
239 SPI: SpiDevice,
240 BUSY: InputPin,
241 DC: OutputPin,
242 RST: OutputPin,
243 DELAY: DelayNs,
244{
245 fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> {
246 self.interface.cmd(spi, command)
247 }
248
249 fn cmd_with_data(
250 &mut self,
251 spi: &mut SPI,
252 command: Command,
253 data: &[u8],
254 ) -> Result<(), SPI::Error> {
255 self.interface.cmd_with_data(spi, command, data)
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262
263 #[test]
264 fn epd_size() {
265 assert_eq!(WIDTH, 880);
266 assert_eq!(HEIGHT, 528);
267 assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::White);
268 }
269}