410 lines
12 KiB
C
Raw Normal View History

2021-08-10 17:19:12 +08:00
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
2019-07-15 14:44:15 +08:00
//
// 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.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in hal/include/hal/readme.md
2019-07-15 14:44:15 +08:00
******************************************************************************/
// The LL layer for ESP32 PCNT register operations
#pragma once
2021-08-10 17:19:12 +08:00
#include <stdlib.h>
#include <stdbool.h>
#include "soc/pcnt_struct.h"
2019-07-15 14:44:15 +08:00
#include "hal/pcnt_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define PCNT_LL_GET_HW(num) (((num) == 0) ? (&PCNT) : NULL)
2021-08-10 17:19:12 +08:00
#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)
2019-07-15 14:44:15 +08:00
/**
2021-08-10 17:19:12 +08:00
* @brief Set PCNT channel edge action
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param channel PCNT channel number
2021-08-10 17:19:12 +08:00
* @param pos_act Counter action when detecting positive edge
* @param neg_act Counter action when detecting negative edge
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
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)
2019-07-15 14:44:15 +08:00
{
if (channel == 0) {
2021-08-10 17:19:12 +08:00
hw->conf_unit[unit].conf0.ch0_pos_mode = pos_act;
hw->conf_unit[unit].conf0.ch0_neg_mode = neg_act;
2019-07-15 14:44:15 +08:00
} else {
2021-08-10 17:19:12 +08:00
hw->conf_unit[unit].conf0.ch1_pos_mode = pos_act;
hw->conf_unit[unit].conf0.ch1_neg_mode = neg_act;
}
}
/**
2021-08-10 17:19:12 +08:00
* @brief Set PCNT channel level action
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param channel PCNT channel number
2021-08-10 17:19:12 +08:00
* @param high_act Counter action when control signal is high level
* @param low_act Counter action when control signal is low level
*/
2021-08-10 17:19:12 +08:00
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)
{
if (channel == 0) {
2021-08-10 17:19:12 +08:00
hw->conf_unit[unit].conf0.ch0_hctrl_mode = high_act;
hw->conf_unit[unit].conf0.ch0_lctrl_mode = low_act;
} else {
2021-08-10 17:19:12 +08:00
hw->conf_unit[unit].conf0.ch1_hctrl_mode = high_act;
hw->conf_unit[unit].conf0.ch1_lctrl_mode = low_act;
2019-07-15 14:44:15 +08:00
}
}
/**
2021-08-10 17:19:12 +08:00
* @brief Get pulse counter value
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit Pulse Counter unit number
* @return PCNT count value (a signed integer)
*/
static inline int pcnt_ll_get_count(pcnt_dev_t *hw, uint32_t unit)
{
typeof(hw->cnt_unit[unit]) cnt_reg = hw->cnt_unit[unit];
int16_t value = cnt_reg.cnt_val;
return value;
}
/**
* @brief Pause PCNT counter of PCNT unit
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_stop_count(pcnt_dev_t *hw, uint32_t unit)
{
2021-08-10 17:19:12 +08:00
hw->ctrl.val |= 1 << (2 * unit + 1);
}
2019-07-15 14:44:15 +08:00
/**
2021-08-10 17:19:12 +08:00
* @brief Resume counting for PCNT counter
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
2021-08-10 17:19:12 +08:00
* @param unit PCNT unit number, select from uint32_t
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_start_count(pcnt_dev_t *hw, uint32_t unit)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
hw->ctrl.val &= ~(1 << (2 * unit + 1));
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Clear PCNT counter value to zero
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
2021-08-10 17:19:12 +08:00
* @param unit PCNT unit number, select from uint32_t
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_clear_count(pcnt_dev_t *hw, uint32_t unit)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
hw->ctrl.val |= 1 << (2 * unit);
hw->ctrl.val &= ~(1 << (2 * unit));
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Enable PCNT interrupt for PCNT unit
* @note Each PCNT unit has five watch point events that share the same interrupt bit.
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
2021-08-10 17:19:12 +08:00
* @param unit_mask PCNT units mask
* @param enable True to enable interrupt, False to disable interrupt
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_enable_intr(pcnt_dev_t *hw, uint32_t unit_mask, bool enable)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
if (enable) {
hw->int_ena.val |= unit_mask;
} else {
hw->int_ena.val &= ~unit_mask;
}
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Get PCNT interrupt status
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
2021-08-10 17:19:12 +08:00
* @return Interrupt status word
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
__attribute__((always_inline)) static inline uint32_t pcnt_ll_get_intr_status(pcnt_dev_t *hw)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
return hw->int_st.val;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Clear PCNT interrupt status
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
2021-08-10 17:19:12 +08:00
* @param status value to clear interrupt status
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
__attribute__((always_inline)) static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
hw->int_clr.val = status;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Enable PCNT high limit event
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
2021-08-10 17:19:12 +08:00
* @param enable true to enable, false to disable
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_enable_high_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
hw->conf_unit[unit].conf0.thr_h_lim_en = enable;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Enable PCNT low limit event
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
2021-08-10 17:19:12 +08:00
* @param unit PCNT unit number
* @param enable true to enable, false to disable
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_enable_low_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
hw->conf_unit[unit].conf0.thr_l_lim_en = enable;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Enable PCNT zero cross event
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
2021-08-10 17:19:12 +08:00
* @param unit PCNT unit number
* @param enable true to enable, false to disable
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_enable_zero_cross_event(pcnt_dev_t *hw, uint32_t unit, bool enable)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
hw->conf_unit[unit].conf0.thr_zero_en = enable;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Enable PCNT threshold event
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
2021-08-10 17:19:12 +08:00
* @param thres Threshold ID
* @param enable true to enable, false to disable
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_enable_thres_event(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, bool enable)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
if (thres == 0) {
hw->conf_unit[unit].conf0.thr_thres0_en = enable;
} else {
hw->conf_unit[unit].conf0.thr_thres1_en = enable;
2019-07-15 14:44:15 +08:00
}
}
/**
2021-08-10 17:19:12 +08:00
* @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
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
2021-08-10 17:19:12 +08:00
* @param value PCNT high limit value
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_set_high_limit_value(pcnt_dev_t *hw, uint32_t unit, int value)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
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;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Set PCNT low limit value
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
2021-08-10 17:19:12 +08:00
* @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
2019-07-15 14:44:15 +08:00
*
2021-08-10 17:19:12 +08:00
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
* @param thres Threshold ID
* @param value PCNT threshold value
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_set_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, int value)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
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;
2019-07-15 14:44:15 +08:00
}
2021-08-10 17:19:12 +08:00
hw->conf_unit[unit].conf1 = conf1_reg;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Get PCNT high limit value
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
2021-08-10 17:19:12 +08:00
* @return PCNT high limit value
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline int pcnt_ll_get_high_limit_value(pcnt_dev_t *hw, uint32_t unit)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
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;
2019-07-15 14:44:15 +08:00
} else {
2021-08-10 17:19:12 +08:00
value = conf1_reg.cnt_thres1;
2019-07-15 14:44:15 +08:00
}
2021-08-10 17:19:12 +08:00
return value;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Get PCNT unit runtime status
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
2021-08-10 17:19:12 +08:00
* @return PCNT unit runtime status
*/
2021-08-10 17:19:12 +08:00
static inline uint32_t pcnt_ll_get_unit_status(pcnt_dev_t *hw, uint32_t unit)
{
return hw->status_unit[unit].val;
}
2019-07-15 14:44:15 +08:00
/**
2021-08-10 17:19:12 +08:00
* @brief Get PCNT count sign
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
2021-08-10 17:19:12 +08:00
* @return Count sign
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline pcnt_unit_count_sign_t pcnt_ll_get_count_sign(pcnt_dev_t *hw, uint32_t unit)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
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
*/
static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, uint32_t unit)
{
return hw->status_unit[unit].val >> 2;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Set PCNT glitch filter threshold
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
2021-08-10 17:19:12 +08:00
* @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.
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_set_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit, uint32_t filter_val)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
hw->conf_unit[unit].conf0.filter_thres = filter_val;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Get PCNT glitch filter threshold
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
2021-08-10 17:19:12 +08:00
* @return glitch filter threshold
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline uint32_t pcnt_ll_get_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
return hw->conf_unit[unit].conf0.filter_thres;
2019-07-15 14:44:15 +08:00
}
/**
2021-08-10 17:19:12 +08:00
* @brief Enable PCNT glitch filter
2019-07-15 14:44:15 +08:00
*
* @param hw Peripheral PCNT hardware instance address.
* @param unit PCNT unit number
2021-08-10 17:19:12 +08:00
* @param enable True to enable the filter, False to disable the filter
2019-07-15 14:44:15 +08:00
*/
2021-08-10 17:19:12 +08:00
static inline void pcnt_ll_enable_glitch_filter(pcnt_dev_t *hw, uint32_t unit, bool enable)
2019-07-15 14:44:15 +08:00
{
2021-08-10 17:19:12 +08:00
hw->conf_unit[unit].conf0.filter_en = enable;
2019-07-15 14:44:15 +08:00
}
#ifdef __cplusplus
}
#endif