rmt: split TX and RX in LL driver

Split TX and RX function in LL driver.
Channel number is encoded in driver layer.
Added channel signal list in periph.c
This commit is contained in:
morris 2020-10-09 16:41:41 +08:00
parent 9465af0066
commit ff976867b3
21 changed files with 1208 additions and 863 deletions

View File

@ -28,7 +28,7 @@ extern "C" {
#include "soc/rmt_struct.h"
#include "hal/rmt_types.h"
#define RMT_CHANNEL_FLAGS_ALWAYS_ON (1 << 0) /*!< Channel can work when APB frequency is changing (RMT channel adopts REF_TICK as clock source) */
#define RMT_CHANNEL_FLAGS_ALWAYS_ON (1 << 0) /*!< Channel can work during APB clock scaling */
/**
* @brief Define memory space of each RMT channel (in words = 4 bytes)
@ -357,7 +357,7 @@ esp_err_t rmt_rx_start(rmt_channel_t channel, bool rx_idx_rst);
esp_err_t rmt_rx_stop(rmt_channel_t channel);
/**
* @brief Reset RMT TX/RX memory index.
* @brief Reset RMT TX memory
*
* @param channel RMT channel
*
@ -365,7 +365,18 @@ esp_err_t rmt_rx_stop(rmt_channel_t channel);
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
*/
esp_err_t rmt_memory_rw_rst(rmt_channel_t channel);
esp_err_t rmt_tx_memory_reset(rmt_channel_t channel);
/**
* @brief Reset RMT RX memory
*
* @param channel RMT channel
*
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
*/
esp_err_t rmt_rx_memory_reset(rmt_channel_t channel);
/**
* @brief Set RMT memory owner.
@ -504,22 +515,6 @@ esp_err_t rmt_get_idle_level(rmt_channel_t channel, bool *idle_out_en, rmt_idle_
*/
esp_err_t rmt_get_status(rmt_channel_t channel, uint32_t *status);
/**
* @brief Set mask value to RMT interrupt enable register.
*
* @param mask Bit mask to set to the register
*
*/
void rmt_set_intr_enable_mask(uint32_t mask);
/**
* @brief Clear mask value to RMT interrupt enable register.
*
* @param mask Bit mask to clear the register
*
*/
void rmt_clr_intr_enable_mask(uint32_t mask);
/**
* @brief Set RMT RX interrupt enable
*
@ -833,6 +828,36 @@ esp_err_t rmt_add_channel_to_group(rmt_channel_t channel);
esp_err_t rmt_remove_channel_from_group(rmt_channel_t channel);
#endif
/**
* @brief Reset RMT TX/RX memory index.
*
* @param channel RMT channel
*
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success
*/
esp_err_t rmt_memory_rw_rst(rmt_channel_t channel)
__attribute__((deprecated("use rmt_tx_memory_reset or rmt_rx_memory_reset instead")));
/**
* @brief Set mask value to RMT interrupt enable register.
*
* @param mask Bit mask to set to the register
*
*/
void rmt_set_intr_enable_mask(uint32_t mask)
__attribute__((deprecated("interrupt should be handled by driver")));
/**
* @brief Clear mask value to RMT interrupt enable register.
*
* @param mask Bit mask to clear the register
*
*/
void rmt_clr_intr_enable_mask(uint32_t mask)
__attribute__((deprecated("interrupt should be handled by driver")));
#ifdef __cplusplus
}
#endif

View File

