Skip to content

Commit 3f70195

Browse files
committed
Touch Sensor IDF Refactoring
1 parent 0b4516e commit 3f70195

File tree

9 files changed

+309
-157
lines changed

9 files changed

+309
-157
lines changed

cores/esp32/esp32-hal-touch.c

Lines changed: 174 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -12,219 +12,242 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include "esp32-hal-touch.h"
16-
#ifndef CONFIG_IDF_TARGET_ESP32C3
17-
#include "freertos/FreeRTOS.h"
18-
#include "freertos/task.h"
19-
#include "esp_attr.h"
20-
#include "soc/rtc_io_reg.h"
21-
#include "soc/sens_reg.h"
22-
#include "soc/sens_struct.h"
23-
#include "soc/rtc_cntl_reg.h"
15+
#include "soc/soc_caps.h"
16+
17+
#if SOC_TOUCH_SENSOR_NUM > 0
2418
#include "driver/touch_sensor.h"
19+
#include "esp32-hal-touch.h"
2520

26-
#include "esp_system.h"
27-
#ifdef ESP_IDF_VERSION_MAJOR // IDF 4+
28-
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
29-
#include "esp32/rom/ets_sys.h"
30-
#include "esp_intr_alloc.h"
31-
#elif CONFIG_IDF_TARGET_ESP32S2
32-
#include "esp32s2/rom/ets_sys.h"
33-
#include "esp_intr_alloc.h"
34-
#include "soc/periph_defs.h"
35-
#else
36-
#error Target CONFIG_IDF_TARGET is not supported
37-
#endif
38-
#else // ESP32 Before IDF 4.0
39-
#include "rom/ets_sys.h"
40-
#include "esp_intr.h"
41-
#endif
21+
/*
22+
Internal Private Touch Data Structure and Functions
23+
*/
4224

4325
static uint16_t __touchSleepCycles = 0x1000;
4426
static uint16_t __touchMeasureCycles = 0x1000;
4527

4628
typedef void (*voidFuncPtr)(void);
47-
static voidFuncPtr __touchInterruptHandlers[10] = {0,};
48-
static intr_handle_t touch_intr_handle = NULL;
29+
typedef void (*voidArgFuncPtr)(void *);
30+
31+
typedef struct {
32+
voidFuncPtr fn;
33+
bool callWithArgs;
34+
void* arg;
35+
#if SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3
36+
bool lastStatusIsPressed;
37+
#endif
38+
} TouchInterruptHandle_t;
4939

