Re-wrote socket implementations to be more compatible with embedded-nal
This commit is contained in:
parent
b1e83e3d05
commit
f546ff2011
17 changed files with 673 additions and 1603 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use byteorder::{BigEndian, ByteOrder};
|
||||
use core::fmt;
|
||||
use embedded_hal::digital::v2::OutputPin;
|
||||
use embedded_hal::spi::FullDuplex;
|
||||
|
||||
|
|
@ -34,33 +34,39 @@ pub struct ActiveFourWire<Spi: FullDuplex<u8>, ChipSelect: OutputPin> {
|
|||
|
||||
impl<Spi: FullDuplex<u8>, ChipSelect: OutputPin> ActiveBus for ActiveFourWire<Spi, ChipSelect> {
|
||||
type Error = FourWireError<Spi::Error, ChipSelect::Error>;
|
||||
fn transfer_frame<'a>(
|
||||
&mut self,
|
||||
block: u8,
|
||||
address: u16,
|
||||
is_write: bool,
|
||||
data: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], Self::Error> {
|
||||
let mut control_phase = block << 3;
|
||||
if is_write {
|
||||
control_phase |= WRITE_MODE_MASK;
|
||||
}
|
||||
fn read_frame(&mut self, block: u8, address: u16, data: &mut [u8]) -> Result<(), Self::Error> {
|
||||
let address_phase = address.to_be_bytes();
|
||||
let control_phase = block << 3;
|
||||
let data_phase = data;
|
||||
let mut address_phase = [0u8; 2];
|
||||
BigEndian::write_u16(&mut address_phase, address);
|
||||
|
||||
self.cs
|
||||
.set_low()
|
||||
.map_err(|e| FourWireError::ChipSelectError(e))?;
|
||||
Self::transfer_bytes(&mut self.spi, &mut address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, &mut control_phase))
|
||||
.and_then(|_| Self::transfer_bytes(&mut self.spi, data_phase))
|
||||
.map_err(|e| FourWireError::SpiError(e))?;
|
||||
Self::write_bytes(&mut self.spi, &address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, control_phase))
|
||||
.and_then(|_| Self::read_bytes(&mut self.spi, data_phase))
|
||||
.map_err(|e| FourWireError::SpiError(e))?;
|
||||
self.cs
|
||||
.set_high()
|
||||
.map_err(|e| FourWireError::ChipSelectError(e))?;
|
||||
|
||||
Ok(data_phase)
|
||||
Ok(())
|
||||
}
|
||||
fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error> {
|
||||
let address_phase = address.to_be_bytes();
|
||||
let control_phase = block << 3 | WRITE_MODE_MASK;
|
||||
let data_phase = data;
|
||||
self.cs
|
||||
.set_low()
|
||||
.map_err(|e| FourWireError::ChipSelectError(e))?;
|
||||
Self::write_bytes(&mut self.spi, &address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, control_phase))
|
||||
.and_then(|_| Self::write_bytes(&mut self.spi, data_phase))
|
||||
.map_err(|e| FourWireError::SpiError(e))?;
|
||||
self.cs
|
||||
.set_high()
|
||||
.map_err(|e| FourWireError::ChipSelectError(e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl<Spi: FullDuplex<u8>, ChipSelect: OutputPin> ActiveFourWire<Spi, ChipSelect> {
|
||||
|
|
@ -74,3 +80,17 @@ pub enum FourWireError<SpiError, ChipSelectError> {
|
|||
SpiError(SpiError),
|
||||
ChipSelectError(ChipSelectError),
|
||||
}
|
||||
|
||||
impl<SpiError, ChipSelectError> fmt::Debug for FourWireError<SpiError, ChipSelectError> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"FourWireError::{}",
|
||||
match self {
|
||||
Self::SpiError(_) => "SpiError",
|
||||
Self::ChipSelectError(_) => "ChipSelectError",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// TODO impl From and remove map_errs
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use core::fmt::Debug;
|
||||
use embedded_hal::spi::FullDuplex;
|
||||
|
||||
mod four_wire;
|
||||
|
|
@ -11,31 +12,27 @@ pub use self::three_wire::ThreeWire;
|
|||
pub trait Bus {}
|
||||
|
||||
pub trait ActiveBus {
|
||||
type Error;
|
||||
type Error: Debug;
|
||||
|
||||
fn transfer_frame<'a>(
|
||||
&mut self,
|
||||
block: u8,
|
||||
address: u16,
|
||||
is_write: bool,
|
||||
data: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], Self::Error>;
|
||||
fn read_frame(&mut self, block: u8, address: u16, data: &mut [u8]) -> Result<(), Self::Error>;
|
||||
|
||||
fn transfer_bytes<'a, Spi: FullDuplex<u8>>(
|
||||
spi: &mut Spi,
|
||||
bytes: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], Spi::Error> {
|
||||
fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error>;
|
||||
|
||||
fn read_bytes<Spi: FullDuplex<u8>>(spi: &mut Spi, bytes: &mut [u8]) -> Result<(), Spi::Error> {
|
||||
for byte in bytes.iter_mut() {
|
||||
Self::transfer_byte(spi, byte)?;
|
||||
*byte = Self::transfer_byte(spi, *byte)?;
|
||||
}
|
||||
Ok(bytes)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn transfer_byte<'a, Spi: FullDuplex<u8>>(
|
||||
spi: &mut Spi,
|
||||
byte: &'a mut u8,
|
||||
) -> Result<&'a mut u8, Spi::Error> {
|
||||
*byte = block!(spi.send(*byte)).and_then(|_| block!(spi.read()))?;
|
||||
Ok(byte)
|
||||
fn write_bytes<Spi: FullDuplex<u8>>(spi: &mut Spi, bytes: &[u8]) -> Result<(), Spi::Error> {
|
||||
for byte in bytes.iter() {
|
||||
Self::transfer_byte(spi, *byte)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn transfer_byte<Spi: FullDuplex<u8>>(spi: &mut Spi, byte: u8) -> Result<u8, Spi::Error> {
|
||||
block!(spi.send(byte)).and_then(|_| block!(spi.read()))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use byteorder::{BigEndian, ByteOrder};
|
||||
use core::fmt;
|
||||
use embedded_hal::spi::FullDuplex;
|
||||
|
||||
use crate::bus::{ActiveBus, Bus};
|
||||
|
|
@ -30,7 +30,7 @@ pub struct ActiveThreeWire<Spi: FullDuplex<u8>> {
|
|||
}
|
||||
|
||||
impl<Spi: FullDuplex<u8>> ActiveBus for ActiveThreeWire<Spi> {
|
||||
type Error = Spi::Error;
|
||||
type Error = ThreeWireError<Spi::Error>;
|
||||
|
||||
/// Transfers a frame with an arbitrary data length in FDM
|
||||
///
|
||||
|
|
@ -43,17 +43,13 @@ impl<Spi: FullDuplex<u8>> ActiveBus for ActiveThreeWire<Spi> {
|
|||
/// (address 23) 0xF0 0xAB 0x83 0xB2
|
||||
/// (address 27) 44 2C
|
||||
/// (address 29) AA
|
||||
fn transfer_frame<'a>(
|
||||
fn read_frame(
|
||||
&mut self,
|
||||
block: u8,
|
||||
mut address: u16,
|
||||
is_write: bool,
|
||||
data: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], Self::Error> {
|
||||
data: &mut [u8],
|
||||
) -> Result<(), Self::Error> {
|
||||
let mut control_phase = block << 3;
|
||||
if is_write {
|
||||
control_phase |= WRITE_MODE_MASK;
|
||||
}
|
||||
|
||||
let mut data_phase = &mut data[..];
|
||||
let mut last_length_written: u16;
|
||||
|
|
@ -69,19 +65,51 @@ impl<Spi: FullDuplex<u8>> ActiveBus for ActiveThreeWire<Spi> {
|
|||
last_length_written = 1;
|
||||
}
|
||||
|
||||
let mut address_phase = [0u8; 2];
|
||||
BigEndian::write_u16(&mut address_phase, address);
|
||||
Self::transfer_bytes(&mut self.spi, &mut address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, &mut control_phase))
|
||||
.and_then(|_| Self::transfer_bytes(
|
||||
&mut self.spi,
|
||||
&mut data_phase[..last_length_written as usize]
|
||||
))?;
|
||||
let address_phase = address.to_be_bytes();
|
||||
Self::write_bytes(&mut self.spi, &address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, control_phase))
|
||||
.and_then(|_| {
|
||||
Self::read_bytes(
|
||||
&mut self.spi,
|
||||
&mut data_phase[..last_length_written as usize],
|
||||
)
|
||||
})
|
||||
.map_err(|e| ThreeWireError::SpiError(e))?;
|
||||
|
||||
address += last_length_written;
|
||||
data_phase = &mut data_phase[last_length_written as usize..];
|
||||
}
|
||||
Ok(data_phase)
|
||||
Ok(())
|
||||
}
|
||||
fn write_frame(&mut self, block: u8, mut address: u16, data: &[u8]) -> Result<(), Self::Error> {
|
||||
let mut control_phase = block << 3 | WRITE_MODE_MASK;
|
||||
|
||||
let mut data_phase = &data[..];
|
||||
let mut last_length_written: u16;
|
||||
while data_phase.len() > 0 {
|
||||
if data_phase.len() >= 4 {
|
||||
control_phase |= FIXED_DATA_LENGTH_MODE_4;
|
||||
last_length_written = 4;
|
||||
} else if data_phase.len() >= 2 {
|
||||
control_phase |= FIXED_DATA_LENGTH_MODE_2;
|
||||
last_length_written = 2;
|
||||
} else {
|
||||
control_phase |= FIXED_DATA_LENGTH_MODE_1;
|
||||
last_length_written = 1;
|
||||
}
|
||||
|
||||
let address_phase = address.to_be_bytes();
|
||||
Self::write_bytes(&mut self.spi, &address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, control_phase))
|
||||
.and_then(|_| {
|
||||
Self::write_bytes(&mut self.spi, &data_phase[..last_length_written as usize])
|
||||
})
|
||||
.map_err(|e| ThreeWireError::SpiError(e))?;
|
||||
|
||||
address += last_length_written;
|
||||
data_phase = &data_phase[last_length_written as usize..];
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -90,3 +118,19 @@ impl<Spi: FullDuplex<u8>> ActiveThreeWire<Spi> {
|
|||
(ThreeWire::new(), self.spi)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ThreeWireError<SpiError> {
|
||||
SpiError(SpiError),
|
||||
}
|
||||
impl<SpiError> fmt::Debug for ThreeWireError<SpiError> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"ThreeWireError::{}",
|
||||
match self {
|
||||
Self::SpiError(_) => "SpiError",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// TODO impl From and remove map_errs
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue