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}