50-
void ARDUINO_ISR_ATTR __touchISR(void * arg)
40+
static TouchInterruptHandle_t __touchInterruptHandlers[SOC_TOUCH_SENSOR_NUM] = {0,};
41+
42+
static void ARDUINO_ISR_ATTR __touchISR(void * arg)
5143
{
52-
#if CONFIG_IDF_TARGET_ESP32
53-
uint32_t pad_intr = READ_PERI_REG(SENS_SAR_TOUCH_CTRL2_REG) & 0x3ff;
54-
uint32_t rtc_intr = READ_PERI_REG(RTC_CNTL_INT_ST_REG);
55-
uint8_t i = 0;
44+
#if SOC_TOUCH_VERSION_1 // ESP32
45+
uint32_t pad_intr = touch_pad_get_status();
5646
//clear interrupt
57-
WRITE_PERI_REG(RTC_CNTL_INT_CLR_REG, rtc_intr);
58-
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR);
59-
60-
if (rtc_intr & RTC_CNTL_TOUCH_INT_ST) {
61-
for (i = 0; i < 10; ++i) {
62-
if ((pad_intr >> i) & 0x01) {
63-
if(__touchInterruptHandlers[i]){
64-
__touchInterruptHandlers[i]();
47+
touch_pad_clear_status();
48+
// call Pad ISR User callback
49+
for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) {
50+
if ((pad_intr >> i) & 0x01) {
51+
if(__touchInterruptHandlers[i].fn){
52+
// keeping backward compatibility with "void cb(void)" and with new "void cb(vooid *)"
53+
if (__touchInterruptHandlers[i].callWithArgs) {
54+
((voidArgFuncPtr)__touchInterruptHandlers[i].fn)(__touchInterruptHandlers[i].arg);
55+
} else {
56+
__touchInterruptHandlers[i].fn();
6557
}
6658
}
6759
}
6860
}
6961
#endif
62+
63+
#if SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3
64+
touch_pad_intr_mask_t evt = touch_pad_read_intr_status_mask();
65+
uint8_t pad_num = touch_pad_get_current_meas_channel();
66+
if (evt & TOUCH_PAD_INTR_MASK_ACTIVE) {
67+
// touch has been pressed / touched
68+
__touchInterruptHandlers[pad_num].lastStatusIsPressed = true;
69+
}
70+
if (evt & TOUCH_PAD_INTR_MASK_INACTIVE) {
71+
// touch has been released / untouched
72+
__touchInterruptHandlers[pad_num].lastStatusIsPressed = false;
73+
}
74+
if(__touchInterruptHandlers[pad_num].fn){
75+
// keeping backward compatibility with "void cb(void)" and with new "void cb(vooid *)"
76+
if (__touchInterruptHandlers[pad_num].callWithArgs) {
77+
((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg);
78+
} else {
79+
__touchInterruptHandlers[pad_num].fn();
80+
}
81+
}
82+
#endif
7083
}
7184

72-
void __touchSetCycles(uint16_t measure, uint16_t sleep)
85+
86+
87+
static void __touchSetCycles(uint16_t measure, uint16_t sleep)
7388
{
7489
__touchSleepCycles = sleep;
7590
__touchMeasureCycles = measure;
76-
#if CONFIG_IDF_TARGET_ESP32
77-
//Touch pad SleepCycle Time
78-
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_SLEEP_CYCLES, __touchSleepCycles, SENS_TOUCH_SLEEP_CYCLES_S);
79-
//Touch Pad Measure Time
80-
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_MEAS_DELAY, __touchMeasureCycles, SENS_TOUCH_MEAS_DELAY_S);
81-
#else
91+
#if SOC_TOUCH_VERSION_1 || SOC_TOUCH_VERSION_2 // ESP32 || ESP32S2, ESP32S3
8292
touch_pad_set_meas_time(sleep, measure);
8393
#endif
8494
}
8595

86-
void __touchInit()
96+
97+
98+
static void __touchInit()
8799
{
88100
static bool initialized = false;
89101
if(initialized){
90102
return;
91103
}
92104
initialized = true;
93-
#if CONFIG_IDF_TARGET_ESP32
94-
SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS, 1, RTC_IO_TOUCH_XPD_BIAS_S);
95-
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN_CLR);
96-
//clear touch enable
97-
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, 0x0);
98-
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_TOUCH_SLP_TIMER_EN);
99-
__touchSetCycles(__touchMeasureCycles, __touchSleepCycles);
100-
esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, (int)ARDUINO_ISR_FLAG, __touchISR, NULL, &touch_intr_handle);
101-
#else
105+
106+
#if SOC_TOUCH_VERSION_1 // ESP32
107+
touch_pad_init();
108+
// the next two lines will drive the touch reading values
109+
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V);
110+
touch_pad_set_meas_time(__touchMeasureCycles, __touchSleepCycles);
111+
// Touch Sensor Timer initiated
112+
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
113+
touch_pad_filter_start(10);
114+
// Initial no Threshold and setup
115+
for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) {
116+
__touchInterruptHandlers[i].fn = NULL;
117+
touch_pad_config(i, SOC_TOUCH_PAD_THRESHOLD_MAX);
118+
}
119+
// keep ISR activated - it can run all together (ISR + touchRead())
120+
touch_pad_isr_register(__touchISR, NULL);
121+
touch_pad_intr_enable();
122+
#endif
123+
124+
#if SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3
102125
touch_pad_init();
103-
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V5);
104-
touch_pad_set_idle_channel_connect(TOUCH_PAD_CONN_GND);
105-
__touchSetCycles(__touchMeasureCycles, __touchSleepCycles);
126+
// the next two lines will drive the touch reading values
127+
touch_pad_set_meas_time(TOUCH_PAD_SLEEP_CYCLE_DEFAULT, TOUCH_PAD_MEASURE_CYCLE_DEFAULT);
128+
touch_pad_set_voltage(TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD);
129+
touch_pad_set_idle_channel_connect(TOUCH_PAD_IDLE_CH_CONNECT_DEFAULT);
106130
touch_pad_denoise_t denoise = {
107131
.grade = TOUCH_PAD_DENOISE_BIT4,
108132
.cap_level = TOUCH_PAD_DENOISE_CAP_L4,
109133
};
110134
touch_pad_denoise_set_config(&denoise);
111135
touch_pad_denoise_enable();
136+
// Touch Sensor Timer initiated
112137
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
113138
touch_pad_fsm_start();
139+
140+
// Initial no Threshold and setup - TOUCH0 is internal denoise channel
141+
for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) {
142+
__touchInterruptHandlers[i].fn = NULL;
143+
touch_pad_config(i);
144+
}
145+
// keep ISR activated - it can run all together (ISR + touchRead())
146+
touch_pad_isr_register(__touchISR, NULL, TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE);
147+
touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE);
114148
#endif
115149
}
116150