@ -14,6 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/lock.h>
#include "esp_compiler.h"
#include "esp_intr_alloc.h"
#include "esp_log.h"
#include "driver/gpio.h"
@ -24,6 +25,7 @@
#include "freertos/semphr.h"
#include "freertos/ringbuf.h"
#include "soc/soc_memory_layout.h"
#include "soc/rmt_periph.h"
#include "soc/rtc.h"
#include "hal/rmt_hal.h"
#include "hal/rmt_ll.h"
@ -47,17 +49,24 @@
#define RMT_PARAM_ERR_STR "RMT param error"
static const char *RMT_TAG = "rmt";
#define RMT_CHECK(a, str, ret_val) \
if (!(a)) \
{ \
ESP_LOGE(RMT_TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \
return (ret_val); \
#define RMT_CHECK(a, str, ret_val, ...) \
if (unlikely(!(a))) { \
ESP_LOGE(RMT_TAG, "%s(%d): "str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
return (ret_val); \
}
// Spinlock for protecting concurrent register-level access only
#define RMT_ENTER_CRITICAL() portENTER_CRITICAL_SAFE(&(rmt_contex.rmt_spinlock))
#define RMT_EXIT_CRITICAL() portEXIT_CRITICAL_SAFE(&(rmt_contex.rmt_spinlock))
#define RMT_RX_CHANNEL_ENCODING_START (SOC_RMT_CHANNELS_NUM-SOC_RMT_TX_CHANNELS_NUM)
#define RMT_TX_CHANNEL_ENCODING_END (SOC_RMT_TX_CHANNELS_NUM-1)
#define RMT_IS_RX_CHANNEL(channel) ((channel) >= RMT_RX_CHANNEL_ENCODING_START)
#define RMT_IS_TX_CHANNEL(channel) ((channel) <= RMT_TX_CHANNEL_ENCODING_END)
#define RMT_DECODE_RX_CHANNEL(encode_chan) ((encode_chan - RMT_RX_CHANNEL_ENCODING_START))
#define RMT_ENCODE_RX_CHANNEL(decode_chan) ((decode_chan + RMT_RX_CHANNEL_ENCODING_START))
typedef struct {
rmt_hal_context_t hal;
_lock_t rmt_driver_isr_lock;
@ -108,13 +117,19 @@ static rmt_contex_t rmt_contex = {
static rmt_obj_t *p_rmt_obj[RMT_CHANNEL_MAX] = {0};
#if SOC_RMT_SOURCE_CLK_INDEPENDENT
static uint32_t s_rmt_source_clock_hz[RMT_CHANNEL_MAX];
#else
static uint32_t s_rmt_source_clock_hz;
#endif
//Enable RMT module
static void rmt_module_enable(void)
{
RMT_ENTER_CRITICAL();
if (rmt_contex.rmt_module_enabled == false) {
periph_module_reset(PERIPH_RMT_MODULE);
periph_module_enable(PERIPH_RMT_MODULE);
periph_module_reset(rmt_periph_signals.module);
periph_module_enable(rmt_periph_signals.module);
rmt_contex.rmt_module_enabled = true;
}
RMT_EXIT_CRITICAL();
@ -125,7 +140,7 @@ static void rmt_module_disable(void)
{
RMT_ENTER_CRITICAL();
if (rmt_contex.rmt_module_enabled == true) {
periph_module_disable(PERIPH_RMT_MODULE);
periph_module_disable(rmt_periph_signals.module);
rmt_contex.rmt_module_enabled = false;
}
RMT_EXIT_CRITICAL();
@ -135,7 +150,11 @@ esp_err_t rmt_set_clk_div(rmt_channel_t channel, uint8_t div_cnt)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_set_counter_clock_div(rmt_contex.hal.regs, channel, div_cnt);
if (RMT_IS_RX_CHANNEL(channel)) {
rmt_ll_rx_set_counter_clock_div(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), div_cnt);
} else {
rmt_ll_tx_set_counter_clock_div(rmt_contex.hal.regs, channel, div_cnt);
}
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -145,26 +164,30 @@ esp_err_t rmt_get_clk_div(rmt_channel_t channel, uint8_t *div_cnt)
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(div_cnt != NULL, RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
*div_cnt = (uint8_t)rmt_ll_get_counter_clock_div(rmt_contex.hal.regs, channel);
if (RMT_IS_RX_CHANNEL(channel)) {
*div_cnt = (uint8_t)rmt_ll_rx_get_counter_clock_div(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
} else {
*div_cnt = (uint8_t)rmt_ll_tx_get_counter_clock_div(rmt_contex.hal.regs, channel);
}
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_set_rx_idle_thresh(rmt_channel_t channel, uint16_t thresh)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_set_rx_idle_thres(rmt_contex.hal.regs, channel, thresh);
rmt_ll_rx_set_idle_thres(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), thresh);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_get_rx_idle_thresh(rmt_channel_t channel, uint16_t *thresh)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(thresh != NULL, RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
*thresh = (uint16_t)rmt_ll_get_rx_idle_thres(rmt_contex.hal.regs, channel);
*thresh = (uint16_t)rmt_ll_rx_get_idle_thres(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -174,7 +197,11 @@ esp_err_t rmt_set_mem_block_num(rmt_channel_t channel, uint8_t rmt_mem_num)
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(rmt_mem_num <= RMT_CHANNEL_MAX - channel, RMT_MEM_CNT_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_set_mem_blocks(rmt_contex.hal.regs, channel, rmt_mem_num);
if (RMT_IS_RX_CHANNEL(channel)) {
rmt_ll_rx_set_mem_blocks(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), rmt_mem_num);
} else {
rmt_ll_tx_set_mem_blocks(rmt_contex.hal.regs, channel, rmt_mem_num);
}
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -184,7 +211,11 @@ esp_err_t rmt_get_mem_block_num(rmt_channel_t channel, uint8_t *rmt_mem_num)
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(rmt_mem_num != NULL, RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
*rmt_mem_num = (uint8_t)rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel);
if (RMT_IS_RX_CHANNEL(channel)) {
*rmt_mem_num = (uint8_t)rmt_ll_rx_get_mem_blocks(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
} else {
*rmt_mem_num = (uint8_t)rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel);
}
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -192,12 +223,12 @@ esp_err_t rmt_get_mem_block_num(rmt_channel_t channel, uint8_t *rmt_mem_num)
esp_err_t rmt_set_tx_carrier(rmt_channel_t channel, bool carrier_en, uint16_t high_level, uint16_t low_level,
rmt_carrier_level_t carrier_level)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(carrier_level < RMT_CARRIER_LEVEL_MAX, RMT_CARRIER_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_set_tx_carrier_high_low_ticks(rmt_contex.hal.regs, channel, high_level, low_level);
rmt_ll_set_carrier_on_level(rmt_contex.hal.regs, channel, carrier_level);
rmt_ll_enable_carrier(rmt_contex.hal.regs, channel, carrier_en);
rmt_ll_tx_set_carrier_high_low_ticks(rmt_contex.hal.regs, channel, high_level, low_level);
rmt_ll_tx_set_carrier_level(rmt_contex.hal.regs, channel, carrier_level);
rmt_ll_tx_enable_carrier_modulation(rmt_contex.hal.regs, channel, carrier_en);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -222,10 +253,10 @@ esp_err_t rmt_get_mem_pd(rmt_channel_t channel, bool *pd_en)
esp_err_t rmt_tx_start(rmt_channel_t channel, bool tx_idx_rst)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
if (tx_idx_rst) {
rmt_ll_reset_tx_pointer(rmt_contex.hal.regs, channel);
rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel);
}
rmt_ll_clear_tx_end_interrupt(rmt_contex.hal.regs, channel);
// enable tx end interrupt in non-loop mode
@ -233,106 +264,114 @@ esp_err_t rmt_tx_start(rmt_channel_t channel, bool tx_idx_rst)
rmt_ll_enable_tx_end_interrupt(rmt_contex.hal.regs, channel, true);
} else {
#if SOC_RMT_SUPPORT_TX_LOOP_COUNT
rmt_ll_reset_tx_loop(rmt_contex.hal.regs, channel);
rmt_ll_enable_tx_loop_count(rmt_contex.hal.regs, channel, true);
rmt_ll_tx_reset_loop(rmt_contex.hal.regs, channel);
rmt_ll_tx_enable_loop_count(rmt_contex.hal.regs, channel, true);
rmt_ll_clear_tx_loop_interrupt(rmt_contex.hal.regs, channel);
rmt_ll_enable_tx_loop_interrupt(rmt_contex.hal.regs, channel, true);
#endif
}
rmt_ll_start_tx(rmt_contex.hal.regs, channel);
rmt_ll_tx_start(rmt_contex.hal.regs, channel);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_tx_stop(rmt_channel_t channel)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_stop_tx(rmt_contex.hal.regs, channel);
rmt_ll_reset_tx_pointer(rmt_contex.hal.regs, channel);
rmt_ll_tx_stop(rmt_contex.hal.regs, channel);
rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_rx_start(rmt_channel_t channel, bool rx_idx_rst)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_enable_rx(rmt_contex.hal.regs, channel, false);
rmt_ll_rx_enable(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), false);
if (rx_idx_rst) {
rmt_ll_reset_rx_pointer(rmt_contex.hal.regs, channel);
rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
}
rmt_ll_clear_rx_end_interrupt(rmt_contex.hal.regs, channel);
rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, channel, true);
rmt_ll_clear_rx_end_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), true);
#if SOC_RMT_SUPPORT_RX_PINGPONG
const uint32_t item_block_len = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM;
const uint32_t item_block_len = rmt_ll_rx_get_mem_blocks(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)) * RMT_MEM_ITEM_NUM;
p_rmt_obj[channel]->rx_item_start_idx = 0;
p_rmt_obj[channel]->rx_item_len = 0;
rmt_set_rx_thr_intr_en(channel, true, item_block_len / 2);
#endif
rmt_ll_enable_rx(rmt_contex.hal.regs, channel, true);
rmt_ll_rx_enable(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), true);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_rx_stop(rmt_channel_t channel)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, channel, false);
rmt_ll_enable_rx(rmt_contex.hal.regs, channel, false);
rmt_ll_reset_rx_pointer(rmt_contex.hal.regs, channel);
rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), false);
rmt_ll_rx_enable(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), false);
rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
#if SOC_RMT_SUPPORT_RX_PINGPONG
rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, channel, false);
rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), false);
#endif
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_memory_rw_rst(rmt_channel_t channel)
esp_err_t rmt_tx_memory_reset(rmt_channel_t channel)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_reset_tx_pointer(rmt_contex.hal.regs, channel);
rmt_ll_reset_rx_pointer(rmt_contex.hal.regs, channel);
rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_rx_memory_reset(rmt_channel_t channel)
{
RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_set_memory_owner(rmt_channel_t channel, rmt_mem_owner_t owner)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(owner < RMT_MEM_OWNER_MAX, RMT_MEM_OWNER_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, owner);
rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), owner);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_get_memory_owner(rmt_channel_t channel, rmt_mem_owner_t *owner)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(owner != NULL, RMT_MEM_OWNER_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
*owner = (rmt_mem_owner_t)rmt_ll_get_mem_owner(rmt_contex.hal.regs, channel);
*owner = (rmt_mem_owner_t)rmt_ll_rx_get_mem_owner(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_set_tx_loop_mode(rmt_channel_t channel, bool loop_en)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_enable_tx_loop(rmt_contex.hal.regs, channel, loop_en);
rmt_ll_tx_enable_loop(rmt_contex.hal.regs, channel, loop_en);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_get_tx_loop_mode(rmt_channel_t channel, bool *loop_en)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
*loop_en = rmt_ll_is_tx_loop_enabled(rmt_contex.hal.regs, channel);
RMT_EXIT_CRITICAL();
@ -341,10 +380,10 @@ esp_err_t rmt_get_tx_loop_mode(rmt_channel_t channel, bool *loop_en)
esp_err_t rmt_set_rx_filter(rmt_channel_t channel, bool rx_filter_en, uint8_t thresh)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_enable_rx_filter(rmt_contex.hal.regs, channel, rx_filter_en);
rmt_ll_set_rx_filter_thres(rmt_contex.hal.regs, channel, thresh);
rmt_ll_rx_enable_filter(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), rx_filter_en);
rmt_ll_rx_set_filter_thres(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), thresh);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -354,7 +393,7 @@ esp_err_t rmt_set_source_clk(rmt_channel_t channel, rmt_source_clk_t base_clk)
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(base_clk < RMT_BASECLK_MAX, RMT_BASECLK_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_set_counter_clock_src(rmt_contex.hal.regs, channel, base_clk);
rmt_ll_set_counter_clock_src(rmt_contex.hal.regs, channel, base_clk, 0, 0, 0);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -373,8 +412,8 @@ esp_err_t rmt_set_idle_level(rmt_channel_t channel, bool idle_out_en, rmt_idle_l
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(level < RMT_IDLE_LEVEL_MAX, "RMT IDLE LEVEL ERR", ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_enable_tx_idle(rmt_contex.hal.regs, channel, idle_out_en);
rmt_ll_set_tx_idle_level(rmt_contex.hal.regs, channel, level);
rmt_ll_tx_enable_idle(rmt_contex.hal.regs, channel, idle_out_en);
rmt_ll_tx_set_idle_level(rmt_contex.hal.regs, channel, level);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -384,7 +423,7 @@ esp_err_t rmt_get_idle_level(rmt_channel_t channel, bool *idle_out_en, rmt_idle_
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
*idle_out_en = rmt_ll_is_tx_idle_enabled(rmt_contex.hal.regs, channel);
*level = rmt_ll_get_tx_idle_level(rmt_contex.hal.regs, channel);
*level = rmt_ll_tx_get_idle_level(rmt_contex.hal.regs, channel);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -393,7 +432,11 @@ esp_err_t rmt_get_status(rmt_channel_t channel, uint32_t *status)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
*status = rmt_ll_get_channel_status(rmt_contex.hal.regs, channel);
if (RMT_IS_RX_CHANNEL(channel)) {
*status = rmt_ll_rx_get_channel_status(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
} else {
*status = rmt_ll_tx_get_channel_status(rmt_contex.hal.regs, channel);
}
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -414,9 +457,9 @@ void rmt_clr_intr_enable_mask(uint32_t mask)
esp_err_t rmt_set_rx_intr_en(rmt_channel_t channel, bool en)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, channel, en);
rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), en);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -424,17 +467,17 @@ esp_err_t rmt_set_rx_intr_en(rmt_channel_t channel, bool en)
#if SOC_RMT_SUPPORT_RX_PINGPONG
esp_err_t rmt_set_rx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_thresh)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_RX_CHANNEL(channel) && channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
if (en) {
uint32_t item_block_len = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM;
uint32_t item_block_len = rmt_ll_rx_get_mem_blocks(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel)) * RMT_MEM_ITEM_NUM;
RMT_CHECK(evt_thresh <= item_block_len, "RMT EVT THRESH ERR", ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_set_rx_limit(rmt_contex.hal.regs, channel, evt_thresh);
rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, channel, true);
rmt_ll_rx_set_limit(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), evt_thresh);
rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), true);
RMT_EXIT_CRITICAL();
} else {
RMT_ENTER_CRITICAL();
rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, channel, false);
rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), false);
RMT_EXIT_CRITICAL();
}
return ESP_OK;
@ -445,14 +488,18 @@ esp_err_t rmt_set_err_intr_en(rmt_channel_t channel, bool en)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_enable_err_interrupt(rmt_contex.hal.regs, channel, en);
if (RMT_IS_RX_CHANNEL(channel)) {
rmt_ll_enable_rx_err_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), en);
} else {
rmt_ll_enable_tx_err_interrupt(rmt_contex.hal.regs, channel, en);
}
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_set_tx_intr_en(rmt_channel_t channel, bool en)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_enable_tx_end_interrupt(rmt_contex.hal.regs, channel, en);
RMT_EXIT_CRITICAL();
@ -461,12 +508,12 @@ 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)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
if (en) {
uint32_t item_block_len = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM;
uint32_t item_block_len = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM;
RMT_CHECK(evt_thresh <= item_block_len, "RMT EVT THRESH ERR", ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_set_tx_limit(rmt_contex.hal.regs, channel, evt_thresh);
rmt_ll_tx_set_limit(rmt_contex.hal.regs, channel, evt_thresh);
rmt_ll_enable_tx_thres_interrupt(rmt_contex.hal.regs, channel, true);
RMT_EXIT_CRITICAL();
} else {
@ -487,19 +534,27 @@ esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_nu
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
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_SIG_OUT0_IDX + channel, 0, 0);
esp_rom_gpio_connect_out_signal(gpio_num, rmt_periph_signals.channels[channel].tx_sig, 0, 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);
#if SOC_RMT_TX_RX_CHANNEL_INDEPENDENT
esp_rom_gpio_connect_in_signal(gpio_num, RMT_SIG_IN0_IDX + channel - RMT_LL_TX_CHAN_NUM, 0);
#else
esp_rom_gpio_connect_in_signal(gpio_num, RMT_SIG_IN0_IDX + channel, 0);
#endif
esp_rom_gpio_connect_in_signal(gpio_num, rmt_periph_signals.channels[channel].rx_sig, 0);
}
return ESP_OK;
}
static bool rmt_is_channel_number_valid(rmt_channel_t channel, uint8_t mode)
{
// RX mode
if (mode == RMT_MODE_RX) {
return RMT_IS_RX_CHANNEL(channel) && (channel < RMT_CHANNEL_MAX);
}
// TX mode
return (channel >= 0) && RMT_IS_TX_CHANNEL(channel);
}
static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_param)
{
uint8_t mode = rmt_param->rmt_mode;
@ -511,7 +566,7 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par
bool carrier_en = rmt_param->tx_config.carrier_en;
uint32_t rmt_source_clk_hz;
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(rmt_is_channel_number_valid(channel, mode), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK((mem_cnt + channel <= 8 && mem_cnt > 0), RMT_MEM_CNT_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK((clk_div > 0), RMT_CLK_DIV_ERROR_STR, ESP_ERR_INVALID_ARG);
@ -520,59 +575,67 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par
}
RMT_ENTER_CRITICAL();
rmt_ll_set_counter_clock_div(dev, channel, clk_div);
rmt_ll_enable_mem_access(dev, true);
rmt_ll_reset_tx_pointer(dev, channel);
rmt_ll_reset_rx_pointer(dev, channel);
if (rmt_param->flags & RMT_CHANNEL_FLAGS_ALWAYS_ON) {
#ifdef SOC_RMT_SUPPORT_REF_TICK
// clock src: REF_CLK
rmt_source_clk_hz = REF_CLK_FREQ;
rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_REF);
#elif defined SOC_RMT_SUPPORT_XTAL_CLOCK
#if SOC_RMT_SUPPORT_XTAL
// clock src: XTAL_CLK
rmt_source_clk_hz = rtc_clk_xtal_freq_get() * 1000000;
rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_XTAL);
rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_XTAL, 0, 0, 0);
#elif SOC_RMT_SUPPORT_REF_TICK
// clock src: REF_CLK
rmt_source_clk_hz = REF_CLK_FREQ;
rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_REF, 0, 0, 0);
#endif
} else {
// clock src: APB_CLK
rmt_source_clk_hz = APB_CLK_FREQ;
rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_APB);
rmt_ll_set_counter_clock_src(dev, channel, RMT_BASECLK_APB, 0, 0, 0);
}
esp_rom_printf("rmt_source_clk_hz: %d\n", rmt_source_clk_hz);
rmt_ll_set_mem_blocks(dev, channel, mem_cnt);
rmt_ll_set_mem_owner(dev, channel, RMT_MEM_OWNER_HW);
RMT_EXIT_CRITICAL();
#if SOC_RMT_SOURCE_CLK_INDEPENDENT
s_rmt_source_clock_hz[channel] = rmt_source_clk_hz;
#else
if (s_rmt_source_clock_hz && rmt_source_clk_hz != s_rmt_source_clock_hz) {
ESP_LOGW(RMT_TAG, "RMT clock source has been configured to %d by other channel, now reconfigure it to %d", s_rmt_source_clock_hz, rmt_source_clk_hz);
}
s_rmt_source_clock_hz = rmt_source_clk_hz;
#endif
ESP_LOGD(RMT_TAG, "rmt_source_clk_hz: %d\n", rmt_source_clk_hz);
if (mode == RMT_MODE_TX) {
uint16_t carrier_duty_percent = rmt_param->tx_config.carrier_duty_percent;
uint8_t carrier_level = rmt_param->tx_config.carrier_level;
uint8_t idle_level = rmt_param->tx_config.idle_level;
RMT_ENTER_CRITICAL();
rmt_ll_enable_tx_loop(dev, channel, rmt_param->tx_config.loop_en);
rmt_ll_tx_set_counter_clock_div(dev, channel, clk_div);
rmt_ll_tx_set_mem_blocks(dev, channel, mem_cnt);
rmt_ll_tx_reset_pointer(dev, channel);
rmt_ll_tx_enable_loop(dev, channel, rmt_param->tx_config.loop_en);
#if SOC_RMT_SUPPORT_TX_LOOP_COUNT
if (rmt_param->tx_config.loop_en) {
rmt_ll_set_tx_loop_count(dev, channel, rmt_param->tx_config.loop_count);
rmt_ll_tx_set_loop_count(dev, channel, rmt_param->tx_config.loop_count);
}
#endif
/* always enable tx ping-pong */
rmt_ll_enable_tx_pingpong(dev, channel, true);
rmt_ll_tx_enable_pingpong(dev, channel, true);
/*Set idle level */
rmt_ll_enable_tx_idle(dev, channel, rmt_param->tx_config.idle_output_en);
rmt_ll_set_tx_idle_level(dev, channel, idle_level);
rmt_ll_tx_enable_idle(dev, channel, rmt_param->tx_config.idle_output_en);
rmt_ll_tx_set_idle_level(dev, channel, idle_level);
/*Set carrier*/
rmt_ll_enable_carrier(dev, channel, carrier_en);
rmt_ll_tx_enable_carrier_modulation(dev, channel, carrier_en);
if (carrier_en) {
uint32_t duty_div, duty_h, duty_l;
duty_div = rmt_source_clk_hz / carrier_freq_hz;
duty_h = duty_div * carrier_duty_percent / 100;
duty_l = duty_div - duty_h;
rmt_ll_set_carrier_on_level(dev, channel, carrier_level);
rmt_ll_set_tx_carrier_high_low_ticks(dev, channel, duty_h, duty_l);
rmt_ll_tx_set_carrier_level(dev, channel, carrier_level);
rmt_ll_tx_set_carrier_high_low_ticks(dev, channel, duty_h, duty_l);
} else {
rmt_ll_set_carrier_on_level(dev, channel, 0);
rmt_ll_set_tx_carrier_high_low_ticks(dev, channel, 0, 0);
rmt_ll_tx_set_carrier_level(dev, channel, 0);
rmt_ll_tx_set_carrier_high_low_ticks(dev, channel, 0, 0);
}
RMT_EXIT_CRITICAL();
@ -583,25 +646,29 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par
uint16_t threshold = rmt_param->rx_config.idle_threshold;
RMT_ENTER_CRITICAL();
rmt_ll_rx_set_counter_clock_div(dev, RMT_DECODE_RX_CHANNEL(channel), clk_div);
rmt_ll_rx_set_mem_blocks(dev, RMT_DECODE_RX_CHANNEL(channel), mem_cnt);
rmt_ll_rx_reset_pointer(dev, RMT_DECODE_RX_CHANNEL(channel));
rmt_ll_rx_set_mem_owner(dev, RMT_DECODE_RX_CHANNEL(channel), RMT_MEM_OWNER_HW);
/*Set idle threshold*/
rmt_ll_set_rx_idle_thres(dev, channel, threshold);
rmt_ll_rx_set_idle_thres(dev, RMT_DECODE_RX_CHANNEL(channel), threshold);
/* Set RX filter */
rmt_ll_set_rx_filter_thres(dev, channel, filter_cnt);
rmt_ll_enable_rx_filter(dev, channel, rmt_param->rx_config.filter_en);
rmt_ll_rx_set_filter_thres(dev, RMT_DECODE_RX_CHANNEL(channel), filter_cnt);
rmt_ll_rx_enable_filter(dev, RMT_DECODE_RX_CHANNEL(channel), rmt_param->rx_config.filter_en);
#if SOC_RMT_SUPPORT_RX_PINGPONG
/* always enable rx ping-pong */
rmt_ll_enable_rx_pingpong(dev, channel, true);
rmt_ll_rx_enable_pingpong(dev, RMT_DECODE_RX_CHANNEL(channel), true);
#endif
#if SOC_RMT_SUPPORT_RX_DEMODULATION
rmt_ll_enable_carrier(dev, channel, rmt_param->rx_config.rm_carrier);
rmt_ll_rx_enable_carrier_demodulation(dev, RMT_DECODE_RX_CHANNEL(channel), rmt_param->rx_config.rm_carrier);
if (rmt_param->rx_config.rm_carrier) {
uint32_t duty_total = rmt_source_clk_hz / rmt_ll_get_counter_clock_div(dev, channel) / rmt_param->rx_config.carrier_freq_hz;
uint32_t duty_total = rmt_source_clk_hz / rmt_ll_rx_get_counter_clock_div(dev, RMT_DECODE_RX_CHANNEL(channel)) / rmt_param->rx_config.carrier_freq_hz;
uint32_t duty_high = duty_total * rmt_param->rx_config.carrier_duty_percent / 100;
// there could be residual in timing the carrier pulse, so double enlarge the theoretical value
rmt_ll_set_rx_carrier_high_low_ticks(dev, channel, duty_high * 2, (duty_total - duty_high) * 2);
rmt_ll_set_carrier_on_level(dev, channel, rmt_param->rx_config.carrier_level);
rmt_ll_rx_set_carrier_high_low_ticks(dev, RMT_DECODE_RX_CHANNEL(channel), duty_high * 2, (duty_total - duty_high) * 2);
rmt_ll_rx_set_carrier_level(dev, RMT_DECODE_RX_CHANNEL(channel), rmt_param->rx_config.carrier_level);
}
#endif
RMT_EXIT_CRITICAL();
@ -609,6 +676,7 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par
ESP_LOGD(RMT_TAG, "Rmt Rx Channel %u|Gpio %u|Sclk_Hz %u|Div %u|Thresold %u|Filter %u",
channel, gpio_num, rmt_source_clk_hz, clk_div, threshold, filter_cnt);
}
return ESP_OK;
}
@ -629,20 +697,18 @@ static void IRAM_ATTR rmt_fill_memory(rmt_channel_t channel, const rmt_item32_t
uint16_t item_num, uint16_t mem_offset)
{
RMT_ENTER_CRITICAL();
rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_SW);
rmt_ll_write_memory(rmt_contex.hal.mem, channel, item, item_num, mem_offset);
rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_HW);
RMT_EXIT_CRITICAL();
}
esp_err_t rmt_fill_tx_items(rmt_channel_t channel, const rmt_item32_t *item, uint16_t item_num, uint16_t mem_offset)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, (0));
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, (0));
RMT_CHECK((item != NULL), RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK((item_num > 0), RMT_DRIVER_LENGTH_ERROR_STR, ESP_ERR_INVALID_ARG);
/*Each block has 64 x 32 bits of data*/
uint8_t mem_cnt = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel);
uint8_t mem_cnt = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel);
RMT_CHECK((mem_cnt * RMT_MEM_ITEM_NUM >= item_num), RMT_WR_MEM_OVF_ERROR_STR, ESP_ERR_INVALID_ARG);
rmt_fill_memory(channel, item, item_num, mem_offset);
return ESP_OK;
@ -653,7 +719,7 @@ esp_err_t rmt_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags,
RMT_CHECK((fn != NULL), RMT_ADDR_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(rmt_contex.rmt_driver_channels == 0, "RMT driver installed, can not install generic ISR handler", ESP_FAIL);
return esp_intr_alloc(ETS_RMT_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
return esp_intr_alloc(rmt_periph_signals.irq, intr_alloc_flags, fn, arg, handle);
}
esp_err_t rmt_isr_deregister(rmt_isr_handle_t handle)
@ -661,11 +727,11 @@ esp_err_t rmt_isr_deregister(rmt_isr_handle_t handle)
return esp_intr_free(handle);
}
static int IRAM_ATTR rmt_get_mem_len(rmt_channel_t channel)
static int IRAM_ATTR rmt_rx_get_mem_len_in_isr(rmt_channel_t channel)
{
int block_num = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel);
int block_num = rmt_ll_rx_get_mem_blocks(rmt_contex.hal.regs, channel);
int item_block_len = block_num * RMT_MEM_ITEM_NUM;
volatile rmt_item32_t *data = (rmt_item32_t *)RMTMEM.chan[channel].data32;
volatile rmt_item32_t *data = (rmt_item32_t *)RMTMEM.chan[RMT_ENCODE_RX_CHANNEL(channel)].data32;
int idx;
for (idx = 0; idx < item_block_len; idx++) {
if (data[idx].duration0 == 0) {
@ -693,7 +759,7 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg)
rmt_obj_t *p_rmt = p_rmt_obj[channel];
if (p_rmt) {
xSemaphoreGiveFromISR(p_rmt->tx_sem, &HPTaskAwoken);
rmt_ll_reset_tx_pointer(rmt_contex.hal.regs, channel);
rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel);
p_rmt->tx_data = NULL;
p_rmt->tx_len_rem = 0;
p_rmt->tx_offset = 0;
@ -761,13 +827,13 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg)
while (status) {
channel = __builtin_ffs(status) - 1;
status &= ~(1 << channel);
rmt_obj_t *p_rmt = p_rmt_obj[channel];
rmt_obj_t *p_rmt = p_rmt_obj[RMT_ENCODE_RX_CHANNEL(channel)];
if (p_rmt) {
rmt_ll_enable_rx(rmt_contex.hal.regs, channel, false);
int item_len = rmt_get_mem_len(channel);
rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_SW);
rmt_ll_rx_enable(rmt_contex.hal.regs, channel, false);
int item_len = rmt_rx_get_mem_len_in_isr(channel);
rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_SW);
if (p_rmt->rx_buf) {
addr = RMTMEM.chan[channel].data32;
addr = RMTMEM.chan[RMT_ENCODE_RX_CHANNEL(channel)].data32;
#if SOC_RMT_SUPPORT_RX_PINGPONG
if (item_len > p_rmt->rx_item_start_idx) {
item_len = item_len - p_rmt->rx_item_start_idx;
@ -790,9 +856,9 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg)
p_rmt->rx_item_len = 0;
memset((void *)p_rmt->rx_item_buf, 0, p_rmt->rx_item_buf_size);
#endif
rmt_ll_reset_rx_pointer(rmt_contex.hal.regs, channel);
rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_HW);
rmt_ll_enable_rx(rmt_contex.hal.regs, channel, true);
rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, channel);
rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_HW);
rmt_ll_rx_enable(rmt_contex.hal.regs, channel, true);
}
rmt_ll_clear_rx_end_interrupt(hal->regs, channel);
}
@ -803,14 +869,14 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg)
while (status) {
channel = __builtin_ffs(status) - 1;
status &= ~(1 << channel);
rmt_obj_t *p_rmt = p_rmt_obj[channel];
int mem_item_size = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM;
int rx_thres_lim = rmt_ll_get_rx_limit(rmt_contex.hal.regs, channel);
rmt_obj_t *p_rmt = p_rmt_obj[RMT_ENCODE_RX_CHANNEL(channel)];
int mem_item_size = rmt_ll_rx_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM;
int rx_thres_lim = rmt_ll_rx_get_limit(rmt_contex.hal.regs, channel);
int item_len = (p_rmt->rx_item_start_idx == 0) ? rx_thres_lim : (mem_item_size - rx_thres_lim);
if ((p_rmt->rx_item_len + item_len) < (p_rmt->rx_item_buf_size / 4)) {
rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_SW);
memcpy((void *)(p_rmt->rx_item_buf + p_rmt->rx_item_len), (void *)(RMTMEM.chan[channel].data32 + p_rmt->rx_item_start_idx), item_len * 4);
rmt_ll_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_HW);
rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_SW);
memcpy((void *)(p_rmt->rx_item_buf + p_rmt->rx_item_len), (void *)(RMTMEM.chan[RMT_ENCODE_RX_CHANNEL(channel)].data32 + p_rmt->rx_item_start_idx), item_len * 4);
rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, channel, RMT_MEM_OWNER_HW);
p_rmt->rx_item_len += item_len;
p_rmt->rx_item_start_idx += item_len;
if (p_rmt->rx_item_start_idx >= mem_item_size) {
@ -840,20 +906,34 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg)
}
#endif
// Err interrupt
status = rmt_ll_get_err_interrupt_status(hal->regs);
// RX Err interrupt
status = rmt_ll_get_rx_err_interrupt_status(hal->regs);
while (status) {
channel = __builtin_ffs(status) - 1;
status &= ~(1 << channel);
rmt_obj_t *p_rmt = p_rmt_obj[RMT_ENCODE_RX_CHANNEL(channel)];
if (p_rmt) {
// Reset the receiver's write/read addresses to prevent endless err interrupts.
rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, channel);
ESP_EARLY_LOGD(RMT_TAG, "RMT RX channel %d error", channel);
ESP_EARLY_LOGD(RMT_TAG, "status: 0x%08x", rmt_ll_rx_get_channel_status(rmt_contex.hal.regs, channel));
}
rmt_ll_clear_rx_err_interrupt(hal->regs, channel);
}
// TX Err interrupt
status = rmt_ll_get_tx_err_interrupt_status(hal->regs);
while (status) {
channel = __builtin_ffs(status) - 1;
status &= ~(1 << channel);
rmt_obj_t *p_rmt = p_rmt_obj[channel];
if (p_rmt) {
// Reset the receiver/transmitter's write/read addresses to prevent endless err interrupts.
rmt_ll_reset_tx_pointer(rmt_contex.hal.regs, channel);
rmt_ll_reset_rx_pointer(rmt_contex.hal.regs, channel);
ESP_EARLY_LOGD(RMT_TAG, "RMT[%d] ERR", channel);
ESP_EARLY_LOGD(RMT_TAG, "status: 0x%08x", rmt_ll_get_channel_status(rmt_contex.hal.regs, channel));
// Reset the transmitter's write/read addresses to prevent endless err interrupts.
rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel);
ESP_EARLY_LOGD(RMT_TAG, "RMT TX channel %d error", channel);
ESP_EARLY_LOGD(RMT_TAG, "status: 0x%08x", rmt_ll_tx_get_channel_status(rmt_contex.hal.regs, channel));
}
rmt_ll_clear_err_interrupt(hal->regs, channel);
rmt_ll_clear_tx_err_interrupt(hal->regs, channel);
}
if (HPTaskAwoken == pdTRUE) {
@ -873,16 +953,23 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel)
if (p_rmt_obj[channel]->wait_done) {
xSemaphoreTake(p_rmt_obj[channel]->tx_sem, portMAX_DELAY);
}
rmt_set_rx_intr_en(channel, 0);
rmt_set_err_intr_en(channel, 0);
rmt_set_tx_intr_en(channel, 0);
rmt_set_tx_thr_intr_en(channel, false, 0xffff);
RMT_ENTER_CRITICAL();
// check channel's working mode
if (p_rmt_obj[channel]->rx_buf) {
rmt_ll_enable_rx_end_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), 0);
rmt_ll_enable_rx_err_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), 0);
#if SOC_RMT_SUPPORT_RX_PINGPONG
rmt_set_rx_thr_intr_en(channel, false, 0xffff);
rmt_ll_enable_rx_thres_interrupt(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel), 0);
#endif
} else {
rmt_ll_enable_tx_end_interrupt(rmt_contex.hal.regs, channel, 0);
rmt_ll_enable_tx_err_interrupt(rmt_contex.hal.regs, channel, 0);
rmt_ll_enable_tx_thres_interrupt(rmt_contex.hal.regs, channel, false);
}
RMT_EXIT_CRITICAL();
_lock_acquire_recursive(&(rmt_contex.rmt_driver_isr_lock));
rmt_contex.rmt_driver_channels &= ~BIT(channel);
if (rmt_contex.rmt_driver_channels == 0) {
rmt_module_disable();
@ -890,7 +977,6 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel)
err = rmt_isr_deregister(rmt_contex.rmt_driver_intr_handle);
rmt_contex.rmt_driver_intr_handle = NULL;
}
_lock_release_recursive(&(rmt_contex.rmt_driver_isr_lock));
if (err != ESP_OK) {
@ -1007,17 +1093,21 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr
rmt_contex.rmt_driver_channels |= BIT(channel);
}
_lock_release_recursive(&(rmt_contex.rmt_driver_isr_lock));
rmt_module_enable();
rmt_set_err_intr_en(channel, 0);
rmt_hal_channel_reset(&rmt_contex.hal, channel);
rmt_set_err_intr_en(channel, 1);
if (RMT_IS_RX_CHANNEL(channel)) {
rmt_hal_rx_channel_reset(&rmt_contex.hal, RMT_DECODE_RX_CHANNEL(channel));
} else {
rmt_hal_tx_channel_reset(&rmt_contex.hal, channel);
}
return err;
}
esp_err_t rmt_write_items(rmt_channel_t channel, const rmt_item32_t *rmt_item, int item_num, bool wait_tx_done)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL);
RMT_CHECK(rmt_item != NULL, RMT_ADDR_ERROR_STR, ESP_FAIL);
RMT_CHECK(item_num > 0, RMT_DRIVER_LENGTH_ERROR_STR, ESP_ERR_INVALID_ARG);
@ -1030,7 +1120,7 @@ esp_err_t rmt_write_items(rmt_channel_t channel, const rmt_item32_t *rmt_item, i
}
#endif
rmt_obj_t *p_rmt = p_rmt_obj[channel];
int block_num = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel);
int block_num = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel);
int item_block_len = block_num * RMT_MEM_ITEM_NUM;
int item_sub_len = block_num * RMT_MEM_ITEM_NUM / 2;
int len_rem = item_num;
@ -1071,7 +1161,7 @@ esp_err_t rmt_write_items(rmt_channel_t channel, const rmt_item32_t *rmt_item, i
esp_err_t rmt_wait_tx_done(rmt_channel_t channel, TickType_t wait_time)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL);
if (xSemaphoreTake(p_rmt_obj[channel]->tx_sem, wait_time) == pdTRUE) {
p_rmt_obj[channel]->wait_done = false;
@ -1106,9 +1196,9 @@ rmt_tx_end_callback_t rmt_register_tx_end_callback(rmt_tx_end_fn_t function, voi
esp_err_t rmt_translator_init(rmt_channel_t channel, sample_to_rmt_t fn)
{
RMT_CHECK(fn != NULL, RMT_TRANSLATOR_NULL_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL);
const uint32_t block_size = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) *
const uint32_t block_size = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel) *
RMT_MEM_ITEM_NUM * sizeof(rmt_item32_t);
if (p_rmt_obj[channel]->tx_buf == NULL) {
#if !CONFIG_SPIRAM_USE_MALLOC
@ -1134,7 +1224,7 @@ esp_err_t rmt_translator_init(rmt_channel_t channel, sample_to_rmt_t fn)
esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src_size, bool wait_tx_done)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL);
RMT_CHECK(p_rmt_obj[channel]->sample_to_rmt != NULL, RMT_TRANSLATOR_UNINIT_STR, ESP_FAIL);
#if CONFIG_SPIRAM_USE_MALLOC
@ -1148,7 +1238,7 @@ esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src
size_t item_num = 0;
size_t translated_size = 0;
rmt_obj_t *p_rmt = p_rmt_obj[channel];
const uint32_t item_block_len = rmt_ll_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM;
const uint32_t item_block_len = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM;
const uint32_t item_sub_len = item_block_len / 2;
xSemaphoreTake(p_rmt->tx_sem, portMAX_DELAY);
p_rmt->sample_to_rmt((void *)src, p_rmt->tx_buf, src_size, item_block_len, &translated_size, &item_num);
@ -1202,20 +1292,16 @@ esp_err_t rmt_get_counter_clock(rmt_channel_t channel, uint32_t *clock_hz)
RMT_CHECK(clock_hz, "parameter clock_hz can't be null", ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
uint32_t rmt_source_clk_hz = 0;
if (rmt_ll_get_counter_clock_src(rmt_contex.hal.regs, channel) == RMT_BASECLK_APB) {
rmt_source_clk_hz = APB_CLK_FREQ;
}
#ifdef SOC_RMT_SUPPORT_REF_TICK
else if (rmt_ll_get_counter_clock_src(rmt_contex.hal.regs, channel) == RMT_BASECLK_REF) {
rmt_source_clk_hz = REF_CLK_FREQ;
}
#if SOC_RMT_SOURCE_CLK_INDEPENDENT
rmt_source_clk_hz = s_rmt_source_clock_hz[channel];
#else
rmt_source_clk_hz = s_rmt_source_clock_hz;
#endif
#ifdef SOC_RMT_SUPPORT_XTAL_CLOCK
else if (rmt_ll_get_counter_clock_src(rmt_contex.hal.regs, channel) == RMT_BASECLK_XTAL) {
rmt_source_clk_hz = rtc_clk_xtal_freq_get() * 1000000;
if (RMT_IS_RX_CHANNEL(channel)) {
*clock_hz = rmt_source_clk_hz / rmt_ll_rx_get_counter_clock_div(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
} else {
*clock_hz = rmt_source_clk_hz / rmt_ll_tx_get_counter_clock_div(rmt_contex.hal.regs, channel);
}
#endif
*clock_hz = rmt_hal_get_counter_clock(&rmt_contex.hal, channel, rmt_source_clk_hz);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
@ -1223,21 +1309,34 @@ esp_err_t rmt_get_counter_clock(rmt_channel_t channel, uint32_t *clock_hz)
#if SOC_RMT_SUPPORT_TX_GROUP
esp_err_t rmt_add_channel_to_group(rmt_channel_t channel)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
rmt_ll_enable_tx_sync(rmt_contex.hal.regs, true);
rmt_ll_add_channel_to_group(rmt_contex.hal.regs, channel);
rmt_ll_reset_counter_clock_div(rmt_contex.hal.regs, channel);
rmt_ll_tx_enable_sync(rmt_contex.hal.regs, true);
rmt_ll_tx_add_channel_to_group(rmt_contex.hal.regs, channel);
rmt_ll_tx_reset_counter_clock_div(rmt_contex.hal.regs, channel);
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_remove_channel_from_group(rmt_channel_t channel)
{
RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
if (rmt_ll_tx_remove_channel_from_group(rmt_contex.hal.regs, channel) == 0) {
rmt_ll_tx_enable_sync(rmt_contex.hal.regs, false);
}
RMT_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t rmt_memory_rw_rst(rmt_channel_t channel)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
RMT_ENTER_CRITICAL();
if (rmt_ll_remove_channel_from_group(rmt_contex.hal.regs, channel) == 0) {
rmt_ll_enable_tx_sync(rmt_contex.hal.regs, false);
if (RMT_IS_RX_CHANNEL(channel)) {
rmt_ll_rx_reset_pointer(rmt_contex.hal.regs, RMT_DECODE_RX_CHANNEL(channel));
} else {
rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel);
}
RMT_EXIT_CRITICAL();
return ESP_OK;

View File

@ -12,7 +12,8 @@
#include "test_utils.h"
#include "esp_rom_gpio.h"
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
#define RMT_RX_CHANNEL_ENCODING_START (SOC_RMT_CHANNELS_NUM-SOC_RMT_TX_CHANNELS_NUM)
#define RMT_TX_CHANNEL_ENCODING_END (SOC_RMT_TX_CHANNELS_NUM-1)
// CI ONLY: Don't connect any other signals to this GPIO
#define RMT_DATA_IO (12) // bind signal RMT_SIG_OUT0_IDX and RMT_SIG_IN0_IDX on the same GPIO
@ -123,7 +124,7 @@ TEST_CASE("RMT wrong configuration", "[rmt][error]")
TEST_CASE("RMT miscellaneous functions", "[rmt]")
{
rmt_channel_t channel = SOC_RMT_CHANNELS_NUM - 2;
rmt_channel_t channel = 0;
uint8_t div_cnt;
rmt_source_clk_t src_clk;
uint8_t memNum;
@ -147,15 +148,12 @@ TEST_CASE("RMT miscellaneous functions", "[rmt]")
TEST_ASSERT_EQUAL_INT(RMT_BASECLK_REF, src_clk);
#endif
#if SOC_RMT_SUPPORT_XTAL_CLOCK
#if SOC_RMT_SUPPORT_XTAL
TEST_ESP_OK(rmt_set_source_clk(channel, RMT_BASECLK_XTAL));
TEST_ESP_OK(rmt_get_source_clk(channel, &src_clk));
TEST_ASSERT_EQUAL_INT(RMT_BASECLK_XTAL, src_clk);
#endif
TEST_ESP_OK(rmt_set_memory_owner(channel, RMT_MEM_OWNER_RX));
TEST_ESP_OK(rmt_get_memory_owner(channel, &owner));
TEST_ASSERT_EQUAL_INT(RMT_MEM_OWNER_RX, owner);
TEST_ESP_OK(rmt_set_tx_carrier(channel, 0, 1, 0, 1));
TEST_ESP_OK(rmt_set_idle_level(channel, 1, 0));
@ -163,6 +161,7 @@ TEST_CASE("RMT miscellaneous functions", "[rmt]")
rmt_clean_testbench(channel, -1);
// RX related functions
channel = RMT_RX_CHANNEL_ENCODING_START;
rmt_setup_testbench(-1, channel, 0);
TEST_ESP_OK(rmt_set_rx_idle_thresh(channel, 200));
@ -171,6 +170,10 @@ TEST_CASE("RMT miscellaneous functions", "[rmt]")
TEST_ESP_OK(rmt_set_rx_filter(channel, 1, 100));
TEST_ESP_OK(rmt_set_memory_owner(channel, RMT_MEM_OWNER_RX));
TEST_ESP_OK(rmt_get_memory_owner(channel, &owner));
TEST_ASSERT_EQUAL_INT(RMT_MEM_OWNER_RX, owner);
rmt_clean_testbench(-1, channel);
}
@ -196,7 +199,13 @@ TEST_CASE("RMT multiple channels", "[rmt]")
TEST_CASE("RMT install/uninstall test", "[rmt][pressure]")
{
rmt_config_t rx_cfg = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, SOC_RMT_CHANNELS_NUM - 2);
rmt_config_t tx_cfg = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, RMT_TX_CHANNEL_ENCODING_END);
TEST_ESP_OK(rmt_config(&tx_cfg));
for (int i = 0; i < 100; i++) {
TEST_ESP_OK(rmt_driver_install(tx_cfg.channel, 1000, 0));
TEST_ESP_OK(rmt_driver_uninstall(tx_cfg.channel));
}
rmt_config_t rx_cfg = RMT_DEFAULT_CONFIG_RX(RMT_DATA_IO, RMT_RX_CHANNEL_ENCODING_START);
TEST_ESP_OK(rmt_config(&rx_cfg));
for (int i = 0; i < 100; i++) {
TEST_ESP_OK(rmt_driver_install(rx_cfg.channel, 1000, 0));
@ -213,11 +222,7 @@ static void do_nec_tx_rx(uint32_t flags)
uint32_t cmd = 0x20;
bool repeat = false;
int tx_channel = 0;
#ifdef CONFIG_IDF_TARGET_ESP32S3
int rx_channel = 4;
#else
int rx_channel = 1;
#endif
int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1;
// test on different flags combinations
rmt_setup_testbench(tx_channel, rx_channel, flags);
@ -273,7 +278,7 @@ TEST_CASE("RMT NEC TX and RX (APB)", "[rmt]")
}
// test with RMT_TESTBENCH_FLAGS_ALWAYS_ON will take a long time (REF_TICK is much slower than APB CLOCK)
TEST_CASE("RMT NEC TX and RX (REF_TICK)", "[rmt][timeout=240]")
TEST_CASE("RMT NEC TX and RX (always on)", "[rmt][timeout=240]")
{
do_nec_tx_rx(RMT_TESTBENCH_FLAGS_ALWAYS_ON);
}
@ -314,11 +319,7 @@ TEST_CASE("RMT TX stop", "[rmt]")
uint32_t cmd = 0x20;
bool repeat = false;
int tx_channel = 0;
#ifdef CONFIG_IDF_TARGET_ESP32S3
int rx_channel = 4;
#else
int rx_channel = 1;
#endif
int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1;
rmt_setup_testbench(tx_channel, rx_channel, 0);
@ -377,11 +378,7 @@ TEST_CASE("RMT TX stop", "[rmt]")
TEST_CASE("RMT Ping-Pong operation", "[rmt]")
{
int tx_channel = 0;
#ifdef CONFIG_IDF_TARGET_ESP32S3
int rx_channel = 4;
#else
int rx_channel = 1;
#endif
int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1;
rmt_item32_t frames[SOC_RMT_CHANNEL_MEM_WORDS * 2]; // send two block data using ping-pong
RingbufHandle_t rb = NULL;
uint32_t size = sizeof(frames) / sizeof(frames[0]);
@ -498,11 +495,7 @@ TEST_CASE("RMT TX loop", "[rmt]")
uint32_t cmd = 0x20;
bool repeat = false;
int tx_channel = 0;
#ifdef CONFIG_IDF_TARGET_ESP32S3
int rx_channel = 4;
#else
int rx_channel = 1;
#endif
int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1;
uint32_t count = 0;
rmt_setup_testbench(tx_channel, rx_channel, RMT_TESTBENCH_FLAGS_LOOP_ON);
@ -545,5 +538,3 @@ TEST_CASE("RMT TX loop", "[rmt]")
rmt_clean_testbench(tx_channel, rx_channel);
}
#endif
#endif

View File

@ -24,47 +24,14 @@ extern "C" {
#define RMT_LL_HW_BASE (&RMT)
#define RMT_LL_MEM_BASE (&RMTMEM)
// Note: TX and RX channel number are all index from zero in the LL driver
// i.e. tx_channel belongs to [0,7], and rx_channel belongs to [0,7]
static inline void rmt_ll_enable_drive_clock(rmt_dev_t *dev, bool enable)
{
dev->conf_ch[0].conf0.clk_en = enable;
}
static inline void rmt_ll_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.ref_cnt_rst = 1;
dev->conf_ch[channel].conf1.ref_cnt_rst = 0;
}
static inline void rmt_ll_reset_tx_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.mem_rd_rst = 1;
dev->conf_ch[channel].conf1.mem_rd_rst = 0;
}
static inline void rmt_ll_reset_rx_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.mem_wr_rst = 1;
dev->conf_ch[channel].conf1.mem_wr_rst = 0;
}
static inline void rmt_ll_start_tx(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.tx_start = 1;
}
static inline void rmt_ll_stop_tx(rmt_dev_t *dev, uint32_t channel)
{
RMTMEM.chan[channel].data32[0].val = 0;
dev->conf_ch[channel].conf1.tx_start = 0;
dev->conf_ch[channel].conf1.mem_rd_rst = 1;
dev->conf_ch[channel].conf1.mem_rd_rst = 0;
}
static inline void rmt_ll_enable_rx(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.rx_en = enable;
}
static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable)
{
dev->conf_ch[0].conf0.mem_pd = enable; // Only conf0 register of channel0 has `mem_pd`
@ -75,78 +42,12 @@ static inline bool rmt_ll_is_mem_power_down(rmt_dev_t *dev)
return dev->conf_ch[0].conf0.mem_pd; // Only conf0 register of channel0 has `mem_pd`
}
static inline void rmt_ll_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
dev->conf_ch[channel].conf0.mem_size = block_num;
}
static inline uint32_t rmt_ll_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf0.mem_size;
}
static inline void rmt_ll_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
dev->conf_ch[channel].conf0.div_cnt = div;
}
static inline uint32_t rmt_ll_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
uint32_t div = dev->conf_ch[channel].conf0.div_cnt;
return div == 0 ? 256 : div;
}
static inline void rmt_ll_enable_tx_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->apb_conf.mem_tx_wrap_en = enable;
}
static inline void rmt_ll_enable_mem_access(rmt_dev_t *dev, bool enable)
{
dev->apb_conf.fifo_mask = enable;
}
static inline void rmt_ll_set_rx_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->conf_ch[channel].conf0.idle_thres = thres;
}
static inline uint32_t rmt_ll_get_rx_idle_thres(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf0.idle_thres;
}
static inline void rmt_ll_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner)
{
dev->conf_ch[channel].conf1.mem_owner = owner;
}
static inline uint32_t rmt_ll_get_mem_owner(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf1.mem_owner;
}
static inline void rmt_ll_enable_tx_loop(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.tx_conti_mode = enable;
}
static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf1.tx_conti_mode;
}
static inline void rmt_ll_enable_rx_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.rx_filter_en = enable;
}
static inline void rmt_ll_set_rx_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->conf_ch[channel].conf1.rx_filter_thres = thres;
}
static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src)
static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src, uint8_t div_num, uint8_t div_a, uint8_t div_b)
{
dev->conf_ch[channel].conf1.ref_always_on = src;
}
@ -156,7 +57,136 @@ static inline uint32_t rmt_ll_get_counter_clock_src(rmt_dev_t *dev, uint32_t cha
return dev->conf_ch[channel].conf1.ref_always_on;
}
static inline void rmt_ll_enable_tx_idle(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_tx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.ref_cnt_rst = 1;
dev->conf_ch[channel].conf1.ref_cnt_rst = 0;
}
static inline void rmt_ll_rx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.ref_cnt_rst = 1;
dev->conf_ch[channel].conf1.ref_cnt_rst = 0;
}
static inline void rmt_ll_tx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.mem_rd_rst = 1;
dev->conf_ch[channel].conf1.mem_rd_rst = 0;
}
static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.mem_wr_rst = 1;
dev->conf_ch[channel].conf1.mem_wr_rst = 0;
}
static inline void rmt_ll_tx_start(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.tx_start = 1;
}
static inline void rmt_ll_tx_stop(rmt_dev_t *dev, uint32_t channel)
{
RMTMEM.chan[channel].data32[0].val = 0;
dev->conf_ch[channel].conf1.tx_start = 0;
dev->conf_ch[channel].conf1.mem_rd_rst = 1;
dev->conf_ch[channel].conf1.mem_rd_rst = 0;
}
static inline void rmt_ll_rx_enable(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.rx_en = enable;
}
static inline void rmt_ll_tx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
dev->conf_ch[channel].conf0.mem_size = block_num;
}
static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
dev->conf_ch[channel].conf0.mem_size = block_num;
}
static inline uint32_t rmt_ll_tx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf0.mem_size;
}
static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf0.mem_size;
}
static inline void rmt_ll_tx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
dev->conf_ch[channel].conf0.div_cnt = div;
}
static inline void rmt_ll_rx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
dev->conf_ch[channel].conf0.div_cnt = div;
}
static inline uint32_t rmt_ll_tx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
uint32_t div = dev->conf_ch[channel].conf0.div_cnt;
return div == 0 ? 256 : div;
}
static inline uint32_t rmt_ll_rx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
uint32_t div = dev->conf_ch[channel].conf0.div_cnt;
return div == 0 ? 256 : div;
}
static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->apb_conf.mem_tx_wrap_en = enable;
}
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->conf_ch[channel].conf0.idle_thres = thres;
}
static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf0.idle_thres;
}
static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner)
{
dev->conf_ch[channel].conf1.mem_owner = owner;
}
static inline uint32_t rmt_ll_rx_get_mem_owner(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf1.mem_owner;
}
static inline void rmt_ll_tx_enable_loop(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.tx_conti_mode = enable;
}
static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf1.tx_conti_mode;
}
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.rx_filter_en = enable;
}
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->conf_ch[channel].conf1.rx_filter_thres = thres;
}
static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.idle_out_en = enable;
}
@ -166,22 +196,27 @@ static inline bool rmt_ll_is_tx_idle_enabled(rmt_dev_t *dev, uint32_t channel)
return dev->conf_ch[channel].conf1.idle_out_en;
}
static inline void rmt_ll_set_tx_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
static inline void rmt_ll_tx_set_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
{
dev->conf_ch[channel].conf1.idle_out_lv = level;
}
static inline uint32_t rmt_ll_get_tx_idle_level(rmt_dev_t *dev, uint32_t channel)
static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf1.idle_out_lv;
}
static inline uint32_t rmt_ll_get_channel_status(rmt_dev_t *dev, uint32_t channel)
static inline uint32_t rmt_ll_rx_get_channel_status(rmt_dev_t *dev, uint32_t channel)
{
return dev->status_ch[channel];
}
static inline void rmt_ll_set_tx_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
static inline uint32_t rmt_ll_tx_get_channel_status(rmt_dev_t *dev, uint32_t channel)
{
return dev->status_ch[channel];
}
static inline void rmt_ll_tx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
{
dev->tx_lim_ch[channel].limit = limit;
}
@ -198,7 +233,13 @@ static inline void rmt_ll_enable_rx_end_interrupt(rmt_dev_t *dev, uint32_t chann
dev->int_ena.val |= (enable << (channel * 3 + 1));
}
static inline void rmt_ll_enable_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_enable_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->int_ena.val &= ~(1 << (channel * 3 + 2));
dev->int_ena.val |= (enable << (channel * 3 + 2));
}
static inline void rmt_ll_enable_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->int_ena.val &= ~(1 << (channel * 3 + 2));
dev->int_ena.val |= (enable << (channel * 3 + 2));
@ -220,7 +261,12 @@ static inline void rmt_ll_clear_rx_end_interrupt(rmt_dev_t *dev, uint32_t channe
dev->int_clr.val = (1 << (channel * 3 + 1));
}
static inline void rmt_ll_clear_err_interrupt(rmt_dev_t *dev, uint32_t channel)
static inline void rmt_ll_clear_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel)
{
dev->int_clr.val = (1 << (channel * 3 + 2));
}
static inline void rmt_ll_clear_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel)
{
dev->int_clr.val = (1 << (channel * 3 + 2));
}
@ -244,7 +290,14 @@ static inline uint32_t rmt_ll_get_rx_end_interrupt_status(rmt_dev_t *dev)
((status & 0x2000) >> 9) | ((status & 0x10000) >> 11) | ((status & 0x80000) >> 13) | ((status & 0x400000) >> 15);
}
static inline uint32_t rmt_ll_get_err_interrupt_status(rmt_dev_t *dev)
static inline uint32_t rmt_ll_get_tx_err_interrupt_status(rmt_dev_t *dev)
{
uint32_t status = dev->int_st.val;
return ((status & 0x04) >> 2) | ((status & 0x20) >> 4) | ((status & 0x100) >> 6) | ((status & 0x800) >> 8) |
((status & 0x4000) >> 10) | ((status & 0x20000) >> 12) | ((status & 0x100000) >> 14) | ((status & 0x800000) >> 16);
}
static inline uint32_t rmt_ll_get_rx_err_interrupt_status(rmt_dev_t *dev)
{
uint32_t status = dev->int_st.val;
return ((status & 0x04) >> 2) | ((status & 0x20) >> 4) | ((status & 0x100) >> 6) | ((status & 0x800) >> 8) |
@ -257,24 +310,24 @@ static inline uint32_t rmt_ll_get_tx_thres_interrupt_status(rmt_dev_t *dev)
return (status & 0xFF000000) >> 24;
}
static inline void rmt_ll_set_tx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
static inline void rmt_ll_tx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
{
dev->carrier_duty_ch[channel].high = high_ticks;
dev->carrier_duty_ch[channel].low = low_ticks;
}
static inline void rmt_ll_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks)
static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks)
{
*high_ticks = dev->carrier_duty_ch[channel].high;
*low_ticks = dev->carrier_duty_ch[channel].low;
}
static inline void rmt_ll_enable_carrier(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf0.carrier_en = enable;
}
static inline void rmt_ll_set_carrier_on_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
{
dev->conf_ch[channel].conf0.carrier_out_lv = level;
}
@ -288,8 +341,12 @@ static inline void rmt_ll_write_memory(rmt_mem_t *mem, uint32_t channel, const r
}
}
static inline void rmt_ll_config_update(rmt_dev_t *dev, uint32_t channel)
{
}
/************************************************************************************************
* Following Low Level APIs only used for backward compatible, will be deprecated in the future!
* Following Low Level APIs only used for backward compatible, will be deprecated in the IDF v5.0
***********************************************************************************************/
static inline void rmt_ll_set_intr_enable_mask(uint32_t mask)

