pub mod config;
pub mod encoder;
mod tx_channel;
pub use tx_channel::*;
mod tx_queue;
pub use tx_queue::*;
mod rx_channel;
pub use rx_channel::*;
mod sync_manager;
pub use sync_manager::*;
mod pulse;
pub use pulse::*;
use core::time::Duration;
use core::{fmt, ptr};
use esp_idf_sys::*;
use crate::rmt::config::CarrierConfig;
use crate::units::Hertz;
#[cfg(esp_idf_version_at_least_6_0_0)]
#[allow(non_camel_case_types)]
type rmt_carrier_config_t__bindgen_ty_1 = rmt_carrier_config_t_extra_rmt_carrier_config_flags;
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Symbol(rmt_symbol_word_t);
impl Symbol {
#[must_use]
pub fn new(level0: Pulse, level1: Pulse) -> Self {
let item = rmt_symbol_word_t { val: 0 };
let mut this = Self(item);
this.update(level0, level1);
this
}
pub fn new_with(
resolution: Hertz,
level0: PinState,
duration0: Duration,
level1: PinState,
duration1: Duration,
) -> Result<Self, EspError> {
Ok(Self::new(
Pulse::new_with_duration(resolution, level0, duration0)?,
Pulse::new_with_duration(resolution, level1, duration1)?,
))
}
pub fn new_half_split(
resolution: Hertz,
level0: PinState,
level1: PinState,
duration: Duration,
) -> Result<Self, EspError> {
let first_half_duration = duration / 2;
let second_half_duration = duration - first_half_duration;
Ok(Self::new(
Pulse::new_with_duration(resolution, level0, first_half_duration)?,
Pulse::new_with_duration(resolution, level1, second_half_duration)?,
))
}
pub fn repeat_for(&self, resolution: Hertz, duration: Duration) -> impl Iterator<Item = Self> {
let symbol_duration = self.duration(resolution);
if symbol_duration.is_zero() {
panic!("Cannot repeat a symbol with zero duration for {duration:?}");
}
let count = duration.as_nanos() / symbol_duration.as_nanos();
let remainder =
Duration::from_nanos((duration.as_nanos() % symbol_duration.as_nanos()) as u64);
let last_symbol = {
if remainder.is_zero() {
None
} else {
let duration0 = self.level0().ticks.duration(resolution).min(remainder);
let duration1 = remainder.saturating_sub(duration0);
Some(
Self::new_with(
resolution,
self.level0().pin_state,
duration0,
self.level1().pin_state,
duration1,
)
.unwrap(),
)
}
};
core::iter::repeat_n(*self, count as usize).chain(core::iter::once(last_symbol).flatten())
}
#[must_use]
fn symbol_word_to_pulse(word: &rmt_symbol_word_t) -> (Pulse, Pulse) {
let inner = unsafe { &word.__bindgen_anon_1 };
(
Pulse::new(
(inner.level0() as u32).into(),
PulseTicks::new(inner.duration0()).unwrap(),
),
Pulse::new(
(inner.level1() as u32).into(),
PulseTicks::new(inner.duration1()).unwrap(),
),
)
}
#[must_use]
pub fn level0(&self) -> Pulse {
Self::symbol_word_to_pulse(&self.0).0
}
#[must_use]
pub fn level1(&self) -> Pulse {
Self::symbol_word_to_pulse(&self.0).1
}
pub fn duration(&self, resolution: Hertz) -> Duration {
self.level0().ticks.duration(resolution) + self.level1().ticks.duration(resolution)
}
pub fn update(&mut self, level0: Pulse, level1: Pulse) {
let inner = unsafe { &mut self.0.__bindgen_anon_1 };
inner.set_level0(level0.pin_state as u16);
inner.set_duration0(level0.ticks.ticks());
inner.set_level1(level1.pin_state as u16);
inner.set_duration1(level1.ticks.ticks());
}
}
impl fmt::Debug for Symbol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Symbol")
.field("level0", &self.level0())
.field("level1", &self.level1())
.finish()
}
}
impl Default for Symbol {
fn default() -> Self {
Self::new(Default::default(), Default::default())
}
}
impl PartialEq for Symbol {
fn eq(&self, other: &Self) -> bool {
(self.level0(), self.level1()) == (other.level0(), other.level1())
}
}
impl Eq for Symbol {}
impl From<rmt_symbol_word_t> for Symbol {
fn from(value: rmt_symbol_word_t) -> Self {
Self(value)
}
}
impl From<Symbol> for rmt_symbol_word_t {
fn from(value: Symbol) -> Self {
value.0
}
}
fn assert_not_in_isr() {
if crate::interrupt::active() {
panic!("This function cannot be called from an ISR");
}
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub struct TxDoneEventData {
pub num_symbols: usize,
}
impl From<rmt_tx_done_event_data_t> for TxDoneEventData {
fn from(data: rmt_tx_done_event_data_t) -> Self {
Self {
num_symbols: data.num_symbols,
}
}
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub struct RxDoneEventData {
pub received_symbols: *mut Symbol,
pub num_symbols: usize,
#[cfg(esp_idf_version_at_least_5_3_0)]
pub is_last: bool,
}
impl RxDoneEventData {
pub unsafe fn as_slice(&self) -> &[Symbol] {
core::slice::from_raw_parts(self.received_symbols, self.num_symbols)
}
}
impl From<rmt_rx_done_event_data_t> for RxDoneEventData {
fn from(data: rmt_rx_done_event_data_t) -> Self {
Self {
received_symbols: data.received_symbols as *mut Symbol,
num_symbols: data.num_symbols,
#[cfg(esp_idf_version_at_least_5_3_0)]
is_last: data.flags.is_last() != 0,
}
}
}
pub trait RmtChannel {
fn handle(&self) -> rmt_channel_handle_t;
#[must_use]
fn is_enabled(&self) -> bool;
#[doc(hidden)]
unsafe fn set_internal_enabled(&mut self, is_enabled: bool);
fn enable(&mut self) -> Result<(), EspError> {
esp!(unsafe { rmt_enable(self.handle()) })?;
unsafe { self.set_internal_enabled(true) };
Ok(())
}
fn disable(&mut self) -> Result<(), EspError> {
esp!(unsafe { rmt_disable(self.handle()) })?;
unsafe { self.set_internal_enabled(false) };
Ok(())
}
fn apply_carrier(&mut self, carrier_config: Option<&CarrierConfig>) -> Result<(), EspError> {
let mut sys_carrier = None;
if let Some(CarrierConfig {
frequency,
duty_cycle,
polarity_active_low,
always_on,
__internal,
}) = carrier_config
{
sys_carrier = Some(rmt_carrier_config_t {
frequency_hz: (*frequency).into(),
duty_cycle: duty_cycle.to_f32(),
flags: rmt_carrier_config_t__bindgen_ty_1 {
_bitfield_1: rmt_carrier_config_t__bindgen_ty_1::new_bitfield_1(
*polarity_active_low as u32,
*always_on as u32,
),
..Default::default()
},
})
}
esp!(unsafe {
rmt_apply_carrier(
self.handle(),
sys_carrier.as_ref().map_or(ptr::null(), |c| c as *const _),
)
})
}
}
impl<R: RmtChannel> RmtChannel for &mut R {
fn handle(&self) -> rmt_channel_handle_t {
(**self).handle()
}
fn is_enabled(&self) -> bool {
(**self).is_enabled()
}
unsafe fn set_internal_enabled(&mut self, is_enabled: bool) {
(**self).set_internal_enabled(is_enabled)
}
fn enable(&mut self) -> Result<(), EspError> {
(**self).enable()
}
fn disable(&mut self) -> Result<(), EspError> {
(**self).disable()
}
fn apply_carrier(&mut self, carrier_config: Option<&CarrierConfig>) -> Result<(), EspError> {
(**self).apply_carrier(carrier_config)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum ClockSource {
#[default]
Default,
#[cfg(any(esp32, esp32c3, esp32s2, esp32s3))]
APB,
#[cfg(any(esp32c3, esp32c5, esp32c6, esp32h2, esp32h4, esp32p4, esp32s3))]
RcFast,
#[cfg(any(esp32, esp32s2))]
RefTick,
#[cfg(any(esp32c3, esp32c5, esp32c6, esp32h2, esp32h4, esp32p4, esp32s3))]
XTAL,
#[cfg(any(esp32c5, esp32c6, esp32p4))]
PLLF80M,
}
impl From<ClockSource> for rmt_clock_source_t {
fn from(clock: ClockSource) -> Self {
match clock {
ClockSource::Default => soc_periph_rmt_clk_src_t_RMT_CLK_SRC_DEFAULT,
#[cfg(any(esp32, esp32c3, esp32s2, esp32s3))]
ClockSource::APB => soc_periph_rmt_clk_src_t_RMT_CLK_SRC_APB,
#[cfg(any(esp32c3, esp32c5, esp32c6, esp32h2, esp32h4, esp32p4, esp32s3))]
ClockSource::RcFast => soc_periph_rmt_clk_src_t_RMT_CLK_SRC_RC_FAST,
#[cfg(any(esp32, esp32s2))]
ClockSource::RefTick => soc_periph_rmt_clk_src_t_RMT_CLK_SRC_REF_TICK,
#[cfg(any(esp32c3, esp32c5, esp32c6, esp32h2, esp32h4, esp32p4, esp32s3))]
ClockSource::XTAL => soc_periph_rmt_clk_src_t_RMT_CLK_SRC_XTAL,
#[cfg(any(esp32c5, esp32c6, esp32p4))]
ClockSource::PLLF80M => soc_periph_rmt_clk_src_t_RMT_CLK_SRC_PLL_F80M,
}
}
}