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}