- Added RgbLed trait with impl on () for boards without LED - Added WS2812 driver (driver/ws2812.rs) using ESP32-S3 RMT peripheral - 80MHz clock, 12.5ns resolution, 24-bit GRB encoding - Zero extra crate dependencies - Heltec V3/V3-UART/V4: WS2812B on GPIO38 via RMT channel 0 - RAK WisBlock/Wio Tracker: type LedDriver = (), led = None (no-op) - Display task: green blink on RX packet, red blink on TX packet - LED auto-off on timer tick (~1s), off when display is off/reset - LoRaBoard trait gains type LedDriver: RgbLed associated type - BoardParts gains led: Option<L> field
103 lines
2.7 KiB
Rust
103 lines
2.7 KiB
Rust
//! DongLoRa firmware — transparent LoRa radio over USB.
|
|
//!
|
|
//! Three async tasks communicate via static channels:
|
|
//!
|
|
//! ```text
|
|
//! host_task ──Command──► radio_task ──► SX1262
|
|
//! ◄──Response── │
|
|
//! StatusWatch
|
|
//! ▼
|
|
//! display_task (optional)
|
|
//! ```
|
|
//!
|
|
//! The host drives everything. The radio idles until commanded.
|
|
|
|
#![cfg_attr(not(test), no_std)]
|
|
#![cfg_attr(not(test), no_main)]
|
|
|
|
#[cfg(not(test))]
|
|
mod board;
|
|
#[cfg(not(test))]
|
|
mod channel;
|
|
#[cfg(not(test))]
|
|
mod display;
|
|
#[cfg(not(test))]
|
|
mod driver;
|
|
#[cfg(not(test))]
|
|
mod hal;
|
|
#[cfg(not(test))]
|
|
mod host;
|
|
mod protocol;
|
|
#[cfg(not(test))]
|
|
mod radio;
|
|
|
|
#[cfg(not(test))]
|
|
use embassy_executor::Spawner;
|
|
|
|
#[cfg(not(test))]
|
|
use crate::board::LoRaBoard;
|
|
#[cfg(not(test))]
|
|
use crate::channel::{CommandChannel, DisplayCommandChannel, ResponseChannel, StatusWatch};
|
|
|
|
#[cfg(not(test))]
|
|
cfg_if::cfg_if! {
|
|
if #[cfg(any(feature = "rak_wisblock_4631", feature = "wio_tracker_l1"))] {
|
|
use defmt_rtt as _;
|
|
use panic_probe as _;
|
|
} else if #[cfg(any(feature = "heltec_v3", feature = "heltec_v3_uart", feature = "heltec_v4"))] {
|
|
use esp_backtrace as _;
|
|
use esp_println as _;
|
|
}
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
static COMMANDS: CommandChannel = CommandChannel::new();
|
|
#[cfg(not(test))]
|
|
static RESPONSES: ResponseChannel = ResponseChannel::new();
|
|
#[cfg(not(test))]
|
|
static STATUS: StatusWatch = StatusWatch::new();
|
|
#[cfg(not(test))]
|
|
static DISPLAY_COMMANDS: DisplayCommandChannel = DisplayCommandChannel::new();
|
|
|
|
#[cfg(not(test))]
|
|
cfg_if::cfg_if! {
|
|
if #[cfg(any(feature = "rak_wisblock_4631", feature = "wio_tracker_l1"))] {
|
|
#[embassy_executor::main]
|
|
async fn main(spawner: Spawner) {
|
|
run(spawner).await;
|
|
}
|
|
} else if #[cfg(any(feature = "heltec_v3", feature = "heltec_v3_uart", feature = "heltec_v4"))] {
|
|
#[esp_rtos::main]
|
|
async fn main(spawner: Spawner) {
|
|
run(spawner).await;
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(not(test))]
|
|
async fn run(spawner: Spawner) {
|
|
let board = <board::Board as LoRaBoard>::init();
|
|
let parts = board.into_parts();
|
|
|
|
spawner
|
|
.spawn(radio::radio_task(parts.radio, &COMMANDS, &RESPONSES, &STATUS))
|
|
.expect("spawn radio_task");
|
|
|
|
spawner
|
|
.spawn(host::host_task(
|
|
parts.host,
|
|
&COMMANDS,
|
|
&RESPONSES,
|
|
&DISPLAY_COMMANDS,
|
|
parts.display.is_some(),
|
|
parts.mac,
|
|
))
|
|
.expect("spawn host_task");
|
|
|
|
if let Some(dp) = parts.display {
|
|
spawner
|
|
.spawn(display::display_task(dp, parts.led, &STATUS, &DISPLAY_COMMANDS))
|
|
.expect("spawn display_task");
|
|
}
|
|
}
|