Skip to content

Commit

Permalink
error: use EH1 NoAcknowledgeSource
Browse files Browse the repository at this point in the history
  • Loading branch information
newAM committed Oct 30, 2023
1 parent 5c4f40d commit 6447dfa
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 44 deletions.
23 changes: 12 additions & 11 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::fmt;
use std::io;
use eh1::i2c::NoAcknowledgeSource;
use std::{fmt, io};

/// Error type.
#[derive(Debug)]
Expand All @@ -17,27 +17,28 @@ pub enum Error<E: std::error::Error> {
#[non_exhaustive]
pub enum ErrorKind {
/// No ACK from the I2C slave
I2cNoAck,
I2cNoAck(NoAcknowledgeSource),
}

impl ErrorKind {
fn as_str(&self) -> &str {
match *self {
ErrorKind::I2cNoAck => "No ACK from slave",
ErrorKind::I2cNoAck(NoAcknowledgeSource::Address) => {
"No ACK from slave during addressing"
}
ErrorKind::I2cNoAck(NoAcknowledgeSource::Data) => {
"No ACK from slave during data transfer"
}
ErrorKind::I2cNoAck(NoAcknowledgeSource::Unknown) => "No ACK from slave",
}
}
}

impl<E: std::error::Error> eh1::i2c::Error for Error<E> {
fn kind(&self) -> eh1::i2c::ErrorKind {
match self {
Error::Hal(kind) => match kind {
ErrorKind::I2cNoAck => {
eh1::i2c::ErrorKind::NoAcknowledge(eh1::i2c::NoAcknowledgeSource::Unknown)
}
},
Error::Io(_io_err) => eh1::i2c::ErrorKind::Other,
Error::Backend(_std_err) => eh1::i2c::ErrorKind::Other,
Self::Hal(ErrorKind::I2cNoAck(src)) => eh1::i2c::ErrorKind::NoAcknowledge(*src),
_ => eh1::i2c::ErrorKind::Other,
}
}
}
Expand Down
62 changes: 29 additions & 33 deletions src/i2c.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::error::Error;
use crate::error::ErrorKind::I2cNoAck;
use crate::{FtInner, PinUse};
use eh1::i2c::{Operation, SevenBitAddress};
use eh1::i2c::{NoAcknowledgeSource, Operation, SevenBitAddress};
use ftdi_mpsse::{ClockBitsIn, ClockBitsOut, MpsseCmdBuilder, MpsseCmdExecutor};
use std::sync::{Arc, Mutex};

Expand Down Expand Up @@ -97,14 +97,22 @@ where

/// Enable faster I2C transactions by sending commands in a single write.
///
/// This is disabled by default.
/// This is disabled by default, and currently has no effect when using
/// version 1 of the `embedded-hal` traits.
///
/// Normally the I2C methods will send commands with a delay after each
/// slave ACK to read from the USB device.
/// Enabling this will send I2C commands without a delay, but slave ACKs
/// will only be checked at the end of each call to `read`, `write`, or
/// `write_read`.
///
/// Additionally this changes the type of errors that can occur:
///
/// * enabled: NAK errors will be reported as
/// `NoAcknowledgeSource::Unknown`.
/// * disabled: NAK errors will be reported as
/// `NoAcknowledgeSource::Address` or `NoAcknowledgeSource::Data`.
///
/// # Example
///
/// ```no_run
Expand Down Expand Up @@ -188,7 +196,7 @@ where
lock.ft.recv(buffer)?;

if (ack_buf[0] & 0b1) != 0x00 {
return Err(Error::Hal(I2cNoAck));
return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Unknown)));
}

Ok(())
Expand Down Expand Up @@ -221,7 +229,7 @@ where
let mut ack_buf: [u8; 1] = [0; 1];
lock.ft.recv(&mut ack_buf)?;
if (ack_buf[0] & 0b1) != 0x00 {
return Err(Error::Hal(I2cNoAck));
return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Address)));
}

let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
Expand Down Expand Up @@ -318,7 +326,7 @@ where
let mut ack_buf: Vec<u8> = vec![0; 1 + bytes.len()];
lock.ft.recv(ack_buf.as_mut_slice())?;
if ack_buf.iter().any(|&ack| (ack & 0b1) != 0x00) {
Err(Error::Hal(I2cNoAck))
Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Unknown)))
} else {
Ok(())
}
Expand Down Expand Up @@ -351,7 +359,7 @@ where
let mut ack_buf: [u8; 1] = [0; 1];
lock.ft.recv(&mut ack_buf)?;
if (ack_buf[0] & 0b1) != 0x00 {
return Err(Error::Hal(I2cNoAck));
return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Address)));
}

