Module rmt

Module rmt 

Source
Available on crate feature unstable only.
Expand description

§Remote Control Peripheral (RMT)

§Overview

The RMT (Remote Control) module is designed to send and receive infrared remote control signals. A variety of remote control protocols can be encoded/decoded via software based on the RMT module. The RMT module converts pulse codes stored in the module’s built-in RAM into output signals, or converts input signals into pulse codes and stores them in RAM. In addition, the RMT module optionally modulates its output signals with a carrier wave, or optionally demodulates and filters its input signals.

Typically, the RMT peripheral can be used in the following scenarios:

  • Transmit or receive infrared signals, with any IR protocols, e.g., NEC
  • General-purpose sequence generator
  • Transmit signals in a hardware-controlled loop, with a finite or infinite number of times
  • Modulate the carrier to the output signal or demodulate the carrier from the input signal

§Channels

There are 4 channels, Channel<0> and Channel<1> hardcoded for transmitting signals and Channel<2> and Channel<3> hardcoded for receiving signals.

For more information, please refer to the ESP-IDF documentation

§Configuration

Each TX/RX channel has the same functionality controlled by a dedicated set of registers and is able to independently transmit or receive data. TX channels are indicated by n which is used as a placeholder for the channel number, and by m for RX channels.

§Examples

§Initialization

let freq = Rate::from_mhz(80);
let rmt = Rmt::new(peripherals.RMT, freq)?;
let mut channel = rmt.channel0.configure_tx(
    peripherals.GPIO1,
    TxChannelConfig::default()
        .with_clk_divider(1)
        .with_idle_output_level(Level::Low)
        .with_idle_output(false)
        .with_carrier_modulation(false)
        .with_carrier_high(1)
        .with_carrier_low(1)
        .with_carrier_level(Level::Low),
)?;

§TX operation


// Configure frequency based on chip type
let freq = Rate::from_mhz(80);
let rmt = Rmt::new(peripherals.RMT, freq)?;

let tx_config = TxChannelConfig::default().with_clk_divider(255);

let mut channel = rmt.channel0.configure_tx(peripherals.GPIO4, tx_config)?;

let delay = Delay::new();

let mut data = [PulseCode::new(Level::High, 200, Level::Low, 50); 20];
data[data.len() - 2] = PulseCode::new(Level::High, 3000, Level::Low, 500);
data[data.len() - 1] = PulseCode::end_marker();

loop {
    let transaction = channel.transmit(&data)?;
    channel = transaction.wait()?;
    delay.delay_millis(500);
}

§RX operation


const WIDTH: usize = 80;

let mut out = Output::new(peripherals.GPIO5, Level::Low, OutputConfig::default());

// Configure frequency based on chip type
let freq = Rate::from_mhz(80);
let rmt = Rmt::new(peripherals.RMT, freq)?;

let rx_config = RxChannelConfig::default()
    .with_clk_divider(1)
    .with_idle_threshold(10000);
let mut channel = rmt.channel2.configure_rx(peripherals.GPIO4, rx_config)?;
let delay = Delay::new();
let mut data: [PulseCode; 48] = [PulseCode::default(); 48];

loop {
    for x in data.iter_mut() {
        x.reset()
    }

    let transaction = channel.receive(&mut data)?;

    // Simulate input
    for i in 0u32..5u32 {
        out.set_high();
        delay.delay_micros(i * 10 + 20);
        out.set_low();
        delay.delay_micros(i * 20 + 20);
    }

    match transaction.wait() {
        Ok((symbol_count, channel_res)) => {
            channel = channel_res;
            let mut total = 0usize;
            for entry in &data[..symbol_count] {
                if entry.length1() == 0 {
                    break;
                }
                total += entry.length1() as usize;

                if entry.length2() == 0 {
                    break;
                }
                total += entry.length2() as usize;
            }

            for entry in &data[..symbol_count] {
                if entry.length1() == 0 {
                    break;
                }

                let count = WIDTH / (total / entry.length1() as usize);
                let c = match entry.level1() {
                    Level::High => '-',
                    Level::Low => '_',
                };
                for _ in 0..count + 1 {
                    print!("{}", c);
                }

                if entry.length2() == 0 {
                    break;
                }

                let count = WIDTH / (total / entry.length2() as usize);
                let c = match entry.level2() {
                    Level::High => '-',
                    Level::Low => '_',
                };
                for _ in 0..count + 1 {
                    print!("{}", c);
                }
            }

            println!();
        }
        Err((_err, channel_res)) => {
            channel = channel_res;
        }
    }

    delay.delay_millis(1500);
}

Note: on ESP32 and ESP32-S2 you cannot specify a base frequency other than 80 MHz

Structs§

Channel
RMT Channel
ChannelCreator
RMT Channel Creator
ContinuousTxTransaction
An in-progress continuous TX transaction
PulseCode
Convenience newtype to work with pulse codes.
Rmt
RMT Instance
Rx
Marker for a channel capable of/configured for receive operations
RxChannelConfig
Channel configuration for RX channels
RxTransaction
RX transaction instance
SingleShotTxTransaction
An in-progress transaction for a single shot TX transaction.
Tx
Marker for a channel capable of/configured for transmit operations
TxChannelConfig
Channel configuration for TX channels

Enums§

Error
Errors
LoopMode
Loop mode for continuous transmission

Constants§

CHANNEL_RAM_SIZE
Per-channel size of the RMT hardware buffer (number of PulseCodes).
HAS_RX_WRAP
Whether the channel supports wrapping rx (wrapping tx is supported on all devices)
MAX_RX_IDLE_THRESHOLD
The largest valid value for RxChannelConfig::with_idle_threshold.
MAX_TX_LOOPCOUNT
The largest valid value for loopcounts in LoopMode.

Traits§

Direction
A trait implemented by the Rx and Tx marker structs.
RxChannelCreator
Creates a RX channel
TxChannelCreator
Creates a TX channel