diff --git a/.github/bors.toml b/.github/bors.toml deleted file mode 100644 index 1779788..0000000 --- a/.github/bors.toml +++ /dev/null @@ -1,2 +0,0 @@ -status = ["ci"] -delete_merged_branches = true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 757f62a..d6ec01f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,43 +1,72 @@ -on: push - name: ci +on: [push, pull_request] jobs: - ci: + name: Check build + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo check --release + + cross-check: + name: Check Cross-Compilation runs-on: ubuntu-latest strategy: matrix: - rust: - - stable target: - - x86_64-unknown-linux-gnu - - thumbv6m-none-eabi - armv7-unknown-linux-gnueabihf - thumbv7em-none-eabihf - steps: - - uses: actions/checkout@v2 - - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable with: - profile: minimal - toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true - components: rustfmt, clippy + targets: "armv7-unknown-linux-gnueabihf, thumbv7em-none-eabihf" + - run: cargo check --release --target=${{matrix.target}} --no-default-features - - uses: actions-rs/cargo@v1 - with: - use-cross: true - command: check + check: + test: + name: Run Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - name: Install nextest + uses: taiki-e/install-action@nextest + - run: cargo nextest run --all-features + - run: cargo test --doc - - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + msrv: + name: Check MSRV + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@1.68.2 + - run: cargo check --release - - uses: actions-rs/cargo@v1 - with: - use-cross: true - command: clippy - args: -- -D warnings + fmt: + name: Check formatting + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo fmt --all -- --check + + docs: + name: Check Documentation Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo +nightly doc --all-features --config 'build.rustdocflags=["--cfg", "docs_rs"]' + + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo clippy -- -D warnings diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d46aff..773aa5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [unreleased] +## [v0.3.0] + +- Update `embedded-hal` to v1. +- Add optional `defmt` feature. + ## [v0.2.1] - README tweaks diff --git a/Cargo.toml b/Cargo.toml index 7f786b3..c1910e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "max116xx-10bit" -version = "0.2.1" +version = "0.3.0" authors = ["Robin Mueller "] edition = "2021" description = "Driver crate for the MAX116xx 10-bit ADC devices" @@ -12,5 +12,10 @@ categories = ["embedded", "no-std", "hardware-support"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -embedded-hal = { version = "0.2.6", features = ["unproven"] } -nb = "1.0.0" +embedded-hal = "1" +nb = "1" +defmt = { version = "0.3", optional = true } + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docs_rs", "--generate-link-to-definition"] diff --git a/src/lib.rs b/src/lib.rs index 5421eae..3050dba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,13 +21,12 @@ //! You can find an example application [here](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/examples/max11619-adc.rs) //! using a [thin abstraction layer](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/src/max11619.rs) #![no_std] +#![cfg_attr(docs_rs, feature(doc_auto_cfg))] +use core::convert::Infallible; use core::{marker::PhantomData, slice::IterMut}; -use embedded_hal::{ - blocking::delay::DelayUs, - blocking::spi::Transfer, - digital::v2::{InputPin, OutputPin}, - spi::FullDuplex, -}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; //================================================================================================== // Type-level support @@ -90,15 +89,15 @@ impl HasChannels for Max11625 { const NUM: u8 = 16; } -pub trait Clocked: private::Sealed { +pub trait ClockedProvider: private::Sealed { const CLK_SEL: ClockMode; } -pub trait InternallyClocked: Clocked {} +pub trait InternallyClocked: ClockedProvider {} pub struct InternallyClockedInternallyTimedCnvst {} impl private::Sealed for InternallyClockedInternallyTimedCnvst {} -impl Clocked for InternallyClockedInternallyTimedCnvst { +impl ClockedProvider for InternallyClockedInternallyTimedCnvst { const CLK_SEL: ClockMode = ClockMode::InternalClockInternallyTimedCnvst; } impl InternallyClocked for InternallyClockedInternallyTimedCnvst {} @@ -106,7 +105,7 @@ type IntClkdIntTmdCnvst = InternallyClockedInternallyTimedCnvst; pub struct InternallyClockedExternallyTimedCnvst {} impl private::Sealed for InternallyClockedExternallyTimedCnvst {} -impl Clocked for InternallyClockedExternallyTimedCnvst { +impl ClockedProvider for InternallyClockedExternallyTimedCnvst { const CLK_SEL: ClockMode = ClockMode::InternalClockExternallyTimedCnvst; } impl InternallyClocked for InternallyClockedExternallyTimedCnvst {} @@ -114,7 +113,7 @@ type IntClkdExtTmdCnvst = InternallyClockedExternallyTimedCnvst; pub struct InternallyClockedInternallyTimedSerialInterface {} impl private::Sealed for InternallyClockedInternallyTimedSerialInterface {} -impl Clocked for InternallyClockedInternallyTimedSerialInterface { +impl ClockedProvider for InternallyClockedInternallyTimedSerialInterface { const CLK_SEL: ClockMode = ClockMode::InternalClockInternallyTimedSerialInterface; } impl InternallyClocked for InternallyClockedInternallyTimedSerialInterface {} @@ -122,7 +121,7 @@ type IntClkdIntTmdSerIF = InternallyClockedInternallyTimedSerialInterface; pub struct ExternallyClocked {} impl private::Sealed for ExternallyClocked {} -impl Clocked for ExternallyClocked { +impl ClockedProvider for ExternallyClocked { const CLK_SEL: ClockMode = ClockMode::ExternalClockExternallyTimedSclk; } type ExtClkd = ExternallyClocked; @@ -133,6 +132,7 @@ type ExtClkd = ExternallyClocked; /// Clock modes for the MAX116XX devices #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ClockMode { /// Internally timed, CNVST only needs to be pulsed for 40ns. /// CNVST Configuration: CNVST active low @@ -149,6 +149,7 @@ pub enum ClockMode { /// Voltage reference modes #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum VoltageRefMode { /// Auto-Shutdown is on, wake-up delay of 65 us InternalRefWithWakeupDelay = 0b00, @@ -158,6 +159,7 @@ pub enum VoltageRefMode { /// Specifies how many conversions are performed and then averaged for each /// requested result +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AveragingConversions { OneConversion = 0b000, FourConversions = 0b100, @@ -168,6 +170,7 @@ pub enum AveragingConversions { /// Specifies the number of returned result in single scan mode #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AveragingResults { FourResults = 0b00, EightResults = 0b01, @@ -176,6 +179,7 @@ pub enum AveragingResults { } #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ScanMode { Scan0ToChannelN = 0b00, ScanChannelNToHighest = 0b01, @@ -184,6 +188,7 @@ pub enum ScanMode { } #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AdcError { InvalidChannel, InvalidRefMode, @@ -208,6 +213,8 @@ impl From for Error { } } +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct InternalCfg { clk_mode: ClockMode, ref_mode: VoltageRefMode, @@ -216,25 +223,25 @@ struct InternalCfg { results_len: u8, requested_conversions: usize, } + //================================================================================================== // ADC implementation //================================================================================================== -pub struct Max116xx10Bit { - spi: SPI, - cs: CS, +pub struct Max116xx10Bit { + spi: Spi, cfg: InternalCfg, - clocked: PhantomData, - delay: PhantomData, + clocked: PhantomData, + delay: PhantomData, } -pub struct Max116xx10BitEocExt { - base: Max116xx10Bit, +pub struct Max116xx10BitEocExt { + base: Max116xx10Bit, eoc: EOC, } -pub struct Max116xx10BitCnvstEocExt { - base: Max116xx10Bit, +pub struct Max116xx10BitCnvstEocExt { + base: Max116xx10Bit, eoc: EOC, cnvst: CNVST, } @@ -243,28 +250,24 @@ pub struct Max116xx10BitCnvstEocExt Max116xx10Bit -where - SPI: Transfer + FullDuplex, - CS: OutputPin, -{ - pub fn max11618(spi: SPI, cs: CS) -> Result> { - Self::new::(spi, cs) +impl Max116xx10Bit { + pub fn max11618(spi: Spi) -> Result> { + Self::new::(spi) } - pub fn max11619(spi: SPI, cs: CS) -> Result> { - Self::new::(spi, cs) + pub fn max11619(spi: Spi) -> Result> { + Self::new::(spi) } - pub fn max11620(spi: SPI, cs: CS) -> Result> { - Self::new::(spi, cs) + pub fn max11620(spi: Spi) -> Result> { + Self::new::(spi) } - pub fn max11621(spi: SPI, cs: CS) -> Result> { - Self::new::(spi, cs) + pub fn max11621(spi: Spi) -> Result> { + Self::new::(spi) } - pub fn max11624(spi: SPI, cs: CS) -> Result> { - Self::new::(spi, cs) + pub fn max11624(spi: Spi) -> Result> { + Self::new::(spi) } - pub fn max11625(spi: SPI, cs: CS) -> Result> { - Self::new::(spi, cs) + pub fn max11625(spi: Spi) -> Result> { + Self::new::(spi) } /// Create a new generic MAX116xx instance. By default the generated ADC struct is configured @@ -274,10 +277,9 @@ where /// /// The corresponding SETUP register is `0b0111_0100` /// Please note that you still might have to reset and setup the ADC. - pub fn new(spi: SPI, cs: CS) -> Result> { + pub fn new(spi: Spi) -> Result> { let max_dev = Max116xx10Bit { spi, - cs, cfg: InternalCfg { clk_mode: ExtClkd::CLK_SEL, ref_mode: VoltageRefMode::ExternalSingleEndedNoWakeupDelay, @@ -298,10 +300,9 @@ where /// The corresponding SETUP register is `0b0111_0000` pub fn into_ext_clkd_with_int_ref_wakeup_delay( self, - ) -> Max116xx10Bit { + ) -> Max116xx10Bit { Max116xx10Bit { spi: self.spi, - cs: self.cs, cfg: InternalCfg { clk_mode: ExtClkd::CLK_SEL, ref_mode: VoltageRefMode::InternalRefWithWakeupDelay, @@ -321,10 +322,9 @@ where /// The corresponding SETUP register is `0b0111_1000` pub fn into_ext_clkd_with_int_ref_no_wakeup_delay( self, - ) -> Max116xx10Bit { + ) -> Max116xx10Bit { Max116xx10Bit { spi: self.spi, - cs: self.cs, cfg: InternalCfg { clk_mode: ExtClkd::CLK_SEL, ref_mode: VoltageRefMode::InternalRefWithoutWakeupDelay, @@ -342,14 +342,13 @@ where /// and a wakeup delay. This can be used to reduce power consumption /// /// The corresponding SETUP register is `0b0110_1100` - pub fn into_int_clkd_int_timed_through_ser_if_with_wakeup>( + pub fn into_int_clkd_int_timed_through_ser_if_with_wakeup( self, - eoc: EOC, - ) -> Max116xx10BitEocExt { + eoc: Eoc, + ) -> Max116xx10BitEocExt { Max116xx10BitEocExt { base: Max116xx10Bit { spi: self.spi, - cs: self.cs, cfg: InternalCfg { clk_mode: IntClkdIntTmdSerIF::CLK_SEL, ref_mode: VoltageRefMode::InternalRefWithWakeupDelay, @@ -371,18 +370,17 @@ where /// The corresponding SETUP register can be one of the two /// - External Voltage reference: `0b0110_0100` /// - Internal Voltage reference always on: `0b0110_1000` - pub fn into_int_clkd_int_timed_through_ser_if_without_wakeup>( + pub fn into_int_clkd_int_timed_through_ser_if_without_wakeup( self, v_ref: VoltageRefMode, - eoc: EOC, - ) -> Result, AdcError> { + eoc: Eoc, + ) -> Result, AdcError> { if v_ref == VoltageRefMode::InternalRefWithWakeupDelay { return Err(AdcError::InvalidRefMode); } Ok(Max116xx10BitEocExt { base: Max116xx10Bit { spi: self.spi, - cs: self.cs, cfg: InternalCfg { clk_mode: IntClkdIntTmdSerIF::CLK_SEL, ref_mode: VoltageRefMode::InternalRefWithWakeupDelay, @@ -399,22 +397,16 @@ where } } -impl Max116xx10Bit -where - SPI: Transfer + FullDuplex, - CS: OutputPin, -{ +impl Max116xx10Bit { #[inline] - fn send_wrapper(&mut self, byte: u8) -> Result<(), Error> { - self.cs.set_low().map_err(Error::Pin)?; - nb::block!(self.spi.send(byte)).map_err(Error::Spi)?; - self.cs.set_high().map_err(Error::Pin)?; + fn send_wrapper(&mut self, byte: u8) -> Result<(), Error> { + self.spi.write(&[byte]).map_err(Error::Spi)?; Ok(()) } /// Set up the ADC depending on clock and reference configuration #[inline] - pub fn setup(&mut self) -> Result<(), Error> { + pub fn setup(&mut self) -> Result<(), Error> { self.send_wrapper(self.get_setup_byte()) } @@ -425,13 +417,13 @@ where &mut self, avg_conv: AveragingConversions, avg_res: AveragingResults, - ) -> Result<(), Error> { + ) -> Result<(), Error> { self.cfg.results_len = Self::get_results_len(avg_res); self.send_wrapper(Self::get_averaging_byte(avg_conv, avg_res)) } #[inline] - pub fn reset(&mut self, fifo_only: bool) -> Result<(), Error> { + pub fn reset(&mut self, fifo_only: bool) -> Result<(), Error> { let mut reset_byte = 0b0001_0000; if fifo_only { reset_byte |= 1 << 3; @@ -468,24 +460,22 @@ where /// Generic function which can be used a single result is available /// when EOC is low - fn internal_read_single_channel>( + fn internal_read_single_channel( &mut self, - eoc: &mut EOC, - ) -> nb::Result> { + eoc: &mut Eoc, + ) -> nb::Result> { if self.cfg.pending_scan_mode.is_none() { return Err(nb::Error::Other(Error::Adc(AdcError::NoPendingOperation))); } else if self.cfg.pending_scan_mode != Some(ScanMode::ConvertChannelNOnce) { return Err(nb::Error::Other(Error::Adc(AdcError::PendingOperation))); } if eoc.is_low().map_err(Error::Pin)? { - let mut dummy_cmd: [u8; 2] = [0; 2]; - self.cs.set_low().map_err(Error::Pin)?; - let transfer_result = self.spi.transfer(&mut dummy_cmd); - self.cs.set_high().map_err(Error::Pin)?; + let mut reply_buf: [u8; 2] = [0; 2]; + let transfer_result = self.spi.read(&mut reply_buf); match transfer_result { - Ok(reply) => { + Ok(_) => { self.cfg.pending_scan_mode = None; - Ok(((reply[0] as u16) << 6) | (reply[1] as u16 >> 2)) + Ok(((reply_buf[0] as u16) << 6) | (reply_buf[1] as u16 >> 2)) } Err(e) => Err(nb::Error::Other(Error::Spi(e))), } @@ -499,7 +489,7 @@ macro_rules! ext_impl { () => { /// Set up the ADC depending on clock and reference configuration #[inline] - pub fn setup(&mut self) -> Result<(), Error> { + pub fn setup(&mut self) -> Result<(), Error> { self.base.send_wrapper(self.base.get_setup_byte()) } @@ -510,16 +500,16 @@ macro_rules! ext_impl { &mut self, avg_conv: AveragingConversions, avg_res: AveragingResults, - ) -> Result<(), Error> { - self.base.cfg.results_len = Max116xx10Bit::::get_results_len(avg_res); + ) -> Result<(), Error> { + self.base.cfg.results_len = Max116xx10Bit::::get_results_len(avg_res); self.base - .send_wrapper(Max116xx10Bit::::get_averaging_byte( + .send_wrapper(Max116xx10Bit::::get_averaging_byte( avg_conv, avg_res, )) } #[inline] - pub fn reset(&mut self, fifo_only: bool) -> Result<(), Error> { + pub fn reset(&mut self, fifo_only: bool) -> Result<(), Error> { let mut reset_byte = 0b0001_0000; if fifo_only { reset_byte |= 1 << 3; @@ -528,19 +518,12 @@ macro_rules! ext_impl { } }; } -impl Max116xx10BitEocExt -where - SPI: Transfer + FullDuplex, - CS: OutputPin, -{ +impl Max116xx10BitEocExt { ext_impl!(); } -impl - Max116xx10BitCnvstEocExt -where - SPI: Transfer + FullDuplex, - CS: OutputPin, +impl + Max116xx10BitCnvstEocExt { ext_impl!(); } @@ -550,26 +533,20 @@ where //================================================================================================== /// Implementations when using the external SPI clock to time the conversions -impl Max116xx10Bit -where - SPI: Transfer + FullDuplex, - CS: OutputPin, -{ +impl Max116xx10Bit { pub fn read_single_channel( &mut self, buf: &mut [u8], channel_num: u8, - ) -> Result> { + ) -> Result> { if buf.len() < 3 { return Err(Error::Adc(AdcError::CmdBufTooSmall)); } buf[0] = self.get_conversion_byte(ScanMode::ConvertChannelNOnce, channel_num)?; buf[1] = 0x00; buf[2] = 0x00; - self.cs.set_low().map_err(Error::Pin)?; - let reply = self.spi.transfer(&mut buf[0..3]).ok().unwrap(); - self.cs.set_high().map_err(Error::Pin)?; - Ok(((reply[1] as u16) << 6) | (reply[2] as u16 >> 2)) + self.spi.transfer_in_place(&mut buf[0..3]).ok().unwrap(); + Ok(((buf[1] as u16) << 6) | (buf[2] as u16 >> 2)) } pub fn read_multiple_channels_0_to_n( @@ -577,7 +554,7 @@ where buf: &mut [u8], result_iter: &mut IterMut, n: u8, - ) -> Result<(), Error> { + ) -> Result<(), Error> { let mut iter = buf.iter_mut(); let mut next_byte: &mut u8; for idx in 0..n + 1 { @@ -588,13 +565,10 @@ where } next_byte = iter.next().ok_or(Error::Adc(AdcError::CmdBufTooSmall))?; *next_byte = 0x00; - self.cs.set_low().map_err(Error::Pin)?; - let reply = self - .spi - .transfer(&mut buf[0..((n + 1) * 2 + 1) as usize]) + self.spi + .transfer_in_place(&mut buf[0..((n + 1) * 2 + 1) as usize]) .map_err(Error::Spi)?; - self.cs.set_high().map_err(Error::Pin)?; - let mut reply_iter = reply.iter(); + let mut reply_iter = buf.iter(); // Skip first reply byte reply_iter.next().unwrap(); for _ in 0..n + 1 { @@ -612,7 +586,7 @@ where buf: &mut [u8], result_iter: &mut IterMut, n: u8, - ) -> Result<(), Error> { + ) -> Result<(), Error> { let mut iter = buf.iter_mut(); let mut next_byte: &mut u8; if n > self.cfg.max_channels - 1 { @@ -627,13 +601,10 @@ where } next_byte = iter.next().ok_or(Error::Adc(AdcError::CmdBufTooSmall))?; *next_byte = 0x00; - self.cs.set_low().map_err(Error::Pin)?; - let reply = self - .spi - .transfer(&mut buf[0..(conversions * 2 + 1) as usize]) + self.spi + .transfer_in_place(&mut buf[0..(conversions * 2 + 1) as usize]) .map_err(Error::Spi)?; - self.cs.set_high().map_err(Error::Pin)?; - let mut reply_iter = reply.iter(); + let mut reply_iter = buf.iter(); // Skip first reply byte reply_iter.next().unwrap(); for _ in 0..conversions { @@ -649,17 +620,13 @@ where /// Implementations when using the external SPI clock to time the conversions but also requiring /// a wakeup delay -impl Max116xx10Bit -where - SPI: Transfer + FullDuplex, - CS: OutputPin, -{ - pub fn read_single_channel>( +impl Max116xx10Bit { + pub fn read_single_channel( &mut self, buf: &mut [u8], channel_num: u8, - delay: &mut DELAY, - ) -> Result> { + delay: &mut Delay, + ) -> Result> { if buf.len() < 3 { return Err(Error::Adc(AdcError::CmdBufTooSmall)); } @@ -670,19 +637,19 @@ where delay.delay_us(65); buf[0] = 0x00; buf[1] = 0x00; - self.cs.set_low().map_err(Error::Pin)?; - let reply = self.spi.transfer(&mut buf[0..2]).map_err(Error::Spi)?; - self.cs.set_high().map_err(Error::Pin)?; - Ok(((reply[0] as u16) << 6) | (reply[1] as u16 >> 2)) + self.spi + .transfer_in_place(&mut buf[0..2]) + .map_err(Error::Spi)?; + Ok(((buf[0] as u16) << 6) | (buf[1] as u16 >> 2)) } - pub fn read_multiple_channels_0_to_n>( + pub fn read_multiple_channels_0_to_n( &mut self, buf: &mut [u8], result_iter: &mut IterMut, n: u8, - delay: &mut DELAY, - ) -> Result<(), Error> { + delay: &mut Delay, + ) -> Result<(), Error> { let mut iter = buf.iter_mut(); let mut next_byte: &mut u8; for idx in 0..n + 1 { @@ -697,13 +664,10 @@ where self.send_wrapper(buf[0])?; delay.delay_us(65); - self.cs.set_low().map_err(Error::Pin)?; - let reply = self - .spi - .transfer(&mut buf[1..((n + 1) * 2 + 1) as usize]) + self.spi + .transfer_in_place(&mut buf[1..((n + 1) * 2 + 1) as usize]) .map_err(Error::Spi)?; - self.cs.set_high().map_err(Error::Pin)?; - let mut reply_iter = reply.iter(); + let mut reply_iter = buf.iter(); for _ in 0..n + 1 { let next_res = result_iter .next() @@ -714,13 +678,13 @@ where Ok(()) } - pub fn read_multiple_channels_n_to_highest>( + pub fn read_multiple_channels_n_to_highest( &mut self, buf: &mut [u8], result_iter: &mut IterMut, n: u8, - delay: &mut DELAY, - ) -> Result<(), Error> { + delay: &mut Delay, + ) -> Result<(), Error> { let mut iter = buf.iter_mut(); let mut next_byte: &mut u8; if n > self.cfg.max_channels - 1 { @@ -739,13 +703,10 @@ where // reference to power up self.send_wrapper(buf[0])?; delay.delay_us(65); - self.cs.set_low().map_err(Error::Pin)?; - let reply = self - .spi - .transfer(&mut buf[1..(conversions * 2 + 1) as usize]) + self.spi + .transfer_in_place(&mut buf[1..(conversions * 2 + 1) as usize]) .map_err(Error::Spi)?; - self.cs.set_high().map_err(Error::Pin)?; - let mut reply_iter = reply.iter(); + let mut reply_iter = buf.iter(); for _ in 0..conversions { let next_res = result_iter .next() @@ -763,18 +724,13 @@ where /// Implementations when using the internal clock with a conversion started /// through the serial interface -impl Max116xx10BitEocExt -where - SPI: Transfer + FullDuplex, - CS: OutputPin, - EOC: InputPin, -{ +impl Max116xx10BitEocExt { #[inline] fn request_wrapper( &mut self, channel_num: u8, scan_mode: ScanMode, - ) -> Result<(), Error> { + ) -> Result<(), Error> { if self.base.cfg.pending_scan_mode.is_some() { return Err(Error::Adc(AdcError::PendingOperation)); } @@ -782,12 +738,15 @@ where .base .get_conversion_byte(scan_mode, channel_num) .map_err(Error::Adc)?; - self.base.send_wrapper(conv_byte)?; + self.base.send_wrapper(conv_byte).ok(); self.base.cfg.pending_scan_mode = Some(scan_mode); Ok(()) } - pub fn request_single_channel(&mut self, channel_num: u8) -> Result<(), Error> { + pub fn request_single_channel( + &mut self, + channel_num: u8, + ) -> Result<(), Error> { self.request_wrapper(channel_num, ScanMode::ConvertChannelNOnce) } @@ -797,11 +756,14 @@ where pub fn request_channel_n_repeatedly( &mut self, channel_num: u8, - ) -> Result<(), Error> { + ) -> Result<(), Error> { self.request_wrapper(channel_num, ScanMode::ScanChannelNRepeatedly) } - pub fn request_multiple_channels_0_to_n(&mut self, n: u8) -> Result<(), Error> { + pub fn request_multiple_channels_0_to_n( + &mut self, + n: u8, + ) -> Result<(), Error> { self.base.cfg.requested_conversions = n as usize + 1; self.request_wrapper(n, ScanMode::Scan0ToChannelN) } @@ -809,7 +771,7 @@ where pub fn request_multiple_channels_n_to_highest( &mut self, n: u8, - ) -> Result<(), Error> { + ) -> Result<(), Error> { self.base.cfg.requested_conversions = self.base.cfg.max_channels as usize + 1 - n as usize; self.request_wrapper(n, ScanMode::ScanChannelNToHighest) } @@ -818,7 +780,7 @@ where /// needs to be passed explicitely here. /// If no request was made, [AdcError::NoPendingOperation] is returned. /// If a request was made for multipel results, [AdcError::PendingOperation] will be returned. - pub fn get_single_channel(&mut self) -> nb::Result> { + pub fn get_single_channel(&mut self) -> nb::Result> { self.base.internal_read_single_channel(&mut self.eoc) } @@ -828,7 +790,7 @@ where pub fn get_multi_channel( &mut self, result_iter: &mut IterMut, - ) -> nb::Result<(), Error> { + ) -> nb::Result<(), Error> { if self.base.cfg.pending_scan_mode.is_none() { return Err(nb::Error::Other(Error::Adc(AdcError::NoPendingOperation))); } else if self.base.cfg.pending_scan_mode == Some(ScanMode::ConvertChannelNOnce) { @@ -836,7 +798,7 @@ where } if self.eoc.is_low().map_err(Error::Pin)? { // maximum length of reply is 32 for 16 channels - let mut dummy_cmd: [u8; 32] = [0; 32]; + let mut reply_buf: [u8; 32] = [0; 32]; let num_conv: usize = if self.base.cfg.pending_scan_mode == Some(ScanMode::ScanChannelNRepeatedly) { self.base.cfg.results_len as usize @@ -845,23 +807,19 @@ where }; self.base.cfg.pending_scan_mode = None; self.base.cfg.requested_conversions = 0; - self.base.cs.set_low().map_err(Error::Pin)?; - let transfer_result = self.base.spi.transfer(&mut dummy_cmd[0..(num_conv * 2)]); - self.base.cs.set_high().map_err(Error::Pin)?; - match transfer_result { - Ok(reply) => { - let mut reply_iter = reply.iter(); - for _ in 0..num_conv { - let next_res = result_iter - .next() - .ok_or(Error::Adc(AdcError::ResulBufTooSmall))?; - *next_res = ((*reply_iter.next().unwrap() as u16) << 6) - | (*reply_iter.next().unwrap() as u16 >> 2); - } - Ok(()) - } - Err(e) => Err(nb::Error::Other(Error::Spi(e))), + self.base + .spi + .read(&mut reply_buf[0..(num_conv * 2)]) + .map_err(Error::Spi)?; + let mut reply_iter = reply_buf.iter(); + for _ in 0..num_conv { + let next_res = result_iter + .next() + .ok_or(Error::Adc(AdcError::ResulBufTooSmall))?; + *next_res = ((*reply_iter.next().unwrap() as u16) << 6) + | (*reply_iter.next().unwrap() as u16 >> 2); } + Ok(()) } else { Err(nb::Error::WouldBlock) } @@ -877,17 +835,9 @@ where /// /// TODO: Implement. Unfortunately, the test board used to verify this library did not have /// the CNVST connected, so I wouldn't be able to test an implementation easily. -impl - Max116xx10BitCnvstEocExt -where - SPI: Transfer + FullDuplex, - CS: OutputPin, - EOC: InputPin, - CNVST: OutputPin, +impl + Max116xx10BitCnvstEocExt { - pub fn dummy() { - todo!("Implement this") - } } /// Implementations when using the internal clock where CNVST is only pulsed to start acquisition @@ -895,13 +845,8 @@ where /// /// TODO: Test. Unfortunately, the test board used to verify this library did not have /// the CNVST connected, so I wouldn't be able to test an implementation easily. -impl - Max116xx10BitCnvstEocExt -where - SPI: Transfer + FullDuplex, - CS: OutputPin, - EOC: InputPin, - CNVST: OutputPin, +impl, Cnvst: OutputPin, PinE> + Max116xx10BitCnvstEocExt { /// The pulse needs to be at least 40ns. A pulse cycle value can be used to increase /// the width of the pulse @@ -909,7 +854,7 @@ where &mut self, channel_num: u8, pulse_cycles: u8, - ) -> Result<(), Error> { + ) -> Result<(), Error> { self.request_wrapper(channel_num, ScanMode::ConvertChannelNOnce, pulse_cycles) } @@ -919,7 +864,7 @@ where channel_num: u8, scan_mode: ScanMode, pulse_cycles: u8, - ) -> Result<(), Error> { + ) -> Result<(), Error> { if self.base.cfg.pending_scan_mode.is_some() { return Err(Error::Adc(AdcError::PendingOperation)); } @@ -927,7 +872,7 @@ where .base .get_conversion_byte(scan_mode, channel_num) .map_err(Error::Adc)?; - self.base.send_wrapper(conv_byte)?; + self.base.send_wrapper(conv_byte).ok(); self.cnvst.set_low().map_err(Error::Pin)?; for _ in 0..pulse_cycles {} self.cnvst.set_high().map_err(Error::Pin)?; @@ -935,7 +880,7 @@ where Ok(()) } - pub fn get_single_channel(&mut self) -> nb::Result> { + pub fn get_single_channel(&mut self) -> nb::Result> { self.base.internal_read_single_channel(&mut self.eoc) } }