capsules_extra/
st77xx.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! ST77xx Screen
6//!
7//! - <https://learn.adafruit.com/adafruit-1-3-and-1-54-240-x-240-wide-angle-tft-lcd-displays>
8//!
9//! The screen supports multiple physical busses, and this driver is implemented
10//! on top of the generic `Bus` interface.
11//!
12//! Usage
13//! -----
14//!
15//! SPI example
16//!
17//! ```rust,ignore
18//! let tft = components::st77xx::ST77XXComponent::new(mux_alarm,
19//!                                                    bus,
20//!                                                    Some(&nrf52840::gpio::PORT[GPIO_D3]),
21//!                                                    Some(&nrf52840::gpio::PORT[GPIO_D2]),
22//!                                                    &capsules::st77xx::ST7735).finalize(
23//!     components::st77xx_component_static!(
24//!         // bus type
25//!         capsules::bus::SpiMasterBus<
26//!             'static,
27//!             VirtualSpiMasterDevice<'static, nrf52840::spi::SPIM>,
28//!         >,
29//!         // timer type
30//!         nrf52840::rtc::Rtc,
31//!         // pin type
32//!         nrf52::gpio::GPIOPin<'static>,
33//!     ),
34//! );
35//! ```
36
37use 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, // 255?
67};
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    // first usize is the position in the buffer
199    // second usize is the length in the buffer starting from the position
200    Position(&'static Command, usize, usize),
201    // first usize is the position in the buffer (4 bytes - repeat times, length bytes data)
202    // second usize is the length in the buffer
203    // third usize is the number of repeats
204    Repeat(&'static Command, usize, usize, usize),
205    // usize is length
206    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            // set status to delay so that do_next_op will send the next item in the sequence
310            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                // buffer[0] = cmd.id;
324                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                    // shift parameters
356                    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.send_command_with_default_parameters(&NOP);
568                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                        // CASET
634                        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                        // RASET
639                        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    /// set_delay sets an alarm and saved the next state after that.
665    ///
666    /// As argument, there are:
667    ///  - the duration of the alarm in ms
668    ///  - the status of the program after the alarm fires
669    ///
670    /// Example:
671    ///  self.set_delay(10, Status::Idle);
672    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                // set buffer
767                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            // Data is provided as RGB565 ( RRRRR GGG | GGG BBBBB ), but the device expects it to come over the bus in little endian, so ( GGG BBBBB | RRRRR GGG ).
795            // TODO(alevy): replace `chunks_mut` wit `array_chunks` when stable.
796            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                // Writing new data for the first time, make sure to reset
806                // the screen buffer location to the beginning.
807
808                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                    // set buffer
814                    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                // Continuing the previous write.
828                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/************ ST7735 **************/
891#[allow(dead_code)]
892const GAMSET: Command = Command {
893    id: 0x26,
894    // Default parameters: Gama Set
895    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
983/************ ST7789H2 **************/
984
985const 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
1080/******** LS016B8UY *********/
1081
1082const 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    /// This function allows the translation of the image
1217    /// as some screen implementations might have off screen
1218    /// pixels for some of the rotations
1219    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};