The SimpleEncoder provides a high-level interface for implementing custom RMT (Remote Control) encoders. Instead of managing low-level buffers manually, you implement the EncoderCallback trait, which provides a SymbolBuffer to write output symbols into.
Workflow
- Define your data type: Choose the type of input data you want to encode (e.g.,
u8). - Implement
EncoderCallback: Implement the encode method. This method is called from an ISR context, so avoid blocking or calling non-ISR-safe APIs. - Handle Buffer Limits: If the provided
SymbolBuffer is too small to encode the next chunk of data, return Err(NotEnoughSpace). The encoder will call your callback again later with a larger buffer. You must track how much input data you have already processed. - Complete Encoding: Once all input data is processed, return
Ok(()). The encoder will set the done flag. - Initialize: Use
SimpleEncoder::with_config to create the encoder.
Tracking Progress
Since the encode method might be called multiple times for the same input data (if space runs out), you must track your progress. You can use SymbolBuffer::position() to see how many symbols have been written so far. If you know your encoding ratio (e.g., 1 input byte = 8 output symbols), you can calculate processed items via position / 8.
ISR Safety Warning
The encode function is called from an ISR context. Do not call std, libc, or standard FreeRTOS APIs. You may only use FreeRTOS APIs with the FromISR suffix.
use esp_idf_hal::rmt::encoder::{SimpleEncoder, EncoderCallback, SimpleEncoderConfig, SymbolBuffer, NotEnoughSpace};
use esp_idf_hal::rmt::Symbol;
struct MyEncoder {
processed_count: usize
}
impl EncoderCallback for MyEncoder {
type Item = u8;
fn encode(&mut self, input_data: &[Self::Item], buffer: &mut SymbolBuffer<'_>) -> Result<(), NotEnoughSpace> {
let remaining_input = input_data.len() - self.processed_count;
for i in 0..remaining_input {
let val = input_data[self.processed_count + i];
// Example: encode 1 byte into 2 symbols
if buffer.remaining() < 2 {
return Err(NotEnoughSpace);
}
// Logic to convert val to symbols...
// buffer.write_all(&[symbol1, symbol2]).unwrap();
self.processed_count += 1;
}
Ok(())
}
}
// Usage:
// let config = SimpleEncoderConfig::default();
// let encoder = SimpleEncoder::with_config(MyEncoder { processed_count: 0 }, &config).unwrap();