test_pcnt.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. /**
  2. * this case is used for test PCNT
  3. * prepare job for test environment UT_T1_PCNT:
  4. * 1. prepare one ESP-WROOM-32 board and connect it to PC.
  5. * 2. connect GPIO18 with GPIO4
  6. * 3. GPIO5 connect to 3.3v
  7. * 4. GPIO19 connect to GND
  8. * 5. logic analyzer will help too if possible
  9. *
  10. * the GPIO18 is the pulse producer, the GPIO4 is the input GPIO
  11. */
  12. #include <stdio.h>
  13. #include "freertos/FreeRTOS.h"
  14. #include "freertos/portmacro.h"
  15. #include "freertos/task.h"
  16. #include "freertos/queue.h"
  17. #include "driver/periph_ctrl.h"
  18. #include "driver/gpio.h"
  19. #include "driver/pcnt.h"
  20. #include "driver/ledc.h"
  21. #include "esp_attr.h"
  22. #include "esp_log.h"
  23. #include "soc/gpio_periph.h"
  24. #include "unity.h"
  25. #include "esp32/rom/ets_sys.h"
  26. #define PULSE_IO 18
  27. #define PCNT_INPUT_IO 4
  28. #define PCNT_CTRL_FLOATING_IO 5
  29. #define PCNT_CTRL_GND_IO 19
  30. #define HIGHEST_LIMIT 10
  31. #define LOWEST_LIMIT 0
  32. #define MAX_THRESHOLD 5
  33. #define MIN_THRESHOLD 0
  34. static xQueueHandle pcnt_evt_queue;
  35. typedef struct {
  36. int zero_times;
  37. int h_limit;
  38. int l_limit;
  39. int h_threshold;
  40. int l_threshold;
  41. int filter_time;
  42. } event_times;
  43. /* use LEDC to produce pulse for PCNT
  44. * the frequency of LEDC is 1000, so every second will get 1000 count values
  45. * the PCNT count the LEDC pulse
  46. * */
  47. static void produce_pulse(void)
  48. {
  49. ledc_timer_config_t ledc_timer = {
  50. .speed_mode = LEDC_HIGH_SPEED_MODE,
  51. .timer_num = LEDC_TIMER_1,
  52. .duty_resolution = LEDC_TIMER_10_BIT,
  53. .freq_hz = 1,
  54. .clk_cfg = LEDC_AUTO_CLK,
  55. };
  56. ledc_timer_config(&ledc_timer);
  57. ledc_channel_config_t ledc_channel = {
  58. .speed_mode = LEDC_HIGH_SPEED_MODE,
  59. .channel = LEDC_CHANNEL_1,
  60. .timer_sel = LEDC_TIMER_1,
  61. .intr_type = LEDC_INTR_DISABLE,
  62. .gpio_num = PULSE_IO,
  63. .duty = 100,
  64. .hpoint = 0,
  65. };
  66. ledc_channel_config(&ledc_channel);
  67. }
  68. static void IRAM_ATTR pcnt_intr_handler(void *arg)
  69. {
  70. uint32_t intr_status = PCNT.int_st.val;
  71. int i;
  72. uint32_t status;
  73. BaseType_t port_status = pdFALSE;
  74. for (i = 0; i < PCNT_UNIT_MAX; i++) {
  75. if (intr_status & (BIT(i))) {
  76. status = PCNT.status_unit[i].val;
  77. PCNT.int_clr.val = BIT(i);
  78. xQueueSendFromISR(pcnt_evt_queue, &status, &port_status);
  79. if (port_status == pdTRUE) {
  80. portYIELD_FROM_ISR();
  81. }
  82. }
  83. }
  84. }
  85. static void event_calculate(event_times* event)
  86. {
  87. int16_t test_counter = 0;
  88. int times = 0;
  89. BaseType_t port_status;
  90. uint32_t status = 0;
  91. while (times < 10) {
  92. port_status = xQueueReceive(pcnt_evt_queue, &status, 1000 / portTICK_PERIOD_MS);
  93. if (port_status == pdTRUE) {
  94. event->filter_time++;
  95. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  96. printf("Current counter value :%d\n", test_counter);
  97. if (status & PCNT_STATUS_THRES1_M) {
  98. printf("THRES1 EVT\n");
  99. event->h_threshold++;
  100. }
  101. if (status & PCNT_STATUS_THRES0_M) {
  102. printf("THRES0 EVT\n");
  103. event->l_threshold++;
  104. }
  105. if (status & PCNT_STATUS_L_LIM_M) {
  106. printf("L_LIM EVT\n");
  107. event->l_limit++;
  108. }
  109. if (status & PCNT_STATUS_H_LIM_M) {
  110. printf("H_LIM EVT\n");
  111. event->h_limit++;
  112. }
  113. if (status & PCNT_STATUS_ZERO_M) {
  114. printf("ZERO EVT\n");
  115. event->zero_times++;
  116. }
  117. } else {
  118. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  119. printf("Current counter value :%d\n", test_counter);
  120. }
  121. times++;
  122. }
  123. printf("%d, %d, %d, %d, %d, %d\n", event->h_threshold, event->l_threshold,
  124. event->l_limit, event->h_limit, event->zero_times, event->filter_time);
  125. }
  126. /*
  127. * There exist 2 kind of counting methods: positive and negative counting method
  128. * 1. when control IO is high level, PCNT is positive counting mode
  129. * 2. when control IO is low level, PCNT is positive negative mode
  130. * the positive method standard is as below:
  131. * ----------------------------------------------------------------------------------
  132. * POS_ MODE | LCTRL_ MODE | HCTRL_ MODE | sig l→h when ctrl=0 | sig l→h when ctrl=1
  133. * NEG_ MODE | | | |
  134. * ===================================================================================
  135. * 1 (inc) | 0 (-) | 0 (-) | Inc ctr | Inc ctr
  136. * 2 (dec) | 0 (-) | 0 (-) | Dec ctr | Dec ctr
  137. * 0 (-) | x | x | No action | No action
  138. * 1 (inc) | 0 (-) | 1 (inv) | Inc ctr | Dec ctr
  139. * 1 (inc) | 1 (inv) | 0 (-) | Dec ctr | Inc ctr
  140. * 2 (dec) | 0 (-) | 1 (inv) | Dec ctr | Inc ctr
  141. * 1 (inc) | 0 (-) | 2 (dis) | Inc ctr | No action
  142. * 1 (inc) | 2 (dis) | 0 (-) | No action | Inc ctr
  143. * -----------------------------------------------------------------------------------
  144. * */
  145. static void count_mode_test(gpio_num_t ctl_io)
  146. {
  147. int16_t test_counter;
  148. //produce pulse, 100HZ
  149. ledc_timer_config_t ledc_timer = {
  150. .speed_mode = LEDC_HIGH_SPEED_MODE,
  151. .timer_num = LEDC_TIMER_1,
  152. .duty_resolution = LEDC_TIMER_10_BIT,
  153. .freq_hz = 100,
  154. .clk_cfg = LEDC_AUTO_CLK,
  155. };
  156. ledc_timer_config(&ledc_timer);
  157. ledc_channel_config_t ledc_channel = {
  158. .speed_mode = LEDC_HIGH_SPEED_MODE,
  159. .channel = LEDC_CHANNEL_1,
  160. .timer_sel = LEDC_TIMER_1,
  161. .intr_type = LEDC_INTR_DISABLE,
  162. .gpio_num = PULSE_IO,
  163. .duty = 100,
  164. .hpoint = 0,
  165. };
  166. ledc_channel_config(&ledc_channel);
  167. pcnt_config_t pcnt_config = {
  168. .pulse_gpio_num = PCNT_INPUT_IO,
  169. .ctrl_gpio_num = ctl_io,
  170. .channel = PCNT_CHANNEL_0,
  171. .unit = PCNT_UNIT_0,
  172. .pos_mode = PCNT_COUNT_INC,
  173. .neg_mode = PCNT_COUNT_DIS,
  174. .lctrl_mode = PCNT_MODE_REVERSE,
  175. .hctrl_mode = PCNT_MODE_KEEP,
  176. .counter_h_lim = 101,
  177. .counter_l_lim = -101,
  178. };
  179. TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
  180. int16_t result1[8] = {100, -100, 0, -100, 100, 100, 0, 100};
  181. int16_t result2[8] = {100, -100, 0, 100, -100, -100, 100, 0};
  182. int16_t *result;
  183. if (gpio_get_level(pcnt_config.ctrl_gpio_num)) {
  184. result = result1;
  185. } else {
  186. result = result2;
  187. }
  188. // 1, 0, 0, 0
  189. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  190. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  191. TEST_ESP_OK(pcnt_set_mode(PCNT_UNIT_0, PCNT_CHANNEL_0,
  192. PCNT_COUNT_INC, PCNT_COUNT_DIS,
  193. PCNT_MODE_KEEP, PCNT_MODE_KEEP));
  194. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  195. vTaskDelay(1000 / portTICK_RATE_MS);
  196. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  197. printf("value: %d\n", test_counter);
  198. TEST_ASSERT_INT16_WITHIN(1, test_counter, result[0]);
  199. //2, 0, 0, 0
  200. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  201. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  202. TEST_ESP_OK(pcnt_set_mode(PCNT_UNIT_0, PCNT_CHANNEL_0,
  203. PCNT_COUNT_DEC, PCNT_COUNT_DIS,
  204. PCNT_MODE_KEEP, PCNT_MODE_KEEP));
  205. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  206. vTaskDelay(1000 / portTICK_RATE_MS);
  207. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  208. printf("value: %d\n", test_counter);
  209. TEST_ASSERT_INT16_WITHIN(1, test_counter, result[1]);
  210. //0,0,0,0
  211. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  212. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  213. TEST_ESP_OK(pcnt_set_mode(PCNT_UNIT_0, PCNT_CHANNEL_0,
  214. PCNT_COUNT_DIS, PCNT_COUNT_DIS,
  215. PCNT_MODE_KEEP, PCNT_MODE_KEEP));
  216. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  217. vTaskDelay(1000 / portTICK_RATE_MS);
  218. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  219. printf("value: %d\n", test_counter);
  220. TEST_ASSERT_INT16_WITHIN(1, test_counter, result[2]);
  221. //1,0,1,0
  222. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  223. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  224. TEST_ESP_OK(pcnt_set_mode(PCNT_UNIT_0, PCNT_CHANNEL_0,
  225. PCNT_COUNT_INC, PCNT_COUNT_DIS,
  226. PCNT_MODE_REVERSE, PCNT_MODE_KEEP));
  227. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  228. vTaskDelay(1000 / portTICK_RATE_MS);
  229. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  230. printf("value: %d\n", test_counter);
  231. TEST_ASSERT_INT16_WITHIN(1, test_counter, result[3]);
  232. //1,0,0,1
  233. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  234. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  235. TEST_ESP_OK(pcnt_set_mode(PCNT_UNIT_0, PCNT_CHANNEL_0,
  236. PCNT_COUNT_INC, PCNT_COUNT_DIS,
  237. PCNT_MODE_KEEP, PCNT_MODE_REVERSE));
  238. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  239. vTaskDelay(1000 / portTICK_RATE_MS);
  240. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  241. printf("value: %d\n", test_counter);
  242. TEST_ASSERT_INT16_WITHIN(1, test_counter, result[4]);
  243. //2,0,0,1
  244. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  245. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  246. TEST_ESP_OK(pcnt_set_mode(PCNT_UNIT_0, PCNT_CHANNEL_0,
  247. PCNT_COUNT_DEC, PCNT_COUNT_DIS,
  248. PCNT_MODE_REVERSE, PCNT_MODE_KEEP));
  249. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  250. vTaskDelay(1000 / portTICK_RATE_MS);
  251. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  252. printf("value: %d\n", test_counter);
  253. TEST_ASSERT_INT16_WITHIN(1, test_counter, result[5]);
  254. //1,0,2,0
  255. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  256. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  257. TEST_ESP_OK(pcnt_set_mode(PCNT_UNIT_0, PCNT_CHANNEL_0,
  258. PCNT_COUNT_INC, PCNT_COUNT_DIS,
  259. PCNT_MODE_DISABLE, PCNT_MODE_KEEP));
  260. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  261. vTaskDelay(1000 / portTICK_RATE_MS);
  262. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  263. printf("value: %d\n", test_counter);
  264. TEST_ASSERT_INT16_WITHIN(1, test_counter, result[6]);
  265. //1,0,0,2
  266. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  267. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  268. TEST_ESP_OK(pcnt_set_mode(PCNT_UNIT_0, PCNT_CHANNEL_0,
  269. PCNT_COUNT_INC, PCNT_COUNT_DIS,
  270. PCNT_MODE_KEEP, PCNT_MODE_DISABLE));
  271. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  272. vTaskDelay(1000 / portTICK_RATE_MS);
  273. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  274. printf("value: %d\n", test_counter);
  275. TEST_ASSERT_INT16_WITHIN(1, test_counter, result[7]);
  276. }
  277. // test PCNT basic configuration
  278. TEST_CASE("PCNT test config", "[pcnt][test_env=UT_T1_PCNT]")
  279. {
  280. pcnt_config_t pcnt_config = {
  281. .pulse_gpio_num = PCNT_INPUT_IO,
  282. .ctrl_gpio_num = PCNT_CTRL_FLOATING_IO,
  283. .channel = PCNT_CHANNEL_0,
  284. .unit = PCNT_UNIT_0,
  285. .pos_mode = PCNT_COUNT_INC,
  286. .neg_mode = PCNT_COUNT_DIS,
  287. .lctrl_mode = PCNT_MODE_REVERSE,
  288. .hctrl_mode = PCNT_MODE_KEEP,
  289. .counter_h_lim = 100,
  290. .counter_l_lim = 0,
  291. };
  292. // basic configuration
  293. pcnt_config_t temp_pcnt_config = pcnt_config;
  294. TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
  295. // test 8 units, from 0-7
  296. pcnt_config = temp_pcnt_config;
  297. pcnt_config.unit = PCNT_UNIT_MAX;
  298. TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config));
  299. for (int i = 0; i <= 7; i++) {
  300. pcnt_config.unit = i;
  301. TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
  302. }
  303. // test channels
  304. pcnt_config = temp_pcnt_config;
  305. pcnt_config.channel = PCNT_CHANNEL_MAX;
  306. TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config));
  307. pcnt_config = temp_pcnt_config;
  308. pcnt_config.pulse_gpio_num = -1;
  309. TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
  310. pcnt_config = temp_pcnt_config;
  311. pcnt_config.pulse_gpio_num = 41;
  312. TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config));
  313. // test pulse_gpio_num and ctrl_gpio_num is the same
  314. pcnt_config = temp_pcnt_config;
  315. pcnt_config.pulse_gpio_num = PCNT_INPUT_IO;
  316. pcnt_config.ctrl_gpio_num = PCNT_INPUT_IO;
  317. TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config));
  318. pcnt_config = temp_pcnt_config;
  319. pcnt_config.pos_mode = PCNT_COUNT_MAX;
  320. TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config));
  321. pcnt_config = temp_pcnt_config;
  322. pcnt_config.hctrl_mode = PCNT_MODE_MAX;
  323. TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config));
  324. pcnt_config = temp_pcnt_config;
  325. pcnt_config.lctrl_mode = PCNT_MODE_MAX;
  326. TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config));
  327. }
  328. /* PCNT basic property:
  329. * 1. pause counter
  330. * 2. resume counter
  331. * 3. clear counter
  332. * 4. check the counter value*/
  333. TEST_CASE("PCNT basic function test", "[pcnt][test_env=UT_T1_PCNT]")
  334. {
  335. int16_t test_counter;
  336. int16_t time = 0;
  337. int clear_count = 0;
  338. int resume_count = 0;
  339. int temp_value = 0;
  340. pcnt_config_t pcnt_config = {
  341. .pulse_gpio_num = PCNT_INPUT_IO,
  342. .ctrl_gpio_num = PCNT_CTRL_FLOATING_IO,
  343. .channel = PCNT_CHANNEL_0,
  344. .unit = PCNT_UNIT_0,
  345. .pos_mode = PCNT_COUNT_INC,
  346. .neg_mode = PCNT_COUNT_DIS,
  347. .lctrl_mode = PCNT_MODE_REVERSE,
  348. .hctrl_mode = PCNT_MODE_KEEP,
  349. .counter_h_lim = 10,
  350. .counter_l_lim = -10,
  351. };
  352. TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
  353. // use LEDC to produce the pulse, then the PCNT to count it
  354. produce_pulse();
  355. // initialize first, the initail value should be 0
  356. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  357. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  358. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  359. TEST_ASSERT_EQUAL_INT16(test_counter, 0);
  360. // resume the PCNT
  361. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  362. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  363. TEST_ASSERT_EQUAL_INT16(test_counter, 0);
  364. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  365. TEST_ASSERT_EQUAL_INT16(test_counter, 0);
  366. //count now
  367. while (time != 10) {
  368. vTaskDelay(1001 / portTICK_RATE_MS); // in case of can't wait to get counter(edge effect)
  369. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  370. printf("COUNT: %d\n", test_counter);
  371. TEST_ASSERT_NOT_EQUAL(test_counter, temp_value);
  372. temp_value = test_counter;
  373. if (test_counter == 5 || test_counter == -5) {
  374. //test clear
  375. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  376. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  377. TEST_ASSERT_EQUAL_INT16(test_counter, 0);
  378. clear_count++;
  379. }
  380. if (test_counter == 0) {
  381. //test pause
  382. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  383. vTaskDelay(1000 / portTICK_RATE_MS);
  384. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  385. printf("PAUSE: %d\n", test_counter);
  386. TEST_ASSERT_EQUAL_INT16(test_counter, 0);
  387. // test resume
  388. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  389. vTaskDelay(1000 / portTICK_RATE_MS);
  390. TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter));
  391. printf("RESUME: %d\n", test_counter);
  392. TEST_ASSERT_EQUAL_INT16(test_counter, (gpio_get_level(PCNT_CTRL_FLOATING_IO) > 0) ? (1) : -1);
  393. resume_count++;
  394. }
  395. time++;
  396. }
  397. TEST_ASSERT_EQUAL_INT16(clear_count, 2);
  398. TEST_ASSERT_EQUAL_INT16(resume_count, 2);
  399. }
  400. /**
  401. * there are 4 situations will be tested:
  402. * 1. set event to interrupt triggered
  403. * 2. disable interrupt to stop triggering interrupt
  404. * 3. enable interrupt to interrupt triggered again
  405. * 4. disable event to stop triggering interrupt
  406. *
  407. * PCNT interrupt type:
  408. * 1. PCNT_EVT_THRES_1
  409. * 2. PCNT_EVT_THRES_0
  410. * 3. PCNT_EVT_ZERO
  411. * 4. PCNT_EVT_H_LIM
  412. * 5. PCNT_EVT_L_LIM
  413. * */
  414. // set it ignore: need to debug
  415. TEST_CASE("PCNT interrupt method test(control IO is high)", "[pcnt][test_env=UT_T1_PCNT][timeout=120][ignore]")
  416. {
  417. pcnt_config_t config = {
  418. .pulse_gpio_num = PCNT_INPUT_IO,
  419. .ctrl_gpio_num = PCNT_CTRL_FLOATING_IO,
  420. .channel = PCNT_CHANNEL_0,
  421. .unit = PCNT_UNIT_0,
  422. .pos_mode = PCNT_COUNT_INC,
  423. .neg_mode = PCNT_COUNT_DIS,
  424. .lctrl_mode = PCNT_MODE_REVERSE,
  425. .hctrl_mode = PCNT_MODE_KEEP,
  426. .counter_h_lim = 5,
  427. .counter_l_lim = 0,
  428. };
  429. TEST_ESP_OK(pcnt_unit_config(&config));
  430. produce_pulse();
  431. event_times event = {
  432. .zero_times = 0,
  433. .h_limit = 0,
  434. .l_limit = 0,
  435. .h_threshold = 0,
  436. .l_threshold = 0,
  437. .filter_time = 0,
  438. };
  439. //interrupt set
  440. TEST_ESP_OK(pcnt_set_filter_value(PCNT_UNIT_0, 2));
  441. TEST_ESP_OK(pcnt_filter_enable(PCNT_UNIT_0));
  442. TEST_ESP_OK(pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_1, 4)); // when arrive to max threshold trigger
  443. TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_1));
  444. TEST_ESP_OK(pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_0, 1)); // when arrive to minimum threshold trigger
  445. TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_0));
  446. TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_ZERO));
  447. TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_H_LIM)); // when arrive to max limit trigger
  448. TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_L_LIM)); // when arrive to minimum limit trigger
  449. // to initialize for PCNT
  450. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  451. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  452. TEST_ESP_OK(pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL));
  453. TEST_ESP_OK(pcnt_intr_enable(PCNT_UNIT_0));
  454. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  455. pcnt_evt_queue = xQueueCreate(10, sizeof(uint32_t));
  456. // test event
  457. event_calculate(&event);
  458. TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 2);
  459. TEST_ASSERT_INT_WITHIN(2, event.l_threshold, 2);
  460. TEST_ASSERT(event.l_limit == 0);
  461. TEST_ASSERT_INT_WITHIN(2, event.h_limit, 2);
  462. TEST_ASSERT_INT_WITHIN(2, event.zero_times, 2);
  463. TEST_ASSERT_INT_WITHIN(3, event.filter_time, 4);
  464. // test interrupt disable
  465. TEST_ESP_OK(pcnt_intr_disable(PCNT_UNIT_0));
  466. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  467. // for the original control io disable interrupt status
  468. event_calculate(&event);
  469. TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 2);
  470. TEST_ASSERT_INT_WITHIN(2, event.l_threshold, 2);
  471. TEST_ASSERT(event.l_limit == 0);
  472. TEST_ASSERT_INT_WITHIN(2, event.h_limit, 2);
  473. TEST_ASSERT_INT_WITHIN(2, event.zero_times, 2);
  474. TEST_ASSERT_INT_WITHIN(3, event.filter_time, 4);
  475. // enable the intr
  476. TEST_ESP_OK(pcnt_intr_enable(PCNT_UNIT_0));
  477. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  478. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  479. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  480. event_calculate(&event);
  481. TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 4);
  482. TEST_ASSERT_INT_WITHIN(2, event.l_threshold, 4);
  483. TEST_ASSERT(event.l_limit == 0);
  484. TEST_ASSERT_INT_WITHIN(2, event.h_limit, 4);
  485. TEST_ASSERT_INT_WITHIN(2, event.zero_times, 4);
  486. TEST_ASSERT_INT_WITHIN(3, event.filter_time, 10);
  487. // disable part of events
  488. TEST_ESP_OK(pcnt_event_disable(PCNT_UNIT_0, PCNT_EVT_ZERO));
  489. TEST_ESP_OK(pcnt_event_disable(PCNT_UNIT_0, PCNT_EVT_L_LIM));
  490. TEST_ESP_OK(pcnt_event_disable(PCNT_UNIT_0, PCNT_EVT_THRES_0));
  491. event_calculate(&event);
  492. TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 5);
  493. TEST_ASSERT_INT_WITHIN(2, event.l_threshold, 4);
  494. TEST_ASSERT(event.l_limit == 0);
  495. TEST_ASSERT_INT_WITHIN(2, event.h_limit, 6);
  496. TEST_ASSERT_INT_WITHIN(2, event.zero_times, 4);
  497. TEST_ASSERT_INT_WITHIN(3, event.filter_time, 14);
  498. pcnt_isr_service_uninstall();
  499. }
  500. // set it ignore: need to debug
  501. TEST_CASE("PCNT interrupt method test(control IO is low)", "[pcnt][test_env=UT_T1_PCNT][timeout=120][ignore]")
  502. {
  503. pcnt_config_t config = {
  504. .pulse_gpio_num = PCNT_INPUT_IO,
  505. .ctrl_gpio_num = PCNT_CTRL_GND_IO,
  506. .channel = PCNT_CHANNEL_0,
  507. .unit = PCNT_UNIT_0,
  508. .pos_mode = PCNT_COUNT_INC,
  509. .neg_mode = PCNT_COUNT_DIS,
  510. .lctrl_mode = PCNT_MODE_REVERSE,
  511. .hctrl_mode = PCNT_MODE_KEEP,
  512. .counter_h_lim = 0,
  513. .counter_l_lim = -5,
  514. };
  515. TEST_ESP_OK(pcnt_unit_config(&config));
  516. produce_pulse();
  517. event_times event = {
  518. .zero_times = 0,
  519. .h_limit = 0,
  520. .l_limit = 0,
  521. .h_threshold = 0,
  522. .l_threshold = 0,
  523. .filter_time = 0,
  524. };
  525. //interrupt set
  526. TEST_ESP_OK(pcnt_set_filter_value(PCNT_UNIT_0, 2));
  527. TEST_ESP_OK(pcnt_filter_enable(PCNT_UNIT_0));
  528. TEST_ESP_OK(pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_1, -4)); // when arrive to max threshold trigger
  529. TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_1));
  530. TEST_ESP_OK(pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_0, 0)); // when arrive to minimum threshold trigger
  531. TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_0));
  532. TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_ZERO));
  533. TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_H_LIM)); // when arrive to max limit trigger
  534. TEST_ESP_OK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_L_LIM)); // when arrive to minimum limit trigger
  535. // to initialize for PCNT
  536. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  537. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  538. TEST_ESP_OK(pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL));
  539. TEST_ESP_OK(pcnt_intr_enable(PCNT_UNIT_0));
  540. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  541. pcnt_evt_queue = xQueueCreate(10, sizeof(uint32_t));
  542. // test event
  543. event_calculate(&event);
  544. TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 1);
  545. TEST_ASSERT_INT_WITHIN(2, event.l_threshold, 1);
  546. TEST_ASSERT_INT_WITHIN(2, event.l_limit, 1);
  547. TEST_ASSERT_INT_WITHIN(2, event.h_limit, 0);
  548. TEST_ASSERT_INT_WITHIN(2, event.zero_times, 1);
  549. TEST_ASSERT_INT_WITHIN(2, event.filter_time, 2);
  550. // test interrupt disable
  551. TEST_ESP_OK(pcnt_intr_disable(PCNT_UNIT_0));
  552. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  553. // for the original control io disable interrupt status
  554. event_calculate(&event);
  555. TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 1);
  556. TEST_ASSERT_INT_WITHIN(2, event.l_threshold, 1);
  557. TEST_ASSERT_INT_WITHIN(2, event.l_limit, 1);
  558. TEST_ASSERT_INT_WITHIN(2, event.h_limit, 0);
  559. TEST_ASSERT_INT_WITHIN(2, event.zero_times, 1);
  560. TEST_ASSERT_INT_WITHIN(2, event.filter_time, 2);
  561. // enable the intr
  562. pcnt_unit_config(&config);
  563. TEST_ESP_OK(pcnt_intr_enable(PCNT_UNIT_0));
  564. TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0));
  565. TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0));
  566. TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0));
  567. event_calculate(&event);
  568. TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 2);
  569. TEST_ASSERT_INT_WITHIN(2, event.l_threshold, 3);
  570. TEST_ASSERT_INT_WITHIN(2, event.l_limit, 2);
  571. TEST_ASSERT_INT_WITHIN(2, event.h_limit, 0);
  572. TEST_ASSERT_INT_WITHIN(2, event.zero_times, 2);
  573. TEST_ASSERT_INT_WITHIN(2, event.filter_time, 6);
  574. // disable part of events
  575. TEST_ESP_OK(pcnt_event_disable(PCNT_UNIT_0, PCNT_EVT_ZERO));
  576. TEST_ESP_OK(pcnt_event_disable(PCNT_UNIT_0, PCNT_EVT_L_LIM));
  577. TEST_ESP_OK(pcnt_event_disable(PCNT_UNIT_0, PCNT_EVT_THRES_0));
  578. event_calculate(&event);
  579. TEST_ASSERT_INT_WITHIN(2, event.h_threshold, 4);
  580. TEST_ASSERT_INT_WITHIN(2, event.l_threshold, 3);
  581. TEST_ASSERT_INT_WITHIN(2, event.l_limit, 2);
  582. TEST_ASSERT_INT_WITHIN(2, event.h_limit, 0);
  583. TEST_ASSERT_INT_WITHIN(2, event.zero_times, 2);
  584. TEST_ASSERT_INT_WITHIN(2, event.filter_time, 8);
  585. pcnt_isr_service_uninstall();
  586. }
  587. TEST_CASE("PCNT counting mode test", "[pcnt][test_env=UT_T1_PCNT]")
  588. {
  589. printf("PCNT mode test for positive count\n");
  590. count_mode_test(PCNT_CTRL_FLOATING_IO);
  591. printf("PCNT mode test for negative count\n");
  592. count_mode_test(PCNT_CTRL_GND_IO);
  593. }