1use core::iter;
2
3#[cfg(not(feature = "blocking"))]
4use display_interface::AsyncWriteOnlyDataCommand;
5#[cfg(feature = "blocking")]
6use display_interface::WriteOnlyDataCommand;
7
8#[cfg(feature = "blocking")]
9use embedded_hal::delay::DelayNs;
10#[cfg(not(feature = "blocking"))]
11use embedded_hal_async::{delay::DelayNs, digital::Wait};
12
13use display_interface::DataFormat;
14use embedded_hal::digital::{InputPin, OutputPin};
15
16#[cfg(feature = "graphics")]
17use crate::graphics::Display;
18use crate::{
19 color::{self, ColorType},
20 command, flag, lut, Color, Result, TriColor,
21};
22
23pub type WeActStudio290BlackWhiteDriver<DI, BSY, RST, DELAY> =
25 DisplayDriver<DI, BSY, RST, DELAY, 128, 128, 296, Color>;
26pub type WeActStudio290TriColorDriver<DI, BSY, RST, DELAY> =
28 DisplayDriver<DI, BSY, RST, DELAY, 128, 128, 296, TriColor>;
29pub type WeActStudio213BlackWhiteDriver<DI, BSY, RST, DELAY> =
31 DisplayDriver<DI, BSY, RST, DELAY, 128, 122, 250, Color>;
32pub type WeActStudio213TriColorDriver<DI, BSY, RST, DELAY> =
34 DisplayDriver<DI, BSY, RST, DELAY, 128, 122, 250, TriColor>;
35
36pub struct DisplayDriver<
40 DI,
41 BSY,
42 RST,
43 DELAY,
44 const WIDTH: u32,
45 const VISIBLE_WIDTH: u32,
46 const HEIGHT: u32,
47 C,
48> {
49 _color: core::marker::PhantomData<C>,
50 interface: DI,
51 busy: BSY,
52 reset: RST,
53 delay: DELAY,
54 using_partial_mode: bool,
56 initial_full_refresh_done: bool,
57}
58
59#[maybe_async_cfg::maybe(
60 sync(
61 feature = "blocking",
62 keep_self,
63 idents(
64 AsyncWriteOnlyDataCommand(sync = "WriteOnlyDataCommand"),
65 Wait(sync = "InputPin")
66 )
67 ),
68 async(not(feature = "blocking"), keep_self)
69)]
70impl<DI, BSY, RST, DELAY, const WIDTH: u32, const VISIBLE_WIDTH: u32, const HEIGHT: u32, C>
71 DisplayDriver<DI, BSY, RST, DELAY, WIDTH, VISIBLE_WIDTH, HEIGHT, C>
72where
73 DI: AsyncWriteOnlyDataCommand,
74 BSY: InputPin + Wait,
75 RST: OutputPin,
76 DELAY: DelayNs,
77 C: ColorType,
78{
79 const RESET_DELAY_MS: u32 = 50;
80
81 pub fn new(interface: DI, busy: BSY, reset: RST, delay: DELAY) -> Self {
85 Self {
86 _color: core::marker::PhantomData,
87 interface,
88 busy,
89 reset,
90 delay,
91 using_partial_mode: false,
92 initial_full_refresh_done: false,
93 }
94 }
95
96 pub async fn init(&mut self) -> Result<()> {
98 self.hw_reset().await;
99 self.command(command::SW_RESET).await?;
100 self.delay.delay_ms(10).await;
101 self.wait_until_idle().await;
102 self.command_with_data(
103 command::DRIVER_CONTROL,
104 &[(HEIGHT - 1) as u8, ((HEIGHT - 1) >> 8) as u8, 0x00],
105 )
106 .await?;
107 self.command_with_data(command::DATA_ENTRY_MODE, &[flag::DATA_ENTRY_INCRY_INCRX])
108 .await?;
109 self.command_with_data(
110 command::BORDER_WAVEFORM_CONTROL,
111 &[flag::BORDER_WAVEFORM_FOLLOW_LUT | flag::BORDER_WAVEFORM_LUT1],
112 )
113 .await?;
114 self.command_with_data(command::DISPLAY_UPDATE_CONTROL, &[0x00, 0x80])
115 .await?;
116 self.command_with_data(command::TEMP_CONTROL, &[flag::INTERNAL_TEMP_SENSOR])
117 .await?;
118 self.use_full_frame().await?;
119 self.wait_until_idle().await;
120 Ok(())
121 }
122
123 pub async fn hw_reset(&mut self) {
125 self.reset.set_low().unwrap();
126 self.delay.delay_ms(Self::RESET_DELAY_MS).await;
127 self.reset.set_high().unwrap();
128 self.delay.delay_ms(Self::RESET_DELAY_MS).await;
129 }
130
131 pub async fn write_bw_buffer(&mut self, buffer: &[u8]) -> Result<()> {
133 self.use_full_frame().await?;
134 self.command_with_data(command::WRITE_BW_DATA, buffer)
135 .await?;
136 Ok(())
137 }
138
139 pub async fn write_red_buffer(&mut self, buffer: &[u8]) -> Result<()> {
143 self.use_full_frame().await?;
144 self.command_with_data(command::WRITE_RED_DATA, buffer)
145 .await?;
146 Ok(())
147 }
148
149 pub async fn write_partial_bw_buffer(
153 &mut self,
154 buffer: &[u8],
155 x: u32,
156 y: u32,
157 width: u32,
158 height: u32,
159 ) -> Result<()> {
160 self.use_partial_frame(x, y, width, height).await?;
161 self.command_with_data(command::WRITE_BW_DATA, buffer)
162 .await?;
163 Ok(())
164 }
165
166 pub async fn write_partial_red_buffer(
172 &mut self,
173 buffer: &[u8],
174 x: u32,
175 y: u32,
176 width: u32,
177 height: u32,
178 ) -> Result<()> {
179 self.use_partial_frame(x, y, width, height).await?;
180 self.command_with_data(command::WRITE_RED_DATA, buffer)
181 .await?;
182 Ok(())
183 }
184
185 pub async fn clear_bw_buffer(&mut self) -> Result<()> {
187 self.use_full_frame().await?;
188
189 let color = color::Color::White.byte_value().0;
191
192 self.command(command::WRITE_BW_DATA).await?;
193 self.data_x_times(color, WIDTH / 8 * HEIGHT).await?;
194 Ok(())
195 }
196
197 pub async fn clear_red_buffer(&mut self) -> Result<()> {
201 self.use_full_frame().await?;
202
203 let color = color::Color::White.byte_value().1;
205
206 self.command(command::WRITE_RED_DATA).await?;
207 self.data_x_times(color, WIDTH / 8 * HEIGHT).await?;
208 Ok(())
209 }
210
211 pub async fn full_refresh(&mut self) -> Result<()> {
213 self.initial_full_refresh_done = true;
214 self.using_partial_mode = false;
215
216 self.command_with_data(command::UPDATE_DISPLAY_CTRL2, &[flag::DISPLAY_MODE_1])
217 .await?;
218 self.command(command::MASTER_ACTIVATE).await?;
219 self.wait_until_idle().await;
220 Ok(())
221 }
222
223 pub async fn sleep(&mut self) -> Result<()> {
226 self.interface
230 .send_commands(DataFormat::U8(&[command::DEEP_SLEEP]))
231 .await?;
232 self.interface
233 .send_data(DataFormat::U8(&[flag::DEEP_SLEEP_MODE_1]))
234 .await?;
235 Ok(())
236 }
237
238 pub async fn wake_up(&mut self) -> Result<()> {
240 self.hw_reset().await;
242 Ok(())
243 }
244
245 async fn use_full_frame(&mut self) -> Result<()> {
246 self.use_partial_frame(0, 0, WIDTH, HEIGHT).await?;
247 Ok(())
248 }
249
250 async fn use_partial_frame(&mut self, x: u32, y: u32, width: u32, height: u32) -> Result<()> {
251 self.set_ram_area(x, y, x + width - 1, y + height - 1)
253 .await?;
254 self.set_ram_counter(x, y).await?;
255 Ok(())
256 }
257
258 async fn set_ram_area(
259 &mut self,
260 start_x: u32,
261 start_y: u32,
262 end_x: u32,
263 end_y: u32,
264 ) -> Result<()> {
265 assert!(start_x < end_x);
266 assert!(start_y < end_y);
267
268 self.command_with_data(
269 command::SET_RAMXPOS,
270 &[(start_x >> 3) as u8, (end_x >> 3) as u8],
271 )
272 .await?;
273
274 self.command_with_data(
275 command::SET_RAMYPOS,
276 &[
277 start_y as u8,
278 (start_y >> 8) as u8,
279 end_y as u8,
280 (end_y >> 8) as u8,
281 ],
282 )
283 .await?;
284 Ok(())
285 }
286
287 async fn set_ram_counter(&mut self, x: u32, y: u32) -> Result<()> {
288 self.command_with_data(command::SET_RAMX_COUNTER, &[(x >> 3) as u8])
291 .await?;
292
293 self.command_with_data(command::SET_RAMY_COUNTER, &[y as u8, (y >> 8) as u8])
295 .await?;
296 Ok(())
297 }
298
299 async fn command(&mut self, command: u8) -> Result<()> {
301 self.interface
302 .send_commands(DataFormat::U8(&[command]))
303 .await?;
304 Ok(())
305 }
306
307 async fn data(&mut self, data: &[u8]) -> Result<()> {
309 self.interface.send_data(DataFormat::U8(data)).await?;
310 self.wait_until_idle().await;
311 Ok(())
312 }
313
314 async fn wait_until_idle(&mut self) {
316 #[cfg(feature = "blocking")]
317 while self.busy.is_high().unwrap_or(true) {
318 self.delay.delay_ms(1)
319 }
320
321 #[cfg(not(feature = "blocking"))]
322 let _ = self.busy.wait_for_low().await;
323 }
324
325 async fn command_with_data(&mut self, command: u8, data: &[u8]) -> Result<()> {
327 self.command(command).await?;
328 self.data(data).await?;
329 Ok(())
330 }
331
332 async fn data_x_times(&mut self, data: u8, repetitions: u32) -> Result<()> {
334 let mut iter = iter::repeat(data).take(repetitions as usize);
335 self.interface
336 .send_data(DataFormat::U8Iter(&mut iter))
337 .await?;
338 Ok(())
339 }
340}
341
342#[maybe_async_cfg::maybe(
344 sync(
345 feature = "blocking",
346 keep_self,
347 idents(
348 AsyncWriteOnlyDataCommand(sync = "WriteOnlyDataCommand"),
349 Wait(sync = "InputPin")
350 )
351 ),
352 async(not(feature = "blocking"), keep_self)
353)]
354impl<DI, BSY, RST, DELAY, const WIDTH: u32, const VISIBLE_WIDTH: u32, const HEIGHT: u32>
355 DisplayDriver<DI, BSY, RST, DELAY, WIDTH, VISIBLE_WIDTH, HEIGHT, Color>
356where
357 DI: AsyncWriteOnlyDataCommand,
358 BSY: InputPin + Wait,
359 RST: OutputPin,
360 DELAY: DelayNs,
361{
362 pub async fn fast_refresh(&mut self) -> Result<()> {
366 if !self.initial_full_refresh_done {
367 self.full_refresh().await?;
370 }
371
372 if !self.using_partial_mode {
373 self.command_with_data(command::WRITE_LUT, &lut::LUT_PARTIAL_UPDATE)
374 .await?;
375 self.using_partial_mode = true;
376 }
377 self.command_with_data(command::UPDATE_DISPLAY_CTRL2, &[flag::UNDOCUMENTED])
378 .await?;
379 self.command(command::MASTER_ACTIVATE).await?;
380 self.wait_until_idle().await;
381 Ok(())
382 }
383
384 pub async fn full_update_from_buffer(&mut self, buffer: &[u8]) -> Result<()> {
386 self.write_red_buffer(buffer).await?;
387 self.write_bw_buffer(buffer).await?;
388 self.full_refresh().await?;
389 self.write_red_buffer(buffer).await?;
390 self.write_bw_buffer(buffer).await?;
391 Ok(())
392 }
393
394 pub async fn fast_update_from_buffer(&mut self, buffer: &[u8]) -> Result<()> {
396 self.write_bw_buffer(buffer).await?;
397 self.fast_refresh().await?;
398 self.write_red_buffer(buffer).await?;
399 self.write_bw_buffer(buffer).await?;
400 Ok(())
401 }
402
403 pub async fn fast_partial_update_from_buffer(
407 &mut self,
408 buffer: &[u8],
409 x: u32,
410 y: u32,
411 width: u32,
412 height: u32,
413 ) -> Result<()> {
414 self.write_partial_bw_buffer(buffer, x, y, width, height)
415 .await?;
416 self.fast_refresh().await?;
417 self.write_partial_red_buffer(buffer, x, y, width, height)
418 .await?;
419 self.write_partial_bw_buffer(buffer, x, y, width, height)
420 .await?;
421 Ok(())
422 }
423
424 #[cfg_attr(docsrs, doc(cfg(feature = "graphics")))]
426 #[cfg(feature = "graphics")]
427 pub async fn full_update<const BUFFER_SIZE: usize>(
428 &mut self,
429 display: &Display<WIDTH, HEIGHT, BUFFER_SIZE, Color>,
430 ) -> Result<()> {
431 self.full_update_from_buffer(display.buffer()).await
432 }
433
434 #[cfg_attr(docsrs, doc(cfg(feature = "graphics")))]
436 #[cfg(feature = "graphics")]
437 pub async fn fast_update<const BUFFER_SIZE: usize>(
438 &mut self,
439 display: &Display<WIDTH, HEIGHT, BUFFER_SIZE, Color>,
440 ) -> Result<()> {
441 self.fast_update_from_buffer(display.buffer()).await
442 }
443
444 #[cfg_attr(docsrs, doc(cfg(feature = "graphics")))]
448 #[cfg(feature = "graphics")]
449 pub async fn fast_partial_update<const W: u32, const H: u32, const BUFFER_SIZE: usize>(
450 &mut self,
451 display: &Display<W, H, BUFFER_SIZE, Color>,
452 x: u32,
453 y: u32,
454 ) -> Result<()> {
455 self.fast_partial_update_from_buffer(display.buffer(), x, y, W, H)
456 .await
457 }
458}
459
460#[maybe_async_cfg::maybe(
462 sync(
463 feature = "blocking",
464 keep_self,
465 idents(
466 AsyncWriteOnlyDataCommand(sync = "WriteOnlyDataCommand"),
467 Wait(sync = "InputPin")
468 )
469 ),
470 async(not(feature = "blocking"), keep_self)
471)]
472impl<DI, BSY, RST, DELAY, const WIDTH: u32, const VISIBLE_WIDTH: u32, const HEIGHT: u32>
473 DisplayDriver<DI, BSY, RST, DELAY, WIDTH, VISIBLE_WIDTH, HEIGHT, TriColor>
474where
475 DI: AsyncWriteOnlyDataCommand,
476 BSY: InputPin + Wait,
477 RST: OutputPin,
478 DELAY: DelayNs,
479{
480 pub async fn full_update_from_buffer(
482 &mut self,
483 bw_buffer: &[u8],
484 red_buffer: &[u8],
485 ) -> Result<()> {
486 self.write_red_buffer(red_buffer).await?;
487 self.write_bw_buffer(bw_buffer).await?;
488 self.full_refresh().await?;
489 Ok(())
490 }
491
492 #[cfg_attr(docsrs, doc(cfg(feature = "graphics")))]
494 #[cfg(feature = "graphics")]
495 pub async fn full_update<const BUFFER_SIZE: usize>(
496 &mut self,
497 display: &Display<WIDTH, HEIGHT, BUFFER_SIZE, TriColor>,
498 ) -> Result<()> {
499 self.full_update_from_buffer(display.bw_buffer(), display.red_buffer())
500 .await
501 }
502
503 }