forked from espressif/esp-idf
feat(pcnt): re-support pcnt on ESP32-C5 V1.0
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -316,7 +316,7 @@ esp_err_t pcnt_unit_remove_watch_point(pcnt_unit_handle_t unit, int watch_point)
|
||||
* @brief Add a step notify for PCNT unit, PCNT will generate an event when the incremental(can be positive or negative) of counter value reaches the step interval
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @param[in] step_interval PCNT step notify interval value
|
||||
* @param[in] step_interval PCNT step notify interval value. Positive value means step forward, negative value means step backward.
|
||||
* @return
|
||||
* - ESP_OK: Add step notify successfully
|
||||
* - ESP_ERR_INVALID_ARG: Add step notify failed because of invalid argument (e.g. the value incremental to be watched is out of the limitation set in `pcnt_unit_config_t`)
|
||||
@ -326,7 +326,7 @@ esp_err_t pcnt_unit_remove_watch_point(pcnt_unit_handle_t unit, int watch_point)
|
||||
esp_err_t pcnt_unit_add_watch_step(pcnt_unit_handle_t unit, int step_interval);
|
||||
|
||||
/**
|
||||
* @brief Remove a step notify for PCNT unit
|
||||
* @brief Remove all step notify for PCNT unit
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @return
|
||||
@ -335,7 +335,25 @@ esp_err_t pcnt_unit_add_watch_step(pcnt_unit_handle_t unit, int step_interval);
|
||||
* - ESP_ERR_INVALID_STATE: Remove step notify failed because the step notify was not added by `pcnt_unit_add_watch_step()` yet
|
||||
* - ESP_FAIL: Remove step notify failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_unit_remove_watch_step(pcnt_unit_handle_t unit);
|
||||
esp_err_t pcnt_unit_remove_all_watch_step(pcnt_unit_handle_t unit);
|
||||
|
||||
/**
|
||||
* @brief Remove a step notify for PCNT unit
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @param[in] step_interval Step notify interval value
|
||||
* @return
|
||||
* - ESP_OK: Remove step notify successfully
|
||||
* - ESP_ERR_INVALID_ARG: Remove step notify failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Remove step notify failed because the step notify was not added by `pcnt_unit_add_watch_step()` yet
|
||||
* - ESP_FAIL: Remove step notify failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_unit_remove_single_watch_step(pcnt_unit_handle_t unit, int step_interval);
|
||||
|
||||
#define _pcnt_unit_remove_all_watch_step(unit) pcnt_unit_remove_all_watch_step(unit)
|
||||
#define _pcnt_unit_remove_single_watch_step(unit, step_interval) pcnt_unit_remove_single_watch_step(unit, step_interval)
|
||||
#define _pcnt_get_remove_func(_1, _2, FUNC, ...) FUNC
|
||||
#define pcnt_unit_remove_watch_step(...) _pcnt_get_remove_func(__VA_ARGS__, _pcnt_unit_remove_single_watch_step, _pcnt_unit_remove_all_watch_step)(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Create PCNT channel for specific unit, each PCNT has several channels associated with it
|
||||
|
@ -92,6 +92,16 @@ typedef struct {
|
||||
int watch_point_value; // value to be watched
|
||||
} pcnt_watch_point_t;
|
||||
|
||||
typedef struct {
|
||||
#if PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
int step_interval; // step interval
|
||||
int step_limit; // step limit value
|
||||
#else
|
||||
int step_interval_forward; // step interval for forward direction
|
||||
int step_interval_backward; // step interval for backward direction
|
||||
#endif
|
||||
} pcnt_step_interval_t;
|
||||
|
||||
typedef enum {
|
||||
PCNT_UNIT_FSM_INIT,
|
||||
PCNT_UNIT_FSM_ENABLE,
|
||||
@ -103,10 +113,9 @@ struct pcnt_unit_t {
|
||||
int unit_id; // allocated unit numerical ID
|
||||
int low_limit; // low limit value
|
||||
int high_limit; // high limit value
|
||||
int step_limit; // step limit value
|
||||
int clear_signal_gpio_num; // which gpio clear signal input
|
||||
int accum_value; // accumulated count value
|
||||
int step_interval; // PCNT step notify interval value
|
||||
pcnt_step_interval_t step_info; // step interval info
|
||||
pcnt_chan_t *channels[SOC_PCNT_CHANNELS_PER_UNIT]; // array of PCNT channels
|
||||
pcnt_watch_point_t watchers[PCNT_LL_WATCH_EVENT_MAX]; // array of PCNT watchers
|
||||
intr_handle_t intr; // interrupt handle
|
||||
@ -281,11 +290,11 @@ esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *re
|
||||
unit->flags.en_step_notify_up = config->flags.en_step_notify_up;
|
||||
#if PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
if (config->flags.en_step_notify_up) {
|
||||
unit->step_limit = config->high_limit;
|
||||
unit->step_info.step_limit = config->high_limit;
|
||||
} else if (config->flags.en_step_notify_down) {
|
||||
unit->step_limit = config->low_limit;
|
||||
unit->step_info.step_limit = config->low_limit;
|
||||
}
|
||||
pcnt_ll_set_step_limit_value(group->hal.dev, unit_id, unit->step_limit);
|
||||
pcnt_ll_set_step_limit_value(group->hal.dev, unit_id, unit->step_info.step_limit);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -679,11 +688,26 @@ esp_err_t pcnt_unit_add_watch_step(pcnt_unit_handle_t unit, int step_interval)
|
||||
ESP_ERR_INVALID_ARG, TAG, "invalid step interval");
|
||||
ESP_RETURN_ON_FALSE(step_interval >= unit->low_limit && step_interval <= unit->high_limit,
|
||||
ESP_ERR_INVALID_ARG, TAG, "step interval out of range [%d,%d]", unit->low_limit, unit->high_limit);
|
||||
ESP_RETURN_ON_FALSE(unit->step_interval == 0,
|
||||
ESP_ERR_INVALID_STATE, TAG, "watch step has been set to %d already", unit->step_interval);
|
||||
|
||||
unit->step_interval = step_interval;
|
||||
pcnt_ll_set_step_value(group->hal.dev, unit->unit_id, step_interval);
|
||||
#if PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
ESP_RETURN_ON_FALSE(unit->step_info.step_interval == 0,
|
||||
ESP_ERR_INVALID_STATE, TAG, "watch step has been set to %d already", unit->step_info.step_interval);
|
||||
pcnt_ll_set_step_value(group->hal.dev, unit->unit_id, step_interval > 0 ? PCNT_STEP_FORWARD : PCNT_STEP_BACKWARD, (uint16_t)step_interval);
|
||||
unit->step_info.step_interval = step_interval;
|
||||
#else
|
||||
if (step_interval > 0) {
|
||||
ESP_RETURN_ON_FALSE(unit->step_info.step_interval_forward == 0,
|
||||
ESP_ERR_INVALID_STATE, TAG, "watch step in forward has been set to %d already", unit->step_info.step_interval_forward);
|
||||
pcnt_ll_set_step_value(group->hal.dev, unit->unit_id, PCNT_STEP_FORWARD, (uint16_t)step_interval);
|
||||
unit->step_info.step_interval_forward = step_interval;
|
||||
} else {
|
||||
ESP_RETURN_ON_FALSE(unit->step_info.step_interval_backward == 0,
|
||||
ESP_ERR_INVALID_STATE, TAG, "watch step in backward has been set to %d already", unit->step_info.step_interval_backward);
|
||||
pcnt_ll_set_step_value(group->hal.dev, unit->unit_id, PCNT_STEP_BACKWARD, (uint16_t)step_interval);
|
||||
unit->step_info.step_interval_backward = step_interval;
|
||||
}
|
||||
#endif //PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
|
||||
// different units are mixing in the same register, so we use the group's spinlock here
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
pcnt_ll_enable_step_notify(group->hal.dev, unit->unit_id, true);
|
||||
@ -692,14 +716,20 @@ esp_err_t pcnt_unit_add_watch_step(pcnt_unit_handle_t unit, int step_interval)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_unit_remove_watch_step(pcnt_unit_handle_t unit)
|
||||
esp_err_t pcnt_unit_remove_all_watch_step(pcnt_unit_handle_t unit)
|
||||
{
|
||||
pcnt_group_t *group = NULL;
|
||||
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
group = unit->group;
|
||||
ESP_RETURN_ON_FALSE(unit->step_interval != 0, ESP_ERR_INVALID_STATE, TAG, "watch step not added yet");
|
||||
|
||||
unit->step_interval = 0;
|
||||
#if PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
ESP_RETURN_ON_FALSE(unit->step_info.step_interval != 0, ESP_ERR_INVALID_STATE, TAG, "watch step not added yet");
|
||||
unit->step_info.step_interval = 0;
|
||||
#else
|
||||
ESP_RETURN_ON_FALSE(unit->step_info.step_interval_forward != 0 || unit->step_info.step_interval_backward != 0,
|
||||
ESP_ERR_INVALID_STATE, TAG, "watch step in forward or backward not added yet");
|
||||
unit->step_info.step_interval_forward = 0;
|
||||
unit->step_info.step_interval_backward = 0;
|
||||
#endif
|
||||
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
pcnt_ll_enable_step_notify(group->hal.dev, unit->unit_id, false);
|
||||
@ -707,6 +737,36 @@ esp_err_t pcnt_unit_remove_watch_step(pcnt_unit_handle_t unit)
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_unit_remove_single_watch_step(pcnt_unit_handle_t unit, int step_interval)
|
||||
{
|
||||
pcnt_group_t *group = NULL;
|
||||
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
group = unit->group;
|
||||
#if PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
ESP_RETURN_ON_FALSE(unit->step_info.step_interval == step_interval, ESP_ERR_INVALID_STATE, TAG, "watch step %d not added yet", step_interval);
|
||||
unit->step_info.step_interval = 0;
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
pcnt_ll_enable_step_notify(group->hal.dev, unit->unit_id, false);
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
#else
|
||||
if (step_interval > 0) {
|
||||
ESP_RETURN_ON_FALSE(unit->step_info.step_interval_forward == step_interval, ESP_ERR_INVALID_STATE, TAG, "watch step %d not added yet", step_interval);
|
||||
pcnt_ll_set_step_value(group->hal.dev, unit->unit_id, PCNT_STEP_FORWARD, 0);
|
||||
unit->step_info.step_interval_forward = 0;
|
||||
} else {
|
||||
ESP_RETURN_ON_FALSE(unit->step_info.step_interval_backward == step_interval, ESP_ERR_INVALID_STATE, TAG, "watch step %d not added yet", step_interval);
|
||||
pcnt_ll_set_step_value(group->hal.dev, unit->unit_id, PCNT_STEP_BACKWARD, 0);
|
||||
unit->step_info.step_interval_backward = 0;
|
||||
}
|
||||
if (unit->step_info.step_interval_forward == 0 && unit->step_info.step_interval_backward == 0) {
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
pcnt_ll_enable_step_notify(group->hal.dev, unit->unit_id, false);
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
|
||||
esp_err_t pcnt_new_channel(pcnt_unit_handle_t unit, const pcnt_chan_config_t *config, pcnt_channel_handle_t *ret_chan)
|
||||
@ -962,6 +1022,7 @@ IRAM_ATTR static void pcnt_default_isr(void *args)
|
||||
// using while loop so that we don't miss any event
|
||||
while (event_status) {
|
||||
#if SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
#if PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
// step event has higher priority than pointer event
|
||||
if (event_status & (BIT(PCNT_LL_STEP_EVENT_REACH_INTERVAL) | BIT(PCNT_LL_STEP_EVENT_REACH_LIMIT))) {
|
||||
if (event_status & BIT(PCNT_LL_STEP_EVENT_REACH_INTERVAL)) {
|
||||
@ -972,13 +1033,27 @@ IRAM_ATTR static void pcnt_default_isr(void *args)
|
||||
if (event_status & BIT(PCNT_LL_STEP_EVENT_REACH_LIMIT)) {
|
||||
event_status &= ~BIT(PCNT_LL_STEP_EVENT_REACH_LIMIT);
|
||||
// adjust current count value to the step limit
|
||||
count_value = unit->step_limit;
|
||||
count_value = unit->step_info.step_limit;
|
||||
if (unit->flags.accum_count) {
|
||||
portENTER_CRITICAL_ISR(&unit->spinlock);
|
||||
unit->accum_value += unit->step_limit;
|
||||
unit->accum_value += unit->step_info.step_limit;
|
||||
portEXIT_CRITICAL_ISR(&unit->spinlock);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// step event has higher priority than pointer event
|
||||
if (event_status & (BIT(PCNT_LL_STEP_EVENT_REACH_INTERVAL_FORWARD) | BIT(PCNT_LL_STEP_EVENT_REACH_INTERVAL_BACKWARD))) {
|
||||
if (event_status & BIT(PCNT_LL_STEP_EVENT_REACH_INTERVAL_FORWARD)) {
|
||||
event_status &= ~BIT(PCNT_LL_STEP_EVENT_REACH_INTERVAL_FORWARD);
|
||||
// align current count value to the step interval
|
||||
count_value = pcnt_ll_get_count(group->hal.dev, unit_id);
|
||||
}
|
||||
if (event_status & BIT(PCNT_LL_STEP_EVENT_REACH_INTERVAL_BACKWARD)) {
|
||||
event_status &= ~BIT(PCNT_LL_STEP_EVENT_REACH_INTERVAL_BACKWARD);
|
||||
// align current count value to the step interval
|
||||
count_value = pcnt_ll_get_count(group->hal.dev, unit_id);
|
||||
}
|
||||
#endif // PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
// step event may happen with other pointer event at the same time, we don't need to process them again
|
||||
event_status &= ~(BIT(PCNT_LL_WATCH_EVENT_LOW_LIMIT) | BIT(PCNT_LL_WATCH_EVENT_HIGH_LIMIT) |
|
||||
BIT(PCNT_LL_WATCH_EVENT_THRES0) | BIT(PCNT_LL_WATCH_EVENT_THRES1));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -681,6 +681,9 @@ TEST_CASE("pcnt_step_notify_event", "[pcnt]")
|
||||
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);
|
||||
// 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_unit_config_t unit_config = {
|
||||
.low_limit = -100,
|
||||
@ -715,10 +718,6 @@ TEST_CASE("pcnt_step_notify_event", "[pcnt]")
|
||||
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,
|
||||
};
|
||||
@ -820,6 +819,141 @@ TEST_CASE("pcnt_step_notify_event", "[pcnt]")
|
||||
TEST_ESP_OK(pcnt_unit_disable(unit));
|
||||
TEST_ESP_OK(pcnt_del_unit(unit));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if !PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
TEST_CASE("pcnt_step_notify_event_bidirectional", "[pcnt]")
|
||||
{
|
||||
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);
|
||||
// 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_unit_config_t unit_config = {
|
||||
.low_limit = -100,
|
||||
.high_limit = 100,
|
||||
.flags = {
|
||||
.en_step_notify_down = true,
|
||||
.en_step_notify_up = 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 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));
|
||||
|
||||
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_ESP_OK(pcnt_unit_add_watch_step(unit, -25));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, -120));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_step(unit, 20));
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
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, 25); // 0+25*4 = 100 -> 0
|
||||
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(0, count_value);
|
||||
TEST_ASSERT_EQUAL(6, user_data.index);
|
||||
TEST_ASSERT_EQUAL(11, user_data.triggered_watch_values[0]); // watch point
|
||||
TEST_ASSERT_EQUAL(20, user_data.triggered_watch_values[1]); // step point (20*1)
|
||||
TEST_ASSERT_EQUAL(40, user_data.triggered_watch_values[2]); // step point (20*2)
|
||||
TEST_ASSERT_EQUAL(60, user_data.triggered_watch_values[3]); // step point (40+20*2)
|
||||
TEST_ASSERT_EQUAL(80, user_data.triggered_watch_values[4]); // step point (60+20*2)
|
||||
TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[5]); // watch point (overflow zero cross)
|
||||
|
||||
printf("change step interval\r\n");
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_remove_watch_step(unit, -20)); // -20 is not a step point
|
||||
TEST_ESP_OK(pcnt_unit_remove_watch_step(unit, -25));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_step(unit, -20));
|
||||
|
||||
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); // 20*(-4) = -80
|
||||
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(-80, count_value);
|
||||
TEST_ASSERT_EQUAL(5, user_data.index);
|
||||
TEST_ASSERT_EQUAL(-20, user_data.triggered_watch_values[0]); // step point (-20*1)
|
||||
TEST_ASSERT_EQUAL(-40, user_data.triggered_watch_values[1]); // step point (-20*2)
|
||||
TEST_ASSERT_EQUAL(-50, user_data.triggered_watch_values[2]); // watch point
|
||||
TEST_ASSERT_EQUAL(-60, user_data.triggered_watch_values[3]); // step point (-20*3)
|
||||
TEST_ASSERT_EQUAL(-80, user_data.triggered_watch_values[4]); // step point (-20*4)
|
||||
|
||||
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 //PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
#endif // SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -34,11 +34,10 @@ typedef enum {
|
||||
} pcnt_ll_watch_event_id_t;
|
||||
|
||||
typedef enum {
|
||||
PCNT_LL_STEP_EVENT_REACH_LIMIT = PCNT_LL_WATCH_EVENT_MAX,
|
||||
PCNT_LL_STEP_EVENT_REACH_INTERVAL
|
||||
PCNT_LL_STEP_EVENT_REACH_INTERVAL_FORWARD = PCNT_LL_WATCH_EVENT_MAX,
|
||||
PCNT_LL_STEP_EVENT_REACH_INTERVAL_BACKWARD,
|
||||
} pcnt_ll_step_event_id_t;
|
||||
|
||||
#define PCNT_LL_STEP_NOTIFY_DIR_LIMIT 1
|
||||
#define PCNT_LL_WATCH_EVENT_MASK ((1 << PCNT_LL_WATCH_EVENT_MAX) - 1)
|
||||
#define PCNT_LL_UNIT_WATCH_EVENT(unit_id) (1 << (unit_id))
|
||||
|
||||
@ -157,23 +156,16 @@ static inline void pcnt_ll_enable_step_notify(pcnt_dev_t *hw, uint32_t unit, boo
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param direction PCNT step direction
|
||||
* @param value PCNT step value
|
||||
*/
|
||||
static inline void pcnt_ll_set_step_value(pcnt_dev_t *hw, uint32_t unit, int value)
|
||||
static inline void pcnt_ll_set_step_value(pcnt_dev_t *hw, uint32_t unit, pcnt_step_direction_t direction, uint16_t value)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->change_conf_unit[3 - unit], cnt_step, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT step limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param value PCNT step limit value
|
||||
*/
|
||||
static inline void pcnt_ll_set_step_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->change_conf_unit[3 - unit], cnt_step_lim, value);
|
||||
if (direction == PCNT_STEP_FORWARD) {
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->conf_unit[unit].conf3, cnt_h_step_un, value);
|
||||
} else {
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->conf_unit[unit].conf3, cnt_l_step_un, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,10 +167,12 @@ static inline void pcnt_ll_enable_step_notify(pcnt_dev_t *hw, uint32_t unit, boo
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param direction PCNT step direction
|
||||
* @param value PCNT step value
|
||||
*/
|
||||
static inline void pcnt_ll_set_step_value(pcnt_dev_t *hw, uint32_t unit, int value)
|
||||
static inline void pcnt_ll_set_step_value(pcnt_dev_t *hw, uint32_t unit, pcnt_step_direction_t direction, int value)
|
||||
{
|
||||
(void)direction;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->change_conf_unit[3 - unit], cnt_step, value);
|
||||
}
|
||||
|
||||
|
@ -159,10 +159,12 @@ static inline void pcnt_ll_enable_step_notify(pcnt_dev_t *hw, uint32_t unit, boo
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param direction PCNT step direction
|
||||
* @param value PCNT step value
|
||||
*/
|
||||
static inline void pcnt_ll_set_step_value(pcnt_dev_t *hw, uint32_t unit, int value)
|
||||
static inline void pcnt_ll_set_step_value(pcnt_dev_t *hw, uint32_t unit, pcnt_step_direction_t direction, int value)
|
||||
{
|
||||
(void)direction;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->change_conf_unit[3 - unit], cnt_step, value);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -39,6 +39,14 @@ typedef enum {
|
||||
PCNT_UNIT_ZERO_CROSS_INVALID, /*!< invalid zero cross mode */
|
||||
} pcnt_unit_zero_cross_mode_t;
|
||||
|
||||
/**
|
||||
* @brief PCNT step direction
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_STEP_FORWARD, /*!< step forward, e.g., [N]->[N+1]->[N+2]->... */
|
||||
PCNT_STEP_BACKWARD, /*!< step backward, e.g., [N]->[N-1]->[N-2]->... */
|
||||
} pcnt_step_direction_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -12,14 +12,14 @@ extern "C" {
|
||||
|
||||
/** Group: Configuration Register */
|
||||
/** Type of un_conf0 register
|
||||
* Configuration register 0 for unit 0
|
||||
* Configuration register 0 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** filter_thres_un : R/W; bitpos: [9:0]; default: 16;
|
||||
* Configures the maximum threshold for the filter. Any pulses with width less than
|
||||
* this will be ignored when the filter is enabled. \\
|
||||
* Measurement unit: APB_CLK cycles.\\
|
||||
* this will be ignored when the filter is enabled.
|
||||
* Measurement unit: APB_CLK cycles.
|
||||
*/
|
||||
uint32_t filter_thres_un:10;
|
||||
/** filter_en_un : R/W; bitpos: [10]; default: 1;
|
||||
@ -49,67 +49,63 @@ typedef union {
|
||||
*/
|
||||
uint32_t thr_thres1_en_un:1;
|
||||
/** ch0_neg_mode_un : R/W; bitpos: [17:16]; default: 0;
|
||||
* Configures the behavior when the signal input of channel 0 detects a negative
|
||||
* edge.\\
|
||||
* 1: Increment the counter\\
|
||||
* 2: Decrement the counter\\
|
||||
* 0, 3: No effect \\
|
||||
* Configures the behavior when the signal input of channel 0 detects a negative edge.
|
||||
* 1: Increment the counter
|
||||
* 2: Decrement the counter
|
||||
* 0, 3: No effect
|
||||
*/
|
||||
uint32_t ch0_neg_mode_un:2;
|
||||
/** ch0_pos_mode_un : R/W; bitpos: [19:18]; default: 0;
|
||||
* Configures the behavior when the signal input of channel 0 detects a positive edge.
|
||||
* \\
|
||||
* 1: Increment the counter\\
|
||||
* 2: Decrement the counter\\
|
||||
* 0, 3: No effect \\
|
||||
* 1: Increment the counter
|
||||
* 2: Decrement the counter
|
||||
* 0, 3: No effect
|
||||
*/
|
||||
uint32_t ch0_pos_mode_un:2;
|
||||
/** ch0_hctrl_mode_un : R/W; bitpos: [21:20]; default: 0;
|
||||
* Configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be modified when the
|
||||
* control signal is high. \\
|
||||
* 0: No modification\\
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)\\
|
||||
* 2, 3: Inhibit counter modification \\
|
||||
* control signal is high.
|
||||
* 0: No modification
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)
|
||||
* 2, 3: Inhibit counter modification
|
||||
*/
|
||||
uint32_t ch0_hctrl_mode_un:2;
|
||||
/** ch0_lctrl_mode_un : R/W; bitpos: [23:22]; default: 0;
|
||||
* Configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be modified when the
|
||||
* control signal is low. \\
|
||||
* 0: No modification\\
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)\\
|
||||
* 2, 3: Inhibit counter modification\\
|
||||
* control signal is low.
|
||||
* 0: No modification
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)
|
||||
* 2, 3: Inhibit counter modification
|
||||
*/
|
||||
uint32_t ch0_lctrl_mode_un:2;
|
||||
/** ch1_neg_mode_un : R/W; bitpos: [25:24]; default: 0;
|
||||
* Configures the behavior when the signal input of channel 1 detects a negative edge.
|
||||
* \\
|
||||
* 1: Increment the counter\\
|
||||
* 2: Decrement the counter\\
|
||||
* 0, 3: No effect \\
|
||||
* 1: Increment the counter
|
||||
* 2: Decrement the counter
|
||||
* 0, 3: No effect
|
||||
*/
|
||||
uint32_t ch1_neg_mode_un:2;
|
||||
/** ch1_pos_mode_un : R/W; bitpos: [27:26]; default: 0;
|
||||
* Configures the behavior when the signal input of channel 1 detects a positive edge.
|
||||
* \\
|
||||
* 1: Increment the counter\\
|
||||
* 2: Decrement the counter\\
|
||||
* 0, 3: No effect \\
|
||||
* 1: Increment the counter
|
||||
* 2: Decrement the counter
|
||||
* 0, 3: No effect
|
||||
*/
|
||||
uint32_t ch1_pos_mode_un:2;
|
||||
/** ch1_hctrl_mode_un : R/W; bitpos: [29:28]; default: 0;
|
||||
* Configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be modified when the
|
||||
* control signal is high. \\
|
||||
* 0: No modification\\
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)\\
|
||||
* 2, 3: Inhibit counter modification \\
|
||||
* control signal is high.
|
||||
* 0: No modification
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)
|
||||
* 2, 3: Inhibit counter modification
|
||||
*/
|
||||
uint32_t ch1_hctrl_mode_un:2;
|
||||
/** ch1_lctrl_mode_un : R/W; bitpos: [31:30]; default: 0;
|
||||
* Configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be modified when the
|
||||
* control signal is low. \\
|
||||
* 0: No modification\\
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)\\
|
||||
* 2, 3: Inhibit counter modification \\
|
||||
* control signal is low.
|
||||
* 0: No modification
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)
|
||||
* 2, 3: Inhibit counter modification
|
||||
*/
|
||||
uint32_t ch1_lctrl_mode_un:2;
|
||||
};
|
||||
@ -117,7 +113,7 @@ typedef union {
|
||||
} pcnt_un_conf0_reg_t;
|
||||
|
||||
/** Type of un_conf1 register
|
||||
* Configuration register 1 for unit 0
|
||||
* Configuration register 1 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
@ -134,7 +130,7 @@ typedef union {
|
||||
} pcnt_un_conf1_reg_t;
|
||||
|
||||
/** Type of un_conf2 register
|
||||
* Configuration register 2 for unit 0
|
||||
* Configuration register 2 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
@ -152,6 +148,24 @@ typedef union {
|
||||
uint32_t val;
|
||||
} pcnt_un_conf2_reg_t;
|
||||
|
||||
/** Type of un_conf3 register
|
||||
* Configuration register for unit n's step value.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_h_step_un : R/W; bitpos: [15:0]; default: 0;
|
||||
* Configures the forward rotation step value for unit n.
|
||||
*/
|
||||
uint32_t cnt_h_step_un:16;
|
||||
/** cnt_l_step_un : R/W; bitpos: [31:16]; default: 0;
|
||||
* Configures the reverse rotation step value for unit n.
|
||||
*/
|
||||
uint32_t cnt_l_step_un:16;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_un_conf3_reg_t;
|
||||
|
||||
|
||||
/** Type of ctrl register
|
||||
* Control register for all counters
|
||||
*/
|
||||
@ -217,26 +231,10 @@ typedef union {
|
||||
uint32_t val;
|
||||
} pcnt_ctrl_reg_t;
|
||||
|
||||
/** Type of un_change_conf register
|
||||
* Configuration register for unit $n's step value.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_step : R/W; bitpos: [15:0]; default: 0;
|
||||
* Configures the step value for unit n.
|
||||
*/
|
||||
uint32_t cnt_step:16;
|
||||
/** cnt_step_lim_u3 : R/W; bitpos: [31:16]; default: 0;
|
||||
* Configures the step limit value for unit n.
|
||||
*/
|
||||
uint32_t cnt_step_lim:16;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_un_change_conf_reg_t;
|
||||
|
||||
/** Group: Status Register */
|
||||
/** Type of un_cnt register
|
||||
* Counter value for unit 0
|
||||
* Counter value for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
@ -250,65 +248,65 @@ typedef union {
|
||||
} pcnt_un_cnt_reg_t;
|
||||
|
||||
/** Type of un_status register
|
||||
* PNCT UNIT0 status register
|
||||
* PNCT UNITn status register
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_thr_zero_mode_un : RO; bitpos: [1:0]; default: 0;
|
||||
* Represents the pulse counter status of PCNT_Un corresponding to 0. \\
|
||||
* 0: pulse counter decreases from positive to 0\\
|
||||
* 1: pulse counter increases from negative to 0\\
|
||||
* 2: pulse counter is negative\\
|
||||
* 3: pulse counter is positive \\
|
||||
* Represents the pulse counter status of PCNT_Un corresponding to 0.
|
||||
* 0: pulse counter decreases from positive to 0
|
||||
* 1: pulse counter increases from negative to 0
|
||||
* 2: pulse counter is negative
|
||||
* 3: pulse counter is positive
|
||||
*/
|
||||
uint32_t cnt_thr_zero_mode_un:2;
|
||||
/** cnt_thr_thres1_lat_un : RO; bitpos: [2]; default: 0;
|
||||
* Represents the latched value of thres1 event of PCNT_Un when threshold event
|
||||
* interrupt is valid. \\
|
||||
* 0: others\\
|
||||
* 1: the current pulse counter equals to thres1 and thres1 event is valid \\
|
||||
* interrupt is valid.
|
||||
* 0: others
|
||||
* 1: the current pulse counter equals to thres1 and thres1 event is valid
|
||||
*/
|
||||
uint32_t cnt_thr_thres1_lat_un:1;
|
||||
/** cnt_thr_thres0_lat_un : RO; bitpos: [3]; default: 0;
|
||||
* Represents the latched value of thres0 event of PCNT_Un when threshold event
|
||||
* interrupt is valid. \\
|
||||
* 0: others\\
|
||||
* 1: the current pulse counter equals to thres0 and thres0 event is valid \\
|
||||
* interrupt is valid.
|
||||
* 0: others
|
||||
* 1: the current pulse counter equals to thres0 and thres0 event is valid
|
||||
*/
|
||||
uint32_t cnt_thr_thres0_lat_un:1;
|
||||
/** cnt_thr_l_lim_lat_un : RO; bitpos: [4]; default: 0;
|
||||
* Represents the latched value of low limit event of PCNT_Un when threshold event
|
||||
* interrupt is valid. \\
|
||||
* 0: others\\
|
||||
* 1: the current pulse counter equals to thr_l_lim and low limit event is valid. \\
|
||||
* interrupt is valid.
|
||||
* 0: others
|
||||
* 1: the current pulse counter equals to thr_l_lim and low limit event is valid.
|
||||
*/
|
||||
uint32_t cnt_thr_l_lim_lat_un:1;
|
||||
/** cnt_thr_h_lim_lat_un : RO; bitpos: [5]; default: 0;
|
||||
* Represents the latched value of high limit event of PCNT_Un when threshold event
|
||||
* interrupt is valid. \\
|
||||
* 0: others\\
|
||||
* 1: the current pulse counter equals to thr_h_lim and high limit event is valid. \\
|
||||
* interrupt is valid.
|
||||
* 0: others
|
||||
* 1: the current pulse counter equals to thr_h_lim and high limit event is valid.
|
||||
*/
|
||||
uint32_t cnt_thr_h_lim_lat_un:1;
|
||||
/** cnt_thr_zero_lat_un : RO; bitpos: [6]; default: 0;
|
||||
* Represents the latched value of zero threshold event of PCNT_Un when threshold
|
||||
* event interrupt is valid. \\
|
||||
* 0: others\\
|
||||
* 1: the current pulse counter equals to 0 and zero threshold event is valid. \\
|
||||
* event interrupt is valid.
|
||||
* 0: others
|
||||
* 1: the current pulse counter equals to 0 and zero threshold event is valid.
|
||||
*/
|
||||
uint32_t cnt_thr_zero_lat_un:1;
|
||||
/** cnt_thr_step_lim_lat_un : RO; bitpos: [7]; default: 0;
|
||||
* The latched value of step counter limit event of PCNT_Un when step counter event
|
||||
* interrupt is valid. 1: the current pulse counter equals to reg_cnt_step_lim and
|
||||
* step counter event is valid. 0: others
|
||||
/** cnt_thr_h_step_lat_un : RO; bitpos: [7]; default: 0;
|
||||
* Represents the latched value of step counter event of PCNT_Un when step counter
|
||||
* event interrupt is valid. 1: the current pulse counter decrement equals to
|
||||
* reg_cnt_step and step counter event is valid. 0: others
|
||||
*/
|
||||
uint32_t cnt_thr_step_lim_lat_un:1;
|
||||
/** cnt_thr_step_lat_un : RO; bitpos: [8]; default: 0;
|
||||
* The latched value of step counter event of PCNT_Un when step counter event
|
||||
* interrupt is valid. 1: the current pulse counter increment equals to reg_cnt_step
|
||||
* and step counter event is valid. 0: others
|
||||
uint32_t cnt_thr_h_step_lat_un:1;
|
||||
/** cnt_thr_l_step_lat_un : RO; bitpos: [8]; default: 0;
|
||||
* Represents the latched value of step counter event of PCNT_Un when step counter
|
||||
* event interrupt is valid. 1: the current pulse counter increment equals to
|
||||
* reg_cnt_step and step counter event is valid. 0: others
|
||||
*/
|
||||
uint32_t cnt_thr_step_lat_un:1;
|
||||
uint32_t cnt_thr_l_step_lat_un:1;
|
||||
uint32_t reserved_9:23;
|
||||
};
|
||||
uint32_t val;
|
||||
@ -427,7 +425,7 @@ typedef union {
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** date : R/W; bitpos: [31:0]; default: 36765968;
|
||||
/** date : R/W; bitpos: [31:0]; default: 37778192;
|
||||
* Version control register.
|
||||
*/
|
||||
uint32_t date:32;
|
||||
@ -441,6 +439,7 @@ typedef struct pcnt_dev_t {
|
||||
pcnt_un_conf0_reg_t conf0;
|
||||
pcnt_un_conf1_reg_t conf1;
|
||||
pcnt_un_conf2_reg_t conf2;
|
||||
pcnt_un_conf3_reg_t conf3;
|
||||
} conf_unit[4];
|
||||
volatile pcnt_un_cnt_reg_t cnt_unit[4];
|
||||
volatile pcnt_int_raw_reg_t int_raw;
|
||||
@ -449,7 +448,6 @@ typedef struct pcnt_dev_t {
|
||||
volatile pcnt_int_clr_reg_t int_clr;
|
||||
volatile pcnt_un_status_reg_t status_unit[4];
|
||||
volatile pcnt_ctrl_reg_t ctrl;
|
||||
volatile pcnt_un_change_conf_reg_t change_conf_unit[4]; // Note the unit order is 3210
|
||||
uint32_t reserved_074[34];
|
||||
volatile pcnt_date_reg_t date;
|
||||
} pcnt_dev_t;
|
||||
|
@ -1,523 +0,0 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Group: Configuration Register */
|
||||
/** Type of un_conf0 register
|
||||
* Configuration register 0 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** filter_thres_un : R/W; bitpos: [9:0]; default: 16;
|
||||
* Configures the maximum threshold for the filter. Any pulses with width less than
|
||||
* this will be ignored when the filter is enabled.
|
||||
* Measurement unit: APB_CLK cycles.
|
||||
*/
|
||||
uint32_t filter_thres_un:10;
|
||||
/** filter_en_un : R/W; bitpos: [10]; default: 1;
|
||||
* This is the enable bit for unit n's input filter.
|
||||
*/
|
||||
uint32_t filter_en_un:1;
|
||||
/** thr_zero_en_un : R/W; bitpos: [11]; default: 1;
|
||||
* This is the enable bit for unit n's zero comparator.
|
||||
*/
|
||||
uint32_t thr_zero_en_un:1;
|
||||
/** thr_h_lim_en_un : R/W; bitpos: [12]; default: 1;
|
||||
* This is the enable bit for unit n's thr_h_lim comparator. Configures it to enable
|
||||
* the high limit interrupt.
|
||||
*/
|
||||
uint32_t thr_h_lim_en_un:1;
|
||||
/** thr_l_lim_en_un : R/W; bitpos: [13]; default: 1;
|
||||
* This is the enable bit for unit n's thr_l_lim comparator. Configures it to enable
|
||||
* the low limit interrupt.
|
||||
*/
|
||||
uint32_t thr_l_lim_en_un:1;
|
||||
/** thr_thres0_en_un : R/W; bitpos: [14]; default: 0;
|
||||
* This is the enable bit for unit n's thres0 comparator.
|
||||
*/
|
||||
uint32_t thr_thres0_en_un:1;
|
||||
/** thr_thres1_en_un : R/W; bitpos: [15]; default: 0;
|
||||
* This is the enable bit for unit n's thres1 comparator.
|
||||
*/
|
||||
uint32_t thr_thres1_en_un:1;
|
||||
/** ch0_neg_mode_un : R/W; bitpos: [17:16]; default: 0;
|
||||
* Configures the behavior when the signal input of channel 0 detects a negative edge.
|
||||
* 1: Increment the counter
|
||||
* 2: Decrement the counter
|
||||
* 0, 3: No effect
|
||||
*/
|
||||
uint32_t ch0_neg_mode_un:2;
|
||||
/** ch0_pos_mode_un : R/W; bitpos: [19:18]; default: 0;
|
||||
* Configures the behavior when the signal input of channel 0 detects a positive edge.
|
||||
* 1: Increment the counter
|
||||
* 2: Decrement the counter
|
||||
* 0, 3: No effect
|
||||
*/
|
||||
uint32_t ch0_pos_mode_un:2;
|
||||
/** ch0_hctrl_mode_un : R/W; bitpos: [21:20]; default: 0;
|
||||
* Configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be modified when the
|
||||
* control signal is high.
|
||||
* 0: No modification
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)
|
||||
* 2, 3: Inhibit counter modification
|
||||
*/
|
||||
uint32_t ch0_hctrl_mode_un:2;
|
||||
/** ch0_lctrl_mode_un : R/W; bitpos: [23:22]; default: 0;
|
||||
* Configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be modified when the
|
||||
* control signal is low.
|
||||
* 0: No modification
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)
|
||||
* 2, 3: Inhibit counter modification
|
||||
*/
|
||||
uint32_t ch0_lctrl_mode_un:2;
|
||||
/** ch1_neg_mode_un : R/W; bitpos: [25:24]; default: 0;
|
||||
* Configures the behavior when the signal input of channel 1 detects a negative edge.
|
||||
* 1: Increment the counter
|
||||
* 2: Decrement the counter
|
||||
* 0, 3: No effect
|
||||
*/
|
||||
uint32_t ch1_neg_mode_un:2;
|
||||
/** ch1_pos_mode_un : R/W; bitpos: [27:26]; default: 0;
|
||||
* Configures the behavior when the signal input of channel 1 detects a positive edge.
|
||||
* 1: Increment the counter
|
||||
* 2: Decrement the counter
|
||||
* 0, 3: No effect
|
||||
*/
|
||||
uint32_t ch1_pos_mode_un:2;
|
||||
/** ch1_hctrl_mode_un : R/W; bitpos: [29:28]; default: 0;
|
||||
* Configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be modified when the
|
||||
* control signal is high.
|
||||
* 0: No modification
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)
|
||||
* 2, 3: Inhibit counter modification
|
||||
*/
|
||||
uint32_t ch1_hctrl_mode_un:2;
|
||||
/** ch1_lctrl_mode_un : R/W; bitpos: [31:30]; default: 0;
|
||||
* Configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be modified when the
|
||||
* control signal is low.
|
||||
* 0: No modification
|
||||
* 1: Invert behavior (increase -> decrease, decrease -> increase)
|
||||
* 2, 3: Inhibit counter modification
|
||||
*/
|
||||
uint32_t ch1_lctrl_mode_un:2;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_un_conf0_reg_t;
|
||||
|
||||
/** Type of un_conf1 register
|
||||
* Configuration register 1 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_thres0_un : R/W; bitpos: [15:0]; default: 0;
|
||||
* Configures the thres0 value for unit n.
|
||||
*/
|
||||
uint32_t cnt_thres0_un:16;
|
||||
/** cnt_thres1_un : R/W; bitpos: [31:16]; default: 0;
|
||||
* Configures the thres1 value for unit n.
|
||||
*/
|
||||
uint32_t cnt_thres1_un:16;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_un_conf1_reg_t;
|
||||
|
||||
/** Type of un_conf2 register
|
||||
* Configuration register 2 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_h_lim_un : R/W; bitpos: [15:0]; default: 0;
|
||||
* Configures the thr_h_lim value for unit n. When pulse_cnt reaches this value, the
|
||||
* counter will be cleared to 0.
|
||||
*/
|
||||
uint32_t cnt_h_lim_un:16;
|
||||
/** cnt_l_lim_un : R/W; bitpos: [31:16]; default: 0;
|
||||
* Configures the thr_l_lim value for unit n. When pulse_cnt reaches this value, the
|
||||
* counter will be cleared to 0.
|
||||
*/
|
||||
uint32_t cnt_l_lim_un:16;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_un_conf2_reg_t;
|
||||
|
||||
/** Type of u0_conf3 register
|
||||
* Configuration register for unit $n's step value.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_h_step_u0 : R/W; bitpos: [15:0]; default: 0;
|
||||
* Configures the forward rotation step value for unit 0.
|
||||
*/
|
||||
uint32_t cnt_h_step_u0:16;
|
||||
/** cnt_l_step_u0 : R/W; bitpos: [31:16]; default: 0;
|
||||
* Configures the reverse rotation step value for unit 0.
|
||||
*/
|
||||
uint32_t cnt_l_step_u0:16;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_u0_conf3_reg_t;
|
||||
|
||||
/** Type of u1_conf3 register
|
||||
* Configuration register for unit $n's step value.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_h_step_u1 : R/W; bitpos: [15:0]; default: 0;
|
||||
* Configures the forward rotation step value for unit 1.
|
||||
*/
|
||||
uint32_t cnt_h_step_u1:16;
|
||||
/** cnt_l_step_u1 : R/W; bitpos: [31:16]; default: 0;
|
||||
* Configures the reverse rotation step value for unit 1.
|
||||
*/
|
||||
uint32_t cnt_l_step_u1:16;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_u1_conf3_reg_t;
|
||||
|
||||
/** Type of u2_conf3 register
|
||||
* Configuration register for unit $n's step value.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_h_step_u2 : R/W; bitpos: [15:0]; default: 0;
|
||||
* Configures the forward rotation step value for unit 2.
|
||||
*/
|
||||
uint32_t cnt_h_step_u2:16;
|
||||
/** cnt_l_step_u2 : R/W; bitpos: [31:16]; default: 0;
|
||||
* Configures the reverse rotation step value for unit 2.
|
||||
*/
|
||||
uint32_t cnt_l_step_u2:16;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_u2_conf3_reg_t;
|
||||
|
||||
/** Type of u3_conf3 register
|
||||
* Configuration register for unit $n's step value.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_h_step_u3 : R/W; bitpos: [15:0]; default: 0;
|
||||
* Configures the forward rotation step value for unit 3.
|
||||
*/
|
||||
uint32_t cnt_h_step_u3:16;
|
||||
/** cnt_l_step_u3 : R/W; bitpos: [31:16]; default: 0;
|
||||
* Configures the reverse rotation step value for unit 3.
|
||||
*/
|
||||
uint32_t cnt_l_step_u3:16;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_u3_conf3_reg_t;
|
||||
|
||||
/** Type of ctrl register
|
||||
* Control register for all counters
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** pulse_cnt_rst_u0 : R/W; bitpos: [0]; default: 1;
|
||||
* Set this bit to clear unit 0's counter.
|
||||
*/
|
||||
uint32_t pulse_cnt_rst_u0:1;
|
||||
/** cnt_pause_u0 : R/W; bitpos: [1]; default: 0;
|
||||
* Set this bit to freeze unit 0's counter.
|
||||
*/
|
||||
uint32_t cnt_pause_u0:1;
|
||||
/** pulse_cnt_rst_u1 : R/W; bitpos: [2]; default: 1;
|
||||
* Set this bit to clear unit 1's counter.
|
||||
*/
|
||||
uint32_t pulse_cnt_rst_u1:1;
|
||||
/** cnt_pause_u1 : R/W; bitpos: [3]; default: 0;
|
||||
* Set this bit to freeze unit 1's counter.
|
||||
*/
|
||||
uint32_t cnt_pause_u1:1;
|
||||
/** pulse_cnt_rst_u2 : R/W; bitpos: [4]; default: 1;
|
||||
* Set this bit to clear unit 2's counter.
|
||||
*/
|
||||
uint32_t pulse_cnt_rst_u2:1;
|
||||
/** cnt_pause_u2 : R/W; bitpos: [5]; default: 0;
|
||||
* Set this bit to freeze unit 2's counter.
|
||||
*/
|
||||
uint32_t cnt_pause_u2:1;
|
||||
/** pulse_cnt_rst_u3 : R/W; bitpos: [6]; default: 1;
|
||||
* Set this bit to clear unit 3's counter.
|
||||
*/
|
||||
uint32_t pulse_cnt_rst_u3:1;
|
||||
/** cnt_pause_u3 : R/W; bitpos: [7]; default: 0;
|
||||
* Set this bit to freeze unit 3's counter.
|
||||
*/
|
||||
uint32_t cnt_pause_u3:1;
|
||||
/** dalta_change_en_u0 : R/W; bitpos: [8]; default: 0;
|
||||
* Configures this bit to enable unit 0's step comparator.
|
||||
*/
|
||||
uint32_t dalta_change_en_u0:1;
|
||||
/** dalta_change_en_u1 : R/W; bitpos: [9]; default: 0;
|
||||
* Configures this bit to enable unit 1's step comparator.
|
||||
*/
|
||||
uint32_t dalta_change_en_u1:1;
|
||||
/** dalta_change_en_u2 : R/W; bitpos: [10]; default: 0;
|
||||
* Configures this bit to enable unit 2's step comparator.
|
||||
*/
|
||||
uint32_t dalta_change_en_u2:1;
|
||||
/** dalta_change_en_u3 : R/W; bitpos: [11]; default: 0;
|
||||
* Configures this bit to enable unit 3's step comparator.
|
||||
*/
|
||||
uint32_t dalta_change_en_u3:1;
|
||||
uint32_t reserved_12:4;
|
||||
/** clk_en : R/W; bitpos: [16]; default: 0;
|
||||
* The registers clock gate enable signal of PCNT module. 1: the registers can be read
|
||||
* and written by application. 0: the registers can not be read or written by
|
||||
* application
|
||||
*/
|
||||
uint32_t clk_en:1;
|
||||
uint32_t reserved_17:15;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_ctrl_reg_t;
|
||||
|
||||
|
||||
/** Group: Status Register */
|
||||
/** Type of un_cnt register
|
||||
* Counter value for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** pulse_cnt_un : RO; bitpos: [15:0]; default: 0;
|
||||
* Represents the current pulse count value for unit n.
|
||||
*/
|
||||
uint32_t pulse_cnt_un:16;
|
||||
uint32_t reserved_16:16;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_un_cnt_reg_t;
|
||||
|
||||
/** Type of un_status register
|
||||
* PNCT UNITn status register
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_thr_zero_mode_un : RO; bitpos: [1:0]; default: 0;
|
||||
* Represents the pulse counter status of PCNT_Un corresponding to 0.
|
||||
* 0: pulse counter decreases from positive to 0
|
||||
* 1: pulse counter increases from negative to 0
|
||||
* 2: pulse counter is negative
|
||||
* 3: pulse counter is positive
|
||||
*/
|
||||
uint32_t cnt_thr_zero_mode_un:2;
|
||||
/** cnt_thr_thres1_lat_un : RO; bitpos: [2]; default: 0;
|
||||
* Represents the latched value of thres1 event of PCNT_Un when threshold event
|
||||
* interrupt is valid.
|
||||
* 0: others
|
||||
* 1: the current pulse counter equals to thres1 and thres1 event is valid
|
||||
*/
|
||||
uint32_t cnt_thr_thres1_lat_un:1;
|
||||
/** cnt_thr_thres0_lat_un : RO; bitpos: [3]; default: 0;
|
||||
* Represents the latched value of thres0 event of PCNT_Un when threshold event
|
||||
* interrupt is valid.
|
||||
* 0: others
|
||||
* 1: the current pulse counter equals to thres0 and thres0 event is valid
|
||||
*/
|
||||
uint32_t cnt_thr_thres0_lat_un:1;
|
||||
/** cnt_thr_l_lim_lat_un : RO; bitpos: [4]; default: 0;
|
||||
* Represents the latched value of low limit event of PCNT_Un when threshold event
|
||||
* interrupt is valid.
|
||||
* 0: others
|
||||
* 1: the current pulse counter equals to thr_l_lim and low limit event is valid.
|
||||
*/
|
||||
uint32_t cnt_thr_l_lim_lat_un:1;
|
||||
/** cnt_thr_h_lim_lat_un : RO; bitpos: [5]; default: 0;
|
||||
* Represents the latched value of high limit event of PCNT_Un when threshold event
|
||||
* interrupt is valid.
|
||||
* 0: others
|
||||
* 1: the current pulse counter equals to thr_h_lim and high limit event is valid.
|
||||
*/
|
||||
uint32_t cnt_thr_h_lim_lat_un:1;
|
||||
/** cnt_thr_zero_lat_un : RO; bitpos: [6]; default: 0;
|
||||
* Represents the latched value of zero threshold event of PCNT_Un when threshold
|
||||
* event interrupt is valid.
|
||||
* 0: others
|
||||
* 1: the current pulse counter equals to 0 and zero threshold event is valid.
|
||||
*/
|
||||
uint32_t cnt_thr_zero_lat_un:1;
|
||||
/** cnt_thr_h_step_lat_un : RO; bitpos: [7]; default: 0;
|
||||
* Represents the latched value of step counter event of PCNT_Un when step counter
|
||||
* event interrupt is valid. 1: the current pulse counter decrement equals to
|
||||
* reg_cnt_step and step counter event is valid. 0: others
|
||||
*/
|
||||
uint32_t cnt_thr_h_step_lat_un:1;
|
||||
/** cnt_thr_l_step_lat_un : RO; bitpos: [8]; default: 0;
|
||||
* Represents the latched value of step counter event of PCNT_Un when step counter
|
||||
* event interrupt is valid. 1: the current pulse counter increment equals to
|
||||
* reg_cnt_step and step counter event is valid. 0: others
|
||||
*/
|
||||
uint32_t cnt_thr_l_step_lat_un:1;
|
||||
uint32_t reserved_9:23;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_un_status_reg_t;
|
||||
|
||||
|
||||
/** Group: Interrupt Register */
|
||||
/** Type of int_raw register
|
||||
* Interrupt raw status register
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_thr_event_u0_int_raw : R/WTC/SS; bitpos: [0]; default: 0;
|
||||
* The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u0_int_raw:1;
|
||||
/** cnt_thr_event_u1_int_raw : R/WTC/SS; bitpos: [1]; default: 0;
|
||||
* The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u1_int_raw:1;
|
||||
/** cnt_thr_event_u2_int_raw : R/WTC/SS; bitpos: [2]; default: 0;
|
||||
* The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u2_int_raw:1;
|
||||
/** cnt_thr_event_u3_int_raw : R/WTC/SS; bitpos: [3]; default: 0;
|
||||
* The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u3_int_raw:1;
|
||||
uint32_t reserved_4:28;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_int_raw_reg_t;
|
||||
|
||||
/** Type of int_st register
|
||||
* Interrupt status register
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_thr_event_u0_int_st : RO; bitpos: [0]; default: 0;
|
||||
* The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u0_int_st:1;
|
||||
/** cnt_thr_event_u1_int_st : RO; bitpos: [1]; default: 0;
|
||||
* The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u1_int_st:1;
|
||||
/** cnt_thr_event_u2_int_st : RO; bitpos: [2]; default: 0;
|
||||
* The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u2_int_st:1;
|
||||
/** cnt_thr_event_u3_int_st : RO; bitpos: [3]; default: 0;
|
||||
* The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u3_int_st:1;
|
||||
uint32_t reserved_4:28;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_int_st_reg_t;
|
||||
|
||||
/** Type of int_ena register
|
||||
* Interrupt enable register
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_thr_event_u0_int_ena : R/W; bitpos: [0]; default: 0;
|
||||
* The interrupt enable bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u0_int_ena:1;
|
||||
/** cnt_thr_event_u1_int_ena : R/W; bitpos: [1]; default: 0;
|
||||
* The interrupt enable bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u1_int_ena:1;
|
||||
/** cnt_thr_event_u2_int_ena : R/W; bitpos: [2]; default: 0;
|
||||
* The interrupt enable bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u2_int_ena:1;
|
||||
/** cnt_thr_event_u3_int_ena : R/W; bitpos: [3]; default: 0;
|
||||
* The interrupt enable bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u3_int_ena:1;
|
||||
uint32_t reserved_4:28;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_int_ena_reg_t;
|
||||
|
||||
/** Type of int_clr register
|
||||
* Interrupt clear register
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** cnt_thr_event_u0_int_clr : WT; bitpos: [0]; default: 0;
|
||||
* Set this bit to clear the PCNT_CNT_THR_EVENT_U0_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u0_int_clr:1;
|
||||
/** cnt_thr_event_u1_int_clr : WT; bitpos: [1]; default: 0;
|
||||
* Set this bit to clear the PCNT_CNT_THR_EVENT_U1_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u1_int_clr:1;
|
||||
/** cnt_thr_event_u2_int_clr : WT; bitpos: [2]; default: 0;
|
||||
* Set this bit to clear the PCNT_CNT_THR_EVENT_U2_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u2_int_clr:1;
|
||||
/** cnt_thr_event_u3_int_clr : WT; bitpos: [3]; default: 0;
|
||||
* Set this bit to clear the PCNT_CNT_THR_EVENT_U3_INT interrupt.
|
||||
*/
|
||||
uint32_t cnt_thr_event_u3_int_clr:1;
|
||||
uint32_t reserved_4:28;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_int_clr_reg_t;
|
||||
|
||||
|
||||
/** Group: Version Register */
|
||||
/** Type of date register
|
||||
* PCNT version control register
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** date : R/W; bitpos: [31:0]; default: 37778192;
|
||||
* Version control register.
|
||||
*/
|
||||
uint32_t date:32;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_date_reg_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile pcnt_un_conf0_reg_t u0_conf0;
|
||||
volatile pcnt_un_conf1_reg_t u0_conf1;
|
||||
volatile pcnt_un_conf2_reg_t u0_conf2;
|
||||
volatile pcnt_u0_conf3_reg_t u0_conf3;
|
||||
volatile pcnt_un_conf0_reg_t u1_conf0;
|
||||
volatile pcnt_un_conf1_reg_t u1_conf1;
|
||||
volatile pcnt_un_conf2_reg_t u1_conf2;
|
||||
volatile pcnt_u1_conf3_reg_t u1_conf3;
|
||||
volatile pcnt_un_conf0_reg_t u2_conf0;
|
||||
volatile pcnt_un_conf1_reg_t u2_conf1;
|
||||
volatile pcnt_un_conf2_reg_t u2_conf2;
|
||||
volatile pcnt_u2_conf3_reg_t u2_conf3;
|
||||
volatile pcnt_un_conf0_reg_t u3_conf0;
|
||||
volatile pcnt_un_conf1_reg_t u3_conf1;
|
||||
volatile pcnt_un_conf2_reg_t u3_conf2;
|
||||
volatile pcnt_u3_conf3_reg_t u3_conf3;
|
||||
volatile pcnt_un_cnt_reg_t un_cnt[4];
|
||||
volatile pcnt_int_raw_reg_t int_raw;
|
||||
volatile pcnt_int_st_reg_t int_st;
|
||||
volatile pcnt_int_ena_reg_t int_ena;
|
||||
volatile pcnt_int_clr_reg_t int_clr;
|
||||
volatile pcnt_un_status_reg_t un_status[4];
|
||||
volatile pcnt_ctrl_reg_t ctrl;
|
||||
uint32_t reserved_074[34];
|
||||
volatile pcnt_date_reg_t date;
|
||||
} pcnt_dev_t;
|
||||
|
||||
extern pcnt_dev_t PCNT;
|
||||
|
||||
#ifndef __cplusplus
|
||||
_Static_assert(sizeof(pcnt_dev_t) == 0x100, "Invalid size of pcnt_dev_t structure");
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -158,7 +158,11 @@ It is recommended to remove the unused watch point by :cpp:func:`pcnt_unit_remov
|
||||
|
||||
PCNT unit can be configured to watch a specific value increment (can be positive or negative) that you are interested in. The function of watching value increment is also called **Watch Step**. To install watch step requires enabling :cpp:member:`pcnt_unit_config_t::en_step_notify_up` or :cpp:member:`pcnt_unit_config_t::en_step_notify_down`. The step interval itself can not exceed the range set in :cpp:type:`pcnt_unit_config_t` by :cpp:member:`pcnt_unit_config_t::low_limit` and :cpp:member:`pcnt_unit_config_t::high_limit`.When the counter increment reaches step interval, a watch event will be triggered and notify you by interrupt if any watch event callback has ever registered in :cpp:func:`pcnt_unit_register_event_callbacks`. See :ref:`pcnt-register-event-callbacks` for how to register event callbacks.
|
||||
|
||||
The watch step can be added and removed by :cpp:func:`pcnt_unit_add_watch_step` and :cpp:func:`pcnt_unit_remove_watch_step`. You can not add multiple watch step, otherwise it will return error :c:macro:`ESP_ERR_INVALID_STATE`。
|
||||
The watch step can be added and removed by :cpp:func:`pcnt_unit_add_watch_step` and :cpp:func:`pcnt_unit_remove_watch_step`. The parameter ``step_interval`` can be positive(step forward, e.g., [N]->[N+1]->[N+2]->...) or negative(step backward, e.g., [N]->[N-1]->[N-2]->...). The same direction can only add one watch step, otherwise it will return error :c:macro:`ESP_ERR_INVALID_STATE`.
|
||||
|
||||
.. note::
|
||||
|
||||
Due to hardware limitations, some chips may only support adding one direction of watch step. Please check the return value of :cpp:func:`pcnt_unit_add_watch_step` for more details.
|
||||
|
||||
It is recommended to remove the unused watch step by :cpp:func:`pcnt_unit_remove_watch_step` to recycle the watch step resources.
|
||||
|
||||
@ -318,8 +322,7 @@ The internal hardware counter will be cleared to zero automatically when it reac
|
||||
.. list::
|
||||
|
||||
1. Enable :cpp:member:`pcnt_unit_config_t::accum_count` when installing the PCNT unit.
|
||||
:SOC_PCNT_SUPPORT_STEP_NOTIFY: 2. Add the high/low limit as the :ref:`pcnt-watch-points` or add watch step as the :ref:`pcnt-step-notify`.
|
||||
:not SOC_PCNT_SUPPORT_STEP_NOTIFY: 2. Add the high/low limit as the :ref:`pcnt-watch-points`.
|
||||
2. Add the high/low limit as the :ref:`pcnt-watch-points`.
|
||||
3. Now, the returned count value from the :cpp:func:`pcnt_unit_get_count` function not only reflects the hardware's count value, but also accumulates the high/low overflow loss to it.
|
||||
|
||||
.. note::
|
||||
|
@ -158,7 +158,11 @@ PCNT 单元可被设置为观察几个特定的数值,这些被观察的数值
|
||||
|
||||
PCNT 单元可被设置为观察一个特定的数值增量(可以是正方向或负方向),这个观察数值增量的功能被称为 **观察步进**。启用观察步进需要使能 :cpp:member:`pcnt_unit_config_t::en_step_notify_up` 或 :cpp:member:`pcnt_unit_config_t::en_step_notify_down` 选项。 步进间隔不能超过 :cpp:type:`pcnt_unit_config_t` 设置的范围,最小值和最大值分别为 :cpp:member:`pcnt_unit_config_t::low_limit` 和 :cpp:member:`pcnt_unit_config_t::high_limit`。当计数器增量到达步进间隔时,会触发一个观察事件,如果在 :cpp:func:`pcnt_unit_register_event_callbacks` 注册过事件回调函数,该事件就会通过中断发送通知。关于如何注册事件回调函数,请参考 :ref:`pcnt-register-event-callbacks`。
|
||||
|
||||
观察步进分别可以通过 :cpp:func:`pcnt_unit_add_watch_step` 和 :cpp:func:`pcnt_unit_remove_watch_step` 进行添加和删除。不能同时添加多个观察步进,否则将返回错误 :c:macro:`ESP_ERR_INVALID_STATE`。
|
||||
观察步进分别可以通过 :cpp:func:`pcnt_unit_add_watch_step` 和 :cpp:func:`pcnt_unit_remove_watch_step` 进行添加和删除。参数 ``step_interval`` 的为正数表示正方向的步进(例如 [N]->[N+1]->[N+2]->...),为负数表示负方向的步进(例如 [N]->[N-1]->[N-2]->...)。同一个方向只能添加一个观察步进,否则将返回错误 :c:macro:`ESP_ERR_INVALID_STATE`。
|
||||
|
||||
.. note::
|
||||
|
||||
由于硬件上的限制,部分芯片可能只能支持添加一个方向的观察步进,请检查 :cpp:func:`pcnt_unit_add_watch_step` 的返回值。
|
||||
|
||||
建议通过 :cpp:func:`pcnt_unit_remove_watch_step` 删除未使用的观察步进来回收资源。
|
||||
|
||||
@ -318,8 +322,7 @@ PCNT 内部的硬件计数器会在计数达到高/低门限的时候自动清
|
||||
.. list::
|
||||
|
||||
1. 在安装 PCNT 计数单元的时候使能 :cpp:member:`pcnt_unit_config_t::accum_count` 选项。
|
||||
:SOC_PCNT_SUPPORT_STEP_NOTIFY: 2. 将高/低计数门限设置为 :ref:`pcnt-watch-points` 或添加观察步进 :ref:`pcnt-step-notify`
|
||||
:not SOC_PCNT_SUPPORT_STEP_NOTIFY: 2. 将高/低计数门限设置为 :ref:`pcnt-watch-points`。
|
||||
2. 将高/低计数门限设置为 :ref:`pcnt-watch-points`。
|
||||
3. 现在,:cpp:func:`pcnt_unit_get_count` 函数返回的计数值就会包含硬件计数器当前的计数值,累加上计数器溢出造成的损失。
|
||||
|
||||
.. note::
|
||||
|
Reference in New Issue
Block a user