tca9554/
address.rs

1use embedded_hal_async::i2c::SevenBitAddress;
2
3/// I²C address for a TCA9554(A) I/O expander.
4///
5/// For the standard variant (model not ending in 'A'), use [`Self::standard`].
6/// Otherwise, use [`Self::alternate`].
7///
8/// Datasheet reference: section 8.6.1, figure 19.
9///
10#[derive(Debug, Clone, Copy)]
11#[cfg_attr(feature = "defmt", derive(defmt::Format))]
12pub struct Address(SevenBitAddress);
13
14impl Address {
15    /// Address for the standard variant of the chip (model TCA9554).
16    pub fn standard() -> Self {
17        Self(0x40 >> 1)
18    }
19
20    /// Address for the alternate variant of the chip (model TCA9554A).
21    pub fn alternate() -> Self {
22        Self(0x70 >> 1)
23    }
24
25    /// Sets the user selectable, rightmost bits in the address: `(a3, a2, a1)`.
26    pub fn with_selectable_bits(self, ax: (bool, bool, bool)) -> Self {
27        let (a2, a1, a0) = ax;
28        let bits = ((a2 as u8) << 2) | ((a1 as u8) << 1) | a0 as u8;
29        Self(self.0 | bits)
30    }
31}
32
33impl Into<SevenBitAddress> for Address {
34    fn into(self) -> SevenBitAddress {
35        self.0
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::{Address, SevenBitAddress};
42
43    #[test]
44    fn test_standard() {
45        let addr: SevenBitAddress = Address::standard().into();
46        assert_eq!(addr, 0x20);
47    }
48
49    #[test]
50    fn test_alternate() {
51        let addr: SevenBitAddress = Address::alternate().into();
52        assert_eq!(addr, 0x38);
53    }
54
55    #[test]
56    fn test_with_selectable_bits() {
57        let addr: SevenBitAddress = Address::standard()
58            .with_selectable_bits((false, true, false))
59            .into();
60        assert_eq!(addr, 0x22);
61    }
62}