Skip to content

feat(touch): Support NG touch driver for P4 #10448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 21, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ set(CORE_SRCS
cores/esp32/esp32-hal-timer.c
cores/esp32/esp32-hal-tinyusb.c
cores/esp32/esp32-hal-touch.c
cores/esp32/esp32-hal-touch-ng.c
cores/esp32/esp32-hal-uart.c
cores/esp32/esp32-hal-rmt.c
cores/esp32/Esp.cpp
@@ -317,6 +318,10 @@ if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThre
endif()
endif()

if(IDF_TARGET STREQUAL "esp32p4")
list(APPEND requires esp_driver_touch_sens)
endif()

idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires})

if(NOT CONFIG_FREERTOS_HZ EQUAL 1000 AND NOT "$ENV{ARDUINO_SKIP_TICK_CHECK}")
453 changes: 453 additions & 0 deletions cores/esp32/esp32-hal-touch-ng.c

Large diffs are not rendered by default.

91 changes: 91 additions & 0 deletions cores/esp32/esp32-hal-touch-ng.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
Arduino.h - Main include file for the Arduino SDK
Copyright (c) 2005-2013 Arduino Team. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef MAIN_ESP32_HAL_TOUCH_NEW_H_
#define MAIN_ESP32_HAL_TOUCH_NEW_H_

#include "soc/soc_caps.h"
#if SOC_TOUCH_SENSOR_SUPPORTED
#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4

#ifdef __cplusplus
extern "C" {
#endif

#include "esp32-hal.h"

typedef uint32_t touch_value_t;

/*
* Set time in us that measurement operation takes
* The result from touchRead, threshold and detection
* accuracy depend on these values.
* Note: must be called before setting up touch pads
**/
void touchSetTiming(float measure, uint32_t sleep);

/*
* Tune the touch pad frequency.
* Note: Must be called before setting up touch pads
*/
void touchSetConfig(uint32_t _div_num, uint8_t coarse_freq_tune, uint8_t fine_freq_tune);

/*
* Read touch pad value.
* You can use this method to chose a good threshold value
* to use as value for touchAttachInterrupt.
* */
touch_value_t touchRead(uint8_t pin);

/*
* Set function to be called if touch pad value rises by given increment (threshold).
* Use touchRead to determine a proper threshold between touched and untouched state.
* */
void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold);
void touchAttachInterruptArg(uint8_t pin, void (*userFunc)(void *), void *arg, touch_value_t threshold);
void touchDetachInterrupt(uint8_t pin);

/*
* Returns true when the latest ISR status for the Touchpad is that it is touched (Active)
* and false when the Touchpad is untoouched (Inactive).
* This function can be used in conjunction with ISR User callback in order to take action
* as soon as the touchpad is touched and/or released.
**/
bool touchInterruptGetLastStatus(uint8_t pin);

/*
* Set the default threshold for touch pads.
* The threshold is a percentage of the benchmark value.
* The default value is 1.5%.
**/
void touchSetDefaultThreshold(float percentage);

/*
* Setup touch pad wake up from deep sleep /light sleep with given threshold.
* When light sleep is used, all used touch pads will be able to wake up the chip.
**/
void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold);

#ifdef __cplusplus
}
#endif

#endif /* SOC_TOUCH_SENSOR_VERSION == 3 */
#endif /* SOC_TOUCH_SENSOR_SUPPORTED */
#endif /* MAIN_ESP32_HAL_TOUCH_H_ */
27 changes: 12 additions & 15 deletions cores/esp32/esp32-hal-touch.c
Original file line number Diff line number Diff line change
@@ -14,10 +14,8 @@
#include "soc/soc_caps.h"

#if SOC_TOUCH_SENSOR_SUPPORTED
#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4
// ToDo: Implement touch sensor for ESP32P4
#warning "Touch sensor not implemented for ESP32P4 yet"
#else
#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3

#include "driver/touch_sensor.h"
#include "esp32-hal-touch.h"
#include "esp32-hal-periman.h"
@@ -26,10 +24,10 @@
Internal Private Touch Data Structure and Functions
*/

#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
static uint16_t __touchSleepCycles = 0x1000;
static uint16_t __touchMeasureCycles = 0x1000;
#elif SOC_TOUCH_SENSOR_VERSION >= 2 // ESP32S2, ESP32S3, ESP32P4
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3
static uint16_t __touchSleepCycles = TOUCH_PAD_SLEEP_CYCLE_DEFAULT;
static uint16_t __touchMeasureCycles = TOUCH_PAD_MEASURE_CYCLE_DEFAULT;
#endif
@@ -55,7 +53,7 @@ static bool initialized = false;
static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false};

