test_pulse_cnt.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. /*
  2. * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdio.h>
  7. #include "sdkconfig.h"
  8. #include "freertos/FreeRTOS.h"
  9. #include "freertos/task.h"
  10. #include "unity.h"
  11. #include "driver/pulse_cnt.h"
  12. #include "driver/gpio.h"
  13. #include "soc/soc_caps.h"
  14. #include "esp_attr.h"
  15. #include "test_pulse_cnt_board.h"
  16. TEST_CASE("pcnt_unit_install_uninstall", "[pcnt]")
  17. {
  18. pcnt_unit_config_t unit_config = {
  19. .low_limit = -100,
  20. .high_limit = 100,
  21. };
  22. pcnt_unit_handle_t units[SOC_PCNT_UNITS_PER_GROUP];
  23. int count_value = 0;
  24. printf("install pcnt units and check initial count\r\n");
  25. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  26. TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[i]));
  27. TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
  28. TEST_ASSERT_EQUAL(0, count_value);
  29. }
  30. // no more free pcnt units
  31. TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, pcnt_new_unit(&unit_config, &units[0]));
  32. printf("set glitch filter\r\n");
  33. pcnt_glitch_filter_config_t filter_config = {
  34. .max_glitch_ns = 1000,
  35. };
  36. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  37. TEST_ESP_OK(pcnt_unit_set_glitch_filter(units[i], &filter_config));
  38. }
  39. // invalid glitch configuration
  40. filter_config.max_glitch_ns = 500000;
  41. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_set_glitch_filter(units[0], &filter_config));
  42. printf("enable pcnt units\r\n");
  43. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  44. TEST_ESP_OK(pcnt_unit_enable(units[i]));
  45. }
  46. printf("start pcnt units\r\n");
  47. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  48. TEST_ESP_OK(pcnt_unit_start(units[i]));
  49. }
  50. printf("stop pcnt units\r\n");
  51. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  52. TEST_ESP_OK(pcnt_unit_stop(units[i]));
  53. }
  54. // can't uninstall unit before disable it
  55. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_del_unit(units[0]));
  56. printf("disable pcnt units\r\n");
  57. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  58. TEST_ESP_OK(pcnt_unit_disable(units[i]));
  59. }
  60. printf("uninstall pcnt units\r\n");
  61. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  62. TEST_ESP_OK(pcnt_del_unit(units[i]));
  63. }
  64. }
  65. TEST_CASE("pcnt_channel_install_uninstall", "[pcnt]")
  66. {
  67. pcnt_unit_config_t unit_config = {
  68. .low_limit = -100,
  69. .high_limit = 100,
  70. };
  71. pcnt_chan_config_t chan_config = {
  72. .edge_gpio_num = TEST_PCNT_GPIO_A, // only detect edge signal in this case
  73. .level_gpio_num = -1,
  74. .flags.io_loop_back = true,
  75. };
  76. pcnt_unit_handle_t units[SOC_PCNT_UNITS_PER_GROUP];
  77. pcnt_channel_handle_t chans[SOC_PCNT_UNITS_PER_GROUP][SOC_PCNT_CHANNELS_PER_UNIT];
  78. printf("install pcnt units\r\n");
  79. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  80. TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[i]));
  81. }
  82. printf("install pcnt channels\r\n");
  83. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  84. for (int j = 0; j < SOC_PCNT_CHANNELS_PER_UNIT; j++) {
  85. TEST_ESP_OK(pcnt_new_channel(units[i], &chan_config, &chans[i][j]));
  86. TEST_ESP_OK(pcnt_channel_set_edge_action(chans[i][j], PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  87. TEST_ESP_OK(pcnt_channel_set_level_action(chans[i][j], PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
  88. }
  89. TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, pcnt_new_channel(units[i], &chan_config, &chans[i][0]));
  90. TEST_ESP_OK(pcnt_unit_enable(units[i]));
  91. }
  92. printf("start units\r\n");
  93. int count_value = 0;
  94. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  95. // start unit
  96. TEST_ESP_OK(pcnt_unit_start(units[i]));
  97. // trigger 10 rising edge on GPIO0
  98. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
  99. TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
  100. // each channel increases to the same unit counter
  101. TEST_ASSERT_EQUAL(10 * SOC_PCNT_CHANNELS_PER_UNIT, count_value);
  102. }
  103. printf("clear counts\r\n");
  104. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  105. TEST_ESP_OK(pcnt_unit_clear_count(units[i]));
  106. TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
  107. TEST_ASSERT_EQUAL(0, count_value);
  108. }
  109. printf("stop unit\r\n");
  110. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  111. // stop unit
  112. TEST_ESP_OK(pcnt_unit_stop(units[i]));
  113. }
  114. // trigger 10 rising edge on GPIO0 shouldn't increase the counter
  115. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
  116. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  117. TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
  118. TEST_ASSERT_EQUAL(0, count_value);
  119. }
  120. printf("restart units\r\n");
  121. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  122. // start unit
  123. TEST_ESP_OK(pcnt_unit_start(units[i]));
  124. // trigger 10 rising edge on GPIO
  125. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
  126. TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
  127. // each channel increases to the same unit counter
  128. TEST_ASSERT_EQUAL(10 * SOC_PCNT_CHANNELS_PER_UNIT, count_value);
  129. }
  130. printf("uninstall channels and units\r\n");
  131. for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
  132. // stop unit
  133. TEST_ESP_OK(pcnt_unit_stop(units[i]));
  134. TEST_ESP_OK(pcnt_unit_disable(units[i]));
  135. // can't uninstall unit when channel is still alive
  136. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_del_unit(units[i]));
  137. for (int j = 0; j < SOC_PCNT_CHANNELS_PER_UNIT; j++) {
  138. TEST_ESP_OK(pcnt_del_channel(chans[i][j]));
  139. }
  140. TEST_ESP_OK(pcnt_del_unit(units[i]));
  141. }
  142. }
  143. TEST_CASE("pcnt_multiple_units_pulse_count", "[pcnt]")
  144. {
  145. printf("install pcnt units\r\n");
  146. pcnt_unit_config_t unit_config = {
  147. .low_limit = -100,
  148. .high_limit = 100,
  149. };
  150. pcnt_unit_handle_t units[2];
  151. for (int i = 0; i < 2; i++) {
  152. TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[i]));
  153. }
  154. printf("install pcnt channels\r\n");
  155. const int channel_gpios[] = {TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B};
  156. pcnt_chan_config_t chan_config = {
  157. .level_gpio_num = -1,
  158. .flags.io_loop_back = true,
  159. };
  160. pcnt_channel_handle_t chans[2];
  161. for (int i = 0; i < 2; i++) {
  162. chan_config.edge_gpio_num = channel_gpios[i];
  163. TEST_ESP_OK(pcnt_new_channel(units[i], &chan_config, &chans[i]));
  164. TEST_ESP_OK(pcnt_channel_set_edge_action(chans[i], PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  165. TEST_ESP_OK(pcnt_channel_set_level_action(chans[i], PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
  166. }
  167. printf("enable and start unit\r\n");
  168. for (int i = 0; i < 2; i++) {
  169. TEST_ESP_OK(pcnt_unit_enable(units[i]));
  170. TEST_ESP_OK(pcnt_unit_start(units[i]));
  171. }
  172. // trigger 10 rising edge on GPIO
  173. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
  174. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_B, 10);
  175. int count_value = 0;
  176. for (int i = 0; i < 2; i++) {
  177. TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
  178. TEST_ASSERT_EQUAL(10, count_value);
  179. }
  180. for (int i = 0; i < 2; i++) {
  181. TEST_ESP_OK(pcnt_unit_stop(units[i]));
  182. TEST_ESP_OK(pcnt_unit_disable(units[i]));
  183. TEST_ESP_OK(pcnt_del_channel(chans[i]));
  184. TEST_ESP_OK(pcnt_del_unit(units[i]));
  185. }
  186. }
  187. /**
  188. * @brief Using this context to save the triggered watch-points in sequence
  189. */
  190. typedef struct {
  191. uint32_t index;
  192. int triggered_watch_values[8];
  193. } test_pcnt_quadrature_context_t;
  194. TEST_PCNT_CALLBACK_ATTR
  195. static bool test_pcnt_quadrature_reach_watch_point(pcnt_unit_handle_t handle, const pcnt_watch_event_data_t *event_data, void *user_data)
  196. {
  197. test_pcnt_quadrature_context_t *user_ctx = (test_pcnt_quadrature_context_t *)user_data;
  198. user_ctx->triggered_watch_values[user_ctx->index++] = event_data->watch_point_value;
  199. return false;
  200. }
  201. TEST_CASE("pcnt_quadrature_decode_event", "[pcnt]")
  202. {
  203. pcnt_unit_config_t unit_config = {
  204. .low_limit = -100,
  205. .high_limit = 100
  206. };
  207. printf("install pcnt unit\r\n");
  208. pcnt_unit_handle_t unit = NULL;
  209. TEST_ESP_OK(pcnt_new_unit(&unit_config, &unit));
  210. pcnt_glitch_filter_config_t filter_config = {
  211. .max_glitch_ns = 1000,
  212. };
  213. TEST_ESP_OK(pcnt_unit_set_glitch_filter(unit, &filter_config));
  214. printf("install two pcnt channels with different edge/level action\r\n");
  215. pcnt_chan_config_t channel_config = {
  216. .edge_gpio_num = TEST_PCNT_GPIO_A,
  217. .level_gpio_num = TEST_PCNT_GPIO_B,
  218. .flags.io_loop_back = true,
  219. };
  220. pcnt_channel_handle_t channelA = NULL;
  221. TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelA));
  222. TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_INCREASE));
  223. TEST_ESP_OK(pcnt_channel_set_level_action(channelA, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));
  224. // switch edge gpio and level gpio, the assign to another channel in the same unit
  225. pcnt_channel_handle_t channelB = NULL;
  226. channel_config.edge_gpio_num = TEST_PCNT_GPIO_B;
  227. channel_config.level_gpio_num = TEST_PCNT_GPIO_A;
  228. TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelB));
  229. TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_DECREASE));
  230. TEST_ESP_OK(pcnt_channel_set_level_action(channelB, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));
  231. // ensure the simulation signal in a stable state
  232. TEST_ESP_OK(gpio_set_level(TEST_PCNT_GPIO_A, 1));
  233. TEST_ESP_OK(gpio_set_level(TEST_PCNT_GPIO_B, 1));
  234. pcnt_event_callbacks_t cbs = {
  235. .on_reach = test_pcnt_quadrature_reach_watch_point,
  236. };
  237. test_pcnt_quadrature_context_t user_data = {
  238. .index = 0,
  239. .triggered_watch_values = {}
  240. };
  241. TEST_ESP_OK(pcnt_unit_register_event_callbacks(unit, &cbs, &user_data));
  242. printf("add watchpoints\r\n");
  243. TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 0));
  244. TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 100));
  245. TEST_ESP_OK(pcnt_unit_add_watch_point(unit, -100));
  246. TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 50));
  247. TEST_ESP_OK(pcnt_unit_add_watch_point(unit, -50));
  248. TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, pcnt_unit_add_watch_point(unit, 33));
  249. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_add_watch_point(unit, 50));
  250. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_add_watch_point(unit, 100));
  251. // Clear internal counter, and make the watch points take effect
  252. TEST_ESP_OK(pcnt_unit_clear_count(unit));
  253. // start unit should fail if it's not enabled yet
  254. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_start(unit));
  255. TEST_ESP_OK(pcnt_unit_enable(unit));
  256. TEST_ESP_OK(pcnt_unit_start(unit));
  257. printf("simulating quadrature signals\r\n");
  258. test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B, 30);
  259. // simply wait for done
  260. vTaskDelay(pdMS_TO_TICKS(100));
  261. int count_value;
  262. printf("checking count value\r\n");
  263. TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
  264. printf("count_value=%d\r\n", count_value);
  265. TEST_ASSERT_EQUAL(-20, count_value); // 0-30*4+100
  266. TEST_ASSERT_EQUAL(3, user_data.index);
  267. TEST_ASSERT_EQUAL(-50, user_data.triggered_watch_values[0]);
  268. TEST_ASSERT_EQUAL(-100, user_data.triggered_watch_values[1]);
  269. TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[2]);
  270. printf("simulating quadrature signals in another direction\r\n");
  271. user_data.index = 0;
  272. test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_B, TEST_PCNT_GPIO_A, 40);
  273. // simply wait for done
  274. vTaskDelay(pdMS_TO_TICKS(100));
  275. printf("checking count value\r\n");
  276. TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
  277. printf("count_value=%d\r\n", count_value);
  278. TEST_ASSERT_EQUAL(40, count_value); // -20+40*4-100
  279. TEST_ASSERT_EQUAL(4, user_data.index);
  280. TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[0]);
  281. TEST_ASSERT_EQUAL(50, user_data.triggered_watch_values[1]);
  282. TEST_ASSERT_EQUAL(100, user_data.triggered_watch_values[2]);
  283. TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[3]);
  284. printf("remove watchpoints and uninstall channels\r\n");
  285. TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, 0));
  286. TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, 100));
  287. TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, -100));
  288. TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, 50));
  289. TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, -50));
  290. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_remove_watch_point(unit, 50));
  291. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_remove_watch_point(unit, 33));
  292. TEST_ESP_OK(pcnt_del_channel(channelA));
  293. TEST_ESP_OK(pcnt_del_channel(channelB));
  294. TEST_ESP_OK(pcnt_unit_stop(unit));
  295. TEST_ESP_OK(pcnt_unit_disable(unit));
  296. TEST_ESP_OK(pcnt_del_unit(unit));
  297. }
  298. typedef struct {
  299. pcnt_unit_zero_cross_mode_t mode;
  300. } test_pcnt_zero_cross_context_t;
  301. TEST_PCNT_CALLBACK_ATTR
  302. static bool test_pcnt_on_zero_cross(pcnt_unit_handle_t handle, const pcnt_watch_event_data_t *event_data, void *user_data)
  303. {
  304. test_pcnt_zero_cross_context_t *user_ctx = (test_pcnt_zero_cross_context_t *)user_data;
  305. user_ctx->mode = event_data->zero_cross_mode;
  306. return false;
  307. }
  308. TEST_CASE("pcnt_zero_cross_mode", "[pcnt]")
  309. {
  310. pcnt_unit_config_t unit_config = {
  311. .low_limit = -100,
  312. .high_limit = 100
  313. };
  314. printf("install pcnt unit\r\n");
  315. pcnt_unit_handle_t unit = NULL;
  316. TEST_ESP_OK(pcnt_new_unit(&unit_config, &unit));
  317. printf("add watchpoint to detect zero cross\r\n");
  318. TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 0));
  319. printf("register callback for zero cross event\r\n");
  320. pcnt_event_callbacks_t cbs = {
  321. .on_reach = test_pcnt_on_zero_cross,
  322. };
  323. test_pcnt_zero_cross_context_t user_data = {};
  324. TEST_ESP_OK(pcnt_unit_register_event_callbacks(unit, &cbs, &user_data));
  325. printf("install pcnt channels\r\n");
  326. pcnt_chan_config_t channel_config = {
  327. .edge_gpio_num = TEST_PCNT_GPIO_A,
  328. .level_gpio_num = -1,
  329. .flags.io_loop_back = true,
  330. };
  331. pcnt_channel_handle_t channelA = NULL;
  332. pcnt_channel_handle_t channelB = NULL;
  333. TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelA));
  334. TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelB));
  335. printf("Initialize pcnt actions for channels\r\n");
  336. // only channel will increase the counter, 0->1
  337. TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  338. TEST_ESP_OK(pcnt_channel_set_level_action(channelA, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
  339. TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  340. TEST_ESP_OK(pcnt_channel_set_level_action(channelB, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
  341. printf("enable unit\r\n");
  342. TEST_ESP_OK(pcnt_unit_enable(unit));
  343. printf("start unit\r\n");
  344. TEST_ESP_OK(pcnt_unit_start(unit));
  345. int count_value = 0;
  346. printf("counter goes 0->1\r\n");
  347. TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  348. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 1);
  349. TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
  350. TEST_ASSERT_EQUAL(1, count_value);
  351. printf("counter goes 1->-1\r\n");
  352. TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  353. TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  354. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 1);
  355. TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
  356. TEST_ASSERT_EQUAL(-1, count_value);
  357. TEST_ASSERT_EQUAL(PCNT_UNIT_ZERO_CROSS_POS_NEG, user_data.mode);
  358. printf("counter goes -1->1\r\n");
  359. TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  360. TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  361. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 1);
  362. TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
  363. TEST_ASSERT_EQUAL(1, count_value);
  364. TEST_ASSERT_EQUAL(PCNT_UNIT_ZERO_CROSS_NEG_POS, user_data.mode);
  365. printf("counter goes 1->0->-1\r\n");
  366. TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  367. TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  368. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 2);
  369. TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
  370. TEST_ASSERT_EQUAL(-1, count_value);
  371. TEST_ASSERT_EQUAL(PCNT_UNIT_ZERO_CROSS_POS_ZERO, user_data.mode);
  372. printf("counter goes -1->0->1\r\n");
  373. TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  374. TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  375. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 2);
  376. TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
  377. TEST_ASSERT_EQUAL(1, count_value);
  378. TEST_ASSERT_EQUAL(PCNT_UNIT_ZERO_CROSS_NEG_ZERO, user_data.mode);
  379. TEST_ESP_OK(pcnt_unit_stop(unit));
  380. TEST_ESP_OK(pcnt_unit_disable(unit));
  381. TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, 0));
  382. TEST_ESP_OK(pcnt_del_channel(channelA));
  383. TEST_ESP_OK(pcnt_del_channel(channelB));
  384. TEST_ESP_OK(pcnt_del_unit(unit));
  385. }
  386. TEST_CASE("pcnt_virtual_io", "[pcnt]")
  387. {
  388. pcnt_unit_config_t unit_config = {
  389. .low_limit = -100,
  390. .high_limit = 100,
  391. };
  392. pcnt_chan_config_t chan_config = {
  393. .edge_gpio_num = TEST_PCNT_GPIO_A, // only detect edge signal in this case
  394. .level_gpio_num = -1, // level signal is connected to a virtual IO internally
  395. .flags.io_loop_back = true,
  396. .flags.virt_level_io_level = 1, // the level input is connected to high level, internally
  397. };
  398. pcnt_unit_handle_t unit = NULL;
  399. pcnt_channel_handle_t chan = NULL;
  400. printf("install pcnt unit\r\n");
  401. TEST_ESP_OK(pcnt_new_unit(&unit_config, &unit));
  402. printf("install pcnt channel\r\n");
  403. TEST_ESP_OK(pcnt_new_channel(unit, &chan_config, &chan));
  404. TEST_ESP_OK(pcnt_channel_set_edge_action(chan, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
  405. TEST_ESP_OK(pcnt_channel_set_level_action(chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
  406. TEST_ESP_OK(pcnt_unit_enable(unit));
  407. int count_value = 0;
  408. printf("start units\r\n");
  409. // start unit
  410. TEST_ESP_OK(pcnt_unit_start(unit));
  411. // trigger 10 rising edge on GPIO
  412. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
  413. TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
  414. TEST_ASSERT_EQUAL(10, count_value);
  415. printf("update level action\r\n");
  416. // the counter will hold-on (i.e. freeze) if the level input is high level (which is obviously yes in this case)
  417. TEST_ESP_OK(pcnt_channel_set_level_action(chan, PCNT_CHANNEL_LEVEL_ACTION_HOLD, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
  418. TEST_ESP_OK(pcnt_unit_clear_count(unit));
  419. // trigger 10 rising edge on GPIO
  420. test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
  421. TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
  422. // the count value should still be zero, because the level signal is high level, and the high level action is to hold-on the count value
  423. TEST_ASSERT_EQUAL(0, count_value);
  424. TEST_ESP_OK(pcnt_unit_stop(unit));
  425. TEST_ESP_OK(pcnt_unit_disable(unit));
  426. TEST_ESP_OK(pcnt_del_channel(chan));
  427. TEST_ESP_OK(pcnt_del_unit(unit));
  428. }