Skip to main content
RKTK API Docs RKTK Home Repo

rktk_drivers_common/display/
mipi_display.rs

1//! Generic MIPI display driver using `display-driver`
2
3use display_interface::DisplayError;
4use display_driver::{Area, FrameControl};
5use rktk::drivers::interface::display::DisplayDriver;
6use embedded_graphics::{
7    draw_target::DrawTarget,
8    geometry::OriginDimensions,
9    pixelcolor::{
10        raw::{BigEndian, RawU16},
11        Rgb565,
12    },
13    prelude::*,
14    framebuffer::Framebuffer,
15};
16
17pub struct MipiDisplayWrapper<const W: usize, const H: usize, const SIZE: usize> {
18    pub fb: Framebuffer<Rgb565, RawU16, BigEndian, W, H, SIZE>,
19}
20
21impl<const W: usize, const H: usize, const SIZE: usize> MipiDisplayWrapper<W, H, SIZE> {
22    pub fn new() -> Self {
23        Self {
24            fb: Framebuffer::new(),
25        }
26    }
27}
28
29impl<const W: usize, const H: usize, const SIZE: usize> Default for MipiDisplayWrapper<W, H, SIZE> {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34
35impl<const W: usize, const H: usize, const SIZE: usize> DrawTarget for MipiDisplayWrapper<W, H, SIZE> {
36    type Color = Rgb565;
37    type Error = core::convert::Infallible;
38
39    fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
40    where
41        I: IntoIterator<Item = Pixel<Self::Color>>,
42    {
43        self.fb.draw_iter(pixels)
44    }
45}
46
47impl<const W: usize, const H: usize, const SIZE: usize> OriginDimensions for MipiDisplayWrapper<W, H, SIZE> {
48    fn size(&self) -> Size {
49        Size::new(W as u32, H as u32)
50    }
51}
52
53pub struct MipiDisplayDriver<BUS, PANEL, const W: usize, const H: usize, const SIZE: usize>
54where
55    BUS: display_driver::DisplayBus,
56    PANEL: display_driver::Panel<BUS>,
57{
58    pub display: display_driver::DisplayDriver<BUS, PANEL>,
59    pub wrapper: MipiDisplayWrapper<W, H, SIZE>,
60}
61
62impl<BUS, PANEL, const W: usize, const H: usize, const SIZE: usize> MipiDisplayDriver<BUS, PANEL, W, H, SIZE>
63where
64    BUS: display_driver::DisplayBus,
65    PANEL: display_driver::Panel<BUS>,
66{
67    pub fn new(display: display_driver::DisplayDriver<BUS, PANEL>) -> Self {
68        Self {
69            display,
70            wrapper: MipiDisplayWrapper::new(),
71        }
72    }
73}
74
75impl<BUS, PANEL, const W: usize, const H: usize, const SIZE: usize> DisplayDriver
76    for MipiDisplayDriver<BUS, PANEL, W, H, SIZE>
77where
78    BUS: display_driver::DisplayBus + 'static,
79    PANEL: display_driver::Panel<BUS> + 'static,
80    BUS::Error: core::fmt::Debug + 'static,
81    display_driver::DisplayError<BUS::Error>: From<BUS::Error>,
82{
83    type Color = Rgb565;
84    type Display = MipiDisplayWrapper<W, H, SIZE>;
85
86    fn draw_target(&mut self) -> &mut Self::Display {
87        &mut self.wrapper
88    }
89
90    async fn init(&mut self) -> Result<(), DisplayError> {
91        self.display.init(&mut embassy_time::Delay)
92            .await
93            .map_err(|_| DisplayError::BusWriteError)
94    }
95
96    async fn flush(&mut self) -> Result<(), DisplayError> {
97        self.display.write_pixels(
98            Area::new(0, 0, W as u16, H as u16),
99            FrameControl::new_last(),
100            self.wrapper.fb.data(),
101        )
102        .await
103        .map_err(|_| DisplayError::BusWriteError)
104    }
105
106    async fn clear(&mut self) -> Result<(), DisplayError> {
107        let _ = self.wrapper.fb.clear(Rgb565::BLACK);
108        Ok(())
109    }
110
111    async fn set_display_on(&mut self, _on: bool) -> Result<(), DisplayError> {
112        Ok(())
113    }
114}