From efa92cb2043d055f1e627cbbe32c8963629a2d49 Mon Sep 17 00:00:00 2001 From: morris Date: Fri, 19 Feb 2021 17:38:03 +0800 Subject: [PATCH] rmt: support invert RMT signal by GPIO matrix --- components/driver/include/driver/rmt.h | 28 ++++++++++++++++++----- components/driver/rmt.c | 14 ++++++++---- docs/en/api-reference/peripherals/rmt.rst | 3 ++- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/components/driver/include/driver/rmt.h b/components/driver/include/driver/rmt.h index ca4734d029..ef9d58107d 100644 --- a/components/driver/include/driver/rmt.h +++ b/components/driver/include/driver/rmt.h @@ -29,6 +29,7 @@ extern "C" { #include "hal/rmt_types.h" #define RMT_CHANNEL_FLAGS_AWARE_DFS (1 << 0) /*!< Channel can work during APB clock scaling */ +#define RMT_CHANNEL_FLAGS_INVERT_SIG (1 << 1) /*!< Invert RMT signal */ /** @cond */ #define RMT_CHANNEL_FLAGS_ALWAYS_ON RMT_CHANNEL_FLAGS_AWARE_DFS /*!< Deprecated name, defined here for compatibility */ @@ -572,17 +573,18 @@ 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 pin +* @brief Configure the GPIO used by RMT channel * * @param channel RMT channel -* @param mode TX or RX mode for RMT -* @param gpio_num GPIO number to transmit or receive the signal. +* @param mode RMT mode, either RMT_MODE_TX or RMT_MODE_RX +* @param gpio_num GPIO number, which is connected with certain RMT signal +* @param invert_signal Invert RMT signal physically by GPIO matrix * * @return -* - ESP_ERR_INVALID_ARG Parameter error -* - ESP_OK Success +* - ESP_ERR_INVALID_ARG Configure RMT GPIO failed because of wrong parameter +* - ESP_OK Configure RMT GPIO successfully */ -esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_num); +esp_err_t rmt_set_gpio(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_num, bool invert_signal); /** * @brief Configure RMT parameters @@ -903,6 +905,20 @@ __attribute__((deprecated("interrupt should be handled by driver"))); void rmt_clr_intr_enable_mask(uint32_t mask) __attribute__((deprecated("interrupt should be handled by driver"))); +/** +* @brief Set RMT pin +* +* @param channel RMT channel +* @param mode TX or RX mode for RMT +* @param gpio_num GPIO number to transmit or receive the signal. +* +* @return +* - ESP_ERR_INVALID_ARG Parameter error +* - ESP_OK Success +*/ +esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_num) +__attribute__((deprecated("use rmt_set_gpio instead"))); + #ifdef __cplusplus } #endif diff --git a/components/driver/rmt.c b/components/driver/rmt.c index 2e1daf5761..12c29dde30 100644 --- a/components/driver/rmt.c +++ b/components/driver/rmt.c @@ -528,7 +528,7 @@ esp_err_t rmt_set_tx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_th return ESP_OK; } -esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_num) +esp_err_t rmt_set_gpio(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_num, bool invert_signal) { RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(mode < RMT_MODE_MAX, RMT_MODE_ERROR_STR, ESP_ERR_INVALID_ARG); @@ -540,15 +540,21 @@ esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_nu if (mode == RMT_MODE_TX) { RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(gpio_num, rmt_periph_signals.channels[channel].tx_sig, 0, 0); + esp_rom_gpio_connect_out_signal(gpio_num, rmt_periph_signals.channels[channel].tx_sig, invert_signal, 0); } else { RMT_CHECK(RMT_IS_RX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); gpio_set_direction(gpio_num, GPIO_MODE_INPUT); - esp_rom_gpio_connect_in_signal(gpio_num, rmt_periph_signals.channels[channel].rx_sig, 0); + esp_rom_gpio_connect_in_signal(gpio_num, rmt_periph_signals.channels[channel].rx_sig, invert_signal); } return ESP_OK; } +esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_num) +{ + // only for backword compatibility + return rmt_set_gpio(channel, mode, gpio_num, false); +} + static bool rmt_is_channel_number_valid(rmt_channel_t channel, uint8_t mode) { // RX mode @@ -688,7 +694,7 @@ esp_err_t rmt_config(const rmt_config_t *rmt_param) { rmt_module_enable(); - RMT_CHECK(rmt_set_pin(rmt_param->channel, rmt_param->rmt_mode, rmt_param->gpio_num) == ESP_OK, + RMT_CHECK(rmt_set_gpio(rmt_param->channel, rmt_param->rmt_mode, rmt_param->gpio_num, rmt_param->flags & RMT_CHANNEL_FLAGS_INVERT_SIG) == ESP_OK, "set gpio for RMT driver failed", ESP_ERR_INVALID_ARG); RMT_CHECK(rmt_internal_config(&RMT, rmt_param) == ESP_OK, diff --git a/docs/en/api-reference/peripherals/rmt.rst b/docs/en/api-reference/peripherals/rmt.rst index ee0d83410f..2fced3f08a 100644 --- a/docs/en/api-reference/peripherals/rmt.rst +++ b/docs/en/api-reference/peripherals/rmt.rst @@ -119,6 +119,7 @@ Common Parameters * Extra miscellaneous parameters for the channel can be set in the **flags**. * When **RMT_CHANNEL_FLAGS_AWARE_DFS** is set, RMT channel will take REF_TICK or XTAL as source clock. The benefit is, RMT channel can continue work even when APB clock is changing. See :doc:`power_management <../system/power_management>` for more information. + * When **RMT_CHANNEL_FLAGS_INVERT_SIG** is set, the driver will invert the RMT signal sending to or receiving from the channel. It just works like an external inverter connected to the GPIO of certain RMT channel. * 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. But when **RMT_CHANNEL_FLAGS_AWARE_DFS** is set in **flags**, RMT source clock is changed to REF_TICK or XTAL. @@ -234,7 +235,7 @@ Previously described function :cpp:func:`rmt_config` provides a convenient way t 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` +* Selection of a GPIO pin number on the input or output of the RMT - :cpp:func:`rmt_set_gpio` * 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`