View File

@ -24,45 +24,15 @@ extern "C" {
#define RMT_LL_HW_BASE (&RMT)
#define RMT_LL_MEM_BASE (&RMTMEM)
// Note: TX and RX channel number are all index from zero in the LL driver
// i.e. tx_channel belongs to [0,3], and rx_channel belongs to [0,3]
static inline void rmt_ll_enable_drive_clock(rmt_dev_t *dev, bool enable)
{
dev->apb_conf.clk_en = enable; // register clock gating
dev->apb_conf.mem_clk_force_on = enable; // memory clock gating
}
static inline void rmt_ll_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
dev->ref_cnt_rst.val |= (1 << channel);
dev->ref_cnt_rst.val &= ~(1 << channel);
}
static inline void rmt_ll_reset_tx_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.mem_rd_rst = 1;
dev->conf_ch[channel].conf1.mem_rd_rst = 0;
}
static inline void rmt_ll_reset_rx_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.mem_wr_rst = 1;
dev->conf_ch[channel].conf1.mem_wr_rst = 0;
}
static inline void rmt_ll_start_tx(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.tx_start = 1;
}
static inline void rmt_ll_stop_tx(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.tx_stop = 1;
}
static inline void rmt_ll_enable_rx(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.rx_en = enable;
}
static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable)
{
dev->apb_conf.mem_force_pu = !enable;
@ -77,110 +47,12 @@ static inline bool rmt_ll_is_mem_power_down(rmt_dev_t *dev)
return (dev->apb_conf.mem_force_pd) || !(dev->apb_conf.mem_force_pu);
}
static inline void rmt_ll_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
dev->conf_ch[channel].conf0.mem_size = block_num;
}
static inline uint32_t rmt_ll_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf0.mem_size;
}
static inline void rmt_ll_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
dev->conf_ch[channel].conf0.div_cnt = div;
}
static inline uint32_t rmt_ll_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
uint32_t div = dev->conf_ch[channel].conf0.div_cnt;
return div == 0 ? 256 : div;
}
static inline void rmt_ll_enable_tx_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->apb_conf.mem_tx_wrap_en = enable;
}
static inline void rmt_ll_enable_mem_access(rmt_dev_t *dev, bool enable)
{
dev->apb_conf.fifo_mask = enable;
}
static inline void rmt_ll_set_rx_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->conf_ch[channel].conf0.idle_thres = thres;
}
static inline uint32_t rmt_ll_get_rx_idle_thres(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf0.idle_thres;
}
static inline void rmt_ll_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner)
{
dev->conf_ch[channel].conf1.mem_owner = owner;
}
static inline uint32_t rmt_ll_get_mem_owner(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf1.mem_owner;
}
static inline void rmt_ll_enable_tx_loop(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.tx_conti_mode = enable;
}
static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf1.tx_conti_mode;
}
static inline void rmt_ll_set_tx_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count)
{
dev->tx_lim_ch[channel].tx_loop_num = count;
}
static inline void rmt_ll_reset_tx_loop(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_lim_ch[channel].loop_count_reset = 1;
dev->tx_lim_ch[channel].loop_count_reset = 0;
}
static inline void rmt_ll_enable_tx_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->tx_lim_ch[channel].tx_loop_cnt_en = enable;
}
static inline void rmt_ll_enable_tx_sync(rmt_dev_t *dev, bool enable)
{
dev->tx_sim.en = enable;
}
static inline void rmt_ll_add_channel_to_group(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_sim.val |= 1 << channel;
}
static inline uint32_t rmt_ll_remove_channel_from_group(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_sim.val &= ~(1 << channel);
return dev->tx_sim.val & 0x0F;
}
static inline void rmt_ll_enable_rx_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.rx_filter_en = enable;
}
static inline void rmt_ll_set_rx_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->conf_ch[channel].conf1.rx_filter_thres = thres;
}
static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src)
static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src, uint8_t div_num, uint8_t div_a, uint8_t div_b)
{
dev->conf_ch[channel].conf1.ref_always_on = src;
}
@ -190,7 +62,165 @@ static inline uint32_t rmt_ll_get_counter_clock_src(rmt_dev_t *dev, uint32_t cha
return dev->conf_ch[channel].conf1.ref_always_on;
}
static inline void rmt_ll_enable_tx_idle(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_tx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
dev->ref_cnt_rst.val |= (1 << channel);
dev->ref_cnt_rst.val &= ~(1 << channel);
}
static inline void rmt_ll_rx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
dev->ref_cnt_rst.val |= (1 << channel);
dev->ref_cnt_rst.val &= ~(1 << channel);
}
static inline void rmt_ll_tx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.mem_rd_rst = 1;
dev->conf_ch[channel].conf1.mem_rd_rst = 0;
}
static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.mem_wr_rst = 1;
dev->conf_ch[channel].conf1.mem_wr_rst = 0;
}
static inline void rmt_ll_tx_start(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.tx_start = 1;
}
static inline void rmt_ll_tx_stop(rmt_dev_t *dev, uint32_t channel)
{
dev->conf_ch[channel].conf1.tx_stop = 1;
}
static inline void rmt_ll_rx_enable(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.rx_en = enable;
}
static inline void rmt_ll_tx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
dev->conf_ch[channel].conf0.mem_size = block_num;
}
static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
dev->conf_ch[channel].conf0.mem_size = block_num;
}
static inline uint32_t rmt_ll_tx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf0.mem_size;
}
static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf0.mem_size;
}
static inline void rmt_ll_tx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
dev->conf_ch[channel].conf0.div_cnt = div;
}
static inline void rmt_ll_rx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
dev->conf_ch[channel].conf0.div_cnt = div;
}
static inline uint32_t rmt_ll_tx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
uint32_t div = dev->conf_ch[channel].conf0.div_cnt;
return div == 0 ? 256 : div;
}
static inline uint32_t rmt_ll_rx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
uint32_t div = dev->conf_ch[channel].conf0.div_cnt;
return div == 0 ? 256 : div;
}
static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->apb_conf.mem_tx_wrap_en = enable;
}
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->conf_ch[channel].conf0.idle_thres = thres;
}
static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf0.idle_thres;
}
static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner)
{
dev->conf_ch[channel].conf1.mem_owner = owner;
}
static inline uint32_t rmt_ll_rx_get_mem_owner(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf1.mem_owner;
}
static inline void rmt_ll_tx_enable_loop(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.tx_conti_mode = enable;
}
static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf1.tx_conti_mode;
}
static inline void rmt_ll_tx_set_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count)
{
dev->tx_lim_ch[channel].tx_loop_num = count;
}
static inline void rmt_ll_tx_reset_loop(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_lim_ch[channel].loop_count_reset = 1;
dev->tx_lim_ch[channel].loop_count_reset = 0;
}
static inline void rmt_ll_tx_enable_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->tx_lim_ch[channel].tx_loop_cnt_en = enable;
}
static inline void rmt_ll_tx_enable_sync(rmt_dev_t *dev, bool enable)
{
dev->tx_sim.en = enable;
}
static inline void rmt_ll_tx_add_channel_to_group(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_sim.val |= 1 << channel;
}
static inline uint32_t rmt_ll_tx_remove_channel_from_group(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_sim.val &= ~(1 << channel);
return dev->tx_sim.val & 0x0F;
}
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.rx_filter_en = enable;
}
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->conf_ch[channel].conf1.rx_filter_thres = thres;
}
static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.idle_out_en = enable;
}
@ -200,32 +230,37 @@ static inline bool rmt_ll_is_tx_idle_enabled(rmt_dev_t *dev, uint32_t channel)
return dev->conf_ch[channel].conf1.idle_out_en;
}
static inline void rmt_ll_set_tx_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
static inline void rmt_ll_tx_set_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
{
dev->conf_ch[channel].conf1.idle_out_lv = level;
}
static inline uint32_t rmt_ll_get_tx_idle_level(rmt_dev_t *dev, uint32_t channel)
static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel)
{
return dev->conf_ch[channel].conf1.idle_out_lv;
}
static inline uint32_t rmt_ll_get_channel_status(rmt_dev_t *dev, uint32_t channel)
static inline uint32_t rmt_ll_rx_get_channel_status(rmt_dev_t *dev, uint32_t channel)
{
return dev->status_ch[channel].val;
}
static inline void rmt_ll_set_tx_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
static inline uint32_t rmt_ll_tx_get_channel_status(rmt_dev_t *dev, uint32_t channel)
{
return dev->status_ch[channel].val;
}
static inline void rmt_ll_tx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
{
dev->tx_lim_ch[channel].limit = limit;
}
static inline void rmt_ll_set_rx_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
static inline void rmt_ll_rx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
{
dev->tx_lim_ch[channel].rx_lim = limit;
}
static inline uint32_t rmt_ll_get_rx_limit(rmt_dev_t *dev, uint32_t channel)
static inline uint32_t rmt_ll_rx_get_limit(rmt_dev_t *dev, uint32_t channel)
{
return dev->tx_lim_ch[channel].rx_lim;
}
@ -242,7 +277,13 @@ static inline void rmt_ll_enable_rx_end_interrupt(rmt_dev_t *dev, uint32_t chann
dev->int_ena.val |= (enable << (channel * 3 + 1));
}
static inline void rmt_ll_enable_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_enable_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->int_ena.val &= ~(1 << (channel * 3 + 2));
dev->int_ena.val |= (enable << (channel * 3 + 2));
}
static inline void rmt_ll_enable_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->int_ena.val &= ~(1 << (channel * 3 + 2));
dev->int_ena.val |= (enable << (channel * 3 + 2));
@ -276,7 +317,12 @@ static inline void rmt_ll_clear_rx_end_interrupt(rmt_dev_t *dev, uint32_t channe
dev->int_clr.val = (1 << (channel * 3 + 1));
}
static inline void rmt_ll_clear_err_interrupt(rmt_dev_t *dev, uint32_t channel)
static inline void rmt_ll_clear_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel)
{
dev->int_clr.val = (1 << (channel * 3 + 2));
}
static inline void rmt_ll_clear_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel)
{
dev->int_clr.val = (1 << (channel * 3 + 2));
}
@ -308,7 +354,13 @@ static inline uint32_t rmt_ll_get_rx_end_interrupt_status(rmt_dev_t *dev)
return ((status & 0x02) >> 1) | ((status & 0x10) >> 3) | ((status & 0x80) >> 5) | ((status & 0x400) >> 7);
}
static inline uint32_t rmt_ll_get_err_interrupt_status(rmt_dev_t *dev)
static inline uint32_t rmt_ll_get_tx_err_interrupt_status(rmt_dev_t *dev)
{
uint32_t status = dev->int_st.val;
return ((status & 0x04) >> 2) | ((status & 0x20) >> 4) | ((status & 0x100) >> 6) | ((status & 0x800) >> 8);
}
static inline uint32_t rmt_ll_get_rx_err_interrupt_status(rmt_dev_t *dev)
{
uint32_t status = dev->int_st.val;
return ((status & 0x04) >> 2) | ((status & 0x20) >> 4) | ((status & 0x100) >> 6) | ((status & 0x800) >> 8);
@ -332,7 +384,7 @@ static inline uint32_t rmt_ll_get_rx_thres_interrupt_status(rmt_dev_t *dev)
return (status & 0xF00000) >> 20;
}
static inline void rmt_ll_set_tx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
static inline void rmt_ll_tx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
{
// In case the compiler optimise a 32bit instruction (e.g. s32i) into two 16bit instruction (e.g. s16i, which is not allowed to access a register)
// We take care of the "read-modify-write" procedure by ourselves.
@ -342,27 +394,42 @@ static inline void rmt_ll_set_tx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t
dev->carrier_duty_ch[channel].val = reg.val;
}
static inline void rmt_ll_set_rx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
{
dev->ch_rx_carrier_rm[channel].carrier_high_thres_ch = high_ticks;
dev->ch_rx_carrier_rm[channel].carrier_low_thres_ch = low_ticks;
typeof(dev->ch_rx_carrier_rm[0]) reg;
reg.carrier_high_thres_ch = high_ticks;
reg.carrier_low_thres_ch = low_ticks;
dev->ch_rx_carrier_rm[channel].val = reg.val;
}
static inline void rmt_ll_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks)
static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks)
{
*high_ticks = dev->carrier_duty_ch[channel].high;
*low_ticks = dev->carrier_duty_ch[channel].low;
}
// This function has different meaning for TX and RX
// TX: enable to modulate carrier
// RX: enable to demodulate carrier
static inline void rmt_ll_enable_carrier(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks)
{
*high_ticks = dev->ch_rx_carrier_rm[channel].carrier_high_thres_ch;
*low_ticks = dev->ch_rx_carrier_rm[channel].carrier_low_thres_ch;
}
static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf0.carrier_en = enable;
}
static inline void rmt_ll_set_carrier_on_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
static inline void rmt_ll_rx_enable_carrier_demodulation(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf0.carrier_en = enable;
}
static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
{
dev->conf_ch[channel].conf0.carrier_out_lv = level;
}
static inline void rmt_ll_rx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
{
dev->conf_ch[channel].conf0.carrier_out_lv = level;
}
@ -383,13 +450,17 @@ static inline void rmt_ll_write_memory(rmt_mem_t *mem, uint32_t channel, const r
}
}
static inline void rmt_ll_enable_rx_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_rx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->conf_ch[channel].conf1.chk_rx_carrier_en = enable;
}
static inline void rmt_ll_config_update(rmt_dev_t *dev, uint32_t channel)
{
}
/************************************************************************************************
* Following Low Level APIs only used for backward compatible, will be deprecated in the future!
* Following Low Level APIs only used for backward compatible, will be deprecated in the IDF v5.0
***********************************************************************************************/
static inline void rmt_ll_set_intr_enable_mask(uint32_t mask)

