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
// Copyright 2021 Kenton Hamaluik
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use embedded_hal::blocking::i2c;

/// The default address for the PCF8591 (all address pins tied to ground)
pub const PCF8591_DEFAULT_ADDRESS: u8 = 0x48;

/// The PCF8591 has four ADC channels, represented here
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum PCFADCNum {
    A0,
    A1,
    A2,
    A3,
}

/// A PCF8591 ADC using the underlying i2c channel
pub struct PCF8591<C: i2c::WriteRead> {
    channel: C,
    addr: u8,
}

impl<C: i2c::WriteRead> PCF8591<C> {
    /// Instantiate the device using the given channel
    pub fn new(channel: C, addr: u8) -> PCF8591<C> {
        PCF8591 { channel, addr }
    }

    /// Read a single ADC value from a single port
    pub fn read(&mut self, adc: PCFADCNum) -> Result<u8, C::Error> {
        // first trigger the measurement
        self.half_read(adc)?;
        // then communicate again to get the actual result
        self.half_read(adc)
    }

    fn half_read(&mut self, adc: PCFADCNum) -> Result<u8, C::Error> {
        let adc: u8 = match adc {
            PCFADCNum::A0 => 0,
            PCFADCNum::A1 => 1,
            PCFADCNum::A2 => 2,
            PCFADCNum::A3 => 3,
        };

        // TODO: take into account writing to the DAC
        let command: [u8; 2] = [adc, 0];
        let mut buffer: [u8; 2] = [0, 0];

        self.channel
            .write_read(self.addr, &command[..], &mut buffer[..])?;
        Ok(buffer[1])
    }

    /// Consume the driver, returning the underlying channel
    pub fn into_inner(self) -> C {
        self.channel
    }
}