From 2ec35f60ca6866551309f74aba5c157970e8925a Mon Sep 17 00:00:00 2001 From: krzychb Date: Mon, 20 Nov 2017 04:51:30 +0100 Subject: [PATCH 1/4] RMT API docs update, new example --- components/driver/include/driver/rmt.h | 187 ++++++------------ docs/api-reference/peripherals/rmt.rst | 159 ++++++++++++++- examples/peripherals/rmt_tx/Makefile | 9 + examples/peripherals/rmt_tx/README.md | 25 +++ examples/peripherals/rmt_tx/main/component.mk | 4 + .../peripherals/rmt_tx/main/rmt_tx_main.c | 119 +++++++++++ 6 files changed, 374 insertions(+), 129 deletions(-) create mode 100644 examples/peripherals/rmt_tx/Makefile create mode 100644 examples/peripherals/rmt_tx/README.md create mode 100644 examples/peripherals/rmt_tx/main/component.mk create mode 100644 examples/peripherals/rmt_tx/main/rmt_tx_main.c diff --git a/components/driver/include/driver/rmt.h b/components/driver/include/driver/rmt.h index 56c5ed4952..79ac0e5d67 100644 --- a/components/driver/include/driver/rmt.h +++ b/components/driver/include/driver/rmt.h @@ -33,14 +33,14 @@ extern "C" { #define RMT_MEM_ITEM_NUM (RMT_MEM_BLOCK_BYTE_NUM/4) typedef enum { - RMT_CHANNEL_0=0, /*!< RMT Channel0 */ - RMT_CHANNEL_1, /*!< RMT Channel1 */ - RMT_CHANNEL_2, /*!< RMT Channel2 */ - RMT_CHANNEL_3, /*!< RMT Channel3 */ - RMT_CHANNEL_4, /*!< RMT Channel4 */ - RMT_CHANNEL_5, /*!< RMT Channel5 */ - RMT_CHANNEL_6, /*!< RMT Channel6 */ - RMT_CHANNEL_7, /*!< RMT Channel7 */ + RMT_CHANNEL_0 = 0, /*!< RMT Channel 0 */ + RMT_CHANNEL_1, /*!< RMT Channel 1 */ + RMT_CHANNEL_2, /*!< RMT Channel 2 */ + RMT_CHANNEL_3, /*!< RMT Channel 3 */ + RMT_CHANNEL_4, /*!< RMT Channel 4 */ + RMT_CHANNEL_5, /*!< RMT Channel 5 */ + RMT_CHANNEL_6, /*!< RMT Channel 6 */ + RMT_CHANNEL_7, /*!< RMT Channel 7 */ RMT_CHANNEL_MAX } rmt_channel_t; @@ -51,7 +51,7 @@ typedef enum { }rmt_mem_owner_t; typedef enum { - RMT_BASECLK_REF = 0, /*!< RMT source clock system reference tick, 1MHz by default(Not supported in this version) */ + RMT_BASECLK_REF = 0, /*!< RMT source clock system reference tick, 1MHz by default (not supported in this version) */ RMT_BASECLK_APB, /*!< RMT source clock is APB CLK, 80Mhz by default */ RMT_BASECLK_MAX, } rmt_source_clk_t; @@ -63,20 +63,20 @@ typedef enum { } rmt_data_mode_t; typedef enum { - RMT_MODE_TX=0, /*!< RMT TX mode */ - RMT_MODE_RX, /*!< RMT RX mode */ + RMT_MODE_TX = 0, /*!< RMT TX mode */ + RMT_MODE_RX, /*!< RMT RX mode */ RMT_MODE_MAX } rmt_mode_t; typedef enum { - RMT_IDLE_LEVEL_LOW=0, /*!< RMT TX idle level: low Level */ - RMT_IDLE_LEVEL_HIGH, /*!< RMT TX idle level: high Level */ + RMT_IDLE_LEVEL_LOW = 0, /*!< RMT TX idle level: low Level */ + RMT_IDLE_LEVEL_HIGH, /*!< RMT TX idle level: high Level */ RMT_IDLE_LEVEL_MAX, } rmt_idle_level_t; typedef enum { - RMT_CARRIER_LEVEL_LOW=0, /*!< RMT carrier wave is modulated for low Level output */ - RMT_CARRIER_LEVEL_HIGH, /*!< RMT carrier wave is modulated for high Level output */ + RMT_CARRIER_LEVEL_LOW = 0, /*!< RMT carrier wave is modulated for low Level output */ + RMT_CARRIER_LEVEL_HIGH, /*!< RMT carrier wave is modulated for high Level output */ RMT_CARRIER_LEVEL_MAX } rmt_carrier_level_t; @@ -84,21 +84,21 @@ typedef enum { * @brief Data struct of RMT TX configure parameters */ typedef struct { - bool loop_en; /*!< RMT loop output mode*/ + bool loop_en; /*!< Enable sending RMT items in a loop */ uint32_t carrier_freq_hz; /*!< RMT carrier frequency */ uint8_t carrier_duty_percent; /*!< RMT carrier duty (%) */ - rmt_carrier_level_t carrier_level; /*!< RMT carrier level */ + rmt_carrier_level_t carrier_level; /*!< Level of the RMT output, when the carrier is applied */ bool carrier_en; /*!< RMT carrier enable */ rmt_idle_level_t idle_level; /*!< RMT idle level */ - bool idle_output_en; /*!< RMT idle level output enable*/ + bool idle_output_en; /*!< RMT idle level output enable */ }rmt_tx_config_t; /** * @brief Data struct of RMT RX configure parameters */ typedef struct { - bool filter_en; /*!< RMT receiver filer enable*/ - uint8_t filter_ticks_thresh; /*!< RMT filter tick number */ + bool filter_en; /*!< RMT receiver filter enable */ + uint8_t filter_ticks_thresh; /*!< RMT filter tick number */ uint16_t idle_threshold; /*!< RMT RX idle threshold */ }rmt_rx_config_t; @@ -186,14 +186,16 @@ esp_err_t rmt_get_rx_idle_thresh(rmt_channel_t channel, uint16_t *thresh); * The 8 channels share a 512x32-bit RAM block which can be read and written * by the processor cores over the APB bus, as well as read by the transmitters * and written by the receivers. + * * The RAM address range for channel n is start_addr_CHn to end_addr_CHn, which are defined by: * Memory block start address is RMT_CHANNEL_MEM(n) (in soc/rmt_reg.h), * that is, start_addr_chn = RMT base address + 0x800 + 64 ∗ 4 ∗ n, and * end_addr_chn = RMT base address + 0x800 + 64 ∗ 4 ∗ n + 64 ∗ 4 ∗ RMT_MEM_SIZE_CHn mod 512 ∗ 4 + * * @note * If memory block number of one channel is set to a value greater than 1, this channel will occupy the memory * block of the next channel. - * Channel0 can use at most 8 blocks of memory, accordingly channel7 can only use one memory block. + * Channel 0 can use at most 8 blocks of memory, accordingly channel 7 can only use one memory block. * * @param channel RMT channel (0-7) * @@ -232,11 +234,9 @@ esp_err_t rmt_get_mem_block_num(rmt_channel_t channel, uint8_t* rmt_mem_num); * * @param low_level Low level duration of carrier. * - * @param carrier_level Configure the way carrier wave is modulated for channel0-7. - * - * 1'b1:transmit on low output level - * - * 1'b0:transmit on high output level + * @param carrier_level Configure the way carrier wave is modulated for channel 0-7. + * - 1'b1:transmit on low output level + * - 1'b0:transmit on high output level * * @return * - ESP_ERR_INVALID_ARG Parameter error @@ -278,7 +278,7 @@ esp_err_t rmt_get_mem_pd(rmt_channel_t channel, bool* pd_en); * @param channel RMT channel (0-7) * * @param tx_idx_rst Set true to reset memory index for TX. - * Otherwise, transmitter will continue sending from the last index in memory. + * Otherwise, transmitter will continue sending from the last index in memory. * * @return * - ESP_ERR_INVALID_ARG Parameter error @@ -364,10 +364,9 @@ esp_err_t rmt_get_memory_owner(rmt_channel_t channel, rmt_mem_owner_t* owner); * * @param channel RMT channel (0-7) * - * @param loop_en To enable RMT transmitter loop sending mode. - * + * @param loop_en Enable RMT transmitter loop sending mode. * If set true, transmitter will continue sending from the first data - * to the last data in channel0-7 again and again. + * to the last data in channel 0-7 over and over again in a loop. * * @return * - ESP_ERR_INVALID_ARG Parameter error @@ -391,7 +390,7 @@ esp_err_t rmt_get_tx_loop_mode(rmt_channel_t channel, bool* loop_en); /** * @brief Set RMT RX filter. * - * In receive mode, channel0-7 will ignore input pulse when the pulse width is smaller than threshold. + * In receive mode, channel 0-7 will ignore input pulse when the pulse width is smaller than threshold. * Counted in source clock, not divided counter clock. * * @param channel RMT channel (0-7) @@ -409,9 +408,9 @@ esp_err_t rmt_set_rx_filter(rmt_channel_t channel, bool rx_filter_en, uint8_t th /** * @brief Set RMT source clock * - * RMT module has two source clock: + * RMT module has two clock sources: * 1. APB clock which is 80Mhz - * 2. REF tick clock, which would be 1Mhz( not supported in this version). + * 2. REF tick clock, which would be 1Mhz (not supported in this version). * * @param channel RMT channel (0-7) * @@ -426,9 +425,9 @@ esp_err_t rmt_set_source_clk(rmt_channel_t channel, rmt_source_clk_t base_clk); /** * @brief Get RMT source clock * - * RMT module has two source clock: + * RMT module has two clock sources: * 1. APB clock which is 80Mhz - * 2. REF tick clock, which would be 1Mhz( not supported in this version). + * 2. REF tick clock, which would be 1Mhz (not supported in this version). * * @param channel RMT channel (0-7) * @@ -447,7 +446,7 @@ esp_err_t rmt_get_source_clk(rmt_channel_t channel, rmt_source_clk_t* src_clk); * * @param idle_out_en To enable idle level output. * - * @param level To set the output signal's level for channel0-7 in idle state. + * @param level To set the output signal's level for channel 0-7 in idle state. * * @return * - ESP_ERR_INVALID_ARG Parameter error @@ -526,7 +525,7 @@ esp_err_t rmt_set_tx_intr_en(rmt_channel_t channel, bool en); /** * @brief Set RMT TX threshold event interrupt enable * - * Causes an interrupt when a threshold number of items have been transmitted. + * An interrupt will be triggered when the number of transmitted items reaches the threshold value * * @param channel RMT channel (0 - 7) * @@ -541,7 +540,7 @@ esp_err_t rmt_set_tx_intr_en(rmt_channel_t channel, bool en); esp_err_t rmt_set_tx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_thresh); /** - * @brief Set RMT pins + * @brief Set RMT pin * * @param channel RMT channel (0 - 7) * @@ -558,7 +557,7 @@ esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_nu /** * @brief Configure RMT parameters * - * @param rmt_param RMT parameter structor + * @param rmt_param RMT parameter struct * * @return * - ESP_ERR_INVALID_ARG Parameter error @@ -567,17 +566,18 @@ esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_nu esp_err_t rmt_config(const rmt_config_t* rmt_param); /** - * @brief register RMT interrupt handler, the handler is an ISR. + * @brief Register RMT interrupt handler, the handler is an ISR. * - * The handler will be attached to the same CPU core that this function is running on. - * @note If you already called rmt_driver_install to use system RMT driver, - * please do not register ISR handler again. + * The handler will be attached to the same CPU core that this function is running on. + * + * @note If you already called rmt_driver_install to use system RMT driver, + * please do not register ISR handler again. * * @param fn Interrupt handler function. - * @param arg Parameter for handler function - * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred) - * ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. - * @param handle If non-zero, a handle to later clean up the ISR gets stored here. + * @param arg Parameter for the handler function + * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred) + * ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. + * @param handle If non-zero, a handle to later clean up the ISR gets stored here. * * @return * - ESP_OK Success @@ -653,18 +653,18 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel); * * @param item_num RMT data item number. * - * @param wait_tx_done If set 1, it will block the task and wait for sending done. + * @param wait_tx_done + * - If set 1, it will block the task and wait for sending done. + * - If set 0, it will not wait and return immediately. * - * If set 0, it will not wait and return immediately. - * - * @note - * This function will not copy data, instead, it will point to the original items, - * and send the waveform items. - * If wait_tx_done is set to true, this function will block and will not return until - * all items have been sent out. - * If wait_tx_done is set to false, this function will return immediately, and the driver - * interrupt will continue sending the items. We must make sure the item data will not be - * damaged when the driver is still sending items in driver interrupt. + * @note + * This function will not copy data, instead, it will point to the original items, + * and send the waveform items. + * If wait_tx_done is set to true, this function will block and will not return until + * all items have been sent out. + * If wait_tx_done is set to false, this function will return immediately, and the driver + * interrupt will continue sending the items. We must make sure the item data will not be + * damaged when the driver is still sending items in driver interrupt. * * @return * - ESP_ERR_INVALID_ARG Parameter error @@ -677,24 +677,24 @@ esp_err_t rmt_write_items(rmt_channel_t channel, const rmt_item32_t* rmt_item, i * * @param channel RMT channel (0 - 7) * - * @param wait_time Maximum time to wait for transmission to be complete + * @param wait_time Maximum time in ticks to wait for transmission to be complete * * @return * - ESP_OK RMT Tx done successfully - * - ESP_ERR_TIMEOUT Crossed the 'wait_time' given + * - ESP_ERR_TIMEOUT Exceeded the 'wait_time' given * - ESP_ERR_INVALID_ARG Parameter error * - ESP_FAIL Driver not installed */ esp_err_t rmt_wait_tx_done(rmt_channel_t channel, TickType_t wait_time); /** - * @brief Get ringbuffer from UART. + * @brief Get ringbuffer from RMT. * - * Users can get the RMT RX ringbuffer handler, and process the RX data. + * Users can get the RMT RX ringbuffer handle, and process the RX data. * * @param channel RMT channel (0 - 7) * - * @param buf_handle Pointer to buffer handler to accept RX ringbuffer handler. + * @param buf_handle Pointer to buffer handle to accept RX ringbuffer handle. * * @return * - ESP_ERR_INVALID_ARG Parameter error @@ -702,62 +702,7 @@ esp_err_t rmt_wait_tx_done(rmt_channel_t channel, TickType_t wait_time); */ esp_err_t rmt_get_ringbuf_handle(rmt_channel_t channel, RingbufHandle_t* buf_handle); -/***************************EXAMPLE********************************** - * - * @note - * You can also refer to example/09_rmt_nec_tx_rx to have more information about how to use RMT module. - * - * ----------------EXAMPLE OF RMT SETTING --------------------- - * @code{c} - * //1. enable RMT - * //enable RMT module, or you can not set any register of it. - * //this will be done in rmt_config API. - * periph_module_enable(PERIPH_RMT_MODULE); - * @endcode - * - * @code{c} - * //2. set RMT transmitter - * void rmt_tx_init() - * { - * rmt_config_t rmt_tx; - * rmt_tx.channel = 0; - * rmt_tx.gpio_num = 16; - * rmt_tx.mem_block_num = 1; - * rmt_tx.clk_div = 100; - * rmt_tx.tx_config.loop_en = false; - * rmt_tx.tx_config.carrier_duty_percent = 50; - * rmt_tx.tx_config.carrier_freq_hz = 38000; - * rmt_tx.tx_config.carrier_level = 1; - * rmt_tx.tx_config.carrier_en = RMT_TX_CARRIER_EN; - * rmt_tx.tx_config.idle_level = 0; - * rmt_tx.tx_config.idle_output_en = true; - * rmt_tx.rmt_mode = 0; - * rmt_config(&rmt_tx); - * - * //install system RMT driver, disable rx ringbuffer for transmitter. - * rmt_driver_install(rmt_tx.channel, 0, 0); - * } - * - * @endcode - * @code{c} - * //3. set RMT receiver - * void rmt_rx_init() - * { - * rmt_config_t rmt_rx; - * rmt_rx.channel = 1; - * rmt_rx.gpio_num = 19; - * rmt_rx.clk_div = 100; - * rmt_rx.mem_block_num = 1; - * rmt_rx.rmt_mode = RMT_MODE_RX; - * rmt_rx.rx_config.filter_en = true; - * rmt_rx.rx_config.filter_ticks_thresh = 100; - * rmt_rx.rx_config.idle_threshold = 0xffff; - * rmt_config(&rmt_rx); - * - * //install system RMT driver. - * rmt_driver_install(rmt_rx.channel, 1000, 0); - * } - * +/* * ----------------EXAMPLE OF RMT INTERRUPT ------------------ * @code{c} * @@ -774,7 +719,7 @@ esp_err_t rmt_get_ringbuf_handle(rmt_channel_t channel, RingbufHandle_t* buf_han * //read RMT interrupt status. * uint32_t intr_st = RMT.int_st.val; * - * //you will find which channels have triggered fade_end interrupt here, + * //you will find which channels have triggered an interrupt here, * //then, you can post some event to RTOS queue to process the event. * //later we will add a queue in the driver code. * @@ -788,8 +733,6 @@ esp_err_t rmt_get_ringbuf_handle(rmt_channel_t channel, RingbufHandle_t* buf_han - - #ifdef __cplusplus } #endif diff --git a/docs/api-reference/peripherals/rmt.rst b/docs/api-reference/peripherals/rmt.rst index 5097a5f0e5..7d16efd8de 100644 --- a/docs/api-reference/peripherals/rmt.rst +++ b/docs/api-reference/peripherals/rmt.rst @@ -1,15 +1,160 @@ RMT -======== +=== -Overview --------- +The RMT (Remote Control) module driver can be used to send and receive infrared remote control signals. Due to flexibility of RMT module, the driver can also be used to generate or receive many other types of signals. -The RMT (Remote Control) module driver can be used to send and receive infrared remote control signals. Due to flexibility of RMT module, the driver can also be used to generate many other types of signals. +There couple of typical steps to setup and operate the RMT and they are discussed in the following sections: -Application Example -------------------- +1. `Configure Driver`_ +2. `Transmit Data`_ or `Receive Data`_ +3. `Change Operation Parameters`_ +4. `Use Interrupts`_ + +The RMT has eight channels numbered from zero to seven. Each channel is able to independently transmit or receive data. They are refereed to using indexes defined in structure :cpp:type:`rmt_channel_t`. + + +Configure Driver +---------------- + +There are several parameters that define how particular channel operates. Most of these parameters are configured by setting specific members of :cpp:type:`rmt_config_t` structure. Some of the parameters are common to both transmit or receive mode, and some are mode specific. They are all discussed below. + + +Common Parameters +^^^^^^^^^^^^^^^^^ + +* The **channel** that to be configured to be configured, select one from the :cpp:type:`rmt_channel_t` enumerator. +* The RMT **operation mode** - whether this channel is used to transmit or receive data, selected by setting a **rmt_mode** members to one of the values from :cpp:type:`rmt_mode_t`. +* What is the **pin number** to transmit or receive RMT signals, selected by setting **gpio_num**. +* How many **memory blocks** will be used by the channel, set with **mem_block_num**. +* A **clock divider**, that will determine the range of pulse length generated by the RMT transmitter or discriminated by the receiver. Selected by setting **clk_div** to a value within [1 .. 255] range. The RMT source clock is typically APB CLK, 80Mhz by default. + +.. note:: + + The period of a square valve after the clock divider is called a 'tick'. The length the pulses generated by the RMT transmitter or discriminated by the receiver is configured in number of 'ticks'. + +There are also couple of specific parameters that should be set up depending if selected channel is configured in `Transmit Mode`_ or `Receive Mode`_: + + +Transmit Mode +^^^^^^^^^^^^^ + +When configuring channel in transmit mode, set **tx_config** and the following members of :cpp:type:`rmt_tx_config_t`: + +* Transmit the currently configured data items in a loop - **loop_en** +* Enable the RMT carrier signal - **carrier_en** +* Frequency of the carrier in Hz - **carrier_freq_hz** +* Duty cycle of the carrier signal in percent (%) - **carrier_duty_percent** +* Level of the RMT output, when the carrier is applied - **carrier_level** +* Enable the RMT output if idle - **idle_output_en** +* Set the signal level on the RMT output if idle - **idle_level** + + +Receive Mode +^^^^^^^^^^^^ + +In receive mode, set **rx_config** and the following members of :cpp:type:`rmt_rx_config_t`: + +* Enable a filter on the input of the RMT receiver - **filter_en** +* A threshold of the filter, set in the number of ticks - **filter_ticks_thresh**. Pulses shorter than this setting will be filtered out. Note, that the range of entered tick values is [0..255]. +* A pulse length threshold that will turn the RMT receiver idle, set in number of ticks - **idle_threshold**. The receiver will ignore pulses longer than this setting. + + +Finalize Configuration +^^^^^^^^^^^^^^^^^^^^^^ + +Once the :cpp:type:`rmt_config_t` structure is populated with parameters, it should be then invoked with :cpp:func:`rmt_config` to make the configuration effective. + +The last configuration step is installation of the driver in memory by calling :cpp:func:`rmt_driver_install`. If :cpp:type:`rx_buf_size` parameter of this function is > 0, then a ring buffer for incoming data will be allocated. A default ISR handler will be installed, see a note in `Use Interrupts`_. + +Now, depending on how the channel is configured, we are ready to either `Transmit Data`_ or `Receive Data`_. This is described in next two sections. + + +Transmit Data +------------- + +Before being able to transmit some RMT pulses, we need to define the pulse pattern. The minimum pattern recognized by the RMT controller, later called an 'item', is provided in a structure :cpp:type:`rmt_item32_t`, see :component_file:`soc/esp32/include/soc/rmt_struct.h`. Each 'item' consists of two pairs of two values. The first value in a pair describes the signal duration in ticks, the second provides the signal level (high or low). For example how to define and populate items see an example application :example:`peripherals/rmt_tx`. + +The items are provided to the RMT controller by calling function :cpp:func:`rmt_write_items`. This function also automatically triggers start of transmission. It may be called to wait for transmission completion or exit just after transmission start. In such case you can wait for the transmission end by calling :cpp:func:`rmt_wait_tx_done`. This function does not limit the number of data items to transmit. It is using an interrupt to successively copy the new data chunks to RMT's internal memory as previously provided data are sent out. + +Another way to provide data for transmission is by calling :cpp:func:`rmt_fill_tx_items`. In this case transmission is not started automatically. To control the transmission process use :cpp:func:`rmt_tx_start` and :cpp:func:`rmt_tx_stop`. The number of items to sent is restricted by the size of memory blocks allocated in the RMT controller's internal memory, see :cpp:func:`rmt_set_mem_block_num`. + + +Receive Data +------------ + +Before starting the receiver we need some storage for incoming items. The RMT controller has 512 x 32-bits of internal RAM shared between all eight channels. In typical scenarios it is not enough as an ultimate storage for all incoming (and outgoing) items. Therefore this API supports retrieval of incoming items on the fly to save them in a ring buffer of a size defined by the user. The size is provided when calling :cpp:func:`rmt_driver_install` discussed above. To get a handle to this buffer call :cpp:func:`rmt_get_ringbuf_handle`. + +With the above steps complete we can start the receiver by calling :cpp:func:`rmt_rx_start` and then move to checking what's inside the buffer. To do so, you can use common FreeRTOS functions that interact with the ring buffer. Please see an example how to do it in :example:`peripherals/rmt_nec_tx_rx`. + +To stop the receiver, call :cpp:func:`rmt_rx_stop`. + + +Change Operation Parameters +--------------------------- + +Previously described function :cpp:func:`rmt_config` provides a convenient way to set several configuration parameters in one shot. This is usually done on application start. Then, when the application is running, the API provides an alternate way to update individual parameters by calling dedicated functions. Each function refers to the specific RMT channel provided as the first input parameter. Most of the functions have `_get_` counterpart to read back the currently configured value. + + +Parameters Common to Transmit and Receive Mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Selection of a GPIO pin number on the input or output of the RMT - :cpp:func:`rmt_set_pin` +* Number of memory blocks allocated for the incoming or outgoing data - :cpp:func:`rmt_set_mem_pd` +* Setting of the clock divider - :cpp:func:`rmt_set_clk_div` +* Selection of the clock source, note that currently one clock source is supported, the APB clock which is 80Mhz - :cpp:func:`rmt_set_source_clk` + + +Transmit Mode Parameters +^^^^^^^^^^^^^^^^^^^^^^^^ + +* Enable or disable the loop back mode for the transmitter - :cpp:func:`rmt_set_tx_loop_mode` +* Binary level on the output to apply the carrier - :cpp:func:`rmt_set_tx_carrier`, selected from :cpp:type:`rmt_carrier_level_t` +* Determines the binary level on the output when transmitter is idle - :cpp:func:`rmt_set_idle_level()`, selected from :cpp:type:`rmt_idle_level_t` + + +Receive Mode Parameters +^^^^^^^^^^^^^^^^^^^^^^^ + +* The filter setting - :cpp:func:`rmt_set_rx_filter` +* The receiver threshold setting - :cpp:func:`rmt_set_rx_idle_thresh` +* Whether the transmitter or receiver is entitled to access RMT's memory - :cpp:func:`rmt_set_memory_owner`, selection is from :cpp:type:`rmt_mem_owner_t`. + + +Use Interrupts +-------------- + +Registering of an interrupt handler for the RMT controller is done be calling :cpp:func:`rmt_isr_register`. + +.. note:: + + When calling :cpp:func:`rmt_driver_install` to use the system RMT driver, a default ISR is being installed. In such case you cannot register a generic ISR handler with :cpp:func:`rmt_isr_register`. + +The RMT controller triggers interrupts on four specific events describes below. To enable interrupts on these events, the following functions are provided: + +* RMT's receiver has finished receiving a signal - :cpp:func:`rmt_set_rx_intr_en` +* Ownership to the RMT memory block has been violated - :cpp:func:`rmt_set_err_intr_en` +* RMT's transmitter has finished transmitting the signal - :cpp:func:`rmt_set_tx_intr_en` +* The number of events the transmitter has sent matches a threshold value :cpp:func:`rmt_set_tx_thr_intr_en` + +Setting or clearing an interrupt enable mask for specific channels and events may be also done by calling :cpp:func:`rmt_set_intr_enable_mask` or :cpp:func:`rmt_clr_intr_enable_mask`. + +When servicing an interrupt within an ISR, the interrupt need to explicitly cleared. To do so, set specific bits described as ``RMT.int_clr.val.chN_event_name`` and defined as a ``volatile struct`` in :component_file:`soc/esp32/include/soc/rmt_struct.h`, where N is the RMT channel number [0, 7] and the ``event_name`` is one of four events described above. + +If you do not need an ISR anymore, you can deregister it by calling a function :cpp:func:`rmt_isr_deregister`. + + +Uninstall Driver +---------------- + +If the RMT driver has been installed with :cpp:func:`rmt_driver_install` for some specific period of time and then not required, the driver may be removed to free allocated resources by calling :cpp:func:`rmt_driver_uninstall`. + + +Application Examples +-------------------- + +* A simple RMT TX example: :example:`peripherals/rmt_tx`. +* NEC remote control TX and RX example: :example:`peripherals/rmt_nec_tx_rx`. -NEC remote control TX and RX example: :example:`peripherals/rmt_nec_tx_rx`. API Reference ------------- diff --git a/examples/peripherals/rmt_tx/Makefile b/examples/peripherals/rmt_tx/Makefile new file mode 100644 index 0000000000..f4b09f84a6 --- /dev/null +++ b/examples/peripherals/rmt_tx/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := rmt_tx + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/peripherals/rmt_tx/README.md b/examples/peripherals/rmt_tx/README.md new file mode 100644 index 0000000000..5e63859845 --- /dev/null +++ b/examples/peripherals/rmt_tx/README.md @@ -0,0 +1,25 @@ +# RMT Transmit Example + +This example shows how to configure and operate the remote control (RMT) peripheral to transmit a sample message in the [Morse code](https://en.wikipedia.org/wiki/Morse_code). + +Configuration (pin number, etc.) can be modified in the top of the `main/rmt_tx_main.c` file. + +To be able to see and hear the message output by the RMT, connect a LED and a speaker or an earphone (be careful - it may be loud) to the GPIO configured under `RMT_TX_GPIO` define (default is GPIO 18). + +Example connections: + +``` + 330R LED +GPIO18 +----/\/\/\----+------|>|-----+ GND + | + | /| + +-+ | Speaker + | | | or + +-+ | earphone + | \| + | + +--------------+ GND +``` + + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/peripherals/rmt_tx/main/component.mk b/examples/peripherals/rmt_tx/main/component.mk new file mode 100644 index 0000000000..b4fa72791c --- /dev/null +++ b/examples/peripherals/rmt_tx/main/component.mk @@ -0,0 +1,4 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/peripherals/rmt_tx/main/rmt_tx_main.c b/examples/peripherals/rmt_tx/main/rmt_tx_main.c new file mode 100644 index 0000000000..b19dbc2b49 --- /dev/null +++ b/examples/peripherals/rmt_tx/main/rmt_tx_main.c @@ -0,0 +1,119 @@ +/* RMT transmit example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "driver/rmt.h" + +static const char *RMT_TX_TAG = "RMT Tx"; + +#define RMT_TX_CHANNEL RMT_CHANNEL_0 +#define RMT_TX_GPIO 18 +#define RMT_MESSAGE_LENGTH 12 + +rmt_item32_t items[RMT_MESSAGE_LENGTH]; + +/* + * Prepare a table with a message in the Morse code + * + * The message is "ESP" : . ... .--. + * + * The table structure: + * {duration, level, duration, level} + * + */ +uint32_t message[RMT_MESSAGE_LENGTH][4] = { + // E : dot + {32767, 1, 32767, 0}, // dot + // + {32767, 0, 32767, 0}, // SPACE + // S : dot, dot, dot + {32767, 1, 32767, 0}, // dot + {32767, 1, 32767, 0}, // dot + {32767, 1, 32767, 0}, // dot + // + {32767, 0, 32767, 0}, // SPACE + // P : dot, dash, dash, dot + {32767, 1, 32767, 0}, // dot + {32767, 1, 32767, 1}, + {32767, 1, 32767, 0}, // dash + {32767, 1, 32767, 1}, + {32767, 1, 32767, 0}, // dash + {32767, 1, 32767, 0} // dot +}; + + +/* + * Populate the RMT items array + * with a previously prepared message + */ +static void populate_rmt_items(void) +{ + for (int i = 0; i < RMT_MESSAGE_LENGTH; i++) { + items[i].duration0 = message[i][0]; + items[i].level0 = message[i][1]; + items[i].duration1 = message[i][2]; + items[i].level1 = message[i][3]; + } +} + + +/* + * Initialize the RMT Tx channel + */ +static void rmt_tx_int() +{ + rmt_config_t config; + config.rmt_mode = RMT_MODE_TX; + config.channel = RMT_TX_CHANNEL; + config.gpio_num = RMT_TX_GPIO; + config.mem_block_num = 1; + config.tx_config.loop_en = 0; + // enable the carrier to be able to hear the Morse sound + // if the RMT_TX_GPIO is connected to a speaker + config.tx_config.carrier_en = 1; + config.tx_config.idle_output_en = 1; + config.tx_config.idle_level = 0; + config.tx_config.carrier_duty_percent = 50; + // set audible career frequency of 611 Hz + // actually 611 Hz is the minimum, that can be set + // with current implementation of the RMT API + config.tx_config.carrier_freq_hz = 611; + config.tx_config.carrier_level = 1; + // set the maximum clock divider to be able to output + // RMT pulses in range of about one hundred milliseconds + config.clk_div = 255; + + ESP_ERROR_CHECK(rmt_config(&config)); + ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0)); +} + + +/* + * Transmit all the items in a loop + */ +static void rmt_tx_task(void *ignore) +{ + while (1) { + ESP_ERROR_CHECK(rmt_write_items(RMT_TX_CHANNEL, items, RMT_MESSAGE_LENGTH, 1)); + ESP_LOGI(RMT_TX_TAG, "Transmission complete"); + vTaskDelay(2000 / portTICK_PERIOD_MS); + } +} + + +void app_main(void *ignore) +{ + ESP_LOGI(RMT_TX_TAG, "Configuring transmitter"); + rmt_tx_int(); + populate_rmt_items(); + + ESP_LOGI(RMT_TX_TAG, "Spinning out transmit task"); + xTaskCreatePinnedToCore(&rmt_tx_task, "rmt_tx_task", 4 * 1024, NULL, 5, NULL, 0); +} From cdad1e83828b3e6ace47a54e734ee5bc0ba10052 Mon Sep 17 00:00:00 2001 From: krzychb Date: Wed, 22 Nov 2017 07:07:49 +0100 Subject: [PATCH 2/4] Implement review comments --- docs/api-reference/peripherals/rmt.rst | 25 ++++++- .../peripherals/rmt_tx/main/rmt_tx_main.c | 74 +++++++------------ 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/docs/api-reference/peripherals/rmt.rst b/docs/api-reference/peripherals/rmt.rst index 7d16efd8de..2f7787c207 100644 --- a/docs/api-reference/peripherals/rmt.rst +++ b/docs/api-reference/peripherals/rmt.rst @@ -72,7 +72,30 @@ Now, depending on how the channel is configured, we are ready to either `Transmi Transmit Data ------------- -Before being able to transmit some RMT pulses, we need to define the pulse pattern. The minimum pattern recognized by the RMT controller, later called an 'item', is provided in a structure :cpp:type:`rmt_item32_t`, see :component_file:`soc/esp32/include/soc/rmt_struct.h`. Each 'item' consists of two pairs of two values. The first value in a pair describes the signal duration in ticks, the second provides the signal level (high or low). For example how to define and populate items see an example application :example:`peripherals/rmt_tx`. +Before being able to transmit some RMT pulses, we need to define the pulse pattern. The minimum pattern recognized by the RMT controller, later called an 'item', is provided in a structure :cpp:type:`rmt_item32_t`, see :component_file:`soc/esp32/include/soc/rmt_struct.h`. Each item consists of two pairs of two values. The first value in a pair describes the signal duration in ticks and is 15 bits long, the second provides the signal level (high or low) and is contained in a single bit. A block of couple of items and the structure of an item is presented below. + +.. packetdiag:: + :caption: Structure of RMT items (L - signal level) + :align: center + + packetdiag rmt_items { + colwidth = 32 + node_width = 10 + node_height = 24 + default_fontsize = 12 + + 0-14: Period (15) + 15: L + 16-30: Period (15) + 31: L + 32-95: ... [colheight=2] + 96-110: Period (15) + 111: L + 112-126: Period (15) + 127: L + } + +For a simple example how to define a block of items see :example:`peripherals/rmt_tx`. The items are provided to the RMT controller by calling function :cpp:func:`rmt_write_items`. This function also automatically triggers start of transmission. It may be called to wait for transmission completion or exit just after transmission start. In such case you can wait for the transmission end by calling :cpp:func:`rmt_wait_tx_done`. This function does not limit the number of data items to transmit. It is using an interrupt to successively copy the new data chunks to RMT's internal memory as previously provided data are sent out. diff --git a/examples/peripherals/rmt_tx/main/rmt_tx_main.c b/examples/peripherals/rmt_tx/main/rmt_tx_main.c index b19dbc2b49..d71663a58e 100644 --- a/examples/peripherals/rmt_tx/main/rmt_tx_main.c +++ b/examples/peripherals/rmt_tx/main/rmt_tx_main.c @@ -15,55 +15,40 @@ static const char *RMT_TX_TAG = "RMT Tx"; #define RMT_TX_CHANNEL RMT_CHANNEL_0 #define RMT_TX_GPIO 18 -#define RMT_MESSAGE_LENGTH 12 - -rmt_item32_t items[RMT_MESSAGE_LENGTH]; /* - * Prepare a table with a message in the Morse code + * Prepare a raw table with a message in the Morse code * * The message is "ESP" : . ... .--. * - * The table structure: + * The table structure represents the RMT item structure: * {duration, level, duration, level} * */ -uint32_t message[RMT_MESSAGE_LENGTH][4] = { +rmt_item32_t items[] = { // E : dot - {32767, 1, 32767, 0}, // dot + {{{ 32767, 1, 32767, 0 }}}, // dot // - {32767, 0, 32767, 0}, // SPACE + {{{ 32767, 0, 32767, 0 }}}, // SPACE // S : dot, dot, dot - {32767, 1, 32767, 0}, // dot - {32767, 1, 32767, 0}, // dot - {32767, 1, 32767, 0}, // dot + {{{ 32767, 1, 32767, 0 }}}, // dot + {{{ 32767, 1, 32767, 0 }}}, // dot + {{{ 32767, 1, 32767, 0 }}}, // dot // - {32767, 0, 32767, 0}, // SPACE + {{{ 32767, 0, 32767, 0 }}}, // SPACE // P : dot, dash, dash, dot - {32767, 1, 32767, 0}, // dot - {32767, 1, 32767, 1}, - {32767, 1, 32767, 0}, // dash - {32767, 1, 32767, 1}, - {32767, 1, 32767, 0}, // dash - {32767, 1, 32767, 0} // dot + {{{ 32767, 1, 32767, 0 }}}, // dot + {{{ 32767, 1, 32767, 1 }}}, + {{{ 32767, 1, 32767, 0 }}}, // dash + {{{ 32767, 1, 32767, 1 }}}, + {{{ 32767, 1, 32767, 0 }}}, // dash + {{{ 32767, 1, 32767, 0 }}}, // dot + + // RMT end marker + {{{ 0, 1, 0, 0 }}} }; -/* - * Populate the RMT items array - * with a previously prepared message - */ -static void populate_rmt_items(void) -{ - for (int i = 0; i < RMT_MESSAGE_LENGTH; i++) { - items[i].duration0 = message[i][0]; - items[i].level0 = message[i][1]; - items[i].duration1 = message[i][2]; - items[i].level1 = message[i][3]; - } -} - - /* * Initialize the RMT Tx channel */ @@ -95,25 +80,16 @@ static void rmt_tx_int() } -/* - * Transmit all the items in a loop - */ -static void rmt_tx_task(void *ignore) -{ - while (1) { - ESP_ERROR_CHECK(rmt_write_items(RMT_TX_CHANNEL, items, RMT_MESSAGE_LENGTH, 1)); - ESP_LOGI(RMT_TX_TAG, "Transmission complete"); - vTaskDelay(2000 / portTICK_PERIOD_MS); - } -} - - void app_main(void *ignore) { ESP_LOGI(RMT_TX_TAG, "Configuring transmitter"); rmt_tx_int(); - populate_rmt_items(); + int number_of_items = sizeof(items) / sizeof(items[0]); - ESP_LOGI(RMT_TX_TAG, "Spinning out transmit task"); - xTaskCreatePinnedToCore(&rmt_tx_task, "rmt_tx_task", 4 * 1024, NULL, 5, NULL, 0); + while (1) { + ESP_ERROR_CHECK(rmt_write_items(RMT_TX_CHANNEL, items, number_of_items, true)); + ESP_LOGI(RMT_TX_TAG, "Transmission complete"); + vTaskDelay(2000 / portTICK_PERIOD_MS); + } + vTaskDelete(NULL); } From 2b010d4bc92b2f72724f3eb7e815d25cb899eea4 Mon Sep 17 00:00:00 2001 From: krzychb Date: Thu, 23 Nov 2017 23:53:06 +0100 Subject: [PATCH 3/4] RMT transmitter and receiver overview pictures --- docs/_static/rmt-carrier.png | Bin 0 -> 4491 bytes docs/_static/rmt-waveform-modulated.png | Bin 0 -> 4250 bytes docs/_static/rmt-waveform.png | Bin 0 -> 3270 bytes docs/api-reference/peripherals/rmt.rst | 83 +++++++++++++++++++++++- 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 docs/_static/rmt-carrier.png create mode 100644 docs/_static/rmt-waveform-modulated.png create mode 100644 docs/_static/rmt-waveform.png diff --git a/docs/_static/rmt-carrier.png b/docs/_static/rmt-carrier.png new file mode 100644 index 0000000000000000000000000000000000000000..41d1c8d8d0b168261e0f9514c444a87d7c1aa0a1 GIT binary patch literal 4491 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 PSAZk#K5mt+VJZIviM`tb literal 0 HcmV?d00001 diff --git a/docs/_static/rmt-waveform-modulated.png b/docs/_static/rmt-waveform-modulated.png new file mode 100644 index 0000000000000000000000000000000000000000..448b73758c35b285581ff6a1b57001225fdb814d GIT binary patch literal 4250 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 L?>5R8hyL<+yx(#S literal 0 HcmV?d00001 diff --git a/docs/api-reference/peripherals/rmt.rst b/docs/api-reference/peripherals/rmt.rst index 2f7787c207..77c3e06956 100644 --- a/docs/api-reference/peripherals/rmt.rst +++ b/docs/api-reference/peripherals/rmt.rst @@ -3,6 +3,87 @@ RMT The RMT (Remote Control) module driver can be used to send and receive infrared remote control signals. Due to flexibility of RMT module, the driver can also be used to generate or receive many other types of signals. +The signal, that consists of a series of pulses, is generated by RMT's transmitter basing on a list of values. The values define the pulse duration and a binary level, see below. The transmitter can also provide a carrier and modulate it with provided pulses. + +.. blockdiag:: + :scale: 100 + :caption: RMT Transmitter Overview + :align: center + + blockdiag rmt_tx { + + node_width = 80; + node_height = 60; + default_group_color = lightgrey; + + a -> b -> c -> d; + e -> f -> g -- h; + d -> o [label=GPIO]; + h -> d [folded]; + + a [style=none, width=100, label="{11,high,7,low},\n{5,high,5,low},\n..."] + b [label="Waveform\nGenerator"] + c [style=none, label="", background="_static/rmt-waveform.png"] + d [shape=beginpoint, label="mod"] + e [style=none, width=60, height=40, label="Carrier\nenable"] + f [label="Carrier\nGenerator"] + g [style=none, label="", background="_static/rmt-carrier.png"] + h [shape=none] + o [style=none, label="", background="_static/rmt-waveform-modulated.png"] + + group { + label = Input + a,e; + } + group { + label = "RMT Transmitter" + b,f,c,g,d,h; + } + group { + label = Output + o; + } + } + +Reverse operation is performed by the receiver, where a series of pulses is decoded into a list of values containing the pulse duration and binary level. A filter may be applied to remove high frequency noise from the input signal. + +.. blockdiag:: + :scale: 90 + :caption: RMT Receiver Overview + :align: center + + blockdiag rmt_rx { + + node_width = 80; + node_height = 60; + default_group_color = lightgrey; + + a -> b [label=GPIO]; + b -> c -> d; + e -- f; + f -> b [folded]; + + a [style=none, label="", background="_static/rmt-waveform.png"] + b [label=Filter] + c [label="Edge\nDetect"] + d [style=none, width=100, label="{11,high,7,low},\n{5,high,5,low},\n..."] + e [style=none, width=60, height=40, label="Filter\nenable"] + f [shape=none, label=""] + + group { + label = Input + a,e; + } + group { + label = "RMT Receiver" + b,c; + } + group { + label = Output + d; + } + } + There couple of typical steps to setup and operate the RMT and they are discussed in the following sections: 1. `Configure Driver`_ @@ -155,9 +236,9 @@ Registering of an interrupt handler for the RMT controller is done be calling :c The RMT controller triggers interrupts on four specific events describes below. To enable interrupts on these events, the following functions are provided: * RMT's receiver has finished receiving a signal - :cpp:func:`rmt_set_rx_intr_en` -* Ownership to the RMT memory block has been violated - :cpp:func:`rmt_set_err_intr_en` * RMT's transmitter has finished transmitting the signal - :cpp:func:`rmt_set_tx_intr_en` * The number of events the transmitter has sent matches a threshold value :cpp:func:`rmt_set_tx_thr_intr_en` +* Ownership to the RMT memory block has been violated - :cpp:func:`rmt_set_err_intr_en` Setting or clearing an interrupt enable mask for specific channels and events may be also done by calling :cpp:func:`rmt_set_intr_enable_mask` or :cpp:func:`rmt_clr_intr_enable_mask`. From fe1e1e2f8e43d65c52249422bcc73649106f0969 Mon Sep 17 00:00:00 2001 From: krzychb Date: Fri, 1 Dec 2017 07:29:54 +0100 Subject: [PATCH 4/4] Review comments implemented --- docs/api-reference/peripherals/rmt.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/api-reference/peripherals/rmt.rst b/docs/api-reference/peripherals/rmt.rst index 77c3e06956..359344a764 100644 --- a/docs/api-reference/peripherals/rmt.rst +++ b/docs/api-reference/peripherals/rmt.rst @@ -3,7 +3,7 @@ RMT The RMT (Remote Control) module driver can be used to send and receive infrared remote control signals. Due to flexibility of RMT module, the driver can also be used to generate or receive many other types of signals. -The signal, that consists of a series of pulses, is generated by RMT's transmitter basing on a list of values. The values define the pulse duration and a binary level, see below. The transmitter can also provide a carrier and modulate it with provided pulses. +The signal, which consists of a series of pulses, is generated by RMT's transmitter based on a list of values. The values define the pulse duration and a binary level, see below. The transmitter can also provide a carrier and modulate it with provided pulses. .. blockdiag:: :scale: 100 @@ -45,7 +45,7 @@ The signal, that consists of a series of pulses, is generated by RMT's transmitt } } -Reverse operation is performed by the receiver, where a series of pulses is decoded into a list of values containing the pulse duration and binary level. A filter may be applied to remove high frequency noise from the input signal. +The reverse operation is performed by the receiver, where a series of pulses is decoded into a list of values containing the pulse duration and binary level. A filter may be applied to remove high frequency noise from the input signal. .. blockdiag:: :scale: 90 @@ -91,7 +91,7 @@ There couple of typical steps to setup and operate the RMT and they are discusse 3. `Change Operation Parameters`_ 4. `Use Interrupts`_ -The RMT has eight channels numbered from zero to seven. Each channel is able to independently transmit or receive data. They are refereed to using indexes defined in structure :cpp:type:`rmt_channel_t`. +The RMT has eight channels numbered from zero to seven. Each channel is able to independently transmit or receive data. They are referred to using indexes defined in structure :cpp:type:`rmt_channel_t`. Configure Driver @@ -103,7 +103,7 @@ There are several parameters that define how particular channel operates. Most o Common Parameters ^^^^^^^^^^^^^^^^^ -* The **channel** that to be configured to be configured, select one from the :cpp:type:`rmt_channel_t` enumerator. +* The **channel** to be configured, select one from the :cpp:type:`rmt_channel_t` enumerator. * The RMT **operation mode** - whether this channel is used to transmit or receive data, selected by setting a **rmt_mode** members to one of the values from :cpp:type:`rmt_mode_t`. * What is the **pin number** to transmit or receive RMT signals, selected by setting **gpio_num**. * How many **memory blocks** will be used by the channel, set with **mem_block_num**. @@ -111,7 +111,7 @@ Common Parameters .. note:: - The period of a square valve after the clock divider is called a 'tick'. The length the pulses generated by the RMT transmitter or discriminated by the receiver is configured in number of 'ticks'. + The period of a square wave after the clock divider is called a 'tick'. The length of the pulses generated by the RMT transmitter or discriminated by the receiver is configured in number of 'ticks'. There are also couple of specific parameters that should be set up depending if selected channel is configured in `Transmit Mode`_ or `Receive Mode`_: @@ -231,12 +231,12 @@ Registering of an interrupt handler for the RMT controller is done be calling :c .. note:: - When calling :cpp:func:`rmt_driver_install` to use the system RMT driver, a default ISR is being installed. In such case you cannot register a generic ISR handler with :cpp:func:`rmt_isr_register`. + When calling :cpp:func:`rmt_driver_install` to use the system RMT driver, a default ISR is being installed. In such a case you cannot register a generic ISR handler with :cpp:func:`rmt_isr_register`. The RMT controller triggers interrupts on four specific events describes below. To enable interrupts on these events, the following functions are provided: -* RMT's receiver has finished receiving a signal - :cpp:func:`rmt_set_rx_intr_en` -* RMT's transmitter has finished transmitting the signal - :cpp:func:`rmt_set_tx_intr_en` +* The RMT receiver has finished receiving a signal - :cpp:func:`rmt_set_rx_intr_en` +* The RMT transmitter has finished transmitting the signal - :cpp:func:`rmt_set_tx_intr_en` * The number of events the transmitter has sent matches a threshold value :cpp:func:`rmt_set_tx_thr_intr_en` * Ownership to the RMT memory block has been violated - :cpp:func:`rmt_set_err_intr_en`