Selaa lähdekoodia

Merge branch 'bugfix/touch_pad_driver' into 'master'

driver(touch): fix bug and add more features

See merge request !1056

Wang Jia Lin 8 vuotta sitten
vanhempi
sitoutus
f1ecffb46c

+ 432 - 106
components/driver/include/driver/touch_pad.h

@@ -20,150 +20,476 @@ extern "C" {
 #include "esp_intr.h"
 #include "esp_intr.h"
 #include "esp_err.h"
 #include "esp_err.h"
 #include "esp_intr_alloc.h"
 #include "esp_intr_alloc.h"
-#define TOUCH_PAD_SLEEP_CYCLE_CONFIG   (0x1000)//The Time is 150Khz,the Max value is 0xffff
-#define TOUCH_PAD_MEASURE_CYCLE_CONFIG (0xffff)//The Time is 8Mhz,the Max value is 0xffff
+
 typedef enum {
 typedef enum {
     TOUCH_PAD_NUM0 = 0, /*!< Touch pad channel 0 is GPIO4 */
     TOUCH_PAD_NUM0 = 0, /*!< Touch pad channel 0 is GPIO4 */
-    TOUCH_PAD_NUM1,    /*!< Touch pad channel 0 is GPIO0 */
-    TOUCH_PAD_NUM2,    /*!< Touch pad channel 0 is GPIO2 */
-    TOUCH_PAD_NUM3,    /*!< Touch pad channel 0 is GPIO15 */
-    TOUCH_PAD_NUM4,    /*!< Touch pad channel 0 is GPIO13 */
-    TOUCH_PAD_NUM5,    /*!< Touch pad channel 0 is GPIO12 */
-    TOUCH_PAD_NUM6,    /*!< Touch pad channel 0 is GPIO14 */
-    TOUCH_PAD_NUM7,    /*!< Touch pad channel 0 is GPIO27*/
-    TOUCH_PAD_NUM8,    /*!< Touch pad channel 0 is GPIO33*/
-    TOUCH_PAD_NUM9,    /*!< Touch pad channel 0 is GPIO32*/
+    TOUCH_PAD_NUM1,     /*!< Touch pad channel 1 is GPIO0 */
+    TOUCH_PAD_NUM2,     /*!< Touch pad channel 2 is GPIO2 */
+    TOUCH_PAD_NUM3,     /*!< Touch pad channel 3 is GPIO15*/
+    TOUCH_PAD_NUM4,     /*!< Touch pad channel 4 is GPIO13*/
+    TOUCH_PAD_NUM5,     /*!< Touch pad channel 5 is GPIO12*/
+    TOUCH_PAD_NUM6,     /*!< Touch pad channel 6 is GPIO14*/
+    TOUCH_PAD_NUM7,     /*!< Touch pad channel 7 is GPIO27*/
+    TOUCH_PAD_NUM8,     /*!< Touch pad channel 8 is GPIO32*/
+    TOUCH_PAD_NUM9,     /*!< Touch pad channel 9 is GPIO33*/
     TOUCH_PAD_MAX,
     TOUCH_PAD_MAX,
 } touch_pad_t;
 } touch_pad_t;
 
 
+typedef enum {
+    TOUCH_HVOLT_KEEP = -1, /*!<Touch sensor high reference voltage, no change  */
+    TOUCH_HVOLT_2V4 = 0,   /*!<Touch sensor high reference voltage, 2.4V  */
+    TOUCH_HVOLT_2V5,       /*!<Touch sensor high reference voltage, 2.5V  */
+    TOUCH_HVOLT_2V6,       /*!<Touch sensor high reference voltage, 2.6V  */
+    TOUCH_HVOLT_2V7,       /*!<Touch sensor high reference voltage, 2.7V  */
+    TOUCH_HVOLT_MAX,
+} touch_high_volt_t;
+
+typedef enum {
+    TOUCH_LVOLT_KEEP = -1, /*!<Touch sensor low reference voltage, no change  */
+    TOUCH_LVOLT_0V5 = 0,   /*!<Touch sensor low reference voltage, 0.5V  */
+    TOUCH_LVOLT_0V6,       /*!<Touch sensor low reference voltage, 0.6V  */
+    TOUCH_LVOLT_0V7,       /*!<Touch sensor low reference voltage, 0.7V  */
+    TOUCH_LVOLT_0V8,       /*!<Touch sensor low reference voltage, 0.8V  */
+    TOUCH_LVOLT_MAX,
+} touch_low_volt_t;
+
+typedef enum {
+    TOUCH_HVOLT_ATTEN_KEEP = -1,  /*!<Touch sensor high reference voltage attenuation, no change  */
+    TOUCH_HVOLT_ATTEN_1V5 = 0,    /*!<Touch sensor high reference voltage attenuation, 1.5V attenuation  */
+    TOUCH_HVOLT_ATTEN_1V,         /*!<Touch sensor high reference voltage attenuation, 1.0V attenuation  */
+    TOUCH_HVOLT_ATTEN_0V5,        /*!<Touch sensor high reference voltage attenuation, 0.5V attenuation  */
+    TOUCH_HVOLT_ATTEN_0V,         /*!<Touch sensor high reference voltage attenuation,   0V attenuation  */
+    TOUCH_HVOLT_ATTEN_MAX,
+} touch_volt_atten_t;
+
+typedef enum {
+    TOUCH_PAD_SLOPE_0 = 0,       /*!<Touch sensor charge / discharge speed, always zero  */
+    TOUCH_PAD_SLOPE_1 = 1,       /*!<Touch sensor charge / discharge speed, slowest  */
+    TOUCH_PAD_SLOPE_2 = 2,       /*!<Touch sensor charge / discharge speed */
+    TOUCH_PAD_SLOPE_3 = 3,       /*!<Touch sensor charge / discharge speed  */
+    TOUCH_PAD_SLOPE_4 = 4,       /*!<Touch sensor charge / discharge speed  */
+    TOUCH_PAD_SLOPE_5 = 5,       /*!<Touch sensor charge / discharge speed  */
+    TOUCH_PAD_SLOPE_6 = 6,       /*!<Touch sensor charge / discharge speed  */
+    TOUCH_PAD_SLOPE_7 = 7,       /*!<Touch sensor charge / discharge speed, fast  */
+    TOUCH_PAD_SLOPE_MAX,
+} touch_cnt_slope_t;
+
+typedef enum {
+    TOUCH_TRIGGER_BELOW = 0,   /*!<Touch interrupt will happen if counter value is less than threshold.*/
+    TOUCH_TRIGGER_ABOVE = 1,   /*!<Touch interrupt will happen if counter value is larger than threshold.*/
+    TOUCH_TRIGGER_MAX,
+} touch_trigger_mode_t;
+
+typedef enum {
+    TOUCH_TRIGGER_SOURCE_BOTH = 0,  /*!< wakeup interrupt is generated if both SET1 and SET2 are "touched"*/
+    TOUCH_TRIGGER_SOURCE_SET1 = 1,  /*!< wakeup interrupt is generated if SET1 is "touched"*/
+    TOUCH_TRIGGER_SOURCE_MAX,
+} touch_trigger_src_t;
+
+typedef enum {
+    TOUCH_PAD_TIE_OPT_LOW = 0,    /*!<Initial level of charging voltage, low level */
+    TOUCH_PAD_TIE_OPT_HIGH = 1,   /*!<Initial level of charging voltage, high level */
+    TOUCH_PAD_TIE_OPT_MAX,
+} touch_tie_opt_t;
+
+typedef enum {
+    TOUCH_FSM_MODE_TIMER = 0,   /*!<To start touch FSM by timer */
+    TOUCH_FSM_MODE_SW,          /*!<To start touch FSM by software trigger */
+    TOUCH_FSM_MODE_MAX,
+} touch_fsm_mode_t;
+
+
 typedef intr_handle_t touch_isr_handle_t;
 typedef intr_handle_t touch_isr_handle_t;
 
 
+#define TOUCH_PAD_SLEEP_CYCLE_DEFAULT   (0x1000)  /*!<The timer frequency is RTC_SLOW_CLK( can be 150k or 32k depending on the options), max value is 0xffff */
+#define TOUCH_PAD_MEASURE_CYCLE_DEFAULT (0xffff)  /*!<The time frequency is 8Mhz, the max value is 0xffff */
+#define TOUCH_FSM_MODE_DEFAULT          (TOUCH_FSM_MODE_TIMER)
+#define TOUCH_TRIGGER_MODE_DEFAULT      (TOUCH_TRIGGER_BELOW)
+#define TOUCH_TRIGGER_SOURCE_DEFAULT    (TOUCH_TRIGGER_SOURCE_SET1)
+#define TOUCH_PAD_BIT_MASK_MAX          (0x3ff)
+
 /**
 /**
- * @brief       Initialize touch module.
- *
- *This function int touch pad module ,enable touch module
- *
+ * @brief Initialize touch module.
  * @return
  * @return
  *     - ESP_OK Success
  *     - ESP_OK Success
  *     - ESP_FAIL Touch pad init error
  *     - ESP_FAIL Touch pad init error
- *
  */
  */
 esp_err_t touch_pad_init();
 esp_err_t touch_pad_init();
 
 
 /**
 /**
- * @brief Uninstall TouchPad driver.
- *
+ * @brief Un-install touch pad driver.
  * @return
  * @return
  *     - ESP_OK   Success
  *     - ESP_OK   Success
- *     - ESP_FAIL Touch pad deinit error
+ *     - ESP_FAIL Touch pad driver not initialized
  */
  */
 esp_err_t touch_pad_deinit();
 esp_err_t touch_pad_deinit();
 
 
 /**
 /**
- * @brief       Configure touch pad interrupt threshold.
- *
- *
- * @param[in]  touch_num  : config touch num
- *
- * @param[in]  threshold : interrupt threshold  ,When the touch_pad_register less than threshold,
- *                         will trigger the touch interrupt.User can use touch_pad_read function
- *                         to determine the threshold.
- *
+ * @brief Configure touch pad interrupt threshold.
+ * @param touch_num touch pad index
+ * @param threshold interrupt threshold,
  * @return    - ESP_OK Success
  * @return    - ESP_OK Success
- *            - ESP_ERR_INVALID_ARG Touch pad error
- *            - ESP_FAIL Touch pad not initialized
- *
+ *            - ESP_ERR_INVALID_ARG if argument wrong
+ *            - ESP_FAIL if touch pad not initialized
  */
  */
 esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold);
 esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold);
 
 
 /**
 /**
- * @brief       get touch pad touch_pad_register counter.
- *
- *User can use this function to determine the the interrupt threshold .When you do not touch  the
- *pad ,read the touch_pad_read number(NumNotTouch) by the touch_pad_register.When you touch the pad ,read the touch_pad_register
- *number(NumTouch) by the touch_pad_read.Normal NumNotTouch>NumTouch,so you can select a interrupt threshold.
+ * @brief get touch sensor counter value.
+ *  Each touch sensor has a counter to count the number of charge/discharge cycles.
+ *  When the pad is not 'touched', we can get a number of the counter.
+ *  When the pad is 'touched', the value in counter will get smaller because of the larger equivalent capacitance.
+ *  User can use this function to determine the interrupt trigger threshold.
  *
  *
- * @param[in]  touch_num    : touch num
- * @param[out]  touch_value : touch output value
- *
- *  @return   - ESP_OK Success
+ * @param touch_num touch pad index
+ * @param touch_value pointer to accept touch sensor value
+ * @return   - ESP_OK Success
  *            - ESP_ERR_INVALID_ARG Touch pad error
  *            - ESP_ERR_INVALID_ARG Touch pad error
  *            - ESP_FAIL Touch pad not initialized
  *            - ESP_FAIL Touch pad not initialized
- *
  */
  */
 esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t * touch_value);
 esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t * touch_value);
 
 
 /**
 /**
- * @brief   register TouchPad interrupt handler, the handler is an ISR.
- *          The handler will be attached to the same CPU core that this function is running on.
- *
- * @param  fn  Interrupt handler function.
- * @param  arg  Parameter for handler function
- * @param  intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
- *            ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
- * @param  handle Pointer to return handle. If non-NULL, a handle for the interrupt will
- *            be returned here.
+ * @brief get filtered touch sensor counter value by IIR filter.
+ * @note touch_pad_filter_start has to be called before calling touch_pad_read_filtered.
+ *       This function can be called from ISR
  *
  *
+ * @param touch_num touch pad index
+ * @param touch_value pointer to accept touch sensor value
+ * @return   - ESP_OK Success
+ *            - ESP_ERR_INVALID_ARG Touch pad error
+ *            - ESP_FAIL Touch pad not initialized
+ */
+esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value);
+
+/**
+ * @brief   Register touch-pad ISR,
+ * @note Deprecated function, users should replace this with touch_pad_isr_register,
+ *       because RTC modules share a same interrupt index.
+ * @param fn  Pointer to ISR handler
+ * @param arg  Parameter for ISR
+ * @param unused Reserved, not used
+ * @param handle_unused Reserved, not used
+ * @return
+ *     - ESP_OK Success ;
+ *     - ESP_ERR_INVALID_ARG GPIO error
+ */
+esp_err_t touch_pad_isr_handler_register(void(*fn)(void *), void *arg, int unused, intr_handle_t *handle_unused) __attribute__ ((deprecated));
+
+/**
+ * @brief   Register touch-pad ISR.
+ *          The handler will be attached to the same CPU core that this function is running on.
+ * @param fn  Pointer to ISR handler
+ * @param arg  Parameter for ISR
  * @return
  * @return
  *     - ESP_OK Success ;
  *     - ESP_OK Success ;
  *     - ESP_ERR_INVALID_ARG GPIO error
  *     - ESP_ERR_INVALID_ARG GPIO error
  */
  */
