103 lines
3.3 KiB
Rust
103 lines
3.3 KiB
Rust
//! Heltec WiFi LoRa 32 V3 — native USB (requires hardware mod).
|
|
//!
|
|
//! Stock V3 boards route USB through a CP2102 bridge to UART. To use native
|
|
//! USB CDC-ACM, solder R29 (D+) and R3 (D-) on the PCB and disconnect the
|
|
//! CP2102 from the USB data lines. See the project README for details.
|
|
//!
|
|
//! For stock (unmodified) V3 boards, use the `heltec_v3_uart` feature instead.
|
|
|
|
use esp_hal::gpio::{Level, Output, OutputConfig};
|
|
use static_cell::StaticCell;
|
|
|
|
use super::esp32s3;
|
|
use super::traits::{BoardParts, LoRaBoard};
|
|
use crate::driver::simple_led::SimpleLed;
|
|
use crate::hal::esp32s3 as mcu;
|
|
|
|
pub use super::esp32s3::{create_display, DisplayDriver, DisplayParts, RadioDriver, RadioParts};
|
|
|
|
pub type UsbDriver = esp_hal::otg_fs::asynch::Driver<'static>;
|
|
pub type LedDriver = SimpleLed<Output<'static>>;
|
|
|
|
pub struct UsbParts {
|
|
pub driver: UsbDriver,
|
|
}
|
|
|
|
pub struct Board {
|
|
p: esp_hal::peripherals::Peripherals,
|
|
}
|
|
|
|
impl LoRaBoard for Board {
|
|
const NAME: &'static str = "Heltec V3";
|
|
const TX_POWER_RANGE: (i8, i8) = (-9, 22);
|
|
|
|
type RadioParts = RadioParts;
|
|
type CommParts = UsbParts;
|
|
type DisplayParts = DisplayParts;
|
|
type DisplayDriver = DisplayDriver;
|
|
type LedDriver = LedDriver;
|
|
|
|
fn init() -> Self {
|
|
let p = esp_hal::init(esp_hal::Config::default());
|
|
Self { p }
|
|
}
|
|
|
|
fn mac_address() -> [u8; 6] {
|
|
mcu::mac_address()
|
|
}
|
|
|
|
fn into_parts(self) -> BoardParts<RadioParts, UsbParts, DisplayParts, LedDriver> {
|
|
let p = self.p;
|
|
|
|
mcu::start_timer(p.TIMG0, p.SW_INTERRUPT);
|
|
|
|
// Vext power: GPIO36, active LOW to enable peripherals.
|
|
// Output has no Drop impl, so the pin stays configured for program lifetime.
|
|
let _vext = Output::new(p.GPIO36, Level::Low, OutputConfig::default());
|
|
|
|
let spi_bus = mcu::init_spi(p.SPI2, p.DMA_CH0, p.GPIO9, p.GPIO10, p.GPIO11);
|
|
let radio = esp32s3::init_radio(
|
|
spi_bus,
|
|
p.GPIO8,
|
|
p.GPIO12,
|
|
p.GPIO14,
|
|
p.GPIO13,
|
|
lora_phy::sx126x::TcxoCtrlVoltage::Ctrl1V8,
|
|
);
|
|
|
|
// Note: switches internal USB PHY from Serial-JTAG to OTG.
|
|
let usb_inst = esp_hal::otg_fs::Usb::new(p.USB0, p.GPIO20, p.GPIO19);
|
|
static EP_OUT_BUF: StaticCell<[u8; 1024]> = StaticCell::new();
|
|
let ep_out_buf = EP_OUT_BUF.init([0u8; 1024]);
|
|
let host = UsbParts {
|
|
driver: esp_hal::otg_fs::asynch::Driver::new(
|
|
usb_inst,
|
|
ep_out_buf,
|
|
esp_hal::otg_fs::asynch::Config::default(),
|
|
),
|
|
};
|
|
|
|
// SSD1306 display reset: pulse GPIO21 low->high before I2C init.
|
|
// Output has no Drop impl; pin stays HIGH after this block.
|
|
let mut display_rst = Output::new(p.GPIO21, Level::Low, OutputConfig::default());
|
|
esp_hal::delay::Delay::new().delay_millis(10);
|
|
display_rst.set_high();
|
|
esp_hal::delay::Delay::new().delay_millis(10);
|
|
|
|
let i2c = mcu::init_i2c(p.I2C0, p.GPIO17, p.GPIO18);
|
|
let display = Some(DisplayParts { i2c });
|
|
|
|
// White LED on GPIO35
|
|
let led_pin = Output::new(p.GPIO35, Level::Low, OutputConfig::default());
|
|
let led = SimpleLed(led_pin);
|
|
|
|
BoardParts {
|
|
radio,
|
|
host,
|
|
display,
|
|
led,
|
|
mac: Self::mac_address(),
|
|
}
|
|
}
|
|
}
|