10 Commits
v0.2.0 ... main

Author SHA1 Message Date
ef2f8d309a add date in changelog
All checks were successful
Rust/max116xx-10bit/pipeline/head This commit looks good
2024-06-16 16:02:48 +02:00
ba41653564 fix CI file
All checks were successful
Rust/max116xx-10bit/pipeline/head This commit looks good
2024-06-16 15:58:08 +02:00
c5a5ead52d Merge pull request 'embedded HAL v1 and defmt support' (#2) from bump-embedded-hal into main
All checks were successful
Rust/max116xx-10bit/pipeline/head This commit looks good
Reviewed-on: #2
2024-06-16 15:57:05 +02:00
aab40bc027 update CI and docs settings
Some checks are pending
Rust/max116xx-10bit/pipeline/head Build started...
Rust/max116xx-10bit/pipeline/pr-main Build started...
2024-06-16 15:53:27 +02:00
88270085c9 remove chip select management
All checks were successful
Rust/max116xx-10bit/pipeline/head This commit looks good
Rust/max116xx-10bit/pipeline/pr-main This commit looks good
2024-06-15 19:30:49 +02:00
a69671ce22 bumped embedded HAL
All checks were successful
Rust/max116xx-10bit/pipeline/head This commit looks good
2024-06-15 19:05:50 +02:00
c9b5f6a4e9 add Eq derives
All checks were successful
Rust/max116xx-10bit/pipeline/head This commit looks good
2022-09-13 10:46:30 +02:00
3422801850 small clippy improvement
All checks were successful
Rust/max116xx-10bit/pipeline/head This commit looks good
2022-06-18 22:40:05 +02:00
8a81b3a721 typo
All checks were successful
Rust/max116xx-10bit/pipeline/head This commit looks good
2021-12-14 14:36:58 +01:00
0532c1b94e v0.2.1
All checks were successful
Rust/max116xx-10bit/pipeline/head This commit looks good
2021-12-14 14:23:10 +01:00
6 changed files with 222 additions and 249 deletions

2
.github/bors.toml vendored
View File

@ -1,2 +0,0 @@
status = ["ci"]
delete_merged_branches = true

View File

@ -1,43 +1,64 @@
on: push
name: ci name: ci
on: [push, pull_request]
jobs: jobs:
ci: check:
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 runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
rust:
- stable
target: target:
- x86_64-unknown-linux-gnu
- thumbv6m-none-eabi
- armv7-unknown-linux-gnueabihf - armv7-unknown-linux-gnueabihf
- thumbv7em-none-eabihf - thumbv7em-none-eabihf
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: actions-rs/toolchain@v1
with: with:
profile: minimal targets: "armv7-unknown-linux-gnueabihf, thumbv7em-none-eabihf"
toolchain: ${{ matrix.rust }} - run: cargo check --release --target=${{matrix.target}} --no-default-features
target: ${{ matrix.target }}
override: true
components: rustfmt, clippy
- uses: actions-rs/cargo@v1 test:
with: name: Run Tests
use-cross: true runs-on: ubuntu-latest
command: check 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 fmt:
with: name: Check formatting
command: fmt runs-on: ubuntu-latest
args: --all -- --check steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo fmt --all -- --check
- uses: actions-rs/cargo@v1 docs:
with: name: Check Documentation Build
use-cross: true runs-on: ubuntu-latest
command: clippy steps:
args: -- -D warnings - 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

View File

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

View File

@ -1,6 +1,6 @@
[package] [package]
name = "max116xx-10bit" name = "max116xx-10bit"
version = "0.2.0" 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,10 @@ 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 }
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docs_rs", "--generate-link-to-definition"]

View File

