Skip to content

New api #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 47 additions & 68 deletions i2c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Generic I2C interface for display drivers
use embedded_hal as hal;

use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand};
use display_interface::{DisplayError, WriteOnlyDataCommand};

/// I2C communication interface
pub struct I2CInterface<I2C> {
Expand All @@ -30,81 +30,60 @@ where
pub fn release(self) -> I2C {
self.i2c
}
}

impl<I2C> WriteOnlyDataCommand for I2CInterface<I2C>
where
I2C: hal::blocking::i2c::Write,
{
fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result<(), DisplayError> {
// Copy over given commands to new aray to prefix with command identifier
match cmds {
DataFormat::U8(slice) => {
let mut writebuf: [u8; 8] = [0; 8];
writebuf[1..=slice.len()].copy_from_slice(&slice[0..slice.len()]);

self.i2c
.write(self.addr, &writebuf[..=slice.len()])
.map_err(|_| DisplayError::BusWriteError)
}
_ => Err(DisplayError::DataFormatNotImplemented),
}
}

fn send_data(&mut self, buf: DataFormat<'_>) -> Result<(), DisplayError> {
match buf {
DataFormat::U8(slice) => {
// No-op if the data buffer is empty
if slice.is_empty() {
return Ok(());
}

let mut writebuf = [0; 17];

// Data mode
writebuf[0] = self.data_byte;
fn send_iter(
&mut self,
first_byte: u8,
data: impl Iterator<Item = u8>,
) -> Result<(), DisplayError> {
let mut writebuf = [0; 17];
let mut i = 1;
let len = writebuf.len();

slice
.chunks(16)
.try_for_each(|c| {
let chunk_len = c.len();
// Data/command mode
writebuf[0] = first_byte;

// Copy over all data from buffer, leaving the data command byte intact
writebuf[1..=chunk_len].copy_from_slice(c);
for byte in data {
writebuf[i] = byte;
i += 1;

self.i2c.write(self.addr, &writebuf[0..=chunk_len])
})
.map_err(|_| DisplayError::BusWriteError)
if i == len {
self.i2c
.write(self.addr, &writebuf[0..=len])
.map_err(|_| DisplayError::BusWriteError)?;
i = 1;
}
DataFormat::U8Iter(iter) => {
let mut writebuf = [0; 17];
let mut i = 1;
let len = writebuf.len();

// Data mode
writebuf[0] = self.data_byte;
}

for byte in iter.into_iter() {
writebuf[i] = byte;
i += 1;
if i > 1 {
self.i2c
.write(self.addr, &writebuf[0..=i])
.map_err(|_| DisplayError::BusWriteError)?;
}

if i == len {
self.i2c
.write(self.addr, &writebuf[0..=len])
.map_err(|_| DisplayError::BusWriteError)?;
i = 1;
}
}
Ok(())
}
}

if i > 1 {
self.i2c
.write(self.addr, &writebuf[0..=i])
.map_err(|_| DisplayError::BusWriteError)?;
}
impl<I2C> WriteOnlyDataCommand for I2CInterface<I2C>
where
I2C: hal::blocking::i2c::Write,
{
type Word = u8;

#[inline]
fn send_command_iter(
&mut self,
iter: impl Iterator<Item = Self::Word>,
) -> Result<(), DisplayError> {
self.send_iter(0, iter)
}

Ok(())
}
_ => Err(DisplayError::DataFormatNotImplemented),
}
#[inline]
fn send_data_iter(
&mut self,
iter: impl Iterator<Item = Self::Word>,
) -> Result<(), DisplayError> {
self.send_iter(self.data_byte, iter)
}
}
1 change: 0 additions & 1 deletion parallel-gpio/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@ all-features = true
[dependencies]
embedded-hal = "0.2.3"
display-interface = "0.4"
byte-slice-cast = { version = "0.3.5", default-features = false }

185 changes: 57 additions & 128 deletions parallel-gpio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use embedded_hal::digital::v2::OutputPin;

pub use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand};
pub use display_interface::{DisplayError, WriteOnlyDataCommand};

/// This trait represents the data pins of a parallel bus.
///
Expand Down Expand Up @@ -108,24 +108,48 @@ generic_bus! {
}
}

/// Parallel 8 Bit communication interface
generic_bus! {
Generic16BitBus {
type Word = u16;
Pins {
P0 => 0,
P1 => 1,
P2 => 2,
P3 => 3,
P4 => 4,
P5 => 5,
P6 => 6,
P7 => 7,
P8 => 8,
P9 => 9,
P10 => 10,
P11 => 11,
P12 => 12,
P13 => 13,
P14 => 14,
P15 => 15,
}
}
}

