epd_waveshare/epd1in54b/
mod.rs

1//! A simple Driver for the Waveshare 1.54" (B) E-Ink Display via SPI
2
3use embedded_hal::{delay::*, digital::*, spi::SpiDevice};
4
5use crate::interface::DisplayInterface;
6use crate::traits::{
7    InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay,
8};
9
10//The Lookup Tables for the Display
11mod constants;
12use crate::epd1in54b::constants::*;
13
14/// Width of epd1in54 in pixels
15pub const WIDTH: u32 = 200;
16/// Height of epd1in54 in pixels
17pub const HEIGHT: u32 = 200;
18/// Default Background Color (white)
19pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White;
20const IS_BUSY_LOW: bool = true;
21const SINGLE_BYTE_WRITE: bool = true;
22
23use crate::color::Color;
24
25pub(crate) mod command;
26use self::command::Command;
27use crate::buffer_len;
28
29/// Full size buffer for use with the 1in54b EPD
30/// TODO this should be a TriColor, but let's keep it as is at first
31#[cfg(feature = "graphics")]
32pub type Display1in54b = crate::graphics::Display<
33    WIDTH,
34    HEIGHT,
35    false,
36    { buffer_len(WIDTH as usize, HEIGHT as usize) },
37    Color,
38>;
39
40/// Epd1in54b driver
41pub struct Epd1in54b<SPI, BUSY, DC, RST, DELAY> {
42    interface: DisplayInterface<SPI, BUSY, DC, RST, DELAY, SINGLE_BYTE_WRITE>,
43    color: Color,
44}
45
46impl<SPI, BUSY, DC, RST, DELAY> InternalWiAdditions<SPI, BUSY, DC, RST, DELAY>
47    for Epd1in54b<SPI, BUSY, DC, RST, DELAY>
48where
49    SPI: SpiDevice,
50    BUSY: InputPin,
51    DC: OutputPin,
52    RST: OutputPin,
53    DELAY: DelayNs,
54{
55    fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
56        self.interface.reset(delay, 10_000, 10_000);
57
58        // set the power settings
59        self.interface
60            .cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x00, 0x08, 0x00])?;
61
62        // start the booster
63        self.interface
64            .cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x07])?;
65
66        // power on
67        self.command(spi, Command::PowerOn)?;
68        delay.delay_us(5000);
69        self.wait_until_idle(spi, delay)?;
70
71        // set the panel settings
72        self.cmd_with_data(spi, Command::PanelSetting, &[0xCF])?;
73
74        self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?;
75
76        // PLL
77        self.cmd_with_data(spi, Command::PllControl, &[0x39])?;
78
79        // set resolution
80        self.send_resolution(spi)?;
81
82        self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0E])?;
83
84        self.set_lut(spi, delay, None)?;
85
86        self.wait_until_idle(spi, delay)?;
87
88        Ok(())
89    }
90}
91
92impl<SPI, BUSY, DC, RST, DELAY> WaveshareThreeColorDisplay<SPI, BUSY, DC, RST, DELAY>
93    for Epd1in54b<SPI, BUSY, DC, RST, DELAY>
94where
95    SPI: SpiDevice,
96    BUSY: InputPin,
97    DC: OutputPin,
98    RST: OutputPin,
99    DELAY: DelayNs,
100{
101    fn update_color_frame(
102        &mut self,
103        spi: &mut SPI,
104        delay: &mut DELAY,
105        black: &[u8],
106        chromatic: &[u8],
107    ) -> Result<(), SPI::Error> {
108        self.update_achromatic_frame(spi, delay, black)?;
109        self.update_chromatic_frame(spi, delay, chromatic)
110    }
111
112    fn update_achromatic_frame(
113        &mut self,
114        spi: &mut SPI,
115        delay: &mut DELAY,
116        black: &[u8],
117    ) -> Result<(), SPI::Error> {
118        self.wait_until_idle(spi, delay)?;
119        self.send_resolution(spi)?;
120
121        self.interface.cmd(spi, Command::DataStartTransmission1)?;
122
123        for b in black {
124            let expanded = expand_bits(*b);
125            self.interface.data(spi, &expanded)?;
126        }
127        Ok(())
128    }
129
130    fn update_chromatic_frame(
131        &mut self,
132        spi: &mut SPI,
133        _delay: &mut DELAY,
134        chromatic: &[u8],
135    ) -> Result<(), SPI::Error> {
136        self.interface.cmd(spi, Command::DataStartTransmission2)?;
137        self.interface.data(spi, chromatic)?;
138        Ok(())
139    }
140}
141
142impl<SPI, BUSY, DC, RST, DELAY> WaveshareDisplay<SPI, BUSY, DC, RST, DELAY>
143    for Epd1in54b<SPI, BUSY, DC, RST, DELAY>
144where
145    SPI: SpiDevice,
146    BUSY: InputPin,
147    DC: OutputPin,
148    RST: OutputPin,
149    DELAY: DelayNs,
150{
151    type DisplayColor = Color;
152    fn new(
153        spi: &mut SPI,
154        busy: BUSY,
155        dc: DC,
156        rst: RST,
157        delay: &mut DELAY,
158        delay_us: Option<u32>,
159    ) -> Result<Self, SPI::Error> {
160        let interface = DisplayInterface::new(busy, dc, rst, delay_us);
161        let color = DEFAULT_BACKGROUND_COLOR;
162
163        let mut epd = Epd1in54b { interface, color };
164
165        epd.init(spi, delay)?;
166
167        Ok(epd)
168    }
169
170    fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
171        self.wait_until_idle(spi, delay)?;
172        self.interface
173            .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating
174
175        self.interface
176            .cmd_with_data(spi, Command::VcmDcSetting, &[0x00])?; // Vcom to 0V
177
178        self.interface
179            .cmd_with_data(spi, Command::PowerSetting, &[0x02, 0x00, 0x00, 0x00])?; //VG&VS to 0V fast
180
181        self.wait_until_idle(spi, delay)?;
182
183        //NOTE: The example code has a 1s delay here
184
185        self.command(spi, Command::PowerOff)?;
186
187        Ok(())
188    }
189
190    fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
191        self.init(spi, delay)
192    }
193
194    fn set_background_color(&mut self, color: Color) {
195        self.color = color;
196    }
197
198    fn background_color(&self) -> &Color {
199        &self.color
200    }
201
202    fn width(&self) -> u32 {
203        WIDTH
204    }
205
206    fn height(&self) -> u32 {
207        HEIGHT
208    }
209
210    fn update_frame(
211        &mut self,
212        spi: &mut SPI,
213        buffer: &[u8],
214        delay: &mut DELAY,
215    ) -> Result<(), SPI::Error> {
216        self.wait_until_idle(spi, delay)?;
217        self.send_resolution(spi)?;
218
219        self.interface.cmd(spi, Command::DataStartTransmission1)?;
220
221        for b in buffer {
222            // Two bits per pixel
223            let expanded = expand_bits(*b);
224            self.interface.data(spi, &expanded)?;
225        }
226
227        //NOTE: Example code has a delay here
228
229        // Clear the read layer
230        let color = self.color.get_byte_value();
231        let nbits = WIDTH * (HEIGHT / 8);
232
233        self.interface.cmd(spi, Command::DataStartTransmission2)?;
234        self.interface.data_x_times(spi, color, nbits)?;
235
236        //NOTE: Example code has a delay here
237        Ok(())
238    }
239
240    #[allow(unused)]
241    fn update_partial_frame(
242        &mut self,
243        spi: &mut SPI,
244        delay: &mut DELAY,
245        buffer: &[u8],
246        x: u32,
247        y: u32,
248        width: u32,
249        height: u32,
250    ) -> Result<(), SPI::Error> {
251        unimplemented!()
252    }
253
254    fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
255        self.wait_until_idle(spi, delay)?;
256        self.command(spi, Command::DisplayRefresh)?;
257        Ok(())
258    }
259
260    fn update_and_display_frame(
261        &mut self,
262        spi: &mut SPI,
263        buffer: &[u8],
264        delay: &mut DELAY,
265    ) -> Result<(), SPI::Error> {
266        self.update_frame(spi, buffer, delay)?;
267        self.display_frame(spi, delay)?;
268        Ok(())
269    }
270
271    fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
272        self.wait_until_idle(spi, delay)?;
273        self.send_resolution(spi)?;
274
275        let color = DEFAULT_BACKGROUND_COLOR.get_byte_value();
276
277        // Clear the black
278        self.interface.cmd(spi, Command::DataStartTransmission1)?;
279
280        // Uses 2 bits per pixel
281        self.interface
282            .data_x_times(spi, color, 2 * (WIDTH / 8 * HEIGHT))?;
283
284        // Clear the red
285        self.interface.cmd(spi, Command::DataStartTransmission2)?;
286        self.interface
287            .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?;
288        Ok(())
289    }
290
291    fn set_lut(
292        &mut self,
293        spi: &mut SPI,
294        _delay: &mut DELAY,
295        _refresh_rate: Option<RefreshLut>,
296    ) -> Result<(), SPI::Error> {
297        self.interface
298            .cmd_with_data(spi, Command::LutForVcom, LUT_VCOM0)?;
299        self.interface
300            .cmd_with_data(spi, Command::LutWhiteToWhite, LUT_WHITE_TO_WHITE)?;
301        self.interface
302            .cmd_with_data(spi, Command::LutBlackToWhite, LUT_BLACK_TO_WHITE)?;
303        self.interface.cmd_with_data(spi, Command::LutG0, LUT_G1)?;
304        self.interface.cmd_with_data(spi, Command::LutG1, LUT_G2)?;
305        self.interface
306            .cmd_with_data(spi, Command::LutRedVcom, LUT_RED_VCOM)?;
307        self.interface
308            .cmd_with_data(spi, Command::LutRed0, LUT_RED0)?;
309        self.interface
310            .cmd_with_data(spi, Command::LutRed1, LUT_RED1)?;
311
312        Ok(())
313    }
314
315    fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
316        self.interface.wait_until_idle(delay, IS_BUSY_LOW);
317        Ok(())
318    }
319}
320
321impl<SPI, BUSY, DC, RST, DELAY> Epd1in54b<SPI, BUSY, DC, RST, DELAY>
322where
323    SPI: SpiDevice,
324    BUSY: InputPin,
325    DC: OutputPin,
326    RST: OutputPin,
327    DELAY: DelayNs,
328{
329    fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> {
330        self.interface.cmd(spi, command)
331    }
332
333    fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> {
334        self.interface.data(spi, data)
335    }
336
337    fn cmd_with_data(
338        &mut self,
339        spi: &mut SPI,
340        command: Command,
341        data: &[u8],
342    ) -> Result<(), SPI::Error> {
343        self.interface.cmd_with_data(spi, command, data)
344    }
345
346    fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
347        let w = self.width();
348        let h = self.height();
349
350        self.command(spi, Command::ResolutionSetting)?;
351
352        self.send_data(spi, &[w as u8])?;
353        self.send_data(spi, &[(h >> 8) as u8])?;
354        self.send_data(spi, &[h as u8])
355    }
356}
357
358fn expand_bits(bits: u8) -> [u8; 2] {
359    let mut x = bits as u16;
360
361    x = (x | (x << 4)) & 0x0F0F;
362    x = (x | (x << 2)) & 0x3333;
363    x = (x | (x << 1)) & 0x5555;
364    x = x | (x << 1);
365
366    [(x >> 8) as u8, (x & 0xFF) as u8]
367}
368
369#[cfg(test)]
370mod tests {
371    use super::*;
372
373    #[test]
374    fn epd_size() {
375        assert_eq!(WIDTH, 200);
376        assert_eq!(HEIGHT, 200);
377        assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::White);
378    }
379}