1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use embedded_graphics::drawable::Pixel;
use embedded_graphics::geometry::Dimensions;
use embedded_graphics::image::{Image, ImageDimensions, IntoPixelIter};
use embedded_graphics::pixelcolor::raw::{RawData, RawU16};
use embedded_graphics::pixelcolor::Rgb565;
use embedded_graphics::prelude::{DrawTarget, Size};
use embedded_graphics::primitives::Rectangle;
use embedded_graphics::style::{PrimitiveStyle, Styled};

use embedded_hal::digital::v2::OutputPin;

use crate::{Error, Orientation, ST7789};
use display_interface::WriteOnlyDataCommand;

impl<DI, RST, PinE> ST7789<DI, RST>
where
    DI: WriteOnlyDataCommand,
    RST: OutputPin<Error = PinE>,
{
    fn fill_rect(
        &mut self,
        item: &dyn Dimensions,
        colors: &mut dyn Iterator<Item = u16>,
    ) -> Result<(), Error<PinE>> {
        let sx = item.top_left().x as u16;
        let sy = item.top_left().y as u16;
        let ex = item.bottom_right().x as u16;
        let ey = item.bottom_right().y as u16;

        self.set_pixels(sx, sy, ex, ey, colors)
    }
}

impl<DI, RST, PinE> DrawTarget<Rgb565> for ST7789<DI, RST>
where
    DI: WriteOnlyDataCommand,
    RST: OutputPin<Error = PinE>,
{
    type Error = Error<PinE>;

    fn draw_pixel(&mut self, pixel: Pixel<Rgb565>) -> Result<(), Self::Error> {
        let color = RawU16::from(pixel.1).into_inner();
        let x = pixel.0.x as u16;
        let y = pixel.0.y as u16;

        self.set_pixel(x, y, color)
    }

    #[cfg(feature = "batch")]
    fn draw_iter<T>(&mut self, item: T) -> Result<(), Self::Error>
    where
        T: IntoIterator<Item = Pixel<Rgb565>>,
    {
        use crate::batch::DrawBatch;

        self.draw_batch(item)
    }

    fn draw_rectangle(
        &mut self,
        item: &Styled<Rectangle, PrimitiveStyle<Rgb565>>,
    ) -> Result<(), Self::Error> {
        // filled rect can be rendered into frame window directly
        if item.style.fill_color.is_some() {
            let mut colors = item.into_iter().map(|p| RawU16::from(p.1).into_inner());

            self.fill_rect(item, &mut colors)
        } else if let Some(_color) = item.style.stroke_color {
            if item.style.stroke_width == 0 {
                return Ok(()); // nothing to draw
            }
            // let sw = item.style.stroke_width as u16;

            // TODO: construct rectangle as 4 frames
            self.draw_iter(item)
        } else {
            // if we don't know what this rect is, draw individual pixels
            self.draw_iter(item)
        }
    }

    fn draw_image<'a, 'b, I>(&mut self, item: &'a Image<'b, I, Rgb565>) -> Result<(), Self::Error>
    where
        &'b I: IntoPixelIter<Rgb565>,
        I: ImageDimensions,
    {
        // TODO: this is inconsistent in embedded-graphics between Rectangle and Image
        // See: https://github.com/jamwaffles/embedded-graphics/issues/182
        let sx = item.top_left().x as u16;
        let sy = item.top_left().y as u16;
        let ex = (item.bottom_right().x - 1) as u16;
        let ey = (item.bottom_right().y - 1) as u16;
        let colors = item.into_iter().map(|p| RawU16::from(p.1).into_inner());

        self.set_pixels(sx, sy, ex, ey, colors)
    }

    fn size(&self) -> Size {
        Size::new(self.size_x.into(), self.size_y.into()) // visible area, not RAM-pixel size
    }

    fn clear(&mut self, color: Rgb565) -> Result<(), Self::Error>
    where
        Self: Sized,
    {
        let colors = core::iter::repeat(RawU16::from(color).into_inner()).take(240 * 320); // blank entire HW RAM contents

        match self.orientation {
            Orientation::Portrait | Orientation::PortraitSwapped => {
                self.set_pixels(0, 0, 239, 319, colors)
            }
            Orientation::Landscape | Orientation::LandscapeSwapped => {
                self.set_pixels(0, 0, 319, 239, colors)
            }
        }
    }
}