diff options
author | Diego Barrios Romero <eldruin@gmail.com> | 2018-11-07 20:22:59 +0100 |
---|---|---|
committer | Diego Barrios Romero <eldruin@gmail.com> | 2018-11-07 20:22:59 +0100 |
commit | 483221e740ffaebe406ee428beb59fa136d70c7f (patch) | |
tree | f7fee2bbc46b97f1508d4b8bc2fec258695e4239 /src | |
parent | ec0ffcaa6d49ae7c6e3256f9742e996d7b0752c4 (diff) | |
download | ads1x1x-async-483221e740ffaebe406ee428beb59fa136d70c7f.tar.gz ads1x1x-async-483221e740ffaebe406ee428beb59fa136d70c7f.tar.xz ads1x1x-async-483221e740ffaebe406ee428beb59fa136d70c7f.zip |
Add support for one-shot measurements
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/ads1x1x/common.rs | 37 | ||||
-rw-r--r-- | src/devices/ads1x1x/mod.rs | 9 | ||||
-rw-r--r-- | src/devices/ads1x1x/mode/continuous.rs | 22 | ||||
-rw-r--r-- | src/devices/ads1x1x/mode/mod.rs | 26 | ||||
-rw-r--r-- | src/devices/ads1x1x/mode/oneshot.rs | 61 | ||||
-rw-r--r-- | src/lib.rs | 4 |
6 files changed, 159 insertions, 0 deletions
diff --git a/src/devices/ads1x1x/common.rs b/src/devices/ads1x1x/common.rs new file mode 100644 index 0000000..ce8a67a --- /dev/null +++ b/src/devices/ads1x1x/common.rs @@ -0,0 +1,37 @@ +//! Common functions + +use { Ads1x1x, DataRate, Error, Register, BitFlags, interface }; +use super::OperatingMode; + +impl<DI, IC, MODE, E> Ads1x1x<DI, IC, MODE> +where + DI: interface::WriteData<Error = E> +{ + pub(super) fn set_operating_mode(&mut self, mode: OperatingMode) -> Result<(), Error<E>> { + let config; + match mode { + OperatingMode::OneShot => config = self.config.with_high(BitFlags::OP_MODE), + OperatingMode::Continuous => config = self.config.with_low(BitFlags::OP_MODE), + } + self.iface.write_register(Register::CONFIG, config.bits)?; + self.config = config; + Ok(()) + } + + /// Set data rate + pub fn set_data_rate(&mut self, rate: DataRate) -> Result<(), Error<E>> { + let config; + match rate { + DataRate::Sps128 => config = self.config.with_low( BitFlags::DR2).with_low( BitFlags::DR1).with_low( BitFlags::DR0), + DataRate::Sps250 => config = self.config.with_low( BitFlags::DR2).with_low( BitFlags::DR1).with_high(BitFlags::DR0), + DataRate::Sps490 => config = self.config.with_low( BitFlags::DR2).with_high(BitFlags::DR1).with_low( BitFlags::DR0), + DataRate::Sps920 => config = self.config.with_low( BitFlags::DR2).with_high(BitFlags::DR1).with_high(BitFlags::DR0), + DataRate::Sps1600 => config = self.config.with_high(BitFlags::DR2).with_low( BitFlags::DR1).with_low( BitFlags::DR0), + DataRate::Sps2400 => config = self.config.with_high(BitFlags::DR2).with_low( BitFlags::DR1).with_high(BitFlags::DR0), + DataRate::Sps3300 => config = self.config.with_high(BitFlags::DR2).with_high(BitFlags::DR1).with_low( BitFlags::DR0), + } + self.iface.write_register(Register::CONFIG, config.bits)?; + self.config = config; + Ok(()) + } +} diff --git a/src/devices/ads1x1x/mod.rs b/src/devices/ads1x1x/mod.rs new file mode 100644 index 0000000..b7146a9 --- /dev/null +++ b/src/devices/ads1x1x/mod.rs @@ -0,0 +1,9 @@ +//! Functions for all devices + +enum OperatingMode { + OneShot, + Continuous +} + +mod common; +mod mode; diff --git a/src/devices/ads1x1x/mode/continuous.rs b/src/devices/ads1x1x/mode/continuous.rs new file mode 100644 index 0000000..1532b62 --- /dev/null +++ b/src/devices/ads1x1x/mode/continuous.rs @@ -0,0 +1,22 @@ +//! Common functions + +use core::marker::PhantomData; +use { Ads1x1x, mode, Error, interface }; +use super::super::OperatingMode; + +impl<DI, IC, E> Ads1x1x<DI, IC, mode::Continuous> +where + DI: interface::WriteData<Error = E> +{ + /// Change operating mode to OneShot + pub fn into_one_shot(mut self) -> Result<Ads1x1x<DI, IC, mode::OneShot>, Error<E>> { + self.set_operating_mode(OperatingMode::OneShot)?; + Ok(Ads1x1x { + iface: self.iface, + config: self.config, + a_conversion_was_started: self.a_conversion_was_started, + _ic: PhantomData, + _mode: PhantomData + }) + } +} diff --git a/src/devices/ads1x1x/mode/mod.rs b/src/devices/ads1x1x/mode/mod.rs new file mode 100644 index 0000000..1a01d27 --- /dev/null +++ b/src/devices/ads1x1x/mode/mod.rs @@ -0,0 +1,26 @@ +//! Functions for all devices specific to each operating mode + +use ic; + +fn convert_measurement<IC>(register_data: u16) -> i16 +where + IC: ic::Resolution +{ + let value = register_data; + if IC::BITS == ic::ResolutionBits::_12 { + let is_negative = (value & 0b1000_0000_0000_0000) != 0; + if is_negative { + let value = 0b1111_0000_0000_0000 | (value >> 4); + value as i16 + } + else { + (value >> 4) as i16 + } + } + else { + value as i16 + } +} + +mod oneshot; +mod continuous; diff --git a/src/devices/ads1x1x/mode/oneshot.rs b/src/devices/ads1x1x/mode/oneshot.rs new file mode 100644 index 0000000..61d4e70 --- /dev/null +++ b/src/devices/ads1x1x/mode/oneshot.rs @@ -0,0 +1,61 @@ +//! Common functions + +use core::marker::PhantomData; +use { Ads1x1x, mode, Error, Register, BitFlags, Config, ic }; +use { interface, hal }; +use super::super::OperatingMode; +use super::convert_measurement; + +impl<DI, IC, E> Ads1x1x<DI, IC, mode::OneShot> +where + DI: interface::WriteData<Error = E> + interface::ReadData<Error = E> +{ + /// Change operating mode to Continuous + pub fn into_continuous(mut self) -> Result<Ads1x1x<DI, IC, mode::Continuous>, Error<E>> { + self.set_operating_mode(OperatingMode::Continuous)?; + Ok(Ads1x1x { + iface: self.iface, + config: self.config, + a_conversion_was_started: self.a_conversion_was_started, + _ic: PhantomData, + _mode: PhantomData + }) + } + + fn is_measurement_in_progress(&mut self) -> Result<bool, Error<E>> { + let config = Config { + bits: self.iface.read_register(Register::CONFIG)? + }; + Ok(!config.is_high(BitFlags::OS)) + } + + fn trigger_measurement(&mut self) -> Result<(), Error<E>> { + let config = self.config.with_high(BitFlags::OS); + self.iface.write_register(Register::CONFIG, config.bits) + } +} + +impl<DI, IC, E, CH> hal::adc::OneShot<Ads1x1x<DI, IC, mode::OneShot>, i16, CH> for Ads1x1x<DI, IC, mode::OneShot> +where + DI: interface::ReadData<Error = E> + interface::WriteData<Error = E>, + IC: ic::Resolution, + CH: hal::adc::Channel<Ads1x1x<DI, IC, mode::OneShot>> +{ + type Error = Error<E>; + + fn read(&mut self, _channel: &mut CH) -> nb::Result<i16, Self::Error> { + //TODO for devices with MUX select channel, if it is the wrong one, return AlreadyInProgress or WrongChannel error + if self.is_measurement_in_progress().map_err(nb::Error::Other)? { + return Err(nb::Error::WouldBlock); + } + if self.a_conversion_was_started { + // result is ready + let value = self.iface.read_register(Register::CONVERSION).map_err(nb::Error::Other)?; + self.a_conversion_was_started = false; + return Ok(convert_measurement::<IC>(value)); + } + self.trigger_measurement().map_err(nb::Error::Other)?; + self.a_conversion_was_started = true; + Err(nb::Error::WouldBlock) + } +} @@ -53,6 +53,7 @@ //TODO #![deny(warnings)] #![no_std] +extern crate nb; extern crate embedded_hal as hal; use core::marker::PhantomData; @@ -133,6 +134,9 @@ struct BitFlags; impl BitFlags { const OP_MODE : u16 = 0b0000_0001_0000_0000; const OS : u16 = 0b1000_0000_0000_0000; + const DR2 : u16 = 0b0000_0000_1000_0000; + const DR1 : u16 = 0b0000_0000_0100_0000; + const DR0 : u16 = 0b0000_0000_0010_0000; } |