| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 |
- /*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include <stdio.h>
- #include "sdkconfig.h"
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "unity.h"
- #include "driver/pulse_cnt.h"
- #include "driver/gpio.h"
- #include "soc/soc_caps.h"
- #include "esp_attr.h"
- #include "test_pulse_cnt_board.h"
- TEST_CASE("pcnt_unit_install_uninstall", "[pcnt]")
- {
- pcnt_unit_config_t unit_config = {
- .low_limit = -100,
- .high_limit = 100,
- };
- pcnt_unit_handle_t units[SOC_PCNT_UNITS_PER_GROUP];
- int count_value = 0;
- printf("install pcnt units and check initial count\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[i]));
- TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
- TEST_ASSERT_EQUAL(0, count_value);
- }
- // no more free pcnt units
- TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, pcnt_new_unit(&unit_config, &units[0]));
- printf("set glitch filter\r\n");
- pcnt_glitch_filter_config_t filter_config = {
- .max_glitch_ns = 1000,
- };
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- TEST_ESP_OK(pcnt_unit_set_glitch_filter(units[i], &filter_config));
- }
- // invalid glitch configuration
- filter_config.max_glitch_ns = 500000;
- TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_set_glitch_filter(units[0], &filter_config));
- printf("enable pcnt units\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- TEST_ESP_OK(pcnt_unit_enable(units[i]));
- }
- printf("start pcnt units\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- TEST_ESP_OK(pcnt_unit_start(units[i]));
- }
- printf("stop pcnt units\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- TEST_ESP_OK(pcnt_unit_stop(units[i]));
- }
- // can't uninstall unit before disable it
- TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_del_unit(units[0]));
- printf("disable pcnt units\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- TEST_ESP_OK(pcnt_unit_disable(units[i]));
- }
- printf("uninstall pcnt units\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- TEST_ESP_OK(pcnt_del_unit(units[i]));
- }
- }
- TEST_CASE("pcnt_channel_install_uninstall", "[pcnt]")
- {
- pcnt_unit_config_t unit_config = {
- .low_limit = -100,
- .high_limit = 100,
- };
- pcnt_chan_config_t chan_config = {
- .edge_gpio_num = TEST_PCNT_GPIO_A, // only detect edge signal in this case
- .level_gpio_num = -1,
- .flags.io_loop_back = true,
- };
- pcnt_unit_handle_t units[SOC_PCNT_UNITS_PER_GROUP];
- pcnt_channel_handle_t chans[SOC_PCNT_UNITS_PER_GROUP][SOC_PCNT_CHANNELS_PER_UNIT];
- printf("install pcnt units\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[i]));
- }
- printf("install pcnt channels\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- for (int j = 0; j < SOC_PCNT_CHANNELS_PER_UNIT; j++) {
- TEST_ESP_OK(pcnt_new_channel(units[i], &chan_config, &chans[i][j]));
- TEST_ESP_OK(pcnt_channel_set_edge_action(chans[i][j], PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- TEST_ESP_OK(pcnt_channel_set_level_action(chans[i][j], PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
- }
- TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, pcnt_new_channel(units[i], &chan_config, &chans[i][0]));
- TEST_ESP_OK(pcnt_unit_enable(units[i]));
- }
- printf("start units\r\n");
- int count_value = 0;
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- // start unit
- TEST_ESP_OK(pcnt_unit_start(units[i]));
- // trigger 10 rising edge on GPIO0
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
- TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
- // each channel increases to the same unit counter
- TEST_ASSERT_EQUAL(10 * SOC_PCNT_CHANNELS_PER_UNIT, count_value);
- }
- printf("clear counts\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- TEST_ESP_OK(pcnt_unit_clear_count(units[i]));
- TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
- TEST_ASSERT_EQUAL(0, count_value);
- }
- printf("stop unit\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- // stop unit
- TEST_ESP_OK(pcnt_unit_stop(units[i]));
- }
- // trigger 10 rising edge on GPIO0 shouldn't increase the counter
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
- TEST_ASSERT_EQUAL(0, count_value);
- }
- printf("restart units\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- // start unit
- TEST_ESP_OK(pcnt_unit_start(units[i]));
- // trigger 10 rising edge on GPIO
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
- TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
- // each channel increases to the same unit counter
- TEST_ASSERT_EQUAL(10 * SOC_PCNT_CHANNELS_PER_UNIT, count_value);
- }
- printf("uninstall channels and units\r\n");
- for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
- // stop unit
- TEST_ESP_OK(pcnt_unit_stop(units[i]));
- TEST_ESP_OK(pcnt_unit_disable(units[i]));
- // can't uninstall unit when channel is still alive
- TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_del_unit(units[i]));
- for (int j = 0; j < SOC_PCNT_CHANNELS_PER_UNIT; j++) {
- TEST_ESP_OK(pcnt_del_channel(chans[i][j]));
- }
- TEST_ESP_OK(pcnt_del_unit(units[i]));
- }
- }
- TEST_CASE("pcnt_multiple_units_pulse_count", "[pcnt]")
- {
- printf("install pcnt units\r\n");
- pcnt_unit_config_t unit_config = {
- .low_limit = -100,
- .high_limit = 100,
- };
- pcnt_unit_handle_t units[2];
- for (int i = 0; i < 2; i++) {
- TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[i]));
- }
- printf("install pcnt channels\r\n");
- const int channel_gpios[] = {TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B};
- pcnt_chan_config_t chan_config = {
- .level_gpio_num = -1,
- .flags.io_loop_back = true,
- };
- pcnt_channel_handle_t chans[2];
- for (int i = 0; i < 2; i++) {
- chan_config.edge_gpio_num = channel_gpios[i];
- TEST_ESP_OK(pcnt_new_channel(units[i], &chan_config, &chans[i]));
- TEST_ESP_OK(pcnt_channel_set_edge_action(chans[i], PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- TEST_ESP_OK(pcnt_channel_set_level_action(chans[i], PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
- }
- printf("enable and start unit\r\n");
- for (int i = 0; i < 2; i++) {
- TEST_ESP_OK(pcnt_unit_enable(units[i]));
- TEST_ESP_OK(pcnt_unit_start(units[i]));
- }
- // trigger 10 rising edge on GPIO
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_B, 10);
- int count_value = 0;
- for (int i = 0; i < 2; i++) {
- TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
- TEST_ASSERT_EQUAL(10, count_value);
- }
- for (int i = 0; i < 2; i++) {
- TEST_ESP_OK(pcnt_unit_stop(units[i]));
- TEST_ESP_OK(pcnt_unit_disable(units[i]));
- TEST_ESP_OK(pcnt_del_channel(chans[i]));
- TEST_ESP_OK(pcnt_del_unit(units[i]));
- }
- }
- /**
- * @brief Using this context to save the triggered watch-points in sequence
- */
- typedef struct {
- uint32_t index;
- int triggered_watch_values[8];
- } test_pcnt_quadrature_context_t;
- TEST_PCNT_CALLBACK_ATTR
- static bool test_pcnt_quadrature_reach_watch_point(pcnt_unit_handle_t handle, const pcnt_watch_event_data_t *event_data, void *user_data)
- {
- test_pcnt_quadrature_context_t *user_ctx = (test_pcnt_quadrature_context_t *)user_data;
- user_ctx->triggered_watch_values[user_ctx->index++] = event_data->watch_point_value;
- return false;
- }
- TEST_CASE("pcnt_quadrature_decode_event", "[pcnt]")
- {
- pcnt_unit_config_t unit_config = {
- .low_limit = -100,
- .high_limit = 100
- };
- printf("install pcnt unit\r\n");
- pcnt_unit_handle_t unit = NULL;
- TEST_ESP_OK(pcnt_new_unit(&unit_config, &unit));
- pcnt_glitch_filter_config_t filter_config = {
- .max_glitch_ns = 1000,
- };
- TEST_ESP_OK(pcnt_unit_set_glitch_filter(unit, &filter_config));
- printf("install two pcnt channels with different edge/level action\r\n");
- pcnt_chan_config_t channel_config = {
- .edge_gpio_num = TEST_PCNT_GPIO_A,
- .level_gpio_num = TEST_PCNT_GPIO_B,
- .flags.io_loop_back = true,
- };
- pcnt_channel_handle_t channelA = NULL;
- TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelA));
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_INCREASE));
- TEST_ESP_OK(pcnt_channel_set_level_action(channelA, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));
- // switch edge gpio and level gpio, the assign to another channel in the same unit
- pcnt_channel_handle_t channelB = NULL;
- channel_config.edge_gpio_num = TEST_PCNT_GPIO_B;
- channel_config.level_gpio_num = TEST_PCNT_GPIO_A;
- TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelB));
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_DECREASE));
- TEST_ESP_OK(pcnt_channel_set_level_action(channelB, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));
- // ensure the simulation signal in a stable state
- TEST_ESP_OK(gpio_set_level(TEST_PCNT_GPIO_A, 1));
- TEST_ESP_OK(gpio_set_level(TEST_PCNT_GPIO_B, 1));
- pcnt_event_callbacks_t cbs = {
- .on_reach = test_pcnt_quadrature_reach_watch_point,
- };
- test_pcnt_quadrature_context_t user_data = {
- .index = 0,
- .triggered_watch_values = {}
- };
- TEST_ESP_OK(pcnt_unit_register_event_callbacks(unit, &cbs, &user_data));
- printf("add watchpoints\r\n");
- TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 0));
- TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 100));
- TEST_ESP_OK(pcnt_unit_add_watch_point(unit, -100));
- TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 50));
- TEST_ESP_OK(pcnt_unit_add_watch_point(unit, -50));
- TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, pcnt_unit_add_watch_point(unit, 33));
- TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_add_watch_point(unit, 50));
- TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_add_watch_point(unit, 100));
- // Clear internal counter, and make the watch points take effect
- TEST_ESP_OK(pcnt_unit_clear_count(unit));
- // start unit should fail if it's not enabled yet
- TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_start(unit));
- TEST_ESP_OK(pcnt_unit_enable(unit));
- TEST_ESP_OK(pcnt_unit_start(unit));
- printf("simulating quadrature signals\r\n");
- test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B, 30);
- // simply wait for done
- vTaskDelay(pdMS_TO_TICKS(100));
- int count_value;
- printf("checking count value\r\n");
- TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
- printf("count_value=%d\r\n", count_value);
- TEST_ASSERT_EQUAL(-20, count_value); // 0-30*4+100
- TEST_ASSERT_EQUAL(3, user_data.index);
- TEST_ASSERT_EQUAL(-50, user_data.triggered_watch_values[0]);
- TEST_ASSERT_EQUAL(-100, user_data.triggered_watch_values[1]);
- TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[2]);
- printf("simulating quadrature signals in another direction\r\n");
- user_data.index = 0;
- test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_B, TEST_PCNT_GPIO_A, 40);
- // simply wait for done
- vTaskDelay(pdMS_TO_TICKS(100));
- printf("checking count value\r\n");
- TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
- printf("count_value=%d\r\n", count_value);
- TEST_ASSERT_EQUAL(40, count_value); // -20+40*4-100
- TEST_ASSERT_EQUAL(4, user_data.index);
- TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[0]);
- TEST_ASSERT_EQUAL(50, user_data.triggered_watch_values[1]);
- TEST_ASSERT_EQUAL(100, user_data.triggered_watch_values[2]);
- TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[3]);
- printf("remove watchpoints and uninstall channels\r\n");
- TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, 0));
- TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, 100));
- TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, -100));
- TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, 50));
- TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, -50));
- TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_remove_watch_point(unit, 50));
- TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_remove_watch_point(unit, 33));
- TEST_ESP_OK(pcnt_del_channel(channelA));
- TEST_ESP_OK(pcnt_del_channel(channelB));
- TEST_ESP_OK(pcnt_unit_stop(unit));
- TEST_ESP_OK(pcnt_unit_disable(unit));
- TEST_ESP_OK(pcnt_del_unit(unit));
- }
- typedef struct {
- pcnt_unit_zero_cross_mode_t mode;
- } test_pcnt_zero_cross_context_t;
- TEST_PCNT_CALLBACK_ATTR
- static bool test_pcnt_on_zero_cross(pcnt_unit_handle_t handle, const pcnt_watch_event_data_t *event_data, void *user_data)
- {
- test_pcnt_zero_cross_context_t *user_ctx = (test_pcnt_zero_cross_context_t *)user_data;
- user_ctx->mode = event_data->zero_cross_mode;
- return false;
- }
- TEST_CASE("pcnt_zero_cross_mode", "[pcnt]")
- {
- pcnt_unit_config_t unit_config = {
- .low_limit = -100,
- .high_limit = 100
- };
- printf("install pcnt unit\r\n");
- pcnt_unit_handle_t unit = NULL;
- TEST_ESP_OK(pcnt_new_unit(&unit_config, &unit));
- printf("add watchpoint to detect zero cross\r\n");
- TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 0));
- printf("register callback for zero cross event\r\n");
- pcnt_event_callbacks_t cbs = {
- .on_reach = test_pcnt_on_zero_cross,
- };
- test_pcnt_zero_cross_context_t user_data = {};
- TEST_ESP_OK(pcnt_unit_register_event_callbacks(unit, &cbs, &user_data));
- printf("install pcnt channels\r\n");
- pcnt_chan_config_t channel_config = {
- .edge_gpio_num = TEST_PCNT_GPIO_A,
- .level_gpio_num = -1,
- .flags.io_loop_back = true,
- };
- pcnt_channel_handle_t channelA = NULL;
- pcnt_channel_handle_t channelB = NULL;
- TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelA));
- TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelB));
- printf("Initialize pcnt actions for channels\r\n");
- // only channel will increase the counter, 0->1
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- TEST_ESP_OK(pcnt_channel_set_level_action(channelA, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- TEST_ESP_OK(pcnt_channel_set_level_action(channelB, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
- printf("enable unit\r\n");
- TEST_ESP_OK(pcnt_unit_enable(unit));
- printf("start unit\r\n");
- TEST_ESP_OK(pcnt_unit_start(unit));
- int count_value = 0;
- printf("counter goes 0->1\r\n");
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 1);
- TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
- TEST_ASSERT_EQUAL(1, count_value);
- printf("counter goes 1->-1\r\n");
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 1);
- TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
- TEST_ASSERT_EQUAL(-1, count_value);
- TEST_ASSERT_EQUAL(PCNT_UNIT_ZERO_CROSS_POS_NEG, user_data.mode);
- printf("counter goes -1->1\r\n");
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 1);
- TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
- TEST_ASSERT_EQUAL(1, count_value);
- TEST_ASSERT_EQUAL(PCNT_UNIT_ZERO_CROSS_NEG_POS, user_data.mode);
- printf("counter goes 1->0->-1\r\n");
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 2);
- TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
- TEST_ASSERT_EQUAL(-1, count_value);
- TEST_ASSERT_EQUAL(PCNT_UNIT_ZERO_CROSS_POS_ZERO, user_data.mode);
- printf("counter goes -1->0->1\r\n");
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- TEST_ESP_OK(pcnt_channel_set_edge_action(channelB, PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 2);
- TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
- TEST_ASSERT_EQUAL(1, count_value);
- TEST_ASSERT_EQUAL(PCNT_UNIT_ZERO_CROSS_NEG_ZERO, user_data.mode);
- TEST_ESP_OK(pcnt_unit_stop(unit));
- TEST_ESP_OK(pcnt_unit_disable(unit));
- TEST_ESP_OK(pcnt_unit_remove_watch_point(unit, 0));
- TEST_ESP_OK(pcnt_del_channel(channelA));
- TEST_ESP_OK(pcnt_del_channel(channelB));
- TEST_ESP_OK(pcnt_del_unit(unit));
- }
- TEST_CASE("pcnt_virtual_io", "[pcnt]")
- {
- pcnt_unit_config_t unit_config = {
- .low_limit = -100,
- .high_limit = 100,
- };
- pcnt_chan_config_t chan_config = {
- .edge_gpio_num = TEST_PCNT_GPIO_A, // only detect edge signal in this case
- .level_gpio_num = -1, // level signal is connected to a virtual IO internally
- .flags.io_loop_back = true,
- .flags.virt_level_io_level = 1, // the level input is connected to high level, internally
- };
- pcnt_unit_handle_t unit = NULL;
- pcnt_channel_handle_t chan = NULL;
- printf("install pcnt unit\r\n");
- TEST_ESP_OK(pcnt_new_unit(&unit_config, &unit));
- printf("install pcnt channel\r\n");
- TEST_ESP_OK(pcnt_new_channel(unit, &chan_config, &chan));
- TEST_ESP_OK(pcnt_channel_set_edge_action(chan, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
- TEST_ESP_OK(pcnt_channel_set_level_action(chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
- TEST_ESP_OK(pcnt_unit_enable(unit));
- int count_value = 0;
- printf("start units\r\n");
- // start unit
- TEST_ESP_OK(pcnt_unit_start(unit));
- // trigger 10 rising edge on GPIO
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
- TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
- TEST_ASSERT_EQUAL(10, count_value);
- printf("update level action\r\n");
- // the counter will hold-on (i.e. freeze) if the level input is high level (which is obviously yes in this case)
- TEST_ESP_OK(pcnt_channel_set_level_action(chan, PCNT_CHANNEL_LEVEL_ACTION_HOLD, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
- TEST_ESP_OK(pcnt_unit_clear_count(unit));
- // trigger 10 rising edge on GPIO
- test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
- TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
- // 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
- TEST_ASSERT_EQUAL(0, count_value);
- TEST_ESP_OK(pcnt_unit_stop(unit));
- TEST_ESP_OK(pcnt_unit_disable(unit));
- TEST_ESP_OK(pcnt_del_channel(chan));
- TEST_ESP_OK(pcnt_del_unit(unit));
- }
|