diff --git a/CHANGELOG.md b/CHANGELOG.md index b9fa7708..a03af2e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,15 @@ SSD1306 monochrome OLED display. - ## [Unreleased] - ReleaseDate +### Changed +- Update `embedded-hal-bus` dependency to 0.3.0 +- Update examples + +### Fixed +- Parentheses for expression in mode/terminal.rs (see [precedence](https://rust-lang.github.io/rust-clippy/master/index.html#precedence)) in mode/terminal.rs +- Switch iterator in `write_str` in mode/terminal.rs from last() to next_back (see [double_ended_iterator_last](https://rust-lang.github.io/rust-clippy/master/index.html#double_ended_iterator_last)) +- If feature `async` is enabled, the `embedded_hal_async::i2c::I2c` is used instead of `embedded_hal::i2c::I2c` so the I2C can be shared - Update dependencies for `embassy-executor` to 0.7.0 - Remove `embassy-executor` feature "integrated-timer". See https://github.com/embassy-rs/embassy/blob/main/embassy-executor/CHANGELOG.md - Switch `embassy-executor` from git to crates.io diff --git a/Cargo.toml b/Cargo.toml index ebb43cbc..8d9585eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,7 @@ embassy-stm32 = { version = "0.2.0", features = [ ] } embassy-time = { version = "0.4.0" } embassy-futures = "0.1.1" -embedded-hal-bus = { version = "0.2.0", features = ["async"] } +embedded-hal-bus = { version = "0.3.0", features = ["async"] } [features] default = ["graphics"] diff --git a/examples/bmp_i2c.rs b/examples/bmp_i2c.rs index c042cfa7..4d244b2d 100644 --- a/examples/bmp_i2c.rs +++ b/examples/bmp_i2c.rs @@ -25,6 +25,8 @@ use cortex_m::asm::nop; use cortex_m_rt::entry; use defmt_rtt as _; use embassy_stm32::time::Hertz; +#[cfg(feature = "async")] +use embassy_stm32::{bind_interrupts, i2c, peripherals}; use embedded_graphics::{image::Image, pixelcolor::Rgb565, prelude::*}; use panic_probe as _; use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; @@ -33,16 +35,35 @@ use tinybmp::Bmp; #[entry] fn main() -> ! { - let p = embassy_stm32::init(Default::default()); - let i2c = embassy_stm32::i2c::I2c::new_blocking( + let p: embassy_stm32::Peripherals = embassy_stm32::init(Default::default()); + #[cfg(feature = "async")] + bind_interrupts!(struct Irqs { + I2C1_EV => i2c::EventInterruptHandler; + I2C1_ER => i2c::ErrorInterruptHandler; + }); + + #[cfg(feature = "async")] + let i2c = embassy_stm32::i2c::I2c::new( p.I2C1, p.PB6, p.PB7, + Irqs, + p.DMA1_CH6, + p.DMA1_CH7, Hertz::khz(400), Default::default(), ); + #[cfg(not(feature = "async"))] + let i2c = embassy_stm32::i2c::I2c::new_blocking( + p.I2C1, + p.PB6, + p.PB7, + Hertz::khz(400), + Default::default(), + ); let interface = I2CDisplayInterface::new(i2c); + let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0) .into_buffered_graphics_mode(); display.init().unwrap(); diff --git a/examples/graphics_i2c.rs b/examples/graphics_i2c.rs index d8c06124..64958e33 100644 --- a/examples/graphics_i2c.rs +++ b/examples/graphics_i2c.rs @@ -21,6 +21,8 @@ use cortex_m::asm::nop; use cortex_m_rt::entry; use defmt_rtt as _; use embassy_stm32::time::Hertz; +#[cfg(feature = "async")] +use embassy_stm32::{bind_interrupts, i2c, peripherals}; use embedded_graphics::{ pixelcolor::BinaryColor, prelude::*, @@ -32,6 +34,25 @@ use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; #[entry] fn main() -> ! { let p = embassy_stm32::init(Default::default()); + #[cfg(feature = "async")] + bind_interrupts!(struct Irqs { + I2C1_EV => i2c::EventInterruptHandler; + I2C1_ER => i2c::ErrorInterruptHandler; + }); + + #[cfg(feature = "async")] + let i2c = embassy_stm32::i2c::I2c::new( + p.I2C1, + p.PB6, + p.PB7, + Irqs, + p.DMA1_CH6, + p.DMA1_CH7, + Hertz::khz(400), + Default::default(), + ); + + #[cfg(not(feature = "async"))] let i2c = embassy_stm32::i2c::I2c::new_blocking( p.I2C1, p.PB6, diff --git a/examples/graphics_i2c_128x32.rs b/examples/graphics_i2c_128x32.rs index 9620b933..ba25d5a2 100644 --- a/examples/graphics_i2c_128x32.rs +++ b/examples/graphics_i2c_128x32.rs @@ -21,6 +21,8 @@ use cortex_m::asm::nop; use cortex_m_rt::entry; use defmt_rtt as _; use embassy_stm32::time::Hertz; +#[cfg(feature = "async")] +use embassy_stm32::{bind_interrupts, i2c, peripherals}; use embedded_graphics::{ pixelcolor::BinaryColor, prelude::*, @@ -32,6 +34,25 @@ use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; #[entry] fn main() -> ! { let p = embassy_stm32::init(Default::default()); + #[cfg(feature = "async")] + bind_interrupts!(struct Irqs { + I2C1_EV => i2c::EventInterruptHandler; + I2C1_ER => i2c::ErrorInterruptHandler; + }); + + #[cfg(feature = "async")] + let i2c = embassy_stm32::i2c::I2c::new( + p.I2C1, + p.PB6, + p.PB7, + Irqs, + p.DMA1_CH6, + p.DMA1_CH7, + Hertz::khz(400), + Default::default(), + ); + + #[cfg(not(feature = "async"))] let i2c = embassy_stm32::i2c::I2c::new_blocking( p.I2C1, p.PB6, diff --git a/examples/graphics_i2c_72x40.rs b/examples/graphics_i2c_72x40.rs index e45a4eed..e0cbbe76 100644 --- a/examples/graphics_i2c_72x40.rs +++ b/examples/graphics_i2c_72x40.rs @@ -21,6 +21,8 @@ use cortex_m::asm::nop; use cortex_m_rt::entry; use defmt_rtt as _; use embassy_stm32::time::Hertz; +#[cfg(feature = "async")] +use embassy_stm32::{bind_interrupts, i2c, peripherals}; use embedded_graphics::{ pixelcolor::BinaryColor, prelude::*, @@ -32,6 +34,25 @@ use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; #[entry] fn main() -> ! { let p = embassy_stm32::init(Default::default()); + #[cfg(feature = "async")] + bind_interrupts!(struct Irqs { + I2C1_EV => i2c::EventInterruptHandler; + I2C1_ER => i2c::ErrorInterruptHandler; + }); + + #[cfg(feature = "async")] + let i2c = embassy_stm32::i2c::I2c::new( + p.I2C1, + p.PB6, + p.PB7, + Irqs, + p.DMA1_CH6, + p.DMA1_CH7, + Hertz::khz(400), + Default::default(), + ); + + #[cfg(not(feature = "async"))] let i2c = embassy_stm32::i2c::I2c::new_blocking( p.I2C1, p.PB6, diff --git a/examples/image_i2c.rs b/examples/image_i2c.rs index 772cc8ae..ff928951 100644 --- a/examples/image_i2c.rs +++ b/examples/image_i2c.rs @@ -26,6 +26,9 @@ use cortex_m::asm::nop; use cortex_m_rt::entry; use defmt_rtt as _; +#[cfg(feature = "async")] +use embassy_stm32::{bind_interrupts, i2c, peripherals}; + use embassy_stm32::time::Hertz; use embedded_graphics::{ image::{Image, ImageRaw}, @@ -38,6 +41,25 @@ use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; #[entry] fn main() -> ! { let p = embassy_stm32::init(Default::default()); + #[cfg(feature = "async")] + bind_interrupts!(struct Irqs { + I2C1_EV => i2c::EventInterruptHandler; + I2C1_ER => i2c::ErrorInterruptHandler; + }); + + #[cfg(feature = "async")] + let i2c = embassy_stm32::i2c::I2c::new( + p.I2C1, + p.PB6, + p.PB7, + Irqs, + p.DMA1_CH6, + p.DMA1_CH7, + Hertz::khz(400), + Default::default(), + ); + + #[cfg(not(feature = "async"))] let i2c = embassy_stm32::i2c::I2c::new_blocking( p.I2C1, p.PB6, diff --git a/examples/noise_i2c.rs b/examples/noise_i2c.rs index c51ca290..e1407252 100644 --- a/examples/noise_i2c.rs +++ b/examples/noise_i2c.rs @@ -21,6 +21,9 @@ use cortex_m_rt::entry; use defmt_rtt as _; +#[cfg(feature = "async")] +use embassy_stm32::{bind_interrupts, i2c, peripherals}; + use embassy_stm32::time::Hertz; use panic_probe as _; use rand::prelude::*; @@ -29,6 +32,25 @@ use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; #[entry] fn main() -> ! { let p = embassy_stm32::init(Default::default()); + #[cfg(feature = "async")] + bind_interrupts!(struct Irqs { + I2C1_EV => i2c::EventInterruptHandler; + I2C1_ER => i2c::ErrorInterruptHandler; + }); + + #[cfg(feature = "async")] + let i2c = embassy_stm32::i2c::I2c::new( + p.I2C1, + p.PB6, + p.PB7, + Irqs, + p.DMA1_CH6, + p.DMA1_CH7, + Hertz::khz(400), + Default::default(), + ); + + #[cfg(not(feature = "async"))] let i2c = embassy_stm32::i2c::I2c::new_blocking( p.I2C1, p.PB6, diff --git a/examples/rotation_i2c.rs b/examples/rotation_i2c.rs index 67535559..3219ab9b 100644 --- a/examples/rotation_i2c.rs +++ b/examples/rotation_i2c.rs @@ -27,6 +27,8 @@ use cortex_m::asm::nop; use cortex_m_rt::entry; use defmt_rtt as _; use embassy_stm32::time::Hertz; +#[cfg(feature = "async")] +use embassy_stm32::{bind_interrupts, i2c, peripherals}; use embedded_graphics::{ image::{Image, ImageRaw}, pixelcolor::BinaryColor, @@ -38,6 +40,25 @@ use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; #[entry] fn main() -> ! { let p = embassy_stm32::init(Default::default()); + #[cfg(feature = "async")] + bind_interrupts!(struct Irqs { + I2C1_EV => i2c::EventInterruptHandler; + I2C1_ER => i2c::ErrorInterruptHandler; + }); + + #[cfg(feature = "async")] + let i2c = embassy_stm32::i2c::I2c::new( + p.I2C1, + p.PB6, + p.PB7, + Irqs, + p.DMA1_CH6, + p.DMA1_CH7, + Hertz::khz(400), + Default::default(), + ); + + #[cfg(not(feature = "async"))] let i2c = embassy_stm32::i2c::I2c::new_blocking( p.I2C1, p.PB6, diff --git a/examples/terminal_i2c.rs b/examples/terminal_i2c.rs index f1fb86bb..f7d143ec 100644 --- a/examples/terminal_i2c.rs +++ b/examples/terminal_i2c.rs @@ -21,12 +21,33 @@ use core::fmt::Write; use cortex_m_rt::entry; use defmt_rtt as _; use embassy_stm32::time::Hertz; +#[cfg(feature = "async")] +use embassy_stm32::{bind_interrupts, i2c, peripherals}; use panic_probe as _; use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; #[entry] fn main() -> ! { let p = embassy_stm32::init(Default::default()); + #[cfg(feature = "async")] + bind_interrupts!(struct Irqs { + I2C1_EV => i2c::EventInterruptHandler; + I2C1_ER => i2c::ErrorInterruptHandler; + }); + + #[cfg(feature = "async")] + let i2c = embassy_stm32::i2c::I2c::new( + p.I2C1, + p.PB6, + p.PB7, + Irqs, + p.DMA1_CH6, + p.DMA1_CH7, + Hertz::khz(400), + Default::default(), + ); + + #[cfg(not(feature = "async"))] let i2c = embassy_stm32::i2c::I2c::new_blocking( p.I2C1, p.PB6, diff --git a/examples/text_i2c.rs b/examples/text_i2c.rs index b5e95158..47de4b9a 100644 --- a/examples/text_i2c.rs +++ b/examples/text_i2c.rs @@ -22,6 +22,8 @@ use cortex_m::asm::nop; use cortex_m_rt::entry; use defmt_rtt as _; use embassy_stm32::time::Hertz; +#[cfg(feature = "async")] +use embassy_stm32::{bind_interrupts, i2c, peripherals}; use embedded_graphics::{ mono_font::{ascii::FONT_6X10, MonoTextStyleBuilder}, pixelcolor::BinaryColor, @@ -34,6 +36,25 @@ use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; #[entry] fn main() -> ! { let p = embassy_stm32::init(Default::default()); + #[cfg(feature = "async")] + bind_interrupts!(struct Irqs { + I2C1_EV => i2c::EventInterruptHandler; + I2C1_ER => i2c::ErrorInterruptHandler; + }); + + #[cfg(feature = "async")] + let i2c = embassy_stm32::i2c::I2c::new( + p.I2C1, + p.PB6, + p.PB7, + Irqs, + p.DMA1_CH6, + p.DMA1_CH7, + Hertz::khz(400), + Default::default(), + ); + + #[cfg(not(feature = "async"))] let i2c = embassy_stm32::i2c::I2c::new_blocking( p.I2C1, p.PB6, diff --git a/src/i2c_interface.rs b/src/i2c_interface.rs index d76a8773..7d7c72e0 100644 --- a/src/i2c_interface.rs +++ b/src/i2c_interface.rs @@ -8,6 +8,7 @@ pub struct I2CDisplayInterface(()); impl I2CDisplayInterface { /// Create new builder with a default I2C address of 0x3C + #[cfg(not(feature = "async"))] #[allow(clippy::new_ret_no_self)] // pub fn with_i2c(i2c: I) -> I2CInterface // alternative, but breaking change pub fn new(i2c: I) -> I2CInterface @@ -16,7 +17,17 @@ impl I2CDisplayInterface { { Self::new_custom_address(i2c, 0x3C) } + #[cfg(feature = "async")] + #[allow(clippy::new_ret_no_self)] + /// Create a new async I2C interface with the address 0x3D + pub fn new(i2c: I) -> I2CInterface + where + I: embedded_hal_async::i2c::I2c, + { + Self::new_custom_address(i2c, 0x3C) + } + #[cfg(not(feature = "async"))] /// Create a new I2C interface with the alternate address 0x3D as specified in the datasheet. pub fn new_alternate_address(i2c: I) -> I2CInterface where @@ -25,6 +36,16 @@ impl I2CDisplayInterface { Self::new_custom_address(i2c, 0x3D) } + #[cfg(feature = "async")] + /// Create a new async I2C interface with the alternate address 0x3D as specified in the datasheet. + pub fn new_alternate_address(i2c: I) -> I2CInterface + where + I: embedded_hal_async::i2c::I2c, + { + Self::new_custom_address(i2c, 0x3D) + } + + #[cfg(not(feature = "async"))] /// Create a new I2C interface with a custom address. pub fn new_custom_address(i2c: I, address: u8) -> I2CInterface where @@ -32,4 +53,12 @@ impl I2CDisplayInterface { { I2CInterface::new(i2c, address, 0x40) } + #[cfg(feature = "async")] + /// Create a new async I2C interface with a custom address. + pub fn new_custom_address(i2c: I, address: u8) -> I2CInterface + where + I: embedded_hal_async::i2c::I2c, + { + I2CInterface::new(i2c, address, 0x40) + } } diff --git a/src/mode/terminal.rs b/src/mode/terminal.rs index f3d86385..d9b4c9d1 100644 --- a/src/mode/terminal.rs +++ b/src/mode/terminal.rs @@ -592,7 +592,7 @@ where for (col, source) in bitmap.iter().enumerate() { // source.msb is the top pixel for (row, item) in rotated.iter_mut().enumerate() { - let bit = source & 1 << row != 0; + let bit = source & (1 << row) != 0; if bit { *item |= 1 << col; } @@ -624,7 +624,7 @@ where SIZE: TerminalDisplaySize, { fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { - s.chars().map(move |c| self.print_char(c)).last(); + s.chars().map(move |c| self.print_char(c)).next_back(); Ok(()) } }