fix: V4 also has plain LED on GPIO35, not WS2812 on GPIO38
Per the official V4 schematic (HTIT-WB32LAF_V4.3.pdf), the V4 has an orange LED on GPIO35 with a series resistor — same setup as V3. GPIO38 is GNSS_RX on V4, not an LED. Neither V3 nor V4 has a WS2812. - V4: switched from WS2812/GPIO38 to SimpleLed/GPIO35 - Removed ws2812.rs driver (no current board uses addressable LEDs) - All ESP boards now use the same SimpleLed driver on GPIO35
This commit is contained in:
3 files changed
+8
-86
No files matched your search
@@ -1,11 +1,9 @@
|
|||||||
use esp_hal::gpio::{Level, Output, OutputConfig};
|
use esp_hal::gpio::{Level, Output, OutputConfig};
|
||||||
use esp_hal::rmt::{Rmt, TxChannelConfig, TxChannelCreator};
|
|
||||||
use esp_hal::time::Rate;
|
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
|
|
||||||
use super::esp32s3;
|
use super::esp32s3;
|
||||||
use super::traits::{BoardParts, LoRaBoard};
|
use super::traits::{BoardParts, LoRaBoard};
|
||||||
use crate::driver::ws2812::Ws2812;
|
use crate::driver::simple_led::SimpleLed;
|
||||||
use crate::hal::esp32s3 as mcu;
|
use crate::hal::esp32s3 as mcu;
|
||||||
|
|
||||||
pub use super::esp32s3::{
|
pub use super::esp32s3::{
|
||||||
@@ -14,7 +12,7 @@ pub use super::esp32s3::{
|
|||||||
|
|
||||||
pub type UsbDriver = esp_hal::otg_fs::asynch::Driver<'static>;
|
pub type UsbDriver = esp_hal::otg_fs::asynch::Driver<'static>;
|
||||||
|
|
||||||
pub type LedDriver = Ws2812;
|
pub type LedDriver = SimpleLed;
|
||||||
|
|
||||||
pub struct UsbParts {
|
pub struct UsbParts {
|
||||||
pub driver: UsbDriver,
|
pub driver: UsbDriver,
|
||||||
@@ -32,7 +30,7 @@ impl LoRaBoard for Board {
|
|||||||
type CommParts = UsbParts;
|
type CommParts = UsbParts;
|
||||||
type DisplayParts = DisplayParts;
|
type DisplayParts = DisplayParts;
|
||||||
type DisplayDriver = DisplayDriver;
|
type DisplayDriver = DisplayDriver;
|
||||||
type LedDriver = Ws2812;
|
type LedDriver = LedDriver;
|
||||||
|
|
||||||
fn init() -> Self {
|
fn init() -> Self {
|
||||||
let p = esp_hal::init(esp_hal::Config::default());
|
let p = esp_hal::init(esp_hal::Config::default());
|
||||||
@@ -43,7 +41,7 @@ impl LoRaBoard for Board {
|
|||||||
mcu::mac_address()
|
mcu::mac_address()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_parts(self) -> BoardParts<RadioParts, UsbParts, DisplayParts, Ws2812> {
|
fn into_parts(self) -> BoardParts<RadioParts, UsbParts, DisplayParts, LedDriver> {
|
||||||
let p = self.p;
|
let p = self.p;
|
||||||
|
|
||||||
mcu::start_timer(p.TIMG0);
|
mcu::start_timer(p.TIMG0);
|
||||||
@@ -77,18 +75,9 @@ impl LoRaBoard for Board {
|
|||||||
let i2c = mcu::init_i2c(p.I2C0, p.GPIO17, p.GPIO18);
|
let i2c = mcu::init_i2c(p.I2C0, p.GPIO17, p.GPIO18);
|
||||||
let display = Some(DisplayParts { i2c });
|
let display = Some(DisplayParts { i2c });
|
||||||
|
|
||||||
// WS2812B RGB LED on GPIO38 via RMT channel 0 (blocking, ~31µs per update)
|
// Orange LED on GPIO35
|
||||||
let rmt = Rmt::new(p.RMT, Rate::from_mhz(80)).expect("RMT init");
|
let led_pin = Output::new(p.GPIO35, Level::Low, OutputConfig::default());
|
||||||
let led_channel = rmt
|
let led = Some(SimpleLed::new(led_pin));
|
||||||
.channel0
|
|
||||||
.configure_tx(
|
|
||||||
p.GPIO38,
|
|
||||||
TxChannelConfig::default()
|
|
||||||
.with_clk_divider(1)
|
|
||||||
.with_idle_output(true),
|
|
||||||
)
|
|
||||||
.expect("RMT TX channel init");
|
|
||||||
let led = Some(Ws2812::new(led_channel));
|
|
||||||
|
|
||||||
BoardParts {
|
BoardParts {
|
||||||
radio,
|
radio,
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
#[cfg(feature = "wio_tracker_l1")]
|
#[cfg(feature = "wio_tracker_l1")]
|
||||||
pub mod sh1106;
|
pub mod sh1106;
|
||||||
|
|
||||||
#[cfg(any(feature = "heltec_v3", feature = "heltec_v3_uart"))]
|
#[cfg(any(feature = "heltec_v3", feature = "heltec_v3_uart", feature = "heltec_v4"))]
|
||||||
pub mod simple_led;
|
pub mod simple_led;
|
||||||
|
|
||||||
#[cfg(feature = "heltec_v4")]
|
|
||||||
pub mod ws2812;
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
//! WS2812B single-LED driver using the ESP32-S3 RMT peripheral.
|
|
||||||
//!
|
|
||||||
//! Encodes RGB values as GRB PulseCodes and transmits via RMT.
|
|
||||||
//! At 80 MHz with divider=1, each tick is 12.5 ns.
|
|
||||||
//! Uses blocking transmit (~31µs per LED update).
|
|
||||||
|
|
||||||
use esp_hal::gpio::Level;
|
|
||||||
use esp_hal::rmt::{Channel, PulseCode, Tx};
|
|
||||||
|
|
||||||
use crate::board::RgbLed;
|
|
||||||
|
|
||||||
/// WS2812 0-bit: High 400ns (32 ticks), Low 850ns (68 ticks).
|
|
||||||
const BIT_0: PulseCode = PulseCode::new(Level::High, 32, Level::Low, 68);
|
|
||||||
|
|
||||||
/// WS2812 1-bit: High 800ns (64 ticks), Low 450ns (36 ticks).
|
|
||||||
const BIT_1: PulseCode = PulseCode::new(Level::High, 64, Level::Low, 36);
|
|
||||||
|
|
||||||
/// WS2812B single-LED driver over RMT (blocking).
|
|
||||||
pub struct Ws2812 {
|
|
||||||
channel: Option<Channel<'static, esp_hal::Blocking, Tx>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ws2812 {
|
|
||||||
pub fn new(channel: Channel<'static, esp_hal::Blocking, Tx>) -> Self {
|
|
||||||
Self {
|
|
||||||
channel: Some(channel),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encode 3 bytes (GRB order) + end marker into PulseCodes.
|
|
||||||
fn encode(r: u8, g: u8, b: u8) -> [PulseCode; 25] {
|
|
||||||
let mut data = [PulseCode::end_marker(); 25];
|
|
||||||
let bytes = [g, r, b]; // WS2812 expects GRB order
|
|
||||||
let mut idx = 0;
|
|
||||||
for byte in bytes {
|
|
||||||
for bit in (0..8).rev() {
|
|
||||||
data[idx] = if byte & (1 << bit) != 0 { BIT_1 } else { BIT_0 };
|
|
||||||
idx += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RgbLed for Ws2812 {
|
|
||||||
async fn set_rgb(&mut self, r: u8, g: u8, b: u8) {
|
|
||||||
let data = Self::encode(r, g, b);
|
|
||||||
if let Some(ch) = self.channel.take() {
|
|
||||||
match ch.transmit(&data) {
|
|
||||||
Ok(tx) => match tx.wait() {
|
|
||||||
Ok(ch) => self.channel = Some(ch),
|
|
||||||
Err((e, ch)) => {
|
|
||||||
defmt::warn!("WS2812 wait error: {}", e);
|
|
||||||
self.channel = Some(ch);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
defmt::warn!("WS2812 transmit error: {}", e);
|
|
||||||
// Channel consumed on transmit error — LED is lost
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user