1use embedded_hal::{
2 delay::DelayNs,
3 digital::OutputPin,
4 i2c::{NoAcknowledgeSource, SevenBitAddress, TenBitAddress},
5};
6
7use super::OpenDrainPin;
8
9#[derive(Debug, PartialEq, Eq, Clone, Copy)]
11pub enum SoftI2CError {
12 Address,
14 WriteData,
16}
17
18#[derive(Debug, Clone, Copy)]
20pub enum SoftI2CAddr {
21 SevenBitAddress(u8),
23 TenBitAddress(u16),
25}
26
27#[derive(Debug)]
29pub struct SoftI2C<'a, C, D, Delay, const CLK_HZ: u32> {
30 scl: &'a mut C,
32 sda: &'a mut D,
34 delay: &'a mut Delay,
36}
37
38impl<'a, C, D, Delay, const CLK_HZ: u32> SoftI2C<'a, C, D, Delay, CLK_HZ>
39where
40 C: OutputPin,
41 D: OpenDrainPin,
42 Delay: DelayNs,
43{
44 pub fn new(scl: &'a mut C, sda: &'a mut D, delay: &'a mut Delay) -> Self {
46 scl.set_high().ok();
47 sda.set(true);
48
49 SoftI2C { scl, sda, delay }
50 }
51
52 #[inline]
54 fn i2c_delay(&mut self) {
55 self.delay.delay_ns(500_000_000 / CLK_HZ);
56 }
57
58 fn scl_hi(&mut self) {
60 self.scl.set_high().ok();
61 self.i2c_delay();
62 }
63
64 fn scl_lo(&mut self) {
66 self.scl.set_low().ok();
67 self.i2c_delay();
68 }
69
70 fn sda_hi(&mut self) {
72 self.sda.set(true);
73 self.i2c_delay();
74 }
75
76 fn sda_lo(&mut self) {
78 self.sda.set(false);
79 self.i2c_delay();
80 }
81
82 #[inline]
84 fn sda_free(&mut self) {
85 self.sda.set(true);
86 }
87 fn start(&mut self) {
89 self.sda.set(true);
90 self.scl_hi();
91 self.sda_lo();
92 self.scl_lo();
93 }
94
95 fn stop(&mut self) {
97 self.sda_lo();
98 self.scl_hi();
99 self.sda.set(true);
100 }
101
102 fn clock_pulse(&mut self) {
104 self.scl_hi();
105 self.scl_lo();
106 }
107
108 fn write_byte(&mut self, mut data_byte: u8) {
110 for _ in 0..8 {
111 self.sda.set(data_byte & 0x80 != 0);
112 data_byte <<= 1;
113 self.clock_pulse();
114 }
115 }
116
117 fn read_bit(&mut self) -> bool {
119 self.scl_hi();
120 let sda_bit = self.sda.get();
121 self.scl_lo();
122
123 sda_bit
124 }
125
126 fn read_byte(&mut self) -> u8 {
128 let mut out_byte = 0;
129
130 self.sda_free();
131 for _ in 0..8 {
132 out_byte <<= 1;
133 out_byte |= (self.read_bit() as u8) & 1;
134 }
135
136 out_byte
137 }
138
139 fn read_ack(&mut self, err: SoftI2CError) -> Result<(), SoftI2CError> {
141 self.sda_free();
142 if self.read_bit() {
143 self.stop();
144 Err(err)
145 } else {
146 Ok(())
147 }
148 }
149
150 fn mak(&mut self) {
152 self.sda_lo();
153 self.clock_pulse();
154 }
155
156 fn nmak(&mut self) {
158 self.sda_hi();
159 self.clock_pulse();
160 }
161
162 fn address(&mut self, address: SoftI2CAddr, is_read: bool) -> Result<(), SoftI2CError> {
164 let r_w_bit = if is_read { 1 } else { 0 };
165
166 match address {
167 SoftI2CAddr::SevenBitAddress(addr) => {
168 self.write_byte((addr << 1) | r_w_bit);
169 self.read_ack(SoftI2CError::Address)?
170 }
171 SoftI2CAddr::TenBitAddress(addr) => {
172 let h_addr = ((((addr >> 7) as u8 & 0xFE) | r_w_bit) & 0x07) | 0xF0;
173 let l_addr = (addr & 0xFF) as u8;
174 for byte in [h_addr, l_addr] {
175 self.write_byte(byte);
176 self.read_ack(SoftI2CError::Address)?
177 }
178 }
179 }
180 Ok(())
181 }
182
183 pub fn soft_i2c_write_read(
196 &mut self,
197 address: SoftI2CAddr,
198 write: &[u8],
199 read: &mut [u8],
200 ) -> Result<(), SoftI2CError> {
201 self.start();
202 self.address(address, false)?;
203
204 for i in 0..write.len() {
205 self.write_byte(write[i]);
206 self.read_ack(SoftI2CError::WriteData)?;
207 }
208
209 self.soft_i2c_read(address, read)
210 }
211
212 pub fn soft_i2c_write(
223 &mut self,
224 address: SoftI2CAddr,
225 write: &[u8],
226 ) -> Result<(), SoftI2CError> {
227 self.start();
228 self.address(address, false)?;
229
230 for i in 0..write.len() {
231 self.write_byte(write[i]);
232 self.read_ack(SoftI2CError::WriteData)?;
233 }
234 self.stop();
235
236 Ok(())
237 }
238
239 pub fn soft_i2c_read(
252 &mut self,
253 address: SoftI2CAddr,
254 read: &mut [u8],
255 ) -> Result<(), SoftI2CError> {
256 self.start();
257 self.address(address, true)?;
258
259 for i in 0..read.len() {
260 read[i] = self.read_byte();
261 if i < read.len() - 1 {
262 self.mak();
263 } else {
264 self.nmak();
265 }
266 }
267 self.stop();
268
269 Ok(())
270 }
271}
272
273impl embedded_hal::i2c::Error for SoftI2CError {
274 fn kind(&self) -> embedded_hal::i2c::ErrorKind {
275 match *self {
276 SoftI2CError::Address => {
277 embedded_hal::i2c::ErrorKind::NoAcknowledge(NoAcknowledgeSource::Address)
278 }
279 SoftI2CError::WriteData => {
280 embedded_hal::i2c::ErrorKind::NoAcknowledge(NoAcknowledgeSource::Data)
281 }
282 }
283 }
284}
285
286impl<'a, C: OutputPin, D: OpenDrainPin, Delay: DelayNs, const CLK_HZ: u32>
287 embedded_hal::i2c::ErrorType for SoftI2C<'a, C, D, Delay, CLK_HZ>
288{
289 type Error = SoftI2CError;
290}
291
292impl<'a, C: OutputPin, D: OpenDrainPin, Delay: DelayNs, const CLK_HZ: u32>
293 embedded_hal::i2c::I2c<SevenBitAddress> for SoftI2C<'a, C, D, Delay, CLK_HZ>
294{
295 fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> {
296 self.soft_i2c_read(SoftI2CAddr::SevenBitAddress(address), read)
297 }
298
299 fn write(&mut self, address: u8, write: &[u8]) -> Result<(), Self::Error> {
300 self.soft_i2c_write(SoftI2CAddr::SevenBitAddress(address), write)
301 }
302
303 fn write_read(
304 &mut self,
305 address: u8,
306 write: &[u8],
307 read: &mut [u8],
308 ) -> Result<(), Self::Error> {
309 self.soft_i2c_write_read(SoftI2CAddr::SevenBitAddress(address), write, read)
310 }
311
312 fn transaction(
313 &mut self,
314 address: u8,
315 operations: &mut [embedded_hal::i2c::Operation<'_>],
316 ) -> Result<(), Self::Error> {
317 for op in operations {
318 match op {
319 embedded_hal::i2c::Operation::Write(data) => {
320 self.soft_i2c_write(SoftI2CAddr::SevenBitAddress(address), data)?;
321 }
322 embedded_hal::i2c::Operation::Read(data) => {
323 self.soft_i2c_read(SoftI2CAddr::SevenBitAddress(address), data)?;
324 }
325 }
326 }
327 Ok(())
328 }
329}
330
331impl<'a, C: OutputPin, D: OpenDrainPin, Delay: DelayNs, const CLK_HZ: u32>
332 embedded_hal::i2c::I2c<TenBitAddress> for SoftI2C<'a, C, D, Delay, CLK_HZ>
333{
334 fn read(&mut self, address: u16, read: &mut [u8]) -> Result<(), Self::Error> {
335 self.soft_i2c_read(SoftI2CAddr::TenBitAddress(address), read)
336 }
337
338 fn write(&mut self, address: u16, write: &[u8]) -> Result<(), Self::Error> {
339 self.soft_i2c_write(SoftI2CAddr::TenBitAddress(address), write)
340 }
341
342 fn write_read(
343 &mut self,
344 address: u16,
345 write: &[u8],
346 read: &mut [u8],
347 ) -> Result<(), Self::Error> {
348 self.soft_i2c_write_read(SoftI2CAddr::TenBitAddress(address), write, read)
349 }
350
351 fn transaction(
352 &mut self,
353 address: u16,
354 operations: &mut [embedded_hal::i2c::Operation<'_>],
355 ) -> Result<(), Self::Error> {
356 for op in operations {
357 match op {
358 embedded_hal::i2c::Operation::Write(data) => {
359 self.soft_i2c_write(SoftI2CAddr::TenBitAddress(address), data)?;
360 }
361 embedded_hal::i2c::Operation::Read(data) => {
362 self.soft_i2c_read(SoftI2CAddr::TenBitAddress(address), data)?;
363 }
364 }
365 }
366 Ok(())
367 }
368}