embedded_ads111x/
lib.rs

1#![no_std]
2
3#[cfg(not(feature = "async"))]
4use embedded_hal::i2c::I2c;
5#[cfg(feature = "async")]
6use embedded_hal_async::i2c::I2c;
7
8static CONVERSION_REGISTER : u8 = 0b00;
9static CONFIG_REGISTER     : u8 = 0b01;
10static LO_THRESH_REGISTER  : u8 = 0b10;
11static HI_THRESH_REGISTER  : u8 = 0b11;
12
13#[derive(Debug)]
14pub enum ADSError{
15    WrongAddress,
16    ModeSetToSingle,
17}
18
19#[derive(Debug)]
20enum OSW{
21    StartConversion,
22    Idle,
23}
24
25#[derive(Debug,PartialEq)]
26enum OSR{
27    PerformingConversion,
28    DeviceIdle,
29}
30
31impl OSW {
32    fn bits(&self) -> u16{
33        match self {
34            OSW::StartConversion => 1<<15,
35            OSW::Idle => 0,
36        }
37    }
38}
39
40impl Default for OSW{
41    fn default() -> Self {
42        OSW::Idle
43    }
44}
45
46impl OSR {
47    fn from_bits(bits: u16) -> Self{
48        match bits >> 15 & 0b01 {
49            0 => OSR::PerformingConversion,
50            _ => OSR::DeviceIdle,
51        }
52    }
53}
54
55impl Default for OSR{
56    fn default() -> Self {
57        OSR::DeviceIdle
58    }
59}
60
61#[derive(Debug)]
62pub enum InputMultiplexer{
63    AIN0AIN1,
64    AIN0AIN3,
65    AIN1AIN3,
66    AIN2AIN3,
67    AIN0GND,
68    AIN1GND,
69    AIN2GND,
70    AIN3GND,
71}
72
73impl InputMultiplexer {
74    fn bits(&self) -> u16{
75        match self {
76            InputMultiplexer::AIN0AIN1 => 0b000 << 12,
77            InputMultiplexer::AIN0AIN3 => 0b001 << 12,
78            InputMultiplexer::AIN1AIN3 => 0b010 << 12,
79            InputMultiplexer::AIN2AIN3 => 0b011 << 12,
80            InputMultiplexer::AIN0GND  => 0b100 << 12,
81            InputMultiplexer::AIN1GND  => 0b101 << 12,
82            InputMultiplexer::AIN2GND  => 0b110 << 12,
83            InputMultiplexer::AIN3GND  => 0b111 << 12,
84        }
85    }
86
87    fn from_bits(bits: u16) -> Self{
88        match bits >> 12 & 0b111{
89            0b000 => InputMultiplexer::AIN0AIN1,
90            0b001 => InputMultiplexer::AIN0AIN3,
91            0b010 => InputMultiplexer::AIN1AIN3,
92            0b011 => InputMultiplexer::AIN2AIN3,
93            0b100 => InputMultiplexer::AIN0GND,
94            0b101 => InputMultiplexer::AIN1GND,
95            0b110 => InputMultiplexer::AIN2GND,
96            _     => InputMultiplexer::AIN3GND,
97        }
98    }
99}
100
101impl Default for InputMultiplexer{
102    fn default() -> Self {
103        InputMultiplexer::AIN0AIN1
104    }
105}
106
107#[derive(Debug)]
108pub enum ProgramableGainAmplifier{
109    V6_144,
110    V4_096,
111    V2_048,
112    V1_024,
113    V0_512,
114    V0_256,
115}
116
117impl ProgramableGainAmplifier{
118    fn bits(&self) -> u16{
119        match self {
120            ProgramableGainAmplifier::V6_144 => 0b000 << 9,
121            ProgramableGainAmplifier::V4_096 => 0b001 << 9,
122            ProgramableGainAmplifier::V2_048 => 0b010 << 9,
123            ProgramableGainAmplifier::V1_024 => 0b011 << 9,
124            ProgramableGainAmplifier::V0_512 => 0b100 << 9,
125            ProgramableGainAmplifier::V0_256 => 0b101 << 9,
126        }
127    }
128
129    fn from_bits(bits: u16) -> Self{
130        match bits >> 9 & 0b111 {
131            0b000 => ProgramableGainAmplifier::V6_144,
132            0b001 => ProgramableGainAmplifier::V4_096,
133            0b010 => ProgramableGainAmplifier::V2_048,
134            0b011 => ProgramableGainAmplifier::V1_024,
135            0b100 => ProgramableGainAmplifier::V0_512,
136            _     => ProgramableGainAmplifier::V0_256,
137        }
138    }
139}
140
141impl Default for ProgramableGainAmplifier{
142    fn default() -> Self {
143        ProgramableGainAmplifier::V2_048
144    }
145}
146
147#[derive(Debug, PartialEq)]
148pub enum Mode{
149    Continuous,
150    Signle,
151}
152
153impl Mode {
154    fn bits(&self) -> u16{
155        match self {
156            Mode::Continuous => 0,
157            Mode::Signle     => 1<<8,
158        }
159    }
160
161    fn from_bits(bits: u16) -> Self{
162        match bits >> 8 & 0b01 {
163            1 => Mode::Signle,
164            _ => Mode::Continuous,
165        }
166    }
167}
168
169impl Default for Mode {
170    fn default() -> Self {
171        Mode::Signle
172    }
173}
174
175#[derive(Debug)]
176pub enum DataRate{
177    SPS8,
178    SPS16,
179    SPS32,
180    SPS64,
181    SPS128,
182    SPS250,
183    SPS475,
184    SPS860,
185}
186
187impl DataRate{
188    fn bits(&self) -> u16{
189        match self {
190            DataRate::SPS8   => 0b000,
191            DataRate::SPS16  => 0b001 << 5,
192            DataRate::SPS32  => 0b010 << 5,
193            DataRate::SPS64  => 0b011 << 5,
194            DataRate::SPS128 => 0b100 << 5,
195            DataRate::SPS250 => 0b101 << 5,
196            DataRate::SPS475 => 0b110 << 5,
197            DataRate::SPS860 => 0b111 << 5,
198        }
199    }
200
201    fn from_bits(bits: u16) -> Self{
202        match bits >> 5 & 0b111 {
203            0b000 => DataRate::SPS8,
204            0b001 => DataRate::SPS16,
205            0b010 => DataRate::SPS32,
206            0b011 => DataRate::SPS64,
207            0b100 => DataRate::SPS128,
208            0b101 => DataRate::SPS250,
209            0b110 => DataRate::SPS475,
210            _     => DataRate::SPS860,
211        }
212    }
213}
214
215impl Default for DataRate{
216    fn default() -> Self {
217        DataRate::SPS128
218    }
219}
220
221#[derive(Debug)]
222pub enum ComparatorMode{
223    Traditional,
224    Window,
225}
226
227impl ComparatorMode{
228    fn bits(&self) -> u16{
229        match self {
230            ComparatorMode::Traditional => 0,
231            ComparatorMode::Window      => 1<<4,
232        }
233    }
234
235    fn from_bits(bits: u16) -> Self{
236        match bits >> 4 & 0b01 {
237            1 => ComparatorMode::Window,
238            _ => ComparatorMode::Traditional,
239        }
240    }
241}
242
243impl Default for ComparatorMode{
244    fn default() -> Self {
245        ComparatorMode::Traditional
246    }
247}
248
249#[derive(Debug)]
250pub enum ComparatorPolarity{
251    ActiveLow,
252    ActiveHigh,
253}
254
255impl ComparatorPolarity{
256    fn bits(&self) -> u16{
257        match self {
258            ComparatorPolarity::ActiveLow  => 0,
259            ComparatorPolarity::ActiveHigh => 1<<3,
260        }
261    }
262
263    fn from_bits(bits: u16) -> Self{
264        match bits >> 3 & 0b01 {
265            1 => ComparatorPolarity::ActiveHigh,
266            _ => ComparatorPolarity::ActiveLow,
267        }
268    }
269}
270
271impl Default for ComparatorPolarity{
272    fn default() -> Self {
273        ComparatorPolarity::ActiveLow
274    }
275}
276
277#[derive(Debug)]
278pub enum LatchingComparator{
279    NonLatching,
280    Latching,
281}
282
283impl LatchingComparator{
284    fn bits(&self) -> u16{
285        match self {
286            LatchingComparator::NonLatching  => 0,
287            LatchingComparator::Latching => 1<<2,
288        }
289    }
290
291    fn from_bits(bits: u16) -> Self{
292        match bits >> 2 & 0b01 {
293            1 => LatchingComparator::Latching,
294            _ => LatchingComparator::NonLatching,
295        }
296    }
297}
298
299impl Default for LatchingComparator{
300    fn default() -> Self {
301        LatchingComparator::NonLatching
302    }
303}
304
305#[derive(Debug)]
306pub enum ComparatorQueue{
307    AsserAfterOne,
308    AsserAfterTwo,
309    AsserAfterFour,
310    Disable,
311}
312
313impl ComparatorQueue{
314    fn bits(&self) -> u16{
315        match self {
316            ComparatorQueue::AsserAfterOne  => 0b00,
317            ComparatorQueue::AsserAfterTwo  => 0b01,
318            ComparatorQueue::AsserAfterFour => 0b10,
319            ComparatorQueue::Disable        => 0b11,
320        }
321    }
322
323    fn from_bits(bits: u16) -> Self{
324        match bits & 0b11 {
325            0b00 => ComparatorQueue::AsserAfterOne,
326            0b01 => ComparatorQueue::AsserAfterTwo,
327            0b10 => ComparatorQueue::AsserAfterFour,
328            _    => ComparatorQueue::Disable,
329        }
330    }
331}
332
333impl Default for ComparatorQueue{
334    fn default() -> Self {
335        ComparatorQueue::Disable
336    }
337}
338
339#[derive(Default, Debug)]
340pub struct ADS111xConfig{
341    osw: OSW,
342    osr: OSR,
343    mux: InputMultiplexer,
344    pga: ProgramableGainAmplifier,
345    mode: Mode,
346    dr: DataRate,
347    comp_mode: ComparatorMode,
348    comp_pol: ComparatorPolarity,
349    comp_lat: LatchingComparator,
350    comp_que: ComparatorQueue,
351}
352
353impl ADS111xConfig{
354    fn bits(&self) -> u16{
355        self.osw.bits() |
356        self.mux.bits() |
357        self.pga.bits() |
358        self.mode.bits() |
359        self.dr.bits() |
360        self.comp_mode.bits() |
361        self.comp_pol.bits() |
362        self.comp_lat.bits() |
363        self.comp_que.bits()
364    }
365
366    fn from_bits(bits: u16) -> Self{
367        ADS111xConfig {
368            osr: OSR::from_bits(bits),
369            osw: OSW::default(),
370            mux: InputMultiplexer::from_bits(bits),
371            pga: ProgramableGainAmplifier::from_bits(bits),
372            mode: Mode::from_bits(bits),
373            dr: DataRate::from_bits(bits),
374            comp_mode: ComparatorMode::from_bits(bits),
375            comp_pol: ComparatorPolarity::from_bits(bits),
376            comp_lat: LatchingComparator::from_bits(bits),
377            comp_que: ComparatorQueue::from_bits(bits)}
378    }
379
380    pub fn mux(mut self, mux: InputMultiplexer) -> Self{
381        self.mux = mux;
382        self
383    }
384
385    pub fn pga(mut self, pga: ProgramableGainAmplifier) -> Self{
386        self.pga = pga;
387        self
388    }
389
390    pub fn mode(mut self, mode: Mode) -> Self{
391        self.mode = mode;
392        self
393    }
394
395    pub fn dr(mut self, dr: DataRate) -> Self{
396        self.dr = dr;
397        self
398    }
399
400    pub fn comp_mode(mut self, cm: ComparatorMode) -> Self{
401        self.comp_mode = cm;
402        self
403    }
404
405    pub fn comp_pol(mut self, cp: ComparatorPolarity) -> Self{
406        self.comp_pol = cp;
407        self
408    }
409
410    pub fn comp_lat(mut self, cl: LatchingComparator) -> Self{
411        self.comp_lat = cl;
412        self
413    }
414
415    pub fn comp_que(mut self, cq: ComparatorQueue) -> Self{
416        self.comp_que = cq;
417        self
418    }
419}
420
421#[maybe_async_cfg::maybe(
422    sync(cfg(not(feature = "async")),),
423    async(feature="async"),
424    keep_self
425)]
426pub struct ADS111x<I2C> {
427    i2c: I2C,
428    address: u8,
429    config: ADS111xConfig,
430}
431
432#[maybe_async_cfg::maybe(
433    sync(cfg(not(feature = "async")),),
434    async(feature="async"),
435    keep_self
436)]
437impl<I2C, E> ADS111x<I2C>
438where
439    I2C: I2c<Error = E>,
440{
441    ///Create a new ADS111x instance with the specified configuration
442    ///Note: This only creates the instance, it doesn't write the configuration to the chip
443    pub fn new(i2c: I2C, address: u8, config: ADS111xConfig) -> Result<Self, ADSError>{
444        match address {
445            0b1001000 => {},
446            0b1001001 => {},
447            0b1001010 => {},
448            0b1001011 => {},
449            _ => return Err(ADSError::WrongAddress),
450        }
451        Ok(ADS111x{ i2c, address, config} )
452    }
453
454    ///Destroys driver instance and returns I²C bus instance.
455    pub fn destroy(self) -> I2C {
456        self.i2c
457    }
458
459    ///Writes self configuration to to the chip's registers
460    ///Config can be used to update configuration
461    ///This step is necessary to apply the configuration
462    pub async fn write_config(&mut self, config: Option<ADS111xConfig>) -> Result<(), E>{
463        if let Some(conf) = config{
464            self.config = conf;
465        }
466        self.config.osw = OSW::Idle;
467        let conf = self.config.bits().to_be_bytes();
468        self.i2c.write(self.address, &[CONFIG_REGISTER, conf[0], conf[1]]).await
469    }
470
471    pub async fn read_config(&mut self) -> Result<ADS111xConfig, E>{
472        self.config.osw = OSW::Idle;
473        let mut conf = [0, 0];
474
475        self.i2c.write_read(self.address, &[CONFIG_REGISTER], &mut conf).await.and(Ok(ADS111xConfig::from_bits(u16::from_be_bytes(conf))))
476    }
477
478    /// Perform single read when mode set to single
479    /// ADC is in low power state until requested and will go back after conversion
480    /// Will block until converstion is ready
481    /// Mux can be used to reconfigure what ADC input to read
482    pub async fn read_single_voltage(&mut self, mux: Option<InputMultiplexer>) -> Result<f32, E>{
483        if let Some(m) = mux{
484            self.config.mux = m;
485        }
486        self.config.osw = OSW::StartConversion;
487        let config = self.config.bits().to_be_bytes();
488        let mut conf = [0, 0];
489
490        self.i2c.write_read(self.address, &[CONFIG_REGISTER, config[0], config[1]], &mut conf).await?;
491
492        while OSR::from_bits(u16::from_be_bytes(conf)) == OSR::PerformingConversion{
493            self.i2c.write_read(self.address, &[CONFIG_REGISTER], &mut conf).await?;
494        }
495
496        self.read_voltage().await
497    }
498
499    pub async fn check_cnversion_ready(&mut self) -> Result<bool, E>{
500        Ok(self.read_config().await?.osr == OSR::DeviceIdle)
501    }
502
503    /// Reads conversion
504    /// does not block to wait for conversion
505    /// will return 0 when conversion was still ongoing
506    /// You can use check_coversion_ready if needed
507    /// only works when Mode is Continuous
508    pub async fn read_voltage(&mut self) -> Result<f32, E> {
509        let mut voltage = [0, 0];
510        self.i2c.write_read(self.address, &[CONVERSION_REGISTER], &mut voltage).await?;
511        let val = i16::from_be_bytes(voltage);
512        let pga = match self.config.pga{
513            ProgramableGainAmplifier::V0_256 => 0.256f32,
514            ProgramableGainAmplifier::V0_512 => 0.512f32,
515            ProgramableGainAmplifier::V1_024 => 1.024f32,
516            ProgramableGainAmplifier::V2_048 => 2.048f32,
517            ProgramableGainAmplifier::V4_096 => 4.096f32,
518            ProgramableGainAmplifier::V6_144 => 6.144f32,
519        };
520
521        Ok(f32::from(val) * pga / 32768f32)
522    }
523
524    pub async fn set_low_treshold(&mut self, low_tresh: i16) -> Result<(), E>{
525        let lt = low_tresh.to_be_bytes();
526        self.i2c.write(self.address, &[LO_THRESH_REGISTER, lt[0], lt[1]]).await
527    }
528
529    pub async fn set_high_treshold(&mut self, high_tresh: i16) -> Result<(), E>{
530        let ht = high_tresh.to_be_bytes();
531        self.i2c.write(self.address, &[HI_THRESH_REGISTER, ht[0], ht[1]]).await
532    }
533}