From 139096297ba5dbb727fa2cf574553fac71075ef6 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 19 Oct 2018 14:36:43 +0200 Subject: [PATCH] Generalise graphics once more Change u16 positions to u32 to adapt to embedded graphics unsigned coordinates Furthermore added epd4in2 defaults graphics buffer --- src/drawing_old/mod.rs | 2 +- src/epd1in54/mod.rs | 26 +++++++------- src/epd2in9/mod.rs | 26 +++++++------- src/epd4in2/constants.rs | 4 +-- src/epd4in2/graphics.rs | 75 ++++++++++++---------------------------- src/epd4in2/mod.rs | 4 +-- src/graphics.rs | 63 +++++++++++++++++++++++++++++++++ src/interface.rs | 2 +- src/lib.rs | 2 +- src/traits.rs | 12 +++---- 10 files changed, 124 insertions(+), 92 deletions(-) diff --git a/src/drawing_old/mod.rs b/src/drawing_old/mod.rs index 979f8e7..a9149b3 100644 --- a/src/drawing_old/mod.rs +++ b/src/drawing_old/mod.rs @@ -44,7 +44,7 @@ impl Display { } } -#[allow(dead_code)] + pub struct Graphics<'a> { width: u16, height: u16, diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 2d9d6ec..5a61fbb 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -19,8 +19,8 @@ //! epd4in2.sleep(); //! ``` -const WIDTH: u16 = 200; -const HEIGHT: u16 = 200; +const WIDTH: u32 = 200; +const HEIGHT: u32 = 200; //const DPI: u16 = 184; const DEFAULT_BACKGROUND_COLOR: Color = Color::White; @@ -109,11 +109,11 @@ where DC: OutputPin, RST: OutputPin, { - fn width(&self) -> u16 { + fn width(&self) -> u32 { WIDTH } - fn height(&self) -> u16 { + fn height(&self) -> u32 { HEIGHT } @@ -157,10 +157,10 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - x: u16, - y: u16, - width: u16, - height: u16, + x: u32, + y: u32, + width: u32, + height: u32, ) -> Result<(), SPI::Error> { self.set_ram_area(spi, x, y, x + width, y + height)?; self.set_ram_counter(spi, x, y)?; @@ -227,10 +227,10 @@ where pub(crate) fn set_ram_area( &mut self, spi: &mut SPI, - start_x: u16, - start_y: u16, - end_x: u16, - end_y: u16, + start_x: u32, + start_y: u32, + end_x: u32, + end_y: u32, ) -> Result<(), SPI::Error> { assert!(start_x < end_x); assert!(start_y < end_y); @@ -251,7 +251,7 @@ where ) } - pub(crate) fn set_ram_counter(&mut self, spi: &mut SPI, x: u16, y: u16) -> Result<(), SPI::Error> { + pub(crate) fn set_ram_counter(&mut self, spi: &mut SPI, x: u32, y: u32) -> Result<(), SPI::Error> { // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant self.interface.cmd_with_data(spi, Command::SET_RAM_X_ADDRESS_COUNTER, &[(x >> 3) as u8])?; diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 4fd3b2a..7e877db 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -19,8 +19,8 @@ //! epd4in2.sleep(); //! ``` -const WIDTH: u16 = 128; -const HEIGHT: u16 = 296; +const WIDTH: u32 = 128; +const HEIGHT: u32 = 296; const DEFAULT_BACKGROUND_COLOR: Color = Color::White; use hal::{ @@ -102,11 +102,11 @@ where DC: OutputPin, RST: OutputPin, { - fn width(&self) -> u16 { + fn width(&self) -> u32 { WIDTH } - fn height(&self) -> u16 { + fn height(&self) -> u32 { HEIGHT } @@ -151,10 +151,10 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - x: u16, - y: u16, - width: u16, - height: u16, + x: u32, + y: u32, + width: u32, + height: u32, ) -> Result<(), SPI::Error> { self.set_ram_area(spi, x, y, x + width, y + height)?; self.set_ram_counter(spi, x, y)?; @@ -220,10 +220,10 @@ where pub(crate) fn set_ram_area( &mut self, spi: &mut SPI, - start_x: u16, - start_y: u16, - end_x: u16, - end_y: u16, + start_x: u32, + start_y: u32, + end_x: u32, + end_y: u32, ) -> Result<(), SPI::Error> { assert!(start_x < end_x); assert!(start_y < end_y); @@ -242,7 +242,7 @@ where ) } - pub(crate) fn set_ram_counter(&mut self, spi: &mut SPI, x: u16, y: u16) -> Result<(), SPI::Error> { + pub(crate) fn set_ram_counter(&mut self, spi: &mut SPI, x: u32, y: u32) -> Result<(), SPI::Error> { // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant self.interface.cmd_with_data(spi, Command::SET_RAM_X_ADDRESS_COUNTER, &[(x >> 3) as u8])?; diff --git a/src/epd4in2/constants.rs b/src/epd4in2/constants.rs index 2e484a4..47bf5f7 100644 --- a/src/epd4in2/constants.rs +++ b/src/epd4in2/constants.rs @@ -1,7 +1,7 @@ use color::Color; -pub(crate) const WIDTH: u16 = 400; -pub(crate) const HEIGHT: u16 = 300; +pub(crate) const WIDTH: u32 = 400; +pub(crate) const HEIGHT: u32 = 300; pub(crate) const DEFAULT_BACKGROUND_COLOR: Color = Color::White; pub(crate) const LUT_VCOM0: [u8; 44] = [ diff --git a/src/epd4in2/graphics.rs b/src/epd4in2/graphics.rs index 7650b85..9980867 100644 --- a/src/epd4in2/graphics.rs +++ b/src/epd4in2/graphics.rs @@ -7,84 +7,48 @@ use graphics::{ use color::Color; use embedded_graphics::prelude::*; +use graphics::Graphics; + use epd4in2::constants::{DEFAULT_BACKGROUND_COLOR, WIDTH, HEIGHT}; -pub struct DisplayEink42BlackWhite { - buffer: [u8; WIDTH as usize * HEIGHT as usize / 8], - rotation: DisplayRotation, +pub struct DisplayEink4in2BlackWhite { + pub buffer: [u8; WIDTH as usize * HEIGHT as usize / 8], } -impl Default for DisplayEink42BlackWhite { +impl Default for DisplayEink4in2BlackWhite { fn default() -> Self { - DisplayEink42BlackWhite { + DisplayEink4in2BlackWhite { buffer: [ DEFAULT_BACKGROUND_COLOR.get_byte_value(); WIDTH as usize * HEIGHT as usize / 8 - ], - rotation: DisplayRotation::default() + ] } } } -impl Display for DisplayEink42BlackWhite { - fn buffer(&self) -> &[u8] { - &self.buffer - } - fn set_rotation(&mut self, rotation: DisplayRotation) { - self.rotation = rotation; - } - fn rotation(&self) -> DisplayRotation { - self.rotation - } -} -impl Drawing for DisplayEink42BlackWhite { - fn draw(&mut self, item_pixels: T) - where - T: Iterator> - { - let width = WIDTH as u32; - let height = HEIGHT as u32; - - for Pixel(UnsignedCoord(x,y), color) in item_pixels { - if outside_display(x, y, width, height, self.rotation) { - return; - } - - let (idx, bit) = rotation(x, y, width, height, self.rotation); - - let idx = idx as usize; - match color { - Color::Black => { - self.buffer[idx] &= !bit; - } - Color::White => { - self.buffer[idx] |= bit; - } - } - } - } -} - #[cfg(test)] mod tests { use super::*; use epd4in2; + use graphics::Graphics; use embedded_graphics::coord::Coord; use embedded_graphics::primitives::Line; // test buffer length #[test] fn graphics_size() { - let display = DisplayEink42BlackWhite::default(); + let mut display4in2 = DisplayEink4in2BlackWhite::default(); + let display = Graphics::new(WIDTH, HEIGHT, &mut display4in2.buffer); assert_eq!(display.buffer().len(), 15000); } // test default background color on all bytes #[test] fn graphics_default() { - let display = DisplayEink42BlackWhite::default(); + let mut display4in2 = DisplayEink4in2BlackWhite::default(); + let mut display = Graphics::new(WIDTH, HEIGHT, &mut display4in2.buffer); use epd4in2; for &byte in display.buffer() { assert_eq!(byte, epd4in2::constants::DEFAULT_BACKGROUND_COLOR.get_byte_value()); @@ -93,7 +57,8 @@ mod tests { #[test] fn graphics_rotation_0() { - let mut display = DisplayEink42BlackWhite::default(); + let mut display4in2 = DisplayEink4in2BlackWhite::default(); + let mut display = Graphics::new(WIDTH, HEIGHT, &mut display4in2.buffer); display.draw( Line::new(Coord::new(0, 0), Coord::new(7, 0)) .with_stroke(Some(Color::Black)) @@ -111,7 +76,8 @@ mod tests { #[test] fn graphics_rotation_90() { - let mut display = DisplayEink42BlackWhite::default(); + let mut display4in2 = DisplayEink4in2BlackWhite::default(); + let mut display = Graphics::new(WIDTH, HEIGHT, &mut display4in2.buffer); display.set_rotation(DisplayRotation::Rotate90); display.draw( Line::new(Coord::new(0, 392), Coord::new(0, 399)) @@ -130,7 +96,8 @@ mod tests { #[test] fn graphics_rotation_180() { - let mut display = DisplayEink42BlackWhite::default(); + let mut display4in2 = DisplayEink4in2BlackWhite::default(); + let mut display = Graphics::new(WIDTH, HEIGHT, &mut display4in2.buffer); display.set_rotation(DisplayRotation::Rotate180); display.draw( Line::new(Coord::new(392, 299), Coord::new(399, 299)) @@ -153,7 +120,8 @@ mod tests { #[test] fn graphics_rotation_270() { - let mut display = DisplayEink42BlackWhite::default(); + let mut display4in2 = DisplayEink4in2BlackWhite::default(); + let mut display = Graphics::new(WIDTH, HEIGHT, &mut display4in2.buffer); display.set_rotation(DisplayRotation::Rotate270); display.draw( Line::new(Coord::new(299, 0), Coord::new(299, 7)) @@ -173,4 +141,5 @@ mod tests { } } -} \ No newline at end of file +} + diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 8e9306c..fbddc57 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -278,11 +278,11 @@ where &self.color } - fn width(&self) -> u16 { + fn width(&self) -> u32 { WIDTH } - fn height(&self) -> u16 { + fn height(&self) -> u32 { HEIGHT } } diff --git a/src/graphics.rs b/src/graphics.rs index eff4641..a477985 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -1,3 +1,6 @@ +use color::Color; +use embedded_graphics::prelude::*; + /// Displayrotation #[derive(Clone, Copy)] pub enum DisplayRotation { @@ -16,6 +19,7 @@ impl Default for DisplayRotation { DisplayRotation::Rotate0 } } +use epd4in2::constants::{DEFAULT_BACKGROUND_COLOR, WIDTH, HEIGHT}; pub trait Display { fn buffer(&self) -> &[u8]; @@ -23,6 +27,65 @@ pub trait Display { fn rotation(&self) -> DisplayRotation; } +pub struct Graphics<'a> { + pub(crate) width: u32, + pub(crate) height: u32, + pub(crate) rotation: DisplayRotation, + pub(crate) buffer: &'a mut [u8], //buffer: Box//[u8; 15000] +} + +impl<'a> Graphics<'a> { + pub fn new(width: u32, height: u32, buffer: &'a mut [u8]) -> Graphics<'a> { + let len = buffer.len() as u32; + assert!(width / 8 * height >= len); + Graphics { + width, + height, + rotation: DisplayRotation::default(), + buffer, + } + } + + pub fn buffer(&self) -> &[u8] { + &self.buffer + } + pub fn set_rotation(&mut self, rotation: DisplayRotation) { + self.rotation = rotation; + } + pub fn rotation(&self) -> DisplayRotation { + self.rotation + } +} + + +impl<'a> Drawing for Graphics<'a> { + fn draw(&mut self, item_pixels: T) + where + T: Iterator> + { + let width = WIDTH as u32; + let height = HEIGHT as u32; + + for Pixel(UnsignedCoord(x,y), color) in item_pixels { + if outside_display(x, y, width, height, self.rotation) { + return; + } + + let (idx, bit) = rotation(x, y, width, height, self.rotation); + + let idx = idx as usize; + match color { + Color::Black => { + self.buffer[idx] &= !bit; + } + Color::White => { + self.buffer[idx] |= bit; + } + } + } + } +} + pub(crate) fn outside_display(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotation) -> bool { match rotation { diff --git a/src/interface.rs b/src/interface.rs index 4e07baf..dd8a5da 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -84,7 +84,7 @@ where &mut self, spi: &mut SPI, val: u8, - repetitions: u16, + repetitions: u32, ) -> Result<(), SPI::Error> { // high for data self.dc.set_high(); diff --git a/src/lib.rs b/src/lib.rs index d23d6b5..359b05d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,7 +67,7 @@ mod epd4in2; #[cfg(feature = "epd4in2")] pub use epd4in2::EPD4in2; #[cfg(feature = "epd4in2")] -pub use epd4in2::graphics::DisplayEink42BlackWhite; +pub use epd4in2::graphics::DisplayEink4in2BlackWhite; #[cfg(feature = "epd1in54")] mod epd1in54; diff --git a/src/traits.rs b/src/traits.rs index a8537a4..be64cb6 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -83,10 +83,10 @@ where fn background_color(&self) -> &Color; /// Get the width of the display - fn width(&self) -> u16; + fn width(&self) -> u32; /// Get the height of the display - fn height(&self) -> u16; + fn height(&self) -> u32; /// Transmit a full frame to the SRAM of the EPD fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; @@ -98,10 +98,10 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - x: u16, - y: u16, - width: u16, - height: u16, + x: u32, + y: u32, + width: u32, + height: u32, ) -> Result<(), SPI::Error>; /// Displays the frame data from SRAM