1use crate::interface::DisplayInterface;
2
3#[derive(Clone, Copy)]
5pub enum DisplayResolution {
6 R96x230,
7 R96x252,
8 R128x296,
9 R160x296,
10}
11
12#[derive(Clone, Copy)]
14pub enum DataPolarity {
15 BWOnly,
16 RedOnly,
17 Both,
18}
19
20#[derive(Clone, Copy)]
22pub enum DataInterval {
23 V2,
24 V3,
25 V4,
26 V5,
27 V6,
28 V7,
29 V8,
30 V9,
31 V10,
32 V11,
33 V12,
34 V13,
35 V14,
36 V15,
37 V16,
38 V17,
39}
40
41#[derive(Clone, Copy)]
43pub enum Command {
44 PanelSetting(DisplayResolution),
46 PowerSetting(u8, u8, u8),
48 PowerOff,
50 PowerOn,
53 BoosterSoftStart(u8, u8, u8),
56 DeepSleep,
58 DataStop,
61 DisplayRefresh,
63 PLLControl(u8),
70 VCOMDataIntervalSetting(u8, DataPolarity, DataInterval),
76 ResolutionSetting(u8, u16),
80 VCMDCSetting(u8),
86 }
95
96pub enum BufCommand<'buf> {
100 WriteBlackData(&'buf [u8]),
104 WriteRedData(&'buf [u8]),
108}
109
110macro_rules! pack {
117 ($buf:ident, $cmd:expr,[]) => {
118 ($cmd, &$buf[..0])
119 };
120 ($buf:ident, $cmd:expr,[$arg0:expr]) => {{
121 $buf[0] = $arg0;
122 ($cmd, &$buf[..1])
123 }};
124 ($buf:ident, $cmd:expr,[$arg0:expr, $arg1:expr]) => {{
125 $buf[0] = $arg0;
126 $buf[1] = $arg1;
127 ($cmd, &$buf[..2])
128 }};
129 ($buf:ident, $cmd:expr,[$arg0:expr, $arg1:expr, $arg2:expr]) => {{
130 $buf[0] = $arg0;
131 $buf[1] = $arg1;
132 $buf[2] = $arg2;
133 ($cmd, &$buf[..3])
134 }};
135 ($buf:ident, $cmd:expr,[$arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr]) => {{
136 $buf[0] = $arg0;
137 $buf[1] = $arg1;
138 $buf[2] = $arg2;
139 $buf[3] = $arg3;
140 ($cmd, &$buf[..4])
141 }};
142 ($buf:ident, $cmd:expr,[$arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr]) => {{
143 $buf[0] = $arg0;
144 $buf[1] = $arg1;
145 $buf[2] = $arg2;
146 $buf[3] = $arg3;
147 $buf[4] = $arg4;
148 ($cmd, &$buf[..5])
149 }};
150}
151
152impl Command {
153 pub fn execute<I: DisplayInterface>(&self, interface: &mut I) -> Result<(), I::Error> {
155 use self::Command::*;
156
157 let mut buf = [0u8; 5];
158 let (command, data) = match *self {
159 PanelSetting(resolution) => {
160 let res = match resolution {
161 self::DisplayResolution::R96x230 => 0b0000_0000,
162 self::DisplayResolution::R96x252 => 0b0100_0000,
163 self::DisplayResolution::R128x296 => 0b1000_0000,
164 self::DisplayResolution::R160x296 => 0b1100_0000,
165 };
166 pack!(buf, 0x0, [res | 0b001111])
167 }
168 PowerSetting(vdh, vdl, vdhr) => {
169 debug_assert!(vdh < 64);
170 debug_assert!(vdl < 64);
171 debug_assert!(vdhr < 64);
172 pack!(buf, 0x1, [0x3, 0x0, vdh, vdl, vdhr])
173 }
174 PowerOff => {
175 pack!(buf, 0x3, [])
176 }
177 PowerOn => {
178 pack!(buf, 0x4, [])
179 }
180 BoosterSoftStart(phase_a, phase_b, phase_c) => {
181 pack!(buf, 0x6, [phase_a, phase_b, phase_c])
182 }
183 DeepSleep => {
184 pack!(buf, 0x8, [0xa5])
185 }
186 DataStop => {
187 pack!(buf, 0x11, [])
188 }
189 DisplayRefresh => {
190 pack!(buf, 0x12, [])
191 }
192 PLLControl(clock) => {
193 pack!(buf, 0x30, [clock])
194 }
195 VCOMDataIntervalSetting(border_data, data_polarity, interval) => {
196 debug_assert!(border_data < 4);
197 let vbd = border_data << 6;
198 let ddx = match data_polarity {
199 DataPolarity::BWOnly => 0b01_0000,
200 DataPolarity::RedOnly => 0b10_0000,
201 DataPolarity::Both => 0b11_0000,
202 };
203 let cdi = match interval {
204 DataInterval::V2 => 0b1111,
205 DataInterval::V3 => 0b1110,
206 DataInterval::V4 => 0b1101,
207 DataInterval::V5 => 0b1100,
208 DataInterval::V6 => 0b1011,
209 DataInterval::V7 => 0b1010,
210 DataInterval::V8 => 0b1001,
211 DataInterval::V9 => 0b1000,
212 DataInterval::V10 => 0b0111,
213 DataInterval::V11 => 0b0110,
214 DataInterval::V12 => 0b0101,
215 DataInterval::V13 => 0b0100,
216 DataInterval::V14 => 0b0011,
217 DataInterval::V15 => 0b0010,
218 DataInterval::V16 => 0b0001,
219 DataInterval::V17 => 0b0000,
220 };
221 pack!(buf, 0x50, [vbd | ddx | cdi])
222 }
223 ResolutionSetting(horiz, vertical) => {
224 let vres_hi = ((vertical & 0x100) >> 8) as u8;
225 let vres_lo = (vertical & 0xFF) as u8;
226 pack!(buf, 0x61, [horiz, vres_hi, vres_lo])
227 }
228 VCMDCSetting(vcom_dc) => {
229 debug_assert!(vcom_dc <= 0b11_1010);
230 pack!(buf, 0x82, [vcom_dc])
231 }
232 };
233
234 interface.send_command(command)?;
235 if data.is_empty() {
236 Ok(())
237 } else {
238 interface.send_data(data)
239 }
240 }
241}
242
243impl<'buf> BufCommand<'buf> {
244 pub fn execute<I: DisplayInterface>(&self, interface: &mut I) -> Result<(), I::Error> {
246 use self::BufCommand::*;
247
248 let (command, data) = match self {
249 WriteBlackData(buffer) => (0x10, buffer),
250 WriteRedData(buffer) => (0x13, buffer),
251 };
252
253 interface.send_command(command)?;
254 if data.is_empty() {
255 Ok(())
256 } else {
257 interface.send_data(data)
258 }
259 }
260}
261
262#[cfg(test)]
263mod tests {
264 use super::*;
265
266 struct MockInterface {
267 data: [u8; 256],
268 offset: usize,
269 }
270
271 impl MockInterface {
272 fn new() -> Self {
273 MockInterface {
274 data: [0; 256],
275 offset: 0,
276 }
277 }
278
279 fn write(&mut self, byte: u8) {
280 self.data[self.offset] = byte;
281 self.offset += 1;
282 }
283
284 fn data(&self) -> &[u8] {
285 &self.data[0..self.offset]
286 }
287 }
288
289 impl DisplayInterface for MockInterface {
290 type Error = ();
291
292 fn send_command(&mut self, command: u8) -> Result<(), Self::Error> {
293 self.write(command);
294 Ok(())
295 }
296
297 fn send_data(&mut self, data: &[u8]) -> Result<(), Self::Error> {
298 for byte in data {
299 self.write(*byte)
300 }
301 Ok(())
302 }
303
304 fn reset<D: hal::blocking::delay::DelayMs<u8>>(&mut self, _delay: &mut D) {
305 self.data = [0; 256];
306 self.offset = 0;
307 }
308
309 fn busy_wait(&self) {
310 }
312
313 fn epd_update_data(
314 &mut self,
315 _layer: u8,
316 _nbytes: u16,
317 _buf: &[u8],
318 ) -> Result<(), Self::Error> {
319 Ok(())
320 }
321
322 #[cfg(feature = "sram")]
323 fn sram_read(&mut self, _address: u16, _data: &mut [u8]) -> Result<(), Self::Error> {
324 Ok(())
325 }
326
327 #[cfg(feature = "sram")]
328 fn sram_write(&mut self, _address: u16, _data: &[u8]) -> Result<(), Self::Error> {
329 Ok(())
330 }
331
332 #[cfg(feature = "sram")]
333 fn sram_clear(&mut self, _address: u16, _nbytes: u16, _val: u8) -> Result<(), Self::Error> {
334 Ok(())
335 }
336
337 #[cfg(feature = "sram")]
338 fn sram_epd_update_data(
339 &mut self,
340 _layer: u8,
341 _nbytes: u16,
342 _start_address: u16,
343 ) -> Result<(), Self::Error> {
344 Ok(())
345 }
346 }
347
348 #[test]
349 fn test_command_execute() {
350 let mut interface = MockInterface::new();
351 let b = 0xCF;
352 let command = Command::PanelSetting(DisplayResolution::R160x296);
353
354 command.execute(&mut interface).unwrap();
355 assert_eq!(interface.data(), &[0x00, b]);
356 }
357}