From 28126fee8ce253e67ab737927ff0d89ebc24e419 Mon Sep 17 00:00:00 2001 From: Diego Barrios Romero Date: Thu, 29 Jul 2021 23:14:25 +0200 Subject: Add value-based one-shot trait to ease driver usage in functions --- CHANGELOG.md | 3 +++ examples/trait.rs | 24 ++++++++++++++++++++++++ src/channels.rs | 9 +++++++++ src/devices/mode/oneshot.rs | 20 ++++++++++++++++---- src/lib.rs | 8 +++++--- src/types.rs | 11 +++++++++++ 6 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 examples/trait.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index cd5f06e..be9b2fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added +- `DynamicOneShot` trait to ease usage of driver in functions. See `trait` example. + ### Changed - Updated `nb` dependency to version `1`. diff --git a/examples/trait.rs b/examples/trait.rs new file mode 100644 index 0000000..eda1f37 --- /dev/null +++ b/examples/trait.rs @@ -0,0 +1,24 @@ +// This example demonstrates the use of a type alias for the `Ads1x1x` struct +// to ease usage in signatures. + +use linux_embedded_hal::I2cdev; +use nb::block; + +use ads1x1x::{Ads1x1x, ChannelSelection, DynamicOneShot, SlaveAddr}; + +/// Read a single value from channel A. +/// Returns 0 on Error. +pub fn read>(adc: &mut A) -> i16 { + block!(adc.read(ChannelSelection::SingleA0)).unwrap_or(0) +} + +fn main() { + let dev = I2cdev::new("/dev/i2c-1").unwrap(); + let address = SlaveAddr::default(); + let mut adc = Ads1x1x::new_ads1115(dev, address); + + let value = read(&mut adc); + println!("Measurement: {}", value); + // get I2C device back + let _dev = adc.destroy_ads1115(); +} diff --git a/src/channels.rs b/src/channels.rs index c0f0ff9..a4c806c 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -23,15 +23,24 @@ pub mod channel { pub struct DifferentialA2A3; } +/// ADC input channel selection #[derive(Debug, Clone, Copy)] pub enum ChannelSelection { + /// Measure single-ended signal on input channel 0 SingleA0, + /// Measure single-ended signal on input channel 1 SingleA1, + /// Measure single-ended signal on input channel 2 SingleA2, + /// Measure single-ended signal on input channel 3 SingleA3, + /// Measure signal on input channel 0 differentially to signal on input channel 1 DifferentialA0A1, + /// Measure signal on input channel 0 differentially to signal on input channel 3 DifferentialA0A3, + /// Measure signal on input channel 1 differentially to signal on input channel 3 DifferentialA1A3, + /// Measure signal on input channel 2 differentially to signal on input channel 3 DifferentialA2A3, } diff --git a/src/devices/mode/oneshot.rs b/src/devices/mode/oneshot.rs index 665ce33..fa4d3b8 100644 --- a/src/devices/mode/oneshot.rs +++ b/src/devices/mode/oneshot.rs @@ -1,7 +1,7 @@ //! Common functions use crate::{ - channels::ChannelSelection, conversion, devices::OperatingMode, interface, mode, Ads1x1x, - BitFlags, Config, Error, ModeChangeError, Register, + conversion, devices::OperatingMode, interface, mode, Ads1x1x, BitFlags, ChannelSelection, + Config, DynamicOneShot, Error, ModeChangeError, Register, }; use core::marker::PhantomData; use embedded_hal::adc; @@ -58,13 +58,25 @@ where /// measurement on a different channel is requested, a new measurement on /// using the new channel selection is triggered. fn read(&mut self, _channel: &mut CH) -> nb::Result { + ::read(self, CH::channel()) + } +} + +impl DynamicOneShot for Ads1x1x +where + DI: interface::ReadData + interface::WriteData, + CONV: conversion::ConvertMeasurement, +{ + type Error = Error; + + fn read(&mut self, channel: ChannelSelection) -> nb::Result { if self .is_measurement_in_progress() .map_err(nb::Error::Other)? { return Err(nb::Error::WouldBlock); } - let same_channel = self.config == self.config.with_mux_bits(CH::channel()); + let same_channel = self.config == self.config.with_mux_bits(channel); if self.a_conversion_was_started && same_channel { // result is ready let value = self @@ -74,7 +86,7 @@ where self.a_conversion_was_started = false; return Ok(CONV::convert_measurement(value)); } - let config = self.config.with_mux_bits(CH::channel()); + let config = self.config.with_mux_bits(channel); self.trigger_measurement(&config) .map_err(nb::Error::Other)?; self.config = config; diff --git a/src/lib.rs b/src/lib.rs index 418fc46..90a0f62 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -237,7 +237,7 @@ impl BitFlags { } mod channels; -pub use crate::channels::channel; +pub use crate::channels::{channel, ChannelSelection}; mod construction; mod conversion; pub use crate::conversion::{ConvertMeasurement, ConvertThreshold}; @@ -250,14 +250,16 @@ mod types; use crate::types::Config; pub use crate::types::{ mode, Ads1x1x, ComparatorLatching, ComparatorMode, ComparatorPolarity, ComparatorQueue, - DataRate12Bit, DataRate16Bit, Error, FullScaleRange, ModeChangeError, SlaveAddr, + DataRate12Bit, DataRate16Bit, DynamicOneShot, Error, FullScaleRange, ModeChangeError, + SlaveAddr, }; mod private { - use super::{ic, interface}; + use super::{ic, interface, Ads1x1x}; pub trait Sealed {} impl Sealed for interface::I2cInterface {} + impl Sealed for Ads1x1x {} impl Sealed for ic::Resolution12Bit {} impl Sealed for ic::Resolution16Bit {} diff --git a/src/types.rs b/src/types.rs index 2b9fc02..957825e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,5 +1,6 @@ //! Type definitions. +use crate::{channels::ChannelSelection, private}; use core::marker::PhantomData; /// Errors in this crate @@ -70,6 +71,7 @@ pub enum DataRate16Bit { /// 860 SPS Sps860, } + /// Comparator mode (only for ADS1x14, ADS1x15) #[derive(Debug, Clone, Copy, PartialEq)] pub enum ComparatorMode { @@ -257,6 +259,15 @@ pub struct Ads1x1x { pub(crate) _mode: PhantomData, } +/// Multi channel One-shot ADC +pub trait DynamicOneShot: private::Sealed { + /// Error type + type Error; + + /// Read a measurement + fn read(&mut self, channel: ChannelSelection) -> nb::Result; +} + #[cfg(test)] mod tests { use crate::DEVICE_BASE_ADDRESS as ADDR; -- cgit v1.2.3-54-g00ecf