From 8adc0b87f458ee94d01b02bd235ce9b26d84340e Mon Sep 17 00:00:00 2001 From: Niklas Kapelle Date: Wed, 20 May 2026 17:44:22 +0200 Subject: [PATCH] improved code structure --- Cargo.lock | 18 +++++- Cargo.toml | 2 + src/display.rs | 5 +- src/init.rs | 6 ++ src/init/i2c_sensor.rs | 24 ++++++++ src/init/logger.rs | 14 +++++ src/init/sbc.rs | 25 ++++++++ src/init/spi_display.rs | 56 ++++++++++++++++++ src/main.rs | 123 +++++++--------------------------------- 9 files changed, 167 insertions(+), 106 deletions(-) create mode 100644 src/init.rs create mode 100644 src/init/i2c_sensor.rs create mode 100644 src/init/logger.rs create mode 100644 src/init/sbc.rs create mode 100644 src/init/spi_display.rs diff --git a/Cargo.lock b/Cargo.lock index 12c242d..ff4e200 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -280,6 +280,8 @@ dependencies = [ "log", "mipidsi", "mmc56x3", + "portable-atomic", + "static_cell", ] [[package]] @@ -1055,9 +1057,12 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +dependencies = [ + "critical-section", +] [[package]] name = "precomputed-hash" @@ -1316,6 +1321,15 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "static_cell" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23" +dependencies = [ + "portable-atomic", +] + [[package]] name = "string_cache" version = "0.8.9" diff --git a/Cargo.toml b/Cargo.toml index bc62cf9..5efc727 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,8 @@ mipidsi = "0.9.0" embedded-hal-bus = "0.3.0" embedded-graphics = "0.8.1" mmc56x3 = "0.1.0" +static_cell = { version = "2.1.1" } +portable-atomic = { version = "1.13.1", features = ["critical-section"] } [profile.dev] codegen-units = 1 diff --git a/src/display.rs b/src/display.rs index 0a2f36c..0251a5c 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,5 +1,8 @@ use embedded_graphics::{ - mono_font::{MonoTextStyle, ascii::{FONT_9X18_BOLD, FONT_10X20}}, + mono_font::{ + MonoTextStyle, + ascii::{FONT_10X20}, + }, pixelcolor::BinaryColor, prelude::{DrawTarget, Point, *}, text::Text, diff --git a/src/init.rs b/src/init.rs new file mode 100644 index 0000000..47ff8aa --- /dev/null +++ b/src/init.rs @@ -0,0 +1,6 @@ +pub mod i2c_sensor; +pub mod logger; +mod sbc; +pub mod spi_display; + +pub use sbc::{hardware_init, reboot}; diff --git a/src/init/i2c_sensor.rs b/src/init/i2c_sensor.rs new file mode 100644 index 0000000..3c123df --- /dev/null +++ b/src/init/i2c_sensor.rs @@ -0,0 +1,24 @@ +use embassy_rp::{ + Peri, + i2c::{self, Async, I2c}, + peripherals::I2C1, +}; +use mmc56x3::MMC56X3; + +use crate::init::sbc::Irqs; + +pub async fn init_sensor( + i2c: Peri<'static, embassy_rp::peripherals::I2C1>, + sda: Peri<'static, embassy_rp::peripherals::PIN_14>, + scl: Peri<'static, embassy_rp::peripherals::PIN_15>, +) -> Result, embassy_time::Delay>, mmc56x3::Error> { + let i2c = I2c::new_async(i2c, scl, sda, Irqs, i2c::Config::default()); + + let mut device = MMC56X3::new(i2c, embassy_time::Delay); + + device.init().await?; + device.set_data_rate(mmc56x3::DataRate::Max1000Hz).await?; + device.set_continuous_mode(true).await?; + + return Ok(device); +} diff --git a/src/init/logger.rs b/src/init/logger.rs new file mode 100644 index 0000000..89f58e6 --- /dev/null +++ b/src/init/logger.rs @@ -0,0 +1,14 @@ +use embassy_executor::Spawner; +use embassy_rp::{Peri, peripherals::USB, usb::Driver}; + +use crate::init::sbc::Irqs; + +#[embassy_executor::task] +async fn logger_task(driver: embassy_rp::usb::Driver<'static, USB>) { + embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver); +} + +pub fn init_logger(spawner: Spawner, usb: Peri<'static, USB>) { + let driver = Driver::new(usb, Irqs); + spawner.must_spawn(logger_task(driver)); +} diff --git a/src/init/sbc.rs b/src/init/sbc.rs new file mode 100644 index 0000000..11404fd --- /dev/null +++ b/src/init/sbc.rs @@ -0,0 +1,25 @@ +use embassy_rp::{ + Peripherals, bind_interrupts, i2c, + peripherals::{self, USB}, +}; +use embassy_time::Timer; + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + // TODO: How to log panic? + loop {} +} + +bind_interrupts!(pub struct Irqs { + USBCTRL_IRQ => embassy_rp::usb::InterruptHandler; + I2C1_IRQ => i2c::InterruptHandler; +}); + +pub async fn reboot() { + Timer::after_secs(1).await; + embassy_rp::rom_data::reset_to_usb_boot(0, 0); +} + +pub fn hardware_init() -> Peripherals { + embassy_rp::init(Default::default()) +} diff --git a/src/init/spi_display.rs b/src/init/spi_display.rs new file mode 100644 index 0000000..588f8d0 --- /dev/null +++ b/src/init/spi_display.rs @@ -0,0 +1,56 @@ +use embassy_rp::{ + Peri, + gpio::{Level, Output}, + spi::{self, Spi}, +}; +use embassy_time::Timer; +use embedded_graphics::{pixelcolor::Rgb565, prelude::DrawTarget}; +use embedded_hal_bus::spi::ExclusiveDevice; +use mipidsi::{ + Builder, + interface::SpiInterface, + models::ST7789, + options::{Orientation, Rotation}, +}; +use static_cell::StaticCell; + +pub async fn init_display( + inner: Peri<'static, embassy_rp::peripherals::SPI0>, + clk: Peri<'static, embassy_rp::peripherals::PIN_6>, + mosi: Peri<'static, embassy_rp::peripherals::PIN_7>, + cs: Peri<'static, embassy_rp::peripherals::PIN_5>, + dc: Peri<'static, embassy_rp::peripherals::PIN_9>, + rst: Peri<'static, embassy_rp::peripherals::PIN_10>, +) -> Result, ()> { + let mut spi_cfg = spi::Config::default(); + spi_cfg.frequency = 62_500_000; + + let spi = Spi::new_blocking_txonly(inner, clk, mosi, spi_cfg); + + let cs_display = Output::new(cs, Level::Low); + let dc_display = Output::new(dc, Level::Low); + let mut rst_display = Output::new(rst, Level::Low); + + rst_display.set_low(); + Timer::after_millis(10).await; + rst_display.set_high(); + Timer::after_millis(120).await; + + let spi_dev = ExclusiveDevice::new_no_delay(spi, cs_display).expect("Error is Infallible"); + + static BUFFER: StaticCell<[u8; 512]> = StaticCell::new(); + let buffer: &'static mut [u8; 512] = BUFFER.init([0u8; 512]); + + let di = SpiInterface::new(spi_dev, dc_display, buffer); + + static DELAY: StaticCell = StaticCell::new(); + let delay = DELAY.init(embassy_time::Delay); + + let display = Builder::new(ST7789, di) + .display_size(240, 320) + .orientation(Orientation::new().rotate(Rotation::Deg90)) + .init(delay) + .map_err(|_| ())?; // TODO: pass error + + Ok(display) +} diff --git a/src/main.rs b/src/main.rs index 18d47c5..e116211 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,123 +2,40 @@ #![no_main] use embassy_executor::Spawner; -use embassy_rp::{ - bind_interrupts, gpio, - i2c::{self, I2c}, - peripherals::{self, USB}, - spi::{self, Spi}, - usb::Driver, -}; use embassy_time::Timer; -use embedded_graphics::prelude::DrawTargetExt; -use embedded_hal_bus::spi::ExclusiveDevice; -use gpio::{Level, Output}; -use log::{error, info}; -use mipidsi::{ - Builder, - interface::SpiInterface, - models::ST7789, - options::{Orientation, Rotation}, -}; -use mmc56x3::MMC56X3; +use embedded_graphics::draw_target::DrawTargetExt; +use log::error; use crate::display::CoMoDisplay; mod display; - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - // TODO: How to log panic? - loop {} -} - -bind_interrupts!(struct Irqs { - USBCTRL_IRQ => embassy_rp::usb::InterruptHandler; - I2C1_IRQ => i2c::InterruptHandler; -}); - -#[embassy_executor::task] -async fn logger_task(driver: Driver<'static, USB>) { - embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver); -} +mod init; #[embassy_executor::main] async fn main(spawner: Spawner) { - let p = embassy_rp::init(Default::default()); + let p = init::hardware_init(); + init::logger::init_logger(spawner, p.USB); - let driver = Driver::new(p.USB, Irqs); - spawner.must_spawn(logger_task(driver)); + let Ok(mag) = init::i2c_sensor::init_sensor(p.I2C1, p.PIN_14, p.PIN_15).await else { + error!("Failed to init sensor"); - let mut spi_cfg = spi::Config::default(); - spi_cfg.frequency = 62_500_000; + init::reboot().await; + return; + }; - let inner = p.SPI0; - let clk = p.PIN_6; - let mosi = p.PIN_7; - let cs = p.PIN_5; - let dc = p.PIN_9; - let rst = p.PIN_10; + let Ok(mut display) = + init::spi_display::init_display(p.SPI0, p.PIN_6, p.PIN_7, p.PIN_5, p.PIN_9, p.PIN_10).await + else { + error!("Failed to init display"); - let spi = Spi::new_blocking_txonly(inner, clk, mosi, spi_cfg); - let cs_display = Output::new(cs, Level::Low); - let dc_display = Output::new(dc, Level::Low); - let mut rst_display = Output::new(rst, Level::Low); - - rst_display.set_low(); - Timer::after_millis(10).await; - rst_display.set_high(); - Timer::after_millis(120).await; - - let spi_dev = ExclusiveDevice::new_no_delay(spi, cs_display).unwrap(); - - let mut buffer = [0u8; 512]; - let di = SpiInterface::new(spi_dev, dc_display, &mut buffer); - - let mut display = Builder::new(ST7789, di) - .display_size(240, 320) - .orientation(Orientation::new().rotate(Rotation::Deg90)) - .init(&mut embassy_time::Delay) - .unwrap(); + init::reboot().await; + return; + }; let mut como_display = CoMoDisplay::new(display.color_converted()); - let _ = como_display.draw(); + como_display.draw(); - let i2c_sda = p.PIN_14; - let i2c_scl = p.PIN_15; - - let i2c = I2c::new_async(p.I2C1, i2c_scl, i2c_sda, Irqs, i2c::Config::default()); - - let mut device = MMC56X3::new(i2c, embassy_time::Delay); - - if let Err(e) = device.init().await { - error!("Failed to init {:?}", e); - reboot().await; - }; - - if let Err(e) = device.set_data_rate(mmc56x3::DataRate::Max1000Hz).await { - error!("Failed to set data rate {:?}", e); - reboot().await; - } - - if let Err(e) = device.set_continuous_mode(true).await { - error!("Failed to set_continuous_mode {:?}", e); - reboot().await; - } - for _ in 0..30 { - Timer::after_secs(1).await; - - match device.read_messurement().await { - Ok(d) => info!("Got: {:?}", d), - Err(e) => error!("Error: {:?}", e), - } - } - - reboot().await; -} - -async fn reboot() { - info!("Doing cold boot"); - Timer::after_secs(1).await; - embassy_rp::rom_data::reset_to_usb_boot(0, 0); + Timer::after_secs(5).await; + init::reboot().await; }