for (idx, byte) in bytes.iter().enumerate() {
Expand Down Expand Up @@ -388,7 +396,7 @@ where
let mut ack_buf: [u8; 1] = [0; 1];
lock.ft.recv(&mut ack_buf)?;
if (ack_buf[0] & 0b1) != 0x00 {
return Err(Error::Hal(I2cNoAck));
return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Data)));
}
}

Expand Down Expand Up @@ -493,7 +501,7 @@ where
lock.ft.recv(buffer)?;

if ack_buf.iter().any(|&ack| (ack & 0b1) != 0x00) {
Err(Error::Hal(I2cNoAck))
Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Unknown)))
} else {
Ok(())
}
Expand Down Expand Up @@ -534,7 +542,7 @@ where
let mut ack_buf: [u8; 1] = [0; 1];
lock.ft.recv(&mut ack_buf)?;
if (ack_buf[0] & 0b1) != 0x00 {
return Err(Error::Hal(I2cNoAck));
return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Address)));
}

for byte in bytes {
Expand All @@ -551,7 +559,7 @@ where
let mut ack_buf: [u8; 1] = [0; 1];
lock.ft.recv(&mut ack_buf)?;
if (ack_buf[0] & 0b1) != 0x00 {
return Err(Error::Hal(I2cNoAck));
return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Data)));
}
}

Expand Down Expand Up @@ -579,7 +587,7 @@ where
let mut ack_buf: [u8; 1] = [0; 1];
lock.ft.recv(&mut ack_buf)?;
if (ack_buf[0] & 0b1) != 0x00 {
return Err(Error::Hal(I2cNoAck));
return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Data)));
}

let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
Expand Down Expand Up @@ -622,7 +630,7 @@ where
Ok(())
}

fn transaction_slow(
fn transaction(
&mut self,
address: u8,
operations: &mut [Operation<'_>],
Expand All @@ -641,13 +649,13 @@ where
}
lock.ft.send(mpsse_cmd.as_slice())?;

let mut last_op_was_a_read = false;
let mut prev_op_was_a_read: bool = false;
for (idx, operation) in operations.iter_mut().enumerate() {
match operation {
Operation::Read(buffer) => {
assert!(!buffer.is_empty(), "buffer must be a non-empty slice");

if idx == 0 || !last_op_was_a_read {
if idx == 0 || !prev_op_was_a_read {
let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
if idx != 0 {
// SR
Expand Down Expand Up @@ -680,7 +688,7 @@ where
let mut ack_buf: [u8; 1] = [0; 1];
lock.ft.recv(&mut ack_buf)?;
if (ack_buf[0] & 0b1) != 0x00 {
return Err(Error::Hal(I2cNoAck));
return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Address)));
}
}

Expand All @@ -704,12 +712,12 @@ where
lock.ft.send(mpsse_cmd.as_slice())?;
lock.ft.recv(buffer)?;

last_op_was_a_read = true;
prev_op_was_a_read = true;
}
Operation::Write(bytes) => {
assert!(!bytes.is_empty(), "bytes must be a non-empty slice");

if idx == 0 || last_op_was_a_read {
if idx == 0 || prev_op_was_a_read {
let mut mpsse_cmd: MpsseCmdBuilder = MpsseCmdBuilder::new();
if idx != 0 {
// SR
Expand Down Expand Up @@ -742,7 +750,7 @@ where
let mut ack_buf: [u8; 1] = [0; 1];
lock.ft.recv(&mut ack_buf)?;
if (ack_buf[0] & 0b1) != 0x00 {
return Err(Error::Hal(I2cNoAck));
return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Address)));
}
}

Expand All @@ -761,11 +769,11 @@ where
let mut ack_buf: [u8; 1] = [0; 1];
lock.ft.recv(&mut ack_buf)?;
if (ack_buf[0] & 0b1) != 0x00 {
return Err(Error::Hal(I2cNoAck));
return Err(Error::Hal(I2cNoAck(NoAcknowledgeSource::Data)));
}
}

last_op_was_a_read = false;
prev_op_was_a_read = false;
}
}
}
Expand All @@ -790,14 +798,6 @@ where

Ok(())
}

fn transaction_fast(
&mut self,
_address: u8,
_operations: &mut [Operation<'_>],
) -> Result<(), Error<E>> {
unimplemented!()
}
}

impl<Device, E> eh0::blocking::i2c::Read for I2c<Device>
Expand Down Expand Up @@ -871,10 +871,6 @@ where
address: SevenBitAddress,
operations: &mut [Operation<'_>],
) -> Result<(), Self::Error> {
if self.fast {
self.transaction_fast(address, operations)
} else {
self.transaction_slow(address, operations)
}
self.transaction(address, operations)
}
}

0 comments on commit 6447dfa

Please sign in to comment.