-esp_err_t touch_pad_isr_handler_register(void(*fn)(void *), void *arg, int intr_alloc_flags, touch_isr_handle_t *handle);
-
-
-/**
- * ***************        ATTENTION       ********************/
-/**
- *@attention
- *Touch button is through the body's capacitive characteristics, 
- *there is a charge discharge circuit inside the. When the hands touch, 
- *the charge and discharge time will be slow.
- *Because of the different hardware, each pad needs to be calibrated at the factory.
- *We use touch_pad_read to determine factory parameters.
- */
-/**
- *----------EXAMPLE TO CONFIGURE GPIO AS OUTPUT ------------ *
- * @code{c}
- *  touch_pad_init();                            
- *  void taskA(void* arg)
- *  {
- *      for(;;){
- *          vtaskDelay(20/portTICK_PERIOD_MS);
- *          ets_printf("touch pad value %u\n",touch_pad_read(0));//Take the touched status and untouched status value
- *      } 
- *  }
- * @endcode
- **/
-/**
- *----------EXAMPLE TO SET ISR HANDLER ----------------------
- * @code{c}
- *   touch_pad_isr_handler_register(rtc_intr,NULL, 0, NULL)    //hook the isr handler for TouchPad interrupt
- * @endcode
- */
-/**
- *----------EXAMPLE TO USE TOUCH_PAD------------ *
- * @code{c}
- *   touch_pad_init();//only init one time
- *   touch_pad_config(0,300);//set the intr threshold,use touch_pad_read to determine this threshold 
- *   touch_pad_isr_handler_register(rtc_intr,NULL, 0, NULL)
- *   #include "esp_attr.h"
- *   void rtc_intr(void * arg)
- *   {
- *       uint32_t pad_intr = READ_PERI_REG(SARADC_SAR_TOUCH_CTRL2_REG) & 0x3ff;
- *       uint8_t i = 0;
- *       uint32_t rtc_intr = READ_PERI_REG(RTC_CNTL_INT_ST_REG);
- *       WRITE_PERI_REG(RTC_CNTL_INT_CLR_REG, rtc_intr);
- *       SET_PERI_REG_MASK(SARADC_SAR_TOUCH_CTRL2_REG, SARADC_TOUCH_MEAS_EN_CLR);
- *       if (rtc_intr & RTC_CNTL_TOUCH_INT_ST) {
- *           for (i = 0; i < TOUCH_PAD_MAX; ++i) {
- *               if ((pad_intr >> i) & 0x01) {
- *                   ets_printf("touch pad intr %u\n",i);
- *               }
- *           }
- *       }
- *  }
- * @endcode
- **/
+esp_err_t touch_pad_isr_register(intr_handler_t fn, void* arg);
+
+/**
+ * @brief Deregister the handler previously registered using touch_pad_isr_handler_register
+ * @param fn  handler function to call (as passed to touch_pad_isr_handler_register)
+ * @param arg  argument of the handler (as passed to touch_pad_isr_handler_register)
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_STATE if a handler matching both fn and
+ *        arg isn't registered
+ */
+esp_err_t touch_pad_isr_deregister(void(*fn)(void *), void *arg);
+
+/**
+ * @brief Set touch sensor measurement and sleep time
+ * @param sleep_cycle  The touch sensor will sleep after each measurement.
+ *                     sleep_cycle decide the interval between each measurement.
+ *                     t_sleep = sleep_cycle / (RTC_SLOW_CLK frequency).
+ *                     The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function.
+ * @param meas_cycle The duration of the touch sensor measurement.
+ *                   t_meas = meas_cycle / 8M, the maximum measure time is 0xffff / 8M = 8.19 ms
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_cycle);
+
+/**
+ * @brief Get touch sensor measurement and sleep time
+ * @param sleep_cycle  Pointer to accept sleep cycle number
+ * @param meas_cycle Pointer to accept measurement cycle count.
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_meas_time(uint16_t *sleep_cycle, uint16_t *meas_cycle);
+
+/**
+ * @brief Set touch sensor reference voltage, if the voltage gap between high and low reference voltage get less,
+ *        the charging and discharging time would be faster, accordingly, the counter value would be larger.
+ *        In the case of detecting very slight change of capacitance, we can narrow down the gap so as to increase
+ *        the sensitivity. On the other hand, narrow voltage gap would also introduce more noise, but we can use a
+ *        software filter to pre-process the counter value.
+ * @param refh the value of DREFH
+ * @param refl the value of DREFL
+ * @param atten the attenuation on DREFH
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_voltage(touch_high_volt_t refh, touch_low_volt_t refl, touch_volt_atten_t atten);
+
+/**
+ * @brief Get touch sensor reference voltage,
+ * @param refh pointer to accept DREFH value
+ * @param refl pointer to accept DREFL value
+ * @param atten pointer to accept the attenuation on DREFH
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_voltage(touch_high_volt_t *refh, touch_low_volt_t *refl, touch_volt_atten_t *atten);
+
+/**
+ * @brief Set touch sensor charge/discharge speed for each pad.
+ *        If the slope is 0, the counter would always be zero.
+ *        If the slope is 1, the charging and discharging would be slow, accordingly, the counter value would be small.
+ *        If the slope is set 7, which is the maximum value, the charging and discharging would be fast, accordingly, the
+ *        counter value would be larger.
+ * @param touch_num touch pad index
+ * @param slope touch pad charge/discharge speed
+ * @param opt the initial voltage
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t slope, touch_tie_opt_t opt);
+
+/**
+ * @brief Get touch sensor charge/discharge speed for each pad
+ * @param touch_num touch pad index
+ * @param slope pointer to accept touch pad charge/discharge slope
+ * @param opt pointer to accept the initial voltage
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_get_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t *slope, touch_tie_opt_t *opt);
+
+/**
+ * @brief Initialize touch pad GPIO
+ * @param touch_num touch pad index
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_io_init(touch_pad_t touch_num);
+
+/**
+ * @brief Set touch sensor FSM mode, the test action can be triggered by the timer,
+ *        as well as by the software.
+ * @param mode FSM mode
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_fsm_mode(touch_fsm_mode_t mode);
+
+/**
+ * @brief Get touch sensor FSM mode
+ * @param mode pointer to accept FSM mode
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_fsm_mode(touch_fsm_mode_t *mode);
+
+/**
+ * @brief Trigger a touch sensor measurement, only support in SW mode of FSM
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_sw_start();
+
+/**
+ * @brief Set touch sensor interrupt threshold
+ * @param touch_num touch pad index
+ * @param threshold threshold of touchpad count, refer to touch_pad_set_trigger_mode to see how to set trigger mode.
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint16_t threshold);
+
+/**
+ * @brief Get touch sensor interrupt threshold
+ * @param touch_num touch pad index
+ * @param threshold pointer to accept threshold
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint16_t *threshold);
+
+/**
+ * @brief Set touch sensor interrupt trigger mode.
+ *        Interrupt can be triggered either when counter result is less than
+ *        threshold or when counter result is more than threshold.
+ * @param mode touch sensor interrupt trigger mode
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_trigger_mode(touch_trigger_mode_t mode);
+
+/**
+ * @brief Get touch sensor interrupt trigger mode
+ * @param mode pointer to accept touch sensor interrupt trigger mode
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_trigger_mode(touch_trigger_mode_t *mode);
+
+/**
+ * @brief 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 src touch sensor interrupt trigger source
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_trigger_source(touch_trigger_src_t src);
+
+/**
+ * @brief Get touch sensor interrupt trigger source
+ * @param src pointer to accept touch sensor interrupt trigger source
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_trigger_source(touch_trigger_src_t *src);
+
+/**
+ * @brief 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 set1_mask bitmask of touch sensor signal group1, it's a 10-bit value
+ * @param set2_mask bitmask of touch sensor signal group2, it's a 10-bit value
+ * @param en_mask bitmask of touch sensor work enable, it's a 10-bit value
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask);
+
+/**
+ * @brief Get touch sensor group mask.
+ * @param set1_mask pointer to accept bitmask of touch sensor signal group1, it's a 10-bit value
+ * @param set2_mask pointer to accept bitmask of touch sensor signal group2, it's a 10-bit value
+ * @param en_mask pointer to accept bitmask of touch sensor work enable, it's a 10-bit value
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_group_mask(uint16_t *set1_mask, uint16_t *set2_mask, uint16_t *en_mask);
+
+/**
+ * @brief Clear touch sensor group mask.
+ *        Touch pad module has two sets of signals, Interrupt is triggered only if
+ *        at least one of touch pad in this group is "touched".
+ *        This function will clear the register bits according to the given bitmask.
+ * @param set1_mask bitmask touch sensor signal group1, it's a 10-bit value
+ * @param set2_mask bitmask touch sensor signal group2, it's a 10-bit value
+ * @param en_mask bitmask of touch sensor work enable, it's a 10-bit value
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_clear_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask);
+
+/**
+ * @brief To clear the touch status register, usually use this function in touch ISR to clear status.
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_clear_status();
+
+/**
+ * @brief Get the touch sensor status, usually used in ISR to decide which pads are 'touched'.
+ * @return
+ *      - touch status
+ */
+uint32_t touch_pad_get_status();
+
+/**
+ * @brief To enable touch pad interrupt
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_intr_enable();
+
+/**
+ * @brief To disable touch pad interrupt
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_intr_disable();
+
+/**
+ * @brief set touch pad filter calibration period, in ms.
+ *        Need to call touch_pad_filter_start before all touch filter APIs
+ * @param new_period_ms filter period, in ms
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_STATE driver state error
+ *      - ESP_ERR_INVALID_ARG parameter error
+ */
+esp_err_t touch_pad_set_filter_period(uint32_t new_period_ms);
+
+/**
+ * @brief get touch pad filter calibration period, in ms
+ *        Need to call touch_pad_filter_start before all touch filter APIs
+ * @param p_period_ms pointer to accept period
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_STATE driver state error
+ *      - ESP_ERR_INVALID_ARG parameter error
+ */
+esp_err_t touch_pad_get_filter_period(uint32_t* p_period_ms);
+
+/**
+ * @brief start touch pad filter function
+ *      This API will start a filter to process the noise in order to prevent false triggering
+ *      when detecting slight change of capacitance.
+ *      Need to call touch_pad_filter_start before all touch filter APIs
+ *
+ *      If filter is not initialized, this API will initialize the filter with given period.
+ *      If filter is already initialized, this API will update the filter period.
+ * @note This filter uses FreeRTOS timer, which is dipatched from a task with
+ *       priority 1 by default on CPU 0. So if some application task with higher priority
+ *       takes a lot of CPU0 time, then the quality of data obtained from this filter will be affected.
+ *       You can adjust FreeRTOS timer task priority in menuconfig.
+ * @param filter_period_ms filter calibration period, in ms
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_ARG parameter error
+ *      - ESP_ERR_NO_MEM No memory for driver
+ *      - ESP_ERR_INVALID_STATE driver state error
+ */
+esp_err_t touch_pad_filter_start(uint32_t filter_period_ms);
+
+/**
+ * @brief stop touch pad filter function
+ *        Need to call touch_pad_filter_start before all touch filter APIs
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_STATE driver state error
+ */
+esp_err_t touch_pad_filter_stop();
+
+/**
+ * @brief delete touch pad filter driver and release the memory
+ *        Need to call touch_pad_filter_start before all touch filter APIs
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_STATE driver state error
+ */
+esp_err_t touch_pad_filter_delete();
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 436 - 98
components/driver/rtc_module.c

