1use crate::bus::{self, Bus, BusAddr8, DataWidth};
38use core::cell::Cell;
39use kernel::hil::gpio::Pin;
40use kernel::hil::screen::{
41 self, ScreenClient, ScreenPixelFormat, ScreenRotation, ScreenSetupClient,
42};
43use kernel::hil::time::{self, Alarm, ConvertTicks};
44use kernel::utilities::cells::{OptionalCell, TakeCell};
45use kernel::utilities::leasable_buffer::SubSliceMut;
46use kernel::ErrorCode;
47
48pub const BUFFER_SIZE: usize = 24;
49
50#[derive(PartialEq)]
51pub struct Command {
52 pub id: u8,
53 pub parameters: Option<&'static [u8]>,
54 pub delay: u8,
55}
56
57const NOP: Command = Command {
58 id: 0x00,
59 parameters: None,
60 delay: 0,
61};
62
63const SW_RESET: Command = Command {
64 id: 0x01,
65 parameters: None,
66 delay: 150, };
68
69const SLEEP_IN: Command = Command {
70 id: 0x10,
71 parameters: None,
72 delay: 10,
73};
74
75const SLEEP_OUT: Command = Command {
76 id: 0x11,
77 parameters: None,
78 delay: 255,
79};
80
81#[allow(dead_code)]
82const PARTIAL_ON: Command = Command {
83 id: 0x12,
84 parameters: None,
85 delay: 0,
86};
87
88const INVOFF: Command = Command {
89 id: 0x20,
90 parameters: None,
91 delay: 0,
92};
93
94const INVON: Command = Command {
95 id: 0x21,
96 parameters: None,
97 delay: 120,
98};
99
100const DISPLAY_OFF: Command = Command {
101 id: 0x28,
102 parameters: None,
103 delay: 100,
104};
105
106const DISPLAY_ON: Command = Command {
107 id: 0x29,
108 parameters: None,
109 delay: 100,
110};
111
112const WRITE_RAM: Command = Command {
113 id: 0x2C,
114 parameters: Some(&[]),
115 delay: 0,
116};
117
118#[allow(dead_code)]
119const READ_RAM: Command = Command {
120 id: 0x2E,
121 parameters: None,
122 delay: 0,
123};
124
125const CASET: Command = Command {
126 id: 0x2A,
127 parameters: Some(&[0x00, 0x00, 0x00, 0x00]),
128 delay: 0,
129};
130
131const RASET: Command = Command {
132 id: 0x2B,
133 parameters: Some(&[0x00, 0x00, 0x00, 0x00]),
134 delay: 0,
135};
136
137const NORON: Command = Command {
138 id: 0x13,
139 parameters: None,
140 delay: 10,
141};
142
143#[allow(dead_code)]
144const IDLE_OFF: Command = Command {
145 id: 0x38,
146 parameters: None,
147 delay: 20,
148};
149
150#[allow(dead_code)]
151const IDLE_ON: Command = Command {
152 id: 0x39,
153 parameters: None,
154 delay: 0,
155};
156
157const COLMOD: Command = Command {
158 id: 0x3A,
159 parameters: Some(&[0x05]),
160 delay: 0,
161};
162
163const MADCTL: Command = Command {
164 id: 0x36,
165 parameters: Some(&[0x00]),
166 delay: 0,
167};
168
169pub type CommandSequence = &'static [SendCommand];
170
171#[macro_export]
172macro_rules! default_parameters_sequence {
173 ($($cmd:expr),+) => {
174 [$(SendCommand::Default($cmd), )+]
175 }
176}
177
178pub const SEQUENCE_BUFFER_SIZE: usize = 24;
179
180#[derive(Copy, Clone, PartialEq)]
181enum Status {
182 Idle,
183 Init,
184 Reset1,
185 Reset2,
186 Reset3,
187 Reset4,
188 SendCommand(usize, usize, usize),
189 SendCommandSlice(usize),
190 SendParametersSlice,
191 Delay,
192 Error(ErrorCode),
193}
194#[derive(Copy, Clone, PartialEq)]
195pub enum SendCommand {
196 Nop,
197 Default(&'static Command),
198 Position(&'static Command, usize, usize),
201 Repeat(&'static Command, usize, usize, usize),
205 Slice(&'static Command, usize),
207}
208
209pub struct ST77XX<'a, A: Alarm<'a>, B: Bus<'a, BusAddr8>, P: Pin> {
210 bus: &'a B,
211 alarm: &'a A,
212 dc: Option<&'a P>,
213 reset: Option<&'a P>,
214 status: Cell<Status>,
215 width: Cell<usize>,
216 height: Cell<usize>,
217
218 client: OptionalCell<&'a dyn screen::ScreenClient>,
219 setup_client: OptionalCell<&'a dyn screen::ScreenSetupClient>,
220 setup_command: Cell<bool>,
221
222 sequence_buffer: TakeCell<'static, [SendCommand]>,
223 position_in_sequence: Cell<usize>,
224 sequence_len: Cell<usize>,
225 command: Cell<&'static Command>,
226 buffer: TakeCell<'static, [u8]>,
227
228 power_on: Cell<bool>,
229
230 write_buffer: TakeCell<'static, [u8]>,
231
232 current_rotation: Cell<ScreenRotation>,
233
234 screen: &'static ST77XXScreen,
235}
236
237impl<'a, A: Alarm<'a>, B: Bus<'a, BusAddr8>, P: Pin> ST77XX<'a, A, B, P> {
238 pub fn new(
239 bus: &'a B,
240 alarm: &'a A,
241 dc: Option<&'a P>,
242 reset: Option<&'a P>,
243 buffer: &'static mut [u8],
244 sequence_buffer: &'static mut [SendCommand],
245 screen: &'static ST77XXScreen,
246 ) -> ST77XX<'a, A, B, P> {
247 dc.map(|dc| dc.make_output());
248 reset.map(|reset| reset.make_output());
249 ST77XX {
250 alarm,
251
252 dc,
253 reset,
254 bus,
255
256 status: Cell::new(Status::Idle),
257 width: Cell::new(screen.default_width),
258 height: Cell::new(screen.default_height),
259
260 client: OptionalCell::empty(),
261 setup_client: OptionalCell::empty(),
262 setup_command: Cell::new(false),
263
264 sequence_buffer: TakeCell::new(sequence_buffer),
265 sequence_len: Cell::new(0),
266 position_in_sequence: Cell::new(0),
267 command: Cell::new(&NOP),
268 buffer: TakeCell::new(buffer),
269
270 power_on: Cell::new(false),
271
272 write_buffer: TakeCell::empty(),
273
274 current_rotation: Cell::new(ScreenRotation::Normal),
275
276 screen,
277 }
278 }
279
280 fn send_sequence(&self, sequence: CommandSequence) -> Result<(), ErrorCode> {
281 if self.status.get() == Status::Idle {
282 let error = self.sequence_buffer.map_or_else(
283 || panic!("st77xx: send sequence has no sequence buffer"),
284 |sequence_buffer| {
285 if sequence.len() <= sequence_buffer.len() {
286 self.sequence_len.set(sequence.len());
287 for (i, cmd) in sequence.iter().enumerate() {
288 sequence_buffer[i] = *cmd;
289 }
290 Ok(())
291 } else {
292 Err(ErrorCode::NOMEM)
293 }
294 },
295 );
296 if error == Ok(()) {
297 self.send_sequence_buffer()
298 } else {
299 error
300 }
301 } else {
302 Err(ErrorCode::BUSY)
303 }
304 }
305
306 fn send_sequence_buffer(&self) -> Result<(), ErrorCode> {
307 if self.status.get() == Status::Idle {
308 self.position_in_sequence.set(0);
309 self.status.set(Status::Delay);
311 self.do_next_op();
312 Ok(())
313 } else {
314 Err(ErrorCode::BUSY)
315 }
316 }
317
318 fn send_command_with_default_parameters(&self, cmd: &'static Command) {
319 let mut len = 0;
320 self.buffer.map_or_else(
321 || panic!("st77xx: send parameters has no buffer"),
322 |buffer| {
323 if let Some(parameters) = cmd.parameters {
325 for parameter in parameters.iter() {
326 buffer[len] = *parameter;
327 len += 1;
328 }
329 }
330 },
331 );
332 self.send_command(cmd, 0, len, 1);
333 }
334
335 fn send_command(&self, cmd: &'static Command, position: usize, len: usize, repeat: usize) {
336 self.command.set(cmd);
337 self.status.set(Status::SendCommand(position, len, repeat));
338 self.dc.map(|dc| dc.clear());
339 let _ = self.bus.set_addr(cmd.id.into());
340 }
341
342 fn send_command_slice(&self, cmd: &'static Command, len: usize) {
343 self.command.set(cmd);
344 self.dc.map(|dc| dc.clear());
345 self.status.set(Status::SendCommandSlice(len));
346 let _ = self.bus.set_addr(cmd.id.into());
347 }
348
349 fn send_parameters(&self, position: usize, len: usize, repeat: usize) {
350 self.status.set(Status::SendCommand(0, len, repeat - 1));
351 if len > 0 {
352 self.buffer.take().map_or_else(
353 || panic!("st77xx: send parameters has no buffer"),
354 |buffer| {
355 if position > 0 {
357 for i in position..len + position {
358 buffer[i - position] = buffer[i];
359 }
360 }
361 self.dc.map(|dc| dc.set());
362 let _ = self.bus.write(DataWidth::Bits8, buffer, len);
363 },
364 );
365 } else {
366 self.do_next_op();
367 }
368 }
369
370 fn send_parameters_slice(&self, len: usize) {
371 self.write_buffer.take().map_or_else(
372 || panic!("st77xx: no write buffer"),
373 |buffer| {
374 self.status.set(Status::SendParametersSlice);
375 self.dc.map(|dc| dc.set());
376 let _ = self.bus.write(DataWidth::Bits16BE, buffer, len / 2);
377 },
378 );
379 }
380
381 fn rotation(&self, rotation: ScreenRotation) -> Result<(), ErrorCode> {
382 if self.status.get() == Status::Idle {
383 let rotation_bits = match rotation {
384 ScreenRotation::Normal => 0x00,
385 ScreenRotation::Rotated90 => 0x60,
386 ScreenRotation::Rotated180 => 0xC0,
387 ScreenRotation::Rotated270 => 0xA0,
388 };
389 match rotation {
390 ScreenRotation::Normal | ScreenRotation::Rotated180 => {
391 self.width.set(self.screen.default_width);
392 self.height.set(self.screen.default_height);
393 }
394 ScreenRotation::Rotated90 | ScreenRotation::Rotated270 => {
395 self.width.set(self.screen.default_height);
396 self.height.set(self.screen.default_width);
397 }
398 }
399 self.buffer.map_or_else(
400 || panic!("st77xx: set rotation has no buffer"),
401 |buffer| {
402 buffer[0] =
403 rotation_bits | MADCTL.parameters.map_or(0, |parameters| parameters[0])
404 },
405 );
406 self.setup_command.set(true);
407 self.send_command(&MADCTL, 0, 1, 1);
408 self.current_rotation.set(rotation);
409 Ok(())
410 } else {
411 Err(ErrorCode::BUSY)
412 }
413 }
414
415 fn display_on(&self) -> Result<(), ErrorCode> {
416 if self.status.get() == Status::Idle {
417 if !self.power_on.get() {
418 Err(ErrorCode::OFF)
419 } else {
420 self.setup_command.set(false);
421 self.send_command_with_default_parameters(&DISPLAY_ON);
422 Ok(())
423 }
424 } else {
425 Err(ErrorCode::BUSY)
426 }
427 }
428
429 fn display_off(&self) -> Result<(), ErrorCode> {
430 if self.status.get() == Status::Idle {
431 if !self.power_on.get() {
432 Err(ErrorCode::OFF)
433 } else {
434 self.setup_command.set(false);
435 self.send_command_with_default_parameters(&DISPLAY_OFF);
436 Ok(())
437 }
438 } else {
439 Err(ErrorCode::BUSY)
440 }
441 }
442
443 fn display_invert_on(&self) -> Result<(), ErrorCode> {
444 if self.status.get() == Status::Idle {
445 if !self.power_on.get() {
446 Err(ErrorCode::OFF)
447 } else {
448 self.setup_command.set(false);
449 let cmd = if self.screen.inverted {
450 &INVOFF
451 } else {
452 &INVON
453 };
454 self.send_command_with_default_parameters(cmd);
455 Ok(())
456 }
457 } else {
458 Err(ErrorCode::BUSY)
459 }
460 }
461
462 fn display_invert_off(&self) -> Result<(), ErrorCode> {
463 if self.status.get() == Status::Idle {
464 if !self.power_on.get() {
465 Err(ErrorCode::OFF)
466 } else {
467 self.setup_command.set(false);
468 let cmd = if self.screen.inverted {
469 &INVON
470 } else {
471 &INVOFF
472 };
473 self.send_command_with_default_parameters(cmd);
474 Ok(())
475 }
476 } else {
477 Err(ErrorCode::BUSY)
478 }
479 }
480
481 fn do_next_op(&self) {
482 match self.status.get() {
483 Status::Delay => {
484 let position = self.position_in_sequence.get();
485
486 self.position_in_sequence
487 .set(self.position_in_sequence.get() + 1);
488 if position < self.sequence_len.get() {
489 self.sequence_buffer.map_or_else(
490 || panic!("st77xx: do next op has no sequence buffer"),
491 |sequence| match sequence[position] {
492 SendCommand::Nop => self.do_next_op(),
493 SendCommand::Default(cmd) => {
494 self.send_command_with_default_parameters(cmd)
495 }
496 SendCommand::Position(cmd, position, len) => {
497 self.send_command(cmd, position, len, 1)
498 }
499 SendCommand::Repeat(cmd, position, len, repeat) => {
500 self.send_command(cmd, position, len, repeat)
501 }
502 SendCommand::Slice(cmd, len) => self.send_command_slice(cmd, len),
503 },
504 );
505 } else {
506 self.status.set(Status::Idle);
507 if !self.power_on.get() {
508 self.client.map(|client| {
509 self.power_on.set(true);
510
511 client.screen_is_ready()
512 });
513 } else {
514 if self.setup_command.get() {
515 self.setup_command.set(false);
516 self.setup_client
517 .map(|setup_client| setup_client.command_complete(Ok(())));
518 } else {
519 self.client.map(|client| {
520 if self.write_buffer.is_some() {
521 self.write_buffer.take().map(|buffer| {
522 let data = SubSliceMut::new(buffer);
523 client.write_complete(data, Ok(()))
524 });
525 } else {
526 client.command_complete(Ok(()))
527 }
528 });
529 }
530 }
531 }
532 }
533 Status::SendCommand(parameters_position, parameters_length, repeat) => {
534 if repeat == 0 {
535 self.dc.map(|dc| dc.clear());
536 let mut delay = self.command.get().delay as u32;
537 if delay > 0 {
538 if delay == 255 {
539 delay = 500;
540 }
541 self.set_delay(delay, Status::Delay)
542 } else {
543 self.status.set(Status::Delay);
544 self.do_next_op();
545 }
546 } else {
547 self.send_parameters(parameters_position, parameters_length, repeat);
548 }
549 }
550 Status::SendCommandSlice(len) => {
551 self.send_parameters_slice(len);
552 }
553 Status::SendParametersSlice => {
554 self.dc.map(|dc| dc.clear());
555 let mut delay = self.command.get().delay as u32;
556 if delay > 0 {
557 if delay == 255 {
558 delay = 500;
559 }
560 self.set_delay(delay, Status::Delay)
561 } else {
562 self.status.set(Status::Delay);
563 self.do_next_op();
564 }
565 }
566 Status::Reset1 => {
567 self.reset.map(|reset| reset.clear());
569 self.set_delay(10, Status::Reset2);
570 }
571 Status::Reset2 => {
572 self.reset.map(|reset| reset.set());
573 self.set_delay(120, Status::Reset3);
574 }
575 Status::Reset3 => {
576 self.reset.map(|reset| reset.clear());
577 self.set_delay(120, Status::Reset4);
578 }
579 Status::Reset4 => {
580 self.reset.map(|reset| reset.set());
581 self.set_delay(120, Status::Init);
582 }
583 Status::Init => {
584 self.status.set(Status::Idle);
585 let _ = self.send_sequence(self.screen.init_sequence);
586 }
587 Status::Error(error) => {
588 if self.setup_command.get() {
589 self.setup_command.set(false);
590 self.setup_client.map(|setup_client| {
591 setup_client.command_complete(Err(error));
592 });
593 } else {
594 self.client.map(|client| {
595 if self.write_buffer.is_some() {
596 self.write_buffer.take().map(|buffer| {
597 let data = SubSliceMut::new(buffer);
598 client.write_complete(data, Err(error));
599 });
600 } else {
601 client.command_complete(Err(error));
602 }
603 });
604 }
605 self.status.set(Status::Idle);
606 }
607 _ => {
608 panic!("ST77XX status Idle");
609 }
610 }
611 }
612
613 fn set_memory_frame(
614 &self,
615 position: usize,
616 sx: usize,
617 sy: usize,
618 ex: usize,
619 ey: usize,
620 ) -> Result<(), ErrorCode> {
621 if sx <= self.width.get()
622 && sy <= self.height.get()
623 && ex <= self.width.get()
624 && ey <= self.height.get()
625 && sx <= ex
626 && sy <= ey
627 {
628 let (ox, oy) = (self.screen.offset)(self.current_rotation.get());
629 if self.status.get() == Status::Idle {
630 self.buffer.map_or_else(
631 || panic!("st77xx: set memory frame has no buffer"),
632 |buffer| {
633 buffer[position] = (((sx + ox) >> 8) & 0xFF) as u8;
635 buffer[position + 1] = ((sx + ox) & 0xFF) as u8;
636 buffer[position + 2] = (((ex + ox) >> 8) & 0xFF) as u8;
637 buffer[position + 3] = ((ex + ox) & 0xFF) as u8;
638 buffer[position + 4] = (((sy + oy) >> 8) & 0xFF) as u8;
640 buffer[position + 5] = ((sy + oy) & 0xFF) as u8;
641 buffer[position + 6] = (((ey + oy) >> 8) & 0xFF) as u8;
642 buffer[position + 7] = ((ey + oy) & 0xFF) as u8;
643 },
644 );
645 Ok(())
646 } else {
647 Err(ErrorCode::BUSY)
648 }
649 } else {
650 Err(ErrorCode::INVAL)
651 }
652 }
653
654 pub fn init(&self) -> Result<(), ErrorCode> {
655 if self.status.get() == Status::Idle {
656 self.status.set(Status::Reset1);
657 self.do_next_op();
658 Ok(())
659 } else {
660 Err(ErrorCode::BUSY)
661 }
662 }
663
664 fn set_delay(&self, timer: u32, next_status: Status) {
673 self.status.set(next_status);
674 let interval = self.alarm.ticks_from_ms(timer);
675 self.alarm.set_alarm(self.alarm.now(), interval);
676 }
677}
678
679impl<'a, A: Alarm<'a>, B: Bus<'a, BusAddr8>, P: Pin> screen::ScreenSetup<'a>
680 for ST77XX<'a, A, B, P>
681{
682 fn set_client(&self, setup_client: &'a dyn ScreenSetupClient) {
683 self.setup_client.set(setup_client);
684 }
685
686 fn set_resolution(&self, resolution: (usize, usize)) -> Result<(), ErrorCode> {
687 if self.status.get() == Status::Idle {
688 if resolution.0 == self.width.get() && resolution.1 == self.height.get() {
689 self.setup_client
690 .map(|setup_client| setup_client.command_complete(Ok(())));
691 Ok(())
692 } else {
693 Err(ErrorCode::NOSUPPORT)
694 }
695 } else {
696 Err(ErrorCode::BUSY)
697 }
698 }
699
700 fn set_pixel_format(&self, depth: ScreenPixelFormat) -> Result<(), ErrorCode> {
701 if self.status.get() == Status::Idle {
702 if depth == ScreenPixelFormat::RGB_565 {
703 self.setup_client
704 .map(|setup_client| setup_client.command_complete(Ok(())));
705 Ok(())
706 } else {
707 Err(ErrorCode::INVAL)
708 }
709 } else {
710 Err(ErrorCode::BUSY)
711 }
712 }
713
714 fn set_rotation(&self, rotation: ScreenRotation) -> Result<(), ErrorCode> {
715 self.rotation(rotation)
716 }
717
718 fn get_num_supported_resolutions(&self) -> usize {
719 1
720 }
721 fn get_supported_resolution(&self, index: usize) -> Option<(usize, usize)> {
722 match index {
723 0 => Some((self.width.get(), self.height.get())),
724 _ => None,
725 }
726 }
727
728 fn get_num_supported_pixel_formats(&self) -> usize {
729 1
730 }
731 fn get_supported_pixel_format(&self, index: usize) -> Option<ScreenPixelFormat> {
732 match index {
733 0 => Some(ScreenPixelFormat::RGB_565),
734 _ => None,
735 }
736 }
737}
738
739impl<'a, A: Alarm<'a>, B: Bus<'a, BusAddr8>, P: Pin> screen::Screen<'a> for ST77XX<'a, A, B, P> {
740 fn get_resolution(&self) -> (usize, usize) {
741 (self.width.get(), self.height.get())
742 }
743
744 fn get_pixel_format(&self) -> ScreenPixelFormat {
745 ScreenPixelFormat::RGB_565
746 }
747
748 fn get_rotation(&self) -> ScreenRotation {
749 self.current_rotation.get()
750 }
751
752 fn set_write_frame(
753 &self,
754 x: usize,
755 y: usize,
756 width: usize,
757 height: usize,
758 ) -> Result<(), ErrorCode> {
759 if self.status.get() == Status::Idle {
760 self.setup_command.set(false);
761 let buffer_len = self.buffer.map_or_else(
762 || panic!("st77xx: buffer is not available"),
763 |buffer| buffer.len() - 1,
764 );
765 if buffer_len >= 9 {
766 let err = self.set_memory_frame(0, x, y, x + width - 1, y + height - 1);
768 if err == Ok(()) {
769 self.sequence_buffer.map_or_else(
770 || panic!("st77xx: set write frame no sequence buffer"),
771 |sequence| {
772 sequence[0] = SendCommand::Position(&CASET, 0, 4);
773 sequence[1] = SendCommand::Position(&RASET, 4, 4);
774 self.sequence_len.set(2);
775 },
776 );
777 let _ = self.send_sequence_buffer();
778 }
779 err
780 } else {
781 Err(ErrorCode::NOMEM)
782 }
783 } else {
784 Err(ErrorCode::BUSY)
785 }
786 }
787
788 fn write(
789 &self,
790 mut data: SubSliceMut<'static, u8>,
791 continue_write: bool,
792 ) -> Result<(), ErrorCode> {
793 if self.status.get() == Status::Idle {
794 for pair in data.as_slice().chunks_mut(2) {
797 pair.swap(0, 1);
798 }
799
800 self.setup_command.set(false);
801 let len = data.len();
802 self.write_buffer.replace(data.take());
803
804 if !continue_write {
805 let buffer_len = self.buffer.map_or_else(
809 || panic!("st77xx: buffer is not available"),
810 |buffer| buffer.len(),
811 );
812 if buffer_len > 0 {
813 self.sequence_buffer.map_or_else(
815 || panic!("st77xx: write no sequence buffer"),
816 |sequence| {
817 sequence[0] = SendCommand::Slice(&WRITE_RAM, len);
818 self.sequence_len.set(1);
819 },
820 );
821 let _ = self.send_sequence_buffer();
822 Ok(())
823 } else {
824 Err(ErrorCode::NOMEM)
825 }
826 } else {
827 self.send_parameters_slice(len);
829 Ok(())
830 }
831 } else {
832 Err(ErrorCode::BUSY)
833 }
834 }
835
836 fn set_client(&self, client: &'a dyn ScreenClient) {
837 self.client.set(client);
838 }
839
840 fn set_brightness(&self, _brightness: u16) -> Result<(), ErrorCode> {
841 Ok(())
842 }
843
844 fn set_power(&self, enabled: bool) -> Result<(), ErrorCode> {
845 if enabled {
846 self.display_on()
847 } else {
848 self.display_off()
849 }
850 }
851
852 fn set_invert(&self, enabled: bool) -> Result<(), ErrorCode> {
853 if enabled {
854 self.display_invert_on()
855 } else {
856 self.display_invert_off()
857 }
858 }
859}
860
861impl<'a, A: Alarm<'a>, B: Bus<'a, BusAddr8>, P: Pin> time::AlarmClient for ST77XX<'a, A, B, P> {
862 fn alarm(&self) {
863 self.do_next_op();
864 }
865}
866
867impl<'a, A: Alarm<'a>, B: Bus<'a, BusAddr8>, P: Pin> bus::Client for ST77XX<'a, A, B, P> {
868 fn command_complete(
869 &self,
870 buffer: Option<&'static mut [u8]>,
871 _len: usize,
872 status: Result<(), ErrorCode>,
873 ) {
874 if let Some(buffer) = buffer {
875 if self.status.get() == Status::SendParametersSlice {
876 self.write_buffer.replace(buffer);
877 } else {
878 self.buffer.replace(buffer);
879 }
880 }
881
882 if let Err(error) = status {
883 self.status.set(Status::Error(error));
884 }
885
886 self.do_next_op();
887 }
888}
889
890#[allow(dead_code)]
892const GAMSET: Command = Command {
893 id: 0x26,
894 parameters: Some(&[0]),
896 delay: 0,
897};
898
899const FRMCTR1: Command = Command {
900 id: 0xB1,
901 parameters: Some(&[0x01, 0x2C, 0x2D]),
902 delay: 0,
903};
904
905const FRMCTR2: Command = Command {
906 id: 0xB2,
907 parameters: Some(&[0x01, 0x2C, 0x2D]),
908 delay: 0,
909};
910
911const FRMCTR3: Command = Command {
912 id: 0xB3,
913 parameters: Some(&[0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D]),
914 delay: 0,
915};
916
917const INVCTR: Command = Command {
918 id: 0xB4,
919 parameters: Some(&[0x07]),
920 delay: 0,
921};
922
923const PWCTR1: Command = Command {
924 id: 0xC0,
925 parameters: Some(&[0xA2, 0x02, 0x84]),
926 delay: 0,
927};
928
929const PWCTR2: Command = Command {
930 id: 0xC1,
931 parameters: Some(&[0xC5]),
932 delay: 0,
933};
934
935const PWCTR3: Command = Command {
936 id: 0xC2,
937 parameters: Some(&[0x0A, 0x00]),
938 delay: 0,
939};
940
941const PWCTR4: Command = Command {
942 id: 0xC3,
943 parameters: Some(&[0x8A, 0x2A]),
944 delay: 0,
945};
946
947const PWCTR5: Command = Command {
948 id: 0xC4,
949 parameters: Some(&[0x8A, 0xEE]),
950 delay: 0,
951};
952
953const VMCTR1: Command = Command {
954 id: 0xC5,
955 parameters: Some(&[0x0E]),
956 delay: 0,
957};
958
959const GMCTRP1: Command = Command {
960 id: 0xE0,
961 parameters: Some(&[
962 0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03,
963 0x10,
964 ]),
965 delay: 0,
966};
967
968const GMCTRN1: Command = Command {
969 id: 0xE1,
970 parameters: Some(&[
971 0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02,
972 0x10,
973 ]),
974 delay: 0,
975};
976
977const ST7735_INIT_SEQUENCE: [SendCommand; 20] = crate::default_parameters_sequence!(
978 &SW_RESET, &SLEEP_OUT, &FRMCTR1, &FRMCTR2, &FRMCTR3, &INVCTR, &PWCTR1, &PWCTR2, &PWCTR3,
979 &PWCTR4, &PWCTR5, &VMCTR1, &INVOFF, &MADCTL, &COLMOD, &CASET, &RASET, &GMCTRP1, &GMCTRN1,
980 &NORON
981);
982
983const PV_GAMMA_CTRL: Command = Command {
986 id: 0xE0,
987 parameters: Some(&[
988 0xD0, 0x08, 0x11, 0x08, 0x0C, 0x15, 0x39, 0x33, 0x50, 0x36, 0x13, 0x14, 0x29, 0x2D,
989 ]),
990 delay: 0,
991};
992
993const NV_GAMMA_CTRL: Command = Command {
994 id: 0xE1,
995 parameters: Some(&[
996 0xD0, 0x08, 0x10, 0x08, 0x06, 0x06, 0x39, 0x44, 0x51, 0x0B, 0x16, 0x14, 0x2F, 0x31,
997 ]),
998 delay: 0,
999};
1000
1001const PORCH_CTRL: Command = Command {
1002 id: 0xB2,
1003 parameters: Some(&[0x0C, 0x0C, 0x00, 0x33, 0x33]),
1004 delay: 0,
1005};
1006
1007const GATE_CTRL: Command = Command {
1008 id: 0xB7,
1009 parameters: Some(&[0x35]),
1010 delay: 0,
1011};
1012
1013const LCM_CTRL: Command = Command {
1014 id: 0xC0,
1015 parameters: Some(&[0x2C]),
1016 delay: 0,
1017};
1018
1019const VDV_VRH_EN: Command = Command {
1020 id: 0xC2,
1021 parameters: Some(&[0x01, 0xC3]),
1022 delay: 0,
1023};
1024
1025const VDV_SET: Command = Command {
1026 id: 0xC4,
1027 parameters: Some(&[0x20]),
1028 delay: 0,
1029};
1030
1031const FR_CTRL: Command = Command {
1032 id: 0xC6,
1033 parameters: Some(&[0x0F]),
1034 delay: 0,
1035};
1036
1037const VCOM_SET: Command = Command {
1038 id: 0xBB,
1039 parameters: Some(&[0x1F]),
1040 delay: 0,
1041};
1042
1043const POWER_CTRL: Command = Command {
1044 id: 0xD0,
1045 parameters: Some(&[0xA4, 0xA1]),
1046 delay: 0,
1047};
1048
1049const TEARING_EFFECT: Command = Command {
1050 id: 0x35,
1051 parameters: Some(&[0x00]),
1052 delay: 0,
1053};
1054
1055const ST7789H2_INIT_SEQUENCE: [SendCommand; 22] = crate::default_parameters_sequence!(
1056 &SLEEP_IN,
1057 &SW_RESET,
1058 &SLEEP_OUT,
1059 &NORON,
1060 &COLMOD,
1061 &INVON,
1062 &CASET,
1063 &RASET,
1064 &PORCH_CTRL,
1065 &GATE_CTRL,
1066 &VCOM_SET,
1067 &LCM_CTRL,
1068 &VDV_VRH_EN,
1069 &VDV_SET,
1070 &FR_CTRL,
1071 &POWER_CTRL,
1072 &PV_GAMMA_CTRL,
1073 &NV_GAMMA_CTRL,
1074 &MADCTL,
1075 &DISPLAY_ON,
1076 &SLEEP_OUT,
1077 &TEARING_EFFECT
1078);
1079
1080const VSYNC_OUTPUT: Command = Command {
1083 id: 0x35,
1084 parameters: Some(&[0x00]),
1085 delay: 0,
1086};
1087
1088const NORMAL_DISPLAY: Command = Command {
1089 id: 0x36,
1090 parameters: Some(&[0x83]),
1091 delay: 0,
1092};
1093
1094const PANEL_SETTING1: Command = Command {
1095 id: 0xB0,
1096 parameters: Some(&[0x01, 0xFE]),
1097 delay: 0,
1098};
1099
1100const PANEL_SETTING2: Command = Command {
1101 id: 0xB1,
1102 parameters: Some(&[0xDE, 0x21]),
1103 delay: 0,
1104};
1105
1106const OSCILLATOR: Command = Command {
1107 id: 0xB3,
1108 parameters: Some(&[0x02]),
1109 delay: 0,
1110};
1111
1112const PANEL_SETTING_LOCK: Command = Command {
1113 id: 0xB4,
1114 parameters: None,
1115 delay: 0,
1116};
1117
1118const PANEL_V_PORCH: Command = Command {
1119 id: 0xB7,
1120 parameters: Some(&[0x05, 0x33]),
1121 delay: 0,
1122};
1123
1124const PANEL_IDLE_V_PORCH: Command = Command {
1125 id: 0xB8,
1126 parameters: Some(&[0x05, 0x33]),
1127 delay: 0,
1128};
1129
1130const GVDD: Command = Command {
1131 id: 0xC0,
1132 parameters: Some(&[0x53]),
1133 delay: 0,
1134};
1135
1136const OPAMP: Command = Command {
1137 id: 0xC2,
1138 parameters: Some(&[0x03, 0x12]),
1139 delay: 0,
1140};
1141
1142const RELOAD_MTP_VCOMH: Command = Command {
1143 id: 0xC5,
1144 parameters: Some(&[0x00, 0x45]),
1145 delay: 0,
1146};
1147
1148const PANEL_TIMING1: Command = Command {
1149 id: 0xC8,
1150 parameters: Some(&[0x04, 0x03]),
1151 delay: 0,
1152};
1153
1154const PANEL_TIMING2: Command = Command {
1155 id: 0xC9,
1156 parameters: Some(&[0x5E, 0x08]),
1157 delay: 0,
1158};
1159
1160const PANEL_TIMING3: Command = Command {
1161 id: 0xCA,
1162 parameters: Some(&[0x0A, 0x0C, 0x02]),
1163 delay: 0,
1164};
1165
1166const PANEL_TIMING4: Command = Command {
1167 id: 0xCC,
1168 parameters: Some(&[0x03, 0x04]),
1169 delay: 0,
1170};
1171
1172const PANEL_POWER: Command = Command {
1173 id: 0xD0,
1174 parameters: Some(&[0x0C]),
1175 delay: 0,
1176};
1177
1178const LS0168BUY_TEARING_EFFECT: Command = Command {
1179 id: 0xDD,
1180 parameters: Some(&[0x00]),
1181 delay: 0,
1182};
1183
1184const LS016B8UY_INIT_SEQUENCE: [SendCommand; 23] = default_parameters_sequence!(
1185 &VSYNC_OUTPUT,
1186 &COLMOD,
1187 &PANEL_SETTING1,
1188 &PANEL_SETTING2,
1189 &PANEL_V_PORCH,
1190 &PANEL_IDLE_V_PORCH,
1191 &PANEL_TIMING1,
1192 &PANEL_TIMING2,
1193 &PANEL_TIMING3,
1194 &PANEL_TIMING4,
1195 &PANEL_POWER,
1196 &OSCILLATOR,
1197 &GVDD,
1198 &RELOAD_MTP_VCOMH,
1199 &OPAMP,
1200 &LS0168BUY_TEARING_EFFECT,
1201 &PANEL_SETTING_LOCK,
1202 &SLEEP_OUT,
1203 &NORMAL_DISPLAY,
1204 &CASET,
1205 &RASET,
1206 &DISPLAY_ON,
1207 &IDLE_OFF
1208);
1209
1210pub struct ST77XXScreen {
1211 init_sequence: &'static [SendCommand],
1212 default_width: usize,
1213 default_height: usize,
1214 inverted: bool,
1215
1216 offset: fn(rotation: ScreenRotation) -> (usize, usize),
1220}
1221
1222pub const ST7735: ST77XXScreen = ST77XXScreen {
1223 init_sequence: &ST7735_INIT_SEQUENCE,
1224 default_width: 128,
1225 default_height: 160,
1226 inverted: false,
1227 offset: |_| (0, 0),
1228};
1229
1230pub const ST7789H2: ST77XXScreen = ST77XXScreen {
1231 init_sequence: &ST7789H2_INIT_SEQUENCE,
1232 default_width: 240,
1233 default_height: 240,
1234 inverted: true,
1235 offset: |rotation| match rotation {
1236 ScreenRotation::Rotated180 => (0, 80),
1237 ScreenRotation::Rotated270 => (80, 0),
1238 _ => (0, 0),
1239 },
1240};
1241
1242pub const LS016B8UY: ST77XXScreen = ST77XXScreen {
1243 init_sequence: &LS016B8UY_INIT_SEQUENCE,
1244 default_width: 240,
1245 default_height: 240,
1246 inverted: false,
1247 offset: |_| (0, 0),
1248};