Skip to main content

pcf8591_hal/
lib.rs

1// Copyright 2021 Kenton Hamaluik
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use embedded_hal::blocking::i2c;
16
17/// The default address for the PCF8591 (all address pins tied to ground)
18pub const PCF8591_DEFAULT_ADDRESS: u8 = 0x48;
19
20/// The PCF8591 has four ADC channels, represented here
21#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
22pub enum PCFADCNum {
23    A0,
24    A1,
25    A2,
26    A3,
27}
28
29/// A PCF8591 ADC using the underlying i2c channel
30pub struct PCF8591<C: i2c::WriteRead> {
31    channel: C,
32    addr: u8,
33}
34
35impl<C: i2c::WriteRead> PCF8591<C> {
36    /// Instantiate the device using the given channel
37    pub fn new(channel: C, addr: u8) -> PCF8591<C> {
38        PCF8591 { channel, addr }
39    }
40
41    /// Read a single ADC value from a single port
42    pub fn read(&mut self, adc: PCFADCNum) -> Result<u8, C::Error> {
43        // first trigger the measurement
44        self.half_read(adc)?;
45        // then communicate again to get the actual result
46        self.half_read(adc)
47    }
48
49    fn half_read(&mut self, adc: PCFADCNum) -> Result<u8, C::Error> {
50        let adc: u8 = match adc {
51            PCFADCNum::A0 => 0,
52            PCFADCNum::A1 => 1,
53            PCFADCNum::A2 => 2,
54            PCFADCNum::A3 => 3,
55        };
56
57        // TODO: take into account writing to the DAC
58        let command: [u8; 2] = [adc, 0];
59        let mut buffer: [u8; 2] = [0, 0];
60
61        self.channel
62            .write_read(self.addr, &command[..], &mut buffer[..])?;
63        Ok(buffer[1])
64    }
65
66    /// Consume the driver, returning the underlying channel
67    pub fn into_inner(self) -> C {
68        self.channel
69    }
70}