mod copy_encoder;
pub use copy_encoder::*;
mod bytes_encoder;
pub use bytes_encoder::*;
#[cfg(esp_idf_version_at_least_5_3_0)]
#[cfg_attr(feature = "nightly", doc(cfg(esp_idf_version_at_least_5_3_0)))]
pub mod simple_encoder;
use alloc::boxed::Box;
use core::mem;
use esp_idf_sys::*;
pub trait RawEncoder {
type Item;
fn handle(&mut self) -> &mut rmt_encoder_t;
fn reset(&mut self) -> Result<(), EspError> {
esp!(unsafe { rmt_encoder_reset(self.handle()) })
}
}
impl<E: RawEncoder> RawEncoder for &mut E {
type Item = E::Item;
fn handle(&mut self) -> &mut rmt_encoder_t {
(*self).handle()
}
fn reset(&mut self) -> Result<(), EspError> {
(*self).reset()
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum EncoderState {
EncodingReset,
EncodingComplete,
EncodingMemoryFull,
#[cfg(esp_idf_version_at_least_5_5_0)]
#[cfg_attr(feature = "nightly", doc(cfg(esp_idf_version_at_least_5_5_0)))]
EncodingWithEof,
}
impl From<EncoderState> for rmt_encode_state_t {
fn from(value: EncoderState) -> Self {
match value {
EncoderState::EncodingReset => rmt_encode_state_t_RMT_ENCODING_RESET,
EncoderState::EncodingComplete => rmt_encode_state_t_RMT_ENCODING_COMPLETE,
EncoderState::EncodingMemoryFull => rmt_encode_state_t_RMT_ENCODING_MEM_FULL,
#[cfg(esp_idf_version_at_least_5_5_0)]
EncoderState::EncodingWithEof => rmt_encode_state_t_RMT_ENCODING_WITH_EOF,
}
}
}
impl From<rmt_encode_state_t> for EncoderState {
fn from(value: rmt_encode_state_t) -> Self {
#[allow(non_upper_case_globals)]
match value {
rmt_encode_state_t_RMT_ENCODING_RESET => Self::EncodingReset,
rmt_encode_state_t_RMT_ENCODING_COMPLETE => Self::EncodingComplete,
rmt_encode_state_t_RMT_ENCODING_MEM_FULL => Self::EncodingMemoryFull,
#[cfg(esp_idf_version_at_least_5_5_0)]
rmt_encode_state_t_RMT_ENCODING_WITH_EOF => Self::EncodingWithEof,
_ => panic!("Unknown rmt_encode_state_t value: {value}"),
}
}
}
#[derive(Debug)]
pub struct RmtChannelHandle {
handle: rmt_channel_handle_t,
}
impl RmtChannelHandle {
#[must_use]
pub(crate) fn as_ptr(&self) -> rmt_channel_handle_t {
self.handle
}
}
pub trait Encoder {
type Item;
fn encode(
&mut self,
handle: &mut RmtChannelHandle,
primary_data: &[Self::Item],
) -> (usize, EncoderState);
fn reset(&mut self) -> Result<(), EspError>;
}
impl<E: RawEncoder> Encoder for E {
type Item = E::Item;
fn encode(
&mut self,
handle: &mut RmtChannelHandle,
primary_data: &[Self::Item],
) -> (usize, EncoderState) {
let encoder_handle = self.handle();
let Some(encode) = encoder_handle.encode else {
return (0, EncoderState::EncodingReset);
};
let mut ret_state: rmt_encode_state_t = rmt_encode_state_t_RMT_ENCODING_RESET;
let data_size = mem::size_of_val::<[Self::Item]>(primary_data);
let written = unsafe {
encode(
encoder_handle,
handle.as_ptr(),
primary_data.as_ptr() as *const core::ffi::c_void,
data_size,
&raw mut ret_state,
)
};
(written, ret_state.into())
}
fn reset(&mut self) -> Result<(), EspError> {
let handle = self.handle();
if let Some(reset) = handle.reset {
esp!(unsafe { reset(handle) })?;
}
Ok(())
}
}
#[must_use]
pub fn into_raw<E: Encoder>(encoder: E) -> EncoderWrapper<E> {
EncoderWrapper::new(encoder).expect("Failed to allocate memory for RMT encoder")
}
#[derive(Debug)]
struct InternalEncoderWrapper<E> {
base: rmt_encoder_t, encoder: Option<E>,
}
#[derive(Debug)]
#[repr(C)]
pub struct EncoderWrapper<E>(Box<InternalEncoderWrapper<E>>);
impl<E: Encoder> EncoderWrapper<E> {
pub fn new(encoder: E) -> Result<Self, EspError> {
Ok(Self(Box::new(InternalEncoderWrapper::new(encoder))))
}
}
impl<E: Encoder> InternalEncoderWrapper<E> {
unsafe fn containerof(ptr: *mut rmt_encoder_t) -> *mut Self {
ptr.cast::<u8>()
.sub(mem::offset_of!(Self, base))
.cast::<Self>()
}
pub fn new(encoder: E) -> Self {
Self {
base: rmt_encoder_t {
encode: Some(Self::encode),
reset: Some(Self::reset),
del: Some(Self::del),
},
encoder: Some(encoder),
}
}
fn encoder(&mut self) -> &mut E {
unsafe { self.encoder.as_mut().unwrap_unchecked() }
}
pub unsafe extern "C" fn encode(
encoder: *mut rmt_encoder_t,
tx_channel: rmt_channel_handle_t,
primary_data: *const ::core::ffi::c_void,
data_size: usize,
ret_state: *mut rmt_encode_state_t,
) -> usize {
let this = Self::containerof(encoder).as_mut().unwrap();
let primary_data = core::slice::from_raw_parts(
primary_data.cast::<E::Item>(),
data_size / mem::size_of::<E::Item>(),
);
let mut channel_handle = RmtChannelHandle { handle: tx_channel };
let (written, state) = this.encoder().encode(&mut channel_handle, primary_data);
*ret_state = state.into();
written
}
pub unsafe extern "C" fn reset(encoder: *mut rmt_encoder_t) -> esp_err_t {
let this = Self::containerof(encoder).as_mut().unwrap();
match this.encoder().reset() {
Ok(()) => ESP_OK,
Err(_) => ESP_FAIL,
}
}
pub unsafe extern "C" fn del(encoder: *mut rmt_encoder_t) -> esp_err_t {
let this = Self::containerof(encoder).as_mut().unwrap();
this.encoder.take();
ESP_OK
}
}
impl<E: Encoder> RawEncoder for EncoderWrapper<E> {
type Item = E::Item;
fn handle(&mut self) -> &mut rmt_encoder_t {
&mut self.0.as_mut().base
}
}