adafruit_seesaw/
driver.rs

1use crate::modules::Reg;
2use embedded_hal::{
3    delay::DelayNs,
4    i2c::{ErrorType, I2c, Operation, SevenBitAddress},
5};
6
7const DELAY_TIME: u32 = 125;
8
9#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10#[derive(Debug)]
11pub struct SeesawDriver<I2C, DELAY>(DELAY, I2C);
12
13impl<I2C, DELAY> SeesawDriver<I2C, DELAY>
14where
15    DELAY: DelayNs,
16    I2C: I2c,
17{
18    pub fn new(delay: DELAY, i2c: I2C) -> Self {
19        SeesawDriver(delay, i2c)
20    }
21}
22
23impl<DELAY, I2C> ErrorType for SeesawDriver<I2C, DELAY>
24where
25    DELAY: DelayNs,
26    I2C: I2c,
27{
28    type Error = I2C::Error;
29}
30
31impl<I2C, DELAY> I2c for SeesawDriver<I2C, DELAY>
32where
33    DELAY: DelayNs,
34    I2C: I2c,
35{
36    fn transaction(
37        &mut self,
38        address: u8,
39        operations: &mut [Operation<'_>],
40    ) -> Result<(), Self::Error> {
41        self.1.transaction(address, operations)
42    }
43}
44
45impl<DELAY, I2C> DelayNs for SeesawDriver<I2C, DELAY>
46where
47    DELAY: DelayNs,
48    I2C: I2c,
49{
50    fn delay_ns(&mut self, ns: u32) {
51        self.0.delay_ns(ns)
52    }
53}
54
55/// Blanket trait for anything that implements I2C and a delay
56pub trait Driver: I2c + DelayNs {}
57impl<T> Driver for T where T: I2c + DelayNs {}
58
59macro_rules! impl_integer_write {
60    ($fn:ident $fn_with_delay:ident $nty:tt) => {
61        fn $fn(
62            &mut self,
63            addr: SevenBitAddress,
64            reg: &Reg,
65            value: $nty,
66        ) -> Result<(), Self::Error> {
67            self.register_write(addr, reg, &<$nty>::to_be_bytes(value))
68        }
69
70        fn $fn_with_delay(
71            &mut self,
72            addr: SevenBitAddress,
73            reg: &Reg,
74            value: $nty,
75            delay: u32,
76        ) -> Result<(), Self::Error> {
77            self.register_write_with_delay(addr, reg, &<$nty>::to_be_bytes(value), delay)
78        }
79    };
80}
81
82macro_rules! impl_integer_read {
83    ($fn:ident $fn_with_delay:ident $nty:tt) => {
84        fn $fn(&mut self, addr: SevenBitAddress, reg: &Reg) -> Result<$nty, Self::Error> {
85            self.register_read::<{ ($nty::BITS / 8) as usize }>(addr, reg)
86                .map($nty::from_be_bytes)
87        }
88
89        fn $fn_with_delay(
90            &mut self,
91            addr: SevenBitAddress,
92            reg: &Reg,
93            delay: u32,
94        ) -> Result<$nty, Self::Error> {
95            self.register_read_with_delay::<{ ($nty::BITS / 8) as usize }>(addr, reg, delay)
96                .map($nty::from_be_bytes)
97        }
98    };
99}
100
101pub trait DriverExt {
102    type Error;
103
104    fn register_read_with_delay<const N: usize>(
105        &mut self,
106        addr: SevenBitAddress,
107        reg: &Reg,
108        delay: u32,
109    ) -> Result<[u8; N], Self::Error>;
110
111    fn register_write_with_delay(
112        &mut self,
113        addr: SevenBitAddress,
114        reg: &Reg,
115        bytes: &[u8],
116        delay: u32,
117    ) -> Result<(), Self::Error>;
118
119    impl_integer_read! { read_u8 read_u8_with_delay u8 }
120    impl_integer_read! { read_u16 read_u16_with_delay u16 }
121    impl_integer_read! { read_u32 read_u32_with_delay u32 }
122    impl_integer_read! { read_u64 read_u64_with_delay u64 }
123    impl_integer_read! { read_i8 read_i8_with_delay i8 }
124    impl_integer_read! { read_i16 read_i16_with_delay i16 }
125    impl_integer_read! { read_i32 read_i32_with_delay i32 }
126    impl_integer_read! { read_i64 read_i64_with_delay i64 }
127    impl_integer_write! { write_u8 write_u8_with_delay u8 }
128    impl_integer_write! { write_u16 write_u16_with_delay u16 }
129    impl_integer_write! { write_u32 write_u32_with_delay u32 }
130    impl_integer_write! { write_u64 write_u64_with_delay u64 }
131    impl_integer_write! { write_i8 write_i8_with_delay i8 }
132    impl_integer_write! { write_i16 write_i16_with_delay i16 }
133    impl_integer_write! { write_i32 write_i32_with_delay i32 }
134    impl_integer_write! { write_i64 write_i64_with_delay i64 }
135
136    fn register_read<const N: usize>(
137        &mut self,
138        addr: SevenBitAddress,
139        reg: &Reg,
140    ) -> Result<[u8; N], Self::Error> {
141        self.register_read_with_delay(addr, reg, DELAY_TIME)
142    }
143
144    fn register_write(
145        &mut self,
146        addr: SevenBitAddress,
147        reg: &Reg,
148        bytes: &[u8],
149    ) -> Result<(), Self::Error> {
150        self.register_write_with_delay(addr, reg, bytes, DELAY_TIME)
151    }
152}
153
154impl<T: Driver> DriverExt for T {
155    type Error = T::Error;
156
157    fn register_read_with_delay<const N: usize>(
158        &mut self,
159        addr: SevenBitAddress,
160        reg: &Reg,
161        delay: u32,
162    ) -> Result<[u8; N], Self::Error> {
163        let mut buffer = [0u8; N];
164        self.write(addr, reg)?;
165        self.delay_us(delay);
166        self.read(addr, &mut buffer)?;
167        Ok(buffer)
168    }
169
170    fn register_write_with_delay(
171        &mut self,
172        addr: SevenBitAddress,
173        reg: &Reg,
174        bytes: &[u8],
175        delay: u32,
176    ) -> Result<(), Self::Error> {
177        self.transaction(addr, &mut [Operation::Write(reg), Operation::Write(bytes)])?;
178        self.delay_us(delay);
179        Ok(())
180    }
181}