mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-08 15:14:33 +02:00
Merge branch 'refactor/pcnt_driver_esp32s3' into 'master'
pcnt: soc update and hal refactor See merge request espressif/esp-idf!14698
This commit is contained in:
@@ -6,20 +6,104 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/pcnt_types.h"
|
||||
#include "soc/pcnt_periph.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PCNT_PIN_NOT_USED (-1) /*!< When selected for a pin, this pin will not be used */
|
||||
|
||||
typedef intr_handle_t pcnt_isr_handle_t;
|
||||
|
||||
/**
|
||||
* @brief PCNT port number, the max port number is (PCNT_PORT_MAX - 1).
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_PORT_0, /*!< PCNT port 0 */
|
||||
PCNT_PORT_MAX, /*!< PCNT port max */
|
||||
} pcnt_port_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of all available PCNT units
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_UNIT_0, /*!< PCNT unit 0 */
|
||||
PCNT_UNIT_1, /*!< PCNT unit 1 */
|
||||
PCNT_UNIT_2, /*!< PCNT unit 2 */
|
||||
PCNT_UNIT_3, /*!< PCNT unit 3 */
|
||||
#if SOC_PCNT_UNITS_PER_GROUP > 4
|
||||
PCNT_UNIT_4, /*!< PCNT unit 4 */
|
||||
PCNT_UNIT_5, /*!< PCNT unit 5 */
|
||||
PCNT_UNIT_6, /*!< PCNT unit 6 */
|
||||
PCNT_UNIT_7, /*!< PCNT unit 7 */
|
||||
#endif
|
||||
PCNT_UNIT_MAX,
|
||||
} pcnt_unit_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of channels available for a single PCNT unit
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_CHANNEL_0, /*!< PCNT channel 0 */
|
||||
PCNT_CHANNEL_1, /*!< PCNT channel 1 */
|
||||
PCNT_CHANNEL_MAX,
|
||||
} pcnt_channel_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of counter's events the may trigger an interrupt
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_EVT_THRES_1 = 1 << 2, /*!< PCNT watch point event: threshold1 value event */
|
||||
PCNT_EVT_THRES_0 = 1 << 3, /*!< PCNT watch point event: threshold0 value event */
|
||||
PCNT_EVT_L_LIM = 1 << 4, /*!< PCNT watch point event: Minimum counter value */
|
||||
PCNT_EVT_H_LIM = 1 << 5, /*!< PCNT watch point event: Maximum counter value */
|
||||
PCNT_EVT_ZERO = 1 << 6, /*!< PCNT watch point event: counter value zero event */
|
||||
PCNT_EVT_MAX
|
||||
} pcnt_evt_type_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of available modes that determine the counter's action depending on the state of the control signal's input GPIO
|
||||
* @note Configuration covers two actions, one for high, and one for low level on the control input
|
||||
*/
|
||||
typedef pcnt_channel_level_action_t pcnt_ctrl_mode_t;
|
||||
#define PCNT_MODE_KEEP PCNT_CHANNEL_LEVEL_ACTION_KEEP /*!< Control mode: won't change counter mode*/
|
||||
#define PCNT_MODE_REVERSE PCNT_CHANNEL_LEVEL_ACTION_INVERSE /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase) */
|
||||
#define PCNT_MODE_DISABLE PCNT_CHANNEL_LEVEL_ACTION_HOLD /*!< Control mode: Inhibit counter(counter value will not change in this condition) */
|
||||
#define PCNT_MODE_MAX 3
|
||||
|
||||
/**
|
||||
* @brief Selection of available modes that determine the counter's action on the edge of the pulse signal's input GPIO
|
||||
* @note Configuration covers two actions, one for positive, and one for negative edge on the pulse input
|
||||
*/
|
||||
typedef pcnt_channel_edge_action_t pcnt_count_mode_t;
|
||||
#define PCNT_COUNT_DIS PCNT_CHANNEL_EDGE_ACTION_HOLD /*!< Counter mode: Inhibit counter(counter value will not change in this condition) */
|
||||
#define PCNT_COUNT_INC PCNT_CHANNEL_EDGE_ACTION_INCREASE /*!< Counter mode: Increase counter value */
|
||||
#define PCNT_COUNT_DEC PCNT_CHANNEL_EDGE_ACTION_DECREASE /*!< Counter mode: Decrease counter value */
|
||||
#define PCNT_COUNT_MAX 3
|
||||
|
||||
/**
|
||||
* @brief Pulse Counter configuration for a single channel
|
||||
*/
|
||||
typedef struct {
|
||||
int pulse_gpio_num; /*!< Pulse input GPIO number, if you want to use GPIO16, enter pulse_gpio_num = 16, a negative value will be ignored */
|
||||
int ctrl_gpio_num; /*!< Control signal input GPIO number, a negative value will be ignored */
|
||||
pcnt_ctrl_mode_t lctrl_mode; /*!< PCNT low control mode */
|
||||
pcnt_ctrl_mode_t hctrl_mode; /*!< PCNT high control mode */
|
||||
pcnt_count_mode_t pos_mode; /*!< PCNT positive edge count mode */
|
||||
pcnt_count_mode_t neg_mode; /*!< PCNT negative edge count mode */
|
||||
int16_t counter_h_lim; /*!< Maximum counter value */
|
||||
int16_t counter_l_lim; /*!< Minimum counter value */
|
||||
pcnt_unit_t unit; /*!< PCNT unit number */
|
||||
pcnt_channel_t channel; /*!< the PCNT channel */
|
||||
} pcnt_config_t;
|
||||
|
||||
/**
|
||||
* @brief Configure Pulse Counter unit
|
||||
* @note
|
||||
@@ -173,7 +257,6 @@ esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16
|
||||
* @param unit PCNT unit number
|
||||
* @param status Pointer to accept event status word
|
||||
* @return
|
||||
*
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
@@ -363,42 +446,6 @@ void pcnt_isr_service_uninstall(void);
|
||||
*/
|
||||
esp_err_t pcnt_isr_handler_remove(pcnt_unit_t unit);
|
||||
|
||||
/**
|
||||
* @addtogroup pcnt-examples
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* EXAMPLE OF PCNT CONFIGURATION
|
||||
* ==============================
|
||||
* @code{c}
|
||||
* //1. Config PCNT unit
|
||||
* pcnt_config_t pcnt_config = {
|
||||
* .pulse_gpio_num = 4, //set gpio4 as pulse input gpio
|
||||
* .ctrl_gpio_num = 5, //set gpio5 as control gpio
|
||||
* .channel = PCNT_CHANNEL_0, //use unit 0 channel 0
|
||||
* .lctrl_mode = PCNT_MODE_REVERSE, //when control signal is low, reverse the primary counter mode(inc->dec/dec->inc)
|
||||
* .hctrl_mode = PCNT_MODE_KEEP, //when control signal is high, keep the primary counter mode
|
||||
* .pos_mode = PCNT_COUNT_INC, //increment the counter
|
||||
* .neg_mode = PCNT_COUNT_DIS, //keep the counter value
|
||||
* .counter_h_lim = 10,
|
||||
* .counter_l_lim = -10,
|
||||
* };
|
||||
* pcnt_unit_config(&pcnt_config); //init unit
|
||||
* @endcode
|
||||
*
|
||||
* EXAMPLE OF PCNT EVENT SETTING
|
||||
* ==============================
|
||||
* @code{c}
|
||||
* //2. Configure PCNT watchpoint event.
|
||||
* pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_1, 5); //set thres1 value
|
||||
* pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_1); //enable thres1 event
|
||||
* @endcode
|
||||
*
|
||||
* For more examples please refer to PCNT example code in IDF_PATH/examples
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -4,14 +4,15 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_PCNT_SUPPORTED
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "driver/pcnt.h"
|
||||
#include "hal/pcnt_hal.h"
|
||||
#include "hal/pcnt_ll.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "soc/pcnt_periph.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
||||
#define PCNT_CHANNEL_ERR_STR "PCNT CHANNEL ERROR"
|
||||
@@ -60,19 +61,20 @@ static portMUX_TYPE pcnt_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
static inline esp_err_t _pcnt_set_mode(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK((pos_mode < PCNT_COUNT_MAX) && (neg_mode < PCNT_COUNT_MAX), PCNT_COUNT_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK((hctrl_mode < PCNT_MODE_MAX) && (lctrl_mode < PCNT_MODE_MAX), PCNT_CTRL_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
pcnt_hal_set_mode(&(p_pcnt_obj[pcnt_port]->hal), unit, channel, pos_mode, neg_mode, hctrl_mode, lctrl_mode);
|
||||
pcnt_ll_set_edge_action(p_pcnt_obj[pcnt_port]->hal.dev, unit, channel, pos_mode, neg_mode);
|
||||
pcnt_ll_set_level_action(p_pcnt_obj[pcnt_port]->hal.dev, unit, channel, hctrl_mode, lctrl_mode);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_set_pin(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, int ctrl_io)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(GPIO_IS_VALID_GPIO(pulse_io) || pulse_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(GPIO_IS_VALID_GPIO(ctrl_io) || ctrl_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
@@ -81,14 +83,14 @@ static inline esp_err_t _pcnt_set_pin(pcnt_port_t pcnt_port, pcnt_unit_t unit, p
|
||||
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[pulse_io], PIN_FUNC_GPIO);
|
||||
gpio_set_direction(pulse_io, GPIO_MODE_INPUT);
|
||||
gpio_set_pull_mode(pulse_io, GPIO_PULLUP_ONLY);
|
||||
esp_rom_gpio_connect_in_signal(pulse_io, pcnt_periph_signals.units[unit].channels[channel].pulse_sig, 0);
|
||||
esp_rom_gpio_connect_in_signal(pulse_io, pcnt_periph_signals.groups[pcnt_port].units[unit].channels[channel].pulse_sig, 0);
|
||||
}
|
||||
|
||||
if (ctrl_io >= 0) {
|
||||
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[ctrl_io], PIN_FUNC_GPIO);
|
||||
gpio_set_direction(ctrl_io, GPIO_MODE_INPUT);
|
||||
gpio_set_pull_mode(ctrl_io, GPIO_PULLUP_ONLY);
|
||||
esp_rom_gpio_connect_in_signal(ctrl_io, pcnt_periph_signals.units[unit].channels[channel].control_sig, 0);
|
||||
esp_rom_gpio_connect_in_signal(ctrl_io, pcnt_periph_signals.groups[pcnt_port].units[unit].channels[channel].control_sig, 0);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
@@ -97,18 +99,18 @@ static inline esp_err_t _pcnt_set_pin(pcnt_port_t pcnt_port, pcnt_unit_t unit, p
|
||||
static inline esp_err_t _pcnt_get_counter_value(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit, int16_t *count)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(count != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
pcnt_hal_get_counter_value(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit, count);
|
||||
*count = pcnt_ll_get_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_counter_pause(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
pcnt_hal_counter_pause(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit);
|
||||
pcnt_ll_stop_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -116,9 +118,9 @@ static inline esp_err_t _pcnt_counter_pause(pcnt_port_t pcnt_port, pcnt_unit_t p
|
||||
static inline esp_err_t _pcnt_counter_resume(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
pcnt_hal_counter_resume(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit);
|
||||
pcnt_ll_start_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -126,115 +128,136 @@ static inline esp_err_t _pcnt_counter_resume(pcnt_port_t pcnt_port, pcnt_unit_t
|
||||
static inline esp_err_t _pcnt_counter_clear(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
pcnt_hal_counter_clear(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit);
|
||||
pcnt_ll_clear_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_intr_enable(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit)
|
||||
static inline esp_err_t _pcnt_intr_enable(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit, bool enable)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
pcnt_hal_intr_enable(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit);
|
||||
pcnt_ll_enable_intr(p_pcnt_obj[pcnt_port]->hal.dev, 1 << pcnt_unit, enable);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_intr_disable(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit)
|
||||
static inline esp_err_t _pcnt_event_enable(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type, bool enable)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
pcnt_hal_intr_disable(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_event_enable(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
pcnt_hal_event_enable(&(p_pcnt_obj[pcnt_port]->hal), unit, evt_type);
|
||||
return ESP_OK;
|
||||
switch (evt_type) {
|
||||
case PCNT_EVT_THRES_1:
|
||||
pcnt_ll_enable_thres_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, 1, enable);
|
||||
break;
|
||||
case PCNT_EVT_THRES_0:
|
||||
pcnt_ll_enable_thres_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, 0, enable);
|
||||
break;
|
||||
case PCNT_EVT_L_LIM:
|
||||
pcnt_ll_enable_low_limit_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable);
|
||||
break;
|
||||
case PCNT_EVT_H_LIM:
|
||||
pcnt_ll_enable_high_limit_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable);
|
||||
break;
|
||||
case PCNT_EVT_ZERO:
|
||||
pcnt_ll_enable_zero_cross_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable);
|
||||
break;
|
||||
default:
|
||||
PCNT_CHECK(false, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
break;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_event_disable(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
pcnt_hal_event_disable(&(p_pcnt_obj[pcnt_port]->hal), unit, evt_type);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_set_event_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(!(evt_type == PCNT_EVT_L_LIM && value > 0), PCNT_LIMT_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(!(evt_type == PCNT_EVT_H_LIM && value < 0), PCNT_LIMT_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
pcnt_hal_set_event_value(&(p_pcnt_obj[pcnt_port]->hal), unit, evt_type, value);
|
||||
switch (evt_type) {
|
||||
case PCNT_EVT_THRES_1:
|
||||
pcnt_ll_set_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 1, value);
|
||||
break;
|
||||
case PCNT_EVT_THRES_0:
|
||||
pcnt_ll_set_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 0, value);
|
||||
break;
|
||||
case PCNT_EVT_L_LIM:
|
||||
pcnt_ll_set_low_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, value);
|
||||
break;
|
||||
case PCNT_EVT_H_LIM:
|
||||
pcnt_ll_set_high_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_get_event_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(value != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
pcnt_hal_get_event_value(&(p_pcnt_obj[pcnt_port]->hal), unit, evt_type, value);
|
||||
switch (evt_type) {
|
||||
case PCNT_EVT_THRES_1:
|
||||
*value = pcnt_ll_get_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 1);
|
||||
break;
|
||||
case PCNT_EVT_THRES_0:
|
||||
*value = pcnt_ll_get_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 0);
|
||||
break;
|
||||
case PCNT_EVT_L_LIM:
|
||||
*value = pcnt_ll_get_low_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit);
|
||||
break;
|
||||
case PCNT_EVT_H_LIM:
|
||||
*value = pcnt_ll_get_high_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_get_event_status(pcnt_port_t pcnt_port, pcnt_unit_t unit, uint32_t *status)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(status != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
*status = pcnt_hal_get_event_status(&(p_pcnt_obj[pcnt_port]->hal), unit);
|
||||
*status = pcnt_ll_get_unit_status(p_pcnt_obj[pcnt_port]->hal.dev, unit);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_set_filter_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, uint16_t filter_val)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(filter_val < 1024, PCNT_PARAM_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
pcnt_hal_set_filter_value(&(p_pcnt_obj[pcnt_port]->hal), unit, filter_val);
|
||||
pcnt_ll_set_glitch_filter_thres(p_pcnt_obj[pcnt_port]->hal.dev, unit, filter_val);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_get_filter_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, uint16_t *filter_val)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(filter_val != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
pcnt_hal_get_filter_value(&(p_pcnt_obj[pcnt_port]->hal), unit, filter_val);
|
||||
*filter_val = (uint16_t)pcnt_ll_get_glitch_filter_thres(p_pcnt_obj[pcnt_port]->hal.dev, unit);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_filter_enable(pcnt_port_t pcnt_port, pcnt_unit_t unit)
|
||||
static inline esp_err_t _pcnt_filter_enable(pcnt_port_t pcnt_port, pcnt_unit_t unit, bool enable)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
pcnt_hal_filter_enable(&(p_pcnt_obj[pcnt_port]->hal), unit);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_filter_disable(pcnt_port_t pcnt_port, pcnt_unit_t unit)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
pcnt_hal_filter_disable(&(p_pcnt_obj[pcnt_port]->hal), unit);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
pcnt_ll_enable_glitch_filter(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -242,16 +265,16 @@ static inline esp_err_t _pcnt_isr_handler_add(pcnt_port_t pcnt_port, pcnt_unit_t
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_isr_func != NULL, "ISR service is not installed, call pcnt_install_isr_service() first", ESP_ERR_INVALID_STATE);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, "PCNT unit error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, "PCNT unit error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
_pcnt_intr_disable(PCNT_PORT_0, unit);
|
||||
_pcnt_intr_enable(PCNT_PORT_0, unit, false);
|
||||
|
||||
if (pcnt_isr_func) {
|
||||
pcnt_isr_func[unit].fn = isr_handler;
|
||||
pcnt_isr_func[unit].args = args;
|
||||
}
|
||||
|
||||
_pcnt_intr_enable(PCNT_PORT_0, unit);
|
||||
_pcnt_intr_enable(PCNT_PORT_0, unit, true);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -260,9 +283,9 @@ static inline esp_err_t _pcnt_isr_handler_remove(pcnt_port_t pcnt_port, pcnt_uni
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_isr_func != NULL, "ISR service is not installed", ESP_ERR_INVALID_STATE);
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, "PCNT unit error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, "PCNT unit error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
_pcnt_intr_disable(PCNT_PORT_0, unit);
|
||||
_pcnt_intr_enable(PCNT_PORT_0, unit, false);
|
||||
|
||||
if (pcnt_isr_func) {
|
||||
pcnt_isr_func[unit].fn = NULL;
|
||||
@@ -278,8 +301,8 @@ static void IRAM_ATTR pcnt_intr_service(void *arg)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
pcnt_port_t pcnt_port = (pcnt_port_t)arg;
|
||||
pcnt_hal_get_intr_status(&(p_pcnt_obj[pcnt_port]->hal), &status);
|
||||
pcnt_hal_clear_intr_status(&(p_pcnt_obj[pcnt_port]->hal), status);
|
||||
status = pcnt_ll_get_intr_status(p_pcnt_obj[pcnt_port]->hal.dev);
|
||||
pcnt_ll_clear_intr_status(p_pcnt_obj[pcnt_port]->hal.dev, status);
|
||||
|
||||
while (status) {
|
||||
int unit = __builtin_ffs(status) - 1;
|
||||
@@ -296,7 +319,7 @@ static inline esp_err_t _pcnt_isr_service_install(pcnt_port_t pcnt_port, int int
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_isr_func == NULL, "ISR service already installed", ESP_ERR_INVALID_STATE);
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
pcnt_isr_func = (pcnt_isr_func_t *) calloc(PCNT_UNIT_MAX, sizeof(pcnt_isr_func_t));
|
||||
pcnt_isr_func = (pcnt_isr_func_t *) calloc(SOC_PCNT_UNITS_PER_GROUP, sizeof(pcnt_isr_func_t));
|
||||
|
||||
if (pcnt_isr_func == NULL) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
@@ -333,7 +356,7 @@ static inline esp_err_t _pcnt_unit_config(pcnt_port_t pcnt_port, const pcnt_conf
|
||||
int input_io = pcnt_config->pulse_gpio_num;
|
||||
int ctrl_io = pcnt_config->ctrl_gpio_num;
|
||||
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(input_io < 0 || (GPIO_IS_VALID_GPIO(input_io) && (input_io != ctrl_io)), "PCNT pulse input io error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(ctrl_io < 0 || GPIO_IS_VALID_GPIO(ctrl_io), "PCNT ctrl io error", ESP_ERR_INVALID_ARG);
|
||||
@@ -342,18 +365,18 @@ static inline esp_err_t _pcnt_unit_config(pcnt_port_t pcnt_port, const pcnt_conf
|
||||
/*Enalbe hardware module*/
|
||||
static bool pcnt_enable = false;
|
||||
if (pcnt_enable == false) {
|
||||
periph_module_reset(pcnt_periph_signals.module);
|
||||
periph_module_reset(pcnt_periph_signals.groups[pcnt_port].module);
|
||||
pcnt_enable = true;
|
||||
}
|
||||
periph_module_enable(pcnt_periph_signals.module);
|
||||
periph_module_enable(pcnt_periph_signals.groups[pcnt_port].module);
|
||||
/*Set counter range*/
|
||||
_pcnt_set_event_value(pcnt_port, unit, PCNT_EVT_H_LIM, pcnt_config->counter_h_lim);
|
||||
_pcnt_set_event_value(pcnt_port, unit, PCNT_EVT_L_LIM, pcnt_config->counter_l_lim);
|
||||
/*Default value after reboot is positive, we disable these events like others*/
|
||||
_pcnt_event_disable(pcnt_port, unit, PCNT_EVT_H_LIM);
|
||||
_pcnt_event_disable(pcnt_port, unit, PCNT_EVT_L_LIM);
|
||||
_pcnt_event_disable(pcnt_port, unit, PCNT_EVT_ZERO);
|
||||
_pcnt_filter_disable(pcnt_port, unit);
|
||||
_pcnt_event_enable(pcnt_port, unit, PCNT_EVT_H_LIM, false);
|
||||
_pcnt_event_enable(pcnt_port, unit, PCNT_EVT_L_LIM, false);
|
||||
_pcnt_event_enable(pcnt_port, unit, PCNT_EVT_ZERO, false);
|
||||
_pcnt_filter_enable(pcnt_port, unit, false);
|
||||
/*set pulse input and control mode*/
|
||||
_pcnt_set_mode(pcnt_port, unit, channel, pcnt_config->pos_mode, pcnt_config->neg_mode, pcnt_config->hctrl_mode, pcnt_config->lctrl_mode);
|
||||
/*Set pulse input and control pins*/
|
||||
@@ -386,8 +409,6 @@ esp_err_t pcnt_init(pcnt_port_t pcnt_port)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// TODO: The following functions are wrappers, for compatibility with current API.
|
||||
|
||||
esp_err_t pcnt_unit_config(const pcnt_config_t *pcnt_config)
|
||||
{
|
||||
esp_err_t ret;
|
||||
@@ -433,22 +454,22 @@ esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit)
|
||||
|
||||
esp_err_t pcnt_intr_enable(pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
return _pcnt_intr_enable(PCNT_PORT_0, pcnt_unit);
|
||||
return _pcnt_intr_enable(PCNT_PORT_0, pcnt_unit, true);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_intr_disable(pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
return _pcnt_intr_disable(PCNT_PORT_0, pcnt_unit);
|
||||
return _pcnt_intr_enable(PCNT_PORT_0, pcnt_unit, false);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
{
|
||||
return _pcnt_event_enable(PCNT_PORT_0, unit, evt_type);
|
||||
return _pcnt_event_enable(PCNT_PORT_0, unit, evt_type, true);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
{
|
||||
return _pcnt_event_disable(PCNT_PORT_0, unit, evt_type);
|
||||
return _pcnt_event_enable(PCNT_PORT_0, unit, evt_type, false);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value)
|
||||
@@ -478,12 +499,12 @@ esp_err_t pcnt_get_filter_value(pcnt_unit_t unit, uint16_t *filter_val)
|
||||
|
||||
esp_err_t pcnt_filter_enable(pcnt_unit_t unit)
|
||||
{
|
||||
return _pcnt_filter_enable(PCNT_PORT_0, unit);
|
||||
return _pcnt_filter_enable(PCNT_PORT_0, unit, true);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_filter_disable(pcnt_unit_t unit)
|
||||
{
|
||||
return _pcnt_filter_disable(PCNT_PORT_0, unit);
|
||||
return _pcnt_filter_enable(PCNT_PORT_0, unit, false);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_isr_unregister(pcnt_isr_handle_t handle)
|
||||
@@ -500,7 +521,7 @@ esp_err_t pcnt_isr_register(void (*fun)(void *), void *arg, int intr_alloc_flags
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
PCNT_CHECK(fun != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
ret = esp_intr_alloc(pcnt_periph_signals.irq, intr_alloc_flags, fun, arg, handle);
|
||||
ret = esp_intr_alloc(pcnt_periph_signals.groups[0].irq, intr_alloc_flags, fun, arg, handle);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ret;
|
||||
}
|
||||
@@ -515,7 +536,6 @@ esp_err_t pcnt_isr_handler_remove(pcnt_unit_t unit)
|
||||
return _pcnt_isr_handler_remove(PCNT_PORT_0, unit);
|
||||
}
|
||||
|
||||
|
||||
esp_err_t pcnt_isr_service_install(int intr_alloc_flags)
|
||||
{
|
||||
return _pcnt_isr_service_install(PCNT_PORT_0, intr_alloc_flags);
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/pcnt_struct.h"
|
||||
#include "unity.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
||||
@@ -96,7 +97,7 @@ static void IRAM_ATTR pcnt_intr_handler(void *arg)
|
||||
uint32_t status;
|
||||
BaseType_t port_status = pdFALSE;
|
||||
|
||||
for (i = 0; i < PCNT_UNIT_MAX; i++) {
|
||||
for (i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
|
||||
if (intr_status & (BIT(i))) {
|
||||
status = PCNT.status_unit[i].val;
|
||||
PCNT.int_clr.val = BIT(i);
|
||||
@@ -333,11 +334,11 @@ TEST_CASE("PCNT test config", "[pcnt]")
|
||||
pcnt_config_t temp_pcnt_config = pcnt_config;
|
||||
TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
|
||||
|
||||
// test PCNT_UNIT_MAX units, from 0-(PCNT_UNIT_MAX-1)
|
||||
// test SOC_PCNT_UNITS_PER_GROUP units, from 0-(SOC_PCNT_UNITS_PER_GROUP-1)
|
||||
pcnt_config = temp_pcnt_config;
|
||||
pcnt_config.unit = PCNT_UNIT_MAX;
|
||||
pcnt_config.unit = SOC_PCNT_UNITS_PER_GROUP;
|
||||
TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config));
|
||||
for (int i = 0; i < PCNT_UNIT_MAX; i++) {
|
||||
for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) {
|
||||
pcnt_config.unit = i;
|
||||
TEST_ESP_OK(pcnt_unit_config(&pcnt_config));
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -22,75 +22,67 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/pcnt_periph.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/pcnt_struct.h"
|
||||
#include "hal/pcnt_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Get PCNT hardware instance with giving pcnt num
|
||||
#define PCNT_LL_GET_HW(num) (((num) == 0) ? (&PCNT) : NULL)
|
||||
#define PCNT_LL_MAX_GLITCH_WIDTH 1023
|
||||
|
||||
typedef enum {
|
||||
PCNT_LL_EVENT_THRES1,
|
||||
PCNT_LL_EVENT_THRES0,
|
||||
PCNT_LL_EVENT_LOW_LIMIT,
|
||||
PCNT_LL_EVENT_HIGH_LIMIT,
|
||||
PCNT_LL_EVENT_ZERO_CROSS,
|
||||
PCNT_LL_EVENT_MAX
|
||||
} pcnt_ll_event_id_t;
|
||||
|
||||
#define PCNT_LL_EVENT_MASK ((1 << PCNT_LL_EVENT_MAX) - 1)
|
||||
|
||||
/**
|
||||
* @brief Set PCNT channel edge mode
|
||||
* @brief Set PCNT channel edge action
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param pos_mode Counter mode when detecting positive edge
|
||||
* @param neg_mode Counter mode when detecting negative edge
|
||||
* @param pos_act Counter action when detecting positive edge
|
||||
* @param neg_act Counter action when detecting negative edge
|
||||
*/
|
||||
static inline void pcnt_ll_set_edge_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode)
|
||||
static inline void pcnt_ll_set_edge_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_edge_action_t pos_act, pcnt_channel_edge_action_t neg_act)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0;
|
||||
if (channel == 0) {
|
||||
conf0_reg.ch0_pos_mode = pos_mode;
|
||||
conf0_reg.ch0_neg_mode = neg_mode;
|
||||
hw->conf_unit[unit].conf0.ch0_pos_mode = pos_act;
|
||||
hw->conf_unit[unit].conf0.ch0_neg_mode = neg_act;
|
||||
} else {
|
||||
conf0_reg.ch1_pos_mode = pos_mode;
|
||||
conf0_reg.ch1_neg_mode = neg_mode;
|
||||
hw->conf_unit[unit].conf0.ch1_pos_mode = pos_act;
|
||||
hw->conf_unit[unit].conf0.ch1_neg_mode = neg_act;
|
||||
}
|
||||
hw->conf_unit[unit].conf0 = conf0_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT channel level mode
|
||||
* @brief Set PCNT channel level action
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param hctrl_mode Counter mode when control signal is high level
|
||||
* @param lctrl_mode Counter mode when control signal is low level
|
||||
* @param high_act Counter action when control signal is high level
|
||||
* @param low_act Counter action when control signal is low level
|
||||
*/
|
||||
static inline void pcnt_ll_set_level_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)
|
||||
static inline void pcnt_ll_set_level_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_level_action_t high_act, pcnt_channel_level_action_t low_act)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0;
|
||||
if (channel == 0) {
|
||||
conf0_reg.ch0_hctrl_mode = hctrl_mode;
|
||||
conf0_reg.ch0_lctrl_mode = lctrl_mode;
|
||||
hw->conf_unit[unit].conf0.ch0_hctrl_mode = high_act;
|
||||
hw->conf_unit[unit].conf0.ch0_lctrl_mode = low_act;
|
||||
} else {
|
||||
conf0_reg.ch1_hctrl_mode = hctrl_mode;
|
||||
conf0_reg.ch1_lctrl_mode = lctrl_mode;
|
||||
hw->conf_unit[unit].conf0.ch1_hctrl_mode = high_act;
|
||||
hw->conf_unit[unit].conf0.ch1_lctrl_mode = low_act;
|
||||
}
|
||||
hw->conf_unit[unit].conf0 = conf0_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT counter mode
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param pos_mode Counter mode when detecting positive edge
|
||||
* @param neg_mode Counter mode when detecting negative edge
|
||||
* @param hctrl_mode Counter mode when control signal is high level
|
||||
* @param lctrl_mode Counter mode when control signal is low level
|
||||
*/
|
||||
static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)
|
||||
{
|
||||
pcnt_ll_set_edge_mode(hw, unit, channel, pos_mode, neg_mode);
|
||||
pcnt_ll_set_level_mode(hw, unit, channel, hctrl_mode, lctrl_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,11 +90,13 @@ static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_chann
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit Pulse Counter unit number
|
||||
* @param count Pointer to accept counter value
|
||||
* @return PCNT count value (a signed integer)
|
||||
*/
|
||||
static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, int16_t *count)
|
||||
static inline int pcnt_ll_get_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
*count = (int16_t) hw->cnt_unit[unit].cnt_val;
|
||||
typeof(hw->cnt_unit[unit]) cnt_reg = hw->cnt_unit[unit];
|
||||
int16_t value = cnt_reg.cnt_val;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,69 +105,60 @@ static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, i
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
static inline void pcnt_ll_counter_pause(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_stop_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
hw->ctrl.val |= BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2));
|
||||
hw->ctrl.val |= 1 << (2 * unit + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume counting for PCNT counter
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number, select from pcnt_unit_t
|
||||
* @param unit PCNT unit number, select from uint32_t
|
||||
*/
|
||||
static inline void pcnt_ll_counter_resume(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_start_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
hw->ctrl.val &= (~(BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2))));
|
||||
hw->ctrl.val &= ~(1 << (2 * unit + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear and reset PCNT counter value to zero
|
||||
* @brief Clear PCNT counter value to zero
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number, select from pcnt_unit_t
|
||||
* @param unit PCNT unit number, select from uint32_t
|
||||
*/
|
||||
static inline void pcnt_ll_counter_clear(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_clear_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
uint32_t reset_bit = BIT(PCNT_PLUS_CNT_RST_U0_S + (unit * 2));
|
||||
hw->ctrl.val |= reset_bit;
|
||||
hw->ctrl.val &= ~reset_bit;
|
||||
hw->ctrl.val |= 1 << (2 * unit);
|
||||
hw->ctrl.val &= ~(1 << (2 * unit));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT interrupt for PCNT unit
|
||||
* @note
|
||||
* Each Pulse counter unit has five watch point events that share the same interrupt.
|
||||
* Configure events with pcnt_event_enable() and pcnt_event_disable()
|
||||
* @note Each PCNT unit has five watch point events that share the same interrupt bit.
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param unit_mask PCNT units mask
|
||||
* @param enable True to enable interrupt, False to disable interrupt
|
||||
*/
|
||||
static inline void pcnt_ll_intr_enable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_enable_intr(pcnt_dev_t *hw, uint32_t unit_mask, bool enable)
|
||||
{
|
||||
hw->int_ena.val |= BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit);
|
||||
if (enable) {
|
||||
hw->int_ena.val |= unit_mask;
|
||||
} else {
|
||||
hw->int_ena.val &= ~unit_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT interrupt for PCNT unit
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
static inline void pcnt_ll_intr_disable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
{
|
||||
hw->int_ena.val &= (~(BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT interrupt status
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param status Pointer to accept value
|
||||
* @return Interrupt status word
|
||||
*/
|
||||
static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status)
|
||||
__attribute__((always_inline)) static inline uint32_t pcnt_ll_get_intr_status(pcnt_dev_t *hw)
|
||||
{
|
||||
*status = hw->int_st.val;
|
||||
return hw->int_st.val;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,163 +167,241 @@ static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status)
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param status value to clear interrupt status
|
||||
*/
|
||||
static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status)
|
||||
__attribute__((always_inline)) static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status)
|
||||
{
|
||||
hw->int_clr.val = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT event of PCNT unit
|
||||
* @brief Enable PCNT high limit event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_event_enable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
static inline void pcnt_ll_enable_high_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_l_lim_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_h_lim_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
hw->conf_unit[unit].conf0.thr_thres0_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
hw->conf_unit[unit].conf0.thr_thres1_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_ZERO) {
|
||||
hw->conf_unit[unit].conf0.thr_zero_en = 1;
|
||||
}
|
||||
hw->conf_unit[unit].conf0.thr_h_lim_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT event of PCNT unit
|
||||
* @brief Enable PCNT low limit event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_event_disable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
static inline void pcnt_ll_enable_low_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_l_lim_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_h_lim_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
hw->conf_unit[unit].conf0.thr_thres0_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
hw->conf_unit[unit].conf0.thr_thres1_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_ZERO) {
|
||||
hw->conf_unit[unit].conf0.thr_zero_en = 0;
|
||||
}
|
||||
hw->conf_unit[unit].conf0.thr_l_lim_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT event value of PCNT unit
|
||||
* @brief Enable PCNT zero cross event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
*
|
||||
* @param value Counter value for PCNT event
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_set_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value)
|
||||
static inline void pcnt_ll_enable_zero_cross_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
hw->conf_unit[unit].conf2.cnt_l_lim = value;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
hw->conf_unit[unit].conf2.cnt_h_lim = value;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
hw->conf_unit[unit].conf1.cnt_thres0 = value;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
hw->conf_unit[unit].conf1.cnt_thres1 = value;
|
||||
}
|
||||
hw->conf_unit[unit].conf0.thr_zero_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT event value of PCNT unit
|
||||
* @brief Enable PCNT threshold event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param value Pointer to accept counter value for PCNT event
|
||||
* @param thres Threshold ID
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_get_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value)
|
||||
static inline void pcnt_ll_enable_thres_event(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf2.cnt_l_lim;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf2.cnt_h_lim;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres0;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres1;
|
||||
if (thres == 0) {
|
||||
hw->conf_unit[unit].conf0.thr_thres0_en = enable;
|
||||
} else {
|
||||
*value = 0;
|
||||
hw->conf_unit[unit].conf0.thr_thres1_en = enable;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable all PCNT threshold events
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit unit number
|
||||
*/
|
||||
static inline void pcnt_ll_disable_all_events(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.val &= ~(PCNT_LL_EVENT_MASK << 11);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT high limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param value PCNT high limit value
|
||||
*/
|
||||
static inline void pcnt_ll_set_high_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf2) conf2_reg = hw->conf_unit[unit].conf2;
|
||||
conf2_reg.cnt_h_lim = value;
|
||||
hw->conf_unit[unit].conf2 = conf2_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT low limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param value PCNT low limit value
|
||||
*/
|
||||
static inline void pcnt_ll_set_low_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf2) conf2_reg = hw->conf_unit[unit].conf2;
|
||||
conf2_reg.cnt_l_lim = value;
|
||||
hw->conf_unit[unit].conf2 = conf2_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT threshold value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param thres Threshold ID
|
||||
* @param value PCNT threshold value
|
||||
*/
|
||||
static inline void pcnt_ll_set_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, int value)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf1) conf1_reg = hw->conf_unit[unit].conf1;
|
||||
if (thres == 0) {
|
||||
conf1_reg.cnt_thres0 = value;
|
||||
} else {
|
||||
conf1_reg.cnt_thres1 = value;
|
||||
}
|
||||
hw->conf_unit[unit].conf1 = conf1_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT high limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return PCNT high limit value
|
||||
*/
|
||||
static inline int pcnt_ll_get_high_limit_value(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf2) conf2_reg = hw->conf_unit[unit].conf2;
|
||||
int16_t value = conf2_reg.cnt_h_lim;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT low limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return PCNT high limit value
|
||||
*/
|
||||
static inline int pcnt_ll_get_low_limit_value(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf2) conf2_reg = hw->conf_unit[unit].conf2;
|
||||
int16_t value = conf2_reg.cnt_l_lim;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT threshold value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param thres Threshold ID
|
||||
* @return PCNT threshold value
|
||||
*/
|
||||
static inline int pcnt_ll_get_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres)
|
||||
{
|
||||
int16_t value;
|
||||
typeof(hw->conf_unit[unit].conf1) conf1_reg = hw->conf_unit[unit].conf1;
|
||||
if (thres == 0) {
|
||||
value = conf1_reg.cnt_thres0;
|
||||
} else {
|
||||
value = conf1_reg.cnt_thres1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT unit runtime status
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return PCNT unit runtime status
|
||||
*/
|
||||
static inline uint32_t pcnt_ll_get_unit_status(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
return hw->status_unit[unit].val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT count sign
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return Count sign
|
||||
*/
|
||||
static inline pcnt_unit_count_sign_t pcnt_ll_get_count_sign(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
return hw->status_unit[unit].val & 0x03;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT event status
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return event status word
|
||||
* @return Event status word
|
||||
*/
|
||||
static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
return hw->status_unit[unit].val;
|
||||
return hw->status_unit[unit].val >> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT filter value
|
||||
* @brief Set PCNT glitch filter threshold
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param filter_val PCNT signal filter value, counter in APB_CLK cycles.
|
||||
* Any pulses lasting shorter than this will be ignored when the filter is enabled.
|
||||
* @note
|
||||
* filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
|
||||
*/
|
||||
static inline void pcnt_ll_set_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t filter_val)
|
||||
static inline void pcnt_ll_set_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit, uint32_t filter_val)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.filter_thres = filter_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT filter value
|
||||
* @brief Get PCNT glitch filter threshold
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param filter_val Pointer to accept PCNT filter value.
|
||||
* @return glitch filter threshold
|
||||
*/
|
||||
static inline void pcnt_ll_get_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t *filter_val)
|
||||
static inline uint32_t pcnt_ll_get_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
*filter_val = hw->conf_unit[unit].conf0.filter_thres;
|
||||
return hw->conf_unit[unit].conf0.filter_thres;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT input filter
|
||||
* @brief Enable PCNT glitch filter
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param enable True to enable the filter, False to disable the filter
|
||||
*/
|
||||
static inline void pcnt_ll_filter_enable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_enable_glitch_filter(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.filter_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT input filter
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
static inline void pcnt_ll_filter_disable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.filter_en = 0;
|
||||
hw->conf_unit[unit].conf0.filter_en = enable;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -22,75 +22,67 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/pcnt_periph.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/pcnt_struct.h"
|
||||
#include "hal/pcnt_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Get PCNT hardware instance with giving pcnt num
|
||||
#define PCNT_LL_GET_HW(num) (((num) == 0) ? (&PCNT) : NULL)
|
||||
#define PCNT_LL_MAX_GLITCH_WIDTH 1023
|
||||
|
||||
typedef enum {
|
||||
PCNT_LL_EVENT_THRES1,
|
||||
PCNT_LL_EVENT_THRES0,
|
||||
PCNT_LL_EVENT_LOW_LIMIT,
|
||||
PCNT_LL_EVENT_HIGH_LIMIT,
|
||||
PCNT_LL_EVENT_ZERO_CROSS,
|
||||
PCNT_LL_EVENT_MAX
|
||||
} pcnt_ll_event_id_t;
|
||||
|
||||
#define PCNT_LL_EVENT_MASK ((1 << PCNT_LL_EVENT_MAX) - 1)
|
||||
|
||||
/**
|
||||
* @brief Set PCNT channel edge mode
|
||||
* @brief Set PCNT channel edge action
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param pos_mode Counter mode when detecting positive edge
|
||||
* @param neg_mode Counter mode when detecting negative edge
|
||||
* @param pos_act Counter action when detecting positive edge
|
||||
* @param neg_act Counter action when detecting negative edge
|
||||
*/
|
||||
static inline void pcnt_ll_set_edge_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode)
|
||||
static inline void pcnt_ll_set_edge_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_edge_action_t pos_act, pcnt_channel_edge_action_t neg_act)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0;
|
||||
if (channel == 0) {
|
||||
conf0_reg.ch0_pos_mode = pos_mode;
|
||||
conf0_reg.ch0_neg_mode = neg_mode;
|
||||
hw->conf_unit[unit].conf0.ch0_pos_mode_un = pos_act;
|
||||
hw->conf_unit[unit].conf0.ch0_neg_mode_un = neg_act;
|
||||
} else {
|
||||
conf0_reg.ch1_pos_mode = pos_mode;
|
||||
conf0_reg.ch1_neg_mode = neg_mode;
|
||||
hw->conf_unit[unit].conf0.ch1_pos_mode_un = pos_act;
|
||||
hw->conf_unit[unit].conf0.ch1_neg_mode_un = neg_act;
|
||||
}
|
||||
hw->conf_unit[unit].conf0 = conf0_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT channel level mode
|
||||
* @brief Set PCNT channel level action
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param hctrl_mode Counter mode when control signal is high level
|
||||
* @param lctrl_mode Counter mode when control signal is low level
|
||||
* @param high_act Counter action when control signal is high level
|
||||
* @param low_act Counter action when control signal is low level
|
||||
*/
|
||||
static inline void pcnt_ll_set_level_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)
|
||||
static inline void pcnt_ll_set_level_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_level_action_t high_act, pcnt_channel_level_action_t low_act)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0;
|
||||
if (channel == 0) {
|
||||
conf0_reg.ch0_hctrl_mode = hctrl_mode;
|
||||
conf0_reg.ch0_lctrl_mode = lctrl_mode;
|
||||
hw->conf_unit[unit].conf0.ch0_hctrl_mode_un = high_act;
|
||||
hw->conf_unit[unit].conf0.ch0_lctrl_mode_un = low_act;
|
||||
} else {
|
||||
conf0_reg.ch1_hctrl_mode = hctrl_mode;
|
||||
conf0_reg.ch1_lctrl_mode = lctrl_mode;
|
||||
hw->conf_unit[unit].conf0.ch1_hctrl_mode_un = high_act;
|
||||
hw->conf_unit[unit].conf0.ch1_lctrl_mode_un = low_act;
|
||||
}
|
||||
hw->conf_unit[unit].conf0 = conf0_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT counter mode
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param pos_mode Counter mode when detecting positive edge
|
||||
* @param neg_mode Counter mode when detecting negative edge
|
||||
* @param hctrl_mode Counter mode when control signal is high level
|
||||
* @param lctrl_mode Counter mode when control signal is low level
|
||||
*/
|
||||
static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)
|
||||
{
|
||||
pcnt_ll_set_edge_mode(hw, unit, channel, pos_mode, neg_mode);
|
||||
pcnt_ll_set_level_mode(hw, unit, channel, hctrl_mode, lctrl_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,11 +90,13 @@ static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_chann
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit Pulse Counter unit number
|
||||
* @param count Pointer to accept counter value
|
||||
* @return PCNT count value (a signed integer)
|
||||
*/
|
||||
static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, int16_t *count)
|
||||
static inline int pcnt_ll_get_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
*count = (int16_t) hw->cnt_unit[unit].cnt_val;
|
||||
pcnt_un_cnt_reg_t cnt_reg = hw->cnt_unit[unit];
|
||||
int16_t value = cnt_reg.pulse_cnt_un;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,69 +105,60 @@ static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, i
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
static inline void pcnt_ll_counter_pause(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_stop_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
hw->ctrl.val |= BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2));
|
||||
hw->ctrl.val |= 1 << (2 * unit + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume counting for PCNT counter
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number, select from pcnt_unit_t
|
||||
* @param unit PCNT unit number, select from uint32_t
|
||||
*/
|
||||
static inline void pcnt_ll_counter_resume(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_start_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
hw->ctrl.val &= (~(BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2))));
|
||||
hw->ctrl.val &= ~(1 << (2 * unit + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear and reset PCNT counter value to zero
|
||||
* @brief Clear PCNT counter value to zero
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number, select from pcnt_unit_t
|
||||
* @param unit PCNT unit number, select from uint32_t
|
||||
*/
|
||||
static inline void pcnt_ll_counter_clear(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_clear_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
uint32_t reset_bit = BIT(PCNT_PULSE_CNT_RST_U0_S + (unit * 2));
|
||||
hw->ctrl.val |= reset_bit;
|
||||
hw->ctrl.val &= ~reset_bit;
|
||||
hw->ctrl.val |= 1 << (2 * unit);
|
||||
hw->ctrl.val &= ~(1 << (2 * unit));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT interrupt for PCNT unit
|
||||
* @note
|
||||
* Each Pulse counter unit has five watch point events that share the same interrupt.
|
||||
* Configure events with pcnt_event_enable() and pcnt_event_disable()
|
||||
* @note Each PCNT unit has five watch point events that share the same interrupt bit.
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param unit_mask PCNT units mask
|
||||
* @param enable True to enable interrupt, False to disable interrupt
|
||||
*/
|
||||
static inline void pcnt_ll_intr_enable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_enable_intr(pcnt_dev_t *hw, uint32_t unit_mask, bool enable)
|
||||
{
|
||||
hw->int_ena.val |= BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit);
|
||||
if (enable) {
|
||||
hw->int_ena.val |= unit_mask;
|
||||
} else {
|
||||
hw->int_ena.val &= ~unit_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT interrupt for PCNT unit
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
static inline void pcnt_ll_intr_disable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
{
|
||||
hw->int_ena.val &= (~(BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT interrupt status
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param status Pointer to accept value
|
||||
* @return Interrupt status word
|
||||
*/
|
||||
static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status)
|
||||
__attribute__((always_inline)) static inline uint32_t pcnt_ll_get_intr_status(pcnt_dev_t *hw)
|
||||
{
|
||||
*status = hw->int_st.val;
|
||||
return hw->int_st.val;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,163 +167,241 @@ static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status)
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param status value to clear interrupt status
|
||||
*/
|
||||
static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status)
|
||||
__attribute__((always_inline)) static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status)
|
||||
{
|
||||
hw->int_clr.val = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT event of PCNT unit
|
||||
* @brief Enable PCNT high limit event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_event_enable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
static inline void pcnt_ll_enable_high_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_l_lim_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_h_lim_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
hw->conf_unit[unit].conf0.thr_thres0_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
hw->conf_unit[unit].conf0.thr_thres1_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_ZERO) {
|
||||
hw->conf_unit[unit].conf0.thr_zero_en = 1;
|
||||
}
|
||||
hw->conf_unit[unit].conf0.thr_h_lim_en_un = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT event of PCNT unit
|
||||
* @brief Enable PCNT low limit event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_event_disable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
static inline void pcnt_ll_enable_low_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_l_lim_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_h_lim_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
hw->conf_unit[unit].conf0.thr_thres0_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
hw->conf_unit[unit].conf0.thr_thres1_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_ZERO) {
|
||||
hw->conf_unit[unit].conf0.thr_zero_en = 0;
|
||||
}
|
||||
hw->conf_unit[unit].conf0.thr_l_lim_en_un = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT event value of PCNT unit
|
||||
* @brief Enable PCNT zero cross event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
*
|
||||
* @param value Counter value for PCNT event
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_set_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value)
|
||||
static inline void pcnt_ll_enable_zero_cross_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
hw->conf_unit[unit].conf2.cnt_l_lim = value;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
hw->conf_unit[unit].conf2.cnt_h_lim = value;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
hw->conf_unit[unit].conf1.cnt_thres0 = value;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
hw->conf_unit[unit].conf1.cnt_thres1 = value;
|
||||
}
|
||||
hw->conf_unit[unit].conf0.thr_zero_en_un = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT event value of PCNT unit
|
||||
* @brief Enable PCNT threshold event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param value Pointer to accept counter value for PCNT event
|
||||
* @param thres Threshold ID
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_get_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value)
|
||||
static inline void pcnt_ll_enable_thres_event(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf2.cnt_l_lim;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf2.cnt_h_lim;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres0;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres1;
|
||||
if (thres == 0) {
|
||||
hw->conf_unit[unit].conf0.thr_thres0_en_un = enable;
|
||||
} else {
|
||||
*value = 0;
|
||||
hw->conf_unit[unit].conf0.thr_thres1_en_un = enable;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable all PCNT threshold events
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit unit number
|
||||
*/
|
||||
static inline void pcnt_ll_disable_all_events(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.val &= ~(PCNT_LL_EVENT_MASK << 11);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT high limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param value PCNT high limit value
|
||||
*/
|
||||
static inline void pcnt_ll_set_high_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
|
||||
{
|
||||
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
|
||||
conf2_reg.cnt_h_lim_un = value;
|
||||
hw->conf_unit[unit].conf2 = conf2_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT low limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param value PCNT low limit value
|
||||
*/
|
||||
static inline void pcnt_ll_set_low_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
|
||||
{
|
||||
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
|
||||
conf2_reg.cnt_l_lim_un = value;
|
||||
hw->conf_unit[unit].conf2 = conf2_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT threshold value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param thres Threshold ID
|
||||
* @param value PCNT threshold value
|
||||
*/
|
||||
static inline void pcnt_ll_set_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, int value)
|
||||
{
|
||||
pcnt_un_conf1_reg_t conf1_reg = hw->conf_unit[unit].conf1;
|
||||
if (thres == 0) {
|
||||
conf1_reg.cnt_thres0_un = value;
|
||||
} else {
|
||||
conf1_reg.cnt_thres1_un = value;
|
||||
}
|
||||
hw->conf_unit[unit].conf1 = conf1_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT high limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return PCNT high limit value
|
||||
*/
|
||||
static inline int pcnt_ll_get_high_limit_value(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
|
||||
int16_t value = conf2_reg.cnt_h_lim_un;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT low limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return PCNT high limit value
|
||||
*/
|
||||
static inline int pcnt_ll_get_low_limit_value(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
|
||||
int16_t value = conf2_reg.cnt_l_lim_un;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT threshold value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param thres Threshold ID
|
||||
* @return PCNT threshold value
|
||||
*/
|
||||
static inline int pcnt_ll_get_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres)
|
||||
{
|
||||
int16_t value;
|
||||
pcnt_un_conf1_reg_t conf1_reg = hw->conf_unit[unit].conf1;
|
||||
if (thres == 0) {
|
||||
value = conf1_reg.cnt_thres0_un;
|
||||
} else {
|
||||
value = conf1_reg.cnt_thres1_un;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT unit runtime status
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return PCNT unit runtime status
|
||||
*/
|
||||
static inline uint32_t pcnt_ll_get_unit_status(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
return hw->status_unit[unit].val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT count sign
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return Count sign
|
||||
*/
|
||||
static inline pcnt_unit_count_sign_t pcnt_ll_get_count_sign(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
return hw->status_unit[unit].val & 0x03;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT event status
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return event status word
|
||||
* @return Event status word
|
||||
*/
|
||||
static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
return hw->status_unit[unit].val;
|
||||
return hw->status_unit[unit].val >> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT filter value
|
||||
* @brief Set PCNT glitch filter threshold
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param filter_val PCNT signal filter value, counter in APB_CLK cycles.
|
||||
* Any pulses lasting shorter than this will be ignored when the filter is enabled.
|
||||
* @note
|
||||
* filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
|
||||
*/
|
||||
static inline void pcnt_ll_set_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t filter_val)
|
||||
static inline void pcnt_ll_set_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit, uint32_t filter_val)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.filter_thres = filter_val;
|
||||
hw->conf_unit[unit].conf0.filter_thres_un = filter_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT filter value
|
||||
* @brief Get PCNT glitch filter threshold
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param filter_val Pointer to accept PCNT filter value.
|
||||
* @return glitch filter threshold
|
||||
*/
|
||||
static inline void pcnt_ll_get_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t *filter_val)
|
||||
static inline uint32_t pcnt_ll_get_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
*filter_val = hw->conf_unit[unit].conf0.filter_thres;
|
||||
return hw->conf_unit[unit].conf0.filter_thres_un;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT input filter
|
||||
* @brief Enable PCNT glitch filter
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param enable True to enable the filter, False to disable the filter
|
||||
*/
|
||||
static inline void pcnt_ll_filter_enable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_enable_glitch_filter(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.filter_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT input filter
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
static inline void pcnt_ll_filter_disable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.filter_en = 0;
|
||||
hw->conf_unit[unit].conf0.filter_en_un = enable;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -22,75 +22,67 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/pcnt_periph.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/pcnt_struct.h"
|
||||
#include "hal/pcnt_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Get PCNT hardware instance with giving pcnt num
|
||||
#define PCNT_LL_GET_HW(num) (((num) == 0) ? (&PCNT) : NULL)
|
||||
#define PCNT_LL_MAX_GLITCH_WIDTH 1023
|
||||
|
||||
typedef enum {
|
||||
PCNT_LL_EVENT_THRES1,
|
||||
PCNT_LL_EVENT_THRES0,
|
||||
PCNT_LL_EVENT_LOW_LIMIT,
|
||||
PCNT_LL_EVENT_HIGH_LIMIT,
|
||||
PCNT_LL_EVENT_ZERO_CROSS,
|
||||
PCNT_LL_EVENT_MAX
|
||||
} pcnt_ll_event_id_t;
|
||||
|
||||
#define PCNT_LL_EVENT_MASK ((1 << PCNT_LL_EVENT_MAX) - 1)
|
||||
|
||||
/**
|
||||
* @brief Set PCNT channel edge mode
|
||||
* @brief Set PCNT channel edge action
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param pos_mode Counter mode when detecting positive edge
|
||||
* @param neg_mode Counter mode when detecting negative edge
|
||||
* @param pos_act Counter action when detecting positive edge
|
||||
* @param neg_act Counter action when detecting negative edge
|
||||
*/
|
||||
static inline void pcnt_ll_set_edge_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode)
|
||||
static inline void pcnt_ll_set_edge_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_edge_action_t pos_act, pcnt_channel_edge_action_t neg_act)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0;
|
||||
if (channel == 0) {
|
||||
conf0_reg.ch0_pos_mode = pos_mode;
|
||||
conf0_reg.ch0_neg_mode = neg_mode;
|
||||
hw->conf_unit[unit].conf0.ch0_pos_mode_un = pos_act;
|
||||
hw->conf_unit[unit].conf0.ch0_neg_mode_un = neg_act;
|
||||
} else {
|
||||
conf0_reg.ch1_pos_mode = pos_mode;
|
||||
conf0_reg.ch1_neg_mode = neg_mode;
|
||||
hw->conf_unit[unit].conf0.ch1_pos_mode_un = pos_act;
|
||||
hw->conf_unit[unit].conf0.ch1_neg_mode_un = neg_act;
|
||||
}
|
||||
hw->conf_unit[unit].conf0 = conf0_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT channel level mode
|
||||
* @brief Set PCNT channel level action
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param hctrl_mode Counter mode when control signal is high level
|
||||
* @param lctrl_mode Counter mode when control signal is low level
|
||||
* @param high_act Counter action when control signal is high level
|
||||
* @param low_act Counter action when control signal is low level
|
||||
*/
|
||||
static inline void pcnt_ll_set_level_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)
|
||||
static inline void pcnt_ll_set_level_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_level_action_t high_act, pcnt_channel_level_action_t low_act)
|
||||
{
|
||||
typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0;
|
||||
if (channel == 0) {
|
||||
conf0_reg.ch0_hctrl_mode = hctrl_mode;
|
||||
conf0_reg.ch0_lctrl_mode = lctrl_mode;
|
||||
hw->conf_unit[unit].conf0.ch0_hctrl_mode_un = high_act;
|
||||
hw->conf_unit[unit].conf0.ch0_lctrl_mode_un = low_act;
|
||||
} else {
|
||||
conf0_reg.ch1_hctrl_mode = hctrl_mode;
|
||||
conf0_reg.ch1_lctrl_mode = lctrl_mode;
|
||||
hw->conf_unit[unit].conf0.ch1_hctrl_mode_un = high_act;
|
||||
hw->conf_unit[unit].conf0.ch1_lctrl_mode_un = low_act;
|
||||
}
|
||||
hw->conf_unit[unit].conf0 = conf0_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT counter mode
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param pos_mode Counter mode when detecting positive edge
|
||||
* @param neg_mode Counter mode when detecting negative edge
|
||||
* @param hctrl_mode Counter mode when control signal is high level
|
||||
* @param lctrl_mode Counter mode when control signal is low level
|
||||
*/
|
||||
static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)
|
||||
{
|
||||
pcnt_ll_set_edge_mode(hw, unit, channel, pos_mode, neg_mode);
|
||||
pcnt_ll_set_level_mode(hw, unit, channel, hctrl_mode, lctrl_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,11 +90,13 @@ static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_chann
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit Pulse Counter unit number
|
||||
* @param count Pointer to accept counter value
|
||||
* @return PCNT count value (a signed integer)
|
||||
*/
|
||||
static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, int16_t *count)
|
||||
static inline int pcnt_ll_get_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
*count = (int16_t) hw->cnt_unit[unit].cnt_val;
|
||||
pcnt_un_cnt_reg_t cnt_reg = hw->cnt_unit[unit];
|
||||
int16_t value = cnt_reg.pulse_cnt_un;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,69 +105,60 @@ static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, i
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
static inline void pcnt_ll_counter_pause(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_stop_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
hw->ctrl.val |= BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2));
|
||||
hw->ctrl.val |= 1 << (2 * unit + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume counting for PCNT counter
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number, select from pcnt_unit_t
|
||||
* @param unit PCNT unit number, select from uint32_t
|
||||
*/
|
||||
static inline void pcnt_ll_counter_resume(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_start_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
hw->ctrl.val &= (~(BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2))));
|
||||
hw->ctrl.val &= ~(1 << (2 * unit + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear and reset PCNT counter value to zero
|
||||
* @brief Clear PCNT counter value to zero
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number, select from pcnt_unit_t
|
||||
* @param unit PCNT unit number, select from uint32_t
|
||||
*/
|
||||
static inline void pcnt_ll_counter_clear(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_clear_count(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
uint32_t reset_bit = BIT(PCNT_PULSE_CNT_RST_U0_S + (unit * 2));
|
||||
hw->ctrl.val |= reset_bit;
|
||||
hw->ctrl.val &= ~reset_bit;
|
||||
hw->ctrl.val |= 1 << (2 * unit);
|
||||
hw->ctrl.val &= ~(1 << (2 * unit));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT interrupt for PCNT unit
|
||||
* @note
|
||||
* Each Pulse counter unit has five watch point events that share the same interrupt.
|
||||
* Configure events with pcnt_event_enable() and pcnt_event_disable()
|
||||
* @note Each PCNT unit has five watch point events that share the same interrupt bit.
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param unit_mask PCNT units mask
|
||||
* @param enable True to enable interrupt, False to disable interrupt
|
||||
*/
|
||||
static inline void pcnt_ll_intr_enable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_enable_intr(pcnt_dev_t *hw, uint32_t unit_mask, bool enable)
|
||||
{
|
||||
hw->int_ena.val |= BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit);
|
||||
if (enable) {
|
||||
hw->int_ena.val |= unit_mask;
|
||||
} else {
|
||||
hw->int_ena.val &= ~unit_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT interrupt for PCNT unit
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
static inline void pcnt_ll_intr_disable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
{
|
||||
hw->int_ena.val &= (~(BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT interrupt status
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param status Pointer to accept value
|
||||
* @return Interrupt status word
|
||||
*/
|
||||
static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status)
|
||||
__attribute__((always_inline)) static inline uint32_t pcnt_ll_get_intr_status(pcnt_dev_t *hw)
|
||||
{
|
||||
*status = hw->int_st.val;
|
||||
return hw->int_st.val;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,163 +167,241 @@ static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status)
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param status value to clear interrupt status
|
||||
*/
|
||||
static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status)
|
||||
__attribute__((always_inline)) static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status)
|
||||
{
|
||||
hw->int_clr.val = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT event of PCNT unit
|
||||
* @brief Enable PCNT high limit event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_event_enable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
static inline void pcnt_ll_enable_high_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_l_lim_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_h_lim_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
hw->conf_unit[unit].conf0.thr_thres0_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
hw->conf_unit[unit].conf0.thr_thres1_en = 1;
|
||||
} else if (evt_type == PCNT_EVT_ZERO) {
|
||||
hw->conf_unit[unit].conf0.thr_zero_en = 1;
|
||||
}
|
||||
hw->conf_unit[unit].conf0.thr_h_lim_en_un = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT event of PCNT unit
|
||||
* @brief Enable PCNT low limit event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_event_disable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
static inline void pcnt_ll_enable_low_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_l_lim_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
hw->conf_unit[unit].conf0.thr_h_lim_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
hw->conf_unit[unit].conf0.thr_thres0_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
hw->conf_unit[unit].conf0.thr_thres1_en = 0;
|
||||
} else if (evt_type == PCNT_EVT_ZERO) {
|
||||
hw->conf_unit[unit].conf0.thr_zero_en = 0;
|
||||
}
|
||||
hw->conf_unit[unit].conf0.thr_l_lim_en_un = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT event value of PCNT unit
|
||||
* @brief Enable PCNT zero cross event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
*
|
||||
* @param value Counter value for PCNT event
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_set_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value)
|
||||
static inline void pcnt_ll_enable_zero_cross_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
hw->conf_unit[unit].conf2.cnt_l_lim = value;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
hw->conf_unit[unit].conf2.cnt_h_lim = value;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
hw->conf_unit[unit].conf1.cnt_thres0 = value;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
hw->conf_unit[unit].conf1.cnt_thres1 = value;
|
||||
}
|
||||
hw->conf_unit[unit].conf0.thr_zero_en_un = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT event value of PCNT unit
|
||||
* @brief Enable PCNT threshold event
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param value Pointer to accept counter value for PCNT event
|
||||
* @param thres Threshold ID
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void pcnt_ll_get_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value)
|
||||
static inline void pcnt_ll_enable_thres_event(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, bool enable)
|
||||
{
|
||||
if (evt_type == PCNT_EVT_L_LIM) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf2.cnt_l_lim;
|
||||
} else if (evt_type == PCNT_EVT_H_LIM) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf2.cnt_h_lim;
|
||||
} else if (evt_type == PCNT_EVT_THRES_0) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres0;
|
||||
} else if (evt_type == PCNT_EVT_THRES_1) {
|
||||
*value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres1;
|
||||
if (thres == 0) {
|
||||
hw->conf_unit[unit].conf0.thr_thres0_en_un = enable;
|
||||
} else {
|
||||
*value = 0;
|
||||
hw->conf_unit[unit].conf0.thr_thres1_en_un = enable;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable all PCNT threshold events
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit unit number
|
||||
*/
|
||||
static inline void pcnt_ll_disable_all_events(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.val &= ~(PCNT_LL_EVENT_MASK << 11);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT high limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param value PCNT high limit value
|
||||
*/
|
||||
static inline void pcnt_ll_set_high_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
|
||||
{
|
||||
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
|
||||
conf2_reg.cnt_h_lim_un = value;
|
||||
hw->conf_unit[unit].conf2 = conf2_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT low limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param value PCNT low limit value
|
||||
*/
|
||||
static inline void pcnt_ll_set_low_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
|
||||
{
|
||||
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
|
||||
conf2_reg.cnt_l_lim_un = value;
|
||||
hw->conf_unit[unit].conf2 = conf2_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT threshold value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param thres Threshold ID
|
||||
* @param value PCNT threshold value
|
||||
*/
|
||||
static inline void pcnt_ll_set_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, int value)
|
||||
{
|
||||
pcnt_un_conf1_reg_t conf1_reg = hw->conf_unit[unit].conf1;
|
||||
if (thres == 0) {
|
||||
conf1_reg.cnt_thres0_un = value;
|
||||
} else {
|
||||
conf1_reg.cnt_thres1_un = value;
|
||||
}
|
||||
hw->conf_unit[unit].conf1 = conf1_reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT high limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return PCNT high limit value
|
||||
*/
|
||||
static inline int pcnt_ll_get_high_limit_value(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
|
||||
int16_t value = conf2_reg.cnt_h_lim_un;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT low limit value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return PCNT high limit value
|
||||
*/
|
||||
static inline int pcnt_ll_get_low_limit_value(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2;
|
||||
int16_t value = conf2_reg.cnt_l_lim_un;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT threshold value
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param thres Threshold ID
|
||||
* @return PCNT threshold value
|
||||
*/
|
||||
static inline int pcnt_ll_get_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres)
|
||||
{
|
||||
int16_t value;
|
||||
pcnt_un_conf1_reg_t conf1_reg = hw->conf_unit[unit].conf1;
|
||||
if (thres == 0) {
|
||||
value = conf1_reg.cnt_thres0_un;
|
||||
} else {
|
||||
value = conf1_reg.cnt_thres1_un;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT unit runtime status
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return PCNT unit runtime status
|
||||
*/
|
||||
static inline uint32_t pcnt_ll_get_unit_status(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
return hw->status_unit[unit].val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT count sign
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return Count sign
|
||||
*/
|
||||
static inline pcnt_unit_count_sign_t pcnt_ll_get_count_sign(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
return hw->status_unit[unit].val & 0x03;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT event status
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @return event status word
|
||||
* @return Event status word
|
||||
*/
|
||||
static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
return hw->status_unit[unit].val;
|
||||
return hw->status_unit[unit].val >> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PCNT filter value
|
||||
* @brief Set PCNT glitch filter threshold
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param filter_val PCNT signal filter value, counter in APB_CLK cycles.
|
||||
* Any pulses lasting shorter than this will be ignored when the filter is enabled.
|
||||
* @note
|
||||
* filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
|
||||
*/
|
||||
static inline void pcnt_ll_set_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t filter_val)
|
||||
static inline void pcnt_ll_set_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit, uint32_t filter_val)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.filter_thres = filter_val;
|
||||
hw->conf_unit[unit].conf0.filter_thres_un = filter_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PCNT filter value
|
||||
* @brief Get PCNT glitch filter threshold
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param filter_val Pointer to accept PCNT filter value.
|
||||
* @return glitch filter threshold
|
||||
*/
|
||||
static inline void pcnt_ll_get_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t *filter_val)
|
||||
static inline uint32_t pcnt_ll_get_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit)
|
||||
{
|
||||
*filter_val = hw->conf_unit[unit].conf0.filter_thres;
|
||||
return hw->conf_unit[unit].conf0.filter_thres_un;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT input filter
|
||||
* @brief Enable PCNT glitch filter
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
* @param enable True to enable the filter, False to disable the filter
|
||||
*/
|
||||
static inline void pcnt_ll_filter_enable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
static inline void pcnt_ll_enable_glitch_filter(pcnt_dev_t *hw, uint32_t unit, bool enable)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.filter_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT input filter
|
||||
*
|
||||
* @param hw Peripheral PCNT hardware instance address.
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
static inline void pcnt_ll_filter_disable(pcnt_dev_t *hw, pcnt_unit_t unit)
|
||||
{
|
||||
hw->conf_unit[unit].conf0.filter_en = 0;
|
||||
hw->conf_unit[unit].conf0.filter_en_un = enable;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -23,10 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include "soc/pcnt_periph.h"
|
||||
#include "hal/pcnt_types.h"
|
||||
#include "hal/pcnt_ll.h"
|
||||
#include "soc/pcnt_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -35,188 +32,18 @@ extern "C" {
|
||||
/**
|
||||
* Context that should be maintained by both the driver and the HAL
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
pcnt_dev_t *dev;
|
||||
pcnt_dev_t *dev; /*!< PCNT peripheral register base address */
|
||||
} pcnt_hal_context_t;
|
||||
|
||||
/**
|
||||
* @brief Set PCNT counter mode
|
||||
* @brief Init the PCNT hal and set the PCNT to the default configuration.
|
||||
* @note This function should be called first before other hal layer function is called.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param pos_mode Counter mode when detecting positive edge
|
||||
* @param neg_mode Counter mode when detecting negative edge
|
||||
* @param hctrl_mode Counter mode when control signal is high level
|
||||
* @param lctrl_mode Counter mode when control signal is low level
|
||||
* @param group_id PCNT group ID
|
||||
*/
|
||||
#define pcnt_hal_set_mode(hal, unit, channel, pos_mode, neg_mode, hctrl_mode, lctrl_mode) pcnt_ll_set_mode((hal)->dev, unit, channel, pos_mode, neg_mode, hctrl_mode, lctrl_mode)
|
||||
|
||||
/**
|
||||
* @brief Get pulse counter value
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit Pulse Counter unit number
|
||||
* @param count Pointer to accept counter value
|
||||
*/
|
||||
#define pcnt_hal_get_counter_value(hal, unit, count) pcnt_ll_get_counter_value((hal)->dev, unit, count)
|
||||
|
||||
/**
|
||||
* @brief Pause PCNT counter of PCNT unit
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
#define pcnt_hal_counter_pause(hal, unit) pcnt_ll_counter_pause((hal)->dev, unit)
|
||||
|
||||
/**
|
||||
* @brief Resume counting for PCNT counter
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number, select from unit_t
|
||||
*/
|
||||
#define pcnt_hal_counter_resume(hal, unit) pcnt_ll_counter_resume((hal)->dev, unit)
|
||||
|
||||
/**
|
||||
* @brief Clear and reset PCNT counter value to zero
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number, select from unit_t
|
||||
*/
|
||||
#define pcnt_hal_counter_clear(hal, unit) pcnt_ll_counter_clear((hal)->dev, unit)
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT interrupt for PCNT unit
|
||||
* @note
|
||||
* Each Pulse counter unit has five watch point events that share the same interrupt.
|
||||
* Configure events with pcnt_event_enable() and pcnt_event_disable()
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
#define pcnt_hal_intr_enable(hal, unit) pcnt_ll_intr_enable((hal)->dev, unit)
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT interrupt for PCNT unit
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
#define pcnt_hal_intr_disable(hal, unit) pcnt_ll_intr_disable((hal)->dev, unit)
|
||||
|
||||
/**
|
||||
* @brief Get PCNT interrupt status
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param mask The interrupt status mask to be cleared. Pointer to accept value interrupt status mask.
|
||||
*/
|
||||
#define pcnt_hal_get_intr_status(hal, mask) pcnt_ll_get_intr_status((hal)->dev, mask)
|
||||
|
||||
/**
|
||||
* @brief Clear PCNT interrupt status
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param mask The interrupt status mask to be cleared.
|
||||
*/
|
||||
#define pcnt_hal_clear_intr_status(hal, mask) pcnt_ll_clear_intr_status((hal)->dev, mask)
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT event of PCNT unit
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
*/
|
||||
#define pcnt_hal_event_enable(hal, unit, evt_type) pcnt_ll_event_enable((hal)->dev, unit, evt_type)
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT event of PCNT unit
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
*/
|
||||
#define pcnt_hal_event_disable(hal, unit, evt_type) pcnt_ll_event_disable((hal)->dev, unit, evt_type)
|
||||
|
||||
/**
|
||||
* @brief Set PCNT event value of PCNT unit
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
*
|
||||
* @param value Counter value for PCNT event
|
||||
*/
|
||||
#define pcnt_hal_set_event_value(hal, unit, evt_type, value) pcnt_ll_set_event_value((hal)->dev, unit, evt_type, value)
|
||||
|
||||
/**
|
||||
* @brief Get PCNT event value of PCNT unit
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param value Pointer to accept counter value for PCNT event
|
||||
*/
|
||||
#define pcnt_hal_get_event_value(hal, unit, evt_type, value) pcnt_ll_get_event_value((hal)->dev, unit, evt_type, value)
|
||||
|
||||
/**
|
||||
* @brief Get PCNT event status
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
* @return event status word
|
||||
*/
|
||||
#define pcnt_hal_get_event_status(hal, unit) pcnt_ll_get_event_status((hal)->dev, unit)
|
||||
|
||||
/**
|
||||
* @brief Set PCNT filter value
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
* @param filter_val PCNT signal filter value, counter in APB_CLK cycles.
|
||||
* Any pulses lasting shorter than this will be ignored when the filter is enabled.
|
||||
* @note
|
||||
* filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
|
||||
*/
|
||||
#define pcnt_hal_set_filter_value(hal, unit, filter_val) pcnt_ll_set_filter_value((hal)->dev, unit, filter_val)
|
||||
|
||||
/**
|
||||
* @brief Get PCNT filter value
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
* @param filter_val Pointer to accept PCNT filter value.
|
||||
*/
|
||||
#define pcnt_hal_get_filter_value(hal, unit, filter_val) pcnt_ll_get_filter_value((hal)->dev, unit, filter_val)
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT input filter
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
#define pcnt_hal_filter_enable(hal, unit) pcnt_ll_filter_enable((hal)->dev, unit)
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT input filter
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param unit PCNT unit number
|
||||
*/
|
||||
#define pcnt_hal_filter_disable(hal, unit) pcnt_ll_filter_disable((hal)->dev, unit)
|
||||
|
||||
/**
|
||||
* @brief Init the PCNT hal and set the PCNT to the default configuration. This function should be called first before other hal layer function is called
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param pcnt_num The uart port number, the max port number is (PCNT_NUM_MAX -1)
|
||||
*/
|
||||
void pcnt_hal_init(pcnt_hal_context_t *hal, int pcnt_num);
|
||||
void pcnt_hal_init(pcnt_hal_context_t *hal, int group_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -18,93 +18,36 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#define PCNT_PIN_NOT_USED (-1) /*!< When selected for a pin, this pin will not be used */
|
||||
|
||||
/**
|
||||
* @brief PCNT port number, the max port number is (PCNT_PORT_MAX - 1).
|
||||
* @brief PCNT channel action on control level
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_PORT_0 = 0, /*!< PCNT port 0 */
|
||||
PCNT_PORT_MAX, /*!< PCNT port max */
|
||||
} pcnt_port_t;
|
||||
PCNT_CHANNEL_LEVEL_ACTION_KEEP, /*!< Keep current count mode */
|
||||
PCNT_CHANNEL_LEVEL_ACTION_INVERSE, /*!< Invert current count mode (increase -> decrease, decrease -> increase) */
|
||||
PCNT_CHANNEL_LEVEL_ACTION_HOLD, /*!< Hold current count value */
|
||||
} pcnt_channel_level_action_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of all available PCNT units
|
||||
* @brief PCNT channel action on signal edge
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_UNIT_0 = 0, /*!< PCNT unit 0 */
|
||||
PCNT_UNIT_1 = 1, /*!< PCNT unit 1 */
|
||||
PCNT_UNIT_2 = 2, /*!< PCNT unit 2 */
|
||||
PCNT_UNIT_3 = 3, /*!< PCNT unit 3 */
|
||||
#if SOC_PCNT_UNIT_NUM > 4
|
||||
PCNT_UNIT_4 = 4, /*!< PCNT unit 4 */
|
||||
PCNT_UNIT_5 = 5, /*!< PCNT unit 5 */
|
||||
PCNT_UNIT_6 = 6, /*!< PCNT unit 6 */
|
||||
PCNT_UNIT_7 = 7, /*!< PCNT unit 7 */
|
||||
#endif
|
||||
PCNT_UNIT_MAX,
|
||||
} pcnt_unit_t;
|
||||
PCNT_CHANNEL_EDGE_ACTION_HOLD, /*!< Hold current count value */
|
||||
PCNT_CHANNEL_EDGE_ACTION_INCREASE, /*!< Increase count value */
|
||||
PCNT_CHANNEL_EDGE_ACTION_DECREASE, /*!< Decrease count value */
|
||||
} pcnt_channel_edge_action_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of available modes that determine the counter's action depending on the state of the control signal's input GPIO
|
||||
* @note Configuration covers two actions, one for high, and one for low level on the control input
|
||||
* @brief PCNT unit counter value's sign
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_MODE_KEEP = 0, /*!< Control mode: won't change counter mode*/
|
||||
PCNT_MODE_REVERSE = 1, /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase) */
|
||||
PCNT_MODE_DISABLE = 2, /*!< Control mode: Inhibit counter(counter value will not change in this condition) */
|
||||
PCNT_MODE_MAX
|
||||
} pcnt_ctrl_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of available modes that determine the counter's action on the edge of the pulse signal's input GPIO
|
||||
* @note Configuration covers two actions, one for positive, and one for negative edge on the pulse input
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_COUNT_DIS = 0, /*!< Counter mode: Inhibit counter(counter value will not change in this condition) */
|
||||
PCNT_COUNT_INC = 1, /*!< Counter mode: Increase counter value */
|
||||
PCNT_COUNT_DEC = 2, /*!< Counter mode: Decrease counter value */
|
||||
PCNT_COUNT_MAX
|
||||
} pcnt_count_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of channels available for a single PCNT unit
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_CHANNEL_0 = 0x00, /*!< PCNT channel 0 */
|
||||
PCNT_CHANNEL_1 = 0x01, /*!< PCNT channel 1 */
|
||||
PCNT_CHANNEL_MAX,
|
||||
} pcnt_channel_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of counter's events the may trigger an interrupt
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_EVT_THRES_1 = BIT(2), /*!< PCNT watch point event: threshold1 value event */
|
||||
PCNT_EVT_THRES_0 = BIT(3), /*!< PCNT watch point event: threshold0 value event */
|
||||
PCNT_EVT_L_LIM = BIT(4), /*!< PCNT watch point event: Minimum counter value */
|
||||
PCNT_EVT_H_LIM = BIT(5), /*!< PCNT watch point event: Maximum counter value */
|
||||
PCNT_EVT_ZERO = BIT(6), /*!< PCNT watch point event: counter value zero event */
|
||||
PCNT_EVT_MAX
|
||||
} pcnt_evt_type_t;
|
||||
|
||||
/**
|
||||
* @brief Pulse Counter configuration for a single channel
|
||||
*/
|
||||
typedef struct {
|
||||
int pulse_gpio_num; /*!< Pulse input GPIO number, if you want to use GPIO16, enter pulse_gpio_num = 16, a negative value will be ignored */
|
||||
int ctrl_gpio_num; /*!< Control signal input GPIO number, a negative value will be ignored */
|
||||
pcnt_ctrl_mode_t lctrl_mode; /*!< PCNT low control mode */
|
||||
pcnt_ctrl_mode_t hctrl_mode; /*!< PCNT high control mode */
|
||||
pcnt_count_mode_t pos_mode; /*!< PCNT positive edge count mode */
|
||||
pcnt_count_mode_t neg_mode; /*!< PCNT negative edge count mode */
|
||||
int16_t counter_h_lim; /*!< Maximum counter value */
|
||||
int16_t counter_l_lim; /*!< Minimum counter value */
|
||||
pcnt_unit_t unit; /*!< PCNT unit number */
|
||||
pcnt_channel_t channel; /*!< the PCNT channel */
|
||||
} pcnt_config_t;
|
||||
PCNT_UNIT_COUNT_SIGN_ZERO_POS, /*!< positive value to zero */
|
||||
PCNT_UNIT_COUNT_SIGN_ZERO_NEG, /*!< negative value to zero */
|
||||
PCNT_UNIT_COUNT_SIGN_NEG, /*!< counter value negative */
|
||||
PCNT_UNIT_COUNT_SIGN_POS, /*!< counter value positive */
|
||||
} pcnt_unit_count_sign_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@
|
||||
// The HAL layer for PCNT (common part)
|
||||
|
||||
#include "hal/pcnt_hal.h"
|
||||
#include "hal/pcnt_ll.h"
|
||||
|
||||
void pcnt_hal_init(pcnt_hal_context_t *hal, int pcnt_num)
|
||||
{
|
||||
|
@@ -180,10 +180,10 @@
|
||||
#define SOC_MPU_REGION_WO_SUPPORTED 0
|
||||
|
||||
/*-------------------------- PCNT CAPS ---------------------------------------*/
|
||||
// ESP32 have 1 PCNT peripheral
|
||||
#define SOC_PCNT_PORT_NUM (1)
|
||||
#define SOC_PCNT_UNIT_NUM (8)
|
||||
#define SOC_PCNT_UNIT_CHANNEL_NUM (2)
|
||||
#define SOC_PCNT_GROUPS (1)
|
||||
#define SOC_PCNT_UNITS_PER_GROUP (8)
|
||||
#define SOC_PCNT_CHANNELS_PER_UNIT (2)
|
||||
#define SOC_PCNT_THRES_POINT_PER_UNIT (2)
|
||||
|
||||
/*-------------------------- RMT CAPS ----------------------------------------*/
|
||||
#define SOC_RMT_GROUPS (1) /*!< One RMT group */
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#include "soc/gpio_sig_map.h"
|
||||
|
||||
const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
.groups = {
|
||||
[0] = {
|
||||
.module = PERIPH_PCNT_MODULE,
|
||||
.irq = ETS_PCNT_INTR_SOURCE,
|
||||
.units = {
|
||||
@@ -116,4 +118,6 @@ const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -66,7 +66,6 @@
|
||||
#define DR_REG_UHCI0_BASE 0x60014000
|
||||
#define DR_REG_SLCHOST_BASE 0x60019000
|
||||
#define DR_REG_RMT_BASE 0x60016000
|
||||
#define DR_REG_PCNT_BASE 0x60017000
|
||||
#define DR_REG_SLC_BASE 0x6002D000
|
||||
#define DR_REG_LEDC_BASE 0x60019000
|
||||
#define DR_REG_EFUSE_BASE 0x6001A000
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,177 +1,416 @@
|
||||
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef _SOC_PCNT_STRUCT_H_
|
||||
#define _SOC_PCNT_STRUCT_H_
|
||||
/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef volatile struct {
|
||||
/** Group: Configuration Register */
|
||||
/** Type of un_conf0 register
|
||||
* Configuration register 0 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
union {
|
||||
struct {
|
||||
uint32_t filter_thres: 10;
|
||||
uint32_t filter_en: 1;
|
||||
uint32_t thr_zero_en: 1;
|
||||
uint32_t thr_h_lim_en: 1;
|
||||
uint32_t thr_l_lim_en: 1;
|
||||
uint32_t thr_thres0_en: 1;
|
||||
uint32_t thr_thres1_en: 1;
|
||||
uint32_t ch0_neg_mode: 2;
|
||||
uint32_t ch0_pos_mode: 2;
|
||||
uint32_t ch0_hctrl_mode: 2;
|
||||
uint32_t ch0_lctrl_mode: 2;
|
||||
uint32_t ch1_neg_mode: 2;
|
||||
uint32_t ch1_pos_mode: 2;
|
||||
uint32_t ch1_hctrl_mode: 2;
|
||||
uint32_t ch1_lctrl_mode: 2;
|
||||
/** filter_thres_un : R/W; bitpos: [9:0]; default: 16;
|
||||
* This sets the maximum threshold, in APB_CLK cycles, for the filter.
|
||||
*
|
||||
* Any pulses with width less than this will be ignored when the filter is enabled.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
* This register sets the behavior when the signal input of channel 0 detects a
|
||||
* negative edge.
|
||||
*
|
||||
* 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter
|
||||
*/
|
||||
uint32_t ch0_neg_mode_un: 2;
|
||||
/** ch0_pos_mode_un : R/W; bitpos: [19:18]; default: 0;
|
||||
* This register sets the behavior when the signal input of channel 0 detects a
|
||||
* positive edge.
|
||||
*
|
||||
* 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter
|
||||
*/
|
||||
uint32_t ch0_pos_mode_un: 2;
|
||||
/** ch0_hctrl_mode_un : R/W; bitpos: [21:20]; default: 0;
|
||||
* This register 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;
|
||||
* This register 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;
|
||||
* This register sets 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 on counter
|
||||
*/
|
||||
uint32_t ch1_neg_mode_un: 2;
|
||||
/** ch1_pos_mode_un : R/W; bitpos: [27:26]; default: 0;
|
||||
* This register sets 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 on counter
|
||||
*/
|
||||
uint32_t ch1_pos_mode_un: 2;
|
||||
/** ch1_hctrl_mode_un : R/W; bitpos: [29:28]; default: 0;
|
||||
* This register 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;
|
||||
* This register 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;
|
||||
} conf0;
|
||||
union {
|
||||
} pcnt_un_conf0_reg_t;
|
||||
|
||||
/** Type of un_conf1 register
|
||||
* Configuration register 1 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t cnt_thres0: 16;
|
||||
uint32_t cnt_thres1: 16;
|
||||
/** cnt_thres0_un : R/W; bitpos: [15:0]; default: 0;
|
||||
* This register is used to configure the thres0 value for unit n.
|
||||
*/
|
||||
uint32_t cnt_thres0_un: 16;
|
||||
/** cnt_thres1_un : R/W; bitpos: [31:16]; default: 0;
|
||||
* This register is used to configure the thres1 value for unit n.
|
||||
*/
|
||||
uint32_t cnt_thres1_un: 16;
|
||||
};
|
||||
uint32_t val;
|
||||
} conf1;
|
||||
union {
|
||||
} pcnt_un_conf1_reg_t;
|
||||
|
||||
/** Type of un_conf2 register
|
||||
* Configuration register 2 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t cnt_h_lim: 16;
|
||||
uint32_t cnt_l_lim: 16;
|
||||
/** cnt_h_lim_un : R/W; bitpos: [15:0]; default: 0;
|
||||
* This register is used to configure the thr_h_lim value for unit n.
|
||||
*/
|
||||
uint32_t cnt_h_lim_un: 16;
|
||||
/** cnt_l_lim_un : R/W; bitpos: [31:16]; default: 0;
|
||||
* This register is used to configure the thr_l_lim value for unit n.
|
||||
*/
|
||||
uint32_t cnt_l_lim_un: 16;
|
||||
};
|
||||
uint32_t val;
|
||||
} conf2;
|
||||
} conf_unit[4];
|
||||
union {
|
||||
} pcnt_un_conf2_reg_t;
|
||||
|
||||
|
||||
/** Type of ctrl register
|
||||
* Control register for all counters
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t cnt_val: 16;
|
||||
uint32_t reserved16: 16;
|
||||
};
|
||||
uint32_t val;
|
||||
} cnt_unit[4];
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_thr_event_u0: 1;
|
||||
uint32_t cnt_thr_event_u1: 1;
|
||||
uint32_t cnt_thr_event_u2: 1;
|
||||
uint32_t cnt_thr_event_u3: 1;
|
||||
uint32_t reserved4: 28;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_raw;
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_thr_event_u0: 1;
|
||||
uint32_t cnt_thr_event_u1: 1;
|
||||
uint32_t cnt_thr_event_u2: 1;
|
||||
uint32_t cnt_thr_event_u3: 1;
|
||||
uint32_t reserved4: 28;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_st;
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_thr_event_u0: 1;
|
||||
uint32_t cnt_thr_event_u1: 1;
|
||||
uint32_t cnt_thr_event_u2: 1;
|
||||
uint32_t cnt_thr_event_u3: 1;
|
||||
uint32_t reserved4: 28;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_ena;
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_thr_event_u0: 1;
|
||||
uint32_t cnt_thr_event_u1: 1;
|
||||
uint32_t cnt_thr_event_u2: 1;
|
||||
uint32_t cnt_thr_event_u3: 1;
|
||||
uint32_t reserved4: 28;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_clr;
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_mode: 2;
|
||||
uint32_t thres1_lat: 1;
|
||||
uint32_t thres0_lat: 1;
|
||||
uint32_t l_lim_lat: 1;
|
||||
uint32_t h_lim_lat: 1;
|
||||
uint32_t zero_lat: 1;
|
||||
uint32_t reserved7: 25;
|
||||
};
|
||||
uint32_t val;
|
||||
} status_unit[4];
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_rst_u0: 1;
|
||||
/** 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;
|
||||
uint32_t cnt_rst_u1: 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;
|
||||
uint32_t cnt_rst_u2: 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;
|
||||
uint32_t cnt_rst_u3: 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;
|
||||
uint32_t reserved8: 8;
|
||||
uint32_t reserved_8: 8;
|
||||
/** 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 reserved17: 15;
|
||||
uint32_t reserved_17: 15;
|
||||
};
|
||||
uint32_t val;
|
||||
} ctrl;
|
||||
uint32_t reserved_64;
|
||||
uint32_t reserved_68;
|
||||
uint32_t reserved_6c;
|
||||
uint32_t reserved_70;
|
||||
uint32_t reserved_74;
|
||||
uint32_t reserved_78;
|
||||
uint32_t reserved_7c;
|
||||
uint32_t reserved_80;
|
||||
uint32_t reserved_84;
|
||||
uint32_t reserved_88;
|
||||
uint32_t reserved_8c;
|
||||
uint32_t reserved_90;
|
||||
uint32_t reserved_94;
|
||||
uint32_t reserved_98;
|
||||
uint32_t reserved_9c;
|
||||
uint32_t reserved_a0;
|
||||
uint32_t reserved_a4;
|
||||
uint32_t reserved_a8;
|
||||
uint32_t reserved_ac;
|
||||
uint32_t reserved_b0;
|
||||
uint32_t reserved_b4;
|
||||
uint32_t reserved_b8;
|
||||
uint32_t reserved_bc;
|
||||
uint32_t reserved_c0;
|
||||
uint32_t reserved_c4;
|
||||
uint32_t reserved_c8;
|
||||
uint32_t reserved_cc;
|
||||
uint32_t reserved_d0;
|
||||
uint32_t reserved_d4;
|
||||
uint32_t reserved_d8;
|
||||
uint32_t reserved_dc;
|
||||
uint32_t reserved_e0;
|
||||
uint32_t reserved_e4;
|
||||
uint32_t reserved_e8;
|
||||
uint32_t reserved_ec;
|
||||
uint32_t reserved_f0;
|
||||
uint32_t reserved_f4;
|
||||
uint32_t reserved_f8;
|
||||
uint32_t date; /**/
|
||||
} 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;
|
||||
* This register stores 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;
|
||||
* 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;
|
||||
* The latched value of thres1 event of PCNT_Un when threshold event interrupt is
|
||||
* valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0:
|
||||
* others
|
||||
*/
|
||||
uint32_t cnt_thr_thres1_lat_un: 1;
|
||||
/** cnt_thr_thres0_lat_un : RO; bitpos: [3]; default: 0;
|
||||
* The latched value of thres0 event of PCNT_Un when threshold event interrupt is
|
||||
* valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0:
|
||||
* others
|
||||
*/
|
||||
uint32_t cnt_thr_thres0_lat_un: 1;
|
||||
/** cnt_thr_l_lim_lat_un : RO; bitpos: [4]; default: 0;
|
||||
* The latched value of low limit event of PCNT_Un when threshold event interrupt is
|
||||
* valid. 1: the current pulse counter equals to thr_l_lim and low limit event is
|
||||
* valid. 0: others
|
||||
*/
|
||||
uint32_t cnt_thr_l_lim_lat_un: 1;
|
||||
/** cnt_thr_h_lim_lat_un : RO; bitpos: [5]; default: 0;
|
||||
* The latched value of high limit event of PCNT_Un when threshold event interrupt is
|
||||
* valid. 1: the current pulse counter equals to thr_h_lim and high limit event is
|
||||
* valid. 0: others
|
||||
*/
|
||||
uint32_t cnt_thr_h_lim_lat_un: 1;
|
||||
/** cnt_thr_zero_lat_un : RO; bitpos: [6]; default: 0;
|
||||
* The latched value of zero threshold event of PCNT_Un when threshold event interrupt
|
||||
* is valid. 1: the current pulse counter equals to 0 and zero threshold event is
|
||||
* valid. 0: others
|
||||
*/
|
||||
uint32_t cnt_thr_zero_lat_un: 1;
|
||||
uint32_t reserved_7: 25;
|
||||
};
|
||||
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 : RO; 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 : RO; 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 : RO; 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 : RO; 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 : WO; 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 : WO; 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 : WO; 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 : WO; 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: 419898881;
|
||||
* This is the PCNT version control register.
|
||||
*/
|
||||
uint32_t date: 32;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_date_reg_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile struct {
|
||||
pcnt_un_conf0_reg_t conf0;
|
||||
pcnt_un_conf1_reg_t conf1;
|
||||
pcnt_un_conf2_reg_t conf2;
|
||||
} conf_unit[4];
|
||||
volatile pcnt_un_cnt_reg_t cnt_unit[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 status_unit[4];
|
||||
volatile pcnt_ctrl_reg_t ctrl;
|
||||
uint32_t reserved_064[38];
|
||||
volatile pcnt_date_reg_t date;
|
||||
} pcnt_dev_t;
|
||||
|
||||
#ifndef __cplusplus
|
||||
_Static_assert(sizeof(pcnt_dev_t) == 0x100, "Invalid size of pcnt_dev_t structure");
|
||||
#endif
|
||||
|
||||
extern pcnt_dev_t PCNT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SOC_PCNT_STRUCT_H_ */
|
||||
|
@@ -164,10 +164,10 @@
|
||||
#define SOC_MPU_REGION_WO_SUPPORTED 0
|
||||
|
||||
/*-------------------------- PCNT CAPS ---------------------------------------*/
|
||||
// ESP32-S2 have 1 PCNT peripheral
|
||||
#define SOC_PCNT_PORT_NUM (1)
|
||||
#define SOC_PCNT_UNIT_NUM (4) // ESP32-S2 only have 4 unit
|
||||
#define SOC_PCNT_UNIT_CHANNEL_NUM (2)
|
||||
#define SOC_PCNT_GROUPS (1)
|
||||
#define SOC_PCNT_UNITS_PER_GROUP (4)
|
||||
#define SOC_PCNT_CHANNELS_PER_UNIT (2)
|
||||
#define SOC_PCNT_THRES_POINT_PER_UNIT (2)
|
||||
|
||||
/*-------------------------- RMT CAPS ----------------------------------------*/
|
||||
#define SOC_RMT_GROUPS (1) /*!< One RMT group */
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#include "soc/gpio_sig_map.h"
|
||||
|
||||
const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
.groups = {
|
||||
[0] = {
|
||||
.module = PERIPH_PCNT_MODULE,
|
||||
.irq = ETS_PCNT_INTR_SOURCE,
|
||||
.units = {
|
||||
@@ -68,4 +70,6 @@ const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,182 +1,416 @@
|
||||
// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef _SOC_PCNT_STRUCT_H_
|
||||
#define _SOC_PCNT_STRUCT_H_
|
||||
|
||||
/** Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef volatile struct {
|
||||
/** Group: Configuration Register */
|
||||
/** Type of un_conf0 register
|
||||
* Configuration register 0 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
union {
|
||||
struct {
|
||||
uint32_t filter_thres : 10;
|
||||
uint32_t filter_en : 1;
|
||||
uint32_t thr_zero_en : 1;
|
||||
uint32_t thr_h_lim_en : 1;
|
||||
uint32_t thr_l_lim_en : 1;
|
||||
uint32_t thr_thres0_en : 1;
|
||||
uint32_t thr_thres1_en : 1;
|
||||
uint32_t ch0_neg_mode : 2;
|
||||
uint32_t ch0_pos_mode : 2;
|
||||
uint32_t ch0_hctrl_mode : 2;
|
||||
uint32_t ch0_lctrl_mode : 2;
|
||||
uint32_t ch1_neg_mode : 2;
|
||||
uint32_t ch1_pos_mode : 2;
|
||||
uint32_t ch1_hctrl_mode : 2;
|
||||
uint32_t ch1_lctrl_mode : 2;
|
||||
/** filter_thres_un : R/W; bitpos: [9:0]; default: 16;
|
||||
* This sets the maximum threshold, in APB_CLK cycles, for the filter.
|
||||
*
|
||||
* Any pulses with width less than this will be ignored when the filter is enabled.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
* This register sets the behavior when the signal input of channel 0 detects a
|
||||
* negative edge.
|
||||
*
|
||||
* 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter
|
||||
*/
|
||||
uint32_t ch0_neg_mode_un: 2;
|
||||
/** ch0_pos_mode_un : R/W; bitpos: [19:18]; default: 0;
|
||||
* This register sets the behavior when the signal input of channel 0 detects a
|
||||
* positive edge.
|
||||
*
|
||||
* 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter
|
||||
*/
|
||||
uint32_t ch0_pos_mode_un: 2;
|
||||
/** ch0_hctrl_mode_un : R/W; bitpos: [21:20]; default: 0;
|
||||
* This register 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;
|
||||
* This register 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;
|
||||
* This register sets 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 on counter
|
||||
*/
|
||||
uint32_t ch1_neg_mode_un: 2;
|
||||
/** ch1_pos_mode_un : R/W; bitpos: [27:26]; default: 0;
|
||||
* This register sets 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 on counter
|
||||
*/
|
||||
uint32_t ch1_pos_mode_un: 2;
|
||||
/** ch1_hctrl_mode_un : R/W; bitpos: [29:28]; default: 0;
|
||||
* This register 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;
|
||||
* This register 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;
|
||||
} conf0;
|
||||
union {
|
||||
} pcnt_un_conf0_reg_t;
|
||||
|
||||
/** Type of un_conf1 register
|
||||
* Configuration register 1 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t cnt_thres0 : 16;
|
||||
uint32_t cnt_thres1 : 16;
|
||||
/** cnt_thres0_un : R/W; bitpos: [15:0]; default: 0;
|
||||
* This register is used to configure the thres0 value for unit n.
|
||||
*/
|
||||
uint32_t cnt_thres0_un: 16;
|
||||
/** cnt_thres1_un : R/W; bitpos: [31:16]; default: 0;
|
||||
* This register is used to configure the thres1 value for unit n.
|
||||
*/
|
||||
uint32_t cnt_thres1_un: 16;
|
||||
};
|
||||
uint32_t val;
|
||||
} conf1;
|
||||
union {
|
||||
} pcnt_un_conf1_reg_t;
|
||||
|
||||
/** Type of un_conf2 register
|
||||
* Configuration register 2 for unit n
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t cnt_h_lim : 16;
|
||||
uint32_t cnt_l_lim : 16;
|
||||
/** cnt_h_lim_un : R/W; bitpos: [15:0]; default: 0;
|
||||
* This register is used to configure the thr_h_lim value for unit n.
|
||||
*/
|
||||
uint32_t cnt_h_lim_un: 16;
|
||||
/** cnt_l_lim_un : R/W; bitpos: [31:16]; default: 0;
|
||||
* This register is used to configure the thr_l_lim value for unit n.
|
||||
*/
|
||||
uint32_t cnt_l_lim_un: 16;
|
||||
};
|
||||
uint32_t val;
|
||||
} conf2;
|
||||
} conf_unit[4];
|
||||
union {
|
||||
} pcnt_un_conf2_reg_t;
|
||||
|
||||
|
||||
/** Type of ctrl register
|
||||
* Control register for all counters
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t cnt_val : 16;
|
||||
uint32_t reserved16 : 16;
|
||||
};
|
||||
uint32_t val;
|
||||
} cnt_unit[4];
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_thr_event_u0 : 1;
|
||||
uint32_t cnt_thr_event_u1 : 1;
|
||||
uint32_t cnt_thr_event_u2 : 1;
|
||||
uint32_t cnt_thr_event_u3 : 1;
|
||||
uint32_t reserved4 : 28;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_raw;
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_thr_event_u0 : 1;
|
||||
uint32_t cnt_thr_event_u1 : 1;
|
||||
uint32_t cnt_thr_event_u2 : 1;
|
||||
uint32_t cnt_thr_event_u3 : 1;
|
||||
uint32_t reserved4 : 28;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_st;
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_thr_event_u0 : 1;
|
||||
uint32_t cnt_thr_event_u1 : 1;
|
||||
uint32_t cnt_thr_event_u2 : 1;
|
||||
uint32_t cnt_thr_event_u3 : 1;
|
||||
uint32_t reserved4 : 28;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_ena;
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_thr_event_u0 : 1;
|
||||
uint32_t cnt_thr_event_u1 : 1;
|
||||
uint32_t cnt_thr_event_u2 : 1;
|
||||
uint32_t cnt_thr_event_u3 : 1;
|
||||
uint32_t reserved4 : 28;
|
||||
};
|
||||
uint32_t val;
|
||||
} int_clr;
|
||||
union {
|
||||
struct {
|
||||
uint32_t zero_mode : 2;
|
||||
uint32_t thres1_lat : 1;
|
||||
uint32_t thres0_lat : 1;
|
||||
uint32_t l_lim_lat : 1;
|
||||
uint32_t h_lim_lat : 1;
|
||||
uint32_t zero_lat : 1;
|
||||
uint32_t reserved7 : 25;
|
||||
};
|
||||
uint32_t val;
|
||||
} status_unit[4];
|
||||
union {
|
||||
struct {
|
||||
uint32_t cnt_rst_u0 : 1;
|
||||
/** 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;
|
||||
uint32_t cnt_rst_u1 : 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;
|
||||
uint32_t cnt_rst_u2 : 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;
|
||||
uint32_t cnt_rst_u3 : 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;
|
||||
uint32_t reserved8 : 8;
|
||||
uint32_t reserved_8: 8;
|
||||
/** 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 reserved17 : 15;
|
||||
uint32_t reserved_17: 15;
|
||||
};
|
||||
uint32_t val;
|
||||
} ctrl;
|
||||
uint32_t reserved_64;
|
||||
uint32_t reserved_68;
|
||||
uint32_t reserved_6c;
|
||||
uint32_t reserved_70;
|
||||
uint32_t reserved_74;
|
||||
uint32_t reserved_78;
|
||||
uint32_t reserved_7c;
|
||||
uint32_t reserved_80;
|
||||
uint32_t reserved_84;
|
||||
uint32_t reserved_88;
|
||||
uint32_t reserved_8c;
|
||||
uint32_t reserved_90;
|
||||
uint32_t reserved_94;
|
||||
uint32_t reserved_98;
|
||||
uint32_t reserved_9c;
|
||||
uint32_t reserved_a0;
|
||||
uint32_t reserved_a4;
|
||||
uint32_t reserved_a8;
|
||||
uint32_t reserved_ac;
|
||||
uint32_t reserved_b0;
|
||||
uint32_t reserved_b4;
|
||||
uint32_t reserved_b8;
|
||||
uint32_t reserved_bc;
|
||||
uint32_t reserved_c0;
|
||||
uint32_t reserved_c4;
|
||||
uint32_t reserved_c8;
|
||||
uint32_t reserved_cc;
|
||||
uint32_t reserved_d0;
|
||||
uint32_t reserved_d4;
|
||||
uint32_t reserved_d8;
|
||||
uint32_t reserved_dc;
|
||||
uint32_t reserved_e0;
|
||||
uint32_t reserved_e4;
|
||||
uint32_t reserved_e8;
|
||||
uint32_t reserved_ec;
|
||||
uint32_t reserved_f0;
|
||||
uint32_t reserved_f4;
|
||||
uint32_t reserved_f8;
|
||||
uint32_t date;
|
||||
} 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;
|
||||
* This register stores 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;
|
||||
* 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;
|
||||
* The latched value of thres1 event of PCNT_Un when threshold event interrupt is
|
||||
* valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0:
|
||||
* others
|
||||
*/
|
||||
uint32_t cnt_thr_thres1_lat_un: 1;
|
||||
/** cnt_thr_thres0_lat_un : RO; bitpos: [3]; default: 0;
|
||||
* The latched value of thres0 event of PCNT_Un when threshold event interrupt is
|
||||
* valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0:
|
||||
* others
|
||||
*/
|
||||
uint32_t cnt_thr_thres0_lat_un: 1;
|
||||
/** cnt_thr_l_lim_lat_un : RO; bitpos: [4]; default: 0;
|
||||
* The latched value of low limit event of PCNT_Un when threshold event interrupt is
|
||||
* valid. 1: the current pulse counter equals to thr_l_lim and low limit event is
|
||||
* valid. 0: others
|
||||
*/
|
||||
uint32_t cnt_thr_l_lim_lat_un: 1;
|
||||
/** cnt_thr_h_lim_lat_un : RO; bitpos: [5]; default: 0;
|
||||
* The latched value of high limit event of PCNT_Un when threshold event interrupt is
|
||||
* valid. 1: the current pulse counter equals to thr_h_lim and high limit event is
|
||||
* valid. 0: others
|
||||
*/
|
||||
uint32_t cnt_thr_h_lim_lat_un: 1;
|
||||
/** cnt_thr_zero_lat_un : RO; bitpos: [6]; default: 0;
|
||||
* The latched value of zero threshold event of PCNT_Un when threshold event interrupt
|
||||
* is valid. 1: the current pulse counter equals to 0 and zero threshold event is
|
||||
* valid. 0: others
|
||||
*/
|
||||
uint32_t cnt_thr_zero_lat_un: 1;
|
||||
uint32_t reserved_7: 25;
|
||||
};
|
||||
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 : RO; 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 : RO; 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 : RO; 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 : RO; 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 : WO; 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 : WO; 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 : WO; 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 : WO; 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: 419898881;
|
||||
* This is the PCNT version control register.
|
||||
*/
|
||||
uint32_t date: 32;
|
||||
};
|
||||
uint32_t val;
|
||||
} pcnt_date_reg_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile struct {
|
||||
pcnt_un_conf0_reg_t conf0;
|
||||
pcnt_un_conf1_reg_t conf1;
|
||||
pcnt_un_conf2_reg_t conf2;
|
||||
} conf_unit[4];
|
||||
volatile pcnt_un_cnt_reg_t cnt_unit[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 status_unit[4];
|
||||
volatile pcnt_ctrl_reg_t ctrl;
|
||||
uint32_t reserved_064[38];
|
||||
volatile pcnt_date_reg_t date;
|
||||
} pcnt_dev_t;
|
||||
|
||||
#ifndef __cplusplus
|
||||
_Static_assert(sizeof(pcnt_dev_t) == 0x100, "Invalid size of pcnt_dev_t structure");
|
||||
#endif
|
||||
|
||||
extern pcnt_dev_t PCNT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /*_SOC_PCNT_STRUCT_H_ */
|
||||
|
@@ -92,9 +92,10 @@
|
||||
#include "mpu_caps.h"
|
||||
|
||||
/*-------------------------- PCNT CAPS ---------------------------------------*/
|
||||
#define SOC_PCNT_PORT_NUM (1)
|
||||
#define SOC_PCNT_UNIT_NUM (4)
|
||||
#define SOC_PCNT_UNIT_CHANNEL_NUM (2)
|
||||
#define SOC_PCNT_GROUPS (1)
|
||||
#define SOC_PCNT_UNITS_PER_GROUP (4)
|
||||
#define SOC_PCNT_CHANNELS_PER_UNIT (2)
|
||||
#define SOC_PCNT_THRES_POINT_PER_UNIT (2)
|
||||
|
||||
/*-------------------------- RMT CAPS ----------------------------------------*/
|
||||
#define SOC_RMT_GROUPS (1) /*!< One RMT group */
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#include "soc/gpio_sig_map.h"
|
||||
|
||||
const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
.groups = {
|
||||
[0] = {
|
||||
.module = PERIPH_PCNT_MODULE,
|
||||
.irq = ETS_PCNT_INTR_SOURCE,
|
||||
.units = {
|
||||
@@ -68,4 +70,6 @@ const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -25,14 +25,16 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
struct {
|
||||
struct {
|
||||
const uint32_t pulse_sig;
|
||||
const uint32_t control_sig;
|
||||
} channels[SOC_PCNT_UNIT_CHANNEL_NUM];
|
||||
} units[SOC_PCNT_UNIT_NUM];
|
||||
} channels[SOC_PCNT_CHANNELS_PER_UNIT];
|
||||
} units[SOC_PCNT_UNITS_PER_GROUP];
|
||||
const uint32_t irq;
|
||||
const periph_module_t module;
|
||||
} groups[SOC_PCNT_GROUPS];
|
||||
} pcnt_signal_conn_t;
|
||||
|
||||
extern const pcnt_signal_conn_t pcnt_periph_signals;
|
||||
|
@@ -39,11 +39,13 @@
|
||||
#include "hal/rmt_hal.h"
|
||||
#include "hal/rmt_ll.h"
|
||||
#include "hal/pcnt_hal.h"
|
||||
#include "hal/pcnt_ll.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#define REF_CLOCK_RMT_CHANNEL 0 // RMT channel 0
|
||||
#define REF_CLOCK_PCNT_UNIT 0 // PCNT unit 0 channel 0
|
||||
#define REF_CLOCK_PCNT_UNIT 0 // PCNT unit 0
|
||||
#define REF_CLOCK_PCNT_CHANNEL 0// PCNT channel 0
|
||||
#define REF_CLOCK_GPIO 21 // GPIO used to combine RMT out signal with PCNT input signal
|
||||
|
||||
#define REF_CLOCK_PRESCALER_MS 30 // PCNT high threshold interrupt fired every 30ms
|
||||
@@ -109,19 +111,17 @@ void ref_clock_init(void)
|
||||
periph_module_enable(PERIPH_PCNT_MODULE);
|
||||
pcnt_hal_init(&s_pcnt_hal, REF_CLOCK_PCNT_UNIT);
|
||||
|
||||
pcnt_ll_set_mode(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, PCNT_CHANNEL_0,
|
||||
PCNT_COUNT_INC, PCNT_COUNT_INC,
|
||||
PCNT_MODE_KEEP, PCNT_MODE_KEEP);
|
||||
pcnt_ll_event_disable(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, PCNT_EVT_L_LIM);
|
||||
pcnt_ll_event_enable(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, PCNT_EVT_H_LIM);
|
||||
pcnt_ll_event_disable(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, PCNT_EVT_ZERO);
|
||||
pcnt_ll_event_disable(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, PCNT_EVT_THRES_0);
|
||||
pcnt_ll_event_disable(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, PCNT_EVT_THRES_1);
|
||||
pcnt_ll_set_event_value(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, PCNT_EVT_H_LIM, REF_CLOCK_PRESCALER_MS * 1000);
|
||||
pcnt_ll_set_edge_action(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, REF_CLOCK_PCNT_CHANNEL,
|
||||
PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_INCREASE);
|
||||
pcnt_ll_set_level_action(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, REF_CLOCK_PCNT_CHANNEL,
|
||||
PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP);
|
||||
pcnt_ll_disable_all_events(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
pcnt_ll_set_high_limit_value(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, REF_CLOCK_PRESCALER_MS * 1000);
|
||||
pcnt_ll_enable_high_limit_event(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, true);
|
||||
|
||||
// Enable PCNT and wait for it to start counting
|
||||
pcnt_ll_counter_resume(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
pcnt_ll_counter_clear(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
pcnt_ll_start_count(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
pcnt_ll_clear_count(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
|
||||
esp_rom_delay_us(10000);
|
||||
|
||||
@@ -129,7 +129,7 @@ void ref_clock_init(void)
|
||||
s_milliseconds = 0;
|
||||
ESP_ERROR_CHECK(esp_intr_alloc(ETS_PCNT_INTR_SOURCE, ESP_INTR_FLAG_IRAM, pcnt_isr, NULL, &s_intr_handle));
|
||||
pcnt_ll_clear_intr_status(s_pcnt_hal.dev, BIT(REF_CLOCK_PCNT_UNIT));
|
||||
pcnt_ll_intr_enable(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
pcnt_ll_enable_intr(s_pcnt_hal.dev, 1 << REF_CLOCK_PCNT_UNIT, true);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR pcnt_isr(void *arg)
|
||||
@@ -145,7 +145,7 @@ void ref_clock_deinit()
|
||||
assert(s_intr_handle && "ref clock deinit called without init");
|
||||
|
||||
// Disable interrupt
|
||||
pcnt_ll_intr_disable(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
pcnt_ll_enable_intr(s_pcnt_hal.dev, 1 << REF_CLOCK_PCNT_UNIT, false);
|
||||
esp_intr_free(s_intr_handle);
|
||||
s_intr_handle = NULL;
|
||||
|
||||
@@ -154,21 +154,20 @@ void ref_clock_deinit()
|
||||
periph_module_disable(PERIPH_RMT_MODULE);
|
||||
|
||||
// Disable PCNT
|
||||
pcnt_ll_counter_pause(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
pcnt_ll_stop_count(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
periph_module_disable(PERIPH_PCNT_MODULE);
|
||||
}
|
||||
|
||||
uint64_t ref_clock_get()
|
||||
{
|
||||
portENTER_CRITICAL(&s_lock);
|
||||
int16_t microseconds = 0;
|
||||
pcnt_ll_get_counter_value(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, µseconds);
|
||||
int microseconds = 0;
|
||||
microseconds = pcnt_ll_get_count(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
uint32_t milliseconds = s_milliseconds;
|
||||
uint32_t intr_status = 0;
|
||||
pcnt_ll_get_intr_status(s_pcnt_hal.dev, &intr_status);
|
||||
uint32_t intr_status = pcnt_ll_get_intr_status(s_pcnt_hal.dev);
|
||||
if (intr_status & BIT(REF_CLOCK_PCNT_UNIT)) {
|
||||
// refresh counter value, in case the overflow has happened after reading cnt_val
|
||||
pcnt_ll_get_counter_value(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT, µseconds);
|
||||
microseconds = pcnt_ll_get_count(s_pcnt_hal.dev, REF_CLOCK_PCNT_UNIT);
|
||||
milliseconds += REF_CLOCK_PRESCALER_MS;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_lock);
|
||||
|
Reference in New Issue
Block a user