Skip to content

Commit 7143d08

Browse files
committed
fix(touch): Revert old touch driver for older IDF
1 parent ec720a8 commit 7143d08

File tree

5 files changed

+439
-0
lines changed

5 files changed

+439
-0
lines changed

cores/esp32/esp32-hal-touch-ng.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "soc/soc_caps.h"
1515

1616
#if SOC_TOUCH_SENSOR_SUPPORTED
17+
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3
1718

1819
#include "esp32-hal-touch-ng.h"
1920
#include "esp32-hal-periman.h"
@@ -540,4 +541,5 @@ extern void touchAttachInterrupt(uint8_t, voidFuncPtr, touch_value_t) __attribut
540541
extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value_t) __attribute__((weak, alias("__touchAttachArgsInterrupt")));
541542
extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt")));
542543

544+
#endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 */
543545
#endif /* SOC_TOUCH_SENSOR_SUPPORTED */

cores/esp32/esp32-hal-touch-ng.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
#define MAIN_ESP32_HAL_TOUCH_NEW_H_
2222

2323
#include "soc/soc_caps.h"
24+
2425
#if SOC_TOUCH_SENSOR_SUPPORTED
26+
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3
2527

2628
#ifdef __cplusplus
2729
extern "C" {
@@ -133,5 +135,6 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold);
133135
}
134136
#endif
135137

138+
#endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 */
136139
#endif /* SOC_TOUCH_SENSOR_SUPPORTED */
137140
#endif /* MAIN_ESP32_HAL_TOUCH_H_ */

