From 18a0ac85b3330e83f55c788f3adf09b7e572166e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Katona?= Date: Mon, 21 Oct 2024 15:52:12 -0700 Subject: [PATCH 1/8] add Model::write_pixels_raw_u8() --- mipidsi/src/models.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/mipidsi/src/models.rs b/mipidsi/src/models.rs index 5662482..1db6291 100644 --- a/mipidsi/src/models.rs +++ b/mipidsi/src/models.rs @@ -1,12 +1,11 @@ //! Display models. use crate::{ - dcs::{Dcs, SetAddressMode}, - error::Error, - error::InitError, + dcs::{Dcs, SetAddressMode, WriteMemoryStart}, + error::{Error, InitError}, options::ModelOptions, }; -use display_interface::WriteOnlyDataCommand; +use display_interface::{DataFormat, WriteOnlyDataCommand}; use embedded_graphics_core::prelude::RgbColor; use embedded_hal::{delay::DelayNs, digital::OutputPin}; @@ -74,4 +73,18 @@ pub trait Model { where DI: WriteOnlyDataCommand, I: IntoIterator; + + /// Writes raw &[u8] buffer to the display IC via the given display interface. + /// + /// No pixel color format conversion, raw data is passed on directly. + fn write_pixels_raw_u8(&mut self, dcs: &mut Dcs, raw_buf: &[u8]) -> Result<(), Error> + where + DI: WriteOnlyDataCommand, + { + dcs.write_command(WriteMemoryStart)?; + + let buf = DataFormat::U8(raw_buf); + dcs.di.send_data(buf)?; + Ok(()) + } } From 973369c8fa232f64ee400036b56d561a8913fccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Katona?= Date: Mon, 21 Oct 2024 15:59:00 -0700 Subject: [PATCH 2/8] add Display::set_pixels_raw_u8() --- mipidsi/src/lib.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/mipidsi/src/lib.rs b/mipidsi/src/lib.rs index c4436e6..bd6b37b 100644 --- a/mipidsi/src/lib.rs +++ b/mipidsi/src/lib.rs @@ -239,6 +239,39 @@ where Ok(()) } + /// + /// Sets pixel colors in a rectangular region. + /// + /// The color values from the `raw_buf` slice will be drawn to the given region starting + /// at the top left corner and continuing, row first, to the bottom right corner. No bounds + /// checking is performed on the `raw_buf` slice and drawing will wrap around if the + /// slice has more color values than the number of pixels in the given region. + /// + /// This is a low level function, which isn't intended to be used in regular user code. + /// Consider using the [`draw_image`](https://TODO) + /// function from the `embedded-graphics` crate as an alternative instead (TODO) + /// + /// # Arguments + /// + /// * `sx` - x coordinate start + /// * `sy` - y coordinate start + /// * `ex` - x coordinate end + /// * `ey` - y coordinate end + /// * `raw_buf` - &[u8] buffer of raw pixel data in the format expected by the display. + pub fn set_pixels_raw_u8( + &mut self, + sx: u16, + sy: u16, + ex: u16, + ey: u16, + raw_buf: &[u8], + ) -> Result<(), Error> { + self.set_address_window(sx, sy, ex, ey)?; + self.model.write_pixels_raw_u8(&mut self.dcs, raw_buf)?; + + Ok(()) + } + /// Sets the vertical scroll region. /// /// The `top_fixed_area` and `bottom_fixed_area` arguments can be used to From e6633384cd632515c9b98229d34a50d589c648d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Katona?= Date: Thu, 24 Oct 2024 09:38:01 -0700 Subject: [PATCH 3/8] remove draw_image comment --- mipidsi/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/mipidsi/src/lib.rs b/mipidsi/src/lib.rs index bd6b37b..0acfebe 100644 --- a/mipidsi/src/lib.rs +++ b/mipidsi/src/lib.rs @@ -248,8 +248,6 @@ where /// slice has more color values than the number of pixels in the given region. /// /// This is a low level function, which isn't intended to be used in regular user code. - /// Consider using the [`draw_image`](https://TODO) - /// function from the `embedded-graphics` crate as an alternative instead (TODO) /// /// # Arguments /// From 0a5ed28784fd14f234ea2434c51abb1c8ec5923d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Katona?= Date: Thu, 24 Oct 2024 09:57:35 -0700 Subject: [PATCH 4/8] add doc warnings --- mipidsi/src/lib.rs | 18 +++++++++++++++++- mipidsi/src/models.rs | 10 +++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/mipidsi/src/lib.rs b/mipidsi/src/lib.rs index 0acfebe..77789f3 100644 --- a/mipidsi/src/lib.rs +++ b/mipidsi/src/lib.rs @@ -222,6 +222,10 @@ where /// * `ex` - x coordinate end /// * `ey` - y coordinate end /// * `colors` - anything that can provide `IntoIterator` to iterate over pixel data + ///
+ /// The `ex`and `ey` coordinates are inclusive. For example when using a rectangle + /// of size `320x240`, one would use `319` an `239` as `ex` and `ey` values. + ///
pub fn set_pixels( &mut self, sx: u16, @@ -255,7 +259,19 @@ where /// * `sy` - y coordinate start /// * `ex` - x coordinate end /// * `ey` - y coordinate end - /// * `raw_buf` - &[u8] buffer of raw pixel data in the format expected by the display. + /// * `raw_buf` - `&[u8]` buffer of raw pixel data in the format expected by the display. + ///
+ /// This method requires the raw_buf data to be in the correct endianness + /// and format expected by the display. + /// + /// The method won't work with a 16bit display-interface-gpio, because it + /// pads the each byte to a u16 instead of converting each two byte chunk + /// into a u16. [See here for more info](https://github.com/therealprof/display-interface/blob/8fca041b0288740678f16c1d05cce21bd3867ee5/parallel-gpio/src/lib.rs#L267) + ///
+ ///
+ /// The ex and ey coordinates are inclusive. For example when using a rectangle + /// of size 320x240, one would use 319 an 239 as ex and ey values. + ///
pub fn set_pixels_raw_u8( &mut self, sx: u16, diff --git a/mipidsi/src/models.rs b/mipidsi/src/models.rs index 1db6291..6681e89 100644 --- a/mipidsi/src/models.rs +++ b/mipidsi/src/models.rs @@ -74,9 +74,17 @@ pub trait Model { DI: WriteOnlyDataCommand, I: IntoIterator; - /// Writes raw &[u8] buffer to the display IC via the given display interface. + /// Writes raw `&[u8]` buffer to the display IC via the given display interface. /// /// No pixel color format conversion, raw data is passed on directly. + ///
+ /// This method requires the `raw_buf` data to be in the correct endianness + /// and format expected by the display. + /// + /// The method won't work with a 16bit display-interface-gpio, because it + /// pads the each byte to a u16 instead of converting each two byte chunk + /// into a u16. [See here for more info](https://github.com/therealprof/display-interface/blob/8fca041b0288740678f16c1d05cce21bd3867ee5/parallel-gpio/src/lib.rs#L267) + ///
fn write_pixels_raw_u8(&mut self, dcs: &mut Dcs, raw_buf: &[u8]) -> Result<(), Error> where DI: WriteOnlyDataCommand, From 882ea0ca7a8c85c78f86a6f2899d87eabb960c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Katona?= Date: Thu, 24 Oct 2024 10:04:40 -0700 Subject: [PATCH 5/8] bump esp32-c3 dependencies to fix example --- mipidsi/examples/spi-ili9486-esp32-c3/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mipidsi/examples/spi-ili9486-esp32-c3/Cargo.toml b/mipidsi/examples/spi-ili9486-esp32-c3/Cargo.toml index 823a6c2..1b8166b 100644 --- a/mipidsi/examples/spi-ili9486-esp32-c3/Cargo.toml +++ b/mipidsi/examples/spi-ili9486-esp32-c3/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] mipidsi = { path = "../../" } hal = { package = "esp-hal", version = "0.17.0", features = ["esp32c3"] } -esp-backtrace = { version = "0.11.1", features = ["esp32c3", "panic-handler", "exception-handler", "println"] } -esp-println = { version = "0.9.1", features = ["esp32c3"] } +esp-backtrace = { version = "0.14", features = ["esp32c3", "panic-handler", "exception-handler", "println"] } +esp-println = { version = "0.12", features = ["esp32c3"] } embedded-graphics = "0.8.0" display-interface-spi = "0.5.0" fugit = "0.3.7" From ca975406933ed6901bb202ffa0e6421c7fe39305 Mon Sep 17 00:00:00 2001 From: Ales Katona Date: Fri, 25 Oct 2024 10:56:25 -0700 Subject: [PATCH 6/8] rename to set_pixels_from_buffer + remove Model method --- mipidsi/src/lib.rs | 64 ++++++++++++++++++++++++++++--------------- mipidsi/src/models.rs | 26 ++---------------- 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/mipidsi/src/lib.rs b/mipidsi/src/lib.rs index 77789f3..43c9ce0 100644 --- a/mipidsi/src/lib.rs +++ b/mipidsi/src/lib.rs @@ -96,8 +96,8 @@ //! ## Troubleshooting //! See [document](https://github.com/almindor/mipidsi/blob/master/docs/TROUBLESHOOTING.md) -use dcs::Dcs; -use display_interface::WriteOnlyDataCommand; +use dcs::{Dcs, WriteMemoryStart}; +use display_interface::{DataFormat, WriteOnlyDataCommand}; pub mod error; use error::Error; @@ -243,36 +243,53 @@ where Ok(()) } + /// Copies raw pixel data to a rectangular region of the framebuffer. /// - /// Sets pixel colors in a rectangular region. + /// This method writes the pixel data stored in the `raw_buf` slice to the + /// specified rectangular region within the display controller's + /// framebuffer. If `raw_buf` contains more data than required to fill the + /// region, writing will wrap around to the top left corner after reaching + /// the bottom right corner. /// - /// The color values from the `raw_buf` slice will be drawn to the given region starting - /// at the top left corner and continuing, row first, to the bottom right corner. No bounds - /// checking is performed on the `raw_buf` slice and drawing will wrap around if the - /// slice has more color values than the number of pixels in the given region. + ///
+ /// + /// This method is intended for advanced use cases where low level access to + /// the displays framebuffer is required for performance reasons. The + /// caller must ensure the raw pixel data in `raw_buf` has the correct + /// format and endianness. /// - /// This is a low level function, which isn't intended to be used in regular user code. + /// For all other use cases it is recommended to instead use + /// [`embedded-graphics`](https://docs.rs/embedded-graphics/latest/embedded_graphics/) + /// to draw to the display. + /// + ///
+ /// + ///
+ /// + /// The method might not work the same for all `display-interface`s and is + /// known to not work as expected when used with a + /// [`PGPIO16BitInterface`](https://docs.rs/display-interface-parallel-gpio/latest/display_interface_parallel_gpio/struct.PGPIO16BitInterface.html) + /// from the `display-interface-gpio` crate. + /// + ///
/// /// # Arguments /// /// * `sx` - x coordinate start /// * `sy` - y coordinate start - /// * `ex` - x coordinate end - /// * `ey` - y coordinate end - /// * `raw_buf` - `&[u8]` buffer of raw pixel data in the format expected by the display. - ///
- /// This method requires the raw_buf data to be in the correct endianness - /// and format expected by the display. + /// * `ex` - x coordinate end (inclusive) + /// * `ey` - y coordinate end (inclusive) + /// * `raw_buf` - `&[u8]` buffer of raw pixel data in the format expected by the display /// - /// The method won't work with a 16bit display-interface-gpio, because it - /// pads the each byte to a u16 instead of converting each two byte chunk - /// into a u16. [See here for more info](https://github.com/therealprof/display-interface/blob/8fca041b0288740678f16c1d05cce21bd3867ee5/parallel-gpio/src/lib.rs#L267) - ///
///
- /// The ex and ey coordinates are inclusive. For example when using a rectangle - /// of size 320x240, one would use 319 an 239 as ex and ey values. + /// + /// The end values of the X and Y coordinate ranges are inclusive, and no + /// bounds checking is performed on these values. Using out of range values + /// (e.g., passing `320` instead of `319` for a 320 pixel wide display) will + /// result in undefined behavior. + /// ///
- pub fn set_pixels_raw_u8( + pub fn set_pixels_from_buffer( &mut self, sx: u16, sy: u16, @@ -281,7 +298,10 @@ where raw_buf: &[u8], ) -> Result<(), Error> { self.set_address_window(sx, sy, ex, ey)?; - self.model.write_pixels_raw_u8(&mut self.dcs, raw_buf)?; + + self.dcs.write_command(WriteMemoryStart)?; + + self.dcs.di.send_data(DataFormat::U8(raw_buf))?; Ok(()) } diff --git a/mipidsi/src/models.rs b/mipidsi/src/models.rs index 6681e89..7236f91 100644 --- a/mipidsi/src/models.rs +++ b/mipidsi/src/models.rs @@ -1,11 +1,11 @@ //! Display models. use crate::{ - dcs::{Dcs, SetAddressMode, WriteMemoryStart}, + dcs::{Dcs, SetAddressMode}, error::{Error, InitError}, options::ModelOptions, }; -use display_interface::{DataFormat, WriteOnlyDataCommand}; +use display_interface::WriteOnlyDataCommand; use embedded_graphics_core::prelude::RgbColor; use embedded_hal::{delay::DelayNs, digital::OutputPin}; @@ -73,26 +73,4 @@ pub trait Model { where DI: WriteOnlyDataCommand, I: IntoIterator; - - /// Writes raw `&[u8]` buffer to the display IC via the given display interface. - /// - /// No pixel color format conversion, raw data is passed on directly. - ///
- /// This method requires the `raw_buf` data to be in the correct endianness - /// and format expected by the display. - /// - /// The method won't work with a 16bit display-interface-gpio, because it - /// pads the each byte to a u16 instead of converting each two byte chunk - /// into a u16. [See here for more info](https://github.com/therealprof/display-interface/blob/8fca041b0288740678f16c1d05cce21bd3867ee5/parallel-gpio/src/lib.rs#L267) - ///
- fn write_pixels_raw_u8(&mut self, dcs: &mut Dcs, raw_buf: &[u8]) -> Result<(), Error> - where - DI: WriteOnlyDataCommand, - { - dcs.write_command(WriteMemoryStart)?; - - let buf = DataFormat::U8(raw_buf); - dcs.di.send_data(buf)?; - Ok(()) - } } From 29f9f351a56f18292b78dd26867852e572d0f690 Mon Sep 17 00:00:00 2001 From: Ales Katona Date: Fri, 25 Oct 2024 10:58:15 -0700 Subject: [PATCH 7/8] fix set_pixels warning doc comment --- mipidsi/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mipidsi/src/lib.rs b/mipidsi/src/lib.rs index 43c9ce0..871983a 100644 --- a/mipidsi/src/lib.rs +++ b/mipidsi/src/lib.rs @@ -223,8 +223,12 @@ where /// * `ey` - y coordinate end /// * `colors` - anything that can provide `IntoIterator` to iterate over pixel data ///
- /// The `ex`and `ey` coordinates are inclusive. For example when using a rectangle - /// of size `320x240`, one would use `319` an `239` as `ex` and `ey` values. + /// + /// The end values of the X and Y coordinate ranges are inclusive, and no + /// bounds checking is performed on these values. Using out of range values + /// (e.g., passing `320` instead of `319` for a 320 pixel wide display) will + /// result in undefined behavior. + /// ///
pub fn set_pixels( &mut self, From 4b3f22962ae7f196e19ff98feff3dbe12d19be7f Mon Sep 17 00:00:00 2001 From: Ales Katona Date: Fri, 25 Oct 2024 13:25:02 -0700 Subject: [PATCH 8/8] add CHANGELOG entry --- mipidsi/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mipidsi/CHANGELOG.md b/mipidsi/CHANGELOG.md index 6f77f4c..1d41466 100644 --- a/mipidsi/CHANGELOG.md +++ b/mipidsi/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + +- added `Display::set_pixels_from_buffer` to allow high performance display writes + ## [v0.8.0] - 2024-05-24 ### Added