Add RMT output channel support for all current ESP32 variants
- Add RMT output channel support for ESP32, ESP32-S2, ESP32-S3, ESP32-C3 - Add add RMT adapter for `smart-leds` crate - Add example `hello_rgb` for ESP32-S2, ESP32-S3 and ESP32-C3 that either drives one LED at the pin where a LED is located on the official devkits - Add example `hello_rgb` for ESP32 that is driving a 12-element RGB ring.
This commit is contained in:
parent
a2afa6cbbe
commit
a55c9d77ec
@ -29,6 +29,10 @@ xtensa-lx-rt = { version = "0.11", optional = true }
|
|||||||
# Part of `ufmt` containing only `uWrite` trait
|
# Part of `ufmt` containing only `uWrite` trait
|
||||||
ufmt-write = { version = "0.1", optional = true }
|
ufmt-write = { version = "0.1", optional = true }
|
||||||
|
|
||||||
|
# Smart-LED (e.g., WS2812/SK68XX) support
|
||||||
|
smart-leds-trait = { version = "0.2.1", optional = true }
|
||||||
|
|
||||||
|
|
||||||
# IMPORTANT:
|
# IMPORTANT:
|
||||||
# Each supported device MUST have its PAC included below along with a
|
# Each supported device MUST have its PAC included below along with a
|
||||||
# corresponding feature. We rename the PAC packages because we cannot
|
# corresponding feature. We rename the PAC packages because we cannot
|
||||||
@ -39,10 +43,10 @@ esp32s2_pac = { package = "esp32s2", git = "https://github.com/esp-rs/esp-pacs.g
|
|||||||
esp32s3_pac = { package = "esp32s3", git = "https://github.com/esp-rs/esp-pacs.git", branch = "with_source", optional = true }
|
esp32s3_pac = { package = "esp32s3", git = "https://github.com/esp-rs/esp-pacs.git", branch = "with_source", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
esp32 = [ "esp32_pac/rt", "xtensa", "dual_core", "xtensa-lx-rt/esp32", "xtensa-lx/esp32"]
|
esp32 = [ "esp32_pac/rt", "xtensa", "dual_core", "xtensa-lx-rt/esp32", "xtensa-lx/esp32", "smartled"]
|
||||||
esp32c3 = ["esp32c3_pac/rt", "risc_v", "single_core"]
|
esp32c3 = ["esp32c3_pac/rt", "risc_v", "single_core", "smartled"]
|
||||||
esp32s2 = ["esp32s2_pac/rt", "xtensa", "single_core", "xtensa-lx-rt/esp32s2", "xtensa-lx/esp32s2"]
|
esp32s2 = ["esp32s2_pac/rt", "xtensa", "single_core", "xtensa-lx-rt/esp32s2", "xtensa-lx/esp32s2", "smartled"]
|
||||||
esp32s3 = ["esp32s3_pac/rt", "xtensa", "dual_core", "xtensa-lx-rt/esp32s3", "xtensa-lx/esp32s3"]
|
esp32s3 = ["esp32s3_pac/rt", "xtensa", "dual_core", "xtensa-lx-rt/esp32s3", "xtensa-lx/esp32s3", "smartled"]
|
||||||
|
|
||||||
# Architecture (should not be enabled directly, but instead by a PAC's feature)
|
# Architecture (should not be enabled directly, but instead by a PAC's feature)
|
||||||
risc_v = ["riscv", "riscv-atomic-emulation-trap"]
|
risc_v = ["riscv", "riscv-atomic-emulation-trap"]
|
||||||
@ -54,3 +58,6 @@ dual_core = []
|
|||||||
|
|
||||||
# To support `ufmt`
|
# To support `ufmt`
|
||||||
ufmt = ["ufmt-write"]
|
ufmt = ["ufmt-write"]
|
||||||
|
|
||||||
|
# To use the external `smart_led` crate
|
||||||
|
smartled = ["smart-leds-trait"]
|
||||||
@ -37,6 +37,10 @@ pub enum InputSignal {
|
|||||||
SPI3_D = 74,
|
SPI3_D = 74,
|
||||||
SPI3_HD = 75,
|
SPI3_HD = 75,
|
||||||
SPI3_CS0 = 76,
|
SPI3_CS0 = 76,
|
||||||
|
RMT_SIG_IN0 = 83,
|
||||||
|
RMT_SIG_IN1 = 84,
|
||||||
|
RMT_SIG_IN2 = 85,
|
||||||
|
RMT_SIG_IN3 = 86,
|
||||||
I2CEXT1_SCL = 95,
|
I2CEXT1_SCL = 95,
|
||||||
I2CEXT1_SDA = 96,
|
I2CEXT1_SDA = 96,
|
||||||
FSPICLK = 108,
|
FSPICLK = 108,
|
||||||
@ -98,6 +102,10 @@ pub enum OutputSignal {
|
|||||||
SPI3_CS0 = 76,
|
SPI3_CS0 = 76,
|
||||||
SPI3_CS1 = 77,
|
SPI3_CS1 = 77,
|
||||||
SPI3_CS2 = 78,
|
SPI3_CS2 = 78,
|
||||||
|
RMT_SIG_OUT0 = 87,
|
||||||
|
RMT_SIG_OUT1 = 88,
|
||||||
|
RMT_SIG_OUT2 = 89,
|
||||||
|
RMT_SIG_OUT3 = 90,
|
||||||
I2CEXT1_SCL = 95,
|
I2CEXT1_SCL = 95,
|
||||||
I2CEXT1_SDA = 96,
|
I2CEXT1_SDA = 96,
|
||||||
GPIO_SD0 = 100,
|
GPIO_SD0 = 100,
|
||||||
|
|||||||
@ -50,6 +50,10 @@ pub enum InputSignal {
|
|||||||
SPI3_HD = 69,
|
SPI3_HD = 69,
|
||||||
SPI3_WP = 70,
|
SPI3_WP = 70,
|
||||||
SPI3_CS0 = 71,
|
SPI3_CS0 = 71,
|
||||||
|
RMT_SIG_IN0 = 81,
|
||||||
|
RMT_SIG_IN1 = 82,
|
||||||
|
RMT_SIG_IN2 = 83,
|
||||||
|
RMT_SIG_IN3 = 84,
|
||||||
I2CEXT0_SCL = 89,
|
I2CEXT0_SCL = 89,
|
||||||
I2CEXT0_SDA = 90,
|
I2CEXT0_SDA = 90,
|
||||||
I2CEXT1_SCL = 91,
|
I2CEXT1_SCL = 91,
|
||||||
@ -139,6 +143,10 @@ pub enum OutputSignal {
|
|||||||
SPI3_WP = 70,
|
SPI3_WP = 70,
|
||||||
SPI3_CS0 = 71,
|
SPI3_CS0 = 71,
|
||||||
SPI3_CS1 = 72,
|
SPI3_CS1 = 72,
|
||||||
|
RMT_SIG_OUT0 = 81,
|
||||||
|
RMT_SIG_OUT1 = 82,
|
||||||
|
RMT_SIG_OUT2 = 83,
|
||||||
|
RMT_SIG_OUT3 = 84,
|
||||||
I2CEXT0_SCL = 89,
|
I2CEXT0_SCL = 89,
|
||||||
I2CEXT0_SDA = 90,
|
I2CEXT0_SDA = 90,
|
||||||
I2CEXT1_SCL = 91,
|
I2CEXT1_SCL = 91,
|
||||||
|
|||||||
@ -34,6 +34,7 @@ pub mod i2c;
|
|||||||
#[cfg_attr(feature = "xtensa", path = "interrupt/xtensa.rs")]
|
#[cfg_attr(feature = "xtensa", path = "interrupt/xtensa.rs")]
|
||||||
pub mod interrupt;
|
pub mod interrupt;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
pub mod pulse_control;
|
||||||
pub mod rng;
|
pub mod rng;
|
||||||
#[cfg(not(feature = "esp32c3"))]
|
#[cfg(not(feature = "esp32c3"))]
|
||||||
pub mod rtc_cntl;
|
pub mod rtc_cntl;
|
||||||
@ -42,11 +43,13 @@ pub mod spi;
|
|||||||
pub mod timer;
|
pub mod timer;
|
||||||
#[cfg(any(feature = "esp32c3", feature = "esp32s3"))]
|
#[cfg(any(feature = "esp32c3", feature = "esp32s3"))]
|
||||||
pub mod usb_serial_jtag;
|
pub mod usb_serial_jtag;
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
pub use delay::Delay;
|
pub use delay::Delay;
|
||||||
pub use gpio::*;
|
pub use gpio::*;
|
||||||
pub use interrupt::*;
|
pub use interrupt::*;
|
||||||
pub use procmacros::ram;
|
pub use procmacros::ram;
|
||||||
|
pub use pulse_control::PulseControl;
|
||||||
pub use rng::Rng;
|
pub use rng::Rng;
|
||||||
#[cfg(not(feature = "esp32c3"))]
|
#[cfg(not(feature = "esp32c3"))]
|
||||||
pub use rtc_cntl::RtcCntl;
|
pub use rtc_cntl::RtcCntl;
|
||||||
|
|||||||
1045
esp-hal-common/src/pulse_control.rs
Normal file
1045
esp-hal-common/src/pulse_control.rs
Normal file
File diff suppressed because it is too large
Load Diff
12
esp-hal-common/src/utils/mod.rs
Normal file
12
esp-hal-common/src/utils/mod.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//! Helper Utils
|
||||||
|
|
||||||
|
// Only provide adapter when feature is enabled!
|
||||||
|
#[cfg(feature = "smartled")]
|
||||||
|
pub mod smart_leds_adapter;
|
||||||
|
#[cfg(feature = "smartled")]
|
||||||
|
pub use smart_leds_adapter::SmartLedsAdapter;
|
||||||
|
|
||||||
|
// Re-export the macro that due to the macro_export configuration was already exported
|
||||||
|
// in the root module (i.e., `esp-hal-common`)
|
||||||
|
#[cfg(feature = "smartled")]
|
||||||
|
pub use crate::smartLedAdapter;
|
||||||
202
esp-hal-common/src/utils/smart_leds_adapter.rs
Normal file
202
esp-hal-common/src/utils/smart_leds_adapter.rs
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
//! # Smart-LEDs RMT Adapter
|
||||||
|
//!
|
||||||
|
//! This adapter allows for the use of an RMT output channel to easily interact
|
||||||
|
//! with RGB LEDs and use the convenience functions of the external
|
||||||
|
//! [`smart-leds`](https://crates.io/crates/smart-leds) crate.
|
||||||
|
//!
|
||||||
|
//! _This is a simple implementation where every LED is adressed in an
|
||||||
|
//! individual RMT operation. This is working perfectly fine in blocking mode,
|
||||||
|
//! but in case this is used in combination with interrupts that might disturb
|
||||||
|
//! the sequential sending, an alternative implementation (addressing the LEDs
|
||||||
|
//! in a sequence in a single RMT send operation) might be required!_
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
use core::{marker::PhantomData, slice::IterMut};
|
||||||
|
|
||||||
|
use smart_leds_trait::{SmartLedsWrite, RGB8};
|
||||||
|
|
||||||
|
#[cfg(any(feature = "esp32", feature = "esp32s2"))]
|
||||||
|
use crate::pulse_control::ClockSource;
|
||||||
|
use crate::{
|
||||||
|
gpio::{types::OutputSignal, OutputPin},
|
||||||
|
pulse_control::{OutputChannel, PulseCode, RepeatMode, TransmissionError},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specifies what clock frequency we're using for the RMT peripheral (if
|
||||||
|
// properly configured)
|
||||||
|
//
|
||||||
|
// TODO: Factor in clock configuration, this needs to be revisited once #24 and
|
||||||
|
// #44 have been addressed.
|
||||||
|
#[cfg(feature = "esp32c3")]
|
||||||
|
const SOURCE_CLK_FREQ: u32 = 40_000_000;
|
||||||
|
#[cfg(feature = "esp32s2")]
|
||||||
|
const SOURCE_CLK_FREQ: u32 = 40_000_000;
|
||||||
|
#[cfg(feature = "esp32")]
|
||||||
|
const SOURCE_CLK_FREQ: u32 = 40_000_000;
|
||||||
|
#[cfg(feature = "esp32s3")]
|
||||||
|
const SOURCE_CLK_FREQ: u32 = 40_000_000;
|
||||||
|
|
||||||
|
const SK68XX_CODE_PERIOD: u32 = 1200;
|
||||||
|
const SK68XX_T0H_NS: u32 = 320;
|
||||||
|
const SK68XX_T0L_NS: u32 = SK68XX_CODE_PERIOD - SK68XX_T0H_NS;
|
||||||
|
const SK68XX_T1H_NS: u32 = 640;
|
||||||
|
const SK68XX_T1L_NS: u32 = SK68XX_CODE_PERIOD - SK68XX_T1H_NS;
|
||||||
|
|
||||||
|
const SK68XX_T0H_CYCLES: u16 = ((SK68XX_T0H_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500) as u16;
|
||||||
|
const SK68XX_T0L_CYCLES: u16 = ((SK68XX_T0L_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500) as u16;
|
||||||
|
const SK68XX_T1H_CYCLES: u16 = ((SK68XX_T1H_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500) as u16;
|
||||||
|
const SK68XX_T1L_CYCLES: u16 = ((SK68XX_T1L_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500) as u16;
|
||||||
|
|
||||||
|
/// All types of errors that can happen during the conversion and transmission
|
||||||
|
/// of LED commands
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum LedAdapterError {
|
||||||
|
/// Raised in the event that the provided data container is not large enough
|
||||||
|
BufferSizeExceeded,
|
||||||
|
/// Raised if something goes wrong in the transmission,
|
||||||
|
TransmissionError(TransmissionError),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Macro to generate adapters with an arbitrary buffer size fitting for a
|
||||||
|
/// specific number of `$buffer_size` LEDs to be addressed. Attempting to use
|
||||||
|
/// more LEDs that the buffer is configured for will result in an
|
||||||
|
/// `LedAdapterError:BufferSizeExceeded` error.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! smartLedAdapter {
|
||||||
|
($buffer_size: literal ) => {
|
||||||
|
// The size we're assigning here is calculated as following
|
||||||
|
// (
|
||||||
|
// Nr. of LEDs
|
||||||
|
// * channels (r,g,b -> 3)
|
||||||
|
// * pulses per channel 8)
|
||||||
|
// ) + 1 additional pulse for the end delimiter
|
||||||
|
SmartLedsAdapter::<_, _, { $buffer_size * 24 + 1 }>
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adapter taking an RMT channel and a specific pin and providing RGB LED
|
||||||
|
/// interaction functionality using the `smart-leds` crate
|
||||||
|
pub struct SmartLedsAdapter<CHANNEL, PIN, const BUFFER_SIZE: usize> {
|
||||||
|
channel: CHANNEL,
|
||||||
|
rmt_buffer: [u32; BUFFER_SIZE],
|
||||||
|
_pin: PhantomData<PIN>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CHANNEL, PIN, const BUFFER_SIZE: usize> SmartLedsAdapter<CHANNEL, PIN, BUFFER_SIZE>
|
||||||
|
where
|
||||||
|
CHANNEL: OutputChannel,
|
||||||
|
PIN: OutputPin<OutputSignal = OutputSignal>,
|
||||||
|
{
|
||||||
|
/// Create a new adapter object that drives the pin using the RMT channel.
|
||||||
|
pub fn new(mut channel: CHANNEL, pin: PIN) -> SmartLedsAdapter<CHANNEL, PIN, BUFFER_SIZE> {
|
||||||
|
#[cfg(any(feature = "esp32c3", feature = "esp32s3"))]
|
||||||
|
channel
|
||||||
|
.set_idle_output_level(false)
|
||||||
|
.set_carrier_modulation(false)
|
||||||
|
.set_channel_divider(1)
|
||||||
|
.set_idle_output(true);
|
||||||
|
|
||||||
|
#[cfg(any(feature = "esp32", feature = "esp32s2"))]
|
||||||
|
channel
|
||||||
|
.set_idle_output_level(false)
|
||||||
|
.set_carrier_modulation(false)
|
||||||
|
.set_channel_divider(1)
|
||||||
|
.set_idle_output(true)
|
||||||
|
.set_clock_source(ClockSource::APB);
|
||||||
|
|
||||||
|
channel.assign_pin(pin);
|
||||||
|
Self {
|
||||||
|
channel,
|
||||||
|
rmt_buffer: [0; BUFFER_SIZE],
|
||||||
|
_pin: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_rgb_to_pulse(
|
||||||
|
value: RGB8,
|
||||||
|
mut_iter: &mut IterMut<u32>,
|
||||||
|
) -> Result<(), LedAdapterError> {
|
||||||
|
SmartLedsAdapter::<CHANNEL, PIN, BUFFER_SIZE>::convert_rgb_channel_to_pulses(
|
||||||
|
value.g, mut_iter,
|
||||||
|
)?;
|
||||||
|
SmartLedsAdapter::<CHANNEL, PIN, BUFFER_SIZE>::convert_rgb_channel_to_pulses(
|
||||||
|
value.r, mut_iter,
|
||||||
|
)?;
|
||||||
|
SmartLedsAdapter::<CHANNEL, PIN, BUFFER_SIZE>::convert_rgb_channel_to_pulses(
|
||||||
|
value.b, mut_iter,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_rgb_channel_to_pulses(
|
||||||
|
channel_value: u8,
|
||||||
|
mut_iter: &mut IterMut<u32>,
|
||||||
|
) -> Result<(), LedAdapterError> {
|
||||||
|
for position in [128, 64, 32, 16, 8, 4, 2, 1] {
|
||||||
|
*mut_iter.next().ok_or(LedAdapterError::BufferSizeExceeded)? =
|
||||||
|
match channel_value & position {
|
||||||
|
0 => PulseCode {
|
||||||
|
level1: true,
|
||||||
|
length1: SK68XX_T0H_CYCLES,
|
||||||
|
level2: false,
|
||||||
|
length2: SK68XX_T0L_CYCLES,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
_ => PulseCode {
|
||||||
|
level1: true,
|
||||||
|
length1: SK68XX_T1H_CYCLES,
|
||||||
|
level2: false,
|
||||||
|
length2: SK68XX_T1L_CYCLES,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CHANNEL, PIN, const BUFFER_SIZE: usize> SmartLedsWrite
|
||||||
|
for SmartLedsAdapter<CHANNEL, PIN, BUFFER_SIZE>
|
||||||
|
where
|
||||||
|
CHANNEL: OutputChannel,
|
||||||
|
PIN: OutputPin<OutputSignal = OutputSignal>,
|
||||||
|
{
|
||||||
|
type Error = LedAdapterError;
|
||||||
|
type Color = RGB8;
|
||||||
|
|
||||||
|
/// Convert all RGB8 items of the iterator to the RMT format and
|
||||||
|
/// add them to internal buffer. Then start a singular RMT operation
|
||||||
|
/// based on that buffer.
|
||||||
|
fn write<T, I>(&mut self, iterator: T) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
T: Iterator<Item = I>,
|
||||||
|
I: Into<Self::Color>,
|
||||||
|
{
|
||||||
|
// We always start from the beginning of the buffer
|
||||||
|
let mut seq_iter = self.rmt_buffer.iter_mut();
|
||||||
|
|
||||||
|
// Add all converted iterator items to the buffer.
|
||||||
|
// This will result in an `BufferSizeExceeded` error in case
|
||||||
|
// the iterator provides more elements than the buffer can take.
|
||||||
|
for item in iterator {
|
||||||
|
SmartLedsAdapter::<CHANNEL, PIN, BUFFER_SIZE>::convert_rgb_to_pulse(
|
||||||
|
item.into(),
|
||||||
|
&mut seq_iter,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, add an end element.
|
||||||
|
*seq_iter.next().ok_or(LedAdapterError::BufferSizeExceeded)? = 0;
|
||||||
|
|
||||||
|
// Perform the actual RMT operation. We use the u32 values here right away.
|
||||||
|
match self
|
||||||
|
.channel
|
||||||
|
.send_pulse_sequence_raw(RepeatMode::SingleShot, &self.rmt_buffer)
|
||||||
|
{
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(x) => Err(LedAdapterError::TransmissionError(x)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,6 +39,7 @@ features = ["esp32"]
|
|||||||
embedded-graphics = "0.7"
|
embedded-graphics = "0.7"
|
||||||
panic-halt = "0.2"
|
panic-halt = "0.2"
|
||||||
ssd1306 = "0.7"
|
ssd1306 = "0.7"
|
||||||
|
smart-leds = "0.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt"]
|
default = ["rt"]
|
||||||
|
|||||||
88
esp32-hal/examples/hello_rgb.rs
Normal file
88
esp32-hal/examples/hello_rgb.rs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
//! RGB LED Demo
|
||||||
|
//!
|
||||||
|
//! This example drives an 12-element RGB ring that is connected to GPIO33
|
||||||
|
//!
|
||||||
|
//! The LEDs in the ring are transitioning though the HSV color spectrum for
|
||||||
|
//! - Saturation: 255
|
||||||
|
//! - Hue: 0 - 255
|
||||||
|
//! - Value: 255
|
||||||
|
//!
|
||||||
|
//! For the 12-element RGB ring to work, building the release version is going
|
||||||
|
//! to be required.
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use esp32_hal::{
|
||||||
|
pac,
|
||||||
|
prelude::*,
|
||||||
|
utils::{smartLedAdapter, SmartLedsAdapter},
|
||||||
|
Delay,
|
||||||
|
PulseControl,
|
||||||
|
RtcCntl,
|
||||||
|
Timer,
|
||||||
|
IO,
|
||||||
|
};
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use panic_halt as _;
|
||||||
|
use smart_leds::{
|
||||||
|
brightness,
|
||||||
|
gamma,
|
||||||
|
hsv::{hsv2rgb, Hsv},
|
||||||
|
SmartLedsWrite,
|
||||||
|
};
|
||||||
|
use xtensa_lx_rt::entry;
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let mut peripherals = pac::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||||
|
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||||
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
// Disable MWDT and RWDT (Watchdog) flash boot protection
|
||||||
|
timer0.disable();
|
||||||
|
rtc_cntl.set_wdt_global_enable(false);
|
||||||
|
|
||||||
|
// Configure RMT peripheral globally
|
||||||
|
let pulse = PulseControl::new(peripherals.RMT, &mut peripherals.DPORT).unwrap();
|
||||||
|
|
||||||
|
// We use one of the RMT channels to instantiate a `SmartLedsAdapter` which can
|
||||||
|
// be used directly with all `smart_led` implementations
|
||||||
|
// -> We need to use the macro `smartLedAdapter!` with the number of addressed
|
||||||
|
// LEDs here to initialize the internal LED pulse buffer to the correct
|
||||||
|
// size!
|
||||||
|
let mut led = <smartLedAdapter!(12)>::new(pulse.channel0, io.pins.gpio33);
|
||||||
|
|
||||||
|
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||||
|
// loop.
|
||||||
|
let mut delay = Delay::new();
|
||||||
|
|
||||||
|
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
|
||||||
|
let rgb_color = hsv2rgb(color);
|
||||||
|
|
||||||
|
// Assign new color to all 12 LEDs
|
||||||
|
data = [rgb_color; 12];
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,10 +6,13 @@ pub use esp_hal_common::{
|
|||||||
interrupt,
|
interrupt,
|
||||||
pac,
|
pac,
|
||||||
prelude,
|
prelude,
|
||||||
|
pulse_control,
|
||||||
ram,
|
ram,
|
||||||
spi,
|
spi,
|
||||||
|
utils,
|
||||||
Cpu,
|
Cpu,
|
||||||
Delay,
|
Delay,
|
||||||
|
PulseControl,
|
||||||
Rng,
|
Rng,
|
||||||
RtcCntl,
|
RtcCntl,
|
||||||
Serial,
|
Serial,
|
||||||
|
|||||||
@ -40,6 +40,7 @@ features = ["esp32c3"]
|
|||||||
embedded-graphics = "0.7"
|
embedded-graphics = "0.7"
|
||||||
panic-halt = "0.2"
|
panic-halt = "0.2"
|
||||||
ssd1306 = "0.7"
|
ssd1306 = "0.7"
|
||||||
|
smart-leds = "0.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt"]
|
default = ["rt"]
|
||||||
|
|||||||
89
esp32c3-hal/examples/hello_rgb.rs
Normal file
89
esp32c3-hal/examples/hello_rgb.rs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
//! //! 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-C3-DevKitM-1 and
|
||||||
|
//! ESP32-C3-DevKitC-02 boards.
|
||||||
|
//!
|
||||||
|
//! 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 esp32c3_hal::{
|
||||||
|
pac,
|
||||||
|
prelude::*,
|
||||||
|
pulse_control::ClockSource,
|
||||||
|
utils::{smartLedAdapter, SmartLedsAdapter},
|
||||||
|
Delay,
|
||||||
|
PulseControl,
|
||||||
|
RtcCntl,
|
||||||
|
Timer,
|
||||||
|
IO,
|
||||||
|
};
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use panic_halt;
|
||||||
|
use riscv_rt::entry;
|
||||||
|
use smart_leds::{
|
||||||
|
brightness,
|
||||||
|
gamma,
|
||||||
|
hsv::{hsv2rgb, Hsv},
|
||||||
|
SmartLedsWrite,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let mut peripherals = pac::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||||
|
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||||
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
// Disable watchdogs
|
||||||
|
rtc_cntl.set_super_wdt_enable(false);
|
||||||
|
rtc_cntl.set_wdt_enable(false);
|
||||||
|
timer0.disable();
|
||||||
|
|
||||||
|
// Configure RMT peripheral globally
|
||||||
|
let pulse = PulseControl::new(
|
||||||
|
peripherals.RMT,
|
||||||
|
&mut peripherals.SYSTEM,
|
||||||
|
ClockSource::APB,
|
||||||
|
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 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(peripherals.SYSTIMER);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,10 +8,13 @@ pub use esp_hal_common::{
|
|||||||
interrupt,
|
interrupt,
|
||||||
pac,
|
pac,
|
||||||
prelude,
|
prelude,
|
||||||
|
pulse_control,
|
||||||
ram,
|
ram,
|
||||||
spi,
|
spi,
|
||||||
|
utils,
|
||||||
Cpu,
|
Cpu,
|
||||||
Delay,
|
Delay,
|
||||||
|
PulseControl,
|
||||||
Rng,
|
Rng,
|
||||||
Serial,
|
Serial,
|
||||||
Timer,
|
Timer,
|
||||||
|
|||||||
@ -39,6 +39,7 @@ features = ["esp32s2"]
|
|||||||
embedded-graphics = "0.7"
|
embedded-graphics = "0.7"
|
||||||
panic-halt = "0.2"
|
panic-halt = "0.2"
|
||||||
ssd1306 = "0.7"
|
ssd1306 = "0.7"
|
||||||
|
smart-leds = "0.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt"]
|
default = ["rt"]
|
||||||
|
|||||||
79
esp32s2-hal/examples/hello_rgb.rs
Normal file
79
esp32s2-hal/examples/hello_rgb.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//! RGB LED Demo
|
||||||
|
//!
|
||||||
|
//! This example drives an SK68XX RGB LED that is connected to GPIO18.
|
||||||
|
//! A RGB LED is connected to that pin on the official DevKits.
|
||||||
|
//!
|
||||||
|
//! 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 esp32s2_hal::{
|
||||||
|
pac,
|
||||||
|
prelude::*,
|
||||||
|
utils::{smartLedAdapter, SmartLedsAdapter},
|
||||||
|
Delay,
|
||||||
|
PulseControl,
|
||||||
|
RtcCntl,
|
||||||
|
Timer,
|
||||||
|
IO,
|
||||||
|
};
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use panic_halt as _;
|
||||||
|
use smart_leds::{
|
||||||
|
brightness,
|
||||||
|
gamma,
|
||||||
|
hsv::{hsv2rgb, Hsv},
|
||||||
|
SmartLedsWrite,
|
||||||
|
};
|
||||||
|
use xtensa_lx_rt::entry;
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let mut peripherals = pac::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||||
|
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||||
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
// Disable MWDT and RWDT (Watchdog) flash boot protection
|
||||||
|
timer0.disable();
|
||||||
|
rtc_cntl.set_wdt_global_enable(false);
|
||||||
|
|
||||||
|
// Configure RMT peripheral globally
|
||||||
|
let pulse = PulseControl::new(peripherals.RMT, &mut peripherals.SYSTEM).unwrap();
|
||||||
|
|
||||||
|
// We use one of the RMT channels to instantiate a `SmartLedsAdapter` which can
|
||||||
|
// be used directly with all `smart_led` implementations
|
||||||
|
let mut led = <smartLedAdapter!(1)>::new(pulse.channel0, io.pins.gpio18);
|
||||||
|
|
||||||
|
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||||
|
// loop.
|
||||||
|
let mut delay = Delay::new();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,10 +6,13 @@ pub use esp_hal_common::{
|
|||||||
interrupt,
|
interrupt,
|
||||||
pac,
|
pac,
|
||||||
prelude,
|
prelude,
|
||||||
|
pulse_control,
|
||||||
ram,
|
ram,
|
||||||
spi,
|
spi,
|
||||||
|
utils,
|
||||||
Cpu,
|
Cpu,
|
||||||
Delay,
|
Delay,
|
||||||
|
PulseControl,
|
||||||
Rng,
|
Rng,
|
||||||
RtcCntl,
|
RtcCntl,
|
||||||
Serial,
|
Serial,
|
||||||
|
|||||||
@ -39,6 +39,7 @@ features = ["esp32s3"]
|
|||||||
embedded-graphics = "0.7"
|
embedded-graphics = "0.7"
|
||||||
panic-halt = "0.2"
|
panic-halt = "0.2"
|
||||||
ssd1306 = "0.7"
|
ssd1306 = "0.7"
|
||||||
|
smart-leds = "0.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rt"]
|
default = ["rt"]
|
||||||
|
|||||||
88
esp32s3-hal/examples/hello_rgb.rs
Normal file
88
esp32s3-hal/examples/hello_rgb.rs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
//! RGB LED Demo
|
||||||
|
//!
|
||||||
|
//! This example drives an SK68XX RGB LED that is connected to the GPI48 pin.
|
||||||
|
//! A RGB LED is connected to that pin on the official DevKits.
|
||||||
|
//!
|
||||||
|
//! 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 esp32s3_hal::{
|
||||||
|
pac,
|
||||||
|
prelude::*,
|
||||||
|
pulse_control::ClockSource,
|
||||||
|
utils::{smartLedAdapter, SmartLedsAdapter},
|
||||||
|
Delay,
|
||||||
|
PulseControl,
|
||||||
|
RtcCntl,
|
||||||
|
Timer,
|
||||||
|
IO,
|
||||||
|
};
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use panic_halt as _;
|
||||||
|
use smart_leds::{
|
||||||
|
brightness,
|
||||||
|
gamma,
|
||||||
|
hsv::{hsv2rgb, Hsv},
|
||||||
|
SmartLedsWrite,
|
||||||
|
};
|
||||||
|
use xtensa_lx_rt::entry;
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let mut peripherals = pac::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||||
|
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||||
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
// Disable MWDT and RWDT (Watchdog) flash boot protection
|
||||||
|
timer0.disable();
|
||||||
|
rtc_cntl.set_wdt_global_enable(false);
|
||||||
|
|
||||||
|
// Configure RMT peripheral globally
|
||||||
|
let pulse = PulseControl::new(
|
||||||
|
peripherals.RMT,
|
||||||
|
&mut peripherals.SYSTEM,
|
||||||
|
ClockSource::APB,
|
||||||
|
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 mut led = <smartLedAdapter!(1)>::new(pulse.channel0, io.pins.gpio48);
|
||||||
|
|
||||||
|
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||||
|
// loop.
|
||||||
|
let mut delay = Delay::new();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,11 +6,14 @@ pub use esp_hal_common::{
|
|||||||
interrupt,
|
interrupt,
|
||||||
pac,
|
pac,
|
||||||
prelude,
|
prelude,
|
||||||
|
pulse_control,
|
||||||
ram,
|
ram,
|
||||||
spi,
|
spi,
|
||||||
|
utils,
|
||||||
usb_serial_jtag,
|
usb_serial_jtag,
|
||||||
Cpu,
|
Cpu,
|
||||||
Delay,
|
Delay,
|
||||||
|
PulseControl,
|
||||||
Rng,
|
Rng,
|
||||||
RtcCntl,
|
RtcCntl,
|
||||||
Serial,
|
Serial,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user