From dc9a389b794f03c2d5244c7ae42ba1084c824def Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Mon, 1 Jun 2020 14:30:03 +0200 Subject: [PATCH] Rough first conversion to display-interface Tested with SPI display Signed-off-by: Daniel Egger --- Cargo.toml | 1 + src/gpio.rs | 122 ------------------------------------------------ src/graphics.rs | 9 ++-- src/lib.rs | 70 ++++++++++----------------- src/spi.rs | 62 ------------------------ 5 files changed, 30 insertions(+), 234 deletions(-) delete mode 100644 src/gpio.rs diff --git a/Cargo.toml b/Cargo.toml index 8355de2..77e4647 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ edition = "2018" [dependencies] +display-interface = "0.4" embedded-hal = "0.2.3" [dependencies.embedded-graphics] diff --git a/src/gpio.rs b/src/gpio.rs deleted file mode 100644 index 1c59920..0000000 --- a/src/gpio.rs +++ /dev/null @@ -1,122 +0,0 @@ -use crate::{Error, Interface}; -use embedded_hal::digital::v2::OutputPin; - -/// `Interface` implementation for GPIO interfaces -pub struct Gpio8Interface<'a, DATA, CSX, WRX, RDX, DCX> { - data_pins: &'a mut [DATA; 8], - csx: CSX, - wrx: WRX, - rdx: RDX, - dcx: DCX, -} - -impl<'a, CSX, WRX, RDX, DCX, PinE> - Gpio8Interface<'_, &'a mut dyn OutputPin, CSX, WRX, RDX, DCX> -where - CSX: OutputPin, - WRX: OutputPin, - RDX: OutputPin, - DCX: OutputPin, -{ - /// Create a new Gpio8Interface - /// - /// Example useage: - /// - /// let csx = gpioc.pc2.into_push_pull_output(); - /// let wrx = gpiod.pd13.into_push_pull_output(); - /// let rdx = gpiod.pd12.into_push_pull_output(); - /// let dcx = gpiof.pf7.into_push_pull_output(); - /// - /// let mut data_pins: [&mut dyn OutputPin; 8] = [ - /// &mut gpiod.pd6.into_push_pull_output(), - /// &mut gpiog.pg11.into_push_pull_output(), - /// ... - /// ]; - /// - /// let if_gpio = ili9341::gpio::Gpio8Interface::new(&mut data_pins, csx, wrx, rdx, dcx); - pub fn new( - data_pins: &'a mut [&'a mut dyn OutputPin; 8], - csx: CSX, - wrx: WRX, - rdx: RDX, - dcx: DCX, - ) -> Self { - Self { - data_pins, - csx, - wrx, - rdx, - dcx, - } - } - - /// Sets the gpio data pins used in the parallel interface - fn set_data_bus(&mut self, data: u8) -> Result<(), Error> { - for (i, d) in self.data_pins.iter_mut().enumerate() { - if ((data >> i) & 0b1) == 0b1 { - d.set_high().map_err(Error::OutputPin)?; - } else { - d.set_low().map_err(Error::OutputPin)?; - } - } - Ok(()) - } -} - -impl<'a, CSX, WRX, RDX, DCX, PinE> Interface - for Gpio8Interface<'_, &mut dyn OutputPin, CSX, WRX, RDX, DCX> -where - CSX: OutputPin, - WRX: OutputPin, - RDX: OutputPin, - DCX: OutputPin, -{ - type Error = Error; - - fn write(&mut self, command: u8, data: &[u8]) -> Result<(), Self::Error> { - self.csx.set_low().map_err(Error::OutputPin)?; - self.rdx.set_high().map_err(Error::OutputPin)?; - self.dcx.set_low().map_err(Error::OutputPin)?; - self.wrx.set_low().map_err(Error::OutputPin)?; - - self.set_data_bus(command)?; - self.wrx.set_high().map_err(Error::OutputPin)?; - - self.dcx.set_high().map_err(Error::OutputPin)?; - for val in data.iter() { - self.wrx.set_low().map_err(Error::OutputPin)?; - self.set_data_bus(*val)?; - self.wrx.set_high().map_err(Error::OutputPin)?; - } - - self.csx.set_high().map_err(Error::OutputPin)?; - - Ok(()) - } - - fn write_iter( - &mut self, - command: u8, - data: impl IntoIterator, - ) -> Result<(), Self::Error> { - self.csx.set_low().map_err(Error::OutputPin)?; - self.rdx.set_high().map_err(Error::OutputPin)?; - self.dcx.set_low().map_err(Error::OutputPin)?; - self.wrx.set_low().map_err(Error::OutputPin)?; - - self.set_data_bus(command)?; - self.wrx.set_high().map_err(Error::OutputPin)?; - - self.dcx.set_high().map_err(Error::OutputPin)?; - for val in data.into_iter() { - for b in &val.to_be_bytes() { - self.wrx.set_low().map_err(Error::OutputPin)?; - self.set_data_bus(*b)?; - self.wrx.set_high().map_err(Error::OutputPin)?; - } - } - - self.csx.set_high().map_err(Error::OutputPin)?; - Ok(()) - } -} diff --git a/src/graphics.rs b/src/graphics.rs index 8aa6aee..669edf5 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -1,4 +1,4 @@ -use crate::{Ili9341, Interface, OutputPin}; +use crate::{Ili9341, OutputPin}; use core::fmt::Debug; @@ -14,14 +14,13 @@ use embedded_graphics::{ DrawTarget, }; -impl DrawTarget for Ili9341 +impl DrawTarget for Ili9341 where - IFACE: Interface, + IFACE: display_interface::WriteOnlyDataCommand, RESET: OutputPin, - IfaceE: Debug, PinE: Debug, { - type Error = IFACE::Error; + type Error = crate::Error; fn size(&self) -> Size { Size::new(self.width as u32, self.height as u32) diff --git a/src/lib.rs b/src/lib.rs index 2b2799f..b7c1794 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,13 +4,13 @@ extern crate embedded_graphics; use embedded_hal::blocking::delay::DelayMs; -use embedded_hal::blocking::spi::{Transfer, Write}; use embedded_hal::digital::v2::OutputPin; -pub mod spi; -use spi::SpiInterface; +use core::iter::once; +use display_interface::DataFormat::{U16BEIter, U8Iter}; +use display_interface::WriteOnlyDataCommand; -pub mod gpio; +pub mod spi; /// Trait representing the interface to the hardware. /// @@ -38,17 +38,11 @@ const WIDTH: usize = 240; const HEIGHT: usize = 320; #[derive(Debug)] -pub enum Error { - Interface(IfaceE), +pub enum Error { + Interface, OutputPin(PinE), } -impl From for Error { - fn from(e: IfaceE) -> Self { - Error::Interface(e) - } -} - /// The default orientation is Portrait pub enum Orientation { Portrait, @@ -80,38 +74,16 @@ pub struct Ili9341 { height: usize, } -impl Ili9341, RESET> +impl Ili9341 where - SPI: Transfer + Write, - CS: OutputPin, - DC: OutputPin, - RESET: OutputPin, -{ - pub fn new_spi>( - spi: SPI, - cs: CS, - dc: DC, - reset: RESET, - delay: &mut DELAY, - ) -> Result> { - let interface = SpiInterface::new(spi, cs, dc); - Self::new(interface, reset, delay).map_err(|e| match e { - Error::Interface(inner) => inner, - Error::OutputPin(inner) => Error::OutputPin(inner), - }) - } -} - -impl Ili9341 -where - IFACE: Interface, + IFACE: WriteOnlyDataCommand, RESET: OutputPin, { pub fn new>( interface: IFACE, reset: RESET, delay: &mut DELAY, - ) -> Result> { + ) -> Result> { let mut ili9341 = Ili9341 { interface, reset, @@ -173,15 +145,23 @@ where Ok(()) } - fn command(&mut self, cmd: Command, args: &[u8]) -> Result<(), IFACE::Error> { - self.interface.write(cmd as u8, args) + fn command(&mut self, cmd: Command, args: &[u8]) -> Result<(), Error> { + self.interface + .send_commands(U8Iter(&mut once(cmd as u8))) + .map_err(|_| Error::Interface)?; + self.interface + .send_data(U8Iter(&mut args.iter().cloned())) + .map_err(|_| Error::Interface) } - fn write_iter>(&mut self, data: I) -> Result<(), IFACE::Error> { - self.interface.write_iter(Command::MemoryWrite as u8, data) + fn write_iter>(&mut self, data: I) -> Result<(), Error> { + self.command(Command::MemoryWrite, &[])?; + self.interface + .send_data(U16BEIter(&mut data.into_iter())) + .map_err(|_| Error::Interface) } - fn set_window(&mut self, x0: u16, y0: u16, x1: u16, y1: u16) -> Result<(), IFACE::Error> { + fn set_window(&mut self, x0: u16, y0: u16, x1: u16, y1: u16) -> Result<(), Error> { self.command( Command::ColumnAddressSet, &[ @@ -219,7 +199,7 @@ where x1: u16, y1: u16, data: I, - ) -> Result<(), IFACE::Error> { + ) -> Result<(), Error> { self.set_window(x0, y0, x1, y1)?; self.write_iter(data) } @@ -240,13 +220,13 @@ where x1: u16, y1: u16, data: &[u16], - ) -> Result<(), IFACE::Error> { + ) -> Result<(), Error> { self.set_window(x0, y0, x1, y1)?; self.write_iter(data.iter().cloned()) } /// Change the orientation of the screen - pub fn set_orientation(&mut self, mode: Orientation) -> Result<(), IFACE::Error> { + pub fn set_orientation(&mut self, mode: Orientation) -> Result<(), Error> { match mode { Orientation::Portrait => { self.width = WIDTH; diff --git a/src/spi.rs b/src/spi.rs index c249c11..0d0853a 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -1,6 +1,3 @@ -use crate::{Error, Interface}; -use embedded_hal::blocking::spi; -use embedded_hal::digital::v2::OutputPin; use embedded_hal::spi::{Mode, Phase, Polarity}; /// SPI mode @@ -8,62 +5,3 @@ pub const MODE: Mode = Mode { polarity: Polarity::IdleLow, phase: Phase::CaptureOnFirstTransition, }; - -/// `Interface` implementation for SPI interfaces -pub struct SpiInterface { - spi: SPI, - cs: CS, - dc: DC, -} - -impl SpiInterface -where - SPI: spi::Transfer + spi::Write, - CS: OutputPin, - DC: OutputPin, -{ - pub fn new(spi: SPI, cs: CS, dc: DC) -> Self { - Self { spi, cs, dc } - } -} - -impl Interface for SpiInterface -where - SPI: spi::Transfer + spi::Write, - CS: OutputPin, - DC: OutputPin, -{ - type Error = Error; - - fn write(&mut self, command: u8, data: &[u8]) -> Result<(), Self::Error> { - self.cs.set_low().map_err(Error::OutputPin)?; - - self.dc.set_low().map_err(Error::OutputPin)?; - self.spi.write(&[command]).map_err(Error::Interface)?; - - self.dc.set_high().map_err(Error::OutputPin)?; - self.spi.write(data).map_err(Error::Interface)?; - - self.cs.set_high().map_err(Error::OutputPin)?; - Ok(()) - } - - fn write_iter( - &mut self, - command: u8, - data: impl IntoIterator, - ) -> Result<(), Self::Error> { - self.cs.set_low().map_err(Error::OutputPin)?; - - self.dc.set_low().map_err(Error::OutputPin)?; - self.spi.write(&[command]).map_err(Error::Interface)?; - - self.dc.set_high().map_err(Error::OutputPin)?; - for w in data.into_iter() { - self.spi.write(&w.to_be_bytes()).map_err(Error::Interface)?; - } - - self.cs.set_high().map_err(Error::OutputPin)?; - Ok(()) - } -}