@@ -15,8 +15,11 @@
 #include "rom/ets_sys.h"
 #include "rom/ets_sys.h"
 #include "esp_log.h"
 #include "esp_log.h"
 #include "soc/rtc_io_reg.h"
 #include "soc/rtc_io_reg.h"
+#include "soc/rtc_io_struct.h"
 #include "soc/sens_reg.h"
 #include "soc/sens_reg.h"
+#include "soc/sens_struct.h"
 #include "soc/rtc_cntl_reg.h"
 #include "soc/rtc_cntl_reg.h"
+#include "soc/rtc_cntl_struct.h"
 #include "rtc_io.h"
 #include "rtc_io.h"
 #include "touch_pad.h"
 #include "touch_pad.h"
 #include "adc.h"
 #include "adc.h"
@@ -24,6 +27,7 @@
 #include "freertos/FreeRTOS.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/xtensa_api.h"
 #include "freertos/xtensa_api.h"
 #include "freertos/semphr.h"
 #include "freertos/semphr.h"
+#include "freertos/timers.h"
 #include "esp_intr_alloc.h"
 #include "esp_intr_alloc.h"
 #include "sys/lock.h"
 #include "sys/lock.h"
 #include "driver/rtc_cntl.h"
 #include "driver/rtc_cntl.h"
@@ -43,6 +47,11 @@ static const char *RTC_MODULE_TAG = "RTC_MODULE";
     return (ret_val);                                                              \
     return (ret_val);                                                              \
 }
 }
 
 
+#define RTC_RES_CHECK(res, ret_val) if ( (a) != ESP_OK) {                           \
+        ESP_LOGE(RTC_MODULE_TAG,"%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__); \
+        return (ret_val);                                                              \
+}
+
 #define ADC1_CHECK_FUNCTION_RET(fun_ret) if(fun_ret!=ESP_OK){\
 #define ADC1_CHECK_FUNCTION_RET(fun_ret) if(fun_ret!=ESP_OK){\
     ESP_LOGE(RTC_MODULE_TAG,"%s:%d\n",__FUNCTION__,__LINE__);\
     ESP_LOGE(RTC_MODULE_TAG,"%s:%d\n",__FUNCTION__,__LINE__);\
     return ESP_FAIL;\
     return ESP_FAIL;\
@@ -51,7 +60,17 @@ static const char *RTC_MODULE_TAG = "RTC_MODULE";
 #define DAC_ERR_STR_CHANNEL_ERROR   "DAC channel error"
 #define DAC_ERR_STR_CHANNEL_ERROR   "DAC channel error"
 
 
 portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
 portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
-static xSemaphoreHandle rtc_touch_sem = NULL;
+static SemaphoreHandle_t rtc_touch_mux = NULL;
+
+
+typedef struct {
+    TimerHandle_t timer;
+    uint32_t filtered_val[TOUCH_PAD_MAX];
+    uint32_t filter_period;
+    uint32_t period;
+    bool enable;
+} touch_pad_filter_t;
+static touch_pad_filter_t *s_touch_pad_filter = NULL;
 
 
 //Reg,Mux,Fun,IE,Up,Down,Rtc_number
 //Reg,Mux,Fun,IE,Up,Down,Rtc_number
 const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = {
 const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = {
@@ -337,10 +356,21 @@ void rtc_gpio_force_hold_dis_all()
 /*---------------------------------------------------------------
 /*---------------------------------------------------------------
                     Touch Pad
                     Touch Pad
 ---------------------------------------------------------------*/
 ---------------------------------------------------------------*/
-esp_err_t touch_pad_isr_handler_register(void(*fn)(void *), void *arg, int intr_alloc_flags, touch_isr_handle_t *handle)
+esp_err_t touch_pad_isr_handler_register(void (*fn)(void *), void *arg, int no_use, intr_handle_t *handle_no_use)
 {
 {
     RTC_MODULE_CHECK(fn, "Touch_Pad ISR null", ESP_ERR_INVALID_ARG);
     RTC_MODULE_CHECK(fn, "Touch_Pad ISR null", ESP_ERR_INVALID_ARG);
-    return esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
+    return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M);
+}
+
+esp_err_t touch_pad_isr_register(intr_handler_t fn, void* arg)
+{
+    RTC_MODULE_CHECK(fn, "Touch_Pad ISR null", ESP_ERR_INVALID_ARG);
+    return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M);
+}
+
+esp_err_t touch_pad_isr_deregister(intr_handler_t fn, void *arg)
+{
+    return rtc_isr_deregister(fn, arg);
 }
 }
 
 
 static esp_err_t touch_pad_get_io_num(touch_pad_t touch_num, gpio_num_t *gpio_num)
 static esp_err_t touch_pad_get_io_num(touch_pad_t touch_num, gpio_num_t *gpio_num)
@@ -371,129 +401,346 @@ static esp_err_t touch_pad_get_io_num(touch_pad_t touch_num, gpio_num_t *gpio_nu
         *gpio_num = 27;
         *gpio_num = 27;
         break;
         break;
     case TOUCH_PAD_NUM8:
     case TOUCH_PAD_NUM8:
-        *gpio_num = 33;
+        *gpio_num = 32;
         break;
         break;
     case TOUCH_PAD_NUM9:
     case TOUCH_PAD_NUM9:
-        *gpio_num = 32;
+        *gpio_num = 33;
         break;
         break;
     default:
     default:
         return ESP_ERR_INVALID_ARG;
         return ESP_ERR_INVALID_ARG;
     }
     }
