Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `timer_interrupt` example in ESP32-H2 and refactor `clk_src` configuration (#576)
- Move `esp-riscv-rt` into esp-hal (#578)
- Add initial implementation of radio clocks for ESP32-H2 (#577)
- Add initial support for `esp-hal-smartled` in ESP32-H2 (#589)

### Changed

Expand Down
2 changes: 1 addition & 1 deletion esp-hal-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ esp32 = { version = "0.23.0", features = ["critical-section"], optional = true
esp32c2 = { version = "0.11.0", features = ["critical-section"], optional = true }
esp32c3 = { version = "0.14.0", features = ["critical-section"], optional = true }
esp32c6 = { version = "0.4.0", features = ["critical-section"], optional = true }
esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "8903688", package = "esp32h2", features = ["critical-section"], optional = true }
esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "4a55004", package = "esp32h2", features = ["critical-section"], optional = true }
esp32s2 = { version = "0.14.0", features = ["critical-section"], optional = true }
esp32s3 = { version = "0.18.0", features = ["critical-section"], optional = true }

Expand Down
43 changes: 35 additions & 8 deletions esp-hal-common/src/pulse_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
//! * The **ESP32-C6** has 4 channels, `Channel0` and `Channel1` hardcoded for
//! transmitting signals and `Channel2` and `Channel3` hardcoded for receiving
//! signals.
//! * The **ESP32-H2** has 4 channels, `Channel0` and `Channel1` hardcoded for
//! transmitting signals and `Channel2` and `Channel3` hardcoded for receiving
//! signals.
//! * The **ESP32-S2** has 4 channels, each of them can be either receiver or
//! transmitter.
//! * The **ESP32-S3** has 8 channels, `Channel0`-`Channel3` hardcdoded for
Expand Down Expand Up @@ -86,7 +89,7 @@ use core::slice::Iter;
use fugit::NanosDurationU32;
pub use paste::paste;

#[cfg(esp32c6)]
#[cfg(any(esp32c6, esp32h2))]
use crate::peripherals::PCR;
use crate::{
gpio::{OutputPin, OutputSignal},
Expand Down Expand Up @@ -150,6 +153,17 @@ pub enum ClockSource {
RTC20M = 1,
}

// Clock source to bool
#[cfg(esp32h2)]
impl Into<bool> for ClockSource {
fn into(self) -> bool {
match self {
ClockSource::XTAL => false,
ClockSource::RTC20M => true,
}
}
}

/// Specify the clock source for the RMT peripheral on the ESP32 and ESP32-S3
/// variants
#[cfg(any(esp32s2, esp32))]
Expand All @@ -165,7 +179,7 @@ pub enum ClockSource {
// to the RMT channel
#[cfg(any(esp32s2, esp32))]
const CHANNEL_RAM_SIZE: u8 = 64;
#[cfg(any(esp32c3, esp32c6, esp32s3, esp32h2))]
#[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))]
const CHANNEL_RAM_SIZE: u8 = 48;

// Specifies where the RMT RAM section starts for the particular ESP32 variant
Expand Down Expand Up @@ -302,7 +316,7 @@ macro_rules! channel_instance {
let mut channel = $cxi { mem_offset: 0 };

cfg_if::cfg_if! {
if #[cfg(any(esp32c3, esp32c6, esp32s3, esp32h2))] {
if #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] {
// Apply default configuration
unsafe { &*RMT::PTR }.ch_tx_conf0[$num].modify(|_, w| unsafe {
// Configure memory block size
Expand Down Expand Up @@ -653,7 +667,7 @@ macro_rules! channel_instance {
#[cfg(not(esp32h2))]
unsafe { interrupts.ch_tx_thr_event_int_raw($num).bit() },
#[cfg(esp32h2)]
interrupts.[<ch $num _tx_err_int_raw>]().bit(),
interrupts.[<ch $num _tx_err_int_raw>]().bit(),
#[cfg(esp32h2)]
interrupts.[<ch $num _tx_thr_event_int_raw>]().bit(),
))
Expand Down Expand Up @@ -962,10 +976,10 @@ macro_rules! rmt {

// Configure peripheral

#[cfg(esp32c6)]
#[cfg(any(esp32c6, esp32h2))]
let pcr = unsafe { &*PCR::ptr() };

#[cfg(esp32c6)]
#[cfg(any(esp32c6, esp32h2))]
pcr.rmt_sclk_conf.write(|w| w.sclk_en().set_bit());


Expand All @@ -986,7 +1000,7 @@ macro_rules! rmt {
.apb_fifo_mask()
.set_bit());
// Select clock source
#[cfg(not(esp32c6))]
#[cfg(not(any(esp32c6, esp32h2)))]
self.reg.sys_conf.modify(|_, w| unsafe {
w.sclk_sel()
.bits(clk_source as u8)
Expand All @@ -1010,7 +1024,20 @@ macro_rules! rmt {
.bits(div_frac_a)
.sclk_div_b()
.bits(div_frac_b)
});
});
#[cfg(esp32h2)]
pcr.rmt_sclk_conf.modify(|_,w| unsafe {
w.sclk_sel()
.bit(clk_source.into())
// Set absolute part of divider
.sclk_div_num()
.bits(div_abs)
// Set fractional parts of divider to 0
.sclk_div_a()
.bits(div_frac_a)
.sclk_div_b()
.bits(div_frac_b)
});

// Disable all interrupts
self.reg.int_ena.write(|w| unsafe { w.bits(0) });
Expand Down
2 changes: 1 addition & 1 deletion esp-hal-smartled/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const SOURCE_CLK_FREQ: u32 = 40_000_000;
#[cfg(feature = "esp32c6")]
const SOURCE_CLK_FREQ: u32 = 40_000_000;
#[cfg(feature = "esp32h2")]
const SOURCE_CLK_FREQ: u32 = 40_000_000;
const SOURCE_CLK_FREQ: u32 = 16_000_000;
#[cfg(feature = "esp32s2")]
const SOURCE_CLK_FREQ: u32 = 40_000_000;
#[cfg(feature = "esp32s3")]
Expand Down
2 changes: 1 addition & 1 deletion esp32h2-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ crypto-bigint = { version = "0.5.2", default-features = false }
embassy-executor = { version = "0.2.0", features = ["nightly", "integrated-timers", "arch-riscv32", "executor-thread"] }
embedded-graphics = "0.7.1"
esp-backtrace = { version = "0.7.0", features = ["esp32h2", "panic-handler", "exception-handler", "print-uart"] }
# esp-hal-smartled = { version = "0.1.0", features = ["esp32h2"], path = "../esp-hal-smartled" }
esp-hal-smartled = { version = "0.2.0", features = ["esp32h2"], path = "../esp-hal-smartled" }
esp-println = { version = "0.5.0", features = ["esp32h2"] }
lis3dh-async = "0.7.0"
sha2 = { version = "0.10.6", default-features = false}
Expand Down
103 changes: 103 additions & 0 deletions esp32h2-hal/examples/hello_rgb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//! //! RGB LED Demo
//!
//! This example drives an SK68XX RGB LED that is connected to the GPIO8 pin.
//! A RGB LED is connected to that pin on the ESP32-H2-DevKitM-1 and board.
//!
//! The demo will leverage the [`smart_leds`](https://crates.io/crates/smart-leds)
//! crate functionality to circle through the HSV hue color space (with
//! saturation and value both at 255). Additionally, we apply a gamma correction
//! and limit the brightness to 10 (out of 255).
#![no_std]
#![no_main]

use esp32h2_hal::{
clock::ClockControl,
peripherals,
prelude::*,
pulse_control::ClockSource,
timer::TimerGroup,
Delay,
PulseControl,
Rtc,
IO,
};
use esp_backtrace as _;
use esp_hal_smartled::{smartLedAdapter, SmartLedsAdapter};
use smart_leds::{
brightness,
gamma,
hsv::{hsv2rgb, Hsv},
SmartLedsWrite,
};

#[entry]
fn main() -> ! {
let peripherals = peripherals::Peripherals::take();
let mut system = peripherals.PCR.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

// Disable the watchdog timers. For the ESP32-H2, this includes the Super WDT,
// and the TIMG WDTs.
let mut rtc = Rtc::new(peripherals.LP_CLKRST);
let timer_group0 = TimerGroup::new(
peripherals.TIMG0,
&clocks,
&mut system.peripheral_clock_control,
);
let mut wdt0 = timer_group0.wdt;
let timer_group1 = TimerGroup::new(
peripherals.TIMG1,
&clocks,
&mut system.peripheral_clock_control,
);
let mut wdt1 = timer_group1.wdt;

// Disable watchdog timers
rtc.swd.disable();
rtc.rwdt.disable();
wdt0.disable();
wdt1.disable();

// Configure RMT peripheral globally
let pulse = PulseControl::new(
peripherals.RMT,
&mut system.peripheral_clock_control,
ClockSource::XTAL,
0,
0,
0,
)
.unwrap();

// We use one of the RMT channels to instantiate a `SmartLedsAdapter` which can
// be used directly with all `smart_led` implementations
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let mut led = <smartLedAdapter!(1)>::new(pulse.channel0, io.pins.gpio8);

// Initialize the Delay peripheral, and use it to toggle the LED state in a
// loop.
let mut delay = Delay::new(&clocks);

let mut color = Hsv {
hue: 0,
sat: 255,
val: 255,
};
let mut data;

loop {
// Iterate over the rainbow!
for hue in 0..=255 {
color.hue = hue;
// Convert from the HSV color space (where we can easily transition from one
// color to the other) to the RGB color space that we can then send to the LED
data = [hsv2rgb(color)];
// When sending to the LED, we do a gamma correction first (see smart_leds
// documentation for details) and then limit the brightness to 10 out of 255 so
// that the output it's not too bright.
led.write(brightness(gamma(data.iter().cloned()), 10))
.unwrap();
delay.delay_ms(20u8);
}
}
}