Move SPI interface implementation into a separate file

This commit is contained in:
Vadim Kaushan 2020-01-28 19:56:12 +03:00
parent f09403d092
commit 5b03a86bb0
No known key found for this signature in database
GPG key ID: A501C5DF67C05C4E
2 changed files with 79 additions and 54 deletions

View file

@ -6,13 +6,15 @@ extern crate embedded_hal as hal;
extern crate embedded_graphics; extern crate embedded_graphics;
use hal::blocking::delay::DelayMs; use hal::blocking::delay::DelayMs;
use hal::blocking::spi; use hal::blocking::spi::{Write, Transfer};
use hal::digital::v2::OutputPin; use hal::digital::v2::OutputPin;
use hal::spi::{Mode, Phase, Polarity};
use core::fmt::Debug; use core::fmt::Debug;
use core::iter::IntoIterator; use core::iter::IntoIterator;
pub mod spi;
use spi::SpiInterface;
/// Trait representing the interface to the hardware. /// Trait representing the interface to the hardware.
/// ///
/// Intended to abstract the various buses (SPI, MPU 8/9/16-bit) from the Controller code. /// Intended to abstract the various buses (SPI, MPU 8/9/16-bit) from the Controller code.
@ -31,12 +33,6 @@ pub trait Interface {
fn write_iter(&mut self, command: u8, data: impl IntoIterator<Item = u16>) -> Result<(), Self::Error>; fn write_iter(&mut self, command: u8, data: impl IntoIterator<Item = u16>) -> Result<(), Self::Error>;
} }
/// SPI mode
pub const MODE: Mode = Mode {
polarity: Polarity::IdleLow,
phase: Phase::CaptureOnFirstTransition,
};
const WIDTH: usize = 240; const WIDTH: usize = 240;
const HEIGHT: usize = 320; const HEIGHT: usize = 320;
@ -71,9 +67,7 @@ pub enum Orientation {
/// and the next word will fill the next pixel (the adjacent on the right, or /// and the next word will fill the next pixel (the adjacent on the right, or
/// the first of the next row if the row ended) /// the first of the next row if the row ended)
pub struct Ili9341<SPI, CS, DC, RESET> { pub struct Ili9341<SPI, CS, DC, RESET> {
spi: SPI, interface: SpiInterface<SPI, CS, DC>,
cs: CS,
dc: DC,
reset: RESET, reset: RESET,
width: usize, width: usize,
height: usize, height: usize,
@ -81,7 +75,7 @@ pub struct Ili9341<SPI, CS, DC, RESET> {
impl<SpiE, PinE, SPI, CS, DC, RESET> Ili9341<SPI, CS, DC, RESET> impl<SpiE, PinE, SPI, CS, DC, RESET> Ili9341<SPI, CS, DC, RESET>
where where
SPI: spi::Transfer<u8, Error = SpiE> + spi::Write<u8, Error = SpiE>, SPI: Transfer<u8, Error = SpiE> + Write<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>, CS: OutputPin<Error = PinE>,
DC: OutputPin<Error = PinE>, DC: OutputPin<Error = PinE>,
RESET: OutputPin<Error = PinE>, RESET: OutputPin<Error = PinE>,
@ -93,10 +87,9 @@ where
reset: RESET, reset: RESET,
delay: &mut DELAY, delay: &mut DELAY,
) -> Result<Self, Error<SpiE, PinE>> { ) -> Result<Self, Error<SpiE, PinE>> {
let interface = SpiInterface::new(spi, cs, dc);
let mut ili9341 = Ili9341 { let mut ili9341 = Ili9341 {
spi, interface,
cs,
dc,
reset, reset,
width: WIDTH, width: WIDTH,
height: HEIGHT, height: HEIGHT,
@ -159,51 +152,16 @@ where
Ok(()) Ok(())
} }
fn command(&mut self, cmd: Command, args: &[u8]) -> Result<(), Error<SpiE, PinE>> { fn command(&mut self, cmd: Command, args: &[u8]) -> Result<(), Error<SpiE, PinE>> {
self.cs.set_low().map_err(Error::OutputPin)?; self.interface.write(cmd as u8, args)
self.dc.set_low().map_err(Error::OutputPin)?;
self.spi.write(&[cmd as u8]).map_err(Error::Spi)?;
self.dc.set_high().map_err(Error::OutputPin)?;
self.spi.write(args).map_err(Error::Spi)?;
self.cs.set_high().map_err(Error::OutputPin)?;
Ok(())
} }
fn write_iter<I: IntoIterator<Item = u16>>( fn write_iter<I: IntoIterator<Item = u16>>(
&mut self, &mut self,
data: I, data: I,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<SpiE, PinE>> {
self.cs.set_low().map_err(Error::OutputPin)?; self.interface.write_iter(Command::MemoryWrite as u8, data)
self.dc.set_low().map_err(Error::OutputPin)?;
self.spi
.write(&[Command::MemoryWrite as u8])
.map_err(Error::Spi)?;
self.dc.set_high().map_err(Error::OutputPin)?;
for d in data.into_iter() {
self.spi
.write(&[(d >> 8) as u8, (d & 0xff) as u8])
.map_err(Error::Spi)?;
}
self.cs.set_high().map_err(Error::OutputPin)?;
Ok(())
} }
fn write_raw(&mut self, data: &[u8]) -> Result<(), Error<SpiE, PinE>> { fn write_raw(&mut self, data: &[u8]) -> Result<(), Error<SpiE, PinE>> {
self.cs.set_low().map_err(Error::OutputPin)?; self.interface.write(Command::MemoryWrite as u8, data)
self.dc.set_low().map_err(Error::OutputPin)?;
self.spi
.write(&[Command::MemoryWrite as u8])
.map_err(Error::Spi)?;
self.dc.set_high().map_err(Error::OutputPin)?;
self.spi.write(data).map_err(Error::Spi)?;
self.cs.set_high().map_err(Error::OutputPin)?;
Ok(())
} }
fn set_window(&mut self, x0: u16, y0: u16, x1: u16, y1: u16) -> Result<(), Error<SpiE, PinE>> { fn set_window(&mut self, x0: u16, y0: u16, x1: u16, y1: u16) -> Result<(), Error<SpiE, PinE>> {
self.command( self.command(
@ -310,7 +268,7 @@ use embedded_graphics::{drawable::Pixel, pixelcolor::Rgb565, Drawing};
#[cfg(feature = "graphics")] #[cfg(feature = "graphics")]
impl<SpiE, PinE, SPI, CS, DC, RESET> Drawing<Rgb565> for Ili9341<SPI, CS, DC, RESET> impl<SpiE, PinE, SPI, CS, DC, RESET> Drawing<Rgb565> for Ili9341<SPI, CS, DC, RESET>
where where
SPI: spi::Transfer<u8, Error = SpiE> + spi::Write<u8, Error = SpiE>, SPI: Transfer<u8, Error = SpiE> + Write<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>, CS: OutputPin<Error = PinE>,
DC: OutputPin<Error = PinE>, DC: OutputPin<Error = PinE>,
RESET: OutputPin<Error = PinE>, RESET: OutputPin<Error = PinE>,

67
src/spi.rs Normal file
View file

@ -0,0 +1,67 @@
use super::hal::blocking::spi;
use super::hal::spi::{Mode, Phase, Polarity};
use super::hal::digital::v2::OutputPin;
use super::{Interface, Error};
/// SPI mode
pub const MODE: Mode = Mode {
polarity: Polarity::IdleLow,
phase: Phase::CaptureOnFirstTransition,
};
/// `Interface` implementation for SPI interfaces
pub struct SpiInterface<SPI, CS, DC> {
spi: SPI,
cs: CS,
dc: DC,
}
impl<SPI, CS, DC, SpiE, PinE> SpiInterface<SPI, CS, DC>
where SPI: spi::Transfer<u8, Error = SpiE> + spi::Write<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
DC: OutputPin<Error = PinE>,
{
pub fn new(spi: SPI, cs: CS, dc: DC) -> Self {
Self {
spi,
cs,
dc,
}
}
}
impl<SPI, CS, DC, SpiE, PinE> Interface for SpiInterface<SPI, CS, DC>
where SPI: spi::Transfer<u8, Error = SpiE> + spi::Write<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
DC: OutputPin<Error = PinE>,
{
type Error = Error<SpiE, PinE>;
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::Spi)?;
self.dc.set_high().map_err(Error::OutputPin)?;
self.spi.write(data).map_err(Error::Spi)?;
self.cs.set_high().map_err(Error::OutputPin)?;
Ok(())
}
fn write_iter(&mut self, command: u8, data: impl IntoIterator<Item=u16>) -> 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::Spi)?;
self.dc.set_high().map_err(Error::OutputPin)?;
for w in data.into_iter() {
self.spi.write(&w.to_be_bytes()).map_err(Error::Spi)?;
}
self.cs.set_high().map_err(Error::OutputPin)?;
Ok(())
}
}