View File

@ -25,19 +25,8 @@ extern "C" {
#define RMT_LL_HW_BASE (&RMT)
#define RMT_LL_MEM_BASE (&RMTMEM)
#define RMT_LL_TX_CHAN_NUM (4)
#define RMT_LL_TX_CHAN_MASK (0x0F)
#define RMT_LL_RX_CHAN_MASK (0xF0)
static inline void rmt_ll_set_sclk(rmt_dev_t *dev, uint32_t source, uint32_t div_num, uint32_t div_frac_a, uint32_t div_frac_b)
{
dev->sys_conf.sclk_active = 0;
dev->sys_conf.sclk_sel = source;
dev->sys_conf.sclk_div_num = div_num;
dev->sys_conf.sclk_div_a = div_frac_a;
dev->sys_conf.sclk_div_b = div_frac_b;
dev->sys_conf.sclk_active = 1;
}
// Note: TX and RX channel number are all index from zero in the LL driver
// i.e. tx_channel belongs to [0,3], and rx_channel belongs to [0,3]
static inline void rmt_ll_enable_drive_clock(rmt_dev_t *dev, bool enable)
{
@ -45,46 +34,6 @@ static inline void rmt_ll_enable_drive_clock(rmt_dev_t *dev, bool enable)
dev->sys_conf.mem_clk_force_on = enable; // memory clock gating
}
static inline void rmt_ll_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
dev->ref_cnt_rst.val |= (1 << channel);
dev->ref_cnt_rst.val &= ~(1 << channel);
}
static inline void rmt_ll_reset_tx_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_conf[channel].mem_rd_rst = 1;
dev->tx_conf[channel].mem_rd_rst = 0;
dev->tx_conf[channel].apb_mem_rst = 1;
dev->tx_conf[channel].apb_mem_rst = 0;
}
static inline void rmt_ll_reset_rx_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.mem_wr_rst = 1;
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.mem_wr_rst = 0;
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.apb_mem_rst = 1;
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.apb_mem_rst = 0;
}
static inline void rmt_ll_start_tx(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_conf[channel].conf_update = 1;
dev->tx_conf[channel].tx_start = 1;
}
static inline void rmt_ll_stop_tx(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_conf[channel].tx_stop = 1;
dev->tx_conf[channel].conf_update = 1;
}
static inline void rmt_ll_enable_rx(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.rx_en = enable;
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.conf_update = 1;
}
static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable)
{
dev->sys_conf.mem_force_pu = !enable;
@ -99,67 +48,139 @@ static inline bool rmt_ll_is_mem_power_down(rmt_dev_t *dev)
return (dev->sys_conf.mem_force_pd) || !(dev->sys_conf.mem_force_pu);
}
static inline void rmt_ll_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
if(channel < RMT_LL_TX_CHAN_NUM) {
dev->tx_conf[channel].mem_size = block_num;
} else {
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.mem_size = block_num;
}
}
static inline uint32_t rmt_ll_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
{
return (channel < RMT_LL_TX_CHAN_NUM) ? (dev->tx_conf[channel].mem_size) : (dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.mem_size);
}
static inline void rmt_ll_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
if(channel < RMT_LL_TX_CHAN_NUM) {
dev->tx_conf[channel].div_cnt = div;
} else {
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.div_cnt = div;
}
}
static inline uint32_t rmt_ll_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
return (channel < RMT_LL_TX_CHAN_NUM) ? (dev->tx_conf[channel].div_cnt) : (dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.div_cnt);
}
static inline void rmt_ll_enable_tx_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->tx_conf[channel].mem_tx_wrap_en = enable;
}
static inline void rmt_ll_enable_mem_access(rmt_dev_t *dev, bool enable)
{
dev->sys_conf.fifo_mask = enable;
}
static inline void rmt_ll_set_rx_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src, uint8_t div_num, uint8_t div_a, uint8_t div_b)
{
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.idle_thres = thres;
// Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b)
dev->sys_conf.sclk_active = 0;
dev->sys_conf.sclk_sel = src;
dev->sys_conf.sclk_div_num = div_num;
dev->sys_conf.sclk_div_a = div_a;
dev->sys_conf.sclk_div_b = div_b;
dev->sys_conf.sclk_active = 1;
}
static inline uint32_t rmt_ll_get_rx_idle_thres(rmt_dev_t *dev, uint32_t channel)
static inline uint32_t rmt_ll_get_counter_clock_src(rmt_dev_t *dev, uint32_t channel)
{
return dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.idle_thres;
return dev->sys_conf.sclk_sel;
}
static inline void rmt_ll_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner)
static inline void rmt_ll_tx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
if (channel >= RMT_LL_TX_CHAN_NUM) {
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.mem_owner = owner;
}
dev->ref_cnt_rst.val |= (1 << channel);
dev->ref_cnt_rst.val &= ~(1 << channel);
}
static inline uint32_t rmt_ll_get_mem_owner(rmt_dev_t *dev, uint32_t channel)
static inline void rmt_ll_rx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
return dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.mem_owner;
dev->ref_cnt_rst.val |= (1 << (channel + 4));
dev->ref_cnt_rst.val &= ~(1 << (channel + 4));
}
static inline void rmt_ll_enable_tx_loop(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_tx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_conf[channel].mem_rd_rst = 1;
dev->tx_conf[channel].mem_rd_rst = 0;
dev->tx_conf[channel].apb_mem_rst = 1;
dev->tx_conf[channel].apb_mem_rst = 0;
}
static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
{
dev->rx_conf[channel].conf1.mem_wr_rst = 1;
dev->rx_conf[channel].conf1.mem_wr_rst = 0;
dev->rx_conf[channel].conf1.apb_mem_rst = 1;
dev->rx_conf[channel].conf1.apb_mem_rst = 0;
}
static inline void rmt_ll_tx_start(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_conf[channel].conf_update = 1;
dev->tx_conf[channel].tx_start = 1;
}
static inline void rmt_ll_tx_stop(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_conf[channel].tx_stop = 1;
dev->tx_conf[channel].conf_update = 1;
}
static inline void rmt_ll_rx_enable(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->rx_conf[channel].conf1.rx_en = enable;
dev->rx_conf[channel].conf1.conf_update = 1;
}
static inline void rmt_ll_tx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
dev->tx_conf[channel].mem_size = block_num;
}
static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
{
dev->rx_conf[channel].conf0.mem_size = block_num;
}
static inline uint32_t rmt_ll_tx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
{
return dev->tx_conf[channel].mem_size;
}
static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
{
return dev->rx_conf[channel].conf0.mem_size;
}
static inline void rmt_ll_tx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
dev->tx_conf[channel].div_cnt = div;
}
static inline void rmt_ll_rx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
{
dev->rx_conf[channel].conf0.div_cnt = div;
}
static inline uint32_t rmt_ll_tx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
return dev->tx_conf[channel].div_cnt;
}
static inline uint32_t rmt_ll_rx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
{
return dev->rx_conf[channel].conf0.div_cnt;
}
static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->tx_conf[channel].mem_tx_wrap_en = enable;
}
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->rx_conf[channel].conf0.idle_thres = thres;
}
static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel)
{
return dev->rx_conf[channel].conf0.idle_thres;
}
static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner)
{
dev->rx_conf[channel].conf1.mem_owner = owner;
}
static inline uint32_t rmt_ll_rx_get_mem_owner(rmt_dev_t *dev, uint32_t channel)
{
return dev->rx_conf[channel].conf1.mem_owner;
}
static inline void rmt_ll_tx_enable_loop(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->tx_conf[channel].tx_conti_mode = enable;
}
@ -169,62 +190,49 @@ static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel)
return dev->tx_conf[channel].tx_conti_mode;
}
static inline void rmt_ll_set_tx_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count)
static inline void rmt_ll_tx_set_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count)
{
dev->tx_lim[channel].tx_loop_num = count;
}
static inline void rmt_ll_reset_tx_loop(rmt_dev_t *dev, uint32_t channel)
static inline void rmt_ll_tx_reset_loop(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_lim[channel].loop_count_reset = 1;
dev->tx_lim[channel].loop_count_reset = 0;
}
static inline void rmt_ll_enable_tx_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_tx_enable_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->tx_lim[channel].tx_loop_cnt_en = enable;
}
static inline void rmt_ll_enable_tx_sync(rmt_dev_t *dev, bool enable)
static inline void rmt_ll_tx_enable_sync(rmt_dev_t *dev, bool enable)
{
dev->tx_sim.en = enable;
}
static inline void rmt_ll_add_channel_to_group(rmt_dev_t *dev, uint32_t channel)
static inline void rmt_ll_tx_add_channel_to_group(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_sim.val |= 1 << channel;
}
static inline uint32_t rmt_ll_remove_channel_from_group(rmt_dev_t *dev, uint32_t channel)
static inline uint32_t rmt_ll_tx_remove_channel_from_group(rmt_dev_t *dev, uint32_t channel)
{
dev->tx_sim.val &= ~(1 << channel);
return dev->tx_sim.val & RMT_LL_TX_CHAN_MASK;
return dev->tx_sim.val & 0x0F;
}
static inline void rmt_ll_enable_rx_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.rx_filter_en = enable;
dev->rx_conf[channel].conf1.rx_filter_en = enable;
}
static inline void rmt_ll_set_rx_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
{
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.rx_filter_thres = thres;
dev->rx_conf[channel].conf1.rx_filter_thres = thres;
}
static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src)
{
dev->sys_conf.sclk_sel = src;
dev->sys_conf.sclk_div_num = 0;
dev->sys_conf.sclk_div_a = 0;
dev->sys_conf.sclk_div_b = 0;
}
static inline uint32_t rmt_ll_get_counter_clock_src(rmt_dev_t *dev, uint32_t channel)
{
return dev->sys_conf.sclk_sel;
}
static inline void rmt_ll_enable_tx_idle(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->tx_conf[channel].idle_out_en = enable;
}
@ -234,173 +242,175 @@ static inline bool rmt_ll_is_tx_idle_enabled(rmt_dev_t *dev, uint32_t channel)
return dev->tx_conf[channel].idle_out_en;
}
static inline void rmt_ll_set_tx_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
static inline void rmt_ll_tx_set_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
{
dev->tx_conf[channel].idle_out_lv = level;
}
static inline uint32_t rmt_ll_get_tx_idle_level(rmt_dev_t *dev, uint32_t channel)
static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel)
{
return dev->tx_conf[channel].idle_out_lv;
}
static inline uint32_t rmt_ll_get_channel_status(rmt_dev_t *dev, uint32_t channel)
static inline uint32_t rmt_ll_rx_get_channel_status(rmt_dev_t *dev, uint32_t channel)
{
return (channel < RMT_LL_TX_CHAN_NUM) ? (dev->tx_status[channel].val) : (dev->rx_status[channel - RMT_LL_TX_CHAN_NUM].val);
return dev->rx_status[channel].val;
}
static inline void rmt_ll_set_tx_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
static inline uint32_t rmt_ll_tx_get_channel_status(rmt_dev_t *dev, uint32_t channel)
{
return dev->tx_status[channel].val;
}
static inline void rmt_ll_tx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
{
dev->tx_lim[channel].limit = limit;
}
static inline void rmt_ll_set_rx_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
static inline void rmt_ll_rx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
{
dev->rx_lim[channel - RMT_LL_TX_CHAN_NUM].rx_lim = limit;
dev->rx_lim[channel].rx_lim = limit;
}
static inline uint32_t rmt_ll_get_rx_limit(rmt_dev_t *dev, uint32_t channel)
static inline uint32_t rmt_ll_rx_get_limit(rmt_dev_t *dev, uint32_t channel)
{
return dev->rx_lim[channel - RMT_LL_TX_CHAN_NUM].rx_lim;
return dev->rx_lim[channel].rx_lim;
}
static inline void rmt_ll_enable_tx_end_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
if (enable) {
dev->int_ena.val |= (BIT(0) << (channel));
dev->int_ena.val |= (1 << channel);
} else {
dev->int_ena.val &= ~(BIT(0) << (channel));
dev->int_ena.val &= ~(1 << channel);
}
}
static inline void rmt_ll_enable_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
if (enable) {
dev->int_ena.val |= (1 << (channel + 4));
} else {
dev->int_ena.val &= ~(1 << (channel + 4));
}
}
static inline void rmt_ll_enable_rx_end_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
if (enable) {
dev->int_ena.val |= (BIT(16) << (channel - RMT_LL_TX_CHAN_NUM));
dev->int_ena.val |= (1 << (channel + 16));
} else {
dev->int_ena.val &= ~(BIT(16) << (channel - RMT_LL_TX_CHAN_NUM));
dev->int_ena.val &= ~(1 << (channel + 16));
}
}
static inline void rmt_ll_enable_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_enable_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
if(channel < RMT_LL_TX_CHAN_NUM) {
if (enable) {
dev->int_ena.val |= (BIT(4) << (channel));
} else {
dev->int_ena.val &= ~(BIT(4) << (channel));
}
if (enable) {
dev->int_ena.val |= (1 << (channel + 20));
} else {
if (enable) {
dev->int_ena.val |= (BIT(20) << (channel - RMT_LL_TX_CHAN_NUM));
} else {
dev->int_ena.val &= ~(BIT(20) << (channel - RMT_LL_TX_CHAN_NUM));
}
dev->int_ena.val &= ~(1 << (channel + 20));
}
}
static inline void rmt_ll_enable_tx_thres_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
if (enable) {
dev->int_ena.val |= (BIT(8) << (channel));
dev->int_ena.val |= (1 << (channel + 8));
} else {
dev->int_ena.val &= ~(BIT(8) << (channel));
dev->int_ena.val &= ~(1 << (channel + 8));
}
}
static inline void rmt_ll_enable_tx_loop_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
if (enable) {
dev->int_ena.val |= (BIT(12) << (channel));
dev->int_ena.val |= (1 << (channel + 12));
} else {
dev->int_ena.val &= ~(BIT(12) << (channel));
dev->int_ena.val &= ~(1 << (channel + 12));
}
}
static inline void rmt_ll_enable_rx_thres_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
{
if (enable) {
dev->int_ena.val |= (BIT(24) << (channel - RMT_LL_TX_CHAN_NUM));
dev->int_ena.val |= (1 << (channel + 24));
} else {
dev->int_ena.val &= ~(BIT(24) << (channel - RMT_LL_TX_CHAN_NUM));
dev->int_ena.val &= ~(1 << (channel + 24));
}
}
static inline void rmt_ll_clear_tx_end_interrupt(rmt_dev_t *dev, uint32_t channel)
{
dev->int_clr.val = (BIT(0) << (channel));
dev->int_clr.val = (1 << (channel));
}
static inline void rmt_ll_clear_rx_end_interrupt(rmt_dev_t *dev, uint32_t channel)
{
dev->int_clr.val = (BIT(16) << (channel - RMT_LL_TX_CHAN_NUM));
dev->int_clr.val = (1 << (channel + 16));
}
static inline void rmt_ll_clear_err_interrupt(rmt_dev_t *dev, uint32_t channel)
static inline void rmt_ll_clear_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel)
{
if(channel < RMT_LL_TX_CHAN_NUM) {
dev->int_clr.val = (BIT(4) << (channel));
} else {
dev->int_clr.val = (BIT(20) << (channel - RMT_LL_TX_CHAN_NUM));
}
dev->int_clr.val = (1 << (channel + 4));
}
static inline void rmt_ll_clear_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel)
{
dev->int_clr.val = (1 << (channel + 20));
}
static inline void rmt_ll_clear_tx_thres_interrupt(rmt_dev_t *dev, uint32_t channel)
{
dev->int_clr.val = (BIT(8) << (channel));
dev->int_clr.val = (1 << (channel + 8));
}
static inline void rmt_ll_clear_tx_loop_interrupt(rmt_dev_t *dev, uint32_t channel)
{
dev->int_clr.val = (BIT(12) << (channel));
dev->int_clr.val = (1 << (channel + 12));
}
static inline void rmt_ll_clear_rx_thres_interrupt(rmt_dev_t *dev, uint32_t channel)
{
dev->int_clr.val = (BIT(24) << (channel -RMT_LL_TX_CHAN_NUM));
dev->int_clr.val = (1 << (channel + 24));
}
static inline uint32_t rmt_ll_get_tx_end_interrupt_status(rmt_dev_t *dev)
{
return dev->int_st.val & RMT_LL_TX_CHAN_MASK;
return dev->int_st.val & 0x0F;
}
static inline uint32_t rmt_ll_get_rx_end_interrupt_status(rmt_dev_t *dev)
{
return (dev->int_st.val >> 12) & RMT_LL_RX_CHAN_MASK;
return (dev->int_st.val >> 16) & 0x0F;
}
static inline uint32_t rmt_ll_get_tx_err_interrupt_status(rmt_dev_t *dev)
{
return (dev->int_st.val >> 4) & RMT_LL_TX_CHAN_MASK;
return (dev->int_st.val >> 4) & 0x0F;
}
static inline uint32_t rmt_ll_get_rx_err_interrupt_status(rmt_dev_t *dev)
{
return (dev->int_st.val >> 16) & RMT_LL_RX_CHAN_MASK;
}
static inline uint32_t rmt_ll_get_err_interrupt_status(rmt_dev_t *dev)
{
return ((dev->int_st.val >> 4) & RMT_LL_TX_CHAN_MASK) | ((dev->int_st.val >> 16) & RMT_LL_RX_CHAN_MASK);
return (dev->int_st.val >> 20) & 0x0F;
}
static inline uint32_t rmt_ll_get_tx_thres_interrupt_status(rmt_dev_t *dev)
{
return (dev->int_st.val >> 8) & RMT_LL_TX_CHAN_MASK;
return (dev->int_st.val >> 8) & 0x0F;
}
static inline uint32_t rmt_ll_get_rx_thres_interrupt_status(rmt_dev_t *dev)
{
return (dev->int_st.val >> 20) & RMT_LL_RX_CHAN_MASK;
return (dev->int_st.val >> 24) & 0x0F;
}
static inline uint32_t rmt_ll_get_tx_loop_interrupt_status(rmt_dev_t *dev)
{
return (dev->int_st.val >> 12) & RMT_LL_TX_CHAN_MASK;
return (dev->int_st.val >> 12) & 0x0F;
}
static inline void rmt_ll_set_tx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
static inline void rmt_ll_tx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
{
// In case the compiler optimise a 32bit instruction (e.g. s32i) into two 16bit instruction (e.g. s16i, which is not allowed to access a register)
// We take care of the "read-modify-write" procedure by ourselves.
@ -410,44 +420,44 @@ static inline void rmt_ll_set_tx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t
dev->tx_carrier[channel].val = reg.val;
}
static inline void rmt_ll_set_rx_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
{
typeof(dev->rx_carrier[0]) reg;
reg.high_thres = high_ticks;
reg.low_thres = low_ticks;
dev->rx_carrier[channel - RMT_LL_TX_CHAN_NUM].val = reg.val;
dev->rx_carrier[channel].val = reg.val;
}
static inline void rmt_ll_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks)
static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks )
{
if (channel < RMT_LL_TX_CHAN_NUM) {
*high_ticks = dev->tx_carrier[channel].high;
*low_ticks = dev->tx_carrier[channel].low;
} else {
*high_ticks = dev->rx_carrier[channel - RMT_LL_TX_CHAN_NUM].high_thres;
*low_ticks = dev->rx_carrier[channel - RMT_LL_TX_CHAN_NUM].low_thres;
}
*high_ticks = dev->tx_carrier[channel].high;
*low_ticks = dev->tx_carrier[channel].low;
}
// This function has different meaning for TX and RX
// TX: enable to modulate carrier
// RX: enable to demodulate carrier
static inline void rmt_ll_enable_carrier(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks)
{
if (channel < RMT_LL_TX_CHAN_NUM) {
dev->tx_conf[channel].carrier_en = enable;
} else {
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.carrier_en = enable;
}
*high_ticks = dev->rx_carrier[channel].high_thres;
*low_ticks = dev->rx_carrier[channel].low_thres;
}
static inline void rmt_ll_set_carrier_on_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable)
{
if (channel < RMT_LL_TX_CHAN_NUM) {
dev->tx_conf[channel].carrier_out_lv = level;
} else {
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf0.carrier_out_lv = level;
}
dev->tx_conf[channel].carrier_en = enable;
}
static inline void rmt_ll_rx_enable_carrier_demodulation(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->rx_conf[channel].conf0.carrier_en = enable;
}
static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
{
dev->tx_conf[channel].carrier_out_lv = level;
}
static inline void rmt_ll_rx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
{
dev->rx_conf[channel].conf0.carrier_out_lv = level;
}
// set true, enable carrier in all RMT state (idle, reading, sending)
@ -457,37 +467,22 @@ static inline void rmt_ll_tx_set_carrier_always_on(rmt_dev_t *dev, uint32_t chan
dev->tx_conf[channel].carrier_eff_en = !enable;
}
//Writes items to the specified TX channel memory with the given offset and writen length.
//the caller should ensure that (length + off) <= (memory block * SOC_RMT_CHANNEL_MEM_WORDS)
static inline void rmt_ll_write_memory(rmt_mem_t *mem, uint32_t channel, const rmt_item32_t *data, uint32_t length, uint32_t off)
{
length = (off + length) > SOC_RMT_CHANNEL_MEM_WORDS ? (SOC_RMT_CHANNEL_MEM_WORDS - off) : length;
for (uint32_t i = 0; i < length; i++) {
mem->chan[channel].data32[i + off].val = data[i].val;
}
}
static inline void rmt_ll_enable_rx_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
static inline void rmt_ll_rx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
{
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.mem_rx_wrap_en = enable;
}
static inline void rmt_write_fifo(rmt_dev_t *dev, uint32_t channel, const rmt_item32_t *data, uint32_t length)
{
for (uint32_t i = 0; i < length; i++) {
dev->data_ch[channel] = data[i].val;
}
}
static inline void rmt_ll_config_update(rmt_dev_t *dev, uint32_t channel)
{
if(channel < RMT_LL_TX_CHAN_NUM) {
dev->tx_conf[channel].conf_update = 1;
} else {
dev->rx_conf[channel - RMT_LL_TX_CHAN_NUM].conf1.conf_update = 1;
}
dev->rx_conf[channel].conf1.mem_rx_wrap_en = enable;
}
/************************************************************************************************
* Following Low Level APIs only used for backward compatible, will be deprecated in the future!
* Following Low Level APIs only used for backward compatible, will be deprecated in the IDF v5.0
***********************************************************************************************/
static inline void rmt_ll_set_intr_enable_mask(uint32_t mask)