117-
uint16_t __touchRead(uint8_t pin)
151+
static uint32_t __touchRead(uint8_t pin)
118152
{
119153
int8_t pad = digitalPinToTouchChannel(pin);
120154
if(pad < 0){
121155
return 0;
122156
}
157+
__touchInit();
123158

124-
pinMode(pin, ANALOG);
159+
#if SOC_TOUCH_VERSION_1 // ESP32
160+
uint16_t touch_value;
161+
#endif
125162

126-
__touchInit();
163+
#if SOC_TOUCH_VERSION_2 // ESP32S2 ESP32S3
164+
uint32_t touch_value;
165+
#endif
127166

128-
#if CONFIG_IDF_TARGET_ESP32
129-
uint32_t v0 = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
130-
//Disable Intr & enable touch pad
131-
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG,
132-
(v0 & ~((1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) | (1 << (pad + SENS_TOUCH_PAD_OUTEN1_S))))
133-
| (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)));
134-
135-
SET_PERI_REG_MASK(SENS_SAR_TOUCH_ENABLE_REG, (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)));
136-
137-
uint32_t rtc_tio_reg = RTC_IO_TOUCH_PAD0_REG + pad * 4;
138-
WRITE_PERI_REG(rtc_tio_reg, (READ_PERI_REG(rtc_tio_reg)
139-
& ~(RTC_IO_TOUCH_PAD0_DAC_M))
140-
| (7 << RTC_IO_TOUCH_PAD0_DAC_S)//Touch Set Slope
141-
| RTC_IO_TOUCH_PAD0_TIE_OPT_M //Enable Tie,Init Level
142-
| RTC_IO_TOUCH_PAD0_START_M //Enable Touch Pad IO
143-
| RTC_IO_TOUCH_PAD0_XPD_M); //Enable Touch Pad Power on
144-
145-
//force oneTime test start
146-
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M);
147-
148-
SET_PERI_REG_BITS(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_XPD_WAIT, 10, SENS_TOUCH_XPD_WAIT_S);
149-
150-
while (GET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_DONE) == 0) {};
151-
152-
uint16_t touch_value = READ_PERI_REG(SENS_SAR_TOUCH_OUT1_REG + (pad / 2) * 4) >> ((pad & 1) ? SENS_TOUCH_MEAS_OUT1_S : SENS_TOUCH_MEAS_OUT0_S);
153-
154-
//clear touch force ,select the Touch mode is Timer
155-
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M);
156-
157-
//restore previous value
158-
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, v0);
159-
return touch_value;
160-
#else
161-
static uint32_t chan_mask = 0;
162-
uint32_t value = 0;
163-
if((chan_mask & (1 << pad)) == 0){
164-
if(touch_pad_set_thresh((touch_pad_t)pad, TOUCH_PAD_THRESHOLD_MAX) != ESP_OK){
165-
log_e("touch_pad_set_thresh failed");
166-
} else if(touch_pad_config((touch_pad_t)pad) != ESP_OK){
167-
log_e("touch_pad_config failed");
168-
} else {
169-
chan_mask |= (1 << pad);
170-
}
171-
}
172-
if((chan_mask & (1 << pad)) != 0) {
173-
if(touch_pad_read_raw_data((touch_pad_t)pad, &value) != ESP_OK){
174-
log_e("touch_pad_read_raw_data failed");
175-
}
176-
}
177-
return value;
167+
#if SOC_TOUCH_VERSION_1 || SOC_TOUCH_VERSION_2 // ESP32 || ESP32S2, ESP32S3
168+
touch_pad_read_raw_data(pad, &touch_value);
178169
#endif
170+
171+
return (uint32_t) touch_value;
179172
}
180173

