epd/
drivers.rs

1use crate::interface::{self, DisplayInterface};
2use embedded_graphics::prelude::GrayColor;
3use embedded_hal::blocking::delay::DelayUs;
4
5pub use self::ssd1608::SSD1608;
6
7mod ssd1608;
8
9// TOOD: add profile support
10pub trait Driver {
11    type Error;
12
13    /// Wake UP and init
14    fn wake_up<DI: DisplayInterface, DELAY: DelayUs<u32>>(
15        di: &mut DI,
16        delay: &mut DELAY,
17    ) -> Result<(), Self::Error>;
18
19    // also set ram pos
20    fn set_shape<DI: DisplayInterface>(di: &mut DI, x: u16, y: u16) -> Result<(), Self::Error>;
21
22    fn update_frame<'a, DI: DisplayInterface, I>(di: &mut DI, buffer: I) -> Result<(), Self::Error>
23    where
24        I: IntoIterator<Item = &'a u8>;
25
26    fn turn_on_display<DI: DisplayInterface>(di: &mut DI) -> Result<(), Self::Error>;
27
28    fn sleep<DI: DisplayInterface, DELAY: DelayUs<u32>>(
29        _di: &mut DI,
30        _delay: &mut DELAY,
31    ) -> Result<(), Self::Error> {
32        Ok(())
33    }
34}
35
36pub trait MultiColorDriver: Driver {
37    fn update_channel_frame<'a, DI: DisplayInterface, I>(
38        di: &mut DI,
39        channel: u8,
40        buffer: I,
41    ) -> Result<(), Self::Error>
42    where
43        I: IntoIterator<Item = &'a u8>;
44}
45
46pub trait GrayScaleDriver<Color: GrayColor>: Driver {
47    // const LUT_FULL_UPDATE: &'static [u8];
48    // const LUT_FRAME_UPDATE: &'static [u8];
49    fn setup_gray_scale<DI: DisplayInterface>(di: &mut DI) -> Result<(), Self::Error>;
50
51    fn restore_normal_mode<DI: DisplayInterface>(di: &mut DI) -> Result<(), Self::Error>;
52}
53
54/// Red/Black/White. 400 source outputs, 300 gate outputs
55/// or Red/Black. 400 source outputs, 300 gate outputs
56pub struct SSD1619A;
57
58impl Driver for SSD1619A {
59    type Error = interface::DisplayError;
60
61    fn wake_up<DI: DisplayInterface, DELAY: DelayUs<u32>>(
62        di: &mut DI,
63        delay: &mut DELAY,
64    ) -> Result<(), Self::Error> {
65        di.reset(delay, 200_000, 200_000);
66        di.busy_wait();
67
68        di.send_command(0x12)?; //swreset
69        di.busy_wait();
70
71        // Set analogue then digital block control
72        di.send_command_data(0x74, &[0x54])?;
73        di.send_command_data(0x7e, &[0x3b])?;
74
75        di.send_command_data(0x2b, &[0x03, 0x63])?; // reduce glitch under ACVCOM
76
77        di.send_command_data(0x0c, &[0x8b, 0x9c, 0x96, 0x0f])?; // soft start setting
78
79        di.send_command_data(0x01, &[0x2b, 0x01, 0x00])?; // Driver Output Control - set mux as 300
80
81        di.send_command_data(0x11, &[0b11])?; // data entry mode, X inc, Y inc
82
83        // 0x44, 0x45, ram x,y start,end
84        di.send_command_data(0x03, &[0x20])?; // Gate Driving Voltage Control
85
86        // A[7:0] = 41h [POR], VSH1 at 15V
87        // B[7:0] = A8h [POR], VSH2 at 5V.
88        // C[7:0] = 32h [POR], VSL at -15V
89        //di.send_command_data(0x04, &[0x4b, 0xce, 0x3a]); // Source Driving Voltage Control
90
91        //di.send_command_data(0x3A, &[0x21]); // dummy line, 0 to 127
92        //di.send_command_data(0x3B, &[0x06]); // gate width
93
94        // 0b10_00_00 , VCOM, black
95        // 0b11_00_00, HiZ
96        // 0b01_00_00, VSS
97        di.send_command_data(0x3C, &[0x01])?; // border wavefrom, HIZ
98
99        di.send_command_data(0x18, &[0x80])?;
100        // load temperature and waveform setting.
101        di.send_command_data(0x22, &[0xb9])?; // B1 or B9
102
103        di.send_command(0x20)?;
104        di.busy_wait();
105
106        Ok(())
107    }
108
109    fn set_shape<DI: DisplayInterface>(di: &mut DI, x: u16, y: u16) -> Result<(), Self::Error> {
110        // Set RAM X - address Start / End position
111        di.send_command_data(0x44, &[0x00, ((x - 1) >> 3) as u8])?;
112
113        // Set RAM Y - address Start / End position
114        di.send_command_data(
115            0x45,
116            &[0x00, 0x00, ((y - 1) & 0xff) as u8, ((y - 1) >> 8) as u8],
117        )?;
118        di.send_command_data(0x4e, &[0])?; // x start
119        di.send_command_data(0x4f, &[0, 0])?; // y start
120
121        Ok(())
122    }
123
124    fn update_frame<'a, DI: DisplayInterface, I>(di: &mut DI, buffer: I) -> Result<(), Self::Error>
125    where
126        I: IntoIterator<Item = &'a u8>,
127    {
128        di.send_command_data(0x4e, &[0])?; // x start
129        di.send_command_data(0x4f, &[0, 0])?; // y start
130
131        di.send_command(0x24)?;
132        di.send_data_from_iter(buffer)?;
133
134        Ok(())
135    }
136
137    fn turn_on_display<DI: DisplayInterface>(di: &mut DI) -> Result<(), Self::Error> {
138        di.send_command_data(0x22, &[0xf7])?; // Display Update Control 2
139        di.send_command(0x20)?; // master activation
140        di.busy_wait();
141        Ok(())
142    }
143}
144
145impl MultiColorDriver for SSD1619A {
146    fn update_channel_frame<'a, DI: DisplayInterface, I>(
147        di: &mut DI,
148        channel: u8,
149        buffer: I,
150    ) -> Result<(), Self::Error>
151    where
152        I: IntoIterator<Item = &'a u8>,
153    {
154        di.send_command_data(0x4e, &[0])?; // x start
155        di.send_command_data(0x4f, &[0, 0])?; // y start
156
157        if channel == 0 {
158            di.send_command(0x24)?;
159            di.send_data_from_iter(buffer)?;
160        } else if channel == 1 {
161            di.send_command(0x26)?;
162            di.send_data_from_iter(buffer)?;
163        } else {
164            // error
165        }
166
167        Ok(())
168    }
169}