test_rmt.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. // RMT driver unit test is based on extended NEC protocol
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "sdkconfig.h"
  5. #include "freertos/FreeRTOS.h"
  6. #include "freertos/task.h"
  7. #include "esp_log.h"
  8. #include "driver/rmt.h"
  9. #include "ir_tools.h"
  10. #include "unity.h"
  11. #include "test_utils.h"
  12. #include "esp_rom_gpio.h"
  13. #define RMT_RX_CHANNEL_ENCODING_START (SOC_RMT_CHANNELS_NUM-SOC_RMT_TX_CHANNELS_NUM)
  14. #define RMT_TX_CHANNEL_ENCODING_END (SOC_RMT_TX_CHANNELS_NUM-1)
  15. // CI ONLY: Don't connect any other signals to this GPIO
  16. #define RMT_DATA_IO (4) // bind signal RMT_SIG_OUT0_IDX and RMT_SIG_IN0_IDX on the same GPIO
  17. #define RMT_TESTBENCH_FLAGS_ALWAYS_ON (1<<0)
  18. #define RMT_TESTBENCH_FLAGS_CARRIER_ON (1<<1)
  19. #define RMT_TESTBENCH_FLAGS_LOOP_ON (1<<2)
  20. static const char *TAG = "RMT.test";
  21. static ir_builder_t *s_ir_builder = NULL;
  22. static ir_parser_t *s_ir_parser = NULL;
  23. static void rmt_setup_testbench(int tx_channel, int rx_channel, uint32_t flags)
  24. {
  25. // RMT channel configuration
  26. if (tx_channel >= 0) {
  27. rmt_config_t tx_config = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, tx_channel);
  28. if (flags & RMT_TESTBENCH_FLAGS_ALWAYS_ON) {
  29. tx_config.flags |= RMT_CHANNEL_FLAGS_AWARE_DFS;
  30. }
  31. if (flags & RMT_TESTBENCH_FLAGS_CARRIER_ON) {
  32. tx_config.tx_config.carrier_en = true;
  33. }
  34. #if SOC_RMT_SUPPORT_TX_LOOP_COUNT
  35. if (flags & RMT_TESTBENCH_FLAGS_LOOP_ON) {
  36. tx_config.tx_config.loop_en = true;
  37. tx_config.tx_config.loop_count = 10;
  38. }
  39. #endif
  40. TEST_ESP_OK(rmt_config(&tx_config));
  41. }
  42. if (rx_channel >= 0) {
  43. rmt_config_t rx_config = RMT_DEFAULT_CONFIG_RX(RMT_DATA_IO, rx_channel);
  44. if (flags & RMT_TESTBENCH_FLAGS_ALWAYS_ON) {
  45. rx_config.flags |= RMT_CHANNEL_FLAGS_AWARE_DFS;
  46. }
  47. #if SOC_RMT_SUPPORT_RX_DEMODULATION
  48. if (flags & RMT_TESTBENCH_FLAGS_CARRIER_ON) {
  49. rx_config.rx_config.rm_carrier = true;
  50. rx_config.rx_config.carrier_freq_hz = 38000;
  51. rx_config.rx_config.carrier_duty_percent = 33;
  52. rx_config.rx_config.carrier_level = RMT_CARRIER_LEVEL_HIGH;
  53. }
  54. #endif
  55. TEST_ESP_OK(rmt_config(&rx_config));
  56. }
  57. // Routing internal signals by IO Matrix (bind rmt tx and rx signal on the same GPIO)
  58. PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[RMT_DATA_IO], PIN_FUNC_GPIO);
  59. TEST_ESP_OK(gpio_set_direction(RMT_DATA_IO, GPIO_MODE_INPUT_OUTPUT));
  60. esp_rom_gpio_connect_out_signal(RMT_DATA_IO, RMT_SIG_OUT0_IDX + tx_channel, 0, 0);
  61. esp_rom_gpio_connect_in_signal(RMT_DATA_IO, RMT_SIG_IN0_IDX + rx_channel, 0);
  62. // install driver
  63. if (tx_channel >= 0) {
  64. TEST_ESP_OK(rmt_driver_install(tx_channel, 0, 0));
  65. ir_builder_config_t ir_builder_config = IR_BUILDER_DEFAULT_CONFIG((ir_dev_t)tx_channel);
  66. ir_builder_config.flags = IR_TOOLS_FLAGS_PROTO_EXT;
  67. s_ir_builder = ir_builder_rmt_new_nec(&ir_builder_config);
  68. TEST_ASSERT_NOT_NULL(s_ir_builder);
  69. }
  70. if (rx_channel >= 0) {
  71. TEST_ESP_OK(rmt_driver_install(rx_channel, 3000, 0));
  72. ir_parser_config_t ir_parser_config = IR_PARSER_DEFAULT_CONFIG((ir_dev_t)rx_channel);
  73. ir_parser_config.flags = IR_TOOLS_FLAGS_PROTO_EXT | IR_TOOLS_FLAGS_INVERSE;
  74. s_ir_parser = ir_parser_rmt_new_nec(&ir_parser_config);
  75. TEST_ASSERT_NOT_NULL(s_ir_parser);
  76. }
  77. }
  78. static void rmt_clean_testbench(int tx_channel, int rx_channel)
  79. {
  80. if (tx_channel >= 0) {
  81. TEST_ESP_OK(rmt_driver_uninstall(tx_channel));
  82. TEST_ESP_OK(s_ir_builder->del(s_ir_builder));
  83. s_ir_builder = NULL;
  84. }
  85. if (rx_channel >= 0) {
  86. TEST_ESP_OK(rmt_driver_uninstall(rx_channel));
  87. TEST_ESP_OK(s_ir_parser->del(s_ir_parser));
  88. s_ir_parser = NULL;
  89. }
  90. }
  91. TEST_CASE("RMT wrong configuration", "[rmt]")
  92. {
  93. rmt_config_t correct_config = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, 0);
  94. rmt_config_t wrong_config = correct_config;
  95. wrong_config.clk_div = 0;
  96. TEST_ASSERT(rmt_config(&wrong_config) == ESP_ERR_INVALID_ARG);
  97. wrong_config = correct_config;
  98. wrong_config.channel = SOC_RMT_CHANNELS_NUM;
  99. TEST_ASSERT(rmt_config(&wrong_config) == ESP_ERR_INVALID_ARG);
  100. wrong_config = correct_config;
  101. wrong_config.channel = 2;
  102. wrong_config.mem_block_num = 8;
  103. TEST_ASSERT(rmt_config(&wrong_config) == ESP_ERR_INVALID_ARG);
  104. TEST_ASSERT(rmt_set_mem_block_num(wrong_config.channel, -1) == ESP_ERR_INVALID_ARG);
  105. }
  106. TEST_CASE("RMT miscellaneous functions", "[rmt]")
  107. {
  108. rmt_channel_t channel = 0;
  109. uint8_t div_cnt;
  110. rmt_source_clk_t src_clk;
  111. uint8_t memNum;
  112. uint16_t idle_thres;
  113. rmt_mem_owner_t owner;
  114. // TX related functions
  115. rmt_setup_testbench(channel, -1, 0);
  116. TEST_ESP_OK(rmt_set_mem_block_num(channel, 2));
  117. TEST_ESP_OK(rmt_get_mem_block_num(channel, &memNum));
  118. TEST_ASSERT_EQUAL_UINT8(2, memNum);
  119. TEST_ESP_OK(rmt_set_clk_div(channel, 160));
  120. TEST_ESP_OK(rmt_get_clk_div(channel, &div_cnt));
  121. TEST_ASSERT_EQUAL_UINT8(160, div_cnt);
  122. #if SOC_RMT_SUPPORT_REF_TICK
  123. TEST_ESP_OK(rmt_set_source_clk(channel, RMT_BASECLK_REF));
  124. TEST_ESP_OK(rmt_get_source_clk(channel, &src_clk));
  125. TEST_ASSERT_EQUAL_INT(RMT_BASECLK_REF, src_clk);
  126. #endif
  127. #if SOC_RMT_SUPPORT_XTAL
  128. TEST_ESP_OK(rmt_set_source_clk(channel, RMT_BASECLK_XTAL));
  129. TEST_ESP_OK(rmt_get_source_clk(channel, &src_clk));
  130. TEST_ASSERT_EQUAL_INT(RMT_BASECLK_XTAL, src_clk);
  131. #endif
  132. TEST_ESP_OK(rmt_set_tx_carrier(channel, 0, 1, 0, 1));
  133. TEST_ESP_OK(rmt_set_idle_level(channel, 1, 0));
  134. rmt_clean_testbench(channel, -1);
  135. // RX related functions
  136. channel = RMT_RX_CHANNEL_ENCODING_START;
  137. rmt_setup_testbench(-1, channel, 0);
  138. TEST_ESP_OK(rmt_set_rx_idle_thresh(channel, 200));
  139. TEST_ESP_OK(rmt_get_rx_idle_thresh(channel, &idle_thres));
  140. TEST_ASSERT_EQUAL_UINT16(200, idle_thres);
  141. TEST_ESP_OK(rmt_set_rx_filter(channel, 1, 100));
  142. TEST_ESP_OK(rmt_set_memory_owner(channel, RMT_MEM_OWNER_RX));
  143. TEST_ESP_OK(rmt_get_memory_owner(channel, &owner));
  144. TEST_ASSERT_EQUAL_INT(RMT_MEM_OWNER_RX, owner);
  145. rmt_clean_testbench(-1, channel);
  146. }
  147. TEST_CASE("RMT multiple channels", "[rmt]")
  148. {
  149. rmt_config_t tx_cfg = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, 0);
  150. for (int i = 0; i < SOC_RMT_TX_CHANNELS_NUM; i++) {
  151. tx_cfg.channel = i;
  152. TEST_ESP_OK(rmt_config(&tx_cfg));
  153. TEST_ESP_OK(rmt_driver_install(tx_cfg.channel, 0, 0));
  154. }
  155. for (int i = 0; i < SOC_RMT_TX_CHANNELS_NUM; i++) {
  156. TEST_ESP_OK(rmt_driver_uninstall(i));
  157. }
  158. rmt_config_t rx_cfg = RMT_DEFAULT_CONFIG_RX(RMT_DATA_IO, RMT_RX_CHANNEL_ENCODING_START);
  159. for (int i = RMT_RX_CHANNEL_ENCODING_START; i < SOC_RMT_CHANNELS_NUM; i++) {
  160. rx_cfg.channel = i;
  161. TEST_ESP_OK(rmt_config(&rx_cfg));
  162. TEST_ESP_OK(rmt_driver_install(rx_cfg.channel, 0, 0));
  163. }
  164. for (int i = RMT_RX_CHANNEL_ENCODING_START; i < SOC_RMT_CHANNELS_NUM; i++) {
  165. TEST_ESP_OK(rmt_driver_uninstall(i));
  166. }
  167. }
  168. TEST_CASE("RMT install/uninstall test", "[rmt]")
  169. {
  170. rmt_config_t tx_cfg = RMT_DEFAULT_CONFIG_TX(RMT_DATA_IO, RMT_TX_CHANNEL_ENCODING_END);
  171. TEST_ESP_OK(rmt_config(&tx_cfg));
  172. for (int i = 0; i < 100; i++) {
  173. TEST_ESP_OK(rmt_driver_install(tx_cfg.channel, 1000, 0));
  174. TEST_ESP_OK(rmt_driver_uninstall(tx_cfg.channel));
  175. }
  176. rmt_config_t rx_cfg = RMT_DEFAULT_CONFIG_RX(RMT_DATA_IO, RMT_RX_CHANNEL_ENCODING_START);
  177. TEST_ESP_OK(rmt_config(&rx_cfg));
  178. for (int i = 0; i < 100; i++) {
  179. TEST_ESP_OK(rmt_driver_install(rx_cfg.channel, 1000, 0));
  180. TEST_ESP_OK(rmt_driver_uninstall(rx_cfg.channel));
  181. }
  182. }
  183. static void do_nec_tx_rx(uint32_t flags)
  184. {
  185. RingbufHandle_t rb = NULL;
  186. rmt_item32_t *items = NULL;
  187. size_t length = 0;
  188. uint32_t addr = 0x10;
  189. uint32_t cmd = 0x20;
  190. bool repeat = false;
  191. int tx_channel = 0;
  192. int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1;
  193. // test on different flags combinations
  194. rmt_setup_testbench(tx_channel, rx_channel, flags);
  195. // get ready to receive
  196. TEST_ESP_OK(rmt_get_ringbuf_handle(rx_channel, &rb));
  197. TEST_ASSERT_NOT_NULL(rb);
  198. TEST_ESP_OK(rmt_rx_start(rx_channel, true));
  199. vTaskDelay(pdMS_TO_TICKS(1000));
  200. // build NEC codes
  201. cmd = 0x20;
  202. while (cmd <= 0x30) {
  203. ESP_LOGI(TAG, "Send command 0x%x to address 0x%x", cmd, addr);
  204. // Send new key code
  205. TEST_ESP_OK(s_ir_builder->build_frame(s_ir_builder, addr, cmd));
  206. TEST_ESP_OK(s_ir_builder->get_result(s_ir_builder, &items, &length));
  207. if (cmd & 0x01) {
  208. TEST_ESP_OK(rmt_write_items(tx_channel, items, length, false)); // no wait
  209. TEST_ESP_OK(rmt_wait_tx_done(tx_channel, portMAX_DELAY));
  210. } else {
  211. TEST_ESP_OK(rmt_write_items(tx_channel, items, length, true)); // wait until done
  212. }
  213. cmd++;
  214. }
  215. // parse NEC codes
  216. while (rb) {
  217. items = (rmt_item32_t *) xRingbufferReceive(rb, &length, 1000);
  218. if (items) {
  219. length /= 4; // one RMT = 4 Bytes
  220. if (s_ir_parser->input(s_ir_parser, items, length) == ESP_OK) {
  221. if (s_ir_parser->get_scan_code(s_ir_parser, &addr, &cmd, &repeat) == ESP_OK) {
  222. ESP_LOGI(TAG, "Scan Code %s --- addr: 0x%04x cmd: 0x%04x", repeat ? "(repeat)" : "", addr, cmd);
  223. }
  224. }
  225. vRingbufferReturnItem(rb, (void *) items);
  226. } else {
  227. ESP_LOGI(TAG, "done");
  228. break;
  229. }
  230. }
  231. TEST_ASSERT_EQUAL(0x30, cmd);
  232. rmt_clean_testbench(tx_channel, rx_channel);
  233. }
  234. // basic nec tx and rx test, using APB source clock, no modulation
  235. TEST_CASE("RMT NEC TX and RX (APB)", "[rmt]")
  236. {
  237. do_nec_tx_rx(0);
  238. }
  239. // test with RMT_TESTBENCH_FLAGS_ALWAYS_ON will take a long time (REF_TICK is much slower than APB CLOCK)
  240. TEST_CASE("RMT NEC TX and RX (always on)", "[rmt][timeout=240]")
  241. {
  242. do_nec_tx_rx(RMT_TESTBENCH_FLAGS_ALWAYS_ON);
  243. }
  244. #if SOC_RMT_SUPPORT_RX_DEMODULATION
  245. // basic nec tx and rx test, using APB source clock, with modulation and demodulation on
  246. TEST_CASE("RMT NEC TX and RX (Modulation/Demodulation)", "[rmt]")
  247. {
  248. do_nec_tx_rx(RMT_TESTBENCH_FLAGS_CARRIER_ON);
  249. }
  250. #endif
  251. TEST_CASE("RMT TX (SOC_RMT_CHANNEL_MEM_WORDS-1) symbols", "[rmt][boundary]")
  252. {
  253. int tx_channel = 0;
  254. rmt_setup_testbench(tx_channel, -1, 0);
  255. rmt_item32_t *items = malloc(sizeof(rmt_item32_t) * (SOC_RMT_CHANNEL_MEM_WORDS - 1));
  256. for (int i = 0; i < SOC_RMT_CHANNEL_MEM_WORDS - 1; i++) {
  257. items[i] = (rmt_item32_t) {
  258. {{
  259. 200, 1, 200, 0
  260. }
  261. }
  262. };
  263. }
  264. TEST_ESP_OK(rmt_write_items(tx_channel, items, SOC_RMT_CHANNEL_MEM_WORDS - 1, 1));
  265. free(items);
  266. rmt_clean_testbench(tx_channel, -1);
  267. }
  268. TEST_CASE("RMT TX stop", "[rmt]")
  269. {
  270. RingbufHandle_t rb = NULL;
  271. rmt_item32_t *frames = NULL;
  272. size_t length = 0;
  273. uint32_t count = 10;
  274. uint32_t addr = 0x10;
  275. uint32_t cmd = 0x20;
  276. bool repeat = false;
  277. int tx_channel = 0;
  278. int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1;
  279. rmt_setup_testbench(tx_channel, rx_channel, 0);
  280. // re-install ir_builder, to enlarge internal buffer size
  281. TEST_ESP_OK(s_ir_builder->del(s_ir_builder));
  282. ir_builder_config_t ir_builder_config = IR_BUILDER_DEFAULT_CONFIG((ir_dev_t)tx_channel);
  283. ir_builder_config.buffer_size *= count;
  284. ir_builder_config.flags = IR_TOOLS_FLAGS_PROTO_EXT;
  285. s_ir_builder = ir_builder_rmt_new_nec(&ir_builder_config);
  286. TEST_ASSERT_NOT_NULL(s_ir_builder);
  287. // get ready to receive
  288. TEST_ESP_OK(rmt_get_ringbuf_handle(rx_channel, &rb));
  289. TEST_ASSERT_NOT_NULL(rb);
  290. TEST_ESP_OK(rmt_rx_start(rx_channel, true));
  291. vTaskDelay(pdMS_TO_TICKS(1000));
  292. // build NEC codes
  293. ESP_LOGI(TAG, "Plan to send command 0x%x~0x%x to address 0x%x", cmd, cmd + count, addr);
  294. for (int i = 0; i <= count; i++) {
  295. TEST_ESP_OK(s_ir_builder->build_frame(s_ir_builder, addr, cmd));
  296. cmd++;
  297. }
  298. TEST_ESP_OK(s_ir_builder->get_result(s_ir_builder, &frames, &length));
  299. // send for 1 second and then stop
  300. TEST_ESP_OK(rmt_write_items(tx_channel, frames, length, true));
  301. vTaskDelay(pdMS_TO_TICKS(100));
  302. TEST_ESP_OK(rmt_tx_stop(tx_channel));
  303. // parse NEC codes
  304. uint32_t num = 0;
  305. while (rb) {
  306. frames = (rmt_item32_t *) xRingbufferReceive(rb, &length, 1000);
  307. if (frames) {
  308. length /= 4; // one RMT = 4 Bytes
  309. if (s_ir_parser->input(s_ir_parser, frames, length) == ESP_OK) {
  310. if (s_ir_parser->get_scan_code(s_ir_parser, &addr, &cmd, &repeat) == ESP_OK) {
  311. ESP_LOGI(TAG, "Scan Code %s --- addr: 0x%04x cmd: 0x%04x", repeat ? "(repeat)" : "", addr, cmd);
  312. num++;
  313. }
  314. }
  315. vRingbufferReturnItem(rb, (void *) frames);
  316. } else {
  317. ESP_LOGI(TAG, "done");
  318. break;
  319. }
  320. }
  321. TEST_ASSERT(num < count);
  322. rmt_clean_testbench(tx_channel, rx_channel);
  323. }
  324. #if SOC_RMT_SUPPORT_RX_PINGPONG
  325. TEST_CASE("RMT Ping-Pong operation", "[rmt]")
  326. {
  327. int tx_channel = 0;
  328. int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1;
  329. rmt_item32_t frames[SOC_RMT_CHANNEL_MEM_WORDS * 2]; // send two block data using ping-pong
  330. RingbufHandle_t rb = NULL;
  331. uint32_t size = sizeof(frames) / sizeof(frames[0]);
  332. // The design of the following test frame should trigger three rx threshold interrupt and one rx end interrupt
  333. int i = 0;
  334. for (i = 0; i < size - 1; i++) {
  335. frames[i].level0 = 1;
  336. frames[i].duration0 = 100;
  337. frames[i].level1 = 0;
  338. frames[i].duration1 = 100;
  339. }
  340. frames[i].level0 = 1;
  341. frames[i].duration0 = 0;
  342. frames[i].level1 = 0;
  343. frames[i].duration1 = 0;
  344. rmt_setup_testbench(tx_channel, rx_channel, 0);
  345. // get ready to receive
  346. TEST_ESP_OK(rmt_get_ringbuf_handle(rx_channel, &rb));
  347. TEST_ASSERT_NOT_NULL(rb);
  348. TEST_ESP_OK(rmt_rx_start(rx_channel, true));
  349. vTaskDelay(pdMS_TO_TICKS(1000));
  350. for (uint32_t test_count = 0; test_count < 5; test_count++) {
  351. TEST_ESP_OK(rmt_write_items(tx_channel, frames, size, true));
  352. // parse received data
  353. size_t length = 0;
  354. rmt_item32_t *items = (rmt_item32_t *) xRingbufferReceive(rb, &length, 1000);
  355. if (items) {
  356. vRingbufferReturnItem(rb, (void *) items);
  357. }
  358. TEST_ASSERT_EQUAL(4 * (size - 1), length);
  359. }
  360. rmt_clean_testbench(tx_channel, rx_channel);
  361. }
  362. #endif
  363. #if SOC_RMT_SUPPORT_TX_GROUP
  364. static uint32_t tx_end_time0, tx_end_time1;
  365. static void rmt_tx_end_cb(rmt_channel_t channel, void *arg)
  366. {
  367. if (channel == 0) {
  368. tx_end_time0 = esp_cpu_get_ccount();
  369. } else {
  370. tx_end_time1 = esp_cpu_get_ccount();
  371. }
  372. }
  373. TEST_CASE("RMT TX simultaneously", "[rmt]")
  374. {
  375. rmt_item32_t frames[SOC_RMT_CHANNEL_MEM_WORDS];
  376. uint32_t size = sizeof(frames) / sizeof(frames[0]);
  377. int channel0 = 0;
  378. int channel1 = 1;
  379. int i = 0;
  380. for (i = 0; i < size - 1; i++) {
  381. frames[i].level0 = 1;
  382. frames[i].duration0 = 1000;
  383. frames[i].level1 = 0;
  384. frames[i].duration1 = 1000;
  385. }
  386. frames[i].level0 = 0;
  387. frames[i].duration0 = 0;
  388. frames[i].level1 = 0;
  389. frames[i].duration1 = 0;
  390. rmt_config_t tx_config0 = RMT_DEFAULT_CONFIG_TX(4, channel0);
  391. rmt_config_t tx_config1 = RMT_DEFAULT_CONFIG_TX(5, channel1);
  392. TEST_ESP_OK(rmt_config(&tx_config0));
  393. TEST_ESP_OK(rmt_config(&tx_config1));
  394. TEST_ESP_OK(rmt_driver_install(channel0, 0, 0));
  395. TEST_ESP_OK(rmt_driver_install(channel1, 0, 0));
  396. rmt_register_tx_end_callback(rmt_tx_end_cb, NULL);
  397. TEST_ESP_OK(rmt_add_channel_to_group(channel0));
  398. TEST_ESP_OK(rmt_add_channel_to_group(channel1));
  399. TEST_ESP_OK(rmt_write_items(channel0, frames, size, false));
  400. vTaskDelay(pdMS_TO_TICKS(1000));
  401. TEST_ESP_OK(rmt_write_items(channel1, frames, size, false));
  402. TEST_ESP_OK(rmt_wait_tx_done(channel0, portMAX_DELAY));
  403. TEST_ESP_OK(rmt_wait_tx_done(channel1, portMAX_DELAY));
  404. ESP_LOGI(TAG, "tx_end_time0=%u, tx_end_time1=%u", tx_end_time0, tx_end_time1);
  405. TEST_ASSERT_LESS_OR_EQUAL_UINT32(2000, tx_end_time1 - tx_end_time0);
  406. TEST_ESP_OK(rmt_remove_channel_from_group(channel0));
  407. TEST_ESP_OK(rmt_remove_channel_from_group(channel1));
  408. TEST_ESP_OK(rmt_driver_uninstall(channel0));
  409. TEST_ESP_OK(rmt_driver_uninstall(channel1));
  410. }
  411. #endif
  412. #if SOC_RMT_SUPPORT_TX_LOOP_COUNT
  413. static void rmt_tx_loop_end(rmt_channel_t channel, void *arg)
  414. {
  415. rmt_tx_stop(channel);
  416. }
  417. TEST_CASE("RMT TX loop", "[rmt]")
  418. {
  419. RingbufHandle_t rb = NULL;
  420. rmt_item32_t *items = NULL;
  421. size_t length = 0;
  422. uint32_t addr = 0x10;
  423. uint32_t cmd = 0x20;
  424. bool repeat = false;
  425. int tx_channel = 0;
  426. int rx_channel = RMT_RX_CHANNEL_ENCODING_START + 1;
  427. uint32_t count = 0;
  428. rmt_setup_testbench(tx_channel, rx_channel, RMT_TESTBENCH_FLAGS_LOOP_ON);
  429. // get ready to receive
  430. TEST_ESP_OK(rmt_get_ringbuf_handle(rx_channel, &rb));
  431. TEST_ASSERT_NOT_NULL(rb);
  432. TEST_ESP_OK(rmt_rx_start(rx_channel, true));
  433. vTaskDelay(pdMS_TO_TICKS(1000));
  434. // register callback functions, invoked when tx loop count to ceiling
  435. rmt_register_tx_end_callback(rmt_tx_loop_end, NULL);
  436. // build NEC codes
  437. ESP_LOGI(TAG, "Send command 0x%x to address 0x%x", cmd, addr);
  438. // Send new key code
  439. TEST_ESP_OK(s_ir_builder->build_frame(s_ir_builder, addr, cmd));
  440. TEST_ESP_OK(s_ir_builder->get_result(s_ir_builder, &items, &length));
  441. TEST_ESP_OK(rmt_write_items(tx_channel, items, length, true)); // wait until done
  442. // parse NEC codes
  443. while (rb) {
  444. items = (rmt_item32_t *) xRingbufferReceive(rb, &length, 1000);
  445. if (items) {
  446. length /= 4; // one RMT = 4 Bytes
  447. if (s_ir_parser->input(s_ir_parser, items, length) == ESP_OK) {
  448. if (s_ir_parser->get_scan_code(s_ir_parser, &addr, &cmd, &repeat) == ESP_OK) {
  449. count++;
  450. ESP_LOGI(TAG, "Scan Code %s --- addr: 0x%04x cmd: 0x%04x", repeat ? "(repeat)" : "", addr, cmd);
  451. }
  452. }
  453. vRingbufferReturnItem(rb, (void *) items);
  454. } else {
  455. ESP_LOGI(TAG, "done");
  456. break;
  457. }
  458. }
  459. TEST_ASSERT_EQUAL(10, count);
  460. rmt_clean_testbench(tx_channel, rx_channel);
  461. }
  462. #endif