181-
void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold)
174+
static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Args, uint32_t threshold, bool callWithArgs)
182175
{
183176
int8_t pad = digitalPinToTouchChannel(pin);
184177
if(pad < 0){
185178
return;
186179
}
187180

188-
pinMode(pin, ANALOG);
189-
190-
__touchInit();
181+
if (userFunc == NULL) {
182+
// dettach ISR User Call
183+
__touchInterruptHandlers[pad].fn = NULL;
184+
threshold = SOC_TOUCH_PAD_THRESHOLD_MAX; // deactivate the ISR with SOC_TOUCH_PAD_THRESHOLD_MAX
185+
} else {
186+
// attach ISR User Call
187+
__touchInit();
188+
__touchInterruptHandlers[pad].fn = userFunc;
189+
__touchInterruptHandlers[pad].callWithArgs = callWithArgs;
190+
__touchInterruptHandlers[pad].arg = Args;
191+
}
191192

192-
__touchInterruptHandlers[pad] = userFunc;
193-
194-
#if CONFIG_IDF_TARGET_ESP32
195-
//clear touch force ,select the Touch mode is Timer
196-
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_EN_M|SENS_TOUCH_START_FORCE_M);
197-
198-
//interrupt when touch value < threshold
199-
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_OUT_SEL);
200-
//Intr will give ,when SET0 < threshold
201-
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_TOUCH_OUT_1EN);
202-
//Enable Rtc Touch Module Intr,the Interrupt need Rtc out Enable
203-
SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_TOUCH_INT_ENA);
204-
205-
//set threshold
206-
uint8_t shift = (pad & 1) ? SENS_TOUCH_OUT_TH1_S : SENS_TOUCH_OUT_TH0_S;
207-
SET_PERI_REG_BITS((SENS_SAR_TOUCH_THRES1_REG + (pad / 2) * 4), SENS_TOUCH_OUT_TH0, threshold, shift);
208-
209-
uint32_t rtc_tio_reg = RTC_IO_TOUCH_PAD0_REG + pad * 4;
210-
WRITE_PERI_REG(rtc_tio_reg, (READ_PERI_REG(rtc_tio_reg)
211-
& ~(RTC_IO_TOUCH_PAD0_DAC_M))
212-
| (7 << RTC_IO_TOUCH_PAD0_DAC_S)//Touch Set Slope
213-
| RTC_IO_TOUCH_PAD0_TIE_OPT_M //Enable Tie,Init Level
214-
| RTC_IO_TOUCH_PAD0_START_M //Enable Touch Pad IO
215-
| RTC_IO_TOUCH_PAD0_XPD_M); //Enable Touch Pad Power on
216-
217-
//Enable Digital rtc control :work mode and out mode
218-
SET_PERI_REG_MASK(SENS_SAR_TOUCH_ENABLE_REG,
219-
(1 << (pad + SENS_TOUCH_PAD_WORKEN_S)) | \
220-
(1 << (pad + SENS_TOUCH_PAD_OUTEN2_S)) | \
221-
(1 << (pad + SENS_TOUCH_PAD_OUTEN1_S)));
222-
#else
193+
#if SOC_TOUCH_VERSION_1 // ESP32
194+
touch_pad_config(pad, (uint16_t) threshold);
195+
#endif
223196