-
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
-static esp_err_t touch_pad_init_config(uint16_t sleep_cycle, uint16_t sample_cycle_num)
+#define TOUCH_PAD_FILTER_FACTOR_DEFAULT   (16)
+#define TOUCH_PAD_SHIFT_DEFAULT           (4)
+static uint32_t _touch_filter_iir(uint32_t in_now, uint32_t out_last, uint32_t k)
+{
+    if (k == 0) {
+        return in_now;
+    } else {
+        uint32_t out_now = (in_now + (k - 1) * out_last) / k;
+        return out_now;
+    }
+}
+
+static void touch_pad_filter_cb(void *arg)
+{
+    if (s_touch_pad_filter == NULL) {
+        return;
+    }
+    uint16_t val;
+    for (int i = 0; i < TOUCH_PAD_MAX; i++) {
+        touch_pad_read(i, &val);
+        s_touch_pad_filter->filtered_val[i] = s_touch_pad_filter->filtered_val[i] == 0 ? (val << TOUCH_PAD_SHIFT_DEFAULT) : s_touch_pad_filter->filtered_val[i];
+        s_touch_pad_filter->filtered_val[i] = _touch_filter_iir((val << TOUCH_PAD_SHIFT_DEFAULT),
+                s_touch_pad_filter->filtered_val[i], TOUCH_PAD_FILTER_FACTOR_DEFAULT);
+    }
+}
+
+esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_cycle)
 {
 {
-    xSemaphoreTake(rtc_touch_sem, portMAX_DELAY);
+    xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
     portENTER_CRITICAL(&rtc_spinlock);
     portENTER_CRITICAL(&rtc_spinlock);
-    SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS, 1, RTC_IO_TOUCH_XPD_BIAS_S);
-    SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR);
-    //clear touch enable
-    WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, 0x0);
-    //enable Rtc Touch pad Timer
-    SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_TOUCH_SLP_TIMER_EN);
-    //config pad module sleep time and sample num
-    //Touch pad SleepCycle Time = 150Khz
-    SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_SLEEP_CYCLES, sleep_cycle, SENS_TOUCH_SLEEP_CYCLES_S);//150kHZ
-    //Touch Pad Measure Time= 8Mhz
-    SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_MEAS_DELAY, sample_cycle_num, SENS_TOUCH_MEAS_DELAY_S); //8Mhz
+    //touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK( can be 150k or 32k depending on the options)
+    SENS.sar_touch_ctrl2.touch_sleep_cycles = sleep_cycle;
+    //touch sensor measure time= meas_cycle / 8Mhz
+    SENS.sar_touch_ctrl1.touch_meas_delay = meas_cycle;
     portEXIT_CRITICAL(&rtc_spinlock);
     portEXIT_CRITICAL(&rtc_spinlock);
-    xSemaphoreGive(rtc_touch_sem);
+    xSemaphoreGive(rtc_touch_mux);
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
-esp_err_t touch_pad_init()
+esp_err_t touch_pad_get_meas_time(uint16_t *sleep_cycle, uint16_t *meas_cycle)
 {
 {
-    if(rtc_touch_sem == NULL) {
-        rtc_touch_sem = xSemaphoreCreateMutex();
+    portENTER_CRITICAL(&rtc_spinlock);
+    if (sleep_cycle) {
+        *sleep_cycle = SENS.sar_touch_ctrl2.touch_sleep_cycles;
     }
     }
-    if(rtc_touch_sem == NULL) {
-        return ESP_FAIL;
+    if (meas_cycle) {
+        *meas_cycle = SENS.sar_touch_ctrl1.touch_meas_delay;
     }
     }
-    return touch_pad_init_config(TOUCH_PAD_SLEEP_CYCLE_CONFIG, TOUCH_PAD_MEASURE_CYCLE_CONFIG);
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
 }
 }
 
 
-esp_err_t touch_pad_deinit()
+esp_err_t touch_pad_set_voltage(touch_high_volt_t refh, touch_low_volt_t refl, touch_volt_atten_t atten)
 {
 {
+    RTC_MODULE_CHECK(((refh < TOUCH_HVOLT_MAX) && (refh >= (int )TOUCH_HVOLT_KEEP)), "touch refh error",
+            ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK(((refl < TOUCH_LVOLT_MAX) && (refh >= (int )TOUCH_LVOLT_KEEP)), "touch refl error",
+            ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK(((atten < TOUCH_HVOLT_ATTEN_MAX) && (refh >= (int )TOUCH_HVOLT_ATTEN_KEEP)), "touch atten error",
+            ESP_ERR_INVALID_ARG);
 
 
-    if(rtc_touch_sem == NULL) {
-        return ESP_FAIL;
+    portENTER_CRITICAL(&rtc_spinlock);
+    if (refh > TOUCH_HVOLT_KEEP) {
+        RTCIO.touch_cfg.drefh = refh;
+    }
+    if (refl > TOUCH_LVOLT_KEEP) {
+        RTCIO.touch_cfg.drefl = refl;
     }
     }
-    vSemaphoreDelete(rtc_touch_sem);
-    rtc_touch_sem=NULL;
+    if (atten > TOUCH_HVOLT_ATTEN_KEEP) {
+        RTCIO.touch_cfg.drange = atten;
+    }
+    portEXIT_CRITICAL(&rtc_spinlock);
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
-static void touch_pad_counter_init(touch_pad_t touch_num)
+esp_err_t touch_pad_get_voltage(touch_high_volt_t *refh, touch_low_volt_t *refl, touch_volt_atten_t *atten)
 {
 {
     portENTER_CRITICAL(&rtc_spinlock);
     portENTER_CRITICAL(&rtc_spinlock);
-    //Enable Tie,Init Level(Counter)
-    SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + touch_num * 4, RTC_IO_TOUCH_PAD0_TIE_OPT_M);
-    //Touch Set Slop(Counter)
-    SET_PERI_REG_BITS(RTC_IO_TOUCH_PAD0_REG + touch_num * 4, RTC_IO_TOUCH_PAD0_DAC_V, 7, RTC_IO_TOUCH_PAD0_DAC_S);
-    //Enable Touch Pad IO
-    SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + touch_num * 4, RTC_IO_TOUCH_PAD0_START_M);
+    if (refh) {
+        *refh = RTCIO.touch_cfg.drefh;
+    }
+    if (refl) {
+        *refl = RTCIO.touch_cfg.drefl;
+    }
+    if (atten) {
+        *atten = RTCIO.touch_cfg.drange;
+    }
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_set_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t slope, touch_tie_opt_t opt)
+{
+    RTC_MODULE_CHECK((slope < TOUCH_PAD_SLOPE_MAX), "touch slope error", ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK((opt < TOUCH_PAD_TIE_OPT_MAX), "touch opt error", ESP_ERR_INVALID_ARG);
+    portENTER_CRITICAL(&rtc_spinlock);
+    //set tie opt value, high or low level seem no difference for counter
+    RTCIO.touch_pad[touch_num].tie_opt = opt;
+    //touch sensor set slope for charging and discharging.
+    RTCIO.touch_pad[touch_num].dac = slope;
     portEXIT_CRITICAL(&rtc_spinlock);
     portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
 }
 }
 
 
-static void touch_pad_power_on(touch_pad_t touch_num)
+esp_err_t touch_pad_get_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t *slope, touch_tie_opt_t *opt)
 {
 {
+    RTC_MODULE_CHECK((touch_num < TOUCH_PAD_MAX), "touch IO error", ESP_ERR_INVALID_ARG);
     portENTER_CRITICAL(&rtc_spinlock);
     portENTER_CRITICAL(&rtc_spinlock);
-    //Enable Touch Pad Power on
-    SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + touch_num * 4, RTC_IO_TOUCH_PAD0_XPD_M);
+    if (slope) {
+        *slope = RTCIO.touch_pad[touch_num].dac;
+    }
+    if (opt) {
+        *opt = RTCIO.touch_pad[touch_num].tie_opt;
+    }
     portEXIT_CRITICAL(&rtc_spinlock);
     portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
 }
 }
 
 
-static void toch_pad_io_init(touch_pad_t touch_num)
+esp_err_t touch_pad_io_init(touch_pad_t touch_num)
 {
 {
+    RTC_MODULE_CHECK((touch_num < TOUCH_PAD_MAX), "touch IO error", ESP_ERR_INVALID_ARG);
     gpio_num_t gpio_num = GPIO_NUM_0;
     gpio_num_t gpio_num = GPIO_NUM_0;
     touch_pad_get_io_num(touch_num, &gpio_num);
     touch_pad_get_io_num(touch_num, &gpio_num);
     rtc_gpio_init(gpio_num);
     rtc_gpio_init(gpio_num);
     rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED);
     rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED);
     rtc_gpio_pulldown_dis(gpio_num);
     rtc_gpio_pulldown_dis(gpio_num);
     rtc_gpio_pullup_dis(gpio_num);
     rtc_gpio_pullup_dis(gpio_num);
+    return ESP_OK;
 }
 }
 
 