@ -9,13 +9,8 @@ This is a platform agnostic Rust driver for the MAX11618-MAX11621, MAX11624 and
[ADC devices](https://www.maximintegrated.com/en/products/analog/data-converters/analog-to-digital-converters/MAX11619.html) [ADC devices](https://www.maximintegrated.com/en/products/analog/data-converters/analog-to-digital-converters/MAX11619.html)
which uses the [`embedded-hal`](https://github.com/rust-embedded/embedded-hal) traits. which uses the [`embedded-hal`](https://github.com/rust-embedded/embedded-hal) traits.
This driver implements basic operations to read raw ADC values: This driver supports most required features but the CNVST pin support is still limited because
the test development board did not have the pin connected. Pull requests to improve this are welcome.
- Read ADC values using the SPI clock as an external clock
- Read ADC values using the End-Of-Conversion (EOC) pin
Currently, the driver only supports operation without a wake-up delay and the EOC read
functionality is still limited. Pull requests to improve this are welcome.
# Usage # Usage
@ -25,6 +20,6 @@ the appropriate device.
The crate uses basic type-level support to prevent using the ADC in a wrong way. The crate uses basic type-level support to prevent using the ADC in a wrong way.
The type-level support defaults to an externally clocked device with no wake-up delay. The type-level support defaults to an externally clocked device with no wake-up delay.
This crate was tested using the Vorago REB1 development board. You can find an example application This crate was tested using the Vorago REB1 development board. You can find the example
[here](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/src/max11619.rs) application [here](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/examples/max11619-adc.rs)
and [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)

View File

@ -4,7 +4,7 @@
//! //!
//! You can create an initial ADC struct by using the [`Max116xx10Bit::max11618`], //! You can create an initial ADC struct by using the [`Max116xx10Bit::max11618`],
//! [`Max116xx10Bit::max11619`], [`Max116xx10Bit::max11620`], [`Max116xx10Bit::max11621`], //! [`Max116xx10Bit::max11619`], [`Max116xx10Bit::max11620`], [`Max116xx10Bit::max11621`],
//! [`Max116xx10Bit::max11624`] and [`Max116xx10Bit::max11625`] functionsdepending on which device //! [`Max116xx10Bit::max11624`] and [`Max116xx10Bit::max11625`] functions depending on which device
//! you are using. This automatically sets the highest channel number accordingly. //! you are using. This automatically sets the highest channel number accordingly.
//! //!
//! The default structs use the externally clocked mode with an external voltage reference. //! The default structs use the externally clocked mode with an external voltage reference.
@ -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) //! 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) //! using a [thin abstraction layer](https://egit.irs.uni-stuttgart.de/rust/vorago-reb1/src/branch/main/src/max11619.rs)
#![no_std] #![no_std]
#![cfg_attr(docs_rs, feature(doc_auto_cfg))]
use core::convert::Infallible;
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 +89,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 +105,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 +113,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 +121,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;
@ -132,7 +131,8 @@ type ExtClkd = ExternallyClocked;
//================================================================================================== //==================================================================================================
/// Clock modes for the MAX116XX devices /// Clock modes for the MAX116XX devices
#[derive(Debug, PartialEq, 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
@ -148,7 +148,8 @@ pub enum ClockMode {
} }
/// Voltage reference modes /// Voltage reference modes
#[derive(Debug, PartialEq, 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 +159,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,
@ -167,7 +169,8 @@ 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, 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,
@ -175,7 +178,8 @@ pub enum AveragingResults {
SixteenResults = 0b11, SixteenResults = 0b11,
} }
#[derive(Debug, PartialEq, 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 +188,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 +213,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,25 +223,25 @@ 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, Clocked = ExtClkd, Wakeup = WithoutWakeupDelay> {
spi: SPI, spi: Spi,
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, EOC, CLOCKED> {
base: Max116xx10Bit<SPI, CS, CLOCKED, WithoutWakeupDelay>, base: Max116xx10Bit<SPI, CLOCKED, WithoutWakeupDelay>,
eoc: EOC, eoc: EOC,
} }
pub struct Max116xx10BitCnvstEocExt<SPI, CS, EOC, CNVST, CLOCKED, WAKEUP = WithoutWakeupDelay> { pub struct Max116xx10BitCnvstEocExt<SPI, EOC, CNVST, CLOCKED, WAKEUP = WithoutWakeupDelay> {
base: Max116xx10Bit<SPI, CS, CLOCKED, WAKEUP>, base: Max116xx10Bit<SPI, CLOCKED, WAKEUP>,
eoc: EOC, eoc: EOC,
cnvst: CNVST, cnvst: CNVST,
} }
@ -243,28 +250,24 @@ pub struct Max116xx10BitCnvstEocExt<SPI, CS, EOC, CNVST, CLOCKED, WAKEUP = Witho
// Generic // Generic
//================================================================================================== //==================================================================================================
impl<SpiE, PinE, CS, SPI> Max116xx10Bit<SPI, CS, ExtClkd, WithoutWakeupDelay> impl<Spi: SpiDevice> Max116xx10Bit<Spi, ExtClkd, WithoutWakeupDelay> {
where pub fn max11618(spi: Spi) -> Result<Self, Error<Spi::Error, Infallible>> {
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>, Self::new::<Max11618>(spi)
CS: OutputPin<Error = PinE>,
{
pub fn max11618(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> {
Self::new::<Max11618>(spi, cs)
} }
pub fn max11619(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn max11619(spi: Spi) -> Result<Self, Error<Spi::Error, Infallible>> {
Self::new::<Max11619>(spi, cs) Self::new::<Max11619>(spi)
} }
pub fn max11620(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn max11620(spi: Spi) -> Result<Self, Error<Spi::Error, Infallible>> {
Self::new::<Max11620>(spi, cs) Self::new::<Max11620>(spi)
} }
pub fn max11621(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn max11621(spi: Spi) -> Result<Self, Error<Spi::Error, Infallible>> {
Self::new::<Max11621>(spi, cs) Self::new::<Max11621>(spi)
} }
pub fn max11624(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn max11624(spi: Spi) -> Result<Self, Error<Spi::Error, Infallible>> {
Self::new::<Max11624>(spi, cs) Self::new::<Max11624>(spi)
} }
pub fn max11625(spi: SPI, cs: CS) -> Result<Self, Error<SpiE, PinE>> { pub fn max11625(spi: Spi) -> Result<Self, Error<Spi::Error, Infallible>> {
Self::new::<Max11625>(spi, cs) Self::new::<Max11625>(spi)
} }
/// Create a new generic MAX116xx instance. By default the generated ADC struct is configured /// 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` /// 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) -> Result<Self, Error<Spi::Error, Infallible>> {
let max_dev = Max116xx10Bit { let max_dev = Max116xx10Bit {
spi, spi,
cs,
cfg: InternalCfg { cfg: InternalCfg {
clk_mode: ExtClkd::CLK_SEL, clk_mode: ExtClkd::CLK_SEL,
ref_mode: VoltageRefMode::ExternalSingleEndedNoWakeupDelay, ref_mode: VoltageRefMode::ExternalSingleEndedNoWakeupDelay,
@ -298,10 +300,9 @@ 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, ExtClkd, WithWakeupDelay> {
Max116xx10Bit { Max116xx10Bit {
spi: self.spi, spi: self.spi,
cs: self.cs,
cfg: InternalCfg { cfg: InternalCfg {
clk_mode: ExtClkd::CLK_SEL, clk_mode: ExtClkd::CLK_SEL,
ref_mode: VoltageRefMode::InternalRefWithWakeupDelay, ref_mode: VoltageRefMode::InternalRefWithWakeupDelay,
@ -321,10 +322,9 @@ 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, ExtClkd, WithoutWakeupDelay> {
Max116xx10Bit { Max116xx10Bit {
spi: self.spi, spi: self.spi,
cs: self.cs,
cfg: InternalCfg { cfg: InternalCfg {
clk_mode: ExtClkd::CLK_SEL, clk_mode: ExtClkd::CLK_SEL,
ref_mode: VoltageRefMode::InternalRefWithoutWakeupDelay, ref_mode: VoltageRefMode::InternalRefWithoutWakeupDelay,
@ -342,14 +342,13 @@ 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, Eoc, IntClkdIntTmdSerIF> {
Max116xx10BitEocExt { Max116xx10BitEocExt {
base: Max116xx10Bit { base: Max116xx10Bit {
spi: self.spi, spi: self.spi,
cs: self.cs,
cfg: InternalCfg { cfg: InternalCfg {
clk_mode: IntClkdIntTmdSerIF::CLK_SEL, clk_mode: IntClkdIntTmdSerIF::CLK_SEL,
ref_mode: VoltageRefMode::InternalRefWithWakeupDelay, ref_mode: VoltageRefMode::InternalRefWithWakeupDelay,
@ -371,18 +370,17 @@ 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, Eoc, IntClkdIntTmdSerIF>, AdcError> {
if v_ref == VoltageRefMode::InternalRefWithWakeupDelay { if v_ref == VoltageRefMode::InternalRefWithWakeupDelay {
return Err(AdcError::InvalidRefMode); return Err(AdcError::InvalidRefMode);
} }
Ok(Max116xx10BitEocExt { Ok(Max116xx10BitEocExt {
base: Max116xx10Bit { base: Max116xx10Bit {
spi: self.spi, spi: self.spi,
cs: self.cs,
cfg: InternalCfg { cfg: InternalCfg {
clk_mode: IntClkdIntTmdSerIF::CLK_SEL, clk_mode: IntClkdIntTmdSerIF::CLK_SEL,
ref_mode: VoltageRefMode::InternalRefWithWakeupDelay, ref_mode: VoltageRefMode::InternalRefWithWakeupDelay,
@ -399,22 +397,16 @@ where
} }
} }
impl<SpiE, PinE, CS, SPI, CLOCKED: Clocked, WAKEUP> Max116xx10Bit<SPI, CS, CLOCKED, WAKEUP> impl<Spi: SpiDevice, Clocked: ClockedProvider, Wakeup> Max116xx10Bit<Spi, Clocked, Wakeup> {
where
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, Infallible>> {
self.cs.set_low().map_err(Error::Pin)?; self.spi.write(&[byte]).map_err(Error::Spi)?;
nb::block!(self.spi.send(byte)).map_err(Error::Spi)?;
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, Infallible>> {
self.send_wrapper(self.get_setup_byte()) self.send_wrapper(self.get_setup_byte())
} }
@ -425,13 +417,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, Infallible>> {
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, Infallible>> {
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 +460,22 @@ 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>(
&mut self, &mut self,
eoc: &mut EOC, eoc: &mut Eoc,
) -> nb::Result<u16, Error<SpiE, PinE>> { ) -> nb::Result<u16, Error<Spi::Error, Eoc::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)?; let transfer_result = self.spi.read(&mut reply_buf);
let transfer_result = self.spi.transfer(&mut dummy_cmd);
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 +489,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, Infallible>> {
self.base.send_wrapper(self.base.get_setup_byte()) self.base.send_wrapper(self.base.get_setup_byte())
} }
@ -510,16 +500,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, Infallible>> {
self.base.cfg.results_len = Max116xx10Bit::<SPI, CS, CLOCKED>::get_results_len(avg_res); self.base.cfg.results_len = Max116xx10Bit::<Spi, Clocked>::get_results_len(avg_res);
self.base self.base
.send_wrapper(Max116xx10Bit::<SPI, CS, CLOCKED>::get_averaging_byte( .send_wrapper(Max116xx10Bit::<Spi, 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, Infallible>> {
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 +518,12 @@ macro_rules! ext_impl {
} }
}; };
} }
impl<SpiE, PinE, CS, SPI, EOC, CLOCKED: Clocked> Max116xx10BitEocExt<SPI, CS, EOC, CLOCKED> impl<Spi: SpiDevice, Eoc, Clocked: ClockedProvider> Max116xx10BitEocExt<Spi, Eoc, Clocked> {
where
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<Spi: SpiDevice, EOC, CNVST, Clocked: ClockedProvider, DELAY>
Max116xx10BitCnvstEocExt<SPI, CS, EOC, CNVST, CLOCKED, DELAY> Max116xx10BitCnvstEocExt<Spi, EOC, CNVST, Clocked, DELAY>
where
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
{ {
ext_impl!(); ext_impl!();
} }
@ -550,26 +533,20 @@ 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> Max116xx10Bit<Spi, 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, Infallible>> {
if buf.len() < 3 { if buf.len() < 3 {
return Err(Error::Adc(AdcError::CmdBufTooSmall)); return Err(Error::Adc(AdcError::CmdBufTooSmall));
} }
buf[0] = self.get_conversion_byte(ScanMode::ConvertChannelNOnce, channel_num)?; buf[0] = self.get_conversion_byte(ScanMode::ConvertChannelNOnce, channel_num)?;
buf[1] = 0x00; buf[1] = 0x00;
buf[2] = 0x00; buf[2] = 0x00;
self.cs.set_low().map_err(Error::Pin)?; self.spi.transfer_in_place(&mut buf[0..3]).ok().unwrap();
let reply = self.spi.transfer(&mut buf[0..3]).ok().unwrap(); Ok(((buf[1] as u16) << 6) | (buf[2] as u16 >> 2))
self.cs.set_high().map_err(Error::Pin)?;
Ok(((reply[1] as u16) << 6) | (reply[2] as u16 >> 2))
} }
pub fn read_multiple_channels_0_to_n( pub fn read_multiple_channels_0_to_n(
@ -577,7 +554,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, Infallible>> {
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 {
@ -588,13 +565,10 @@ 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.spi
let reply = self .transfer_in_place(&mut buf[0..((n + 1) * 2 + 1) as usize])
.spi
.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)?; let mut reply_iter = buf.iter();
let mut reply_iter = reply.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 +586,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, Infallible>> {
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 {
@ -627,13 +601,10 @@ 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.spi
let reply = self .transfer_in_place(&mut buf[0..(conversions * 2 + 1) as usize])
.spi
.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)?; let mut reply_iter = buf.iter();
let mut reply_iter = reply.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 +620,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> Max116xx10Bit<Spi, 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, Infallible>> {
if buf.len() < 3 { if buf.len() < 3 {
return Err(Error::Adc(AdcError::CmdBufTooSmall)); return Err(Error::Adc(AdcError::CmdBufTooSmall));
} }
@ -670,19 +637,19 @@ where
delay.delay_us(65); delay.delay_us(65);
buf[0] = 0x00; buf[0] = 0x00;
buf[1] = 0x00; buf[1] = 0x00;
self.cs.set_low().map_err(Error::Pin)?; self.spi
let reply = self.spi.transfer(&mut buf[0..2]).map_err(Error::Spi)?; .transfer_in_place(&mut buf[0..2])
self.cs.set_high().map_err(Error::Pin)?; .map_err(Error::Spi)?;
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, Infallible>> {
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 {
@ -697,13 +664,10 @@ 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.spi
let reply = self .transfer_in_place(&mut buf[1..((n + 1) * 2 + 1) as usize])
.spi
.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)?; let mut reply_iter = buf.iter();
let mut reply_iter = reply.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 +678,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, Infallible>> {
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 {
@ -739,13 +703,10 @@ where
// reference to power up // reference to power up
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.spi
let reply = self .transfer_in_place(&mut buf[1..(conversions * 2 + 1) as usize])
.spi
.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)?; let mut reply_iter = buf.iter();
let mut reply_iter = reply.iter();
for _ in 0..conversions { for _ in 0..conversions {
let next_res = result_iter let next_res = result_iter
.next() .next()
@ -763,18 +724,13 @@ 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, Eoc: InputPin> Max116xx10BitEocExt<Spi, Eoc, IntClkdIntTmdSerIF> {
where
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, Infallible>> {
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));
} }
@ -782,12 +738,15 @@ where
.base .base
.get_conversion_byte(scan_mode, channel_num) .get_conversion_byte(scan_mode, channel_num)
.map_err(Error::Adc)?; .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); self.base.cfg.pending_scan_mode = Some(scan_mode);
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, Infallible>> {
self.request_wrapper(channel_num, ScanMode::ConvertChannelNOnce) self.request_wrapper(channel_num, ScanMode::ConvertChannelNOnce)
} }
@ -797,11 +756,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, Infallible>> {
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, Infallible>> {
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 +771,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, Infallible>> {
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 +780,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, Eoc::Error>> {
self.base.internal_read_single_channel(&mut self.eoc) self.base.internal_read_single_channel(&mut self.eoc)
} }
@ -828,7 +790,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, Eoc::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,32 +798,28 @@ 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) {
num_conv = self.base.cfg.results_len as usize; self.base.cfg.results_len as usize
} else { } else {
num_conv = self.base.cfg.requested_conversions; self.base.cfg.requested_conversions
} };
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
let transfer_result = self.base.spi.transfer(&mut dummy_cmd[0..(num_conv * 2)]); .spi
self.base.cs.set_high().map_err(Error::Pin)?; .read(&mut reply_buf[0..(num_conv * 2)])
match transfer_result { .map_err(Error::Spi)?;
Ok(reply) => { let mut reply_iter = reply_buf.iter();
let mut reply_iter = reply.iter(); for _ in 0..num_conv {
for _ in 0..num_conv { let next_res = result_iter
let next_res = result_iter .next()
.next() .ok_or(Error::Adc(AdcError::ResulBufTooSmall))?;
.ok_or(Error::Adc(AdcError::ResulBufTooSmall))?; *next_res = ((*reply_iter.next().unwrap() as u16) << 6)
*next_res = ((*reply_iter.next().unwrap() as u16) << 6) | (*reply_iter.next().unwrap() as u16 >> 2);
| (*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 +835,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, Eoc: InputPin, Cnvst: OutputPin>
Max116xx10BitCnvstEocExt<SPI, CS, EOC, CNVST, IntClkdExtTmdCnvst, WithoutWakeupDelay> Max116xx10BitCnvstEocExt<Spi, 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 +845,8 @@ 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<Spi: SpiDevice, Eoc: InputPin<Error = PinE>, Cnvst: OutputPin<Error = PinE>, PinE>
Max116xx10BitCnvstEocExt<SPI, CS, EOC, CNVST, IntClkdIntTmdCnvst, WithWakeupDelay> Max116xx10BitCnvstEocExt<Spi, Eoc, Cnvst, IntClkdIntTmdCnvst, WithWakeupDelay>
where
SPI: Transfer<u8, Error = SpiE> + FullDuplex<u8, Error = SpiE>,
CS: OutputPin<Error = PinE>,
EOC: InputPin<Error = PinE>,
CNVST: OutputPin<Error = PinE>,
{ {
/// 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 +854,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 +864,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));
} }
@ -927,7 +872,7 @@ where
.base .base
.get_conversion_byte(scan_mode, channel_num) .get_conversion_byte(scan_mode, channel_num)
.map_err(Error::Adc)?; .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)?; self.cnvst.set_low().map_err(Error::Pin)?;
for _ in 0..pulse_cycles {} for _ in 0..pulse_cycles {}
self.cnvst.set_high().map_err(Error::Pin)?; self.cnvst.set_high().map_err(Error::Pin)?;
@ -935,7 +880,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)
} }
} }