View File

@ -41,12 +41,20 @@ typedef struct {
void rmt_hal_init(rmt_hal_context_t *hal);
/**
* @brief Reset RMT Channel specific HAL driver
* @brief Reset RMT TX Channel
*
* @param hal: RMT HAL context
* @param channel: RMT channel number
*/
void rmt_hal_channel_reset(rmt_hal_context_t *hal, uint32_t channel);
void rmt_hal_tx_channel_reset(rmt_hal_context_t *hal, uint32_t channel);
/**
* @brief Reset RMT TX Channel
*
* @param hal: RMT HAL context
* @param channel: RMT channel number
*/
void rmt_hal_rx_channel_reset(rmt_hal_context_t *hal, uint32_t channel);
/**
* @brief Set counter clock for RMT channel
@ -56,17 +64,7 @@ void rmt_hal_channel_reset(rmt_hal_context_t *hal, uint32_t channel);
* @param base_clk_hz: base clock for RMT internal channel (counter clock will divide from it)
* @param counter_clk_hz: target counter clock
*/
void rmt_hal_set_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t counter_clk_hz);
/**
* @brief Get counter clock for RMT channel
*
* @param hal: RMT HAL context
* @param channel: RMT channel number
* @param base_clk_hz: base clock for RMT internal channel (counter clock will divide from it)
* @return counter clock in Hz
*/
uint32_t rmt_hal_get_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz);
void rmt_hal_tx_set_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t counter_clk_hz);
/**
* @brief Set carrier clock for RMT channel
@ -79,17 +77,6 @@ uint32_t rmt_hal_get_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uin
*/
void rmt_hal_set_carrier_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t carrier_clk_hz, float carrier_clk_duty);
/**
* @brief Get carrier clock for RMT channel
*
* @param hal: RMT HAL context
* @param channel: RMT channel number
* @param base_clk_hz: base clock for RMT carrier generation
* @param carrier_clk_hz: target carrier clock
* @param carrier_clk_duty: duty ratio of carrier clock
*/
void rmt_hal_get_carrier_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t *carrier_clk_hz, float *carrier_clk_duty);
/**
* @brief Set filter threshold for RMT Receive channel
*
@ -120,18 +107,6 @@ void rmt_hal_set_rx_idle_thres(rmt_hal_context_t *hal, uint32_t channel, uint32_
*/
uint32_t rmt_hal_receive(rmt_hal_context_t *hal, uint32_t channel, rmt_item32_t *buf);
/**
* @brief Transmit a from by RMT
*
* @param hal: RMT HAL context
* @param channel: RMT channel number
* @param src: RMT items to transmit
* @param length: length of RMT items to transmit
* @param offset: offset of RMT internal memory to store the items.
* Note: the caller should ensure that (length + offset) <= (memory block * SOC_RMT_CHANNEL_MEM_WORDS).
*/
void rmt_hal_transmit(rmt_hal_context_t *hal, uint32_t channel, const rmt_item32_t *src, uint32_t length, uint32_t offset);
#ifdef __cplusplus
}
#endif