-static esp_err_t touch_start(touch_pad_t touch_num)
+esp_err_t touch_pad_set_fsm_mode(touch_fsm_mode_t mode)
+{
+    RTC_MODULE_CHECK((mode < TOUCH_FSM_MODE_MAX), "touch fsm mode error", ESP_ERR_INVALID_ARG);
+    portENTER_CRITICAL(&rtc_spinlock);
+    SENS.sar_touch_ctrl2.touch_start_en = 0;
+    SENS.sar_touch_ctrl2.touch_start_force = mode;
+    RTCCNTL.state0.touch_slp_timer_en = (mode == TOUCH_FSM_MODE_TIMER ? 1 : 0);
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_get_fsm_mode(touch_fsm_mode_t *mode)
+{
+    if (mode) {
+        *mode = SENS.sar_touch_ctrl2.touch_start_force;
+    }
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_sw_start()
+{
+    portENTER_CRITICAL(&rtc_spinlock);
+    SENS.sar_touch_ctrl2.touch_start_en = 0;
+    SENS.sar_touch_ctrl2.touch_start_en = 1;
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint16_t threshold)
+{
+    RTC_MODULE_CHECK((touch_num < TOUCH_PAD_MAX), "touch IO error", ESP_ERR_INVALID_ARG);
+    portENTER_CRITICAL(&rtc_spinlock);
+    if (touch_num & 0x1) {
+        SENS.touch_thresh[touch_num / 2].l_thresh = threshold;
+    } else {
+        SENS.touch_thresh[touch_num / 2].h_thresh = threshold;
+
+    }
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint16_t *threshold)
+{
+    RTC_MODULE_CHECK((touch_num < TOUCH_PAD_MAX), "touch IO error", ESP_ERR_INVALID_ARG);
+    if (threshold) {
+        *threshold = (touch_num & 0x1 )? \
+                SENS.touch_thresh[touch_num / 2].l_thresh : \
+                SENS.touch_thresh[touch_num / 2].h_thresh;
+    }
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_set_trigger_mode(touch_trigger_mode_t mode)
+{
+    RTC_MODULE_CHECK((mode < TOUCH_TRIGGER_MAX), "touch trigger mode error", ESP_ERR_INVALID_ARG);
+    portENTER_CRITICAL(&rtc_spinlock);
+    SENS.sar_touch_ctrl1.touch_out_sel = mode;
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_get_trigger_mode(touch_trigger_mode_t *mode)
+{
+    if (mode) {
+        *mode = SENS.sar_touch_ctrl1.touch_out_sel;
+    }
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_set_trigger_source(touch_trigger_src_t src)
+{
+    RTC_MODULE_CHECK((src < TOUCH_TRIGGER_SOURCE_MAX), "touch trigger source error", ESP_ERR_INVALID_ARG);
+    portENTER_CRITICAL(&rtc_spinlock);
+    SENS.sar_touch_ctrl1.touch_out_1en = src;
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_get_trigger_source(touch_trigger_src_t *src)
+{
+    if (src) {
+        *src = SENS.sar_touch_ctrl1.touch_out_1en;
+    }
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_set_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask)
+{
+    RTC_MODULE_CHECK((set1_mask <= TOUCH_PAD_BIT_MASK_MAX), "touch set1 bitmask error", ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK((set2_mask <= TOUCH_PAD_BIT_MASK_MAX), "touch set2 bitmask error", ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK((en_mask <= TOUCH_PAD_BIT_MASK_MAX), "touch work_en bitmask error", ESP_ERR_INVALID_ARG);
+
+    portENTER_CRITICAL(&rtc_spinlock);
+    SENS.sar_touch_enable.touch_pad_outen1 |= set1_mask;
+    SENS.sar_touch_enable.touch_pad_outen2 |= set2_mask;
+    SENS.sar_touch_enable.touch_pad_worken |= en_mask;
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_get_group_mask(uint16_t *set1_mask, uint16_t *set2_mask, uint16_t *en_mask)
+{
+    portENTER_CRITICAL(&rtc_spinlock);
+    if (set1_mask) {
+        *set1_mask = SENS.sar_touch_enable.touch_pad_outen1;
+    }
+    if (set2_mask) {
+        *set2_mask = SENS.sar_touch_enable.touch_pad_outen2;
+    }
+    if (en_mask) {
+        *en_mask = SENS.sar_touch_enable.touch_pad_worken;
+    }
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_clear_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask)
+{
+    RTC_MODULE_CHECK((set1_mask <= TOUCH_PAD_BIT_MASK_MAX), "touch set1 bitmask error", ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK((set2_mask <= TOUCH_PAD_BIT_MASK_MAX), "touch set2 bitmask error", ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK((en_mask <= TOUCH_PAD_BIT_MASK_MAX), "touch work_en bitmask error", ESP_ERR_INVALID_ARG);
+
+    portENTER_CRITICAL(&rtc_spinlock);
+    SENS.sar_touch_enable.touch_pad_outen1 &= (~set1_mask);
+    SENS.sar_touch_enable.touch_pad_outen2 &= (~set2_mask);
+    SENS.sar_touch_enable.touch_pad_worken &= (~en_mask);
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
+
+uint32_t IRAM_ATTR touch_pad_get_status()
+{
+    return SENS.sar_touch_ctrl2.touch_meas_en;
+}
+
+esp_err_t IRAM_ATTR touch_pad_clear_status()
 {
 {
-    RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG);
     portENTER_CRITICAL(&rtc_spinlock);
     portENTER_CRITICAL(&rtc_spinlock);
+    SENS.sar_touch_ctrl2.touch_meas_en_clr = 1;
+    portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
 
 
-    //Enable Digital rtc control :work mode and out mode
-    SET_PERI_REG_MASK(SENS_SAR_TOUCH_ENABLE_REG, (1 << (touch_num + SENS_TOUCH_PAD_WORKEN_S)) | \
-                      (1 << (touch_num + SENS_TOUCH_PAD_OUTEN2_S)) | \
-                      (1 << (touch_num + SENS_TOUCH_PAD_OUTEN1_S)));
+esp_err_t touch_pad_intr_enable()
+{
+    portENTER_CRITICAL(&rtc_spinlock);
+    RTCCNTL.int_ena.rtc_touch = 1;
     portEXIT_CRITICAL(&rtc_spinlock);
     portEXIT_CRITICAL(&rtc_spinlock);
+    return ESP_OK;
+}
 
 
+esp_err_t touch_pad_intr_disable()
+{
+    portENTER_CRITICAL(&rtc_spinlock);
+    RTCCNTL.int_ena.rtc_touch = 0;
+    portEXIT_CRITICAL(&rtc_spinlock);
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
 esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold)
 esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold)
 {
 {
-    RTC_MODULE_CHECK(rtc_touch_sem != NULL, "Touch pad not initialized", ESP_FAIL);
+    RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL);
     RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG);
     RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG);
-    xSemaphoreTake(rtc_touch_sem, portMAX_DELAY);
-    portENTER_CRITICAL(&rtc_spinlock);
-    //clear touch force ,select the Touch mode is Timer
-    CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M);
-    CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_FORCE_M);
-    //set threshold
-    uint8_t shift;
-    shift = (touch_num & 1) ? SENS_TOUCH_OUT_TH1_S : SENS_TOUCH_OUT_TH0_S;
-    SET_PERI_REG_BITS((SENS_SAR_TOUCH_THRES1_REG + (touch_num / 2) * 4), SENS_TOUCH_OUT_TH0, threshold, shift);
-    //When touch value < threshold ,the Intr will give
-    CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_OUT_SEL);
-    //Intr will give ,when SET0 < threshold
-    SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_OUT_1EN);
-    //Enable Rtc Touch Module Intr,the Interrupt need Rtc out  Enable
-    SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_TOUCH_INT_ENA);
-    portEXIT_CRITICAL(&rtc_spinlock);
-    xSemaphoreGive(rtc_touch_sem);
-    touch_pad_power_on(touch_num);
-    toch_pad_io_init(touch_num);
-    touch_pad_counter_init(touch_num);
-    touch_start(touch_num);
+    touch_pad_set_thresh(touch_num, threshold);
+    touch_pad_io_init(touch_num);
+    touch_pad_set_cnt_mode(touch_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_HIGH);
+    touch_pad_set_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num));
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_init()
+{
+    if (rtc_touch_mux == NULL) {
+        rtc_touch_mux = xSemaphoreCreateMutex();
+    }
+    if (rtc_touch_mux == NULL) {
+        return ESP_FAIL;
+    }
+    touch_pad_intr_disable();
+    touch_pad_set_fsm_mode(TOUCH_FSM_MODE_DEFAULT);
+    touch_pad_set_trigger_mode(TOUCH_TRIGGER_MODE_DEFAULT);
+    touch_pad_set_trigger_source(TOUCH_TRIGGER_SOURCE_DEFAULT);
+    touch_pad_clear_status();
+    touch_pad_set_meas_time(TOUCH_PAD_SLEEP_CYCLE_DEFAULT, TOUCH_PAD_MEASURE_CYCLE_DEFAULT);
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_deinit()
+{
+    if (rtc_touch_mux == NULL) {
+        return ESP_FAIL;
+    }
+    touch_pad_filter_delete();
+    touch_pad_set_fsm_mode(TOUCH_FSM_MODE_SW);
+    touch_pad_clear_status();
+    touch_pad_intr_disable();
+    vSemaphoreDelete(rtc_touch_mux);
+    rtc_touch_mux = NULL;
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
@@ -501,33 +748,125 @@ esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value)
 {
 {
     RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG);
     RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG);
     RTC_MODULE_CHECK(touch_value != NULL, "touch_value", ESP_ERR_INVALID_ARG);
     RTC_MODULE_CHECK(touch_value != NULL, "touch_value", ESP_ERR_INVALID_ARG);
-    RTC_MODULE_CHECK(rtc_touch_sem != NULL, "Touch pad not initialized", ESP_FAIL);
-    xSemaphoreTake(rtc_touch_sem, portMAX_DELAY);
-    uint32_t v0 = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
-    portENTER_CRITICAL(&rtc_spinlock);
-    SET_PERI_REG_MASK(SENS_SAR_TOUCH_ENABLE_REG, (1 << (touch_num)));
-    //Disable Intr
-    CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_ENABLE_REG, (1 << (touch_num + SENS_TOUCH_PAD_OUTEN2_S)) | \
-                        ((1 << (touch_num + SENS_TOUCH_PAD_OUTEN1_S))));
-    toch_pad_io_init(touch_num);
-    touch_pad_counter_init(touch_num);
-    touch_pad_power_on(touch_num);
-    //force oneTime test start
-    SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M);
-    SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_FORCE_M);
-    SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_XPD_WAIT, 10, SENS_TOUCH_XPD_WAIT_S);
-    portEXIT_CRITICAL(&rtc_spinlock);
-    while (GET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_DONE) == 0) {};
-    uint8_t shift = (touch_num & 1) ? SENS_TOUCH_MEAS_OUT1_S : SENS_TOUCH_MEAS_OUT0_S;
-    *touch_value = READ_PERI_REG(SENS_SAR_TOUCH_OUT1_REG + (touch_num / 2) * 4) >> shift;
-    WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, v0);
-    //force oneTime test end
-    //clear touch force ,select the Touch mode is Timer
-    portENTER_CRITICAL(&rtc_spinlock);
-    CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M);
-    CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_FORCE_M);
-    portEXIT_CRITICAL(&rtc_spinlock);
-    xSemaphoreGive(rtc_touch_sem);
+    RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL);
+    xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
+    while (SENS.sar_touch_ctrl2.touch_meas_done == 0) {};
+    *touch_value = (touch_num & 0x1) ? \
+                        SENS.touch_meas[touch_num / 2].l_val: \
+                        SENS.touch_meas[touch_num / 2].h_val;
+    xSemaphoreGive(rtc_touch_mux);
+    return ESP_OK;
+}
+
+IRAM_ATTR esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value)
+{
+    RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL);
+    RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK(touch_value != NULL, "touch_value", ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE);
+
+    *touch_value = (s_touch_pad_filter->filtered_val[touch_num] >> TOUCH_PAD_SHIFT_DEFAULT);
+    return ESP_OK;
+}
+
+esp_err_t touch_pad_set_filter_period(uint32_t new_period_ms)
+{
+    RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE);
+    RTC_MODULE_CHECK(new_period_ms > 0, "Touch pad filter period error", ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_ERR_INVALID_STATE);
+
+    esp_err_t ret = ESP_OK;
+    xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
+    if (s_touch_pad_filter != NULL) {
+        xTimerChangePeriod(s_touch_pad_filter->timer, new_period_ms / portTICK_PERIOD_MS, portMAX_DELAY);
+        s_touch_pad_filter->period = new_period_ms;
+    } else {
+        ESP_LOGE(RTC_MODULE_TAG, "Touch pad filter deleted");
+        ret = ESP_ERR_INVALID_STATE;
+    }
+    xSemaphoreGive(rtc_touch_mux);
+    return ret;
+}
+
+esp_err_t touch_pad_get_filter_period(uint32_t* p_period_ms)
+{
+    RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE);
+    RTC_MODULE_CHECK(p_period_ms != NULL, "Touch pad period pointer error", ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_ERR_INVALID_STATE);
+
+    esp_err_t ret = ESP_OK;
+    xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
+    if (s_touch_pad_filter != NULL) {
+        *p_period_ms = s_touch_pad_filter->period;
+    } else {
+        ESP_LOGE(RTC_MODULE_TAG, "Touch pad filter deleted");
+        ret = ESP_ERR_INVALID_STATE;
+    }
+    xSemaphoreGive(rtc_touch_mux);
+    return ret;
+}
+
+esp_err_t touch_pad_filter_start(uint32_t filter_period_ms)
+{
+    RTC_MODULE_CHECK(filter_period_ms >= portTICK_PERIOD_MS, "Touch pad filter period error", ESP_ERR_INVALID_ARG);
+    RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_ERR_INVALID_STATE);
+
+    esp_err_t ret = ESP_OK;
+    xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
+    if (s_touch_pad_filter == NULL) {
+        s_touch_pad_filter = (touch_pad_filter_t *) calloc(1, sizeof(touch_pad_filter_t));
+        if (s_touch_pad_filter == NULL) {
+            ret = ESP_ERR_NO_MEM;
+        }
+    }
+    if (s_touch_pad_filter->timer == NULL) {
+        s_touch_pad_filter->timer = xTimerCreate("filter_tmr", filter_period_ms / portTICK_PERIOD_MS, pdTRUE,
+        NULL, touch_pad_filter_cb);
+        if (s_touch_pad_filter->timer == NULL) {
+            ret = ESP_ERR_NO_MEM;
+        }
+        xTimerStart(s_touch_pad_filter->timer, portMAX_DELAY);
+        s_touch_pad_filter->enable = true;
+    } else {
+        xTimerChangePeriod(s_touch_pad_filter->timer, filter_period_ms / portTICK_PERIOD_MS, portMAX_DELAY);
+        s_touch_pad_filter->period = filter_period_ms;
+        xTimerStart(s_touch_pad_filter->timer, portMAX_DELAY);
+    }
+    xSemaphoreGive(rtc_touch_mux);
+    return ret;
+}
+
+esp_err_t touch_pad_filter_stop()
+{
+    RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE);
+
+    esp_err_t ret = ESP_OK;
+    xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
+    if (s_touch_pad_filter != NULL) {
+        xTimerStop(s_touch_pad_filter->timer, portMAX_DELAY);
+        s_touch_pad_filter->enable = false;
+    } else {
+        ESP_LOGE(RTC_MODULE_TAG, "Touch pad filter deleted");
+        ret = ESP_ERR_INVALID_STATE;
+    }
+    xSemaphoreGive(rtc_touch_mux);
+    return ret;
+}
+
+esp_err_t touch_pad_filter_delete()
+{
+    RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE);
+    xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
+    if (s_touch_pad_filter != NULL) {
+        if (s_touch_pad_filter->timer != NULL) {
+            xTimerStop(s_touch_pad_filter->timer, portMAX_DELAY);
+            xTimerDelete(s_touch_pad_filter->timer, portMAX_DELAY);
+            s_touch_pad_filter->timer = NULL;
+        }
+        free(s_touch_pad_filter);
+        s_touch_pad_filter = NULL;
+    }
+    xSemaphoreGive(rtc_touch_mux);
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
@@ -578,7 +917,6 @@ static esp_err_t adc1_pad_init(adc1_channel_t channel)
     ADC1_CHECK_FUNCTION_RET(rtc_gpio_output_disable(gpio_num));
     ADC1_CHECK_FUNCTION_RET(rtc_gpio_output_disable(gpio_num));
     ADC1_CHECK_FUNCTION_RET(rtc_gpio_input_disable(gpio_num));
     ADC1_CHECK_FUNCTION_RET(rtc_gpio_input_disable(gpio_num));
     ADC1_CHECK_FUNCTION_RET(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
     ADC1_CHECK_FUNCTION_RET(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
-
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 

+ 3 - 0
components/esp32/ld/esp32.peripherals.ld

@@ -3,6 +3,9 @@ PROVIDE ( SPI1 = 0x3ff42000 );
 PROVIDE ( SPI0 = 0x3ff43000 );
 PROVIDE ( SPI0 = 0x3ff43000 );
 PROVIDE ( GPIO = 0x3ff44000 );
 PROVIDE ( GPIO = 0x3ff44000 );
 PROVIDE ( SIGMADELTA = 0x3ff44f00 );
 PROVIDE ( SIGMADELTA = 0x3ff44f00 );
+PROVIDE ( RTCCNTL = 0x3ff48000 );
+PROVIDE ( RTCIO = 0x3ff48400 );
+PROVIDE ( SENS = 0x3ff48800 );
 PROVIDE ( UHCI1 = 0x3ff4C000 );
 PROVIDE ( UHCI1 = 0x3ff4C000 );
 PROVIDE ( I2S0 = 0x3ff4F000 );
 PROVIDE ( I2S0 = 0x3ff4F000 );
 PROVIDE ( UART1 = 0x3ff50000 );
 PROVIDE ( UART1 = 0x3ff50000 );

+ 1 - 0
components/soc/esp32/include/soc/rtc_cntl_struct.h

@@ -550,4 +550,5 @@ typedef volatile struct {
         uint32_t val;
         uint32_t val;
     } date;
     } date;
 } rtc_cntl_dev_t;
 } rtc_cntl_dev_t;
+extern rtc_cntl_dev_t RTCCNTL;
 #endif  /* _SOC_RTC_CNTL_STRUCT_H_ */
 #endif  /* _SOC_RTC_CNTL_STRUCT_H_ */

+ 1 - 0
components/soc/esp32/include/soc/rtc_io_struct.h

@@ -277,4 +277,5 @@ typedef volatile struct {
         uint32_t val;
         uint32_t val;
     } date;
     } date;
 } rtc_io_dev_t;
 } rtc_io_dev_t;
+extern rtc_io_dev_t RTCIO;
 #endif  /* _SOC_RTC_IO_STRUCT_H_ */
 #endif  /* _SOC_RTC_IO_STRUCT_H_ */

+ 316 - 0
components/soc/esp32/include/soc/sens_struct.h

@@ -0,0 +1,316 @@
+// Copyright 2015-2016 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_SENS_STRUCT_H_
+#define _SOC_SENS_STRUCT_H_
+typedef volatile struct {
+    union {
+        struct {
+            uint32_t sar1_clk_div:      8;
+            uint32_t sar1_sample_cycle: 8;
+            uint32_t sar1_sample_bit:   2;
+            uint32_t sar1_clk_gated:    1;
+            uint32_t sar1_sample_num:   8;
+            uint32_t sar1_dig_force:    1;
+            uint32_t sar1_data_inv:     1;
+            uint32_t reserved29:        3;
+        };
+        uint32_t val;
+    } sar_read_ctrl;
+    uint32_t sar_read_status1;                            /**/
+    union {
+        struct {
+            uint32_t sar_amp_wait1:16;
+            uint32_t sar_amp_wait2:16;
+        };
+        uint32_t val;
+    } sar_meas_wait1;
+    union {
+        struct {
+            uint32_t sar_amp_wait3: 16;
+            uint32_t force_xpd_amp:  2;
+            uint32_t force_xpd_sar:  2;
+            uint32_t sar2_rstb_wait: 8;
+            uint32_t reserved28:     4;
+        };
+        uint32_t val;
+    } sar_meas_wait2;
+    union {
+        struct {
+            uint32_t xpd_sar_amp_fsm:       4;
+            uint32_t amp_rst_fb_fsm:        4;
+            uint32_t amp_short_ref_fsm:     4;
+            uint32_t amp_short_ref_gnd_fsm: 4;
+            uint32_t xpd_sar_fsm:           4;
+            uint32_t sar_rstb_fsm:          4;
+            uint32_t sar2_xpd_wait:         8;
+        };
+        uint32_t val;
+    } sar_meas_ctrl;
+    uint32_t sar_read_status2;                            /**/
+    uint32_t ulp_cp_sleep_cyc0;                          /**/
+    uint32_t ulp_cp_sleep_cyc1;                          /**/
+    uint32_t ulp_cp_sleep_cyc2;                          /**/
+    uint32_t ulp_cp_sleep_cyc3;                          /**/
+    uint32_t ulp_cp_sleep_cyc4;                          /**/
+    union {
+        struct {
+            uint32_t sar1_bit_width:         2;
+            uint32_t sar2_bit_width:         2;
+            uint32_t sar2_en_test:           1;
+            uint32_t sar2_pwdet_cct:         3;
+            uint32_t ulp_cp_force_start_top: 1;
+            uint32_t ulp_cp_start_top:       1;
+            uint32_t sarclk_en:              1;
+            uint32_t pc_init:               11;
+            uint32_t sar2_stop:              1;
+            uint32_t sar1_stop:              1;
+            uint32_t sar2_pwdet_en:          1;
+            uint32_t reserved25:             7;
+        };
+        uint32_t val;
+    } sar_start_force;
+    union {
+        struct {
+            uint32_t mem_wr_addr_init:    11;
+            uint32_t mem_wr_addr_size:    11;
+            uint32_t rtc_mem_wr_offst_clr: 1;
+            uint32_t reserved23:           9;
+        };
+        uint32_t val;
+    } sar_mem_wr_ctrl;
+    uint32_t sar_atten1;                                  /**/
+    uint32_t sar_atten2;                                  /**/
+    union {
+        struct {
+            uint32_t i2c_slave_addr1:   11;
+            uint32_t i2c_slave_addr0:   11;
+            uint32_t meas_status:        8;
+            uint32_t reserved30:         2;
+        };
+        uint32_t val;
+    } sar_slave_addr1;
+    union {
+        struct {
+            uint32_t i2c_slave_addr3:11;
+            uint32_t i2c_slave_addr2:11;
+            uint32_t reserved22:     10;
+        };
+        uint32_t val;
+    } sar_slave_addr2;
+    union {
+        struct {
+            uint32_t i2c_slave_addr5:11;
+            uint32_t i2c_slave_addr4:11;
+            uint32_t tsens_out:       8;
+            uint32_t tsens_rdy_out:   1;
+            uint32_t reserved31:      1;
+        };
+        uint32_t val;
+    } sar_slave_addr3;
+    union {
+        struct {
+            uint32_t i2c_slave_addr7:11;
+            uint32_t i2c_slave_addr6:11;
+            uint32_t i2c_rdata:       8;
+            uint32_t i2c_done:        1;
+            uint32_t reserved31:      1;
+        };
+        uint32_t val;
+    } sar_slave_addr4;
+    union {
+        struct {
+            uint32_t tsens_xpd_wait:      12;
+            uint32_t tsens_xpd_force:      1;
+            uint32_t tsens_clk_inv:        1;
+            uint32_t tsens_clk_gated:      1;
+            uint32_t tsens_in_inv:         1;
+            uint32_t tsens_clk_div:        8;
+            uint32_t tsens_power_up:       1;
+            uint32_t tsens_power_up_force: 1;
+            uint32_t tsens_dump_out:       1;
+            uint32_t reserved27:           5;
+        };
+        uint32_t val;
+    } sar_tctrl;
+    union {
+        struct {
+            uint32_t sar_i2c_ctrl:       28;
+            uint32_t sar_i2c_start:       1;
+            uint32_t sar_i2c_start_force: 1;
+            uint32_t reserved30:          2;
+        };
+        uint32_t val;
+    } sar_i2c_ctrl;
+    union {
+        struct {
+            uint32_t meas1_data_sar:   16;
+            uint32_t meas1_done_sar:    1;
+            uint32_t meas1_start_sar:   1;
+            uint32_t meas1_start_force: 1;
+            uint32_t sar1_en_pad:      12;
+            uint32_t sar1_en_pad_force: 1;
+        };
+        uint32_t val;
+    } sar_meas_start1;
+    union {
+        struct {
+            uint32_t touch_meas_delay:16;
+            uint32_t touch_xpd_wait:   8;
+            uint32_t touch_out_sel:    1;
+            uint32_t touch_out_1en:    1;
+            uint32_t xpd_hall_force:   1;
+            uint32_t hall_phase_force: 1;
+            uint32_t reserved28:       4;
+        };
+        uint32_t val;
+    } sar_touch_ctrl1;
+    union {
+        struct {
+            uint32_t l_thresh: 16;
+            uint32_t h_thresh: 16;
+        };
+        uint32_t val;
+    } touch_thresh[5];
+    union {
+        struct {
+            uint32_t l_val: 16;
+            uint32_t h_val: 16;
+        };
+        uint32_t val;
+    } touch_meas[5];
+    union {
+        struct {
+            uint32_t touch_meas_en:     10;
+            uint32_t touch_meas_done:    1;
+            uint32_t touch_start_fsm_en: 1;
+            uint32_t touch_start_en:     1;
+            uint32_t touch_start_force:  1;
+            uint32_t touch_sleep_cycles:16;
+            uint32_t touch_meas_en_clr:  1;
+            uint32_t reserved31:         1;
+        };
+        uint32_t val;
+    } sar_touch_ctrl2;
+    uint32_t reserved_88;
+    union {
+        struct {
+            uint32_t touch_pad_worken:10;
+            uint32_t touch_pad_outen2:10;
+            uint32_t touch_pad_outen1:10;
+            uint32_t reserved30:       2;
+        };
+        uint32_t val;
+    } sar_touch_enable;
+    union {
+        struct {
+            uint32_t sar2_clk_div:      8;
+            uint32_t sar2_sample_cycle: 8;
+            uint32_t sar2_sample_bit:   2;
+            uint32_t sar2_clk_gated:    1;
+            uint32_t sar2_sample_num:   8;
+            uint32_t sar2_pwdet_force:  1;
+            uint32_t sar2_dig_force:    1;
+            uint32_t sar2_data_inv:     1;
+            uint32_t reserved30:        2;
+        };
+        uint32_t val;
+    } sar_read_ctrl2;
+    union {
+        struct {
+            uint32_t meas2_data_sar:   16;
+            uint32_t meas2_done_sar:    1;
+            uint32_t meas2_start_sar:   1;
+            uint32_t meas2_start_force: 1;
+            uint32_t sar2_en_pad:      12;
+            uint32_t sar2_en_pad_force: 1;
+        };
+        uint32_t val;
+    } sar_meas_start2;
+    union {
+        struct {
+            uint32_t sw_fstep:          16;
+            uint32_t sw_tone_en:         1;
+            uint32_t debug_bit_sel:      5;
+            uint32_t dac_dig_force:      1;
+            uint32_t dac_clk_force_low:  1;
+            uint32_t dac_clk_force_high: 1;
+            uint32_t dac_clk_inv:        1;
+            uint32_t reserved26:         6;
+        };
+        uint32_t val;
+    } sar_dac_ctrl1;
+    union {
+        struct {
+            uint32_t dac_dc1:    8;
+            uint32_t dac_dc2:    8;
+            uint32_t dac_scale1: 2;
+            uint32_t dac_scale2: 2;
+            uint32_t dac_inv1:   2;
+            uint32_t dac_inv2:   2;
+            uint32_t dac_cw_en1: 1;
+            uint32_t dac_cw_en2: 1;
+            uint32_t reserved26: 6;
+        };
+        uint32_t val;
+    } sar_dac_ctrl2;
+    union {
+        struct {
+            uint32_t sar1_dac_xpd_fsm:           4;
+            uint32_t sar1_dac_xpd_fsm_idle:      1;
+            uint32_t xpd_sar_amp_fsm_idle:       1;
+            uint32_t amp_rst_fb_fsm_idle:        1;
+            uint32_t amp_short_ref_fsm_idle:     1;
+            uint32_t amp_short_ref_gnd_fsm_idle: 1;
+            uint32_t xpd_sar_fsm_idle:           1;
+            uint32_t sar_rstb_fsm_idle:          1;
+            uint32_t sar2_rstb_force:            2;
+            uint32_t amp_rst_fb_force:           2;
+            uint32_t amp_short_ref_force:        2;
+            uint32_t amp_short_ref_gnd_force:    2;
+            uint32_t reserved19:                13;
+        };
+        uint32_t val;
+    } sar_meas_ctrl2;
+    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 sar_nouse;                                   /**/
+    union {
+        struct {
+            uint32_t sar_date:  28;
+            uint32_t reserved28: 4;
+        };
+        uint32_t val;
+    } sardate;
+} sens_dev_t;
+extern sens_dev_t SENS;
+#endif  /* _SOC_SENS_STRUCT_H_ */

+ 1 - 0
docs/Doxyfile

@@ -72,6 +72,7 @@ INPUT = \
     ../components/driver/include/driver/spi_master.h \
     ../components/driver/include/driver/spi_master.h \
     ../components/driver/include/driver/spi_slave.h \
     ../components/driver/include/driver/spi_slave.h \
     ../components/driver/include/driver/timer.h \
     ../components/driver/include/driver/timer.h \
+    ../components/driver/include/driver/touch_pad.h \
     ../components/driver/include/driver/uart.h \
     ../components/driver/include/driver/uart.h \
     ##
     ##
     ## Protocols - API Reference
     ## Protocols - API Reference

+ 1 - 0
docs/api-reference/peripherals/index.rst

@@ -18,6 +18,7 @@ Peripherals API
    SPI Master <spi_master>
    SPI Master <spi_master>
    SPI Slave <spi_slave>
    SPI Slave <spi_slave>
    Timer <timer>
    Timer <timer>
+   Touch pad <touch_pad>
    UART <uart>
    UART <uart>
 
 
 Example code for this API section is provided in :example:`peripherals` directory of ESP-IDF examples.
 Example code for this API section is provided in :example:`peripherals` directory of ESP-IDF examples.

+ 23 - 0
docs/api-reference/peripherals/touch_pad.rst

@@ -0,0 +1,23 @@
+Touch sensor
+===========
+
+Overview
+--------
+
+A touch-sensor system is built on a substrate which carries electrodes and relevant connections under a protective flat surface. 
+When a user touches the surface, the capacitance variation is triggered and a binary signal is generated to indicate whether the touch is valid.
+
+ESP32 can provide up to 10 capacitive touch pads / GPIOs. The sensing pads can be arranged in different combinations, 
+so that a larger area or more points can be detected. The touch pad sensing process is under the control of a hardware-implemented finite-state machine (FSM) which is initiated by software or a dedicated hardware timer.
+
+Application Example
+-------------------
+
+Touch sensor read example: :example:`peripherals/touch_pad_read`.
+Touch sensor interrupt example: :example:`peripherals/touch_pad_interrupt`.
+
+API Reference
+-------------
+
+.. include:: /_build/inc/touch_pad.inc
+

+ 100 - 27
examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c

@@ -16,13 +16,16 @@
 #include "soc/sens_reg.h"
 #include "soc/sens_reg.h"
 
 
 static const char* TAG = "Touch pad";
 static const char* TAG = "Touch pad";
+#define TOUCH_THRESH_NO_USE   (0)
+#define TOUCH_THRESH_PERCENT  (99)
 
 
 static bool s_pad_activated[TOUCH_PAD_MAX];
 static bool s_pad_activated[TOUCH_PAD_MAX];
+static uint32_t s_pad_init_val[TOUCH_PAD_MAX];
 
 
 
 
 /*
 /*
   Read values sensed at all available touch pads.
   Read values sensed at all available touch pads.
-  Use half of read value as the threshold
+  Use 2 / 3 of read value as the threshold
   to trigger interrupt when the pad is touched.
   to trigger interrupt when the pad is touched.
   Note: this routine demonstrates a simple way
   Note: this routine demonstrates a simple way
   to configure activation threshold for the touch pads.
   to configure activation threshold for the touch pads.
@@ -32,9 +35,17 @@ static bool s_pad_activated[TOUCH_PAD_MAX];
 static void tp_example_set_thresholds(void)
 static void tp_example_set_thresholds(void)
 {
 {
     uint16_t touch_value;
     uint16_t touch_value;
-    for (int i=0; i<TOUCH_PAD_MAX; i++) {
-        ESP_ERROR_CHECK(touch_pad_read(i, &touch_value));
-        ESP_ERROR_CHECK(touch_pad_config(i, touch_value/2));
+    //delay some time in order to make the filter work and get a initial value
+    vTaskDelay(500/portTICK_PERIOD_MS);
+
+    for (int i = 0; i<TOUCH_PAD_MAX; i++) {
+        //read filtered value
+        touch_pad_read_filtered(i, &touch_value);
+        s_pad_init_val[i] = touch_value;
+        ESP_LOGI(TAG, "test init touch val: %d\n", touch_value);
+        //set interrupt threshold.
+        ESP_ERROR_CHECK(touch_pad_set_thresh(i, touch_value * 2 / 3));
+
     }
     }
 }
 }
 
 
@@ -43,29 +54,69 @@ static void tp_example_set_thresholds(void)
   by reading a table updated by rtc_intr()
   by reading a table updated by rtc_intr()
   If so, then print it out on a serial monitor.
   If so, then print it out on a serial monitor.
   Clear related entry in the table afterwards
   Clear related entry in the table afterwards
+
+  In interrupt mode, the table is updated in touch ISR.
+
+  In filter mode, we will compare the current filtered value with the initial one.
+  If the current filtered value is less than 99% of the initial value, we can
+  regard it as a 'touched' event.
+  When calling touch_pad_init, a timer will be started to run the filter.
+  This mode is designed for the situation that the pad is covered
+  by a 2-or-3-mm-thick medium, usually glass or plastic.
+  The difference caused by a 'touch' action could be very small, but we can still use
+  filter mode to detect a 'touch' event.
  */
  */
 static void tp_example_read_task(void *pvParameter)
 static void tp_example_read_task(void *pvParameter)
 {
 {
     static int show_message;
     static int show_message;
+    int change_mode = 0;
+    int filter_mode = 0;
     while (1) {
     while (1) {
-        for (int i=0; i<TOUCH_PAD_MAX; i++) {
-            if (s_pad_activated[i] == true) {
-                ESP_LOGI(TAG, "T%d activated!", i);
-                // Wait a while for the pad being released
-                vTaskDelay(200 / portTICK_PERIOD_MS);
-                // Clear information on pad activation
-                s_pad_activated[i] = false;
-                // Reset the counter triggering a message
-                // that application is running
-                show_message = 1;
+        if (filter_mode == 0) {
+            //interrupt mode, enable touch interrupt
+            touch_pad_intr_enable();
+            for (int i = 0; i < TOUCH_PAD_MAX; i++) {
+                if (s_pad_activated[i] == true) {
+                    ESP_LOGI(TAG, "T%d activated!", i);
+                    // Wait a while for the pad being released
+                    vTaskDelay(200 / portTICK_PERIOD_MS);
+                    // Clear information on pad activation
+                    s_pad_activated[i] = false;
+                    // Reset the counter triggering a message
+                    // that application is running
+                    show_message = 1;
+                }
+            }
+        } else {
+            //filter mode, disable touch interrupt
+            touch_pad_intr_disable();
+            for (int i = 0; i < TOUCH_PAD_MAX; i++) {
+                uint16_t value = 0;
+                touch_pad_read_filtered(i, &value);
+                if (value < s_pad_init_val[i] * TOUCH_THRESH_PERCENT / 100) {
+                    ESP_LOGI(TAG, "T%d activated!", i);
+                    ESP_LOGI(TAG, "value: %d; init val: %d\n", value, s_pad_init_val[i]);
+                    vTaskDelay(200 / portTICK_PERIOD_MS);
+                    // Reset the counter to stop changing mode.
+                    change_mode = 1;
+                    show_message = 1;
+                }
             }
             }
         }
         }
+
+        vTaskDelay(10 / portTICK_PERIOD_MS);
+
         // If no pad is touched, every couple of seconds, show a message
         // If no pad is touched, every couple of seconds, show a message
         // that application is running
         // that application is running
         if (show_message++ % 500 == 0) {
         if (show_message++ % 500 == 0) {
             ESP_LOGI(TAG, "Waiting for any pad being touched...");
             ESP_LOGI(TAG, "Waiting for any pad being touched...");
         }
         }
-        vTaskDelay(10 / portTICK_PERIOD_MS);
+        // Change mode if no pad is touched for a long time.
+        // We can compare the two different mode.
+        if (change_mode++ % 2000 == 0) {
+            filter_mode = !filter_mode;
+            ESP_LOGI(TAG, "Change mode...%s\n", filter_mode == 0? "interrupt mode": "filter mode");
+        }
     }
     }
 }
 }
 
 
@@ -75,29 +126,51 @@ static void tp_example_read_task(void *pvParameter)
  */
  */
 static void tp_example_rtc_intr(void * arg)
 static void tp_example_rtc_intr(void * arg)
 {
 {
-    uint32_t pad_intr = READ_PERI_REG(SENS_SAR_TOUCH_CTRL2_REG) & 0x3ff;
-    uint32_t rtc_intr = READ_PERI_REG(RTC_CNTL_INT_ST_REG);
+    uint32_t pad_intr = touch_pad_get_status();
     //clear interrupt
     //clear interrupt
-    WRITE_PERI_REG(RTC_CNTL_INT_CLR_REG, rtc_intr);
-    SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR);
-
-    if (rtc_intr & RTC_CNTL_TOUCH_INT_ST) {
-        for (int i = 0; i < TOUCH_PAD_MAX; i++) {
-            if ((pad_intr >> i) & 0x01) {
-                s_pad_activated[i] = true;
-            }
+    touch_pad_clear_status();
+    for (int i = 0; i < TOUCH_PAD_MAX; i++) {
+        if ((pad_intr >> i) & 0x01) {
+            s_pad_activated[i] = true;
         }
         }
     }
     }
 }
 }
 
 
+/*
+ * Before reading touch pad, we need to initialize the RTC IO.
+ */
+static void tp_example_touch_pad_init()
+{
+    for (int i = 0;i< TOUCH_PAD_MAX;i++) {
+        //init RTC IO and mode for touch pad.
+        touch_pad_config(i, TOUCH_THRESH_NO_USE);
+    }
+}
 
 
 void app_main()
 void app_main()
 {
 {
-    // Initialize touch pad peripheral
+    // Initialize touch pad peripheral, it will start a timer to run a filter
     ESP_LOGI(TAG, "Initializing touch pad");
     ESP_LOGI(TAG, "Initializing touch pad");
     touch_pad_init();
     touch_pad_init();
+
+    // Initialize and start a software filter to detect slight change of capacitance.
+    touch_pad_filter_start(10);
+    // Set measuring time and sleep time
+    // In this case, measurement will sustain 0xffff / 8Mhz = 8.19ms
+    // Meanwhile, sleep time between two measurement will be 0x1000 / 150Khz = 27.3 ms
+    touch_pad_set_meas_time(0x1000, 0xffff);
+
+    //set reference voltage for charging/discharging
+    // In this case, the high reference valtage will be 2.4V - 1.5V = 0.9V
+    // The low reference voltage will be 0.8V, so that the procedure of charging
+    // and discharging would be very fast.
+    touch_pad_set_voltage(TOUCH_HVOLT_2V4, TOUCH_LVOLT_0V8, TOUCH_HVOLT_ATTEN_1V5);
+    // Init touch pad IO
+    tp_example_touch_pad_init();
+    // Set thresh hold
     tp_example_set_thresholds();
     tp_example_set_thresholds();
-    touch_pad_isr_handler_register(tp_example_rtc_intr, NULL, 0, NULL);
+    // Register touch interrupt ISR
+    touch_pad_isr_register(tp_example_rtc_intr, NULL);
 
 
     // Start a task to show what pads have been touched
     // Start a task to show what pads have been touched
     xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 2048, NULL, 5, NULL);
     xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 2048, NULL, 5, NULL);

+ 63 - 8
examples/peripherals/touch_pad_read/main/tp_read_main.c

@@ -9,24 +9,78 @@
 #include <stdio.h>
 #include <stdio.h>
 #include "freertos/FreeRTOS.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/task.h"
-
 #include "driver/touch_pad.h"
 #include "driver/touch_pad.h"
 
 
-
+#define TOUCH_TEST_LOOP_NUM   (10)
+#define TOUCH_PAD_NO_CHANGE   (-1)
+#define TOUCH_THRESH_NO_USE   (0)
 /*
 /*
   Read values sensed at all available touch pads.
   Read values sensed at all available touch pads.
-  Print out values in a loop on a serial monitor.
+ Print out values in a loop on a serial monitor.
  */
  */
 static void tp_example_read_task(void *pvParameter)
 static void tp_example_read_task(void *pvParameter)
 {
 {
     while (1) {
     while (1) {
         uint16_t touch_value;
         uint16_t touch_value;
-        for (int i=0; i<TOUCH_PAD_MAX; i++) {
-            ESP_ERROR_CHECK(touch_pad_read(i, &touch_value));
-            printf("T%d:%4d ", i, touch_value);
+        //set reference voltage for charging/discharging
+        // In this case, the high reference valtage will be 2.7V - 0V = 2.7V
+        // The low reference voltage will be 0.5
+        // So the charing/discharging time would be longer, so the counter value would be smaller.
+        touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V);
+
+        vTaskDelay(100 / portTICK_PERIOD_MS);
+        printf("Case[1], set default measure time\n");
+        for (int j = 0; j < TOUCH_TEST_LOOP_NUM; j++) {
+            for (int i = 0; i < TOUCH_PAD_MAX; i++) {
+                ESP_ERROR_CHECK(touch_pad_read(i, &touch_value));
+                printf("T%d:%5d ", i, touch_value);
+            }
+            printf("\n");
+            vTaskDelay(500 / portTICK_PERIOD_MS);
+        }
+
+        printf("Case[2], set max measure time\n");
+        //set reference voltage for charging/discharging
+        // In this case, the high reference valtage will be 2.4V - 1.5V = 0.9V
+        // The low reference voltage will be 0.8
+        // So the charing/discharging time would be shorter, so the counter value would be larger.
+        touch_pad_set_voltage(TOUCH_HVOLT_2V4, TOUCH_LVOLT_0V8, TOUCH_HVOLT_ATTEN_1V5);
+        vTaskDelay(100 / portTICK_PERIOD_MS);
+        for (int j = 0; j < TOUCH_TEST_LOOP_NUM; j++) {
+            for (int i = 0; i < TOUCH_PAD_MAX; i++) {
+                ESP_ERROR_CHECK(touch_pad_read(i, &touch_value));
+                printf("T%d:%5d ", i, touch_value);
+            }
+            printf("\n");
+            vTaskDelay(500 / portTICK_PERIOD_MS);
         }
         }
-        printf("\n");
-        vTaskDelay(500 / portTICK_PERIOD_MS);
+
+
+        touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V);
+        vTaskDelay(100/portTICK_PERIOD_MS);
+
+        printf("Case[3], set differen slope for each channel\n");
+        for (int i = 0;i<TOUCH_PAD_MAX;i++) {
+            touch_pad_set_cnt_mode(i, (i % TOUCH_PAD_SLOPE_7) + 1, TOUCH_PAD_TIE_OPT_HIGH);
+        }
+        for (int j = 0; j < TOUCH_TEST_LOOP_NUM; j++) {
+            for (int i = 0; i < TOUCH_PAD_MAX; i++) {
+                ESP_ERROR_CHECK(touch_pad_read(i, &touch_value));
+                printf("T%d:%5d ", i, touch_value);
+            }
+            printf("\n");
+            vTaskDelay(500 / portTICK_PERIOD_MS);
+        }
+        for (int i = 0;i<TOUCH_PAD_MAX;i++) {
+            touch_pad_set_cnt_mode(i, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_HIGH);
+        }
+    }
+}
+
+static void tp_example_touch_pad_init()
+{
+    for (int i = 0;i< TOUCH_PAD_MAX;i++) {
+        touch_pad_config(i, TOUCH_THRESH_NO_USE);
     }
     }
 }
 }
 
 
@@ -34,6 +88,7 @@ void app_main()
 {
 {
     // Initialize touch pad peripheral
     // Initialize touch pad peripheral
     touch_pad_init();
     touch_pad_init();
+    tp_example_touch_pad_init();
 
 
     // Start task to read values sensed by pads
     // Start task to read values sensed by pads
     xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 2048, NULL, 5, NULL);
     xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 2048, NULL, 5, NULL);