mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-04 04:19:39 +00:00
feat(pcnt): support step_notify on esp32h2 eco5
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_attr.h"
|
||||
#include "test_pulse_cnt_board.h"
|
||||
#include "hal/pcnt_ll.h"
|
||||
|
||||
TEST_CASE("pcnt_unit_install_uninstall", "[pcnt]")
|
||||
{
|
||||
@@ -677,145 +678,148 @@ TEST_CASE("pcnt overflow accumulation", "[pcnt]")
|
||||
#if SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
TEST_CASE("pcnt_step_notify_event", "[pcnt]")
|
||||
{
|
||||
test_gpio_init_for_simulation(TEST_PCNT_GPIO_A);
|
||||
test_gpio_init_for_simulation(TEST_PCNT_GPIO_B);
|
||||
if (pcnt_ll_is_step_notify_supported(0)) { // for ESP32H2, only support in chip version v1.2 and above
|
||||
test_gpio_init_for_simulation(TEST_PCNT_GPIO_A);
|
||||
test_gpio_init_for_simulation(TEST_PCNT_GPIO_B);
|
||||
|
||||
pcnt_unit_config_t unit_config = {
|
||||
.low_limit = -100,
|
||||
.high_limit = 100,
|
||||
.flags = {
|
||||
.en_step_notify_down = true,
|
||||
},
|
||||
};
|
||||
pcnt_unit_config_t unit_config = {
|
||||
.low_limit = -100,
|
||||
.high_limit = 100,
|
||||
.flags = {
|
||||
.en_step_notify_down = true,
|
||||
},
|
||||
};
|
||||
|
||||
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 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,
|
||||
};
|
||||
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));
|
||||
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,
|
||||
};
|
||||
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));
|
||||
// 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 = {0},
|
||||
};
|
||||
TEST_ESP_OK(pcnt_unit_register_event_callbacks(unit, &cbs, &user_data));
|
||||
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 = {0},
|
||||
};
|
||||
TEST_ESP_OK(pcnt_unit_register_event_callbacks(unit, &cbs, &user_data));
|
||||
|
||||
printf("add watch step and point\r\n");
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, 0));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, 20));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, -120));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_step(unit, -25));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_add_watch_step(unit, -100));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, -100));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 0));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, -50));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 11));
|
||||
printf("add watch step and point\r\n");
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, 0));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, 20));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, -120));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_step(unit, -25));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_add_watch_step(unit, -100));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, -100));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 0));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, -50));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 11));
|
||||
|
||||
TEST_ESP_OK(pcnt_unit_enable(unit));
|
||||
TEST_ESP_OK(pcnt_unit_start(unit));
|
||||
TEST_ESP_OK(pcnt_unit_enable(unit));
|
||||
TEST_ESP_OK(pcnt_unit_start(unit));
|
||||
|
||||
printf("simulating quadrature signals and count down\r\n");
|
||||
test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B, 25); // 25*(-4) = -100 -> 0
|
||||
printf("simulating quadrature signals and count down\r\n");
|
||||
test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B, 25); // 25*(-4) = -100 -> 0
|
||||
|
||||
int count_value;
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
|
||||
printf("counter stopped at %d\r\n", count_value);
|
||||
int count_value;
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
|
||||
printf("counter stopped at %d\r\n", count_value);
|
||||
|
||||
for (int i = 0 ; i < user_data.index; i++) {
|
||||
printf("%d:%d\r\n", i, user_data.triggered_watch_values[i]);
|
||||
for (int i = 0 ; i < user_data.index; i++) {
|
||||
printf("%d:%d\r\n", i, user_data.triggered_watch_values[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(0, count_value);
|
||||
TEST_ASSERT_EQUAL(5, user_data.index);
|
||||
TEST_ASSERT_EQUAL(-25, user_data.triggered_watch_values[0]); // step point (-25*1)
|
||||
TEST_ASSERT_EQUAL(-50, user_data.triggered_watch_values[1]); // step point && watch point
|
||||
TEST_ASSERT_EQUAL(-75, user_data.triggered_watch_values[2]); // step point (-25*3)
|
||||
TEST_ASSERT_EQUAL(-100, user_data.triggered_watch_values[3]);// step point && watch point
|
||||
TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[4]); // watch point (overflow zero cross)
|
||||
|
||||
printf("simulating quadrature signals and count up\r\n");
|
||||
user_data.index = 0;
|
||||
test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_B, TEST_PCNT_GPIO_A, 3); // 0+3*4 = 12
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
|
||||
printf("counter stopped at %d\r\n", count_value);
|
||||
for (int i = 0 ; i < user_data.index; i++) {
|
||||
printf("%d:%d\r\n", i, user_data.triggered_watch_values[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(12, count_value);
|
||||
TEST_ASSERT_EQUAL(1, user_data.index);
|
||||
TEST_ASSERT_EQUAL(11, user_data.triggered_watch_values[0]); // watch point
|
||||
|
||||
printf("simulating quadrature signals and count down again\r\n");
|
||||
user_data.index = 0;
|
||||
test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B, 13); // 12-13*4 = -40
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
|
||||
printf("counter stopped at %d\r\n", count_value);
|
||||
for (int i = 0 ; i < user_data.index; i++) {
|
||||
printf("%d:%d\r\n", i, user_data.triggered_watch_values[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(-40, count_value);
|
||||
TEST_ASSERT_EQUAL(3, user_data.index);
|
||||
TEST_ASSERT_EQUAL(11, user_data.triggered_watch_values[0]); // watch point
|
||||
TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[1]); // watch point (zero cross)
|
||||
TEST_ASSERT_EQUAL(-25, user_data.triggered_watch_values[2]);// step point (-25*1)
|
||||
|
||||
// before change step interval, the next step point should be -25-25=-50
|
||||
printf("change step interval\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_remove_watch_step(unit));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_step(unit, -20));
|
||||
// but after change, the next step point is -25-20=-45 (-25 is the last active step point)
|
||||
|
||||
printf("simulating quadrature signals and count down\r\n");
|
||||
user_data.index = 0;
|
||||
test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B, 20); // -40+20*(-4) = -120 -> -20
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
|
||||
printf("counter stopped at %d\r\n", count_value);
|
||||
|
||||
for (int i = 0 ; i < user_data.index; i++) {
|
||||
printf("%d:%d\r\n", i, user_data.triggered_watch_values[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(-20, count_value);
|
||||
TEST_ASSERT_EQUAL(7, user_data.index);
|
||||
TEST_ASSERT_EQUAL(-45, user_data.triggered_watch_values[0]); // watch step
|
||||
TEST_ASSERT_EQUAL(-50, user_data.triggered_watch_values[1]); // watch point
|
||||
TEST_ASSERT_EQUAL(-65, user_data.triggered_watch_values[2]); // step point (-45-20)
|
||||
TEST_ASSERT_EQUAL(-85, user_data.triggered_watch_values[3]); // step point (-65-20)
|
||||
TEST_ASSERT_EQUAL(-100, user_data.triggered_watch_values[4]);// step && watch point
|
||||
TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[5]); // watch point (overflow)
|
||||
TEST_ASSERT_EQUAL(-20, user_data.triggered_watch_values[6]); // step point (0-20)
|
||||
|
||||
printf("remove step_notify and uninstall channels\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_remove_watch_step(unit));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_remove_watch_step(unit));
|
||||
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));
|
||||
}
|
||||
TEST_ASSERT_EQUAL(0, count_value);
|
||||
TEST_ASSERT_EQUAL(5, user_data.index);
|
||||
TEST_ASSERT_EQUAL(-25, user_data.triggered_watch_values[0]); // step point (-25*1)
|
||||
TEST_ASSERT_EQUAL(-50, user_data.triggered_watch_values[1]); // step point && watch point
|
||||
TEST_ASSERT_EQUAL(-75, user_data.triggered_watch_values[2]); // step point (-25*3)
|
||||
TEST_ASSERT_EQUAL(-100, user_data.triggered_watch_values[3]);// step point && watch point
|
||||
TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[4]); // watch point (overflow zero cross)
|
||||
|
||||
printf("simulating quadrature signals and count up\r\n");
|
||||
user_data.index = 0;
|
||||
test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_B, TEST_PCNT_GPIO_A, 3); // 0+3*4 = 12
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
|
||||
printf("counter stopped at %d\r\n", count_value);
|
||||
for (int i = 0 ; i < user_data.index; i++) {
|
||||
printf("%d:%d\r\n", i, user_data.triggered_watch_values[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(12, count_value);
|
||||
TEST_ASSERT_EQUAL(1, user_data.index);
|
||||
TEST_ASSERT_EQUAL(11, user_data.triggered_watch_values[0]); // watch point
|
||||
|
||||
printf("simulating quadrature signals and count down again\r\n");
|
||||
user_data.index = 0;
|
||||
test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B, 13); // 12-13*4 = -40
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
|
||||
printf("counter stopped at %d\r\n", count_value);
|
||||
for (int i = 0 ; i < user_data.index; i++) {
|
||||
printf("%d:%d\r\n", i, user_data.triggered_watch_values[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(-40, count_value);
|
||||
TEST_ASSERT_EQUAL(3, user_data.index);
|
||||
TEST_ASSERT_EQUAL(11, user_data.triggered_watch_values[0]); // watch point
|
||||
TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[1]); // watch point (zero cross)
|
||||
TEST_ASSERT_EQUAL(-25, user_data.triggered_watch_values[2]);// step point (-25*1)
|
||||
|
||||
// before change step interval, the next step point should be -25-25=-50
|
||||
printf("change step interval\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_remove_watch_step(unit));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_step(unit, -20));
|
||||
// but after change, the next step point is -25-20=-45 (-25 is the last active step point)
|
||||
|
||||
printf("simulating quadrature signals and count down\r\n");
|
||||
user_data.index = 0;
|
||||
test_gpio_simulate_quadrature_signals(TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B, 20); // -40+20*(-4) = -120 -> -20
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
|
||||
printf("counter stopped at %d\r\n", count_value);
|
||||
|
||||
for (int i = 0 ; i < user_data.index; i++) {
|
||||
printf("%d:%d\r\n", i, user_data.triggered_watch_values[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(-20, count_value);
|
||||
TEST_ASSERT_EQUAL(7, user_data.index);
|
||||
TEST_ASSERT_EQUAL(-45, user_data.triggered_watch_values[0]); // watch step
|
||||
TEST_ASSERT_EQUAL(-50, user_data.triggered_watch_values[1]); // watch point
|
||||
TEST_ASSERT_EQUAL(-65, user_data.triggered_watch_values[2]); // step point (-45-20)
|
||||
TEST_ASSERT_EQUAL(-85, user_data.triggered_watch_values[3]); // step point (-65-20)
|
||||
TEST_ASSERT_EQUAL(-100, user_data.triggered_watch_values[4]);// step && watch point
|
||||
TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[5]); // watch point (overflow)
|
||||
TEST_ASSERT_EQUAL(-20, user_data.triggered_watch_values[6]); // step point (0-20)
|
||||
|
||||
printf("remove step_notify and uninstall channels\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_remove_watch_step(unit));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_remove_watch_step(unit));
|
||||
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));
|
||||
}
|
||||
#endif // SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
|
Reference in New Issue
Block a user