1use crate::color::Color;
21use crate::driver::ssd1680::{Cmd, Flag};
22use crate::driver::EpdDriver;
23use crate::interface::SpiDisplayInterface;
24use display_interface::DisplayError;
25use embedded_hal::delay::DelayNs;
26use embedded_hal::digital::{InputPin, OutputPin};
27use embedded_hal::spi::SpiDevice;
28use log::debug;
29
30pub use crate::graphics::display290_gray4_mfgn::Display2in9Gray2;
31pub use crate::graphics::display290_mono::Display2in9Mono;
32
33pub const WIDTH: u16 = 128;
35pub const HEIGHT: u16 = 296;
37
38#[rustfmt::skip]
39pub const TI_290_MONOFULL_LUT_CODE: [u8; 153] = [
41 0x80, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x80, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x0A, 0x00, 0x0A, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00 ];
60
61#[rustfmt::skip]
62pub const TI_290MFGN_GRAY2_LUT_CODE: [u8; 153] = [
64 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x60, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x14, 0x00, 0x00, 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x05, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x22, 0x22, 0x22, 0x23, 0x32, 0x00, 0x00, 0x00, ];
83
84pub struct ThinkInk2in9Mono<SPI, BSY, DC, RST>
91where
92 SPI: SpiDevice,
93 BSY: InputPin,
94 DC: OutputPin,
95 RST: OutputPin,
96{
97 interface: SpiDisplayInterface<SPI, BSY, DC, RST>,
98}
99
100impl<SPI, BSY, DC, RST> ThinkInk2in9Mono<SPI, BSY, DC, RST>
101where
102 SPI: SpiDevice,
103 BSY: InputPin,
104 DC: OutputPin,
105 RST: OutputPin,
106{
107 pub fn new(spi: SPI, busy: BSY, dc: DC, rst: RST) -> Result<Self, DisplayError> {
109 let interface = SpiDisplayInterface::new(spi, busy, dc, rst);
110 Ok(Self { interface })
111 }
112
113 fn write_bw_ram(&mut self, buffer: &[u8]) -> Result<(), DisplayError> {
115 self.set_ram_counter(0, 0)?;
116 self.interface.cmd_with_data(Cmd::WRITE_BW_DATA, buffer)
117 }
118
119 fn write_red_ram(&mut self, buffer: &[u8]) -> Result<(), DisplayError> {
121 self.set_ram_counter(0, 0)?;
122 self.interface.cmd_with_data(Cmd::WRITE_RED_DATA, buffer)
123 }
124
125 fn display(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
126 self.interface
127 .cmd_with_data(Cmd::DISPLAY_UPDATE_CTRL2, &[Flag::DISPLAY_MODE_1])?;
128 self.interface.cmd(Cmd::MASTER_ACTIVATE)?;
129 self.interface.wait_until_idle(delay);
130 Ok(())
131 }
132
133 pub fn clear_display(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
137 self.clear_bw_ram()?;
138 self.clear_red_ram()?;
139 self.display(delay)?;
140 delay.delay_ms(100);
141 self.display(delay)
142 }
143
144 pub fn update_and_display(
149 &mut self,
150 bw_buffer: &[u8],
151 delay: &mut impl DelayNs,
152 ) -> Result<(), DisplayError> {
153 self.init(delay)?;
154 self.update_bw(bw_buffer, delay)?;
155 self.display(delay)?;
156 self.sleep(delay)
157 }
158
159 pub fn update_gray2_and_display(
168 &mut self,
169 bw_buffer: &[u8],
170 red_buffer: &[u8],
171 delay: &mut impl DelayNs,
172 ) -> Result<(), DisplayError> {
173 self.init(delay)?;
174 self.update_bw(bw_buffer, delay)?;
175 self.update_red(red_buffer, delay)?;
176 self.display(delay)?;
177 self.sleep(delay)
178 }
179
180 fn set_ram_counter(&mut self, x: u32, y: u32) -> Result<(), DisplayError> {
181 self.interface
182 .cmd_with_data(Cmd::SET_RAMX_COUNTER, &[(x >> 3) as u8])?;
183
184 self.interface.cmd_with_data(
185 Cmd::SET_RAMY_COUNTER,
186 &[(y & 0xFF) as u8, ((y >> 8) & 0x01) as u8],
187 )?;
188 Ok(())
189 }
190}
191
192impl<SPI, BSY, DC, RST> EpdDriver for ThinkInk2in9Mono<SPI, BSY, DC, RST>
193where
194 SPI: SpiDevice,
195 BSY: InputPin,
196 DC: OutputPin,
197 RST: OutputPin,
198{
199 fn init(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
205 debug!("powering up ThinkInk 2.9in mono display");
206 self.interface.hard_reset(delay)?;
208 self.interface.cmd(Cmd::SW_RESET)?;
210 delay.delay_ms(10);
211 self.interface
213 .cmd_with_data(Cmd::DRIVER_OUTPUT_CTRL, &[0x27, 0x01, 0x00])?;
214 self.interface
215 .cmd_with_data(Cmd::DATA_ENTRY_MODE, &[Flag::DATA_ENTRY_INCRY_INCRX])?;
216 self.interface
217 .cmd_with_data(Cmd::SET_RAMXPOS, &[0x00, 0x0F])?;
218 self.interface
219 .cmd_with_data(Cmd::SET_RAMYPOS, &[0x00, 0x00, 0x27, 0x01])?;
220 self.interface.cmd_with_data(
221 Cmd::BORDER_WAVEFORM_CTRL,
222 &[Flag::BORDER_WAVEFORM_FOLLOW_LUT | Flag::BORDER_WAVEFORM_LUT1],
223 )?;
224 self.interface
226 .cmd_with_data(Cmd::TEMP_CONTROL, &[Flag::INTERNAL_TEMP_SENSOR])?;
227 self.interface
228 .cmd_with_data(Cmd::DISPLAY_UPDATE_CTRL1, &[0x00, 0x80])?;
229 self.interface
230 .cmd_with_data(Cmd::END_OPTION, &[Flag::END_OPTION_NORMAL])?;
231 self.interface
232 .cmd_with_data(Cmd::GATE_VOLTAGE_CTRL, &[0x17])?;
233 self.interface
234 .cmd_with_data(Cmd::SOURCE_VOLTAGE_CTRL, &[0x41, 0x00, 0x32])?;
235 self.interface.cmd_with_data(Cmd::WRITE_VCOM_REG, &[0x36])?;
236 self.interface
238 .cmd_with_data(Cmd::WRITE_LUT_REG, &TI_290_MONOFULL_LUT_CODE)?;
239 self.interface.wait_until_idle(delay);
240 Ok(())
241 }
242
243 fn sleep(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
245 debug!("powering down ThinkInk 2.9\" display");
246 self.interface.cmd_with_data(Cmd::DEEP_SLEEP, &[0x01])?;
247 delay.delay_ms(1);
248 Ok(())
249 }
250
251 fn update_bw(&mut self, buffer: &[u8], delay: &mut impl DelayNs) -> Result<(), DisplayError> {
253 self.write_bw_ram(buffer)?;
254 self.interface.wait_until_idle(delay);
255 Ok(())
256 }
257
258 fn update_red(&mut self, buffer: &[u8], delay: &mut impl DelayNs) -> Result<(), DisplayError> {
260 self.write_red_ram(buffer)?;
261 self.interface.wait_until_idle(delay);
262 Ok(())
263 }
264
265 fn update(
270 &mut self,
271 low_buffer: &[u8],
272 high_buffer: &[u8],
273 delay: &mut impl DelayNs,
274 ) -> Result<(), DisplayError> {
275 self.write_bw_ram(low_buffer)?;
276 self.write_red_ram(high_buffer)?;
277 self.interface.wait_until_idle(delay);
278 Ok(())
279 }
280
281 fn clear_bw_ram(&mut self) -> Result<(), DisplayError> {
283 let color = Color::White.get_byte_value();
284 self.interface.cmd(Cmd::WRITE_BW_DATA)?;
285 self.interface
286 .data_x_times(color, u32::from(WIDTH).div_ceil(8) * u32::from(HEIGHT))?;
287 Ok(())
288 }
289
290 fn clear_red_ram(&mut self) -> Result<(), DisplayError> {
292 let color = Color::White.inverse().get_byte_value();
293 self.interface.cmd(Cmd::WRITE_RED_DATA)?;
294 self.interface
295 .data_x_times(color, u32::from(WIDTH).div_ceil(8) * u32::from(HEIGHT))?;
296 Ok(())
297 }
298
299 fn begin(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
303 self.interface.hard_reset(delay)?;
304 self.sleep(delay)
305 }
306}
307
308pub struct ThinkInk2in9Gray2<SPI, BSY, DC, RST>
315where
316 SPI: SpiDevice,
317 BSY: InputPin,
318 DC: OutputPin,
319 RST: OutputPin,
320{
321 interface: SpiDisplayInterface<SPI, BSY, DC, RST>,
322}
323
324impl<SPI, BSY, DC, RST> ThinkInk2in9Gray2<SPI, BSY, DC, RST>
325where
326 SPI: SpiDevice,
327 BSY: InputPin,
328 DC: OutputPin,
329 RST: OutputPin,
330{
331 pub fn new(spi: SPI, busy: BSY, dc: DC, rst: RST) -> Result<Self, DisplayError> {
333 let interface = SpiDisplayInterface::new(spi, busy, dc, rst);
334 Ok(Self { interface })
335 }
336
337 fn write_bw_ram(&mut self, buffer: &[u8]) -> Result<(), DisplayError> {
339 self.set_ram_counter(0, 0)?;
340 self.interface.cmd_with_data(Cmd::WRITE_BW_DATA, buffer)
341 }
342
343 fn write_red_ram(&mut self, buffer: &[u8]) -> Result<(), DisplayError> {
345 self.set_ram_counter(0, 0)?;
346 self.interface.cmd_with_data(Cmd::WRITE_RED_DATA, buffer)
347 }
348
349 fn display(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
350 self.interface
351 .cmd_with_data(Cmd::DISPLAY_UPDATE_CTRL2, &[Flag::DISPLAY_MODE_1])?;
352 self.interface.cmd(Cmd::MASTER_ACTIVATE)?;
353 self.interface.wait_until_idle(delay);
354 Ok(())
355 }
356
357 pub fn clear_display(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
361 self.clear_bw_ram()?;
362 self.clear_red_ram()?;
363 self.display(delay)?;
364 delay.delay_ms(100);
365 self.display(delay)
366 }
367
368 pub fn update_and_display(
373 &mut self,
374 bw_buffer: &[u8],
375 delay: &mut impl DelayNs,
376 ) -> Result<(), DisplayError> {
377 self.init(delay)?;
378 self.update_bw(bw_buffer, delay)?;
379 self.display(delay)?;
380 self.sleep(delay)
381 }
382
383 pub fn update_gray2_and_display(
392 &mut self,
393 high_buffer: &[u8],
394 low_buffer: &[u8],
395 delay: &mut impl DelayNs,
396 ) -> Result<(), DisplayError> {
397 self.init(delay)?;
398 self.update_bw(high_buffer, delay)?;
399 self.update_red(low_buffer, delay)?;
400 self.display(delay)?;
401 self.sleep(delay)
402 }
403
404 fn set_ram_counter(&mut self, x: u32, y: u32) -> Result<(), DisplayError> {
405 self.interface
406 .cmd_with_data(Cmd::SET_RAMX_COUNTER, &[(x >> 3) as u8])?;
407
408 self.interface.cmd_with_data(
409 Cmd::SET_RAMY_COUNTER,
410 &[(y & 0xFF) as u8, ((y >> 8) & 0x01) as u8],
411 )?;
412 Ok(())
413 }
414}
415
416impl<SPI, BSY, DC, RST> EpdDriver for ThinkInk2in9Gray2<SPI, BSY, DC, RST>
417where
418 SPI: SpiDevice,
419 BSY: InputPin,
420 DC: OutputPin,
421 RST: OutputPin,
422{
423 fn init(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
429 debug!("powering up ThinkInk 2.9in grayscale display");
430 self.interface.hard_reset(delay)?;
432 self.interface.cmd(Cmd::SW_RESET)?;
433 delay.delay_ms(10);
434 self.interface
436 .cmd_with_data(Cmd::DRIVER_OUTPUT_CTRL, &[0x27, 0x01, 0x00])?;
437 self.interface
438 .cmd_with_data(Cmd::DATA_ENTRY_MODE, &[Flag::DATA_ENTRY_INCRY_INCRX])?;
439 self.interface
440 .cmd_with_data(Cmd::SET_RAMXPOS, &[0x00, 0x0F])?;
441 self.interface
442 .cmd_with_data(Cmd::SET_RAMYPOS, &[0x00, 0x00, 0x27, 0x01])?;
443 self.interface.cmd_with_data(
444 Cmd::BORDER_WAVEFORM_CTRL,
445 &[Flag::BORDER_WAVEFORM_FOLLOW_LUT | Flag::BORDER_WAVEFORM_LUT1],
446 )?;
447 self.interface
449 .cmd_with_data(Cmd::TEMP_CONTROL, &[Flag::INTERNAL_TEMP_SENSOR])?;
450 self.interface
451 .cmd_with_data(Cmd::DISPLAY_UPDATE_CTRL1, &[0x00, 0x80])?;
452 self.interface
453 .cmd_with_data(Cmd::END_OPTION, &[Flag::END_OPTION_NORMAL])?;
454 self.interface
455 .cmd_with_data(Cmd::GATE_VOLTAGE_CTRL, &[0x17])?;
456 self.interface
457 .cmd_with_data(Cmd::SOURCE_VOLTAGE_CTRL, &[0x41, 0x00, 0x32])?;
458 self.interface.cmd_with_data(Cmd::WRITE_VCOM_REG, &[0x36])?;
459 self.interface
461 .cmd_with_data(Cmd::WRITE_LUT_REG, &TI_290MFGN_GRAY2_LUT_CODE)?;
462 self.interface.wait_until_idle(delay);
463 Ok(())
464 }
465
466 fn sleep(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
468 debug!("powering down ThinkInk 2.9\" grayscale display");
469 self.interface.cmd_with_data(Cmd::DEEP_SLEEP, &[0x01])?;
470 delay.delay_ms(1);
471 Ok(())
472 }
473
474 fn update_bw(&mut self, buffer: &[u8], delay: &mut impl DelayNs) -> Result<(), DisplayError> {
476 self.write_bw_ram(buffer)?;
477 self.interface.wait_until_idle(delay);
478 Ok(())
479 }
480
481 fn update_red(&mut self, buffer: &[u8], delay: &mut impl DelayNs) -> Result<(), DisplayError> {
483 self.write_red_ram(buffer)?;
484 self.interface.wait_until_idle(delay);
485 Ok(())
486 }
487
488 fn update(
493 &mut self,
494 bw_buffer: &[u8],
495 red_buffer: &[u8],
496 delay: &mut impl DelayNs,
497 ) -> Result<(), DisplayError> {
498 self.write_bw_ram(bw_buffer)?;
499 self.write_red_ram(red_buffer)?;
500 self.interface.wait_until_idle(delay);
501 Ok(())
502 }
503
504 fn clear_bw_ram(&mut self) -> Result<(), DisplayError> {
506 let color = Color::White.get_byte_value();
507 self.interface.cmd(Cmd::WRITE_BW_DATA)?;
508 self.interface
509 .data_x_times(color, u32::from(WIDTH).div_ceil(8) * u32::from(HEIGHT))?;
510 Ok(())
511 }
512
513 fn clear_red_ram(&mut self) -> Result<(), DisplayError> {
515 let color = Color::White.inverse().get_byte_value();
516 self.interface.cmd(Cmd::WRITE_RED_DATA)?;
517 self.interface
518 .data_x_times(color, u32::from(WIDTH).div_ceil(8) * u32::from(HEIGHT))?;
519 Ok(())
520 }
521
522 fn begin(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
526 self.interface.hard_reset(delay)?;
527 self.sleep(delay)
528 }
529}