lcd_async/models/
rm67162.rs

1use embedded_graphics_core::pixelcolor::Rgb565;
2use embedded_hal_async::delay::DelayNs;
3
4use crate::{
5    dcs::{
6        BitsPerPixel, ExitSleepMode, InterfaceExt, PixelFormat, SetAddressMode, SetDisplayOn,
7        SetInvertMode, SetPixelFormat,
8    },
9    interface::{Interface, InterfaceKind},
10    models::{Model, ModelInitError},
11    options::ModelOptions,
12    ConfigurationError,
13};
14
15/// RM67162 AMOLED display driver implementation
16///
17/// Supports:
18/// - 16-bit RGB565 color
19/// - 240x536 resolution
20///
21/// This driver was developed for the Lilygo T-Display-S3 AMOLED display (v2).
22/// The initialization sequence is based on Lilygo's Arduino example code.
23///
24/// Currently only tested with 240x536 resolution displays.
25/// While it may work with other display sizes, this is untested and could lead to unexpected behavior.
26/// If you encounter issues with different display sizes, please report them.
27///
28pub struct RM67162;
29
30impl Model for RM67162 {
31    type ColorFormat = Rgb565;
32    const FRAMEBUFFER_SIZE: (u16, u16) = (240, 536);
33
34    async fn init<DELAY, DI>(
35        &mut self,
36        di: &mut DI,
37        delay: &mut DELAY,
38        options: &ModelOptions,
39    ) -> Result<SetAddressMode, ModelInitError<DI::Error>>
40    where
41        DELAY: DelayNs,
42        DI: Interface,
43    {
44        if !matches!(
45            DI::KIND,
46            InterfaceKind::Serial4Line | InterfaceKind::Parallel8Bit
47        ) {
48            return Err(ModelInitError::InvalidConfiguration(
49                ConfigurationError::UnsupportedInterface,
50            ));
51        }
52
53        let madctl = SetAddressMode::from(options);
54
55        di.write_raw(0xFE, &[0x04]).await?;
56        di.write_raw(0x6A, &[0x00]).await?;
57        di.write_raw(0xFE, &[0x05]).await?;
58        di.write_raw(0xFE, &[0x07]).await?;
59        di.write_raw(0x07, &[0x4F]).await?;
60        di.write_raw(0xFE, &[0x01]).await?;
61        di.write_raw(0x2A, &[0x02]).await?;
62        di.write_raw(0x2B, &[0x73]).await?;
63        di.write_raw(0xFE, &[0x0A]).await?;
64        di.write_raw(0x29, &[0x10]).await?;
65        di.write_raw(0xFE, &[0x00]).await?;
66        di.write_raw(0x51, &[0xaf]).await?; // Set brightness
67        di.write_raw(0x53, &[0x20]).await?;
68        di.write_raw(0x35, &[0x00]).await?;
69
70        let pf = PixelFormat::with_all(BitsPerPixel::from_rgb_color::<Self::ColorFormat>());
71        di.write_command(SetPixelFormat::new(pf)).await?;
72
73        di.write_raw(0xC4, &[0x80]).await?; // enable SRAM access via SPI
74
75        di.write_command(madctl).await?;
76
77        di.write_command(SetInvertMode::new(options.invert_colors))
78            .await?;
79
80        di.write_command(ExitSleepMode).await?;
81        delay.delay_us(120_000).await;
82
83        di.write_command(SetDisplayOn).await?;
84
85        Ok(madctl)
86    }
87}