From 302809f176e85af233cc5dd16867d9130225c97b Mon Sep 17 00:00:00 2001 From: Jaedson Date: Sat, 30 Sep 2023 11:09:32 -0300 Subject: [PATCH 1/4] Update embedded-hal requirement from 0.2.2 to 1.0.0-rc.1 --- Cargo.toml | 4 +- src/adc.rs | 95 ++++++++++++++++++++++++++++++++++ src/channels.rs | 2 +- src/construction.rs | 7 +-- src/devices/mode/continuous.rs | 2 +- src/devices/mode/oneshot.rs | 2 +- src/interface.rs | 9 ++-- src/lib.rs | 6 ++- 8 files changed, 113 insertions(+), 14 deletions(-) create mode 100644 src/adc.rs diff --git a/Cargo.toml b/Cargo.toml index 236f783..773dad0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ads1x1x" -version = "0.2.2" # remember to update html_root_url +version = "0.3.0" # remember to update html_root_url authors = ["Diego Barrios Romero "] repository = "https://github.com/eldruin/ads1x1x-rs" license = "MIT OR Apache-2.0" @@ -25,7 +25,7 @@ coveralls = { repository = "eldruin/ads1x1x-rs", branch = "master", service = "g [dependencies] nb = "1" -embedded-hal = { version = "0.2.2", features = ["unproven"] } +embedded-hal = "1.0.0-rc.1" [dev-dependencies] linux-embedded-hal = "0.3" diff --git a/src/adc.rs b/src/adc.rs new file mode 100644 index 0000000..dcde3e7 --- /dev/null +++ b/src/adc.rs @@ -0,0 +1,95 @@ +//! Analog-digital conversion traits + +use nb; + +/// A marker trait to identify MCU pins that can be used as inputs to an ADC channel. +/// +/// This marker trait denotes an object, i.e. a GPIO pin, that is ready for use as an input to the +/// ADC. As ADCs channels can be supplied by multiple pins, this trait defines the relationship +/// between the physical interface and the ADC sampling buffer. +/// +/// ``` +/// # use std::marker::PhantomData; +/// # use embedded_hal::adc::Channel; +/// +/// struct Adc1; // Example ADC with single bank of 8 channels +/// struct Gpio1Pin1(PhantomData); +/// struct Analog(()); // marker type to denote a pin in "analog" mode +/// +/// // GPIO 1 pin 1 can supply an ADC channel when it is configured in Analog mode +/// impl Channel for Gpio1Pin1 { +/// type ID = u8; // ADC channels are identified numerically +/// +/// fn channel() -> u8 { 7_u8 } // GPIO pin 1 is connected to ADC channel 7 +/// } +/// +/// struct Adc2; // ADC with two banks of 16 channels +/// struct Gpio2PinA(PhantomData); +/// struct AltFun(()); // marker type to denote some alternate function mode for the pin +/// +/// // GPIO 2 pin A can supply an ADC channel when it's configured in some alternate function mode +/// impl Channel for Gpio2PinA { +/// type ID = (u8, u8); // ADC channels are identified by bank number and channel number +/// +/// fn channel() -> (u8, u8) { (0, 3) } // bank 0 channel 3 +/// } +/// ``` +pub trait Channel { + /// Channel ID type + /// + /// A type used to identify this ADC channel. For example, if the ADC has eight channels, this + /// might be a `u8`. If the ADC has multiple banks of channels, it could be a tuple, like + /// `(u8: bank_id, u8: channel_id)`. + type ID; + + /// Get the specific ID that identifies this channel, for example `0_u8` for the first ADC + /// channel, if Self::ID is u8. + fn channel() -> Self::ID; + + // `channel` is a function due to [this reported + // issue](https://github.com/rust-lang/rust/issues/54973). Something about blanket impls + // combined with `type ID; const CHANNEL: Self::ID;` causes problems. + //const CHANNEL: Self::ID; +} + +/// ADCs that sample on single channels per request, and do so at the time of the request. +/// +/// This trait is the interface to an ADC that is configured to read a specific channel at the time +/// of the request (in contrast to continuous asynchronous sampling). +/// +/// ``` +/// use embedded_hal::adc::{Channel, OneShot}; +/// +/// struct MyAdc; // 10-bit ADC, with 5 channels +/// # impl MyAdc { +/// # pub fn power_up(&mut self) {} +/// # pub fn power_down(&mut self) {} +/// # pub fn do_conversion(&mut self, chan: u8) -> u16 { 0xAA55_u16 } +/// # } +/// +/// impl OneShot for MyAdc +/// where +/// WORD: From, +/// PIN: Channel, +/// { +/// type Error = (); +/// +/// fn read(&mut self, _pin: &mut PIN) -> nb::Result { +/// let chan = 1 << PIN::channel(); +/// self.power_up(); +/// let result = self.do_conversion(chan); +/// self.power_down(); +/// Ok(result.into()) +/// } +/// } +/// ``` +pub trait OneShot> { + /// Error type returned by ADC methods + type Error; + + /// Request that the ADC begin a conversion on the specified pin + /// + /// This method takes a `Pin` reference, as it is expected that the ADC will be able to sample + /// whatever channel underlies the pin. + fn read(&mut self, pin: &mut Pin) -> nb::Result; +} \ No newline at end of file diff --git a/src/channels.rs b/src/channels.rs index a4c806c..759be46 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -1,6 +1,6 @@ //! ADC input channels use crate::{ic, Ads1x1x, BitFlags as BF, Config}; -use embedded_hal::adc; +use crate::adc; /// ADC input channel selection #[allow(dead_code)] diff --git a/src/construction.rs b/src/construction.rs index e217c85..fed0908 100644 --- a/src/construction.rs +++ b/src/construction.rs @@ -5,13 +5,13 @@ use crate::{ DEVICE_BASE_ADDRESS, }; use core::marker::PhantomData; -use embedded_hal::blocking; +use embedded_hal::i2c::I2c; macro_rules! impl_new_destroy { ( $IC:ident, $create:ident, $destroy:ident, $conv:ty ) => { impl Ads1x1x, ic::$IC, $conv, mode::OneShot> where - I2C: blocking::i2c::Write + blocking::i2c::WriteRead, + I2C: I2c, { /// Create a new instance of the device in OneShot mode. pub fn $create(i2c: I2C, address: SlaveAddr) -> Self { @@ -29,7 +29,8 @@ macro_rules! impl_new_destroy { } } } - impl Ads1x1x, ic::$IC, CONV, MODE> { + impl Ads1x1x, ic::$IC, CONV, MODE> + where I2C: embedded_hal::i2c::I2c { /// Destroy driver instance, return I²C bus instance. pub fn $destroy(self) -> I2C { self.iface.i2c diff --git a/src/devices/mode/continuous.rs b/src/devices/mode/continuous.rs index 64aa179..768445c 100644 --- a/src/devices/mode/continuous.rs +++ b/src/devices/mode/continuous.rs @@ -5,7 +5,7 @@ use crate::{ Error, ModeChangeError, Register, }; use core::marker::PhantomData; -use embedded_hal::adc; +use crate::adc; impl Ads1x1x where diff --git a/src/devices/mode/oneshot.rs b/src/devices/mode/oneshot.rs index fa4d3b8..3ebb885 100644 --- a/src/devices/mode/oneshot.rs +++ b/src/devices/mode/oneshot.rs @@ -4,7 +4,7 @@ use crate::{ Config, DynamicOneShot, Error, ModeChangeError, Register, }; use core::marker::PhantomData; -use embedded_hal::adc; +use crate::adc; impl Ads1x1x where diff --git a/src/interface.rs b/src/interface.rs index 960c7ef..6a2a89a 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,11 +1,12 @@ //! I2C interface use crate::{private, Error}; -use embedded_hal::blocking; +use embedded_hal::i2c::I2c; /// I2C interface #[derive(Debug, Default)] -pub struct I2cInterface { +pub struct I2cInterface +where I2C: I2c { pub(crate) i2c: I2C, pub(crate) address: u8, } @@ -20,7 +21,7 @@ pub trait WriteData: private::Sealed { impl WriteData for I2cInterface where - I2C: blocking::i2c::Write, + I2C: I2c, { type Error = E; fn write_register(&mut self, register: u8, data: u16) -> Result<(), Error> { @@ -39,7 +40,7 @@ pub trait ReadData: private::Sealed { impl ReadData for I2cInterface where - I2C: blocking::i2c::WriteRead, + I2C: I2c, { type Error = E; fn read_register(&mut self, register: u8) -> Result> { diff --git a/src/lib.rs b/src/lib.rs index e5405d1..eb9f3e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -202,7 +202,7 @@ //! adc.set_comparator_latching(ComparatorLatching::Latching).unwrap(); //! ``` -#![doc(html_root_url = "https://docs.rs/ads1x1x/0.2.2")] +#![doc(html_root_url = "https://docs.rs/ads1x1x/0.3.0")] #![deny(unsafe_code)] #![deny(missing_docs)] #![no_std] @@ -238,6 +238,7 @@ impl BitFlags { } mod channels; +mod adc; pub use crate::channels::{channel, ChannelSelection}; mod construction; mod conversion; @@ -259,7 +260,8 @@ mod private { use super::{ic, interface, Ads1x1x}; pub trait Sealed {} - impl Sealed for interface::I2cInterface {} + impl Sealed for interface::I2cInterface + where I2C: embedded_hal::i2c::I2c {} impl Sealed for Ads1x1x {} impl Sealed for ic::Resolution12Bit {} From 50a48b87f578028cc90251df7f7ceb9ef9f2f7cb Mon Sep 17 00:00:00 2001 From: Jaedson Date: Sat, 30 Sep 2023 12:15:26 -0300 Subject: [PATCH 2/4] update edition from 2018 to 2021 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 773dad0..a46840a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ include = [ "/LICENSE-MIT", "/LICENSE-APACHE", ] -edition = "2018" +edition = "2021" [badges] coveralls = { repository = "eldruin/ads1x1x-rs", branch = "master", service = "github" } From 2e6f7a3d0d809f4069ca0896e954c16ddf577820 Mon Sep 17 00:00:00 2001 From: Jaedson Date: Sat, 30 Sep 2023 12:19:43 -0300 Subject: [PATCH 3/4] applied clippy suggestions --- src/adc.rs | 2 -- src/conversion.rs | 2 +- src/devices/common.rs | 9 ++++----- src/types.rs | 8 +++----- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/adc.rs b/src/adc.rs index dcde3e7..ca1feb4 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1,7 +1,5 @@ //! Analog-digital conversion traits -use nb; - /// A marker trait to identify MCU pins that can be used as inputs to an ADC channel. /// /// This marker trait denotes an object, i.e. a GPIO pin, that is ready for use as an input to the diff --git a/src/conversion.rs b/src/conversion.rs index d6aea82..142de0e 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -7,7 +7,7 @@ pub trait ConvertThreshold: private::Sealed { impl ConvertThreshold for ic::Resolution12Bit { fn convert_threshold(value: i16) -> Result> { - if value < -2048 || value > 2047 { + if !(-2048..=2047).contains(&value) { return Err(Error::InvalidInputData); } Ok((value << 4) as u16) diff --git a/src/devices/common.rs b/src/devices/common.rs index 2234d93..f1509d3 100644 --- a/src/devices/common.rs +++ b/src/devices/common.rs @@ -7,11 +7,10 @@ where DI: interface::WriteData + interface::ReadData, { pub(super) fn set_operating_mode(&mut self, mode: OperatingMode) -> Result<(), Error> { - let config; - match mode { - OperatingMode::OneShot => config = self.config.with_high(BitFlags::OP_MODE), - OperatingMode::Continuous => config = self.config.with_low(BitFlags::OP_MODE), - } + let config = match mode { + OperatingMode::OneShot => self.config.with_high(BitFlags::OP_MODE), + OperatingMode::Continuous => self.config.with_low(BitFlags::OP_MODE), + }; self.iface.write_register(Register::CONFIG, config.bits)?; self.config = config; Ok(()) diff --git a/src/types.rs b/src/types.rs index 957825e..71aaa33 100644 --- a/src/types.rs +++ b/src/types.rs @@ -139,12 +139,14 @@ pub enum ComparatorQueue { /// The FSR is fixed at ±2.048 V in the ADS1x13. #[derive(Clone, Copy, Debug, PartialEq)] #[allow(non_camel_case_types)] +#[derive(Default)] pub enum FullScaleRange { /// The measurable range is ±6.144V. Within6_144V, /// The measurable range is ±4.096V. Within4_096V, /// The measurable range is ±2.048V. (default) + #[default] Within2_048V, /// The measurable range is ±1.024V. Within1_024V, @@ -241,11 +243,7 @@ impl Default for Config { } } -impl Default for FullScaleRange { - fn default() -> Self { - FullScaleRange::Within2_048V - } -} + /// ADS1x1x ADC driver #[derive(Debug, Default)] From 869a58ba22a1569682ee960c1b45a3688c223a28 Mon Sep 17 00:00:00 2001 From: Jaedson Date: Sat, 30 Sep 2023 12:31:54 -0300 Subject: [PATCH 4/4] Update adc visibility to pub --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index eb9f3e9..863891b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -238,7 +238,7 @@ impl BitFlags { } mod channels; -mod adc; +pub mod adc; pub use crate::channels::{channel, ChannelSelection}; mod construction; mod conversion;