embedded HAL v1 and defmt support #2

Merged
muellerr merged 3 commits from bump-embedded-hal into main 2024-06-16 15:57:06 +02:00
3 changed files with 143 additions and 159 deletions
Showing only changes of commit a69671ce22 - Show all commits

View File

@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased] ## [unreleased]
## [v0.3.0]
- Update `embedded-hal` to v1.
- Add optional `defmt` feature.
## [v0.2.1] ## [v0.2.1]
- README tweaks - README tweaks

View File

@ -1,6 +1,6 @@
[package] [package]
name = "max116xx-10bit" name = "max116xx-10bit"
version = "0.2.1" version = "0.3.0"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"] authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
edition = "2021" edition = "2021"
description = "Driver crate for the MAX116xx 10-bit ADC devices" description = "Driver crate for the MAX116xx 10-bit ADC devices"
@ -12,5 +12,6 @@ categories = ["embedded", "no-std", "hardware-support"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
embedded-hal = { version = "0.2.6", features = ["unproven"] } embedded-hal = "1"
nb = "1.0.0" nb = "1"
defmt = { version = "0.3", optional = true }

View File

@ -22,12 +22,9 @@
//! using a [thin abstraction layer](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/src/max11619.rs) //! using a [thin abstraction layer](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/src/max11619.rs)
#![no_std] #![no_std]
use core::{marker::PhantomData, slice::IterMut}; use core::{marker::PhantomData, slice::IterMut};
use embedded_hal::{ use embedded_hal::delay::DelayNs;
blocking::delay::DelayUs, use embedded_hal::digital::{InputPin, OutputPin};
blocking::spi::Transfer, use embedded_hal::spi::SpiDevice;
digital::v2::{InputPin, OutputPin},
spi::FullDuplex,
};
//================================================================================================== //==================================================================================================
// Type-level support // Type-level support
@ -90,15 +87,15 @@ impl HasChannels for Max11625 {
const NUM: u8 = 16; const NUM: u8 = 16;
} }
pub trait Clocked: private::Sealed { pub trait ClockedProvider: private::Sealed {
const CLK_SEL: ClockMode; const CLK_SEL: ClockMode;
} }
pub trait InternallyClocked: Clocked {} pub trait InternallyClocked: ClockedProvider {}
pub struct InternallyClockedInternallyTimedCnvst {} pub struct InternallyClockedInternallyTimedCnvst {}
impl private::Sealed for InternallyClockedInternallyTimedCnvst {} impl private::Sealed for InternallyClockedInternallyTimedCnvst {}
impl Clocked for InternallyClockedInternallyTimedCnvst { impl ClockedProvider for InternallyClockedInternallyTimedCnvst {
const CLK_SEL: ClockMode = ClockMode::InternalClockInternallyTimedCnvst; const CLK_SEL: ClockMode = ClockMode::InternalClockInternallyTimedCnvst;
} }
impl InternallyClocked for InternallyClockedInternallyTimedCnvst {} impl InternallyClocked for InternallyClockedInternallyTimedCnvst {}
@ -106,7 +103,7 @@ type IntClkdIntTmdCnvst = InternallyClockedInternallyTimedCnvst;
pub struct InternallyClockedExternallyTimedCnvst {} pub struct InternallyClockedExternallyTimedCnvst {}
impl private::Sealed for InternallyClockedExternallyTimedCnvst {} impl private::Sealed for InternallyClockedExternallyTimedCnvst {}
impl Clocked for InternallyClockedExternallyTimedCnvst { impl ClockedProvider for InternallyClockedExternallyTimedCnvst {
const CLK_SEL: ClockMode = ClockMode::InternalClockExternallyTimedCnvst; const CLK_SEL: ClockMode = ClockMode::InternalClockExternallyTimedCnvst;
} }
impl InternallyClocked for InternallyClockedExternallyTimedCnvst {} impl InternallyClocked for InternallyClockedExternallyTimedCnvst {}
@ -114,7 +111,7 @@ type IntClkdExtTmdCnvst = InternallyClockedExternallyTimedCnvst;
pub struct InternallyClockedInternallyTimedSerialInterface {} pub struct InternallyClockedInternallyTimedSerialInterface {}
impl private::Sealed for InternallyClockedInternallyTimedSerialInterface {} impl private::Sealed for InternallyClockedInternallyTimedSerialInterface {}
impl Clocked for InternallyClockedInternallyTimedSerialInterface { impl ClockedProvider for InternallyClockedInternallyTimedSerialInterface {
const CLK_SEL: ClockMode = ClockMode::InternalClockInternallyTimedSerialInterface; const CLK_SEL: ClockMode = ClockMode::InternalClockInternallyTimedSerialInterface;
} }
impl InternallyClocked for InternallyClockedInternallyTimedSerialInterface {} impl InternallyClocked for InternallyClockedInternallyTimedSerialInterface {}
@ -122,7 +119,7 @@ type IntClkdIntTmdSerIF = InternallyClockedInternallyTimedSerialInterface;
pub struct ExternallyClocked {} pub struct ExternallyClocked {}
impl private::Sealed for ExternallyClocked {} impl private::Sealed for ExternallyClocked {}
impl Clocked for ExternallyClocked { impl ClockedProvider for ExternallyClocked {
const CLK_SEL: ClockMode = ClockMode::ExternalClockExternallyTimedSclk; const CLK_SEL: ClockMode = ClockMode::ExternalClockExternallyTimedSclk;
} }
type ExtClkd = ExternallyClocked; type ExtClkd = ExternallyClocked;
@ -133,6 +130,7 @@ type ExtClkd = ExternallyClocked;
/// Clock modes for the MAX116XX devices /// Clock modes for the MAX116XX devices
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ClockMode { pub enum ClockMode {
/// Internally timed, CNVST only needs to be pulsed for 40ns. /// Internally timed, CNVST only needs to be pulsed for 40ns.
/// CNVST Configuration: CNVST active low /// CNVST Configuration: CNVST active low
@ -149,6 +147,7 @@ pub enum ClockMode {
/// Voltage reference modes /// Voltage reference modes
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum VoltageRefMode { pub enum VoltageRefMode {
/// Auto-Shutdown is on, wake-up delay of 65 us /// Auto-Shutdown is on, wake-up delay of 65 us
InternalRefWithWakeupDelay = 0b00, InternalRefWithWakeupDelay = 0b00,
@ -158,6 +157,7 @@ pub enum VoltageRefMode {
/// Specifies how many conversions are performed and then averaged for each /// Specifies how many conversions are performed and then averaged for each
/// requested result /// requested result
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AveragingConversions { pub enum AveragingConversions {
OneConversion = 0b000, OneConversion = 0b000,
FourConversions = 0b100, FourConversions = 0b100,
@ -168,6 +168,7 @@ pub enum AveragingConversions {
/// Specifies the number of returned result in single scan mode /// Specifies the number of returned result in single scan mode
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AveragingResults { pub enum AveragingResults {
FourResults = 0b00, FourResults = 0b00,
EightResults = 0b01, EightResults = 0b01,
@ -176,6 +177,7 @@ pub enum AveragingResults {
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ScanMode { pub enum ScanMode {
Scan0ToChannelN = 0b00, Scan0ToChannelN = 0b00,
ScanChannelNToHighest = 0b01, ScanChannelNToHighest = 0b01,
@ -184,6 +186,7 @@ pub enum ScanMode {
} }
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AdcError { pub enum AdcError {
InvalidChannel, InvalidChannel,
InvalidRefMode, InvalidRefMode,
@ -208,6 +211,8 @@ impl<SpiE, PinE> From<AdcError> for Error<SpiE, PinE> {
} }
} }
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct InternalCfg { struct InternalCfg {
clk_mode: ClockMode, clk_mode: ClockMode,
ref_mode: VoltageRefMode, ref_mode: VoltageRefMode,
@ -216,16 +221,17 @@ struct InternalCfg {
results_len: u8, results_len: u8,
requested_conversions: usize, requested_conversions: usize,
} }
//================================================================================================== //==================================================================================================
// ADC implementation // ADC implementation
//================================================================================================== //==================================================================================================
pub struct Max116xx10Bit<SPI, CS, CLOCKED = ExtClkd, WAKEUP = WithoutWakeupDelay> { pub struct Max116xx10Bit<Spi, Cs, Clocked = ExtClkd, Wakeup = WithoutWakeupDelay> {
spi: SPI, spi: Spi,
cs: CS, cs: Cs,
cfg: InternalCfg, cfg: InternalCfg,
clocked: PhantomData<CLOCKED>, clocked: PhantomData<Clocked>,
delay: PhantomData<WAKEUP>, delay: PhantomData<Wakeup>,
} }
pub struct Max116xx10BitEocExt<SPI, CS, EOC, CLOCKED> { pub struct Max116xx10BitEocExt<SPI, CS, EOC, CLOCKED> {
@ -243,27 +249,23 @@ pub struct Max116xx10BitCnvstEocExt<SPI, CS, EOC, CNVST, CLOCKED, WAKEUP = Witho
// Generic // Generic
//================================================================================================== //==================================================================================================
impl<SpiE, PinE, CS, SPI> Max116xx10Bit<SPI, CS, ExtClkd, WithoutWakeupDelay> impl<Cs: OutputPin, Spi: SpiDevice> Max116xx10Bit<Spi, Cs, ExtClkd, WithoutWakeupDelay> {
where pub fn max11618(spi: Spi, cs: Cs) -> Result<Self, Error<Spi::Error, Cs::Error>> {
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
{
pub fn max11618(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> {
Self::new::<Max11618>(spi, cs) Self::new::<Max11618>(spi, cs)
} }
pub fn max11619(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn max11619(spi: Spi, cs: Cs) -> Result<Self, Error<Spi::Error, Cs::Error>> {
Self::new::<Max11619>(spi, cs) Self::new::<Max11619>(spi, cs)
} }
pub fn max11620(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn max11620(spi: Spi, cs: Cs) -> Result<Self, Error<Spi::Error, Cs::Error>> {
Self::new::<Max11620>(spi, cs) Self::new::<Max11620>(spi, cs)
} }
pub fn max11621(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn max11621(spi: Spi, cs: Cs) -> Result<Self, Error<Spi::Error, Cs::Error>> {
Self::new::<Max11621>(spi, cs) Self::new::<Max11621>(spi, cs)
} }
pub fn max11624(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn max11624(spi: Spi, cs: Cs) -> Result<Self, Error<Spi::Error, Cs::Error>> {
Self::new::<Max11624>(spi, cs) Self::new::<Max11624>(spi, cs)
} }
pub fn max11625(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn max11625(spi: Spi, cs: Cs) -> Result<Self, Error<Spi::Error, Cs::Error>> {
Self::new::<Max11625>(spi, cs) Self::new::<Max11625>(spi, cs)
} }
@ -274,7 +276,7 @@ where
/// ///
/// The corresponding SETUP register is `0b0111_0100` /// The corresponding SETUP register is `0b0111_0100`
/// Please note that you still might have to reset and setup the ADC. /// Please note that you still might have to reset and setup the ADC.
pub fn new<MAX: HasChannels>(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn new<MAX: HasChannels>(spi: Spi, cs: Cs) -> Result<Self, Error<Spi::Error, Cs::Error>> {
let max_dev = Max116xx10Bit { let max_dev = Max116xx10Bit {
spi, spi,
cs, cs,
@ -298,7 +300,7 @@ where
/// The corresponding SETUP register is `0b0111_0000` /// The corresponding SETUP register is `0b0111_0000`
pub fn into_ext_clkd_with_int_ref_wakeup_delay( pub fn into_ext_clkd_with_int_ref_wakeup_delay(
self, self,
) -> Max116xx10Bit<SPI, CS, ExtClkd, WithWakeupDelay> { ) -> Max116xx10Bit<Spi, Cs, ExtClkd, WithWakeupDelay> {
Max116xx10Bit { Max116xx10Bit {
spi: self.spi, spi: self.spi,
cs: self.cs, cs: self.cs,
@ -321,7 +323,7 @@ where
/// The corresponding SETUP register is `0b0111_1000` /// The corresponding SETUP register is `0b0111_1000`
pub fn into_ext_clkd_with_int_ref_no_wakeup_delay( pub fn into_ext_clkd_with_int_ref_no_wakeup_delay(
self, self,
) -> Max116xx10Bit<SPI, CS, ExtClkd, WithoutWakeupDelay> { ) -> Max116xx10Bit<Spi, Cs, ExtClkd, WithoutWakeupDelay> {
Max116xx10Bit { Max116xx10Bit {
spi: self.spi, spi: self.spi,
cs: self.cs, cs: self.cs,
@ -342,10 +344,10 @@ where
/// and a wakeup delay. This can be used to reduce power consumption /// and a wakeup delay. This can be used to reduce power consumption
/// ///
/// The corresponding SETUP register is `0b0110_1100` /// The corresponding SETUP register is `0b0110_1100`
pub fn into_int_clkd_int_timed_through_ser_if_with_wakeup<EOC: InputPin<Error = PinE>>( pub fn into_int_clkd_int_timed_through_ser_if_with_wakeup<Eoc: InputPin>(
self, self,
eoc: EOC, eoc: Eoc,
) -> Max116xx10BitEocExt<SPI, CS, EOC, IntClkdIntTmdSerIF> { ) -> Max116xx10BitEocExt<Spi, Cs, Eoc, IntClkdIntTmdSerIF> {
Max116xx10BitEocExt { Max116xx10BitEocExt {
base: Max116xx10Bit { base: Max116xx10Bit {
spi: self.spi, spi: self.spi,
@ -371,11 +373,11 @@ where
/// The corresponding SETUP register can be one of the two /// The corresponding SETUP register can be one of the two
/// - External Voltage reference: `0b0110_0100` /// - External Voltage reference: `0b0110_0100`
/// - Internal Voltage reference always on: `0b0110_1000` /// - Internal Voltage reference always on: `0b0110_1000`
pub fn into_int_clkd_int_timed_through_ser_if_without_wakeup<EOC: InputPin<Error = PinE>>( pub fn into_int_clkd_int_timed_through_ser_if_without_wakeup<Eoc: InputPin>(
self, self,
v_ref: VoltageRefMode, v_ref: VoltageRefMode,
eoc: EOC, eoc: Eoc,
) -> Result<Max116xx10BitEocExt<SPI, CS, EOC, IntClkdIntTmdSerIF>, AdcError> { ) -> Result<Max116xx10BitEocExt<Spi, Cs, Eoc, IntClkdIntTmdSerIF>, AdcError> {
if v_ref == VoltageRefMode::InternalRefWithWakeupDelay { if v_ref == VoltageRefMode::InternalRefWithWakeupDelay {
return Err(AdcError::InvalidRefMode); return Err(AdcError::InvalidRefMode);
} }
@ -399,22 +401,20 @@ where
} }
} }
impl<SpiE, PinE, CS, SPI, CLOCKED: Clocked, WAKEUP> Max116xx10Bit<SPI, CS, CLOCKED, WAKEUP> impl<Cs: OutputPin, Spi: SpiDevice, Clocked: ClockedProvider, Wakeup>
where Max116xx10Bit<Spi, Cs, Clocked, Wakeup>
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
{ {
#[inline] #[inline]
fn send_wrapper(&mut self, byte: u8) -> Result<(), Error<SpiE, PinE>> { fn send_wrapper(&mut self, byte: u8) -> Result<(), Error<Spi::Error, Cs::Error>> {
self.cs.set_low().map_err(Error::Pin)?; self.cs.set_low().map_err(Error::Pin)?;
nb::block!(self.spi.send(byte)).map_err(Error::Spi)?; self.spi.write(&[byte]).map_err(Error::Spi)?;
self.cs.set_high().map_err(Error::Pin)?; self.cs.set_high().map_err(Error::Pin)?;
Ok(()) Ok(())
} }
/// Set up the ADC depending on clock and reference configuration /// Set up the ADC depending on clock and reference configuration
#[inline] #[inline]
pub fn setup(&mut self) -> Result<(), Error<SpiE, PinE>> { pub fn setup(&mut self) -> Result<(), Error<Spi::Error, Cs::Error>> {
self.send_wrapper(self.get_setup_byte()) self.send_wrapper(self.get_setup_byte())
} }
@ -425,13 +425,13 @@ where
&mut self, &mut self,
avg_conv: AveragingConversions, avg_conv: AveragingConversions,
avg_res: AveragingResults, avg_res: AveragingResults,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, Cs::Error>> {
self.cfg.results_len = Self::get_results_len(avg_res); self.cfg.results_len = Self::get_results_len(avg_res);
self.send_wrapper(Self::get_averaging_byte(avg_conv, avg_res)) self.send_wrapper(Self::get_averaging_byte(avg_conv, avg_res))
} }
#[inline] #[inline]
pub fn reset(&mut self, fifo_only: bool) -> Result<(), Error<SpiE, PinE>> { pub fn reset(&mut self, fifo_only: bool) -> Result<(), Error<Spi::Error, Cs::Error>> {
let mut reset_byte = 0b0001_0000; let mut reset_byte = 0b0001_0000;
if fifo_only { if fifo_only {
reset_byte |= 1 << 3; reset_byte |= 1 << 3;
@ -468,24 +468,24 @@ where
/// Generic function which can be used a single result is available /// Generic function which can be used a single result is available
/// when EOC is low /// when EOC is low
fn internal_read_single_channel<EOC: InputPin<Error = PinE>>( fn internal_read_single_channel<Eoc: InputPin<Error = Cs::Error>>(
&mut self, &mut self,
eoc: &mut EOC, eoc: &mut Eoc,
) -> nb::Result<u16, Error<SpiE, PinE>> { ) -> nb::Result<u16, Error<Spi::Error, Cs::Error>> {
if self.cfg.pending_scan_mode.is_none() { if self.cfg.pending_scan_mode.is_none() {
return Err(nb::Error::Other(Error::Adc(AdcError::NoPendingOperation))); return Err(nb::Error::Other(Error::Adc(AdcError::NoPendingOperation)));
} else if self.cfg.pending_scan_mode != Some(ScanMode::ConvertChannelNOnce) { } else if self.cfg.pending_scan_mode != Some(ScanMode::ConvertChannelNOnce) {
return Err(nb::Error::Other(Error::Adc(AdcError::PendingOperation))); return Err(nb::Error::Other(Error::Adc(AdcError::PendingOperation)));
} }
if eoc.is_low().map_err(Error::Pin)? { if eoc.is_low().map_err(Error::Pin)? {
let mut dummy_cmd: [u8; 2] = [0; 2]; let mut reply_buf: [u8; 2] = [0; 2];
self.cs.set_low().map_err(Error::Pin)?; self.cs.set_low().map_err(Error::Pin)?;
let transfer_result = self.spi.transfer(&mut dummy_cmd); let transfer_result = self.spi.read(&mut reply_buf);
self.cs.set_high().map_err(Error::Pin)?; self.cs.set_high().map_err(Error::Pin)?;
match transfer_result { match transfer_result {
Ok(reply) => { Ok(_) => {
self.cfg.pending_scan_mode = None; 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))), Err(e) => Err(nb::Error::Other(Error::Spi(e))),
} }
@ -499,7 +499,7 @@ macro_rules! ext_impl {
() => { () => {
/// Set up the ADC depending on clock and reference configuration /// Set up the ADC depending on clock and reference configuration
#[inline] #[inline]
pub fn setup(&mut self) -> Result<(), Error<SpiE, PinE>> { pub fn setup(&mut self) -> Result<(), Error<Spi::Error, Cs::Error>> {
self.base.send_wrapper(self.base.get_setup_byte()) self.base.send_wrapper(self.base.get_setup_byte())
} }
@ -510,16 +510,16 @@ macro_rules! ext_impl {
&mut self, &mut self,
avg_conv: AveragingConversions, avg_conv: AveragingConversions,
avg_res: AveragingResults, avg_res: AveragingResults,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, Cs::Error>> {
self.base.cfg.results_len = Max116xx10Bit::<SPI, CS, CLOCKED>::get_results_len(avg_res); self.base.cfg.results_len = Max116xx10Bit::<Spi, Cs, Clocked>::get_results_len(avg_res);
self.base self.base
.send_wrapper(Max116xx10Bit::<SPI, CS, CLOCKED>::get_averaging_byte( .send_wrapper(Max116xx10Bit::<Spi, Cs, Clocked>::get_averaging_byte(
avg_conv, avg_res, avg_conv, avg_res,
)) ))
} }
#[inline] #[inline]
pub fn reset(&mut self, fifo_only: bool) -> Result<(), Error<SpiE, PinE>> { pub fn reset(&mut self, fifo_only: bool) -> Result<(), Error<Spi::Error, Cs::Error>> {
let mut reset_byte = 0b0001_0000; let mut reset_byte = 0b0001_0000;
if fifo_only { if fifo_only {
reset_byte |= 1 << 3; reset_byte |= 1 << 3;
@ -528,19 +528,14 @@ macro_rules! ext_impl {
} }
}; };
} }
impl<SpiE, PinE, CS, SPI, EOC, CLOCKED: Clocked> Max116xx10BitEocExt<SPI, CS, EOC, CLOCKED> impl<Cs: OutputPin, Spi: SpiDevice, Eoc, Clocked: ClockedProvider>
where Max116xx10BitEocExt<Spi, Cs, Eoc, Clocked>
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
{ {
ext_impl!(); ext_impl!();
} }
impl<SpiE, PinE, CS, SPI, EOC, CNVST, CLOCKED: Clocked, DELAY> impl<Cs: OutputPin, Spi: SpiDevice, EOC, CNVST, Clocked: ClockedProvider, DELAY>
Max116xx10BitCnvstEocExt<SPI, CS, EOC, CNVST, CLOCKED, DELAY> Max116xx10BitCnvstEocExt<Spi, Cs, EOC, CNVST, Clocked, DELAY>
where
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
{ {
ext_impl!(); ext_impl!();
} }
@ -550,16 +545,12 @@ where
//================================================================================================== //==================================================================================================
/// Implementations when using the external SPI clock to time the conversions /// Implementations when using the external SPI clock to time the conversions
impl<SpiE, PinE, SPI, CS> Max116xx10Bit<SPI, CS, ExtClkd, WithoutWakeupDelay> impl<Spi: SpiDevice, Cs: OutputPin> Max116xx10Bit<Spi, Cs, ExtClkd, WithoutWakeupDelay> {
where
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
{
pub fn read_single_channel( pub fn read_single_channel(
&mut self, &mut self,
buf: &mut [u8], buf: &mut [u8],
channel_num: u8, channel_num: u8,
) -> Result<u16, Error<SpiE, PinE>> { ) -> Result<u16, Error<Spi::Error, Cs::Error>> {
if buf.len() < 3 { if buf.len() < 3 {
return Err(Error::Adc(AdcError::CmdBufTooSmall)); return Err(Error::Adc(AdcError::CmdBufTooSmall));
} }
@ -567,9 +558,9 @@ where
buf[1] = 0x00; buf[1] = 0x00;
buf[2] = 0x00; buf[2] = 0x00;
self.cs.set_low().map_err(Error::Pin)?; self.cs.set_low().map_err(Error::Pin)?;
let reply = self.spi.transfer(&mut buf[0..3]).ok().unwrap(); self.spi.transfer_in_place(&mut buf[0..3]).ok().unwrap();
self.cs.set_high().map_err(Error::Pin)?; self.cs.set_high().map_err(Error::Pin)?;
Ok(((reply[1] as u16) << 6) | (reply[2] as u16 >> 2)) Ok(((buf[1] as u16) << 6) | (buf[2] as u16 >> 2))
} }
pub fn read_multiple_channels_0_to_n( pub fn read_multiple_channels_0_to_n(
@ -577,7 +568,7 @@ where
buf: &mut [u8], buf: &mut [u8],
result_iter: &mut IterMut<u16>, result_iter: &mut IterMut<u16>,
n: u8, n: u8,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, Cs::Error>> {
let mut iter = buf.iter_mut(); let mut iter = buf.iter_mut();
let mut next_byte: &mut u8; let mut next_byte: &mut u8;
for idx in 0..n + 1 { for idx in 0..n + 1 {
@ -589,12 +580,11 @@ where
next_byte = iter.next().ok_or(Error::Adc(AdcError::CmdBufTooSmall))?; next_byte = iter.next().ok_or(Error::Adc(AdcError::CmdBufTooSmall))?;
*next_byte = 0x00; *next_byte = 0x00;
self.cs.set_low().map_err(Error::Pin)?; self.cs.set_low().map_err(Error::Pin)?;
let reply = self self.spi
.spi .transfer_in_place(&mut buf[0..((n + 1) * 2 + 1) as usize])
.transfer(&mut buf[0..((n + 1) * 2 + 1) as usize])
.map_err(Error::Spi)?; .map_err(Error::Spi)?;
self.cs.set_high().map_err(Error::Pin)?; self.cs.set_high().map_err(Error::Pin)?;
let mut reply_iter = reply.iter(); let mut reply_iter = buf.iter();
// Skip first reply byte // Skip first reply byte
reply_iter.next().unwrap(); reply_iter.next().unwrap();
for _ in 0..n + 1 { for _ in 0..n + 1 {
@ -612,7 +602,7 @@ where
buf: &mut [u8], buf: &mut [u8],
result_iter: &mut IterMut<u16>, result_iter: &mut IterMut<u16>,
n: u8, n: u8,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, Cs::Error>> {
let mut iter = buf.iter_mut(); let mut iter = buf.iter_mut();
let mut next_byte: &mut u8; let mut next_byte: &mut u8;
if n > self.cfg.max_channels - 1 { if n > self.cfg.max_channels - 1 {
@ -628,12 +618,11 @@ where
next_byte = iter.next().ok_or(Error::Adc(AdcError::CmdBufTooSmall))?; next_byte = iter.next().ok_or(Error::Adc(AdcError::CmdBufTooSmall))?;
*next_byte = 0x00; *next_byte = 0x00;
self.cs.set_low().map_err(Error::Pin)?; self.cs.set_low().map_err(Error::Pin)?;
let reply = self self.spi
.spi .transfer_in_place(&mut buf[0..(conversions * 2 + 1) as usize])
.transfer(&mut buf[0..(conversions * 2 + 1) as usize])
.map_err(Error::Spi)?; .map_err(Error::Spi)?;
self.cs.set_high().map_err(Error::Pin)?; self.cs.set_high().map_err(Error::Pin)?;
let mut reply_iter = reply.iter(); let mut reply_iter = buf.iter();
// Skip first reply byte // Skip first reply byte
reply_iter.next().unwrap(); reply_iter.next().unwrap();
for _ in 0..conversions { for _ in 0..conversions {
@ -649,17 +638,13 @@ where
/// Implementations when using the external SPI clock to time the conversions but also requiring /// Implementations when using the external SPI clock to time the conversions but also requiring
/// a wakeup delay /// a wakeup delay
impl<SpiE, PinE, SPI, CS> Max116xx10Bit<SPI, CS, ExtClkd, WithWakeupDelay> impl<Spi: SpiDevice, Cs: OutputPin> Max116xx10Bit<Spi, Cs, ExtClkd, WithWakeupDelay> {
where pub fn read_single_channel<Delay: DelayNs>(
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
{
pub fn read_single_channel<DELAY: DelayUs<u8>>(
&mut self, &mut self,
buf: &mut [u8], buf: &mut [u8],
channel_num: u8, channel_num: u8,
delay: &mut DELAY, delay: &mut Delay,
) -> Result<u16, Error<SpiE, PinE>> { ) -> Result<u16, Error<Spi::Error, Cs::Error>> {
if buf.len() < 3 { if buf.len() < 3 {
return Err(Error::Adc(AdcError::CmdBufTooSmall)); return Err(Error::Adc(AdcError::CmdBufTooSmall));
} }
@ -671,18 +656,20 @@ where
buf[0] = 0x00; buf[0] = 0x00;
buf[1] = 0x00; buf[1] = 0x00;
self.cs.set_low().map_err(Error::Pin)?; self.cs.set_low().map_err(Error::Pin)?;
let reply = self.spi.transfer(&mut buf[0..2]).map_err(Error::Spi)?; self.spi
.transfer_in_place(&mut buf[0..2])
.map_err(Error::Spi)?;
self.cs.set_high().map_err(Error::Pin)?; self.cs.set_high().map_err(Error::Pin)?;
Ok(((reply[0] as u16) << 6) | (reply[1] as u16 >> 2)) Ok(((buf[0] as u16) << 6) | (buf[1] as u16 >> 2))
} }
pub fn read_multiple_channels_0_to_n<DELAY: DelayUs<u8>>( pub fn read_multiple_channels_0_to_n<Delay: DelayNs>(
&mut self, &mut self,
buf: &mut [u8], buf: &mut [u8],
result_iter: &mut IterMut<u16>, result_iter: &mut IterMut<u16>,
n: u8, n: u8,
delay: &mut DELAY, delay: &mut Delay,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, Cs::Error>> {
let mut iter = buf.iter_mut(); let mut iter = buf.iter_mut();
let mut next_byte: &mut u8; let mut next_byte: &mut u8;
for idx in 0..n + 1 { for idx in 0..n + 1 {
@ -698,12 +685,11 @@ where
delay.delay_us(65); delay.delay_us(65);
self.cs.set_low().map_err(Error::Pin)?; self.cs.set_low().map_err(Error::Pin)?;
let reply = self self.spi
.spi .transfer_in_place(&mut buf[1..((n + 1) * 2 + 1) as usize])
.transfer(&mut buf[1..((n + 1) * 2 + 1) as usize])
.map_err(Error::Spi)?; .map_err(Error::Spi)?;
self.cs.set_high().map_err(Error::Pin)?; 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 { for _ in 0..n + 1 {
let next_res = result_iter let next_res = result_iter
.next() .next()
@ -714,13 +700,13 @@ where
Ok(()) Ok(())
} }
pub fn read_multiple_channels_n_to_highest<DELAY: DelayUs<u8>>( pub fn read_multiple_channels_n_to_highest<Delay: DelayNs>(
&mut self, &mut self,
buf: &mut [u8], buf: &mut [u8],
result_iter: &mut IterMut<u16>, result_iter: &mut IterMut<u16>,
n: u8, n: u8,
delay: &mut DELAY, delay: &mut Delay,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, Cs::Error>> {
let mut iter = buf.iter_mut(); let mut iter = buf.iter_mut();
let mut next_byte: &mut u8; let mut next_byte: &mut u8;
if n > self.cfg.max_channels - 1 { if n > self.cfg.max_channels - 1 {
@ -740,12 +726,11 @@ where
self.send_wrapper(buf[0])?; self.send_wrapper(buf[0])?;
delay.delay_us(65); delay.delay_us(65);
self.cs.set_low().map_err(Error::Pin)?; self.cs.set_low().map_err(Error::Pin)?;
let reply = self self.spi
.spi .transfer_in_place(&mut buf[1..(conversions * 2 + 1) as usize])
.transfer(&mut buf[1..(conversions * 2 + 1) as usize])
.map_err(Error::Spi)?; .map_err(Error::Spi)?;
self.cs.set_high().map_err(Error::Pin)?; self.cs.set_high().map_err(Error::Pin)?;
let mut reply_iter = reply.iter(); let mut reply_iter = buf.iter();
for _ in 0..conversions { for _ in 0..conversions {
let next_res = result_iter let next_res = result_iter
.next() .next()
@ -763,18 +748,15 @@ where
/// Implementations when using the internal clock with a conversion started /// Implementations when using the internal clock with a conversion started
/// through the serial interface /// through the serial interface
impl<SpiE, PinE, SPI, CS, EOC> Max116xx10BitEocExt<SPI, CS, EOC, IntClkdIntTmdSerIF> impl<Spi: SpiDevice, Cs: OutputPin<Error = PinE>, Eoc: InputPin<Error = PinE>, PinE>
where Max116xx10BitEocExt<Spi, Cs, Eoc, IntClkdIntTmdSerIF>
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
EOC: InputPin<Error = PinE>,
{ {
#[inline] #[inline]
fn request_wrapper( fn request_wrapper(
&mut self, &mut self,
channel_num: u8, channel_num: u8,
scan_mode: ScanMode, scan_mode: ScanMode,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, Cs::Error>> {
if self.base.cfg.pending_scan_mode.is_some() { if self.base.cfg.pending_scan_mode.is_some() {
return Err(Error::Adc(AdcError::PendingOperation)); return Err(Error::Adc(AdcError::PendingOperation));
} }
@ -787,7 +769,10 @@ where
Ok(()) Ok(())
} }
pub fn request_single_channel(&mut self, channel_num: u8) -> Result<(), Error<SpiE, PinE>> { pub fn request_single_channel(
&mut self,
channel_num: u8,
) -> Result<(), Error<Spi::Error, PinE>> {
self.request_wrapper(channel_num, ScanMode::ConvertChannelNOnce) self.request_wrapper(channel_num, ScanMode::ConvertChannelNOnce)
} }
@ -797,11 +782,14 @@ where
pub fn request_channel_n_repeatedly( pub fn request_channel_n_repeatedly(
&mut self, &mut self,
channel_num: u8, channel_num: u8,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, PinE>> {
self.request_wrapper(channel_num, ScanMode::ScanChannelNRepeatedly) self.request_wrapper(channel_num, ScanMode::ScanChannelNRepeatedly)
} }
pub fn request_multiple_channels_0_to_n(&mut self, n: u8) -> Result<(), Error<SpiE, PinE>> { pub fn request_multiple_channels_0_to_n(
&mut self,
n: u8,
) -> Result<(), Error<Spi::Error, PinE>> {
self.base.cfg.requested_conversions = n as usize + 1; self.base.cfg.requested_conversions = n as usize + 1;
self.request_wrapper(n, ScanMode::Scan0ToChannelN) self.request_wrapper(n, ScanMode::Scan0ToChannelN)
} }
@ -809,7 +797,7 @@ where
pub fn request_multiple_channels_n_to_highest( pub fn request_multiple_channels_n_to_highest(
&mut self, &mut self,
n: u8, n: u8,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, PinE>> {
self.base.cfg.requested_conversions = self.base.cfg.max_channels as usize + 1 - n as usize; self.base.cfg.requested_conversions = self.base.cfg.max_channels as usize + 1 - n as usize;
self.request_wrapper(n, ScanMode::ScanChannelNToHighest) self.request_wrapper(n, ScanMode::ScanChannelNToHighest)
} }
@ -818,7 +806,7 @@ where
/// needs to be passed explicitely here. /// needs to be passed explicitely here.
/// If no request was made, [AdcError::NoPendingOperation] is returned. /// If no request was made, [AdcError::NoPendingOperation] is returned.
/// If a request was made for multipel results, [AdcError::PendingOperation] will be returned. /// If a request was made for multipel results, [AdcError::PendingOperation] will be returned.
pub fn get_single_channel(&mut self) -> nb::Result<u16, Error<SpiE, PinE>> { pub fn get_single_channel(&mut self) -> nb::Result<u16, Error<Spi::Error, Cs::Error>> {
self.base.internal_read_single_channel(&mut self.eoc) self.base.internal_read_single_channel(&mut self.eoc)
} }
@ -828,7 +816,7 @@ where
pub fn get_multi_channel( pub fn get_multi_channel(
&mut self, &mut self,
result_iter: &mut IterMut<u16>, result_iter: &mut IterMut<u16>,
) -> nb::Result<(), Error<SpiE, PinE>> { ) -> nb::Result<(), Error<Spi::Error, Cs::Error>> {
if self.base.cfg.pending_scan_mode.is_none() { if self.base.cfg.pending_scan_mode.is_none() {
return Err(nb::Error::Other(Error::Adc(AdcError::NoPendingOperation))); return Err(nb::Error::Other(Error::Adc(AdcError::NoPendingOperation)));
} else if self.base.cfg.pending_scan_mode == Some(ScanMode::ConvertChannelNOnce) { } else if self.base.cfg.pending_scan_mode == Some(ScanMode::ConvertChannelNOnce) {
@ -836,7 +824,7 @@ where
} }
if self.eoc.is_low().map_err(Error::Pin)? { if self.eoc.is_low().map_err(Error::Pin)? {
// maximum length of reply is 32 for 16 channels // 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 = let num_conv: usize =
if self.base.cfg.pending_scan_mode == Some(ScanMode::ScanChannelNRepeatedly) { if self.base.cfg.pending_scan_mode == Some(ScanMode::ScanChannelNRepeatedly) {
self.base.cfg.results_len as usize self.base.cfg.results_len as usize
@ -846,22 +834,20 @@ where
self.base.cfg.pending_scan_mode = None; self.base.cfg.pending_scan_mode = None;
self.base.cfg.requested_conversions = 0; self.base.cfg.requested_conversions = 0;
self.base.cs.set_low().map_err(Error::Pin)?; 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
.spi
.read(&mut reply_buf[0..(num_conv * 2)])
.map_err(Error::Spi)?;
self.base.cs.set_high().map_err(Error::Pin)?; self.base.cs.set_high().map_err(Error::Pin)?;
match transfer_result { let mut reply_iter = reply_buf.iter();
Ok(reply) => { for _ in 0..num_conv {
let mut reply_iter = reply.iter(); let next_res = result_iter
for _ in 0..num_conv { .next()
let next_res = result_iter .ok_or(Error::Adc(AdcError::ResulBufTooSmall))?;
.next() *next_res = ((*reply_iter.next().unwrap() as u16) << 6)
.ok_or(Error::Adc(AdcError::ResulBufTooSmall))?; | (*reply_iter.next().unwrap() as u16 >> 2);
*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))),
} }
Ok(())
} else { } else {
Err(nb::Error::WouldBlock) Err(nb::Error::WouldBlock)
} }
@ -877,17 +863,9 @@ where
/// ///
/// TODO: Implement. Unfortunately, the test board used to verify this library did not have /// 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. /// the CNVST connected, so I wouldn't be able to test an implementation easily.
impl<SpiE, PinE, SPI, CS, EOC, CNVST> impl<Spi: SpiDevice, Cs: OutputPin, Eoc: InputPin, Cnvst: OutputPin>
Max116xx10BitCnvstEocExt<SPI, CS, EOC, CNVST, IntClkdExtTmdCnvst, WithoutWakeupDelay> Max116xx10BitCnvstEocExt<Spi, Cs, Eoc, Cnvst, IntClkdExtTmdCnvst, WithoutWakeupDelay>
where
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
EOC: InputPin<Error = PinE>,
CNVST: OutputPin<Error = PinE>,
{ {
pub fn dummy() {
todo!("Implement this")
}
} }
/// Implementations when using the internal clock where CNVST is only pulsed to start acquisition /// Implementations when using the internal clock where CNVST is only pulsed to start acquisition
@ -895,13 +873,13 @@ where
/// ///
/// TODO: Test. Unfortunately, the test board used to verify this library did not have /// 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. /// the CNVST connected, so I wouldn't be able to test an implementation easily.
impl<SpiE, PinE, SPI, CS, EOC, CNVST> impl<
Max116xx10BitCnvstEocExt<SPI, CS, EOC, CNVST, IntClkdIntTmdCnvst, WithWakeupDelay> Spi: SpiDevice,
where Cs: OutputPin<Error = PinE>,
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>, Eoc: InputPin<Error = PinE>,
CS: OutputPin<Error = PinE>, Cnvst: OutputPin<Error = PinE>,
EOC: InputPin<Error = PinE>, PinE,
CNVST: OutputPin<Error = PinE>, > Max116xx10BitCnvstEocExt<Spi, Cs, Eoc, Cnvst, IntClkdIntTmdCnvst, WithWakeupDelay>
{ {
/// The pulse needs to be at least 40ns. A pulse cycle value can be used to increase /// The pulse needs to be at least 40ns. A pulse cycle value can be used to increase
/// the width of the pulse /// the width of the pulse
@ -909,7 +887,7 @@ where
&mut self, &mut self,
channel_num: u8, channel_num: u8,
pulse_cycles: u8, pulse_cycles: u8,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, PinE>> {
self.request_wrapper(channel_num, ScanMode::ConvertChannelNOnce, pulse_cycles) self.request_wrapper(channel_num, ScanMode::ConvertChannelNOnce, pulse_cycles)
} }
@ -919,7 +897,7 @@ where
channel_num: u8, channel_num: u8,
scan_mode: ScanMode, scan_mode: ScanMode,
pulse_cycles: u8, pulse_cycles: u8,
) -> Result<(), Error<SpiE, PinE>> { ) -> Result<(), Error<Spi::Error, PinE>> {
if self.base.cfg.pending_scan_mode.is_some() { if self.base.cfg.pending_scan_mode.is_some() {
return Err(Error::Adc(AdcError::PendingOperation)); return Err(Error::Adc(AdcError::PendingOperation));
} }
@ -935,7 +913,7 @@ where
Ok(()) Ok(())
} }
pub fn get_single_channel(&mut self) -> nb::Result<u16, Error<SpiE, PinE>> { pub fn get_single_channel(&mut self) -> nb::Result<u16, Error<Spi::Error, PinE>> {
self.base.internal_read_single_channel(&mut self.eoc) self.base.internal_read_single_channel(&mut self.eoc)
} }
} }