i2c_pio/
eh1_0.rs

1use either::Either::{Left, Right};
2use embedded_hal::i2c::{ErrorKind, NoAcknowledgeSource, Operation};
3
4use crate::{CmdWord, Error, ValidAddressMode};
5
6use super::{AnyPin, PIOExt, StateMachineIndex, I2C};
7
8impl<P, SMI, SDA, SCL> I2C<'_, P, SMI, SDA, SCL>
9where
10    P: PIOExt,
11    SMI: StateMachineIndex,
12    SDA: AnyPin,
13    SCL: AnyPin,
14{
15    pub fn write_iter<B, A>(&mut self, address: A, bytes: B) -> Result<(), Error>
16    where
17        A: ValidAddressMode,
18        B: IntoIterator<Item = u8> + Clone,
19    {
20        self.process_queue(
21            super::setup(address, false, false).chain(bytes.into_iter().map(CmdWord::write)),
22        )?;
23        self.generate_stop();
24        Ok(())
25    }
26
27    pub fn write_iter_read<A, B>(
28        &mut self,
29        address: A,
30        bytes: B,
31        buffer: &mut [u8],
32    ) -> Result<(), Error>
33    where
34        A: ValidAddressMode,
35        B: IntoIterator<Item = u8>,
36    {
37        self.process_queue(
38            super::setup(address, false, false)
39                .chain(bytes.into_iter().map(CmdWord::write))
40                .chain(super::setup(address, true, true))
41                .chain(buffer.iter_mut().map(CmdWord::read)),
42        )?;
43        self.generate_stop();
44        Ok(())
45    }
46
47    pub fn transaction_iter<'a, A, O>(&mut self, address: A, operations: O) -> Result<(), Error>
48    where
49        A: ValidAddressMode,
50        O: IntoIterator<Item = Operation<'a>>,
51    {
52        let mut first = true;
53        for op in operations {
54            let iter = match op {
55                Operation::Read(buf) => Left(
56                    super::setup(address, true, !first).chain(buf.iter_mut().map(CmdWord::read)),
57                ),
58                Operation::Write(buf) => Right(
59                    super::setup(address, false, !first)
60                        .chain(buf.iter().cloned().map(CmdWord::write)),
61                ),
62            };
63            self.process_queue(iter)?;
64            first = false;
65        }
66        self.generate_stop();
67        Ok(())
68    }
69}
70
71impl embedded_hal::i2c::Error for super::Error {
72    fn kind(&self) -> ErrorKind {
73        match self {
74            Error::NoAcknowledgeAddress => ErrorKind::NoAcknowledge(NoAcknowledgeSource::Address),
75            Error::NoAcknowledgeData => ErrorKind::NoAcknowledge(NoAcknowledgeSource::Data),
76            Error::BusContention => ErrorKind::ArbitrationLoss,
77        }
78    }
79}
80
81impl<P, SMI, SDA, SCL> embedded_hal::i2c::ErrorType for I2C<'_, P, SMI, SDA, SCL>
82where
83    P: PIOExt,
84    SMI: StateMachineIndex,
85    SDA: AnyPin,
86    SCL: AnyPin,
87{
88    type Error = super::Error;
89}
90
91impl<A, P, SMI, SDA, SCL> embedded_hal::i2c::I2c<A> for I2C<'_, P, SMI, SDA, SCL>
92where
93    A: ValidAddressMode,
94    P: PIOExt,
95    SMI: StateMachineIndex,
96    SDA: AnyPin,
97    SCL: AnyPin,
98{
99    fn transaction(
100        &mut self,
101        address: A,
102        operations: &mut [Operation<'_>],
103    ) -> Result<(), Self::Error> {
104        let mut first = true;
105        for op in operations {
106            let iter = match op {
107                Operation::Read(buf) => Left(
108                    super::setup(address, true, !first).chain(buf.iter_mut().map(CmdWord::read)),
109                ),
110                Operation::Write(buf) => Right(
111                    super::setup(address, false, !first)
112                        .chain(buf.iter().cloned().map(CmdWord::write)),
113                ),
114            };
115            self.process_queue(iter)?;
116            first = false;
117        }
118        self.generate_stop();
119        Ok(())
120    }
121}