diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 82d3eaa45..6ba968c4a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1013,6 +1013,31 @@ UT_006_04: - UT_T1_GPIO - psram +UT_010_01: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_RMT + +UT_010_02: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_RMT + +UT_010_03: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_RMT + +UT_010_04: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_RMT + - psram + IT_001_01: <<: *test_template tags: diff --git a/components/driver/test/test_rmt.c b/components/driver/test/test_rmt.c new file mode 100644 index 000000000..de9937e3a --- /dev/null +++ b/components/driver/test/test_rmt.c @@ -0,0 +1,682 @@ +/** + * please connect GPIO18 to GPIO19 + */ +#include "stdio.h" +#include +#include "driver/rmt.h" +#include "unity.h" +#include "test_utils.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "driver/periph_ctrl.h" +#include "soc/rmt_reg.h" + +static const char* TAG = "RMT"; + + +#define RMT_RX_ACTIVE_LEVEL 1 /*!< Data bit is active high for self test mode */ +#define RMT_TX_CARRIER_EN 0 /*!< Disable carrier for self test mode */ + +#define RMT_TX_CHANNEL 1 /*!< RMT channel for transmitter */ +#define RMT_TX_GPIO_NUM 18 /*!< GPIO number for transmitter signal */ +#define RMT_RX_CHANNEL 0 /*!< RMT channel for receiver */ +#define RMT_RX_GPIO_NUM 19 /*!< GPIO number for receiver */ +#define RMT_CLK_DIV 100 /*!< RMT counter clock divider */ +#define RMT_TICK_10_US (80000000/RMT_CLK_DIV/100000) /*!< RMT counter value for 10 us.(Source clock is APB clock) */ + +#define HEADER_HIGH_US 9000 /*!< NEC protocol header: positive 9ms */ +#define HEADER_LOW_US 4500 /*!< NEC protocol header: negative 4.5ms*/ +#define BIT_ONE_HIGH_US 560 /*!< NEC protocol data bit 1: positive 0.56ms */ +#define BIT_ONE_LOW_US (2250-BIT_ONE_HIGH_US) /*!< NEC protocol data bit 1: negative 1.69ms */ +#define BIT_ZERO_HIGH_US 560 /*!< NEC protocol data bit 0: positive 0.56ms */ +#define BIT_ZERO_LOW_US (1120-BIT_ZERO_HIGH_US) /*!< NEC protocol data bit 0: negative 0.56ms */ +#define BIT_END 560 /*!< NEC protocol end: positive 0.56ms */ +#define BIT_MARGIN 20 /*!< NEC parse margin time */ + +#define ITEM_DURATION(d) ((d & 0x7fff)*10/RMT_TICK_10_US) /*!< Parse duration time from memory register value */ +#define DATA_ITEM_NUM 34 /*!< NEC code item number: header + 32bit data + end */ +#define RMT_TX_DATA_NUM 100 /*!< NEC tx test data number */ +#define RMT_ITEM32_TIMEOUT_US 9500 /*!< RMT receiver timeout value(us) */ + +/** + * @brief Build register value of waveform for NEC one data bit + */ +static inline void fill_item_level(rmt_item32_t* item, int high_us, int low_us) +{ + item->level0 = 1; + item->duration0 = (high_us) / 10 * RMT_TICK_10_US; + item->level1 = 0; + item->duration1 = (low_us) / 10 * RMT_TICK_10_US; +} + +/** + * @brief Generate NEC header value: active 9ms + negative 4.5ms + */ +static void fill_item_header(rmt_item32_t* item) +{ + fill_item_level(item, HEADER_HIGH_US, HEADER_LOW_US); +} + +/* + * @brief Generate NEC data bit 1: positive 0.56ms + negative 1.69ms + */ +static void fill_item_bit_one(rmt_item32_t* item) +{ + fill_item_level(item, BIT_ONE_HIGH_US, BIT_ONE_LOW_US); +} + +/** + * @brief Generate NEC data bit 0: positive 0.56ms + negative 0.56ms + */ +static void fill_item_bit_zero(rmt_item32_t* item) +{ + fill_item_level(item, BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US); +} + +/** + * @brief Generate NEC end signal: positive 0.56ms + */ +static void fill_item_end(rmt_item32_t* item) +{ + fill_item_level(item, BIT_END, 0x7fff); +} + +/** + * @brief Check whether duration is around target_us + */ +inline bool check_in_range(int duration_ticks, int target_us, int margin_us) +{ + if(( ITEM_DURATION(duration_ticks) < (target_us + margin_us)) + && ( ITEM_DURATION(duration_ticks) > (target_us - margin_us))) { + return true; + } else { + return false; + } +} + +/** + * @brief Check whether this value represents an NEC header + */ +static bool header_if(rmt_item32_t* item) +{ + if((item->level0 == RMT_RX_ACTIVE_LEVEL && item->level1 != RMT_RX_ACTIVE_LEVEL) + && check_in_range(item->duration0, HEADER_HIGH_US, BIT_MARGIN) + && check_in_range(item->duration1, HEADER_LOW_US, BIT_MARGIN)) { + return true; + } + return false; +} + +/** + * @brief Check whether this value represents an NEC data bit 1 + */ +static bool bit_one_if(rmt_item32_t* item) +{ + if((item->level0 == RMT_RX_ACTIVE_LEVEL && item->level1 != RMT_RX_ACTIVE_LEVEL) + && check_in_range(item->duration0, BIT_ONE_HIGH_US, BIT_MARGIN) + && check_in_range(item->duration1, BIT_ONE_LOW_US, BIT_MARGIN)) { + return true; + } + return false; +} + +/** + * @brief Check whether this value represents an NEC data bit 0 + */ +static bool bit_zero_if(rmt_item32_t* item) +{ + if((item->level0 == RMT_RX_ACTIVE_LEVEL && item->level1 != RMT_RX_ACTIVE_LEVEL) + && check_in_range(item->duration0, BIT_ZERO_HIGH_US, BIT_MARGIN) + && check_in_range(item->duration1, BIT_ZERO_LOW_US, BIT_MARGIN)) { + return true; + } + return false; +} + + +/** + * @brief Parse NEC 32 bit waveform to address and command. + */ +static int parse_items(rmt_item32_t* item, int item_num, uint16_t* addr, uint16_t* data) +{ + int w_len = item_num; + if(w_len < DATA_ITEM_NUM) { + return -1; + } + int i = 0, j = 0; + if(!header_if(item++)) { + return -1; + } + uint16_t addr_t = 0; + for(j = 0; j < 16; j++) { + if(bit_one_if(item)) { + addr_t |= (1 << j); + } else if(bit_zero_if(item)) { + addr_t |= (0 << j); + } else { + return -1; + } + item++; + i++; + } + uint16_t data_t = 0; + for(j = 0; j < 16; j++) { + if(bit_one_if(item)) { + data_t |= (1 << j); + } else if(bit_zero_if(item)) { + data_t |= (0 << j); + } else { + return -1; + } + item++; + i++; + } + *addr = addr_t; + *data = data_t; + return i; +} + +/** + * @brief Build NEC 32bit waveform. + */ +static int build_items(int channel, rmt_item32_t* item, int item_num, uint16_t addr, uint16_t cmd_data) +{ + int i = 0, j = 0; + if(item_num < DATA_ITEM_NUM) { + return -1; + } + fill_item_header(item++); + i++; + for(j = 0; j < 16; j++) { + if(addr & 0x1) { + fill_item_bit_one(item); + } else { + fill_item_bit_zero(item); + } + item++; + i++; + addr >>= 1; + } + for(j = 0; j < 16; j++) { + if(cmd_data & 0x1) { + fill_item_bit_one(item); + } else { + fill_item_bit_zero(item); + } + item++; + i++; + cmd_data >>= 1; + } + fill_item_end(item); + i++; + return i; +} + +static void set_tx_data(int tx_channel, uint16_t cmd, uint16_t addr, int item_num, rmt_item32_t* item, int offset) +{ + while(1) { + int i = build_items(tx_channel, item + offset, item_num - offset, ((~addr) << 8) | addr, cmd); + printf("cmd :%d\n", cmd); + if(i < 0) { + break; + } + cmd++; + addr++; + offset += i; + } +} + +static int get_rx_data(RingbufHandle_t rb) +{ + uint16_t tmp = 0; + while(rb) { + size_t rx_size = 0; + rmt_item32_t* rx_item = (rmt_item32_t*) xRingbufferReceive(rb, &rx_size, 1000); + if(rx_item) { + uint16_t rmt_addr; + uint16_t rmt_cmd; + int rx_offset = 0; + while(1) { + int res = parse_items(rx_item + rx_offset, rx_size / 4 - rx_offset, &rmt_addr, &rmt_cmd); + if(res > 0) { + rx_offset += res + 1; + ESP_LOGI(TAG, "RMT RCV --- addr: 0x%04x cmd: 0x%04x", rmt_addr, rmt_cmd); + TEST_ASSERT(rmt_cmd == tmp); + tmp++; + } else { + break; + } + } + vRingbufferReturnItem(rb, (void*) rx_item); + } else { + break; + } + } + return tmp; +} + +/** + * @brief RMT transmitter initialization + */ +static void tx_init() +{ + // the sender once it send something, its frq is 38kHz, and the duty cycle is 50% + rmt_tx_config_t tx_cfg = { + .loop_en = false, + .carrier_duty_percent = 50, + .carrier_freq_hz = 38000, + .carrier_level = 1, + .carrier_en = RMT_TX_CARRIER_EN, + .idle_level = 0, + .idle_output_en = true, + }; + rmt_config_t rmt_tx = { + .channel = RMT_TX_CHANNEL, + .gpio_num = RMT_TX_GPIO_NUM, + .mem_block_num = 1, + .clk_div = RMT_CLK_DIV, + .tx_config = tx_cfg, + .rmt_mode = 0, + }; + rmt_config(&rmt_tx); + rmt_driver_install(rmt_tx.channel, 0, 0); +} + +/** + * @brief RMT receiver initialization + */ +static void rx_init() +{ + rmt_rx_config_t rx_cfg = { + .filter_en = true, + .filter_ticks_thresh = 100, + .idle_threshold = RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US), + }; + rmt_config_t rmt_rx = { + .channel = RMT_RX_CHANNEL, + .gpio_num = RMT_RX_GPIO_NUM, + .clk_div = RMT_CLK_DIV, + .mem_block_num = 1, + .rmt_mode = RMT_MODE_RX, + .rx_config = rx_cfg, + }; + rmt_config(&rmt_rx); + rmt_driver_install(rmt_rx.channel, (sizeof(rmt_item32_t) * DATA_ITEM_NUM * (RMT_TX_DATA_NUM+6)), 0); +} + +TEST_CASE("RMT init config", "[rmt][test_env=UT_T1_RMT]") +{ + // tx settings + rmt_tx_config_t tx_cfg = { + .loop_en = false, + .carrier_duty_percent = 50, + .carrier_freq_hz = 38000, + .carrier_level = 1, + .carrier_en = RMT_TX_CARRIER_EN, + .idle_level = 0, + .idle_output_en = true, + }; + rmt_config_t rmt_tx = { + .channel = RMT_TX_CHANNEL, + .gpio_num = RMT_TX_GPIO_NUM, + .mem_block_num = 1, + .clk_div = RMT_CLK_DIV, + .tx_config = tx_cfg, + }; + TEST_ESP_OK(rmt_config(&rmt_tx)); + TEST_ESP_OK(rmt_driver_install(rmt_tx.channel, 0, 0)); + TEST_ESP_OK(rmt_driver_uninstall(rmt_tx.channel)); + + //rx settings + rmt_rx_config_t rx_cfg = { + .filter_en = true, + .filter_ticks_thresh = 100, + .idle_threshold = RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US), + }; + rmt_config_t rmt_rx = { + .channel = RMT_RX_CHANNEL, + .gpio_num = RMT_RX_GPIO_NUM, + .clk_div = RMT_CLK_DIV, + .mem_block_num = 1, + .rmt_mode = RMT_MODE_RX, + .rx_config = rx_cfg, + }; + TEST_ESP_OK(rmt_config(&rmt_rx)); + TEST_ESP_OK(rmt_driver_install(rmt_rx.channel, 1000, 0)); + TEST_ESP_OK(rmt_driver_uninstall(rmt_rx.channel)); + + //error param setting + rmt_config_t temp_rmt_rx1 = { + .channel = 2, + .gpio_num = 15, + .clk_div = RMT_CLK_DIV, + .mem_block_num = 1, + .rmt_mode = RMT_MODE_RX, + .rx_config = rx_cfg, + }; + rmt_config_t temp_rmt_rx2 = temp_rmt_rx1; + + temp_rmt_rx2.clk_div = 0; // only invalid parameter to test + TEST_ASSERT(rmt_config(&temp_rmt_rx2) == ESP_ERR_INVALID_ARG); + + temp_rmt_rx2 = temp_rmt_rx1; + temp_rmt_rx2.channel = RMT_CHANNEL_MAX; + TEST_ASSERT(rmt_config(&temp_rmt_rx2) == ESP_ERR_INVALID_ARG); + + temp_rmt_rx2 = temp_rmt_rx1; + temp_rmt_rx2.channel = 2; + temp_rmt_rx2.mem_block_num = 8; + TEST_ASSERT(rmt_config(&temp_rmt_rx2) == ESP_ERR_INVALID_ARG); +} + +TEST_CASE("RMT init set function", "[rmt][test_env=UT_T1_RMT]") +{ + rmt_channel_t channel = 7; + TEST_ESP_OK(rmt_set_pin(channel, RMT_MODE_RX, RMT_RX_GPIO_NUM)); + TEST_ESP_OK(rmt_set_clk_div(channel, RMT_CLK_DIV*2)); + TEST_ESP_OK(rmt_set_mem_block_num(channel, 1)); + TEST_ESP_OK(rmt_set_rx_filter(channel, 1, 100)); + TEST_ESP_OK(rmt_set_rx_idle_thresh(channel, RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US)*2)); + TEST_ESP_OK(rmt_driver_install(channel, 0, 0)); + TEST_ESP_OK(rmt_driver_uninstall(channel)); +} + +// need to make sure its phenomenon by logic analyzer, can't run in CI +TEST_CASE("RMT clock devider, clock source set(logic analyzer)", "[rmt][ignore]") +{ + uint8_t div_cnt; + rmt_source_clk_t src_clk; + rmt_config_t rmt_tx; + rmt_tx.channel = RMT_TX_CHANNEL; + rmt_tx.mem_block_num = 1; + rmt_tx.gpio_num = RMT_TX_GPIO_NUM; + rmt_tx.clk_div = RMT_CLK_DIV; + rmt_tx.tx_config.loop_en = true; + rmt_tx.tx_config.carrier_duty_percent = 50; + rmt_tx.tx_config.carrier_freq_hz = 38000; + rmt_tx.tx_config.carrier_level = 1; + rmt_tx.tx_config.carrier_en = RMT_TX_CARRIER_EN; + rmt_tx.tx_config.idle_level = 0; + rmt_tx.tx_config.idle_output_en = true; + rmt_tx.rmt_mode = RMT_MODE_TX; + + TEST_ESP_OK(rmt_config(&rmt_tx)); + TEST_ESP_OK(rmt_get_clk_div(RMT_TX_CHANNEL, &div_cnt)); + TEST_ESP_OK(rmt_driver_install(rmt_tx.channel, 0, 0)); + TEST_ASSERT_EQUAL_UINT8(div_cnt, RMT_CLK_DIV); + vTaskDelay(1000 / portTICK_PERIOD_MS); + + // reset it and check it + TEST_ESP_OK(rmt_set_clk_div(RMT_TX_CHANNEL, 160)); + TEST_ESP_OK(rmt_get_clk_div(RMT_TX_CHANNEL, &div_cnt)); + vTaskDelay(1000 / portTICK_PERIOD_MS); + + TEST_ESP_OK(rmt_set_source_clk(RMT_TX_CHANNEL, RMT_BASECLK_APB)); + TEST_ESP_OK(rmt_get_source_clk(RMT_TX_CHANNEL, &src_clk)); + TEST_ASSERT_EQUAL_UINT8(div_cnt, 160); + TEST_ASSERT_EQUAL_INT(src_clk, RMT_BASECLK_APB); + TEST_ESP_OK(rmt_driver_uninstall(rmt_tx.channel)); +} + +TEST_CASE("RMT rx set and get properties", "[rmt][test_env=UT_T1_RMT]") +{ + rmt_channel_t channel = RMT_RX_CHANNEL; + uint8_t memNum; + uint8_t div_cnt; + uint16_t idleThreshold; + rmt_mem_owner_t owner; + + rx_init(); + + TEST_ESP_OK(rmt_get_clk_div(channel, &div_cnt)); + TEST_ESP_OK(rmt_get_mem_block_num(channel, &memNum)); + TEST_ESP_OK(rmt_get_rx_idle_thresh(channel, &idleThreshold)); + TEST_ESP_OK(rmt_get_memory_owner(channel, &owner)); + + TEST_ASSERT_EQUAL_UINT8(div_cnt, RMT_CLK_DIV); + TEST_ASSERT_EQUAL_UINT8(memNum, 1); + TEST_ASSERT_EQUAL_UINT16(idleThreshold, RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US)); + TEST_ASSERT_EQUAL_INT(owner, RMT_MEM_OWNER_RX); + + //eRR + TEST_ESP_OK(rmt_set_pin(channel, RMT_MODE_RX, 22)); + TEST_ESP_OK(rmt_set_clk_div(channel, RMT_CLK_DIV*2)); + TEST_ESP_OK(rmt_set_mem_block_num(channel, 2)); + TEST_ESP_OK(rmt_set_rx_filter(channel, 1, 100)); + TEST_ESP_OK(rmt_set_rx_idle_thresh(channel, RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US)*2)); + TEST_ESP_OK(rmt_set_memory_owner(channel, RMT_MEM_OWNER_RX)); + + TEST_ESP_OK(rmt_get_clk_div(channel, &div_cnt)); + TEST_ESP_OK(rmt_get_mem_block_num(channel, &memNum)); + TEST_ESP_OK(rmt_get_rx_idle_thresh(channel, &idleThreshold)); + TEST_ESP_OK(rmt_get_memory_owner(channel, &owner)); + + TEST_ASSERT_EQUAL_UINT8(div_cnt, RMT_CLK_DIV*2); + TEST_ASSERT_EQUAL_UINT8(memNum, 2); + TEST_ASSERT_EQUAL_UINT16(idleThreshold, RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US)*2); + TEST_ASSERT_EQUAL_INT(owner, RMT_MEM_OWNER_RX); + + TEST_ESP_OK(rmt_driver_uninstall(channel)); +} + +TEST_CASE("RMT tx set and get properties", "[rmt][test_env=UT_T1_RMT]") +{ + rmt_channel_t channel = RMT_TX_CHANNEL; + uint8_t memNum; + uint8_t div_cnt; + bool loop_en; + rmt_mem_owner_t owner; + + tx_init(); + TEST_ESP_OK(rmt_get_clk_div(channel, &div_cnt)); + TEST_ESP_OK(rmt_get_mem_block_num(channel, &memNum)); + TEST_ESP_OK(rmt_get_tx_loop_mode(channel, &loop_en)); + TEST_ESP_OK(rmt_get_memory_owner(channel, &owner)); + + TEST_ASSERT_EQUAL_INT8(loop_en, 0); + TEST_ASSERT_EQUAL_UINT8(div_cnt, RMT_CLK_DIV); + TEST_ASSERT_EQUAL_UINT8(memNum, 1); + TEST_ASSERT_EQUAL_INT(owner, RMT_MEM_OWNER_TX); + + //reset by "set" + TEST_ESP_OK(rmt_set_pin(channel, RMT_MODE_TX, RMT_TX_GPIO_NUM)); + TEST_ESP_OK(rmt_set_clk_div(channel, RMT_CLK_DIV*2)); + TEST_ESP_OK(rmt_set_mem_block_num(channel, 2)); + TEST_ESP_OK(rmt_set_tx_loop_mode(channel, 1)); + TEST_ESP_OK(rmt_set_tx_carrier(channel, 0, 1, 0, 1)); + TEST_ESP_OK(rmt_set_idle_level(channel, 1, 0)); + TEST_ESP_OK(rmt_set_memory_owner(channel, RMT_MEM_OWNER_TX)); + + TEST_ESP_OK(rmt_get_clk_div(channel, &div_cnt)); + TEST_ESP_OK(rmt_get_mem_block_num(channel, &memNum)); + TEST_ESP_OK(rmt_get_tx_loop_mode(channel, &loop_en)); + TEST_ESP_OK(rmt_get_memory_owner(channel, &owner)); + + TEST_ASSERT_EQUAL_INT8(loop_en, 1); + TEST_ASSERT_EQUAL_UINT8(div_cnt, RMT_CLK_DIV*2); + TEST_ASSERT_EQUAL_UINT8(memNum, 2); + TEST_ASSERT_EQUAL_INT(owner, RMT_MEM_OWNER_TX); + + rmt_item32_t items[1]; + items[0].duration0 = 300 / 10 * RMT_TICK_10_US; //300us + items[0].level0 = 1; + items[0].duration1 = 0; + items[0].level1 = 0; + for(int i=0; i<100; i++) { + TEST_ESP_OK(rmt_write_items(RMT_TX_CHANNEL, items, + 1, /* Number of items */ + 1 /* wait till done */)); + vTaskDelay(10/portTICK_PERIOD_MS); //every 10ms to write the item + } + TEST_ESP_OK(rmt_driver_uninstall(channel)); +} + +TEST_CASE("RMT memory test", "[rmt][test_env=UT_T1_RMT]") +{ + rmt_config_t rmt_rx; + rmt_rx.channel = RMT_RX_CHANNEL; + rmt_rx.gpio_num = RMT_RX_GPIO_NUM; + rmt_rx.clk_div = RMT_CLK_DIV; + rmt_rx.mem_block_num = 1; + rmt_rx.rmt_mode = RMT_MODE_RX; + rmt_rx.rx_config.filter_en = true; + rmt_rx.rx_config.filter_ticks_thresh = 100; + rmt_rx.rx_config.idle_threshold = RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US); + TEST_ESP_OK(rmt_config(&rmt_rx)); + + for(int i = 0; i<100; i++) { + TEST_ESP_OK(rmt_driver_install(rmt_rx.channel, 1000, 0)); + TEST_ESP_OK(rmt_driver_uninstall(rmt_rx.channel)); + } +} + +TEST_CASE("RMT send waveform(logic analyzer)", "[rmt][test_env=UT_T1_RMT][ignore]") +{ + tx_init(); + rmt_item32_t items[1]; + items[0].duration0 = 300 / 10 * RMT_TICK_10_US; //300us + items[0].level0 = 1; + for(int i=0; i<500; i++) { + TEST_ESP_OK(rmt_write_items(RMT_TX_CHANNEL, items, + 1, /* Number of items */ + 1 /* wait till done */)); + vTaskDelay(10/portTICK_PERIOD_MS); //every 10ms to write the item + } + TEST_ESP_OK(rmt_driver_uninstall(RMT_TX_CHANNEL)); +} + +TEST_CASE("RMT basic TX and RX", "[rmt][test_env=UT_T1_RMT]") +{ + tx_init(); + int tx_channel = RMT_TX_CHANNEL; + uint16_t cmd = 0x0; + uint16_t addr = 0x11; + int tx_num = RMT_TX_DATA_NUM; + ESP_LOGI(TAG, "RMT TX DATA"); + size_t size = (sizeof(rmt_item32_t) * DATA_ITEM_NUM * tx_num); + rmt_item32_t* item = (rmt_item32_t*) malloc(size); + int item_num = DATA_ITEM_NUM * tx_num; + memset((void*) item, 0, size); + int offset = 0; + + int rx_channel = RMT_RX_CHANNEL; + rx_init(); + RingbufHandle_t rb = NULL; + rmt_get_ringbuf_handle(rx_channel, &rb); + rmt_rx_start(rx_channel, 1); + // send data + set_tx_data(tx_channel, cmd, addr, item_num, item, offset); + rmt_write_items(tx_channel, item, item_num, 1); + free(item); + // receive data + uint16_t tmp = get_rx_data(rb); + TEST_ASSERT(tmp == 100); + TEST_ESP_OK(rmt_driver_uninstall(RMT_TX_CHANNEL)); + TEST_ESP_OK(rmt_driver_uninstall(RMT_RX_CHANNEL)); +} + +TEST_CASE("RMT TX write item not wait", "[rmt][test_env=UT_T1_RMT]") +{ + tx_init(); + int tx_channel = RMT_TX_CHANNEL; + uint16_t cmd = 0x0; + uint16_t addr = 0x11; + int tx_num = RMT_TX_DATA_NUM; + ESP_LOGI(TAG, "RMT TX DATA"); + size_t size = (sizeof(rmt_item32_t) * DATA_ITEM_NUM * tx_num); + rmt_item32_t* item = (rmt_item32_t*) malloc(size); + int item_num = DATA_ITEM_NUM * tx_num; + memset((void*) item, 0, size); + int offset = 0; + + int rx_channel = RMT_RX_CHANNEL; + rx_init(); + RingbufHandle_t rb = NULL; + rmt_get_ringbuf_handle(rx_channel, &rb); + rmt_rx_start(rx_channel, 1); + + // send data + set_tx_data(tx_channel, cmd, addr, item_num, item, offset); + rmt_write_items(tx_channel, item, item_num, 0); + free(item); + + // receive data + uint16_t tmp = get_rx_data(rb); + TEST_ASSERT(tmp < 100); + TEST_ESP_OK(rmt_driver_uninstall(RMT_TX_CHANNEL)); + TEST_ESP_OK(rmt_driver_uninstall(RMT_RX_CHANNEL)); +} + +TEST_CASE("RMT TX write item wait some ticks", "[rmt][test_env=UT_T1_RMT]") +{ + tx_init(); + int tx_channel = RMT_TX_CHANNEL; + uint16_t cmd = 0x0; + uint16_t addr = 0x11; + int tx_num = RMT_TX_DATA_NUM; + ESP_LOGI(TAG, "RMT TX DATA"); + size_t size = (sizeof(rmt_item32_t) * DATA_ITEM_NUM * tx_num); + rmt_item32_t* item = (rmt_item32_t*) malloc(size); + int item_num = DATA_ITEM_NUM * tx_num; + memset((void*) item, 0, size); + int offset = 0; + + int rx_channel = RMT_RX_CHANNEL; + rx_init(); + RingbufHandle_t rb = NULL; + rmt_get_ringbuf_handle(rx_channel, &rb); + rmt_rx_start(rx_channel, 1); + + // send data + set_tx_data(tx_channel, cmd, addr, item_num, item, offset); + rmt_write_items(tx_channel, item, item_num, 0); + rmt_wait_tx_done(tx_channel, portMAX_DELAY); + free(item); + + // receive data + uint16_t tmp = get_rx_data(rb); + TEST_ASSERT(tmp == 100); + TEST_ESP_OK(rmt_driver_uninstall(RMT_TX_CHANNEL)); + TEST_ESP_OK(rmt_driver_uninstall(RMT_RX_CHANNEL)); +} + +TEST_CASE("RMT TX stop test", "[rmt][test_env=UT_T1_RMT]") +{ + int rx_channel = RMT_RX_CHANNEL; + rx_init(); + RingbufHandle_t rb = NULL; + rmt_get_ringbuf_handle(rx_channel, &rb); + rmt_rx_start(rx_channel, 1); + + vTaskDelay(10); + tx_init(); + int tx_channel = RMT_TX_CHANNEL; + int tx_num = RMT_TX_DATA_NUM; + + ESP_LOGI(TAG, "RMT TX DATA"); + size_t size = (sizeof(rmt_item32_t) * DATA_ITEM_NUM * tx_num); + rmt_item32_t* item = (rmt_item32_t*) malloc(size); + int item_num = DATA_ITEM_NUM * tx_num; + memset((void*) item, 0, size); + int offset = 0; + uint16_t cmd = 0x0; + uint16_t addr = 0x11; + + // send data + set_tx_data(tx_channel, cmd, addr, item_num, item, offset); + rmt_write_items(tx_channel, item, item_num, 0); + vTaskDelay(1000 / portTICK_PERIOD_MS); + rmt_tx_stop(tx_channel); + free(item); + + // receive data + uint16_t tmp = get_rx_data(rb); + TEST_ASSERT(tmp < 100); + + TEST_ESP_OK(rmt_driver_uninstall(RMT_TX_CHANNEL)); + TEST_ESP_OK(rmt_driver_uninstall(RMT_RX_CHANNEL)); +}