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
119
120
121
122
123
124
125
126
127
#![no_std]
use bit_field::BitField;
use embedded_hal::blocking::i2c::{Write, WriteRead};
use num_enum::TryFromPrimitive;

/// Defines errors
#[derive(Debug, Copy, Clone)]
pub enum Error<E> {
    /// Underlying bus error
    BusError(E),
}

impl<E> From<E> for Error<E> {
    fn from(error: E) -> Self {
        Error::BusError(error)
    }
}

/// Pin modes.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Direction {
    /// Represents input mode.
    Input = 1,
    /// Represents output mode.
    Output = 0,
}

/// Pin levels.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Level {
    /// High level
    High = 1,
    /// Low level
    Low = 0,
}

/// Pin names
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, Default)]
#[repr(u8)]
pub enum Pin {
    #[default]
    P00 = 0,
    P01 = 1,
    P02 = 2,
    P03 = 3,
    P04 = 4,
    P05 = 5,
    P06 = 6,
    P07 = 7,
    P10 = 8,
    P11 = 9,
    P12 = 10,
    P13 = 11,
    P14 = 12,
    P15 = 13,
    P16 = 14,
    P17 = 15,
}

/// PCA9539/TCA9539 is a 16-pin I2C I/O Expander with I2C Interface.
#[derive(Clone, Copy, Debug)]
pub struct Pca9539<I2C> {
    i2c: I2C,
    address: u8,
}

///
impl<I2C, E> Pca9539<I2C>
where
    I2C: WriteRead<Error = E> + Write<Error = E>,
{
    const DEFAULT_ADDRESS: u8 = 0x74;

    /// Creates an expander with the default configuration.
    pub fn new_default(i2c: I2C) -> Result<Self, Error<E>> {
        Self::new(i2c, Self::DEFAULT_ADDRESS)
    }

    /// Creates an expander with specific address.
    pub fn new(i2c: I2C, address: u8) -> Result<Self, Error<E>> {
        Ok(Self { i2c, address })
    }

    /// Return the I2C address
    pub fn address(&self) -> u8 {
        self.address
    }

    /// Read an 8 bit register
    pub fn read(&mut self, addr: u8) -> Result<u8, E> {
        let mut data = [0u8];
        self.i2c.write_read(self.address, &[addr], &mut data)?;
        Ok(data[0])
    }

    /// Write an 8 bit register
    pub fn write(&mut self, addr: u8, data: u8) -> Result<(), E> {
        self.i2c.write(self.address, &[addr, data])
    }

    /// Get a single bit in a register
    pub fn bit(&mut self, addr: u8, bit: usize) -> Result<bool, E> {
        let data = self.read(addr)?;
        Ok(data.get_bit(bit))
    }

    /// Set a single bit in a register
    pub fn set_bit(&mut self, addr: u8, bit: usize, value: bool) -> Result<(), E> {
        let mut data = self.read(addr)?;
        data.set_bit(bit, value);
        self.write(addr, data)
    }

    pub fn set_level(&mut self, pin: Pin, level: Level) -> Result<(), E> {
        let pin = pin as u8;
        self.set_bit(0x02 | (pin >> 3), pin as usize & 7, level == Level::High)
    }

    pub fn set_direction(&mut self, pin: Pin, direction: Direction) -> Result<(), E> {
        let pin = pin as u8;
        self.set_bit(
            0x06 | (pin >> 3),
            pin as usize & 7,
            direction == Direction::Input,
        )
    }
}