static void ARDUINO_ISR_ATTR __touchISR(void *arg) {
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
uint32_t pad_intr = touch_pad_get_status();
//clear interrupt
touch_pad_clear_status();
@@ -97,7 +95,7 @@ static void ARDUINO_ISR_ATTR __touchISR(void *arg) {
static void __touchSetCycles(uint16_t measure, uint16_t sleep) {
__touchSleepCycles = sleep;
__touchMeasureCycles = measure;
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
touch_pad_set_measurement_clock_cycles(measure);
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3
touch_pad_set_charge_discharge_times(measure);
@@ -127,7 +125,7 @@ static void __touchInit() {

esp_err_t err = ESP_OK;

#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
err = touch_pad_init();
if (err != ESP_OK) {
goto err;
@@ -147,7 +145,7 @@ static void __touchInit() {
if (err != ESP_OK) {
goto err;
}
touch_pad_intr_enable(); // returns ESP_OK
touch_pad_intr_enable(); // returns ESP_OK
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3
err = touch_pad_init();
if (err != ESP_OK) {
@@ -169,7 +167,6 @@ static void __touchInit() {
touch_pad_fsm_start(); // returns ESP_OK
//ISR setup moved to __touchChannelInit
#endif

initialized = true;
return;
err:
@@ -183,11 +180,11 @@ static void __touchChannelInit(int pad) {
return;
}

#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
// Initial no Threshold and setup
__touchInterruptHandlers[pad].fn = NULL;
touch_pad_config(pad, TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3
// Initial no Threshold and setup
__touchInterruptHandlers[pad].fn = NULL;
touch_pad_config(pad); // returns ESP_OK
@@ -274,7 +271,7 @@ static void __touchDettachInterrupt(uint8_t pin) {
External Public Touch API Functions
*/

#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC
#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC
void touchInterruptSetThresholdDirection(bool mustbeLower) {
if (mustbeLower) {
touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW);
@@ -328,5 +325,5 @@ extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value
extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt")));
extern void touchSetCycles(uint16_t, uint16_t) __attribute__((weak, alias("__touchSetCycles")));

#endif /* SOC_TOUCH_SENSOR_VERSION == 3 */
#endif /* SOC_TOUCH_SENSOR_VERSION <= 2 */
#endif /* SOC_TOUCH_SENSOR_SUPPORTED */
4 changes: 2 additions & 2 deletions cores/esp32/esp32-hal-touch.h
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@

#include "soc/soc_caps.h"
#if SOC_TOUCH_SENSOR_SUPPORTED
#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32 ESP32S2 ESP32S3

#ifdef __cplusplus
extern "C" {
@@ -37,8 +38,6 @@ extern "C" {
typedef uint16_t touch_value_t;
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2 ESP32S3
typedef uint32_t touch_value_t;
#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4
typedef uint32_t touch_value_t;
#endif

/*
@@ -99,5 +98,6 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold);
}
#endif

#endif /* SOC_TOUCH_SENSOR_VERSION <= 2 */
#endif /* SOC_TOUCH_SENSOR_SUPPORTED */
#endif /* MAIN_ESP32_HAL_TOUCH_H_ */
1 change: 1 addition & 0 deletions cores/esp32/esp32-hal.h
Original file line number Diff line number Diff line change
@@ -74,6 +74,7 @@ void yield(void);
#include "esp32-hal-uart.h"
#include "esp32-hal-gpio.h"
#include "esp32-hal-touch.h"
#include "esp32-hal-touch-ng.h"
#include "esp32-hal-dac.h"
#include "esp32-hal-adc.h"
#include "esp32-hal-spi.h"
2 changes: 1 addition & 1 deletion cores/esp32/io_pin_remap.h
Original file line number Diff line number Diff line change
@@ -106,7 +106,7 @@ int8_t gpioNumberToDigitalPin(int8_t gpioNumber);
#define spiAttachMOSI(spi, mosi) spiAttachMOSI(spi, digitalPinToGPIONumber(mosi))
#define spiAttachSS(spi, cs_num, ss) spiAttachSS(spi, cs_num, digitalPinToGPIONumber(ss))

// cores/esp32/esp32-hal-touch.h
// cores/esp32/esp32-hal-touch.h && cores/esp32/esp32-hal-touch-ng.h
#define touchInterruptGetLastStatus(pin) touchInterruptGetLastStatus(digitalPinToGPIONumber(pin))
#define touchRead(pin) touchRead(digitalPinToGPIONumber(pin))
#define touchAttachInterruptArg(pin, userFunc, arg, threshold) touchAttachInterruptArg(digitalPinToGPIONumber(pin), userFunc, arg, threshold)
Original file line number Diff line number Diff line change
@@ -15,9 +15,11 @@ Pranav Cherukupalli <cherukupallip@gmail.com>
*/

#if CONFIG_IDF_TARGET_ESP32
#define THRESHOLD 40 /* Greater the value, more the sensitivity */
#else //ESP32-S2 and ESP32-S3 + default for other chips (to be adjusted) */
#define THRESHOLD 40 /* Greater the value, more the sensitivity */
#elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
#define THRESHOLD 5000 /* Lower the value, more the sensitivity */
#else // ESP32-P4 + default for other chips (to be adjusted) */
#define THRESHOLD 500 /* Lower the value, more the sensitivity */
#endif

RTC_DATA_ATTR int bootCount = 0;
@@ -88,7 +90,7 @@ void setup() {
touchSleepWakeUpEnable(T3, THRESHOLD);
touchSleepWakeUpEnable(T7, THRESHOLD);

#else //ESP32-S2 + ESP32-S3
#else //ESP32-S2 + ESP32-S3 + ESP32-P4
//Setup sleep wakeup on Touch Pad 3 (GPIO3)
touchSleepWakeUpEnable(T3, THRESHOLD);

3 changes: 1 addition & 2 deletions libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@
"targets": {
"esp32c3": false,
"esp32c6": false,
"esp32h2": false,
"esp32p4": false
"esp32h2": false
}
}
Original file line number Diff line number Diff line change
@@ -3,7 +3,12 @@ This is an example how to use Touch Intrrerupts
The bigger the threshold, the more sensible is the touch
*/

#if CONFIG_IDF_TARGET_ESP32P4
int threshold = 0; // when 0 is used, the benchmarked value will be used
#else
int threshold = 40;
#endif

bool touch1detected = false;
bool touch2detected = false;

5 changes: 1 addition & 4 deletions libraries/ESP32/examples/Touch/TouchInterrupt/ci.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
{
"requires": [
"CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y"
],
"targets": {
"esp32p4": false
}
]
}
5 changes: 1 addition & 4 deletions libraries/ESP32/examples/Touch/TouchRead/ci.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
{
"requires": [
"CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y"
],
"targets": {
"esp32p4": false
}
]
}
5 changes: 1 addition & 4 deletions tests/validation/touch/ci.json
Original file line number Diff line number Diff line change
@@ -5,8 +5,5 @@
},
"requires": [
"CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y"
],
"targets": {
"esp32p4": false
}
]
}
75 changes: 64 additions & 11 deletions tests/validation/touch/touch.ino
Original file line number Diff line number Diff line change
@@ -2,6 +2,10 @@
#include "soc/soc_caps.h"
#include "driver/touch_pad.h"

#if SOC_TOUCH_SENSOR_VERSION == 3
#include "hal/touch_sensor_ll.h"
#endif

#if CONFIG_IDF_TARGET_ESP32

#define TEST_TOUCH_CHANNEL (9)
@@ -15,11 +19,7 @@ uint8_t TOUCH_GPIOS[] = {4, 2, 15, 13, 12, 14, 27, 33, 32};

#define NO_TOUCH_GPIO 25

#define RELEASED_VALUE 75 //75+ read value to pass test
#define PRESSED_VALUE 20 //20- read value to pass test
#define INTERRUPT_THRESHOLD 40

#else //ESP32S2 and ESP32S3
#elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)

#define TEST_TOUCH_CHANNEL (12) //14
static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = {
@@ -33,20 +33,39 @@ uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 /*,13,14*/};

#define NO_TOUCH_GPIO 17

#if CONFIG_IDF_TARGET_ESP32S2
#else //ESP32P4

#define TEST_TOUCH_CHANNEL (5) //14
static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = {
TOUCH_PAD_NUM0, TOUCH_PAD_NUM1, TOUCH_PAD_NUM2,
TOUCH_PAD_NUM3, TOUCH_PAD_NUM4, /* TOUCH_PAD_NUM5, TOUCH_PAD_NUM6,
TOUCH_PAD_NUM7, TOUCH_PAD_NUM8, TOUCH_PAD_NUM9, TOUCH_PAD_NUM10, TOUCH_PAD_NUM11, TOUCH_PAD_NUM12, TOUCH_PAD_NUM13*/
};

uint8_t TOUCH_GPIOS[] = {2, 3, 4, 5, 6 /*, 7, 8, 9, 10, 11, 12 ,13, 14, 15*/};

#define NO_TOUCH_GPIO 17
#endif

#if CONFIG_IDF_TARGET_ESP32
#define RELEASED_VALUE 75 //75+ read value to pass test
#define PRESSED_VALUE 20 //20- read value to pass test
#define INTERRUPT_THRESHOLD 40
#elif CONFIG_IDF_TARGET_ESP32S2
#define RELEASED_VALUE 10000 //10000- read value to pass test
#define PRESSED_VALUE 42000 //40000+ read value to pass test
#define INTERRUPT_THRESHOLD 30000
#elif CONFIG_IDF_TARGET_ESP32S3
#define RELEASED_VALUE 25000 //25000- read value to pass test
#define PRESSED_VALUE 90000 //90000+ read value to pass test
#define INTERRUPT_THRESHOLD 80000
#elif CONFIG_IDF_TARGET_ESP32P4
#define PRESSED_VALUE_DIFFERENCE 200 //200+ read value difference against the unpressed value
#define INTERRUPT_THRESHOLD 0 // Use benchmarked threshold
#else
#error Test not currently supported on this chip. Please adjust and try again!
#endif

#endif

bool touch1detected = false;
bool touch2detected = false;

@@ -59,17 +78,25 @@ void gotTouch2() {
}

/*
* Change the slope to get larger value from touch sensor.
* Change the slope to get larger value from touch sensor. (Capacitor for ESP32P4)
*/
static void test_press_fake(touch_pad_t pad_num) {
#if SOC_TOUCH_SENSOR_VERSION <= 2
touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_1, TOUCH_PAD_TIE_OPT_DEFAULT);
#else
touch_ll_set_internal_capacitor(0x7f);
#endif
}

/*
* Change the slope to get smaller value from touch sensor.
* Change the slope to get smaller value from touch sensor. (Capacitor for ESP32P4)
*/
static void test_release_fake(touch_pad_t pad_num) {
#if SOC_TOUCH_SENSOR_VERSION <= 2
touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT);
#else
touch_ll_set_internal_capacitor(0);
#endif
}

/* These functions are intended to be called before and after each test. */
@@ -87,6 +114,7 @@ void tearDown(void) {
*/
void test_touch_read(void) {

#if SOC_TOUCH_SENSOR_VERSION <= 2
//TEST RELEASE STATE
for (int i = 0; i < sizeof(TOUCH_GPIOS); i++) {
#ifdef CONFIG_IDF_TARGET_ESP32
@@ -109,6 +137,29 @@ void test_touch_read(void) {
TEST_ASSERT_GREATER_THAN(PRESSED_VALUE, touchRead(TOUCH_GPIOS[k]));
#endif
}
#else //TOUCH V3
//TEST RELEASE STATE
touch_value_t touch_unpressed[sizeof(TOUCH_GPIOS)];
for (int i = 0; i < sizeof(TOUCH_GPIOS); i++) {
touch_unpressed[i] = touchRead(TOUCH_GPIOS[i]);
}

// TEST PRESS STATE
for (int j = 0; j < TEST_TOUCH_CHANNEL; j++) {
test_press_fake(touch_list[j]);
}
delay(100);

touch_value_t touch_pressed[sizeof(TOUCH_GPIOS)];
for (int k = 0; k < sizeof(TOUCH_GPIOS); k++) {
touch_pressed[k] = touchRead(TOUCH_GPIOS[k]);
}

// COMPARE PRESSED > UNPRESSED
for (int l = 0; l < sizeof(TOUCH_GPIOS); l++) {
TEST_ASSERT_GREATER_THAN((touch_unpressed[l] + PRESSED_VALUE_DIFFERENCE), touch_pressed[l]);
}
#endif
}

void test_touch_interrtupt(void) {
@@ -146,4 +197,6 @@ void setup() {
UNITY_END();
}

void loop() {}
void loop() {
delay(10);
}