View File

@ -53,14 +53,11 @@ typedef enum {
*
*/
typedef enum {
#ifdef SOC_RMT_SUPPORT_REF_TICK
#if SOC_RMT_SUPPORT_REF_TICK
RMT_BASECLK_REF = 0, /*!< RMT source clock is REF_TICK, 1MHz by default */
#endif
RMT_BASECLK_APB = 1, /*!< RMT source clock is APB CLK, 80Mhz by default */
#ifdef SOC_RMT_SUPPORT_RTC8M_CLOCK
RMT_BASECLK_RTC8M = 2, /*!< RMT source clock is RTC 8M clock, 8Mhz by default */
#endif
#ifdef SOC_RMT_SUPPORT_XTAL_CLOCK
#if SOC_RMT_SUPPORT_XTAL
RMT_BASECLK_XTAL = 3, /*!< RMT source clock is XTAL clock, 40Mhz by default */
#endif
RMT_BASECLK_MAX,

View File

@ -20,30 +20,31 @@ void rmt_hal_init(rmt_hal_context_t *hal)
hal->mem = &RMTMEM;
}
void rmt_hal_channel_reset(rmt_hal_context_t *hal, uint32_t channel)
void rmt_hal_tx_channel_reset(rmt_hal_context_t *hal, uint32_t channel)
{
rmt_ll_reset_tx_pointer(hal->regs, channel);
rmt_ll_reset_rx_pointer(hal->regs, channel);
rmt_ll_enable_err_interrupt(hal->regs, channel, false);
rmt_ll_tx_reset_pointer(hal->regs, channel);
rmt_ll_enable_tx_err_interrupt(hal->regs, channel, false);
rmt_ll_enable_tx_end_interrupt(hal->regs, channel, false);
rmt_ll_enable_tx_thres_interrupt(hal->regs, channel, false);
rmt_ll_enable_rx_end_interrupt(hal->regs, channel, false);
rmt_ll_clear_err_interrupt(hal->regs, channel);
rmt_ll_clear_tx_err_interrupt(hal->regs, channel);
rmt_ll_clear_tx_end_interrupt(hal->regs, channel);
rmt_ll_clear_tx_thres_interrupt(hal->regs, channel);
}
void rmt_hal_rx_channel_reset(rmt_hal_context_t *hal, uint32_t channel)
{
rmt_ll_rx_reset_pointer(hal->regs, channel);
rmt_ll_enable_rx_err_interrupt(hal->regs, channel, false);
rmt_ll_enable_rx_end_interrupt(hal->regs, channel, false);
rmt_ll_clear_rx_err_interrupt(hal->regs, channel);
rmt_ll_clear_rx_end_interrupt(hal->regs, channel);
}
void rmt_hal_set_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t counter_clk_hz)
void rmt_hal_tx_set_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t counter_clk_hz)
{
rmt_ll_reset_counter_clock_div(hal->regs, channel);
rmt_ll_tx_reset_counter_clock_div(hal->regs, channel);
uint32_t counter_div = (base_clk_hz + counter_clk_hz / 2) / counter_clk_hz;
rmt_ll_set_counter_clock_div(hal->regs, channel, counter_div);
}
uint32_t rmt_hal_get_counter_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz)
{
return base_clk_hz / rmt_ll_get_counter_clock_div(hal->regs, channel);
rmt_ll_tx_set_counter_clock_div(hal->regs, channel, counter_div);
}
void rmt_hal_set_carrier_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t carrier_clk_hz, float carrier_clk_duty)
@ -51,34 +52,25 @@ void rmt_hal_set_carrier_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_
uint32_t carrier_div = (base_clk_hz + carrier_clk_hz / 2) / carrier_clk_hz;
uint32_t div_high = (uint32_t)(carrier_div * carrier_clk_duty);
uint32_t div_low = carrier_div - div_high;
rmt_ll_set_tx_carrier_high_low_ticks(hal->regs, channel, div_high, div_low);
}
void rmt_hal_get_carrier_clock(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t *carrier_clk_hz, float *carrier_clk_duty)
{
uint32_t div_high = 0;
uint32_t div_low = 0;
rmt_ll_get_carrier_high_low_ticks(hal->regs, channel, &div_high, &div_low);
*carrier_clk_hz = base_clk_hz / (div_high + div_low);
*carrier_clk_duty = (float)div_high / (div_high + div_low);
rmt_ll_tx_set_carrier_high_low_ticks(hal->regs, channel, div_high, div_low);
}
void rmt_hal_set_rx_filter_thres(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t thres_us)
{
uint32_t thres = (uint32_t)(base_clk_hz / 1e6 * thres_us);
rmt_ll_set_rx_filter_thres(hal->regs, channel, thres);
rmt_ll_rx_set_filter_thres(hal->regs, channel, thres);
}
void rmt_hal_set_rx_idle_thres(rmt_hal_context_t *hal, uint32_t channel, uint32_t base_clk_hz, uint32_t thres_us)
{
uint32_t thres = (uint32_t)(base_clk_hz / 1e6 * thres_us);
rmt_ll_set_rx_idle_thres(hal->regs, channel, thres);
rmt_ll_rx_set_idle_thres(hal->regs, channel, thres);
}
uint32_t rmt_hal_receive(rmt_hal_context_t *hal, uint32_t channel, rmt_item32_t *buf)
{
uint32_t len = 0;
rmt_ll_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_SW);
rmt_ll_rx_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_SW);
for (len = 0; len < SOC_RMT_CHANNEL_MEM_WORDS; len++) {
buf[len].val = hal->mem->chan[channel].data32[len].val;
if (!(buf[len].val & 0x7FFF)) {
@ -88,14 +80,7 @@ uint32_t rmt_hal_receive(rmt_hal_context_t *hal, uint32_t channel, rmt_item32_t
break;
}
}
rmt_ll_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_HW);
rmt_ll_reset_rx_pointer(hal->regs, channel);
rmt_ll_rx_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_HW);
rmt_ll_rx_reset_pointer(hal->regs, channel);
return len;
}
void rmt_hal_transmit(rmt_hal_context_t *hal, uint32_t channel, const rmt_item32_t *src, uint32_t length, uint32_t offset)
{
rmt_ll_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_SW);
rmt_ll_write_memory(hal->mem, channel, src, length, offset);
rmt_ll_set_mem_owner(hal->regs, channel, RMT_MEM_OWNER_HW);
}