cores/esp32/esp32-hal-touch.c

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
#include "soc/soc_caps.h"
15+
16+
#if SOC_TOUCH_SENSOR_SUPPORTED
17+
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3
18+
19+
#include "driver/touch_sensor.h"
20+
#include "esp32-hal-touch.h"
21+
#include "esp32-hal-periman.h"
22+
23+
/*
24+
Internal Private Touch Data Structure and Functions
25+
*/
26+
27+
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
28+
static uint16_t __touchSleepCycles = 0x1000;
29+
static uint16_t __touchMeasureCycles = 0x1000;
30+
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3
31+
static uint16_t __touchSleepCycles = TOUCH_PAD_SLEEP_CYCLE_DEFAULT;
32+
static uint16_t __touchMeasureCycles = TOUCH_PAD_MEASURE_CYCLE_DEFAULT;
33+
#endif
34+
35+
typedef void (*voidFuncPtr)(void);
36+
typedef void (*voidArgFuncPtr)(void *);
37+
38+
typedef struct {
39+
voidFuncPtr fn;
40+
bool callWithArgs;
41+
void *arg;
42+
#if SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3
43+
bool lastStatusIsPressed;
44+
#endif
45+
} TouchInterruptHandle_t;
46+
47+
static TouchInterruptHandle_t __touchInterruptHandlers[SOC_TOUCH_SENSOR_NUM] = {
48+
0,
49+
};
50+
51+
static uint8_t used_pads = 0;
52+
static bool initialized = false;
53+
static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false};
54+
55+
static void ARDUINO_ISR_ATTR __touchISR(void *arg) {
56+
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
57+
uint32_t pad_intr = touch_pad_get_status();
58+
//clear interrupt
59+
touch_pad_clear_status();
60+
// call Pad ISR User callback
61+
for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) {
62+
if ((pad_intr >> i) & 0x01) {
63+
if (__touchInterruptHandlers[i].fn) {
64+
// keeping backward compatibility with "void cb(void)" and with new "void cb(vooid *)"
65+
if (__touchInterruptHandlers[i].callWithArgs) {
66+
((voidArgFuncPtr)__touchInterruptHandlers[i].fn)(__touchInterruptHandlers[i].arg);
67+
} else {
68+
__touchInterruptHandlers[i].fn();
69+
}
70+
}
71+
}
72+
}
73+
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3
74+
touch_pad_intr_mask_t evt = touch_pad_read_intr_status_mask();
75+
uint8_t pad_num = touch_pad_get_current_meas_channel();
76+
if (evt & TOUCH_PAD_INTR_MASK_ACTIVE) {
77+
// touch has been pressed / touched
78+
__touchInterruptHandlers[pad_num].lastStatusIsPressed = true;
79+
}
80+
if (evt & TOUCH_PAD_INTR_MASK_INACTIVE) {
81+
// touch has been released / untouched
82+
__touchInterruptHandlers[pad_num].lastStatusIsPressed = false;
83+
}
84+
if (__touchInterruptHandlers[pad_num].fn) {
85+
// keeping backward compatibility with "void cb(void)" and with new "void cb(vooid *)"
86+
if (__touchInterruptHandlers[pad_num].callWithArgs) {
87+
((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg);
88+
} else {
89+
__touchInterruptHandlers[pad_num].fn();
90+
}
91+
}
92+
#endif
93+
}
94+
95+
static void __touchSetCycles(uint16_t measure, uint16_t sleep) {
96+
__touchSleepCycles = sleep;
97+
__touchMeasureCycles = measure;
98+
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
99+
touch_pad_set_measurement_clock_cycles(measure);
100+
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3
101+
touch_pad_set_charge_discharge_times(measure);
102+
#endif
103+
touch_pad_set_measurement_interval(sleep);
104+
}
105+
106+
static bool touchDetachBus(void *pin) {
107+
int8_t pad = digitalPinToTouchChannel((int)(pin - 1));
108+
channels_initialized[pad] = false;
109+
used_pads--;
110+
if (used_pads == 0) {
111+
if (touch_pad_deinit() != ESP_OK) //deinit touch module, as no pads are used
112+
{
113+
log_e("Touch module deinit failed!");
114+
return false;
115+
}
116+
initialized = false;
117+
}
118+
return true;
119+
}
120+
121+
static void __touchInit() {
122+
if (initialized) {
123+
return;
124+
}
125+
126+
esp_err_t err = ESP_OK;
127+
128+
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
129+
err = touch_pad_init();
130+
if (err != ESP_OK) {
131+
goto err;
132+
}
133+
// the next two lines will drive the touch reading values -- both will return ESP_OK
134+
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V);
135+
touch_pad_set_measurement_clock_cycles(__touchMeasureCycles);
136+
touch_pad_set_measurement_interval(__touchSleepCycles);
137+
// Touch Sensor Timer initiated
138+
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // returns ESP_OK
139+
err = touch_pad_filter_start(10);
140+
if (err != ESP_OK) {
141+
goto err;
142+
}
143+
// keep ISR activated - it can run all together (ISR + touchRead())
144+
err = touch_pad_isr_register(__touchISR, NULL);
145+
if (err != ESP_OK) {
146+
goto err;
147+
}
148+
touch_pad_intr_enable(); // returns ESP_OK
149+
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3
150+
err = touch_pad_init();
151+
if (err != ESP_OK) {
152+
goto err;
153+
}
154+
// the next lines will drive the touch reading values -- all os them return ESP_OK
155+
touch_pad_set_charge_discharge_times(__touchMeasureCycles);
156+
touch_pad_set_measurement_interval(__touchSleepCycles);
157+
touch_pad_set_voltage(TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD);
158+
touch_pad_set_idle_channel_connect(TOUCH_PAD_IDLE_CH_CONNECT_DEFAULT);
159+
touch_pad_denoise_t denoise = {
160+
.grade = TOUCH_PAD_DENOISE_BIT4,
161+
.cap_level = TOUCH_PAD_DENOISE_CAP_L4,
162+
};
163+
touch_pad_denoise_set_config(&denoise);
164+
touch_pad_denoise_enable();
165+
// Touch Sensor Timer initiated
166+
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // returns ESP_OK
167+
touch_pad_fsm_start(); // returns ESP_OK
168+
//ISR setup moved to __touchChannelInit
169+
#endif
170+
initialized = true;
171+
return;
172+
err:
173+
log_e(" Touch sensor initialization error.");
174+
initialized = false;
175+
return;
176+
}
177+
178+
static void __touchChannelInit(int pad) {
179+
if (channels_initialized[pad]) {
180+
return;
181+
}
182+
183+
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
184+
// Initial no Threshold and setup
185+
__touchInterruptHandlers[pad].fn = NULL;
186+
touch_pad_config(pad, TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK
187+
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3
188+
// Initial no Threshold and setup
189+
__touchInterruptHandlers[pad].fn = NULL;
190+
touch_pad_config(pad); // returns ESP_OK
191+
// keep ISR activated - it can run all together (ISR + touchRead())
192+
esp_err_t err = touch_pad_isr_register(__touchISR, NULL, TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE);
193+
if (err != ESP_OK) {
194+
log_e(" Touch sensor initialization error.");
195+
return;
196+
}
197+
touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); // returns ESP_OK
198+
#endif
199+
200+
channels_initialized[pad] = true;
201+
used_pads++;
202+
delay(20); //delay needed before reading from touch channel after config
203+
}
204+
205+
static touch_value_t __touchRead(uint8_t pin) {
206+
int8_t pad = digitalPinToTouchChannel(pin);
207+
if (pad < 0) {
208+
log_e(" No touch pad on selected pin!");
209+
return 0;
210+
}
211+
212+
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) {
213+
perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus);
214+
if (!perimanClearPinBus(pin)) {
215+
return 0;
216+
}
217+
__touchInit();
218+
__touchChannelInit(pad);
219+
220+
if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) {
221+
touchDetachBus((void *)(pin + 1));
222+
return 0;
223+
}
224+
}
225+
226+
touch_value_t touch_value;
227+
touch_pad_read_raw_data(pad, &touch_value);
228+
229+
return touch_value;
230+
}
231+
232+
static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Args, touch_value_t threshold, bool callWithArgs) {
233+
int8_t pad = digitalPinToTouchChannel(pin);
234+
if (pad < 0) {
235+
log_e(" No touch pad on selected pin!");
236+
return;
237+
}
238+
239+
if (userFunc == NULL) {
240+
// detach ISR User Call
241+
__touchInterruptHandlers[pad].fn = NULL;
242+
threshold = TOUCH_PAD_THRESHOLD_MAX; // deactivate the ISR with SOC_TOUCH_PAD_THRESHOLD_MAX
243+
} else {
244+
// attach ISR User Call
245+
__touchInit();
246+
__touchChannelInit(pad);
247+
__touchInterruptHandlers[pad].fn = userFunc;
248+
__touchInterruptHandlers[pad].callWithArgs = callWithArgs;
249+
__touchInterruptHandlers[pad].arg = Args;
250+
}
251+
252+
touch_pad_set_thresh(pad, threshold);
253+
}
254+
255+
// it keeps backwards compatibility
256+
static void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold) {
257+
__touchConfigInterrupt(pin, userFunc, NULL, threshold, false);
258+
}
259+
260+
// new additional version of the API with User Args
261+
static void __touchAttachArgsInterrupt(uint8_t pin, void (*userFunc)(void), void *args, touch_value_t threshold) {
262+
__touchConfigInterrupt(pin, userFunc, args, threshold, true);
263+
}
264+
265+
// new additional API to detach touch ISR
266+
static void __touchDettachInterrupt(uint8_t pin) {
267+
__touchConfigInterrupt(pin, NULL, NULL, 0, false); // userFunc as NULL acts as detaching
268+
}
269+
270+
/*
271+
External Public Touch API Functions
272+
*/
273+
274+
#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC
275+
void touchInterruptSetThresholdDirection(bool mustbeLower) {
276+
if (mustbeLower) {
277+
touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW);
278+
} else {
279+
touch_pad_set_trigger_mode(TOUCH_TRIGGER_ABOVE);
280+
}
281+
}
282+
#elif SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3
283+
// returns true if touch pad has been and continues pressed and false otherwise
284+
bool touchInterruptGetLastStatus(uint8_t pin) {
285+
int8_t pad = digitalPinToTouchChannel(pin);
286+
if (pad < 0) {
287+
return false;
288+
}
289+
290+
return __touchInterruptHandlers[pad].lastStatusIsPressed;
291+
}
292+
#endif
293+
294+
void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) {
295+
int8_t pad = digitalPinToTouchChannel(pin);
296+
if (pad < 0) {
297+
log_e(" No touch pad on selected pin!");
298+
return;
299+
}
300+
301+
if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) {
302+
perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus);
303+
__touchInit();
304+
__touchChannelInit(pad);
305+
if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) {
306+
log_e("Failed to set bus to Peripheral manager");
307+
touchDetachBus((void *)(pin + 1));
308+
return;
309+
}
310+
}
311+
#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC
312+
touch_pad_set_thresh(pad, threshold);
313+
314+
#elif SOC_TOUCH_SENSOR_VERSION == 2
315+
touch_pad_sleep_channel_enable(pad, true);
316+
touch_pad_sleep_set_threshold(pad, threshold);
317+
318+
#endif
319+
esp_sleep_enable_touchpad_wakeup();
320+
}
321+
322+
extern touch_value_t touchRead(uint8_t) __attribute__((weak, alias("__touchRead")));
323+
extern void touchAttachInterrupt(uint8_t, voidFuncPtr, touch_value_t) __attribute__((weak, alias("__touchAttachInterrupt")));
324+
extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value_t) __attribute__((weak, alias("__touchAttachArgsInterrupt")));
325+
extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt")));
326+
extern void touchSetCycles(uint16_t, uint16_t) __attribute__((weak, alias("__touchSetCycles")));
327+
328+
#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 */
329+
#endif /* SOC_TOUCH_SENSOR_SUPPORTED */

0 commit comments

Comments
 (0)