/// Parallel communication interface
///
/// This interface implements an 8-Bit "8080" style write-only display interface using any
/// 8-bit [OutputBus] implementation as well as one
/// This interface implements an "8080" style write-only display interface using any
/// [OutputBus] implementation as well as one
/// `OutputPin` for the data/command selection and one `OutputPin` for the write-enable flag.
///
/// All pins are supposed to be high-active, high for the D/C pin meaning "data" and the
/// write-enable being pulled low before the setting of the bits and supposed to be sampled at a
/// low to high edge.
pub struct PGPIO8BitInterface<BUS, DC, WR> {
pub struct ParallelInterface<BUS, DC, WR> {
bus: BUS,
dc: DC,
wr: WR,
}

impl<BUS, DC, WR> PGPIO8BitInterface<BUS, DC, WR>
impl<BUS, DC, WR> ParallelInterface<BUS, DC, WR>
where
BUS: OutputBus<Word = u8>,
BUS: OutputBus,
DC: OutputPin,
WR: OutputPin,
{
Expand All @@ -140,140 +164,45 @@ where
(self.bus, self.dc, self.wr)
}

fn set_value(self: &mut Self, value: u8) -> Result<(), DisplayError> {
fn set_value(self: &mut Self, value: BUS::Word) -> Result<(), DisplayError> {
self.bus.set_value(value)
}

fn send_iter<I: Iterator<Item = BUS::Word>>(
&mut self,
mut iter: I,
) -> Result<(), DisplayError> {
iter.try_for_each(|d| {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(d)?;
self.wr.set_high().map_err(|_| DisplayError::BusWriteError)
})
}
}

impl<BUS, DC, WR> WriteOnlyDataCommand for PGPIO8BitInterface<BUS, DC, WR>
impl<BUS, DC, WR> WriteOnlyDataCommand for ParallelInterface<BUS, DC, WR>
where
BUS: OutputBus<Word = u8>,
BUS: OutputBus,
DC: OutputPin,
WR: OutputPin,
{
fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result<(), DisplayError> {
use byte_slice_cast::*;
self.dc.set_low().map_err(|_| DisplayError::DCError)?;
match cmds {
DataFormat::U8(slice) => slice.iter().try_for_each(|cmd| {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(*cmd)?;
self.wr.set_high().map_err(|_| DisplayError::BusWriteError)
}),
DataFormat::U8Iter(iter) => {
for c in iter.into_iter() {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(c)?;
self.wr
.set_high()
.map_err(|_| DisplayError::BusWriteError)?;
}
type Word = BUS::Word;

Ok(())
}
DataFormat::U16(slice) => slice.as_byte_slice().iter().try_for_each(|cmd| {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(*cmd)?;
self.wr.set_high().map_err(|_| DisplayError::BusWriteError)
}),
DataFormat::U16LE(slice) => slice.iter().try_for_each(|cmd| {
for cmd in &cmd.to_le_bytes() {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(*cmd)?;
self.wr
.set_high()
.map_err(|_| DisplayError::BusWriteError)?;
}

Ok(())
}),
DataFormat::U16BE(slice) => slice.iter().try_for_each(|cmd| {
for cmd in &cmd.to_be_bytes() {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(*cmd)?;
self.wr
.set_high()
.map_err(|_| DisplayError::BusWriteError)?;
}
fn send_command_iter(
&mut self,
iter: impl Iterator<Item = Self::Word>,
) -> Result<(), DisplayError> {
self.dc.set_low().map_err(|_| DisplayError::DCError)?;

Ok(())
}),
_ => Err(DisplayError::DataFormatNotImplemented),
}
self.send_iter(iter)
}

fn send_data(&mut self, buf: DataFormat<'_>) -> Result<(), DisplayError> {
use byte_slice_cast::*;
fn send_data_iter(
&mut self,
iter: impl Iterator<Item = Self::Word>,
) -> Result<(), DisplayError> {
self.dc.set_high().map_err(|_| DisplayError::DCError)?;
match buf {
DataFormat::U8(slice) => slice.iter().try_for_each(|d| {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(*d)?;
self.wr.set_high().map_err(|_| DisplayError::BusWriteError)
}),
DataFormat::U16(slice) => slice.as_byte_slice().iter().try_for_each(|d| {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(*d)?;
self.wr.set_high().map_err(|_| DisplayError::BusWriteError)
}),
DataFormat::U16LE(slice) => slice.iter().try_for_each(|cmd| {
for cmd in &cmd.to_le_bytes() {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(*cmd)?;
self.wr
.set_high()
.map_err(|_| DisplayError::BusWriteError)?;
}

Ok(())
}),
DataFormat::U16BE(slice) => slice.iter().try_for_each(|cmd| {
for cmd in &cmd.to_be_bytes() {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(*cmd)?;
self.wr
.set_high()
.map_err(|_| DisplayError::BusWriteError)?;
}

Ok(())
}),
DataFormat::U8Iter(iter) => {
for d in iter.into_iter() {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(d)?;
self.wr
.set_high()
.map_err(|_| DisplayError::BusWriteError)?;
}

Ok(())
}
DataFormat::U16LEIter(iter) => {
for cmd in iter.into_iter() {
for cmd in &cmd.to_le_bytes() {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(*cmd)?;
self.wr
.set_high()
.map_err(|_| DisplayError::BusWriteError)?;
}
}
Ok(())
}
DataFormat::U16BEIter(iter) => {
for cmd in iter.into_iter() {
for cmd in &cmd.to_be_bytes() {
self.wr.set_low().map_err(|_| DisplayError::BusWriteError)?;
self.set_value(*cmd)?;
self.wr
.set_high()
.map_err(|_| DisplayError::BusWriteError)?;
}
}
Ok(())
}
_ => Err(DisplayError::DataFormatNotImplemented),
}
self.send_iter(iter)
}
}
1 change: 0 additions & 1 deletion spi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,3 @@ all-features = true
[dependencies]
embedded-hal = "0.2.3"
display-interface = "0.4"
byte-slice-cast = { version = "0.3.5", default-features = false }
Loading