i2c_write_iter/
lib.rs

1#![no_std]
2#![allow(async_fn_in_trait)]
3
4use core::iter::once;
5
6pub use embedded_hal::i2c::{AddressMode, I2c};
7
8/// I2C operation.
9///
10/// Several operations can be combined as part of a transaction.
11#[derive(Debug, PartialEq, Eq)]
12#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
13pub enum Operation<'a, B>
14where
15    B: IntoIterator<Item = u8>,
16{
17    /// Read data into the provided buffer.
18    Read(&'a mut [u8]),
19    /// Write data from the provided iterator.
20    WriteIter(B),
21}
22
23pub trait I2cIter<A: AddressMode>: I2c<A> {
24    /// Execute the provided operations on the I2C bus.
25    ///
26    /// Same as `I2c::transaction` but with an interator instead of a slice of operations.
27    fn transaction_iter<'a, O, B>(&mut self, address: A, operations: O) -> Result<(), Self::Error>
28    where
29        O: IntoIterator<Item = Operation<'a, B>>,
30        B: IntoIterator<Item = u8>;
31
32    /// Writes bytes to slave with address `address`
33    ///
34    /// Same as `I2c::write` but with an interator instead of a slice of bytes.
35    fn write_iter<B>(&mut self, address: A, bytes: B) -> Result<(), Self::Error>
36    where
37        B: IntoIterator<Item = u8>,
38    {
39        self.transaction_iter(address, once(Operation::WriteIter(bytes)))
40    }
41
42    /// Writes bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a
43    /// single transaction*
44    ///
45    /// Same as `I2c::write_read` but with an interator instead of a slice of bytes.
46    fn write_iter_read<B>(
47        &mut self,
48        address: A,
49        bytes: B,
50        buffer: &mut [u8],
51    ) -> Result<(), Self::Error>
52    where
53        B: IntoIterator<Item = u8>,
54    {
55        self.transaction_iter(
56            address,
57            [Operation::WriteIter(bytes), Operation::Read(buffer)],
58        )
59    }
60}
61
62/// Exposes trait for async.await use cases. Requires the `async` feature.
63#[cfg(feature = "async")]
64pub mod non_blocking {
65    use core::iter::once;
66
67    pub use embedded_hal_async::i2c::{AddressMode, I2c};
68
69    use crate::Operation;
70
71    pub trait I2cIter<A: AddressMode>: I2c<A> {
72        /// Execute the provided operations on the I2C bus.
73        ///
74        /// Same as `I2c::transaction` but with an interator instead of a slice.
75        async fn transaction_iter<'a, O, B>(
76            &mut self,
77            address: A,
78            operations: O,
79        ) -> Result<(), Self::Error>
80        where
81            O: IntoIterator<Item = Operation<'a, B>>,
82            B: IntoIterator<Item = u8>;
83
84        /// Writes bytes to slave with address `address`
85        ///
86        /// Same as `I2c::write` but with an interator instead of a slice of bytes.
87        async fn write_iter<B>(&mut self, address: A, bytes: B) -> Result<(), Self::Error>
88        where
89            B: IntoIterator<Item = u8>,
90        {
91            self.transaction_iter(address, once(Operation::WriteIter(bytes)))
92                .await
93        }
94
95        /// Writes bytes to slave with address `address` and then reads enough bytes to fill `buffer` *in a
96        /// single transaction*
97        ///
98        /// Same as `I2c::write_read` but with an interator instead of a slice of bytes.
99        async fn write_iter_read<B>(
100            &mut self,
101            address: A,
102            bytes: B,
103            buffer: &mut [u8],
104        ) -> Result<(), Self::Error>
105        where
106            B: IntoIterator<Item = u8>,
107        {
108            self.transaction_iter(
109                address,
110                [Operation::WriteIter(bytes), Operation::Read(buffer)],
111            )
112            .await
113        }
114    }
115}