Skip to main content

display_driver_st7735/
lib.rs

1#![no_std]
2
3use embedded_hal::digital::OutputPin;
4use embedded_hal_async::delay::DelayNs;
5
6use display_driver::bus::DisplayBus;
7use display_driver::panel::initseq::{sequenced_init, InitStep};
8use display_driver::panel::reset::{LCDResetOption, LCDResetHandler};
9use display_driver::panel::{Orientation, Panel};
10
11use display_driver::{ColorFormat, DisplayError};
12
13use display_driver_mipidcs as mipidcs;
14use display_driver_mipidcs::{dcs_types::AddressMode, GenericMipidcs};
15
16pub mod consts;
17pub mod spec;
18
19use consts::*;
20pub use spec::St7735Spec;
21
22/// Driver for the ST7735 display controller.
23pub struct St7735<Spec, RST, B>
24where
25    Spec: St7735Spec,
26    RST: OutputPin,
27    B: DisplayBus,
28{
29    /// Inner generic driver for standard functionality.
30    inner: GenericMipidcs<B, Spec, RST>,
31}
32
33impl<Spec, RST, B> St7735<Spec, RST, B>
34where
35    Spec: St7735Spec,
36    RST: OutputPin,
37    B: DisplayBus,
38{
39    /// Creates a new driver instance.
40    pub fn new(reset_pin: LCDResetOption<RST>) -> Self {
41        Self {
42            inner: GenericMipidcs::new(reset_pin),
43        }
44    }
45
46    delegate::delegate! {
47        to self.inner {
48            pub async fn set_invert_mode(
49                &mut self,
50                bus: &mut B,
51                invert: bool,
52            ) -> Result<(), B::Error>;
53
54            pub async fn set_address_mode(
55                &mut self,
56                bus: &mut B,
57                address_mode: AddressMode,
58                orientation_if_changed: Option<Orientation>,
59            ) -> Result<(), B::Error>;
60
61            pub async fn set_bgr_order(&mut self, bus: &mut B, bgr: bool) -> Result<(), B::Error>;
62        }
63    }
64
65    /// Initialization sequence for ST7735.
66    const INIT_STEPS: &'static [InitStep<'static>] = &[
67        // Sleep Out
68        InitStep::SingleCommand(mipidcs::EXIT_SLEEP_MODE),
69        InitStep::DelayMs(120),
70        // Frame Rate Configuration
71        InitStep::CommandWithParams(FRMCTR1, &Spec::FRMCTR1_PARAMS),
72        InitStep::CommandWithParams(FRMCTR2, &Spec::FRMCTR2_PARAMS),
73        InitStep::CommandWithParams(FRMCTR3, &Spec::FRMCTR3_PARAMS),
74        InitStep::CommandWithParams(INVCTR, &[Spec::INVCTR_PARAM]),
75        // Power Configuration
76        InitStep::CommandWithParams(PWCTR1, &Spec::PWCTR1_PARAMS),
77        InitStep::CommandWithParams(PWCTR2, &[Spec::PWCTR2_PARAM]),
78        InitStep::CommandWithParams(PWCTR3, &Spec::PWCTR3_PARAMS),
79        InitStep::CommandWithParams(PWCTR4, &Spec::PWCTR4_PARAMS),
80        InitStep::CommandWithParams(PWCTR5, &Spec::PWCTR5_PARAMS),
81        InitStep::CommandWithParams(VMCTR1, &[Spec::VMCTR1_PARAM]),
82        // Invert mode
83        InitStep::select_cmd(
84            Spec::INVERTED,
85            mipidcs::ENTER_INVERT_MODE,
86            mipidcs::EXIT_INVERT_MODE,
87        ),
88        InitStep::CommandWithParams(
89            mipidcs::SET_ADDRESS_MODE,
90            &[if Spec::BGR {
91                AddressMode::BGR.bits()
92            } else {
93                0u8
94            }],
95        ),
96        // Gamma Correction
97        InitStep::maybe_cmd_with(GMCTRP1, Spec::GMCTRP1_PARAMS),
98        InitStep::maybe_cmd_with(GMCTRN1, Spec::GMCTRN1_PARAMS),
99        // Display On
100        InitStep::SingleCommand(mipidcs::SET_DISPLAY_ON),
101        InitStep::DelayMs(20), // Small delay after turning on
102    ];
103}
104
105impl<Spec, RST, B> Panel<B> for St7735<Spec, RST, B>
106where
107    Spec: St7735Spec,
108    RST: OutputPin,
109    B: DisplayBus,
110{
111    const CMD_LEN: usize = 1;
112    const PIXEL_WRITE_CMD: [u8; 4] = [mipidcs::WRITE_MEMORY_START, 0, 0, 0];
113
114    async fn init<D: DelayNs>(&mut self, bus: &mut B, mut delay: D) -> Result<(), B::Error> {
115        // Hardware Reset
116        let mut reseter = LCDResetHandler::new(
117            &mut self.inner.reset_pin,
118            bus,
119            &mut delay,
120            10,
121            120,
122            Some(&[mipidcs::SOFT_RESET]),
123        );
124        reseter.reset().await?;
125
126        self.inner.address_mode.set(AddressMode::BGR, Spec::BGR);
127
128        // Execute Initialization Sequence
129        // copied() only copies the items during iteration; it does not copy the entire sequence
130        sequenced_init(Self::INIT_STEPS.iter().copied(), &mut delay, bus).await
131    }
132
133    delegate::delegate! {
134        to self.inner {
135            fn width(&self) -> u16;
136
137            fn height(&self) -> u16;
138
139            fn size(&self) -> (u16, u16);
140
141            async fn set_window(
142                &mut self,
143                bus: &mut B,
144                x0: u16,
145                y0: u16,
146                x1: u16,
147                y1: u16,
148            ) -> Result<(), DisplayError<B::Error>>;
149
150            async fn set_color_format(
151                &mut self,
152                bus: &mut B,
153                color_format: ColorFormat,
154            ) -> Result<(), DisplayError<B::Error>>;
155
156            async fn set_orientation(
157                &mut self,
158                bus: &mut B,
159                orientation: Orientation,
160            ) -> Result<(), DisplayError<B::Error>>;
161        }
162    }
163}