View File

@ -5,8 +5,9 @@ set(srcs
"i2c_periph.c"
"i2s_periph.c"
"interrupts.c"
"pcnt_periph.c"
"ledc_periph.c"
"pcnt_periph.c"
"rmt_periph.c"
"rtc_io_periph.c"
"rtc_periph.c"
"sdio_slave_periph.c"

View File

@ -159,9 +159,12 @@
#define SOC_PCNT_UNIT_CHANNEL_NUM (2)
/*-------------------------- RMT CAPS ----------------------------------------*/
#define SOC_RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory */
#define SOC_RMT_CHANNELS_NUM (8) /*!< Total 8 channels */
#define SOC_RMT_SUPPORT_REF_TICK (1) /*!< Support set REF_TICK as the RMT clock source */
#define SOC_RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory */
#define SOC_RMT_TX_CHANNELS_NUM (8) /*!< Number of channels that capable of Transmit */
#define SOC_RMT_RX_CHANNELS_NUM (8) /*!< Number of channels that capable of Receive */
#define SOC_RMT_CHANNELS_NUM (8) /*!< Total 8 channels (each channel can be configured to either TX or RX) */
#define SOC_RMT_SUPPORT_REF_TICK (1) /*!< Support set REF_TICK as the RMT clock source */
#define SOC_RMT_SOURCE_CLK_INDEPENDENT (1) /*!< Can select different source clock for channels */
/*-------------------------- RTCIO CAPS --------------------------------------*/
#define SOC_RTCIO_PIN_COUNT 18

View File

@ -0,0 +1,56 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/rmt_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/soc.h"
const rmt_signal_conn_t rmt_periph_signals = {
.module = PERIPH_RMT_MODULE,
.irq = ETS_RMT_INTR_SOURCE,
.channels = {
[0] = {
.tx_sig = RMT_SIG_OUT0_IDX,
.rx_sig = -1
},
[1] = {
.tx_sig = RMT_SIG_OUT1_IDX,
.rx_sig = -1
},
[2] = {
.tx_sig = RMT_SIG_OUT2_IDX,
.rx_sig = -1
},
[3] = {
.tx_sig = RMT_SIG_OUT3_IDX,
.rx_sig = -1
},
[4] = {
.tx_sig = -1,
.rx_sig = RMT_SIG_IN0_IDX
},
[5] = {
.tx_sig = -1,
.rx_sig = RMT_SIG_IN1_IDX
},
[6] = {
.tx_sig = -1,
.rx_sig = RMT_SIG_IN2_IDX
},
[7] = {
.tx_sig = -1,
.rx_sig = RMT_SIG_IN3_IDX
}
}
};

View File

@ -8,6 +8,7 @@ set(srcs
"interrupts.c"
"ledc_periph.c"
"pcnt_periph.c"
"rmt_periph.c"
"rtc_io_periph.c"
"rtc_periph.c"
"sigmadelta_periph.c"

View File

@ -143,13 +143,16 @@
#define SOC_PCNT_UNIT_CHANNEL_NUM (2)
/*-------------------------- RMT CAPS ----------------------------------------*/
#define SOC_RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory (1 word = 4 Bytes) */
#define SOC_RMT_CHANNELS_NUM (4) /*!< Total 4 channels */
#define SOC_RMT_SUPPORT_RX_PINGPONG (1) /*!< Support Ping-Pong mode on RX path */
#define SOC_RMT_SUPPORT_RX_DEMODULATION (1) /*!< Support signal demodulation on RX path (i.e. remove carrier) */
#define SOC_RMT_SUPPORT_TX_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */
#define SOC_RMT_SUPPORT_TX_GROUP (1) /*!< Support a group of TX channels to transmit simultaneously */
#define SOC_RMT_SUPPORT_REF_TICK (1) /*!< Support set REF_TICK as the RMT clock source */
#define SOC_RMT_CHANNEL_MEM_WORDS (64) /*!< Each channel owns 64 words memory (1 word = 4 Bytes) */
#define SOC_RMT_TX_CHANNELS_NUM (4) /*!< Number of channels that capable of Transmit */
#define SOC_RMT_RX_CHANNELS_NUM (4) /*!< Number of channels that capable of Receive */
#define SOC_RMT_CHANNELS_NUM (4) /*!< Total 4 channels (each channel can be configured to either TX or RX) */
#define SOC_RMT_SUPPORT_RX_PINGPONG (1) /*!< Support Ping-Pong mode on RX path */
#define SOC_RMT_SUPPORT_RX_DEMODULATION (1) /*!< Support signal demodulation on RX path (i.e. remove carrier) */
#define SOC_RMT_SUPPORT_TX_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */
#define SOC_RMT_SUPPORT_TX_GROUP (1) /*!< Support a group of TX channels to transmit simultaneously */
#define SOC_RMT_SUPPORT_REF_TICK (1) /*!< Support set REF_TICK as the RMT clock source */
#define SOC_RMT_SOURCE_CLK_INDEPENDENT (1) /*!< Can select different source clock for channels */
/*-------------------------- RTCIO CAPS --------------------------------------*/
#define SOC_RTCIO_PIN_COUNT 22

View File

@ -0,0 +1,39 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/rmt_periph.h"
#include "soc/gpio_sig_map.h"
const rmt_signal_conn_t rmt_periph_signals = {
.module = PERIPH_RMT_MODULE,
.irq = ETS_RMT_INTR_SOURCE,
.channels = {
[0] = {
.tx_sig = RMT_SIG_OUT0_IDX,
.rx_sig = RMT_SIG_IN0_IDX
},
[1] = {
.tx_sig = RMT_SIG_OUT1_IDX,
.rx_sig = RMT_SIG_IN1_IDX
},
[2] = {
.tx_sig = RMT_SIG_OUT2_IDX,
.rx_sig = RMT_SIG_IN2_IDX
},
[3] = {
.tx_sig = RMT_SIG_OUT3_IDX,
.rx_sig = RMT_SIG_IN3_IDX
}
}
};

View File

@ -8,6 +8,7 @@ set(srcs
"interrupts.c"
"ledc_periph.c"
"pcnt_periph.c"
"rmt_periph.c"
"rtc_io_periph.c"
"rtc_periph.c"
"sdio_slave_periph.c"

View File

@ -1,33 +0,0 @@
// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define SOC_RMT_CHANNEL_MEM_WORDS (48) /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
#define SOC_RMT_CHANNELS_NUM (8) /*!< Total 8 channels */
#define SOC_RMT_TX_RX_CHANNEL_INDEPENDENT (1) /*!< TX channels and RX channels are independent, channel0~3 transmit only and channel4~8 receive only */
#define SOC_RMT_SUPPORT_RX_PINGPONG (1) /*!< Support Ping-Pong mode on RX path */
#define SOC_RMT_SUPPORT_RX_DEMODULATION (1) /*!< Support signal demodulation on RX path (i.e. remove carrier) */
#define SOC_RMT_SUPPORT_TX_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */
#define SOC_RMT_SUPPORT_TX_GROUP (1) /*!< Support a group of TX channels to transmit simultaneously */
#define SOC_RMT_SUPPORT_RTC8M_CLOCK (1) /*!< Support set RTC 8M clock as the RMT clock source */
#define SOC_RMT_SUPPORT_XTAL_CLOCK (1) /*!< Support set XTAL clock as the RMT clock source */
#ifdef __cplusplus
}
#endif

View File

@ -53,15 +53,15 @@
#define SOC_PCNT_UNIT_CHANNEL_NUM (2)
/*-------------------------- RMT CAPS ----------------------------------------*/
#define SOC_RMT_CHANNEL_MEM_WORDS (48) /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
#define SOC_RMT_CHANNELS_NUM (8) /*!< Total 8 channels */
#define SOC_RMT_TX_RX_CHANNEL_INDEPENDENT (1) /*!< TX channels and RX channels are independent, channel0~3 transmit only and channel4~8 receive only */
#define SOC_RMT_SUPPORT_RX_PINGPONG (1) /*!< Support Ping-Pong mode on RX path */
#define SOC_RMT_SUPPORT_RX_DEMODULATION (1) /*!< Support signal demodulation on RX path (i.e. remove carrier) */
#define SOC_RMT_SUPPORT_TX_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */
#define SOC_RMT_SUPPORT_TX_GROUP (1) /*!< Support a group of TX channels to transmit simultaneously */
#define SOC_RMT_SUPPORT_RTC8M_CLOCK (1) /*!< Support set RTC 8M clock as the RMT clock source */
#define SOC_RMT_SUPPORT_XTAL_CLOCK (1) /*!< Support set XTAL clock as the RMT clock source */
#define SOC_RMT_CHANNEL_MEM_WORDS (48) /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */
#define SOC_RMT_TX_CHANNELS_NUM (4) /*!< Number of channels that capable of Transmit */
#define SOC_RMT_RX_CHANNELS_NUM (4) /*!< Number of channels that capable of Receive */
#define SOC_RMT_CHANNELS_NUM (8) /*!< Total 8 channels (each channel can be configured to either TX or RX) */
#define SOC_RMT_SUPPORT_RX_PINGPONG (1) /*!< Support Ping-Pong mode on RX path */
#define SOC_RMT_SUPPORT_RX_DEMODULATION (1) /*!< Support signal demodulation on RX path (i.e. remove carrier) */
#define SOC_RMT_SUPPORT_TX_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */
#define SOC_RMT_SUPPORT_TX_GROUP (1) /*!< Support a group of TX channels to transmit simultaneously */
#define SOC_RMT_SUPPORT_XTAL (1) /*!< Support set XTAL clock as the RMT clock source */
/*-------------------------- RTCIO CAPS --------------------------------------*/
#include "rtc_io_caps.h"

View File

@ -0,0 +1,55 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/rmt_periph.h"
#include "soc/gpio_sig_map.h"
const rmt_signal_conn_t rmt_periph_signals = {
.module = PERIPH_RMT_MODULE,
.irq = ETS_RMT_INTR_SOURCE,
.channels = {
[0] = {
.tx_sig = RMT_SIG_OUT0_IDX,
.rx_sig = -1
},
[1] = {
.tx_sig = RMT_SIG_OUT1_IDX,
.rx_sig = -1
},
[2] = {
.tx_sig = RMT_SIG_OUT2_IDX,
.rx_sig = -1
},
[3] = {
.tx_sig = RMT_SIG_OUT3_IDX,
.rx_sig = -1
},
[4] = {
.tx_sig = -1,
.rx_sig = RMT_SIG_IN0_IDX
},
[5] = {
.tx_sig = -1,
.rx_sig = RMT_SIG_IN1_IDX
},
[6] = {
.tx_sig = -1,
.rx_sig = RMT_SIG_IN2_IDX
},
[7] = {
.tx_sig = -1,
.rx_sig = RMT_SIG_IN3_IDX
}
}
};

View File

@ -1,4 +1,4 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -13,5 +13,27 @@
// limitations under the License.
#pragma once
#include "soc/rmt_reg.h"
#include "soc/rmt_struct.h"
#include "soc/soc_caps.h"
#include "soc/periph_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
struct {
struct {
const int tx_sig;
const int rx_sig;
};
} channels[SOC_RMT_CHANNELS_NUM];
const int irq;
const periph_module_t module;
} rmt_signal_conn_t;
extern const rmt_signal_conn_t rmt_periph_signals;
#ifdef __cplusplus
}
#endif