197+
#if SOC_TOUCH_VERSION_2 // ESP32S2, ESP32S3
198+
touch_pad_set_thresh(pad, threshold);
224199
#endif
225200
}
226201

227-
extern uint16_t touchRead(uint8_t pin) __attribute__ ((weak, alias("__touchRead")));
228-
extern void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint16_t threshold) __attribute__ ((weak, alias("__touchAttachInterrupt")));
229-
extern void touchSetCycles(uint16_t measure, uint16_t sleep) __attribute__ ((weak, alias("__touchSetCycles")));
202+
// it keeps backwards compatibility
203+
static void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), uint32_t threshold)
204+
{
205+
__touchConfigInterrupt(pin, userFunc, NULL, threshold, false);
206+
}
207+
208+
// new additional version of the API with User Args
209+
static void __touchAttachArgsInterrupt(uint8_t pin, void (*userFunc)(void), void *args, uint32_t threshold)
210+
{
211+
__touchConfigInterrupt(pin, userFunc, args, threshold, true);
212+
}
213+
214+
// new additional API to dettach touch ISR
215+
static void __touchDettachInterrupt(uint8_t pin)
216+
{
217+
__touchConfigInterrupt(pin, NULL, NULL, 0, false); // userFunc as NULL acts as dettaching
218+
}
219+
/*
220+
External Public Touch API Functions
221+
*/
222+
223+
#if SOC_TOUCH_VERSION_1 // Only for ESP32 SoC
224+
void touchInterruptSetThresholdDirection(bool mustbeLower) {
225+
if (mustbeLower) {
226+
touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW);
227+
} else {
228+
touch_pad_set_trigger_mode(TOUCH_TRIGGER_ABOVE);
229+
}
230+
}
231+
#endif
232+
233+
#if SOC_TOUCH_VERSION_2 // Only for ESP32S2 and ESP32S3
234+
// returns true if touch pad has been and continues pressed and false otherwise
235+
bool touchInterruptGetLastStatus(uint8_t pin) {
236+
int8_t pad = digitalPinToTouchChannel(pin);
237+
if(pad < 0){
238+
return false;
239+
}
240+
241+
return __touchInterruptHandlers[pad].lastStatusIsPressed;
242+
}
230243
#endif
244+
245+
246+
247+
extern uint32_t touchRead(uint8_t) __attribute__ ((weak, alias("__touchRead")));
248+
extern void touchAttachInterrupt(uint8_t, voidFuncPtr, uint32_t) __attribute__ ((weak, alias("__touchAttachInterrupt")));
249+
extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, uint32_t) __attribute__ ((weak, alias("__touchAttachArgsInterrupt")));
250+
extern void touchDetachInterrupt(uint8_t) __attribute__ ((weak, alias("__touchDettachInterrupt")));
251+
extern void touchSetCycles(uint16_t, uint16_t) __attribute__ ((weak, alias("__touchSetCycles")));
252+
253+
#endif // #if SOC_TOUCH_SENSOR_NUM > 0

0 commit comments

Comments
 (0)