st7789_driver/
graphics.rs1use embedded_graphics_core::pixelcolor::Rgb565;
2use embedded_graphics_core::prelude::{DrawTarget, IntoStorage, Point, Size};
3use embedded_graphics_core::{
4 pixelcolor::raw::{RawData, RawU16},
5 primitives::Rectangle,
6};
7use embedded_graphics_core::{prelude::OriginDimensions, Pixel};
8
9use embedded_hal::digital::v2::OutputPin;
10
11use crate::{Error, Orientation, ST7789};
12use display_interface::WriteOnlyDataCommand;
13
14impl<DI, RST, BL, PinE> ST7789<DI, RST, BL>
15where
16 DI: WriteOnlyDataCommand,
17 RST: OutputPin<Error = PinE>,
18 BL: OutputPin<Error = PinE>,
19{
20 fn framebuffer_bounding_box(&self) -> Rectangle {
22 let size = match self.orientation {
23 Orientation::Portrait | Orientation::PortraitSwapped => Size::new(240, 320),
24 Orientation::Landscape | Orientation::LandscapeSwapped => Size::new(320, 240),
25 };
26
27 Rectangle::new(Point::zero(), size)
28 }
29}
30
31impl<DI, RST, BL, PinE> DrawTarget for ST7789<DI, RST, BL>
32where
33 DI: WriteOnlyDataCommand,
34 RST: OutputPin<Error = PinE>,
35 BL: OutputPin<Error = PinE>,
36{
37 type Error = Error<PinE>;
38 type Color = Rgb565;
39
40 #[cfg(not(feature = "batch"))]
41 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
42 where
43 I: IntoIterator<Item = Pixel<Self::Color>>,
44 {
45 for pixel in pixels {
46 let color = RawU16::from(pixel.1).into_inner();
47 let x = pixel.0.x as u16;
48 let y = pixel.0.y as u16;
49
50 self.set_pixel(x, y, color)?;
51 }
52
53 Ok(())
54 }
55
56 #[cfg(feature = "batch")]
57 fn draw_iter<T>(&mut self, item: T) -> Result<(), Self::Error>
58 where
59 T: IntoIterator<Item = Pixel<Rgb565>>,
60 {
61 use crate::batch::DrawBatch;
62
63 self.draw_batch(item)
64 }
65
66 fn fill_contiguous<I>(&mut self, area: &Rectangle, colors: I) -> Result<(), Self::Error>
67 where
68 I: IntoIterator<Item = Self::Color>,
69 {
70 if let Some(bottom_right) = area.bottom_right() {
71 let mut count = 0u32;
72 let max = area.size.width * area.size.height;
73
74 let mut colors = colors
75 .into_iter()
76 .take_while(|_| {
77 count += 1;
78 count <= max
79 })
80 .map(|color| RawU16::from(color).into_inner());
81
82 let sx = area.top_left.x as u16;
83 let sy = area.top_left.y as u16;
84 let ex = bottom_right.x as u16;
85 let ey = bottom_right.y as u16;
86 self.set_pixels(sx, sy, ex, ey, &mut colors)
87 } else {
88 Ok(())
90 }
91 }
92
93 fn fill_solid(&mut self, area: &Rectangle, color: Self::Color) -> Result<(), Self::Error> {
94 let area = area.intersection(&self.framebuffer_bounding_box());
95
96 if let Some(bottom_right) = area.bottom_right() {
97 let mut count = 0u32;
98 let max = area.size.width * area.size.height;
99
100 let mut colors = core::iter::repeat(color.into_storage()).take_while(|_| {
101 count += 1;
102 count <= max
103 });
104
105 let sx = area.top_left.x as u16;
106 let sy = area.top_left.y as u16;
107 let ex = bottom_right.x as u16;
108 let ey = bottom_right.y as u16;
109 self.set_pixels(sx, sy, ex, ey, &mut colors)
110 } else {
111 Ok(())
113 }
114 }
115
116 fn clear(&mut self, color: Rgb565) -> Result<(), Self::Error>
117 where
118 Self: Sized,
119 {
120 let color16 = RawU16::from(color).into_inner();
121 const DIM1: u16 = 240;
122 const DIM2: u16 = 320;
123 let colors = (0..(DIM1 as u32 * DIM2 as u32)).map(|_| color16); match self.orientation {
126 Orientation::Portrait | Orientation::PortraitSwapped => {
127 self.set_pixels(0, 0, DIM1 - 1, DIM2 - 1, colors)
128 }
129 Orientation::Landscape | Orientation::LandscapeSwapped => {
130 self.set_pixels(0, 0, DIM2 - 1, DIM1 - 1, colors)
131 }
132 }
133 }
134}
135
136impl<DI, RST, BL, PinE> OriginDimensions for ST7789<DI, RST, BL>
137where
138 DI: WriteOnlyDataCommand,
139 RST: OutputPin<Error = PinE>,
140 BL: OutputPin<Error = PinE>,
141{
142 fn size(&self) -> Size {
143 Size::new(self.size_x.into(), self.size_y.into()) }
145}