View File

@ -34,6 +34,8 @@
#include "driver/periph_ctrl.h"
#include "soc/gpio_sig_map.h"
#include "soc/gpio_periph.h"
#include "soc/soc_caps.h"
#include "hal/rmt_types.h"
#include "hal/rmt_hal.h"
#include "hal/rmt_ll.h"
#include "hal/pcnt_hal.h"
@ -74,26 +76,26 @@ void ref_clock_init(void)
};
rmt_ll_enable_drive_clock(s_rmt_hal.regs, true);
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
rmt_ll_set_counter_clock_src(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 0); // select REF_TICK (1MHz)
#else
rmt_ll_set_sclk(s_rmt_hal.regs, 3, 39, 0, 0); // XTAL(40MHz), rmt_sclk => 1MHz (40/(1+39))
#if SOC_RMT_SUPPORT_XTAL
rmt_ll_set_counter_clock_src(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, RMT_BASECLK_XTAL, 39, 0, 0); // XTAL(40MHz), rmt_sclk => 1MHz (40/(1+39))
#elif SOC_RMT_SUPPORT_REF_TICK
rmt_ll_set_counter_clock_src(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, RMT_BASECLK_REF, 0, 0, 0); // select REF_TICK (1MHz)
#endif
rmt_hal_set_counter_clock(&s_rmt_hal, REF_CLOCK_RMT_CHANNEL, 1000000, 1000000); // counter clock: 1MHz
rmt_ll_enable_tx_idle(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, true); // enable idle output
rmt_ll_set_tx_idle_level(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1); // idle level: 1
rmt_ll_enable_carrier(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, true);
rmt_hal_tx_set_counter_clock(&s_rmt_hal, REF_CLOCK_RMT_CHANNEL, 1000000, 1000000); // counter clock: 1MHz
rmt_ll_tx_enable_idle(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, true); // enable idle output
rmt_ll_tx_set_idle_level(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1); // idle level: 1
rmt_ll_tx_enable_carrier_modulation(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, true);
#if !CONFIG_IDF_TARGET_ESP32
rmt_ll_tx_set_carrier_always_on(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, true);
#endif
rmt_hal_set_carrier_clock(&s_rmt_hal, REF_CLOCK_RMT_CHANNEL, 1000000, 500000, 0.5); // set carrier to 500KHz
rmt_ll_set_carrier_on_level(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1);
rmt_ll_tx_set_carrier_level(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1);
rmt_ll_enable_mem_access(s_rmt_hal.regs, true);
rmt_ll_reset_tx_pointer(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL);
rmt_ll_set_mem_blocks(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1);
rmt_ll_tx_reset_pointer(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL);
rmt_ll_tx_set_mem_blocks(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, 1);
rmt_ll_write_memory(s_rmt_hal.mem, REF_CLOCK_RMT_CHANNEL, &data, 1, 0);
rmt_ll_enable_tx_loop(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, false);
rmt_ll_start_tx(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL);
rmt_ll_tx_enable_loop(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, false);
rmt_ll_tx_start(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL);
// Route signal to PCNT
esp_rom_gpio_connect_in_signal(REF_CLOCK_GPIO, PCNT_SIG_CH0_IN0_IDX, false);
@ -148,7 +150,7 @@ void ref_clock_deinit()
s_intr_handle = NULL;
// Disable RMT
rmt_ll_enable_carrier(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, false);
rmt_ll_tx_enable_carrier_modulation(s_rmt_hal.regs, REF_CLOCK_RMT_CHANNEL, false);
periph_module_disable(PERIPH_RMT_MODULE);
// Disable PCNT