feat: add Heltec V4, wire up V3/V4 peripherals, restructure entry point

- Add heltec_v4 board: ESP32-S3R2, SX1262, SSD1315 display, native USB,
  Vext on GPIO36 (active HIGH)
- Wire up heltec_v3 with real esp-hal peripherals (was a stub)
- V3 and V4 share radio/I2C pins, differ in Vext pin/polarity and
  display reset
- Restructure main.rs: cfg_if selects embassy_executor::main (Cortex-M)
  vs esp_hal_embassy::main (Xtensa) per board
- Display detection via SSD1306 init in display_task — boards always
  provide I2C bus, task exits gracefully if no display responds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
swaitsandClaude Opus 4.6 committed 2026-03-29 20:42:54 -06:00
1 parent 8649b2ec46
commit 110172ded7
6 files changed
+276 -22

No files matched your search

+17 -3
View File
@@ -15,7 +15,7 @@ use crate::channel::{CommandChannel, DisplayCommandChannel, ResponseChannel, Sta
cfg_if::cfg_if! {
if #[cfg(feature = "rak_4631")] {
use panic_probe as _;
} else if #[cfg(feature = "heltec_v3")] {
} else if #[cfg(any(feature = "heltec_v3", feature = "heltec_v4"))] {
use esp_backtrace as _;
}
}
@@ -25,8 +25,22 @@ static RESPONSES: ResponseChannel = ResponseChannel::new();
static STATUS: StatusWatch = StatusWatch::new();
static DISPLAY_COMMANDS: DisplayCommandChannel = DisplayCommandChannel::new();
#[embassy_executor::main]
async fn main(spawner: Spawner) {
// Entry point: each platform needs its own executor macro.
cfg_if::cfg_if! {
if #[cfg(feature = "rak_4631")] {
#[embassy_executor::main]
async fn main(spawner: Spawner) {
run(spawner).await;
}
} else if #[cfg(any(feature = "heltec_v3", feature = "heltec_v4"))] {
#[esp_hal_embassy::main]
async fn main(spawner: Spawner) {
run(spawner).await;
}
}
}
async fn run(spawner: Spawner) {
let board = board::Board::init();
let (radio, usb, display) = board.into_parts();