diff --git a/Cargo.toml b/Cargo.toml index 7b7c523..6652d97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,14 +10,17 @@ license = "MIT OR Apache-2.0" readme = "README.md" edition = "2018" +[features] +no-chip-version-assertion = [] + [dependencies] byteorder = { version = "1.3.4", default-features = false } -embedded-hal = "0.2.4" +embedded-hal = "0.2" embedded-nal = "0.6.0" -bit_field = "0.10.1" +bit_field = "0.10" derive-try-from-primitive = "1" nb = "1.0.0" defmt = { version = "0.3", optional = true } -[features] -no-chip-version-assertion = [] +[dev-dependencies] +embedded-hal-mock = "0.9" \ No newline at end of file diff --git a/src/bus/four_wire.rs b/src/bus/four_wire.rs index f33f5d5..4640191 100644 --- a/src/bus/four_wire.rs +++ b/src/bus/four_wire.rs @@ -29,10 +29,13 @@ impl + Write, ChipSelect: OutputPin> FourWire + Write, ChipSelect: OutputPin> Bus for FourWire { type Error = FourWireError<>::Error, >::Error, ChipSelect::Error>; + 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; + + // set Chip select to Low, i.e. prepare to receive data self.cs.set_low().map_err(FourWireError::ChipSelectError)?; let result = (|| { self.spi @@ -44,29 +47,39 @@ impl + Write, ChipSelect: OutputPin> Bus for FourWire Result<(), Self::Error> { let address_phase = address.to_be_bytes(); let control_phase = block << 3 | WRITE_MODE_MASK; let data_phase = data; + + // set Chip select to Low, i.e. prepare to transmit self.cs.set_low().map_err(FourWireError::ChipSelectError)?; - let result = (|| { - self.spi - .write(&address_phase) - .and_then(|_| self.spi.write(&[control_phase])) - .and_then(|_| self.spi.write(data_phase)) - .map_err(FourWireError::WriteError)?; - Ok(()) - })(); + let result = self + .spi + .write(&address_phase) + .and_then(|_| self.spi.write(&[control_phase])) + .and_then(|_| self.spi.write(data_phase)) + .map_err(FourWireError::WriteError); + + // set Chip select to High, i.e. we've finished transmitting self.cs.set_high().map_err(FourWireError::ChipSelectError)?; + + // then return the result of the transmission result } } // Must use map_err, ambiguity prevents From from being implemented #[repr(u8)] +#[derive(Clone)] pub enum FourWireError { TransferError(TransferError), WriteError(WriteError), @@ -91,3 +104,90 @@ impl fmt::Debug // TODO Improved error rendering could be done with specialization. // 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(), + ); + } +} diff --git a/src/lib.rs b/src/lib.rs index 475ba9e..9c430ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![no_std] +#![cfg_attr(not(test), no_std)] #![allow(unused)] #![deny(rustdoc::broken_intra_doc_links)] #![doc = include_str!("../README.md")]