1use crate::color::Color;
21use crate::driver::il0373::Il0373Cmd;
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_t5::Display2in9Gray2;
31pub use crate::graphics::display290_mono::Display2in9Mono;
32
33pub const WIDTH: u16 = 296;
35pub const HEIGHT: u16 = 128;
37
38#[rustfmt::skip]
44const TI_290T5_GRAY4_LUT1: [u8; 42] = [
49 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01,
50 0x60, 0x14, 0x14, 0x00, 0x00, 0x01,
51 0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
52 0x00, 0x13, 0x0A, 0x01, 0x00, 0x01,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56];
57
58#[rustfmt::skip]
59const TI_290T5_GRAY4_LUTWW: [u8; 42] = [
64 0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
65 0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
66 0x10, 0x14, 0x0A, 0x00, 0x00, 0x01,
67 0xA0, 0x13, 0x01, 0x00, 0x00, 0x01,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71];
72
73#[rustfmt::skip]
74const TI_290T5_GRAY4_LUTBW: [u8; 42] = [
79 0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
80 0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
81 0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,
82 0x99, 0x0C, 0x01, 0x03, 0x04, 0x01,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86];
87
88#[rustfmt::skip]
89const TI_290T5_GRAY4_LUTWB: [u8; 42] = [
94 0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
95 0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
96 0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,
97 0x99, 0x0B, 0x04, 0x04, 0x01, 0x01,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101];
102
103#[rustfmt::skip]
104const TI_290T5_GRAY4_LUTBB: [u8; 42] = [
109 0x80, 0x0A, 0x00, 0x00, 0x00, 0x01,
110 0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
111 0x20, 0x14, 0x0A, 0x00, 0x00, 0x01,
112 0x50, 0x13, 0x01, 0x00, 0x00, 0x01,
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116];
117
118pub struct ThinkInk2in9Mono<SPI, BSY, DC, RST>
125where
126 SPI: SpiDevice,
127 BSY: InputPin,
128 DC: OutputPin,
129 RST: OutputPin,
130{
131 interface: SpiDisplayInterface<SPI, BSY, DC, RST>,
132}
133
134impl<SPI, BSY, DC, RST> ThinkInk2in9Mono<SPI, BSY, DC, RST>
135where
136 SPI: SpiDevice,
137 BSY: InputPin,
138 DC: OutputPin,
139 RST: OutputPin,
140{
141 pub fn new(spi: SPI, busy: BSY, dc: DC, rst: RST) -> Result<Self, DisplayError> {
143 let interface = SpiDisplayInterface::new(spi, busy, dc, rst);
144 Ok(Self { interface })
145 }
146
147 fn write_dtm1(&mut self, buffer: &[u8]) -> Result<(), DisplayError> {
148 self.interface.cmd_with_data(Il0373Cmd::DTM1, buffer)
149 }
150
151 fn display(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
152 self.interface.cmd(Il0373Cmd::DISPLAY_REFRESH)?;
153 delay.delay_ms(100);
154 self.interface.wait_until_idle_active_low(delay);
155 Ok(())
156 }
157
158 pub fn update_and_display(
163 &mut self,
164 bw_buffer: &[u8],
165 delay: &mut impl DelayNs,
166 ) -> Result<(), DisplayError> {
167 self.init(delay)?;
168 self.update_bw(bw_buffer, delay)?;
169 self.display(delay)?;
170 self.sleep(delay)
171 }
172}
173
174impl<SPI, BSY, DC, RST> EpdDriver for ThinkInk2in9Mono<SPI, BSY, DC, RST>
175where
176 SPI: SpiDevice,
177 BSY: InputPin,
178 DC: OutputPin,
179 RST: OutputPin,
180{
181 fn init(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
186 debug!("powering up MagTag 2.9\" IL0373 mono display");
187
188 self.interface.hard_reset(delay)?;
189
190 self.interface
191 .cmd_with_data(Il0373Cmd::BOOSTER_SOFT_START, &[0x17, 0x17, 0x17])?;
192
193 self.interface.cmd(Il0373Cmd::POWER_ON)?;
194 self.interface.wait_until_idle_active_low(delay);
195 delay.delay_ms(200);
196
197 self.interface
200 .cmd_with_data(Il0373Cmd::PANEL_SETTING, &[0x1f, 0x0d])?;
201
202 self.interface.cmd_with_data(Il0373Cmd::CDI, &[0x97])?;
203
204 Ok(())
205 }
206
207 fn sleep(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
209 debug!("powering down MagTag 2.9\" IL0373 mono display");
210 self.interface.cmd_with_data(Il0373Cmd::CDI, &[0x17])?;
211 self.interface.cmd(Il0373Cmd::VCM_DC_SETTING)?;
212 self.interface.cmd(Il0373Cmd::POWER_OFF)?;
213 delay.delay_ms(1);
214 Ok(())
215 }
216
217 fn update_bw(&mut self, buffer: &[u8], delay: &mut impl DelayNs) -> Result<(), DisplayError> {
219 self.write_dtm1(buffer)?;
220 self.interface.wait_until_idle_active_low(delay);
221 Ok(())
222 }
223
224 fn update_red(&mut self, _buffer: &[u8], _delay: &mut impl DelayNs) -> Result<(), DisplayError> {
226 Ok(())
227 }
228
229 fn update(
231 &mut self,
232 bw_buffer: &[u8],
233 _red_buffer: &[u8],
234 delay: &mut impl DelayNs,
235 ) -> Result<(), DisplayError> {
236 self.write_dtm1(bw_buffer)?;
237 self.interface.wait_until_idle_active_low(delay);
238 Ok(())
239 }
240
241 fn clear_bw_ram(&mut self) -> Result<(), DisplayError> {
243 let color = Color::White.get_byte_value();
244 self.interface.cmd(Il0373Cmd::DTM1)?;
245 self.interface
246 .data_x_times(color, u32::from(HEIGHT).div_ceil(8) * u32::from(WIDTH))?;
247 Ok(())
248 }
249
250 fn clear_red_ram(&mut self) -> Result<(), DisplayError> {
252 Ok(())
253 }
254
255 fn begin(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
257 self.interface.hard_reset(delay)?;
258 self.sleep(delay)
259 }
260}
261
262pub struct ThinkInk2in9Gray2<SPI, BSY, DC, RST>
271where
272 SPI: SpiDevice,
273 BSY: InputPin,
274 DC: OutputPin,
275 RST: OutputPin,
276{
277 interface: SpiDisplayInterface<SPI, BSY, DC, RST>,
278}
279
280impl<SPI, BSY, DC, RST> ThinkInk2in9Gray2<SPI, BSY, DC, RST>
281where
282 SPI: SpiDevice,
283 BSY: InputPin,
284 DC: OutputPin,
285 RST: OutputPin,
286{
287 pub fn new(spi: SPI, busy: BSY, dc: DC, rst: RST) -> Result<Self, DisplayError> {
289 let interface = SpiDisplayInterface::new(spi, busy, dc, rst);
290 Ok(Self { interface })
291 }
292
293 fn write_dtm1(&mut self, buffer: &[u8]) -> Result<(), DisplayError> {
295 self.interface.cmd_with_data(Il0373Cmd::DTM1, buffer)
296 }
297
298 fn write_dtm2(&mut self, buffer: &[u8]) -> Result<(), DisplayError> {
300 self.interface.cmd_with_data(Il0373Cmd::DTM2, buffer)
301 }
302
303 fn display(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
308 self.interface.cmd(Il0373Cmd::DISPLAY_REFRESH)?;
309 delay.delay_ms(100);
310 self.interface.wait_until_idle_active_low(delay);
311 Ok(())
312 }
313
314 pub fn update_gray2_and_display(
323 &mut self,
324 high_buffer: &[u8],
325 low_buffer: &[u8],
326 delay: &mut impl DelayNs,
327 ) -> Result<(), DisplayError> {
328 self.init(delay)?;
329 self.update_bw(high_buffer, delay)?;
330 self.update_red(low_buffer, delay)?;
331 self.display(delay)?;
332 self.sleep(delay)
333 }
334}
335
336impl<SPI, BSY, DC, RST> EpdDriver for ThinkInk2in9Gray2<SPI, BSY, DC, RST>
337where
338 SPI: SpiDevice,
339 BSY: InputPin,
340 DC: OutputPin,
341 RST: OutputPin,
342{
343 fn init(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
349 debug!("powering up MagTag 2.9\" IL0373 grayscale display");
350
351 self.interface.hard_reset(delay)?;
353
354 self.interface
356 .cmd_with_data(Il0373Cmd::POWER_SETTING, &[0x03, 0x00, 0x2b, 0x2b, 0x13])?;
357
358 self.interface
360 .cmd_with_data(Il0373Cmd::BOOSTER_SOFT_START, &[0x17, 0x17, 0x17])?;
361
362 self.interface.cmd(Il0373Cmd::POWER_ON)?;
364 self.interface.wait_until_idle_active_low(delay);
365 delay.delay_ms(200);
366
367 self.interface
369 .cmd_with_data(Il0373Cmd::PANEL_SETTING, &[0x3F])?;
370
371 self.interface.cmd_with_data(Il0373Cmd::PLL, &[0x3C])?;
373
374 self.interface
376 .cmd_with_data(Il0373Cmd::VCM_DC_SETTING, &[0x12])?;
377
378 self.interface.cmd_with_data(Il0373Cmd::CDI, &[0x97])?;
380
381 self.interface
383 .cmd_with_data(Il0373Cmd::LUT1, &TI_290T5_GRAY4_LUT1)?;
384 self.interface
385 .cmd_with_data(Il0373Cmd::LUTWW, &TI_290T5_GRAY4_LUTWW)?;
386 self.interface
387 .cmd_with_data(Il0373Cmd::LUTBW, &TI_290T5_GRAY4_LUTBW)?;
388 self.interface
389 .cmd_with_data(Il0373Cmd::LUTWB, &TI_290T5_GRAY4_LUTWB)?;
390 self.interface
391 .cmd_with_data(Il0373Cmd::LUTBB, &TI_290T5_GRAY4_LUTBB)?;
392
393 self.interface.cmd_with_data(
398 Il0373Cmd::RESOLUTION,
399 &[
400 (HEIGHT & 0xFF) as u8, ((WIDTH >> 8) & 0xFF) as u8, (HEIGHT & 0xFF) as u8, ],
404 )?;
405
406 Ok(())
407 }
408
409 fn sleep(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
414 debug!("powering down MagTag 2.9\" IL0373 grayscale display");
415
416 self.interface.cmd_with_data(Il0373Cmd::CDI, &[0x17])?;
418
419 self.interface.cmd(Il0373Cmd::VCM_DC_SETTING)?;
421
422 self.interface.cmd(Il0373Cmd::POWER_OFF)?;
424 delay.delay_ms(1);
425 Ok(())
426 }
427
428 fn update_bw(&mut self, buffer: &[u8], delay: &mut impl DelayNs) -> Result<(), DisplayError> {
430 self.write_dtm1(buffer)?;
431 self.interface.wait_until_idle_active_low(delay);
432 Ok(())
433 }
434
435 fn update_red(&mut self, buffer: &[u8], delay: &mut impl DelayNs) -> Result<(), DisplayError> {
437 self.write_dtm2(buffer)?;
438 self.interface.wait_until_idle_active_low(delay);
439 Ok(())
440 }
441
442 fn update(
448 &mut self,
449 bw_buffer: &[u8],
450 red_buffer: &[u8],
451 delay: &mut impl DelayNs,
452 ) -> Result<(), DisplayError> {
453 self.write_dtm1(bw_buffer)?;
454 self.write_dtm2(red_buffer)?;
455 self.interface.wait_until_idle_active_low(delay);
456 Ok(())
457 }
458
459 fn clear_bw_ram(&mut self) -> Result<(), DisplayError> {
461 let color = Color::White.get_byte_value();
462 self.interface.cmd(Il0373Cmd::DTM1)?;
463 self.interface
464 .data_x_times(color, u32::from(HEIGHT).div_ceil(8) * u32::from(WIDTH))?;
465 Ok(())
466 }
467
468 fn clear_red_ram(&mut self) -> Result<(), DisplayError> {
470 let color = Color::White.inverse().get_byte_value();
471 self.interface.cmd(Il0373Cmd::DTM2)?;
472 self.interface
473 .data_x_times(color, u32::from(HEIGHT).div_ceil(8) * u32::from(WIDTH))?;
474 Ok(())
475 }
476
477 fn begin(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
482 self.interface.hard_reset(delay)?;
483 self.sleep(delay)
484 }
485}