mirror of
https://github.com/espressif/esp-idf.git
synced 2025-11-27 20:59:29 +01:00
Merge branch 'feature/touch_driver_ng_on_32' into 'master'
feat(touch): support touch v1 in new touch driver Closes IDF-10183 and IDF-11423 See merge request espressif/esp-idf!34781
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -17,12 +17,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "hal/misc.h"
|
||||
#include "hal/assert.h"
|
||||
#include "soc/touch_sensor_periph.h"
|
||||
#include "soc/sens_struct.h"
|
||||
#include "soc/rtc_io_struct.h"
|
||||
#include "soc/rtc_cntl_struct.h"
|
||||
#include "hal/touch_sensor_legacy_types.h"
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/touch_sens_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -30,9 +31,413 @@ extern "C" {
|
||||
|
||||
//Some register bits of touch sensor 8 and 9 are mismatched, we need to swap the bits.
|
||||
#define TOUCH_LL_BIT_SWAP(data, n, m) (((data >> n) & 0x1) == ((data >> m) & 0x1) ? (data) : ((data) ^ ((0x1 <<n) | (0x1 << m))))
|
||||
#define TOUCH_LL_BITS_SWAP(v) TOUCH_LL_BIT_SWAP(v, TOUCH_PAD_NUM8, TOUCH_PAD_NUM9)
|
||||
#define TOUCH_LL_BITS_SWAP(v) TOUCH_LL_BIT_SWAP(v, 8, 9)
|
||||
#define TOUCH_LL_CHAN_SWAP(chan) ((chan) == 8 ? 9 : ((chan) == 9 ? 8 : (chan)))
|
||||
#define TOUCH_LL_FULL_CHANNEL_MASK ((uint16_t)((1U << SOC_TOUCH_SENSOR_NUM) - 1))
|
||||
#define TOUCH_LL_READ_RAW 0x0
|
||||
|
||||
#define TOUCH_LL_PAD_MEASURE_WAIT_MAX (0xFF) /*!<The timer frequency is 8Mhz, the max value is 0xff */
|
||||
#define TOUCH_LL_CHARGE_DURATION_MAX (0xFFFF)
|
||||
#define TOUCH_LL_PAD_MEASURE_WAIT_MAX (0xFF) // The timer frequency is 8Mhz, the max value is 0xff
|
||||
#define TOUCH_LL_ACTIVE_THRESH_MAX (0xFFFF) // Max channel active threshold
|
||||
|
||||
#define TOUCH_LL_INTR_MASK_TRIGGER (1UL << 6) // Interrupt when the touch interrupt is triggered (depends on intr trigger mode)
|
||||
#define TOUCH_LL_INTR_MASK_ALL (TOUCH_LL_INTR_MASK_TRIGGER)
|
||||
|
||||
/*********************************** Interrupts *******************************/
|
||||
/**
|
||||
* Enable touch sensor interrupt by bitmask.
|
||||
*
|
||||
* @param int_mask interrupt mask
|
||||
*/
|
||||
static inline void touch_ll_interrupt_enable(uint32_t int_mask)
|
||||
{
|
||||
(void) int_mask;
|
||||
// Only one interrupt, set directly
|
||||
RTCCNTL.int_ena.rtc_touch = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable touch sensor interrupt by bitmask.
|
||||
*
|
||||
* @param int_mask interrupt mask
|
||||
*/
|
||||
static inline void touch_ll_interrupt_disable(uint32_t int_mask)
|
||||
{
|
||||
(void) int_mask;
|
||||
// Only one interrupt, clear directly
|
||||
RTCCNTL.int_ena.rtc_touch = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear touch sensor interrupt by bitmask.
|
||||
*
|
||||
* @param int_mask Pad mask to clear interrupts
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void touch_ll_interrupt_clear(uint32_t int_mask)
|
||||
{
|
||||
(void) int_mask;
|
||||
RTCCNTL.int_clr.rtc_touch = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bitmask of touch sensor interrupt status.
|
||||
*
|
||||
* @return type interrupt type
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline uint32_t touch_ll_get_intr_status_mask(void)
|
||||
{
|
||||
// intr status bit of touch (bit7) is not same as the enable bit (bit6)
|
||||
return RTCCNTL.int_st.rtc_touch ? TOUCH_LL_INTR_MASK_TRIGGER : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set touch sensor interrupt trigger mode.
|
||||
* Interrupt can be triggered either when touch value is below the threshold (touched) or
|
||||
* or when touch value exceed the threshold (release).
|
||||
*
|
||||
* @param mode Touch sensor interrupt trigger mode.
|
||||
* - TOUCH_INTR_TRIG_ON_BELOW_THRESH: interrupt triggers when touched (touch value is below the threshold)
|
||||
* - TOUCH_INTR_TRIG_ON_ABOVE_THRESH: interrupt triggers when released (touch value is exceed the threshold)
|
||||
*/
|
||||
static inline void touch_ll_set_intr_trigger_mode(touch_intr_trig_mode_t mode)
|
||||
{
|
||||
SENS.sar_touch_ctrl1.touch_out_sel = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set touch sensor interrupt trigger source. There are two sets of touch signals.
|
||||
* Set1 and set2 can be mapped to several touch signals. Either set will be triggered
|
||||
* if at least one of its touch signal is 'touched'. The interrupt can be configured to be generated
|
||||
* if set1 is triggered, or only if both sets are triggered.
|
||||
*
|
||||
* @param group Touch sensor interrupt trigger group.
|
||||
*/
|
||||
static inline void touch_ll_set_intr_trigger_group(touch_intr_trig_group_t group)
|
||||
{
|
||||
SENS.sar_touch_ctrl1.touch_out_1en = group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set touch sensor group mask.
|
||||
* Touch pad module has two sets of signals, 'Touched' signal is triggered only if
|
||||
* at least one of touch pad in this group is "touched".
|
||||
* This function will set the register bits according to the given bitmask.
|
||||
*
|
||||
* @param group1_mask bitmask of touch sensor signal group1, it's a 10-bit value
|
||||
* @param group2_mask bitmask of touch sensor signal group2, it's a 10-bit value
|
||||
*/
|
||||
static inline void touch_ll_config_trigger_group1(uint32_t touch_num, bool enable)
|
||||
{
|
||||
touch_num = TOUCH_LL_CHAN_SWAP(touch_num);
|
||||
uint32_t mask = SENS.sar_touch_enable.touch_pad_outen1;
|
||||
if (enable) {
|
||||
mask |= (1 << touch_num);
|
||||
} else {
|
||||
mask &= ~(1 << touch_num);
|
||||
}
|
||||
SENS.sar_touch_enable.touch_pad_outen1 = mask;
|
||||
}
|
||||
|
||||
static inline void touch_ll_config_trigger_group2(uint32_t touch_num, bool enable)
|
||||
{
|
||||
touch_num = TOUCH_LL_CHAN_SWAP(touch_num);
|
||||
uint32_t mask = SENS.sar_touch_enable.touch_pad_outen2;
|
||||
if (enable) {
|
||||
mask |= (1 << touch_num);
|
||||
} else {
|
||||
mask &= ~(1 << touch_num);
|
||||
}
|
||||
SENS.sar_touch_enable.touch_pad_outen2 = mask;
|
||||
}
|
||||
|
||||
static inline void touch_ll_reset_trigger_groups(void)
|
||||
{
|
||||
SENS.sar_touch_enable.touch_pad_outen1 = 0;
|
||||
SENS.sar_touch_enable.touch_pad_outen2 = 0;
|
||||
}
|
||||
|
||||
/********************************* Status Info ********************************/
|
||||
/**
|
||||
* Get touch sensor measure status. No block.
|
||||
*
|
||||
* @return
|
||||
* - If touch sensors measure done.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool touch_ll_is_measure_done(void)
|
||||
{
|
||||
return (bool)SENS.sar_touch_ctrl2.touch_meas_done;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the touch sensor active channel mask, usually used in ISR to decide which channels are 'touched'.
|
||||
*
|
||||
* @param active_mask The touch channel status. e.g. Touch1 trigger status is `status_mask & (BIT1)`.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void touch_ll_get_active_channel_mask(uint32_t *active_mask)
|
||||
{
|
||||
*active_mask = TOUCH_LL_BITS_SWAP(SENS.sar_touch_ctrl2.touch_meas_en);
|
||||
}
|
||||
|
||||
/**************************** Measurement Configuration ***********************/
|
||||
|
||||
/**
|
||||
* Set touch sensor threshold of charge cycles that triggers pad active state.
|
||||
* The threshold determines the sensitivity of the touch sensor.
|
||||
* The threshold is the original value of the trigger state minus the benchmark value.
|
||||
*
|
||||
* @note If set "TOUCH_PAD_THRESHOLD_MAX", the touch is never be triggered.
|
||||
* @param touch_num The touch pad id
|
||||
* @param thresh The threshold of charge cycles
|
||||
*/
|
||||
static inline void touch_ll_set_chan_active_threshold(uint32_t touch_num, uint32_t thresh)
|
||||
{
|
||||
// Workaround: swap chan 8 and chan 9
|
||||
touch_num = TOUCH_LL_CHAN_SWAP(touch_num);
|
||||
if (touch_num & 0x1) {
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.touch_thresh[touch_num >> 1], l_thresh, thresh);
|
||||
} else {
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.touch_thresh[touch_num >> 1], h_thresh, thresh);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get touch sensor threshold of charge cycles that triggers pad active state.
|
||||
* The threshold determines the sensitivity of the touch sensor.
|
||||
* The threshold is the original value of the trigger state minus the benchmark value.
|
||||
*
|
||||
* @note If set "TOUCH_PAD_THRESHOLD_MAX", the touch is never be triggered.
|
||||
* @param touch_num The touch pad id
|
||||
* @return
|
||||
* - The threshold of charge cycles
|
||||
*/
|
||||
static inline uint32_t touch_ll_get_chan_active_threshold(uint32_t touch_num)
|
||||
{
|
||||
// Workaround: swap chan 8 and chan 9
|
||||
touch_num = TOUCH_LL_CHAN_SWAP(touch_num);
|
||||
if (touch_num & 0x1) {
|
||||
return HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_thresh[touch_num >> 1], l_thresh);
|
||||
} else {
|
||||
return HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_thresh[touch_num >> 1], h_thresh);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the power on wait cycle
|
||||
*
|
||||
* @param wait_cycles
|
||||
*/
|
||||
static inline void touch_ll_set_power_on_wait_cycle(uint32_t wait_cycles)
|
||||
{
|
||||
//the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_xpd_wait, wait_cycles); //wait volt stable
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the duration of the charge window
|
||||
*
|
||||
* @param duration The duration of the touch channel charge / discharge window.
|
||||
* duration = meas_ticks / (8MHz), the maximum duration is 0xffff / 8M = 8.19 ms.
|
||||
*/
|
||||
static inline void touch_ll_set_charge_window_duration(uint32_t duration)
|
||||
{
|
||||
//touch sensor charge/discharge window duration= meas_cycle / 8Mhz
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_meas_delay, duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set touch sensor sleep time.
|
||||
*
|
||||
* @param interval_ticks The touch sensor will sleep for some cycles after each measurement.
|
||||
* interval_ticks decide the interval between each measurement.
|
||||
* t_sleep = interval_ticks / (RTC_SLOW_CLK frequency).
|
||||
* The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function.
|
||||
*/
|
||||
static inline void touch_ll_set_measure_interval_ticks(uint16_t interval_ticks)
|
||||
{
|
||||
//touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl2, touch_sleep_cycles, interval_ticks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Touch pad charge speed.
|
||||
*
|
||||
* @param touch_num Touch channel number
|
||||
* @param charge_speed Charge speed of this touch channel
|
||||
*/
|
||||
static inline void touch_ll_set_charge_speed(uint32_t touch_num, touch_charge_speed_t charge_speed)
|
||||
{
|
||||
RTCIO.touch_pad[touch_num].dac = charge_speed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the upper limitation of the touch channel voltage while charging
|
||||
*
|
||||
* @param high_lim The high(upper) limitation of charge
|
||||
*/
|
||||
static inline void touch_ll_set_charge_voltage_high_limit(touch_volt_lim_h_t high_lim)
|
||||
{
|
||||
RTCIO.touch_cfg.drefh = (uint32_t)high_lim & 0x3;
|
||||
RTCIO.touch_cfg.drange = (uint32_t)high_lim >> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the lower limitation of the touch channel voltage while discharging
|
||||
*
|
||||
* @param low_lim The lower limitation of discharge
|
||||
*/
|
||||
static inline void touch_ll_set_charge_voltage_low_limit(touch_volt_lim_l_t low_lim)
|
||||
{
|
||||
RTCIO.touch_cfg.drefl = low_lim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the initial charge voltage of touch channel
|
||||
* i.e., the touch pad measurement start from a low voltage or a high voltage
|
||||
*
|
||||
* @param touch_num Touch channel number
|
||||
* @param init_charge_volt The initial charge voltage
|
||||
*/
|
||||
static inline void touch_ll_set_init_charge_voltage(uint32_t touch_num, touch_init_charge_volt_t init_charge_volt)
|
||||
{
|
||||
// Workaround: swap chan 8 and chan 9
|
||||
touch_num = TOUCH_LL_CHAN_SWAP(touch_num);
|
||||
RTCIO.touch_pad[touch_num].tie_opt = init_charge_volt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable touch sensor channel. Register touch channel into touch sensor measurement group.
|
||||
* The working mode of the touch sensor is simultaneous measurement.
|
||||
* This function will set the measure bits according to the given bitmask.
|
||||
*
|
||||
* @note If set this mask, the FSM timer should be stop firstly.
|
||||
* @note The touch sensor that in scan map, should be deinit GPIO function firstly.
|
||||
* @param enable_mask bitmask of touch sensor scan group.
|
||||
* e.g. TOUCH_PAD_NUM1 -> BIT(1)
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
static inline void touch_ll_enable_channel_mask(uint16_t enable_mask)
|
||||
{
|
||||
SENS.sar_touch_enable.touch_pad_worken = enable_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all touch sensor channels active status.
|
||||
*
|
||||
* @note Generally no manual removal is required.
|
||||
*/
|
||||
static inline void touch_ll_clear_active_channel_status(void)
|
||||
{
|
||||
SENS.sar_touch_ctrl2.touch_meas_en_clr = 1;
|
||||
}
|
||||
|
||||
/********************************* FSM Operation ******************************/
|
||||
/**
|
||||
* Enable touch sensor FSM timer trigger (continuous) mode or software trigger (oneshot) mode.
|
||||
*
|
||||
* @param enable Enable FSM timer mode.
|
||||
* True: the FSM will trigger scanning repeatedly under the control of the hardware timer (continuous mode)
|
||||
* False: the FSM will trigger scanning once under the control of the software (continuous mode)
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void touch_ll_enable_fsm_timer(bool enable)
|
||||
{
|
||||
SENS.sar_touch_ctrl2.touch_start_force = !enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start touch sensor FSM timer to run FSM repeatedly
|
||||
* The measurement action can be triggered by the hardware timer, as well as by the software instruction.
|
||||
* @note
|
||||
* The timer should be triggered
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void touch_ll_start_fsm_repeated_timer(void)
|
||||
{
|
||||
RTCCNTL.state0.touch_slp_timer_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop touch sensor FSM timer.
|
||||
* The measurement action can be triggered by the hardware timer, as well as by the software instruction.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void touch_ll_stop_fsm_repeated_timer(void)
|
||||
{
|
||||
RTCCNTL.state0.touch_slp_timer_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the FSM repeated timer enabled.
|
||||
* @note when the timer is enabled, RTC clock should not be power down
|
||||
*
|
||||
* @return
|
||||
* - true: enabled
|
||||
* - false: disabled
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool touch_ll_is_fsm_repeated_timer_enabled(void)
|
||||
{
|
||||
return (bool)RTCCNTL.state0.touch_slp_timer_en;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable the touch sensor FSM start signal from software
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void touch_ll_trigger_oneshot_measurement(void)
|
||||
{
|
||||
SENS.sar_touch_ctrl2.touch_start_en = 1;
|
||||
SENS.sar_touch_ctrl2.touch_start_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Power on the channel by mask
|
||||
*
|
||||
* @param chan_mask The channel mask that needs to power on
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void touch_ll_channel_sw_measure_mask(uint16_t chan_mask)
|
||||
{
|
||||
(void) chan_mask;
|
||||
// Only for compatibility
|
||||
}
|
||||
|
||||
/************************************** Data **********************************/
|
||||
/**
|
||||
* Get the data of the touch channel according to the types
|
||||
*
|
||||
* @param touch_num touch pad index
|
||||
* @param type data type
|
||||
* 0/1: TOUCH_LL_READ_RAW, raw data of touch channel
|
||||
* 2: TOUCH_LL_READ_BENCHMARK, benchmark value of touch channel,
|
||||
* the benchmark value is the maximum during the first measurement period
|
||||
* 3: TOUCH_LL_READ_SMOOTH, the smoothed data that obtained by filtering the raw data.
|
||||
* @param data pointer to the data
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void touch_ll_read_chan_data(uint32_t touch_num, uint8_t type, uint32_t *data)
|
||||
{
|
||||
HAL_ASSERT(type == TOUCH_LL_READ_RAW);
|
||||
HAL_ASSERT(touch_num < SOC_TOUCH_SENSOR_NUM);
|
||||
touch_num = TOUCH_LL_CHAN_SWAP(touch_num);
|
||||
if (touch_num & 0x1) {
|
||||
*data = HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[touch_num >> 1], l_val);
|
||||
} else {
|
||||
*data = HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[touch_num >> 1], h_val);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Legacy APIs (to be removed in esp-idf v6.0) */
|
||||
/******************************************************************************/
|
||||
|
||||
#include "hal/touch_sensor_legacy_types.h"
|
||||
|
||||
/**
|
||||
* Swap the number of touch8 and touch9.
|
||||
@@ -493,18 +898,6 @@ static inline uint32_t touch_ll_read_raw_data(touch_pad_t touch_num)
|
||||
HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[tp_wrap / 2], h_val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get touch sensor measure status. No block.
|
||||
*
|
||||
* @return
|
||||
* - If touch sensors measure done.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool touch_ll_is_measure_done(void)
|
||||
{
|
||||
return (bool)SENS.sar_touch_ctrl2.touch_meas_done;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user