Skip to content

Commit 57b8d7c

Browse files
committed
i2c: Implement i2c-write-iter traits
1 parent be9b0ab commit 57b8d7c

File tree

5 files changed

+101
-3
lines changed

5 files changed

+101
-3
lines changed

on-target-tests/Cargo.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,10 @@ defmt-test = "0.3.1"
5151
panic-probe = { version = "0.3", features = ["print-defmt"] }
5252

5353
rp2040-hal = { path = "../rp2040-hal", features = [
54-
"defmt",
55-
"critical-section-impl",
56-
"rt",
54+
"critical-section-impl",
55+
"defmt",
56+
"rt",
57+
"i2c-write-iter",
5758
] }
5859
# Needed to set spi frequencies
5960
fugit = "0.3.6"
@@ -70,4 +71,6 @@ nostd_async = { version = "0.6.1", features = ["wfe"] }
7071
futures = { version = "0.3.30", default-features = false, features = [
7172
"async-await",
7273
] }
74+
i2c-write-iter = "1.0.0"
7375
itertools = { version = "0.12.0", default-features = false }
76+
portable-atomic = { version = "1.6.0", features = ["critical-section"] }

rp2040-hal/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ frunk = { version = "0.4.1", default-features = false }
4848

4949
bitfield = { version = "0.14.0" }
5050

51+
i2c-write-iter = { version = "1.0.0", features = ["async"], optional = true }
52+
5153
[dev-dependencies]
5254
cortex-m-rt = "0.7"
5355
cortex-m-rtic = "1.1.4"
@@ -98,6 +100,9 @@ defmt = ["dep:defmt"]
98100
# Implement `rtic_monotonic::Monotonic` based on the RP2040 timer peripheral
99101
rtic-monotonic = ["dep:rtic-monotonic"]
100102

103+
# Implement `i2c-write-iter` traits
104+
i2c-write-iter = ["dep:i2c-write-iter"]
105+
101106
[[example]]
102107
# irq example uses cortex-m-rt::interrupt, need rt feature for that
103108
name = "gpio_irq_example"

rp2040-hal/src/i2c/controller.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,29 @@ impl<T: Deref<Target = Block>, PINS> I2C<T, PINS, Controller> {
386386
}
387387
Ok(())
388388
}
389+
390+
#[cfg(feature = "i2c-write-iter")]
391+
fn transaction_iter<'op, A, O, B>(&mut self, address: A, operations: O) -> Result<(), Error>
392+
where
393+
A: ValidAddress,
394+
O: IntoIterator<Item = i2c_write_iter::Operation<'op, B>>,
395+
B: IntoIterator<Item = u8>,
396+
{
397+
use i2c_write_iter::Operation;
398+
self.setup(address)?;
399+
400+
let mut first = true;
401+
let mut operations = operations.into_iter().peekable();
402+
while let Some(operation) = operations.next() {
403+
let last = operations.peek().is_none();
404+
match operation {
405+
Operation::Read(buf) => self.read_internal(first, buf, last)?,
406+
Operation::WriteIter(buf) => self.write_internal(first, buf, last)?,
407+
}
408+
first = false;
409+
}
410+
Ok(())
411+
}
389412
}
390413

391414
impl<A: ValidAddress, T: Deref<Target = Block>, PINS> Read<A> for I2C<T, PINS, Controller> {
@@ -458,3 +481,16 @@ impl<A: ValidAddress, T: Deref<Target = Block>, PINS> eh1::I2c<A> for I2C<T, PIN
458481
self.transaction(address, operations.iter_mut())
459482
}
460483
}
484+
485+
#[cfg(feature = "i2c-write-iter")]
486+
impl<A: i2c_write_iter::AddressMode + ValidAddress, T: Deref<Target = Block>, PINS>
487+
i2c_write_iter::I2cIter<A> for I2C<T, PINS, Controller>
488+
{
489+
fn transaction_iter<'a, O, B>(&mut self, address: A, operations: O) -> Result<(), Self::Error>
490+
where
491+
O: IntoIterator<Item = i2c_write_iter::Operation<'a, B>>,
492+
B: IntoIterator<Item = u8>,
493+
{
494+
self.transaction_iter(address, operations)
495+
}
496+
}

rp2040-hal/src/i2c/controller/non_blocking.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,38 @@ where
259259
self.non_blocking_write_internal(true, bytes, false).await?;
260260
self.non_blocking_read_internal(false, read, true).await
261261
}
262+
263+
/// Writes to the i2c bus taking operations from and iterator, writing from iterator of bytes,
264+
/// reading to slices of bytes.
265+
#[cfg(feature = "i2c-write-iter")]
266+
pub async fn transaction_iter_async<'b, A, O, B>(
267+
&mut self,
268+
address: A,
269+
operations: O,
270+
) -> Result<(), super::Error>
271+
where
272+
A: ValidAddress,
273+
O: IntoIterator<Item = i2c_write_iter::Operation<'b, B>>,
274+
B: IntoIterator<Item = u8>,
275+
{
276+
self.setup(address)?;
277+
278+
let mut first = true;
279+
let mut operations = operations.into_iter().peekable();
280+
while let Some(operation) = operations.next() {
281+
let last = operations.peek().is_none();
282+
match operation {
283+
i2c_write_iter::Operation::Read(buf) => {
284+
self.non_blocking_read_internal(first, buf, last).await?
285+
}
286+
i2c_write_iter::Operation::WriteIter(buf) => {
287+
self.non_blocking_write_internal(first, buf, last).await?
288+
}
289+
}
290+
first = false;
291+
}
292+
Ok(())
293+
}
262294
}
263295

264296
impl<T, PINS, A> embedded_hal_async::i2c::I2c<A> for I2C<T, PINS, Controller>
@@ -292,3 +324,23 @@ where
292324
Ok(())
293325
}
294326
}
327+
328+
#[cfg(feature = "i2c-write-iter")]
329+
impl<T, PINS, A> i2c_write_iter::non_blocking::I2cIter<A> for I2C<T, PINS, Controller>
330+
where
331+
Self: AsyncPeripheral,
332+
A: 'static + ValidAddress + AddressMode,
333+
T: Deref<Target = RegisterBlock>,
334+
{
335+
async fn transaction_iter<'a, O, B>(
336+
&mut self,
337+
address: A,
338+
operations: O,
339+
) -> Result<(), Self::Error>
340+
where
341+
O: IntoIterator<Item = i2c_write_iter::Operation<'a, B>>,
342+
B: IntoIterator<Item = u8>,
343+
{
344+
self.transaction_iter_async(address, operations).await
345+
}
346+
}

rp2040-hal/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
//! * **rtic-monotonic** -
3434
//! Implement
3535
//! `rtic_monotonic::Monotonic` based on the RP2040 timer peripheral
36+
//! * **i2c-write-iter** -
37+
//! Implement `i2c_write_iter` traits for `I2C<_, _, Controller>`.
3638
3739
#![warn(missing_docs)]
3840
#![no_std]

0 commit comments

Comments
 (0)