1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
extern crate i2cdev;
extern crate byteorder;

pub use i2cdev::linux::{LinuxI2CDevice,LinuxI2CError};
pub use i2cdev::core::I2CDevice;
use byteorder::{BigEndian,ByteOrder};

pub const DEFAULT_ADS1115_SLAVE_ADDRESS: u16 = 0x48;

const ADS111X_CONVERSION_REGISTER: u8 = 0b00;
const ADS111X_CONFIG_REGISTER: u8 = 0b01;

#[derive(Debug,Copy,Clone)]
/// Only functions on ADS1115
pub enum ADS1115MultiplexerConfig {
	AIN0_AIN1 = 0b000,
	AIN0_AIN3 = 0b001,
	AIN1_AIN3 = 0b010,
	AIN2_AIN3 = 0b011,
	AIN0_GND = 0b100,
	AIN1_GND = 0b101,
	AIN2_GND = 0b110,
	AIN3_GND = 0b111,
}

#[derive(Debug,Copy,Clone)]
/// Only functions on ADS1114 and ADS1115
pub enum ADS11145GainAmplifier {
	FS_6_144V = 0b000,
	FS_4_096V = 0b001,
	FS_2_048V = 0b010,
	FS_1_024V = 0b011,
	FS_0_512V = 0b100,
	FS_0_256V = 0b101,
}

#[derive(Debug,Copy,Clone)]
pub enum ADS111XOperatingMode {
	ContinuousConversion = 0b0,
	SingleShot = 0b1
}

#[derive(Debug,Copy,Clone)]
pub enum ADS111XDataRate {
	DR_8SPS = 0b000,
	DR_16SPS = 0b001,
	DR_32SPS = 0b010,
	DR_64SPS = 0b011,
	DR_128SPS = 0b100,
	DR_250SPS = 0b101,
	DR_475SPS = 0b110,
	DR_860SPS = 0b111,
}

#[derive(Debug,Copy,Clone)]
pub struct ADS111XConfig {
	pub multiplexer_config: ADS1115MultiplexerConfig,
	pub gain_amplifier: ADS11145GainAmplifier,
	pub operating_mode: ADS111XOperatingMode,
	pub data_rate: ADS111XDataRate
}

pub struct ADS111X {
	device: LinuxI2CDevice,
	config: u16,
	continuous: bool,
	gain: f32
}

impl ADS111X {
	pub fn new(device: LinuxI2CDevice, config: ADS111XConfig) -> Result<ADS111X, LinuxI2CError> {
		let mut config_reg: u16 = 0b0;
		config_reg |= (config.multiplexer_config as u16) << 12;
		config_reg |= (config.gain_amplifier as u16) << 9;
		config_reg |= (config.operating_mode as u16) << 8;
		config_reg |= (config.data_rate as u16) << 5;
		

		let continuous = match config.operating_mode {
			ADS111XOperatingMode::ContinuousConversion => true,
			ADS111XOperatingMode::SingleShot => false
		};

		let gain = match config.gain_amplifier {
			ADS11145GainAmplifier::FS_6_144V => 6.144,
			ADS11145GainAmplifier::FS_4_096V => 4.096,
			ADS11145GainAmplifier::FS_2_048V => 2.048,
			ADS11145GainAmplifier::FS_1_024V => 1.024,
			ADS11145GainAmplifier::FS_0_512V => 0.512,
			ADS11145GainAmplifier::FS_0_256V => 0.256
		} / 32767.0;

		let mut ads111x = ADS111X{ device: device, config: config_reg, continuous: continuous, gain: gain };
		try!(ads111x.input_config());
		Ok(ads111x)
	}

	fn input_config(&mut self) -> Result<(), LinuxI2CError> {
		try!(self.device.smbus_write_word_data(ADS111X_CONFIG_REGISTER, self.config));
		Ok(())
	}

	fn read_conversion_register(&mut self) -> Result<i16, LinuxI2CError> {
		let mut buf = [0_u8;2];
		try!(self.device.write(&[ADS111X_CONVERSION_REGISTER]));
		try!(self.device.read(&mut buf));
		let raw = BigEndian::read_i16(&buf);	
		Ok(raw as i16)
	}

	pub fn read_voltage(&mut self) -> Result<f32, LinuxI2CError> {
		if !self.continuous {
			try!(self.input_config());
		}
		let raw = try!(self.read_conversion_register());
		Ok((raw as f32) * self.gain)
	}
}