refactor: board-owned display init, zero cfg in application code

- Each board now exports DisplayDriver type and create_display() async fn
- ESP32-S3 boards share SSD1306 create_display in board/esp32s3.rs
- RAK WisBlock has its own SSD1306 create_display (different I2C type)
- Wio Tracker has SH1106 create_display (different display IC)
- Removed all cfg_if from display.rs — calls board::create_display()
- Removed display init retry logic (single attempt, return None on failure)
- ZERO board-specific #[cfg(feature)] outside board/, host/mod.rs, and hal/
This commit is contained in:
swaits committed 2026-04-07 09:46:25 -06:00
1 parent 073d1d5bdb
commit ef2b574ae2
6 files changed
+78 -47

No files matched your search

+28
View File
@@ -47,6 +47,34 @@ pub struct DisplayParts {
pub mac: [u8; 6], pub mac: [u8; 6],
} }
// ── Display driver ──────────────────────────────────────────────────
pub type DisplayDriver = ssd1306::Ssd1306Async<
ssd1306::prelude::I2CInterface<DisplayI2c>,
ssd1306::size::DisplaySize128x64,
ssd1306::mode::BufferedGraphicsModeAsync<ssd1306::size::DisplaySize128x64>,
>;
/// Construct and initialize an SSD1306 display from raw I2C.
pub async fn create_display(i2c: DisplayI2c) -> Option<DisplayDriver> {
use ssd1306::mode::DisplayConfigAsync;
use ssd1306::prelude::{Brightness, DisplayRotation};
use ssd1306::size::DisplaySize128x64;
use ssd1306::{I2CDisplayInterface, Ssd1306Async};
let interface = I2CDisplayInterface::new(i2c);
let mut display = Ssd1306Async::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
.into_buffered_graphics_mode();
embassy_time::Timer::after_millis(100).await;
if display.init().await.is_err() {
defmt::error!("SSD1306 display init failed");
return None;
}
let _ = display.set_brightness(Brightness::BRIGHTEST).await;
Some(display)
}
// ── Shared peripheral init helpers ────────────────────────────────── // ── Shared peripheral init helpers ──────────────────────────────────
/// Construct SX1262 radio from an initialized SPI bus. /// Construct SX1262 radio from an initialized SPI bus.
+4 -1
View File
@@ -5,7 +5,10 @@ use super::traits::LoRaBoard;
use crate::hal::esp32s3 as mcu; use crate::hal::esp32s3 as mcu;
#[allow(unused_imports)] // Re-exported for other modules (display, radio, uart tasks) #[allow(unused_imports)] // Re-exported for other modules (display, radio, uart tasks)
pub use super::esp32s3::{DisplayI2c, DisplayParts, RadioDriver, RadioParts, UartDriver, UartParts}; pub use super::esp32s3::{
create_display, DisplayDriver, DisplayI2c, DisplayParts, RadioDriver, RadioParts, UartDriver,
UartParts,
};
// ── Board init ────────────────────────────────────────────────────── // ── Board init ──────────────────────────────────────────────────────
+4 -1
View File
@@ -5,7 +5,10 @@ use super::traits::LoRaBoard;
use crate::hal::esp32s3 as mcu; use crate::hal::esp32s3 as mcu;
#[allow(unused_imports)] // Re-exported for other modules (display, radio, usb tasks) #[allow(unused_imports)] // Re-exported for other modules (display, radio, usb tasks)
pub use super::esp32s3::{DisplayI2c, DisplayParts, RadioDriver, RadioParts, UsbDriver, UsbParts}; pub use super::esp32s3::{
create_display, DisplayDriver, DisplayI2c, DisplayParts, RadioDriver, RadioParts, UsbDriver,
UsbParts,
};
// ── Board implementation ──────────────────────────────────────────── // ── Board implementation ────────────────────────────────────────────
+25
View File
@@ -21,6 +21,31 @@ pub type RadioDriver = Sx126x<RadioSpiDevice, Iv, Sx1262>;
pub type UsbDriver = mcu::UsbNrfDriver; pub type UsbDriver = mcu::UsbNrfDriver;
pub type DisplayI2c = mcu::I2cBus; pub type DisplayI2c = mcu::I2cBus;
pub type DisplayDriver = ssd1306::Ssd1306Async<
ssd1306::prelude::I2CInterface<DisplayI2c>,
ssd1306::size::DisplaySize128x64,
ssd1306::mode::BufferedGraphicsModeAsync<ssd1306::size::DisplaySize128x64>,
>;
pub async fn create_display(i2c: DisplayI2c) -> Option<DisplayDriver> {
use ssd1306::mode::DisplayConfigAsync;
use ssd1306::prelude::{Brightness, DisplayRotation};
use ssd1306::size::DisplaySize128x64;
use ssd1306::{I2CDisplayInterface, Ssd1306Async};
let interface = I2CDisplayInterface::new(i2c);
let mut display = Ssd1306Async::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
.into_buffered_graphics_mode();
embassy_time::Timer::after_millis(100).await;
if display.init().await.is_err() {
defmt::error!("SSD1306 display init failed");
return None;
}
let _ = display.set_brightness(Brightness::BRIGHTEST).await;
Some(display)
}
// ── Peripheral bundles ────────────────────────────────────────────── // ── Peripheral bundles ──────────────────────────────────────────────
pub struct RadioParts { pub struct RadioParts {
+14
View File
@@ -21,6 +21,20 @@ pub type RadioDriver = Sx126x<RadioSpiDevice, Iv, Sx1262>;
pub type UsbDriver = mcu::UsbNrfDriver; pub type UsbDriver = mcu::UsbNrfDriver;
pub type DisplayI2c = mcu::I2cBus; pub type DisplayI2c = mcu::I2cBus;
pub type DisplayDriver = crate::driver::sh1106::Sh1106<DisplayI2c>;
pub async fn create_display(i2c: DisplayI2c) -> Option<DisplayDriver> {
let mut display = crate::driver::sh1106::Sh1106::new(i2c, 0x3D);
embassy_time::Timer::after_millis(100).await;
if display.init().await.is_err() {
defmt::error!("SH1106 display init failed");
return None;
}
let _ = display.set_brightness(0xFF).await;
Some(display)
}
// ── Peripheral bundles ────────────────────────────────────────────── // ── Peripheral bundles ──────────────────────────────────────────────
pub struct RadioParts { pub struct RadioParts {
+3 -45
View File
@@ -123,52 +123,10 @@ pub async fn display_task(
mac: &mac_str, mac: &mac_str,
}; };
cfg_if::cfg_if! { let Some(mut display) = crate::board::create_display(parts.i2c).await else {
if #[cfg(feature = "wio_tracker_l1")] { defmt::error!("display init failed, giving up");
let mut display = crate::driver::sh1106::Sh1106::new(parts.i2c, 0x3D);
Timer::after_millis(100).await;
if display.init().await.is_err() {
defmt::error!("SH1106 init failed — retrying");
Timer::after_millis(500).await;
if display.init().await.is_err() {
defmt::error!("SH1106 init failed twice, giving up");
return; return;
} };
}
if display.set_brightness(0xFF).await.is_err() {
defmt::warn!("display brightness set failed");
}
} else {
use ssd1306::mode::DisplayConfigAsync;
use ssd1306::prelude::DisplayRotation;
use ssd1306::size::DisplaySize128x64;
use ssd1306::{I2CDisplayInterface, Ssd1306Async};
let interface = I2CDisplayInterface::new(parts.i2c);
let mut display = Ssd1306Async::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
.into_buffered_graphics_mode();
Timer::after_millis(100).await;
if display.init().await.is_err() {
defmt::error!("SSD1306 init failed — retrying");
Timer::after_millis(500).await;
if display.init().await.is_err() {
defmt::error!("SSD1306 init failed twice, giving up");
return;
}
}
if display
.set_brightness(ssd1306::prelude::Brightness::BRIGHTEST)
.await
.is_err()
{
defmt::warn!("display brightness set failed");
}
}
}
let mut state = DisplayState::new(); let mut state = DisplayState::new();
let Some(mut receiver) = status.receiver() else { let Some(mut receiver) = status.receiver() else {