Merge pull request #56 from LechevSpace/chore/four-wire-tests-and-docs

chore: test FourWire with embedded-hal-mock:
This commit is contained in:
Ryan Summers 2023-07-25 14:35:54 +02:00 committed by GitHub
commit f3f0f3e461
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 116 additions and 13 deletions

View file

@ -10,14 +10,17 @@ license = "MIT OR Apache-2.0"
readme = "README.md" readme = "README.md"
edition = "2018" edition = "2018"
[features]
no-chip-version-assertion = []
[dependencies] [dependencies]
byteorder = { version = "1.3.4", default-features = false } byteorder = { version = "1.3.4", default-features = false }
embedded-hal = "0.2.4" embedded-hal = "0.2"
embedded-nal = "0.6.0" embedded-nal = "0.6.0"
bit_field = "0.10.1" bit_field = "0.10"
derive-try-from-primitive = "1" derive-try-from-primitive = "1"
nb = "1.0.0" nb = "1.0.0"
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }
[features] [dev-dependencies]
no-chip-version-assertion = [] embedded-hal-mock = "0.9"

View file

@ -29,10 +29,13 @@ impl<Spi: Transfer<u8> + Write<u8>, ChipSelect: OutputPin> FourWire<Spi, ChipSel
impl<Spi: Transfer<u8> + Write<u8>, ChipSelect: OutputPin> Bus for FourWire<Spi, ChipSelect> { impl<Spi: Transfer<u8> + Write<u8>, ChipSelect: OutputPin> Bus for FourWire<Spi, ChipSelect> {
type Error = type Error =
FourWireError<<Spi as Transfer<u8>>::Error, <Spi as Write<u8>>::Error, ChipSelect::Error>; FourWireError<<Spi as Transfer<u8>>::Error, <Spi as Write<u8>>::Error, ChipSelect::Error>;
fn read_frame(&mut self, block: u8, address: u16, data: &mut [u8]) -> Result<(), Self::Error> { fn read_frame(&mut self, block: u8, address: u16, data: &mut [u8]) -> Result<(), Self::Error> {
let address_phase = address.to_be_bytes(); let address_phase = address.to_be_bytes();
let control_phase = block << 3; let control_phase = block << 3;
let data_phase = data; let data_phase = data;
// set Chip select to Low, i.e. prepare to receive data
self.cs.set_low().map_err(FourWireError::ChipSelectError)?; self.cs.set_low().map_err(FourWireError::ChipSelectError)?;
let result = (|| { let result = (|| {
self.spi self.spi
@ -44,29 +47,39 @@ impl<Spi: Transfer<u8> + Write<u8>, ChipSelect: OutputPin> Bus for FourWire<Spi,
.map_err(FourWireError::TransferError)?; .map_err(FourWireError::TransferError)?;
Ok(()) Ok(())
})(); })();
// set Chip select to High, i.e. we've finished listening
self.cs.set_high().map_err(FourWireError::ChipSelectError)?; self.cs.set_high().map_err(FourWireError::ChipSelectError)?;
// then return the result of the transmission
result result
} }
fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error> { fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error> {
let address_phase = address.to_be_bytes(); let address_phase = address.to_be_bytes();
let control_phase = block << 3 | WRITE_MODE_MASK; let control_phase = block << 3 | WRITE_MODE_MASK;
let data_phase = data; let data_phase = data;
// set Chip select to Low, i.e. prepare to transmit
self.cs.set_low().map_err(FourWireError::ChipSelectError)?; self.cs.set_low().map_err(FourWireError::ChipSelectError)?;
let result = (|| { let result = self
self.spi .spi
.write(&address_phase) .write(&address_phase)
.and_then(|_| self.spi.write(&[control_phase])) .and_then(|_| self.spi.write(&[control_phase]))
.and_then(|_| self.spi.write(data_phase)) .and_then(|_| self.spi.write(data_phase))
.map_err(FourWireError::WriteError)?; .map_err(FourWireError::WriteError);
Ok(())
})(); // set Chip select to High, i.e. we've finished transmitting
self.cs.set_high().map_err(FourWireError::ChipSelectError)?; self.cs.set_high().map_err(FourWireError::ChipSelectError)?;
// then return the result of the transmission
result result
} }
} }
// Must use map_err, ambiguity prevents From from being implemented // Must use map_err, ambiguity prevents From from being implemented
#[repr(u8)] #[repr(u8)]
#[derive(Clone)]
pub enum FourWireError<TransferError, WriteError, ChipSelectError> { pub enum FourWireError<TransferError, WriteError, ChipSelectError> {
TransferError(TransferError), TransferError(TransferError),
WriteError(WriteError), WriteError(WriteError),
@ -91,3 +104,90 @@ impl<TransferError, WriteError, ChipSelectError> fmt::Debug
// TODO Improved error rendering could be done with specialization. // TODO Improved error rendering could be done with specialization.
// https://github.com/rust-lang/rust/issues/31844 // https://github.com/rust-lang/rust/issues/31844
#[cfg(test)]
mod test {
use embedded_hal::digital::v2::OutputPin;
use embedded_hal_mock::{
pin::{Mock as PinMock, State as PinState, Transaction as PinTransaction},
spi::{Mock as SpiMock, Transaction as SpiTransaction},
};
use crate::{
bus::{four_wire::WRITE_MODE_MASK, Bus},
register,
};
use super::FourWire;
#[test]
fn test_read_frame() {
let mut cs_pin = PinMock::new(&[
// we begin with pin HIGH
PinTransaction::set(PinState::High),
// When reading
PinTransaction::set(PinState::Low),
// When finished reading
PinTransaction::set(PinState::High),
]);
// initiate the pin to high.
cs_pin.set_high().expect("Should set pin to high");
let mut actual_version = [0_u8; 1];
let mut expected_version = 5;
let expectations = [
SpiTransaction::write(register::common::VERSION.to_be_bytes().to_vec()),
SpiTransaction::write(vec![register::COMMON << 3]),
SpiTransaction::transfer(actual_version.to_vec(), vec![expected_version]),
];
let mock_spi = SpiMock::new(&expectations);
let mut four_wire = FourWire::new(mock_spi, cs_pin);
four_wire.read_frame(
register::COMMON,
register::common::VERSION,
&mut actual_version,
);
assert_eq!(expected_version, actual_version[0]);
}
#[test]
fn test_write_frame() {
let mut cs_pin = PinMock::new(&[
// we begin with pin HIGH
PinTransaction::set(PinState::High),
// When reading
PinTransaction::set(PinState::Low),
// When finished reading
PinTransaction::set(PinState::High),
]);
// initiate the pin to high.
cs_pin.set_high().expect("Should set pin to high");
let socket_0_reg = 0x01_u8;
let socket_1_reg = 0x05_u8;
let source_port = 49849_u16;
let expectations = [
SpiTransaction::write(register::socketn::SOURCE_PORT.to_be_bytes().to_vec()),
SpiTransaction::write(vec![socket_1_reg << 3 | WRITE_MODE_MASK]),
SpiTransaction::write(source_port.to_be_bytes().to_vec()),
];
let mock_spi = SpiMock::new(&expectations);
let mut four_wire = FourWire::new(mock_spi, cs_pin);
four_wire.write_frame(
socket_1_reg,
register::socketn::SOURCE_PORT,
&source_port.to_be_bytes(),
);
}
}

View file

@ -1,4 +1,4 @@
#![no_std] #![cfg_attr(not(test), no_std)]
#![allow(unused)] #![allow(unused)]
#![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::broken_intra_doc_links)]
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]