mirror of
https://github.com/yuri91/ili9341-rs.git
synced 2024-11-22 06:40:59 +00:00
Merge pull request #16 from therealprof/display-interface
Rough first conversion to display-interface
This commit is contained in:
commit
332aa05bc4
5 changed files with 30 additions and 234 deletions
|
@ -11,6 +11,7 @@ edition = "2018"
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
display-interface = "0.4"
|
||||||
embedded-hal = "0.2.3"
|
embedded-hal = "0.2.3"
|
||||||
|
|
||||||
[dependencies.embedded-graphics]
|
[dependencies.embedded-graphics]
|
||||||
|
|
122
src/gpio.rs
122
src/gpio.rs
|
@ -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<Error = PinE>, CSX, WRX, RDX, DCX>
|
|
||||||
where
|
|
||||||
CSX: OutputPin<Error = PinE>,
|
|
||||||
WRX: OutputPin<Error = PinE>,
|
|
||||||
RDX: OutputPin<Error = PinE>,
|
|
||||||
DCX: OutputPin<Error = PinE>,
|
|
||||||
{
|
|
||||||
/// 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<Error = _>; 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<Error = PinE>; 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<PinE, PinE>> {
|
|
||||||
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<Error = PinE>, CSX, WRX, RDX, DCX>
|
|
||||||
where
|
|
||||||
CSX: OutputPin<Error = PinE>,
|
|
||||||
WRX: OutputPin<Error = PinE>,
|
|
||||||
RDX: OutputPin<Error = PinE>,
|
|
||||||
DCX: OutputPin<Error = PinE>,
|
|
||||||
{
|
|
||||||
type Error = Error<PinE, PinE>;
|
|
||||||
|
|
||||||
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<Item = u16>,
|
|
||||||
) -> 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(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{Ili9341, Interface, OutputPin};
|
use crate::{Ili9341, OutputPin};
|
||||||
|
|
||||||
use core::{fmt::Debug, iter};
|
use core::{fmt::Debug, iter};
|
||||||
|
|
||||||
|
@ -14,14 +14,13 @@ use embedded_graphics::{
|
||||||
DrawTarget,
|
DrawTarget,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<IfaceE, PinE, IFACE, RESET> DrawTarget<Rgb565> for Ili9341<IFACE, RESET>
|
impl<PinE, IFACE, RESET> DrawTarget<Rgb565> for Ili9341<IFACE, RESET>
|
||||||
where
|
where
|
||||||
IFACE: Interface<Error = IfaceE>,
|
IFACE: display_interface::WriteOnlyDataCommand,
|
||||||
RESET: OutputPin<Error = PinE>,
|
RESET: OutputPin<Error = PinE>,
|
||||||
IfaceE: Debug,
|
|
||||||
PinE: Debug,
|
PinE: Debug,
|
||||||
{
|
{
|
||||||
type Error = IFACE::Error;
|
type Error = crate::Error<PinE>;
|
||||||
|
|
||||||
fn size(&self) -> Size {
|
fn size(&self) -> Size {
|
||||||
Size::new(self.width as u32, self.height as u32)
|
Size::new(self.width as u32, self.height as u32)
|
||||||
|
|
70
src/lib.rs
70
src/lib.rs
|
@ -4,13 +4,13 @@
|
||||||
extern crate embedded_graphics;
|
extern crate embedded_graphics;
|
||||||
|
|
||||||
use embedded_hal::blocking::delay::DelayMs;
|
use embedded_hal::blocking::delay::DelayMs;
|
||||||
use embedded_hal::blocking::spi::{Transfer, Write};
|
|
||||||
use embedded_hal::digital::v2::OutputPin;
|
use embedded_hal::digital::v2::OutputPin;
|
||||||
|
|
||||||
pub mod spi;
|
use core::iter::once;
|
||||||
use spi::SpiInterface;
|
use display_interface::DataFormat::{U16BEIter, U8Iter};
|
||||||
|
use display_interface::WriteOnlyDataCommand;
|
||||||
|
|
||||||
pub mod gpio;
|
pub mod spi;
|
||||||
|
|
||||||
/// Trait representing the interface to the hardware.
|
/// Trait representing the interface to the hardware.
|
||||||
///
|
///
|
||||||
|
@ -38,17 +38,11 @@ const WIDTH: usize = 240;
|
||||||
const HEIGHT: usize = 320;
|
const HEIGHT: usize = 320;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error<IfaceE, PinE> {
|
pub enum Error<PinE> {
|
||||||
Interface(IfaceE),
|
Interface,
|
||||||
OutputPin(PinE),
|
OutputPin(PinE),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<IfaceE, PinE> From<IfaceE> for Error<IfaceE, PinE> {
|
|
||||||
fn from(e: IfaceE) -> Self {
|
|
||||||
Error::Interface(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The default orientation is Portrait
|
/// The default orientation is Portrait
|
||||||
pub enum Orientation {
|
pub enum Orientation {
|
||||||
Portrait,
|
Portrait,
|
||||||
|
@ -80,38 +74,16 @@ pub struct Ili9341<IFACE, RESET> {
|
||||||
height: usize,
|
height: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SpiE, PinE, SPI, CS, DC, RESET> Ili9341<SpiInterface<SPI, CS, DC>, RESET>
|
impl<PinE, IFACE, RESET> Ili9341<IFACE, RESET>
|
||||||
where
|
where
|
||||||
SPI: Transfer<u8, Error = SpiE> + Write<u8, Error = SpiE>,
|
IFACE: WriteOnlyDataCommand,
|
||||||
CS: OutputPin<Error = PinE>,
|
|
||||||
DC: OutputPin<Error = PinE>,
|
|
||||||
RESET: OutputPin<Error = PinE>,
|
|
||||||
{
|
|
||||||
pub fn new_spi<DELAY: DelayMs<u16>>(
|
|
||||||
spi: SPI,
|
|
||||||
cs: CS,
|
|
||||||
dc: DC,
|
|
||||||
reset: RESET,
|
|
||||||
delay: &mut DELAY,
|
|
||||||
) -> Result<Self, Error<SpiE, PinE>> {
|
|
||||||
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<IfaceE, PinE, IFACE, RESET> Ili9341<IFACE, RESET>
|
|
||||||
where
|
|
||||||
IFACE: Interface<Error = IfaceE>,
|
|
||||||
RESET: OutputPin<Error = PinE>,
|
RESET: OutputPin<Error = PinE>,
|
||||||
{
|
{
|
||||||
pub fn new<DELAY: DelayMs<u16>>(
|
pub fn new<DELAY: DelayMs<u16>>(
|
||||||
interface: IFACE,
|
interface: IFACE,
|
||||||
reset: RESET,
|
reset: RESET,
|
||||||
delay: &mut DELAY,
|
delay: &mut DELAY,
|
||||||
) -> Result<Self, Error<IfaceE, PinE>> {
|
) -> Result<Self, Error<PinE>> {
|
||||||
let mut ili9341 = Ili9341 {
|
let mut ili9341 = Ili9341 {
|
||||||
interface,
|
interface,
|
||||||
reset,
|
reset,
|
||||||
|
@ -173,15 +145,23 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command(&mut self, cmd: Command, args: &[u8]) -> Result<(), IFACE::Error> {
|
fn command(&mut self, cmd: Command, args: &[u8]) -> Result<(), Error<PinE>> {
|
||||||
self.interface.write(cmd as u8, args)
|
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<I: IntoIterator<Item = u16>>(&mut self, data: I) -> Result<(), IFACE::Error> {
|
fn write_iter<I: IntoIterator<Item = u16>>(&mut self, data: I) -> Result<(), Error<PinE>> {
|
||||||
self.interface.write_iter(Command::MemoryWrite as u8, data)
|
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<PinE>> {
|
||||||
self.command(
|
self.command(
|
||||||
Command::ColumnAddressSet,
|
Command::ColumnAddressSet,
|
||||||
&[
|
&[
|
||||||
|
@ -219,7 +199,7 @@ where
|
||||||
x1: u16,
|
x1: u16,
|
||||||
y1: u16,
|
y1: u16,
|
||||||
data: I,
|
data: I,
|
||||||
) -> Result<(), IFACE::Error> {
|
) -> Result<(), Error<PinE>> {
|
||||||
self.set_window(x0, y0, x1, y1)?;
|
self.set_window(x0, y0, x1, y1)?;
|
||||||
self.write_iter(data)
|
self.write_iter(data)
|
||||||
}
|
}
|
||||||
|
@ -240,13 +220,13 @@ where
|
||||||
x1: u16,
|
x1: u16,
|
||||||
y1: u16,
|
y1: u16,
|
||||||
data: &[u16],
|
data: &[u16],
|
||||||
) -> Result<(), IFACE::Error> {
|
) -> Result<(), Error<PinE>> {
|
||||||
self.set_window(x0, y0, x1, y1)?;
|
self.set_window(x0, y0, x1, y1)?;
|
||||||
self.write_iter(data.iter().cloned())
|
self.write_iter(data.iter().cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the orientation of the screen
|
/// 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<PinE>> {
|
||||||
match mode {
|
match mode {
|
||||||
Orientation::Portrait => {
|
Orientation::Portrait => {
|
||||||
self.width = WIDTH;
|
self.width = WIDTH;
|
||||||
|
|
62
src/spi.rs
62
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};
|
use embedded_hal::spi::{Mode, Phase, Polarity};
|
||||||
|
|
||||||
/// SPI mode
|
/// SPI mode
|
||||||
|
@ -8,62 +5,3 @@ pub const MODE: Mode = Mode {
|
||||||
polarity: Polarity::IdleLow,
|
polarity: Polarity::IdleLow,
|
||||||
phase: Phase::CaptureOnFirstTransition,
|
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::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<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::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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue