1. add sens_struct.h 2. add definition of RTCCNTL and RTCIO 3. modify touch pad examples 4. update example code. 5. add comments add option in menuconfig 6. fix issue that pad index 8 and 9 are mismatched 7. add touch_pad_read_filtered() api to get value filtered by iir filter 8. modify touch pad isr func 9. Make the items in perihperal.ld in the sequence of address 10. delete Kconfig for touch pad 11. add touchpad filter APIs to adjust the filter 12. add touch_pad into index.rst 13. add touch_pad in Doxyfile 14. add touch_pad.rst
177 lines
6.2 KiB
C
177 lines
6.2 KiB
C
/* Touch Pad Interrupt Example
|
|
|
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
|
|
Unless required by applicable law or agreed to in writing, this
|
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
*/
|
|
#include <stdio.h>
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "esp_log.h"
|
|
|
|
#include "driver/touch_pad.h"
|
|
#include "soc/rtc_cntl_reg.h"
|
|
#include "soc/sens_reg.h"
|
|
|
|
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 uint32_t s_pad_init_val[TOUCH_PAD_MAX];
|
|
|
|
|
|
/*
|
|
Read values sensed at all available touch pads.
|
|
Use 2 / 3 of read value as the threshold
|
|
to trigger interrupt when the pad is touched.
|
|
Note: this routine demonstrates a simple way
|
|
to configure activation threshold for the touch pads.
|
|
Do not touch any pads when this routine
|
|
is running (on application start).
|
|
*/
|
|
static void tp_example_set_thresholds(void)
|
|
{
|
|
uint16_t touch_value;
|
|
//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));
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
Check if any of touch pads has been activated
|
|
by reading a table updated by rtc_intr()
|
|
If so, then print it out on a serial monitor.
|
|
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 int show_message;
|
|
int change_mode = 0;
|
|
int filter_mode = 0;
|
|
while (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
|
|
// that application is running
|
|
if (show_message++ % 500 == 0) {
|
|
ESP_LOGI(TAG, "Waiting for any pad being touched...");
|
|
}
|
|
// 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");
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Handle an interrupt triggered when a pad is touched.
|
|
Recognize what pad has been touched and save it in a table.
|
|
*/
|
|
static void tp_example_rtc_intr(void * arg)
|
|
{
|
|
uint32_t pad_intr = touch_pad_get_status();
|
|
//clear interrupt
|
|
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()
|
|
{
|
|
// Initialize touch pad peripheral, it will start a timer to run a filter
|
|
ESP_LOGI(TAG, "Initializing touch pad");
|
|
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();
|
|
// Register touch interrupt ISR
|
|
touch_pad_isr_register(tp_example_rtc_intr, NULL);
|
|
|
|
// Start a task to show what pads have been touched
|
|
xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 2048, NULL, 5, NULL);
|
|
}
|