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(
        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(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::empty();

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(peripherals.GPIO4, rx_config)?;
let delay = Delay::new();
let mut data: [u32; 48] = [PulseCode::empty(); 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(channel_res) => {
            channel = channel_res;
            let mut total = 0usize;
            for entry in &data[..data.len()] {
                if entry.length1() == 0 {
                    break;
                }
                total += entry.length1() as usize;

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

            for entry in &data[..data.len()] {
                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
Rmt
RMT Instance
RxChannelConfig
Channel configuration for RX channels
RxTransaction
RX transaction instance
SingleShotTxTransaction
An in-progress transaction for a single shot TX transaction.
TxChannelConfig
Channel configuration for TX channels

Enums§

Error
Errors

Traits§

PulseCode
Convenience trait to work with pulse codes.
RxChannel
Channel is RX mode
RxChannelAsync
RX channel in async mode
RxChannelCreator
Creates a RX channel
RxChannelCreatorAsync
Creates a RX channel in async mode
TxChannel
Channel in TX mode
TxChannelAsync
TX channel in async mode
TxChannelCreator
Creates a TX channel
TxChannelCreatorAsync
Creates a TX channel in async mode