1#![cfg_attr(not(test), no_std)]
6#![deny(missing_docs)]
7
8use embedded_hal::blocking::i2c::{Write, WriteRead};
27
28mod command {
29 pub const READ_PORT_0: u8 = 0x00;
30 pub const READ_PORT_1: u8 = 0x01;
31 pub const WRITE_PORT_0: u8 = 0x02;
32 pub const WRITE_PORT_1: u8 = 0x03;
33 pub const POLARITY_INVERT_PORT_0: u8 = 0x04;
34 pub const POLARITY_INVERT_PORT_1: u8 = 0x05;
35 pub const CONFIGURATION_PORT_0: u8 = 0x06;
36 pub const CONFIGURATION_PORT_1: u8 = 0x07;
37}
38
39use command::*;
40
41#[derive(Copy, Clone, Debug)]
43pub enum DeviceAddr {
44 Default,
46 Alternative(bool, bool, bool),
49}
50
51impl Default for DeviceAddr {
52 fn default() -> Self {
53 Self::Default
54 }
55}
56
57impl DeviceAddr {
58 const DEFAULT: u8 = 0x20;
59
60 pub fn addr(self) -> u8 {
62 match self {
63 DeviceAddr::Default => Self::DEFAULT,
64 DeviceAddr::Alternative(a0, a1, a2) => {
65 Self::DEFAULT | a0 as u8 | ((a1 as u8) << 1) | ((a2 as u8) << 2)
66 }
67 }
68 }
69}
70
71pub type Tca9535<I2C> = Tca9555<I2C>;
75
76pub struct Tca9555<I2C> {
78 address: DeviceAddr,
79 i2c: I2C,
80}
81
82impl<I2C> Tca9555<I2C> {
83 pub fn new(i2c: I2C, address: DeviceAddr) -> Self {
85 Self { i2c, address }
86 }
87}
88
89impl<I2C, E> Tca9555<I2C>
90where
91 I2C: WriteRead<Error = E>,
92{
93 pub fn read_port_0(&mut self) -> Result<u8, E> {
97 let mut value = [0];
98 self.i2c
99 .write_read(self.address.addr(), &[READ_PORT_0], &mut value)
100 .and(Ok(value[0]))
101 }
102
103 pub fn read_port_1(&mut self) -> Result<u8, E> {
107 let mut value = [0];
108 self.i2c
109 .write_read(self.address.addr(), &[READ_PORT_1], &mut value)
110 .and(Ok(value[0]))
111 }
112
113 pub fn read_all(&mut self) -> Result<u16, E> {
117 let port0 = self.read_port_0()?;
118 let port1 = self.read_port_1()?;
119 Ok(u16::from_be_bytes([port1, port0]))
120 }
121}
122
123impl<I2C, E> Tca9555<I2C>
124where
125 I2C: Write<Error = E>,
126{
127 pub fn write_port_0(&mut self, value: u8) -> Result<(), E> {
130 self.i2c.write(self.address.addr(), &[WRITE_PORT_0, value])
131 }
132
133 pub fn set_port_0_direction(&mut self, dir_mask: u8) -> Result<(), E> {
136 self.i2c
137 .write(self.address.addr(), &[CONFIGURATION_PORT_0, dir_mask])
138 }
139
140 pub fn set_port_0_polarity_invert(
143 &mut self,
144 polarity_mask: u8,
145 ) -> Result<(), E> {
146 self.i2c.write(
147 self.address.addr(),
148 &[POLARITY_INVERT_PORT_0, polarity_mask],
149 )
150 }
151
152 pub fn write_port_1(&mut self, value: u8) -> Result<(), E> {
155 self.i2c.write(self.address.addr(), &[WRITE_PORT_1, value])
156 }
157
158 pub fn set_port_1_direction(&mut self, dir_mask: u8) -> Result<(), E> {
161 self.i2c
162 .write(self.address.addr(), &[CONFIGURATION_PORT_1, dir_mask])
163 }
164
165 pub fn set_port_1_polarity_invert(
168 &mut self,
169 polarity_mask: u8,
170 ) -> Result<(), E> {
171 self.i2c.write(
172 self.address.addr(),
173 &[POLARITY_INVERT_PORT_1, polarity_mask],
174 )
175 }
176
177 pub fn write_all(&mut self, value: u16) -> Result<(), E> {
179 let [port1, port0] = value.to_be_bytes();
180 self.write_port_0(port0)?;
181 self.write_port_1(port1)
182 }
183}
184
185#[cfg(test)]
186mod test {
187 use super::*;
188
189 #[test]
190 fn address_set() {
191 assert_eq!(DeviceAddr::DEFAULT, 0x20);
192 assert_eq!(DeviceAddr::Alternative(false, false, false).addr(), 0x20);
193 assert_eq!(DeviceAddr::Alternative(true, false, false).addr(), 0x21);
194 assert_eq!(DeviceAddr::Alternative(false, true, true).addr(), 0x26);
195 }
196}