1 /*
2  * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdlib.h>
8 #include <ctype.h>
9 #include "sdkconfig.h"
10 #include "esp_types.h"
11 #include "esp_log.h"
12 #include "sys/lock.h"
13 #include "soc/rtc.h"
14 #include "soc/periph_defs.h"
15 #include "freertos/FreeRTOS.h"
16 #include "freertos/xtensa_api.h"
17 #include "freertos/semphr.h"
18 #include "freertos/timers.h"
19 #include "esp_intr_alloc.h"
20 #include "driver/rtc_io.h"
21 #include "driver/touch_pad.h"
22 #include "driver/rtc_cntl.h"
23 #include "driver/gpio.h"
24 #include "esp_check.h"
25 
26 #ifndef NDEBUG
27 // Enable built-in checks in queue.h in debug builds
28 #define INVARIANTS
29 #endif
30 #include "sys/queue.h"
31 #include "hal/touch_sensor_types.h"
32 #include "hal/touch_sensor_hal.h"
33 
34 typedef struct {
35     TimerHandle_t timer;
36     uint16_t filtered_val[TOUCH_PAD_MAX];
37     uint16_t raw_val[TOUCH_PAD_MAX];
38     uint32_t filter_period;
39     uint32_t period;
40     bool enable;
41 } touch_pad_filter_t;
42 static touch_pad_filter_t *s_touch_pad_filter = NULL;
43 // check if touch pad be initialized.
44 static uint16_t s_touch_pad_init_bit = 0x0000;
45 static filter_cb_t s_filter_cb = NULL;
46 static SemaphoreHandle_t rtc_touch_mux = NULL;
47 
48 #define TOUCH_PAD_FILTER_FACTOR_DEFAULT   (4)   // IIR filter coefficient.
49 #define TOUCH_PAD_SHIFT_DEFAULT           (4)   // Increase computing accuracy.
50 #define TOUCH_PAD_SHIFT_ROUND_DEFAULT     (8)   // ROUND = 2^(n-1); rounding off for fractional.
51 
52 static const char *TOUCH_TAG = "TOUCH_SENSOR";
53 
54 #define TOUCH_CHANNEL_CHECK(channel) ESP_RETURN_ON_FALSE(channel < SOC_TOUCH_SENSOR_NUM, ESP_ERR_INVALID_ARG, TOUCH_TAG,  "Touch channel error");
55 #define TOUCH_NULL_POINTER_CHECK(p, name) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, TOUCH_TAG, "input param '"name"' is NULL")
56 #define TOUCH_PARAM_CHECK_STR(s)     ""s" parameter error"
57 
58 extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
59 #define TOUCH_ENTER_CRITICAL()  portENTER_CRITICAL(&rtc_spinlock)
60 #define TOUCH_EXIT_CRITICAL()  portEXIT_CRITICAL(&rtc_spinlock)
61 
62 /*---------------------------------------------------------------
63                     Touch Pad
64 ---------------------------------------------------------------*/
65 //Some register bits of touch sensor 8 and 9 are mismatched, we need to swap the bits.
66 #define BITSWAP(data, n, m)   (((data >> n) &  0x1)  == ((data >> m) & 0x1) ? (data) : ((data) ^ ((0x1 <<n) | (0x1 << m))))
67 #define TOUCH_BITS_SWAP(v)  BITSWAP(v, TOUCH_PAD_NUM8, TOUCH_PAD_NUM9)
68 static esp_err_t _touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value, touch_fsm_mode_t mode);
69 
touch_pad_isr_handler_register(void (* fn)(void *),void * arg,int no_use,intr_handle_t * handle_no_use)70 esp_err_t touch_pad_isr_handler_register(void (*fn)(void *), void *arg, int no_use, intr_handle_t *handle_no_use)
71 {
72     ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TOUCH_TAG,  "Touch_Pad ISR null");
73     return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M);
74 }
75 
touch_pad_isr_register(intr_handler_t fn,void * arg)76 esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg)
77 {
78     ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TOUCH_TAG,  "Touch_Pad ISR null");
79     return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M);
80 }
81 
_touch_filter_iir(uint32_t in_now,uint32_t out_last,uint32_t k)82 static uint32_t _touch_filter_iir(uint32_t in_now, uint32_t out_last, uint32_t k)
83 {
84     if (k == 0) {
85         return in_now;
86     } else {
87         uint32_t out_now = (in_now + (k - 1) * out_last) / k;
88         return out_now;
89     }
90 }
91 
touch_pad_set_filter_read_cb(filter_cb_t read_cb)92 esp_err_t touch_pad_set_filter_read_cb(filter_cb_t read_cb)
93 {
94     s_filter_cb = read_cb;
95     return ESP_OK;
96 }
97 
touch_pad_filter_cb(void * arg)98 static void touch_pad_filter_cb(void *arg)
99 {
100     static uint32_t s_filtered_temp[TOUCH_PAD_MAX] = {0};
101 
102     if (s_touch_pad_filter == NULL || rtc_touch_mux == NULL) {
103         return;
104     }
105     uint16_t val = 0;
106     touch_fsm_mode_t mode;
107     xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
108     touch_pad_get_fsm_mode(&mode);
109     for (int i = 0; i < TOUCH_PAD_MAX; i++) {
110         if ((s_touch_pad_init_bit >> i) & 0x1) {
111             _touch_pad_read(i, &val, mode);
112             s_touch_pad_filter->raw_val[i] = val;
113             s_filtered_temp[i] = s_filtered_temp[i] == 0 ? ((uint32_t)val << TOUCH_PAD_SHIFT_DEFAULT) : s_filtered_temp[i];
114             s_filtered_temp[i] = _touch_filter_iir((val << TOUCH_PAD_SHIFT_DEFAULT),
115                                                    s_filtered_temp[i], TOUCH_PAD_FILTER_FACTOR_DEFAULT);
116             s_touch_pad_filter->filtered_val[i] = (s_filtered_temp[i] + TOUCH_PAD_SHIFT_ROUND_DEFAULT) >> TOUCH_PAD_SHIFT_DEFAULT;
117         }
118     }
119     xTimerReset(s_touch_pad_filter->timer, portMAX_DELAY);
120     xSemaphoreGive(rtc_touch_mux);
121     if (s_filter_cb) {
122         //return the raw data and filtered data.
123         s_filter_cb(s_touch_pad_filter->raw_val, s_touch_pad_filter->filtered_val);
124     }
125 }
126 
touch_pad_set_meas_time(uint16_t sleep_cycle,uint16_t meas_cycle)127 esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_cycle)
128 {
129     TOUCH_ENTER_CRITICAL();
130     touch_hal_set_meas_time(meas_cycle);
131     touch_hal_set_sleep_time(sleep_cycle);
132     TOUCH_EXIT_CRITICAL();
133 
134     return ESP_OK;
135 }
136 
touch_pad_get_meas_time(uint16_t * sleep_cycle,uint16_t * meas_cycle)137 esp_err_t touch_pad_get_meas_time(uint16_t *sleep_cycle, uint16_t *meas_cycle)
138 {
139     TOUCH_NULL_POINTER_CHECK(sleep_cycle, "sleep_cycle");
140     TOUCH_NULL_POINTER_CHECK(meas_cycle, "meas_cycle");
141     TOUCH_ENTER_CRITICAL();
142     touch_hal_get_meas_time(meas_cycle);
143     touch_hal_get_sleep_time(sleep_cycle);
144     TOUCH_EXIT_CRITICAL();
145 
146     return ESP_OK;
147 }
148 
touch_pad_set_trigger_mode(touch_trigger_mode_t mode)149 esp_err_t touch_pad_set_trigger_mode(touch_trigger_mode_t mode)
150 {
151     ESP_RETURN_ON_FALSE((mode < TOUCH_TRIGGER_MAX), ESP_ERR_INVALID_ARG, TOUCH_TAG,  TOUCH_PARAM_CHECK_STR("mode"));
152     TOUCH_ENTER_CRITICAL();
153     touch_hal_set_trigger_mode(mode);
154     TOUCH_EXIT_CRITICAL();
155     return ESP_OK;
156 }
157 
touch_pad_get_trigger_mode(touch_trigger_mode_t * mode)158 esp_err_t touch_pad_get_trigger_mode(touch_trigger_mode_t *mode)
159 {
160     TOUCH_NULL_POINTER_CHECK(mode, "mode");
161     touch_hal_get_trigger_mode(mode);
162     return ESP_OK;
163 }
164 
touch_pad_set_trigger_source(touch_trigger_src_t src)165 esp_err_t touch_pad_set_trigger_source(touch_trigger_src_t src)
166 {
167     ESP_RETURN_ON_FALSE((src < TOUCH_TRIGGER_SOURCE_MAX), ESP_ERR_INVALID_ARG, TOUCH_TAG,  TOUCH_PARAM_CHECK_STR("src"));
168     TOUCH_ENTER_CRITICAL();
169     touch_hal_set_trigger_source(src);
170     TOUCH_EXIT_CRITICAL();
171     return ESP_OK;
172 }
173 
touch_pad_get_trigger_source(touch_trigger_src_t * src)174 esp_err_t touch_pad_get_trigger_source(touch_trigger_src_t *src)
175 {
176     TOUCH_NULL_POINTER_CHECK(src, "src");
177     touch_hal_get_trigger_source(src);
178     return ESP_OK;
179 }
180 
touch_pad_set_group_mask(uint16_t set1_mask,uint16_t set2_mask,uint16_t en_mask)181 esp_err_t touch_pad_set_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask)
182 {
183     ESP_RETURN_ON_FALSE((set1_mask <= TOUCH_PAD_BIT_MASK_ALL), ESP_ERR_INVALID_ARG, TOUCH_TAG,  "touch set1 bitmask error");
184     ESP_RETURN_ON_FALSE((set2_mask <= TOUCH_PAD_BIT_MASK_ALL), ESP_ERR_INVALID_ARG, TOUCH_TAG,  "touch set2 bitmask error");
185     ESP_RETURN_ON_FALSE((en_mask <= TOUCH_PAD_BIT_MASK_ALL), ESP_ERR_INVALID_ARG, TOUCH_TAG,  "touch work_en bitmask error");
186 
187     TOUCH_ENTER_CRITICAL();
188     touch_hal_set_group_mask(set1_mask, set2_mask);
189     touch_hal_set_channel_mask(en_mask);
190     TOUCH_EXIT_CRITICAL();
191 
192     return ESP_OK;
193 }
194 
touch_pad_get_group_mask(uint16_t * set1_mask,uint16_t * set2_mask,uint16_t * en_mask)195 esp_err_t touch_pad_get_group_mask(uint16_t *set1_mask, uint16_t *set2_mask, uint16_t *en_mask)
196 {
197     TOUCH_NULL_POINTER_CHECK(set1_mask, "set1_mask");
198     TOUCH_NULL_POINTER_CHECK(set2_mask, "set2_mask");
199     TOUCH_NULL_POINTER_CHECK(en_mask, "en_mask");
200     TOUCH_ENTER_CRITICAL();
201     touch_hal_get_channel_mask(en_mask);
202     touch_hal_get_group_mask(set1_mask, set2_mask);
203     TOUCH_EXIT_CRITICAL();
204 
205     return ESP_OK;
206 }
207 
touch_pad_clear_group_mask(uint16_t set1_mask,uint16_t set2_mask,uint16_t en_mask)208 esp_err_t touch_pad_clear_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask)
209 {
210     ESP_RETURN_ON_FALSE((set1_mask <= TOUCH_PAD_BIT_MASK_ALL), ESP_ERR_INVALID_ARG, TOUCH_TAG,  "touch set1 bitmask error");
211     ESP_RETURN_ON_FALSE((set2_mask <= TOUCH_PAD_BIT_MASK_ALL), ESP_ERR_INVALID_ARG, TOUCH_TAG,  "touch set2 bitmask error");
212     ESP_RETURN_ON_FALSE((en_mask <= TOUCH_PAD_BIT_MASK_ALL), ESP_ERR_INVALID_ARG, TOUCH_TAG,  "touch work_en bitmask error");
213 
214     TOUCH_ENTER_CRITICAL();
215     touch_hal_clear_channel_mask(en_mask);
216     touch_hal_clear_group_mask(set1_mask, set2_mask);
217     TOUCH_EXIT_CRITICAL();
218     return ESP_OK;
219 }
220 
touch_pad_intr_enable(void)221 esp_err_t touch_pad_intr_enable(void)
222 {
223     TOUCH_ENTER_CRITICAL();
224     touch_hal_intr_enable();
225     TOUCH_EXIT_CRITICAL();
226     return ESP_OK;
227 }
228 
touch_pad_intr_disable(void)229 esp_err_t touch_pad_intr_disable(void)
230 {
231     TOUCH_ENTER_CRITICAL();
232     touch_hal_intr_disable();
233     TOUCH_EXIT_CRITICAL();
234     return ESP_OK;
235 }
236 
touch_pad_intr_clear(void)237 esp_err_t touch_pad_intr_clear(void)
238 {
239     TOUCH_ENTER_CRITICAL();
240     touch_hal_intr_clear();
241     TOUCH_EXIT_CRITICAL();
242     return ESP_OK;
243 }
244 
touch_pad_meas_is_done(void)245 bool touch_pad_meas_is_done(void)
246 {
247     return touch_hal_meas_is_done();
248 }
249 
touch_pad_config(touch_pad_t touch_num,uint16_t threshold)250 esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold)
251 {
252     ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_FAIL, TOUCH_TAG,  "Touch pad not initialized");
253     TOUCH_CHANNEL_CHECK(touch_num);
254     touch_fsm_mode_t mode;
255     touch_pad_io_init(touch_num);
256     TOUCH_ENTER_CRITICAL();
257     touch_hal_config(touch_num);
258     touch_hal_set_threshold(touch_num, threshold);
259     TOUCH_EXIT_CRITICAL();
260     touch_pad_get_fsm_mode(&mode);
261     if (TOUCH_FSM_MODE_SW == mode) {
262         touch_pad_clear_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num));
263         s_touch_pad_init_bit |= (1 << touch_num);
264     } else if (TOUCH_FSM_MODE_TIMER == mode) {
265         uint16_t sleep_time = 0;
266         uint16_t meas_cycle = 0;
267         uint32_t wait_time_ms = 0;
268         uint32_t wait_tick = 0;
269         uint32_t rtc_clk = rtc_clk_slow_freq_get_hz();
270         touch_pad_set_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num));
271         touch_pad_get_meas_time(&sleep_time, &meas_cycle);
272         //If the FSM mode is 'TOUCH_FSM_MODE_TIMER', The data will be ready after one measurement cycle
273         //after this function is executed, otherwise, the "touch_value" by "touch_pad_read" is 0.
274         wait_time_ms = sleep_time / (rtc_clk / 1000) + meas_cycle / (RTC_FAST_CLK_FREQ_APPROX / 1000);
275         wait_tick = wait_time_ms / portTICK_RATE_MS;
276         vTaskDelay(wait_tick ? wait_tick : 1);
277         s_touch_pad_init_bit |= (1 << touch_num);
278     } else {
279         return ESP_FAIL;
280     }
281     return ESP_OK;
282 }
283 
touch_pad_init(void)284 esp_err_t touch_pad_init(void)
285 {
286 #ifdef CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
287     ESP_LOGE(TOUCH_TAG, "Touch Pad can't work because it provides current to external XTAL");
288     return ESP_ERR_NOT_SUPPORTED;
289 #endif // CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT_V2
290     if (rtc_touch_mux == NULL) {
291         rtc_touch_mux = xSemaphoreCreateMutex();
292     }
293     if (rtc_touch_mux == NULL) {
294         return ESP_FAIL;
295     }
296     TOUCH_ENTER_CRITICAL();
297     touch_hal_init();
298     TOUCH_EXIT_CRITICAL();
299     return ESP_OK;
300 }
301 
touch_pad_deinit(void)302 esp_err_t touch_pad_deinit(void)
303 {
304     ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_FAIL, TOUCH_TAG,  "Touch pad not initialized");
305     if (s_touch_pad_filter) {
306         touch_pad_filter_stop();
307         touch_pad_filter_delete();
308     }
309     xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
310     s_touch_pad_init_bit = 0x0000;
311     TOUCH_ENTER_CRITICAL();
312     touch_hal_deinit();
313     TOUCH_EXIT_CRITICAL();
314     xSemaphoreGive(rtc_touch_mux);
315     vSemaphoreDelete(rtc_touch_mux);
316     rtc_touch_mux = NULL;
317     return ESP_OK;
318 }
319 
_touch_pad_read(touch_pad_t touch_num,uint16_t * touch_value,touch_fsm_mode_t mode)320 static esp_err_t _touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value, touch_fsm_mode_t mode)
321 {
322     esp_err_t res = ESP_OK;
323     if (TOUCH_FSM_MODE_SW == mode) {
324         touch_pad_set_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num));
325         touch_pad_sw_start();
326         while (!touch_hal_meas_is_done()) {};
327         *touch_value = touch_hal_read_raw_data(touch_num);
328         touch_pad_clear_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num));
329     } else if (TOUCH_FSM_MODE_TIMER == mode) {
330         while (!touch_hal_meas_is_done()) {};
331         *touch_value = touch_hal_read_raw_data(touch_num);
332     } else {
333         res = ESP_FAIL;
334     }
335     if (*touch_value == 0) {
336         res = ESP_ERR_INVALID_STATE;
337     }
338     return res;
339 }
340 
touch_pad_read(touch_pad_t touch_num,uint16_t * touch_value)341 esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value)
342 {
343     TOUCH_CHANNEL_CHECK(touch_num);
344     TOUCH_NULL_POINTER_CHECK(touch_value, "touch_value");
345     ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_FAIL, TOUCH_TAG,  "Touch pad not initialized");
346 
347     esp_err_t res = ESP_OK;
348     touch_fsm_mode_t mode;
349     touch_pad_get_fsm_mode(&mode);
350     xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
351     res = _touch_pad_read(touch_num, touch_value, mode);
352     xSemaphoreGive(rtc_touch_mux);
353     return res;
354 }
355 
touch_pad_read_raw_data(touch_pad_t touch_num,uint16_t * touch_value)356 IRAM_ATTR esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint16_t *touch_value)
357 {
358     ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_FAIL, TOUCH_TAG,  "Touch pad not initialized");
359     TOUCH_CHANNEL_CHECK(touch_num);
360     TOUCH_NULL_POINTER_CHECK(touch_value, "touch_value");
361     ESP_RETURN_ON_FALSE(s_touch_pad_filter, ESP_FAIL, TOUCH_TAG,  "Touch pad filter not initialized");
362     *touch_value = s_touch_pad_filter->raw_val[touch_num];
363     if (*touch_value == 0) {
364         return ESP_ERR_INVALID_STATE;
365     }
366     return ESP_OK;
367 }
368 
touch_pad_read_filtered(touch_pad_t touch_num,uint16_t * touch_value)369 IRAM_ATTR esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value)
370 {
371     ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_FAIL, TOUCH_TAG,  "Touch pad not initialized");
372     TOUCH_CHANNEL_CHECK(touch_num);
373     TOUCH_NULL_POINTER_CHECK(touch_value, "touch_value");
374     ESP_RETURN_ON_FALSE(s_touch_pad_filter, ESP_FAIL, TOUCH_TAG,  "Touch pad filter not initialized");
375     *touch_value = (s_touch_pad_filter->filtered_val[touch_num]);
376     if (*touch_value == 0) {
377         return ESP_ERR_INVALID_STATE;
378     }
379     return ESP_OK;
380 }
381 
touch_pad_set_filter_period(uint32_t new_period_ms)382 esp_err_t touch_pad_set_filter_period(uint32_t new_period_ms)
383 {
384     ESP_RETURN_ON_FALSE(s_touch_pad_filter, ESP_ERR_INVALID_STATE, TOUCH_TAG,  "Touch pad filter not initialized");
385     ESP_RETURN_ON_FALSE(new_period_ms > 0, ESP_ERR_INVALID_ARG, TOUCH_TAG,  "Touch pad filter period error");
386     ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_ERR_INVALID_STATE, TOUCH_TAG,  "Touch pad not initialized");
387 
388     esp_err_t ret = ESP_OK;
389     xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
390     if (s_touch_pad_filter) {
391         xTimerChangePeriod(s_touch_pad_filter->timer, new_period_ms / portTICK_PERIOD_MS, portMAX_DELAY);
392         s_touch_pad_filter->period = new_period_ms;
393     } else {
394         ESP_LOGE(TOUCH_TAG, "Touch pad filter deleted");
395         ret = ESP_ERR_INVALID_STATE;
396     }
397     xSemaphoreGive(rtc_touch_mux);
398     return ret;
399 }
400 
touch_pad_get_filter_period(uint32_t * p_period_ms)401 esp_err_t touch_pad_get_filter_period(uint32_t *p_period_ms)
402 {
403     ESP_RETURN_ON_FALSE(s_touch_pad_filter, ESP_ERR_INVALID_STATE, TOUCH_TAG,  "Touch pad filter not initialized");
404     TOUCH_NULL_POINTER_CHECK(p_period_ms, "p_period_ms");
405     ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_ERR_INVALID_STATE, TOUCH_TAG,  "Touch pad not initialized");
406 
407     esp_err_t ret = ESP_OK;
408     xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
409     if (s_touch_pad_filter) {
410         *p_period_ms = s_touch_pad_filter->period;
411     } else {
412         ESP_LOGE(TOUCH_TAG, "Touch pad filter deleted");
413         ret = ESP_ERR_INVALID_STATE;
414     }
415     xSemaphoreGive(rtc_touch_mux);
416     return ret;
417 }
418 
touch_pad_filter_start(uint32_t filter_period_ms)419 esp_err_t touch_pad_filter_start(uint32_t filter_period_ms)
420 {
421     ESP_RETURN_ON_FALSE(filter_period_ms >= portTICK_PERIOD_MS, ESP_ERR_INVALID_ARG, TOUCH_TAG,  "Touch pad filter period error");
422     ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_ERR_INVALID_STATE, TOUCH_TAG,  "Touch pad not initialized");
423 
424     xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
425     if (s_touch_pad_filter == NULL) {
426         s_touch_pad_filter = (touch_pad_filter_t *) calloc(1, sizeof(touch_pad_filter_t));
427         if (s_touch_pad_filter == NULL) {
428             goto err_no_mem;
429         }
430     }
431     if (s_touch_pad_filter->timer == NULL) {
432         s_touch_pad_filter->timer = xTimerCreate("filter_tmr", filter_period_ms / portTICK_PERIOD_MS, pdFALSE,
433                                     NULL, (TimerCallbackFunction_t) touch_pad_filter_cb);
434         if (s_touch_pad_filter->timer == NULL) {
435             free(s_touch_pad_filter);
436             s_touch_pad_filter = NULL;
437             goto err_no_mem;
438         }
439         s_touch_pad_filter->period = filter_period_ms;
440     }
441     xSemaphoreGive(rtc_touch_mux);
442     touch_pad_filter_cb(NULL);
443     return ESP_OK;
444 
445 err_no_mem:
446     xSemaphoreGive(rtc_touch_mux);
447     return ESP_ERR_NO_MEM;
448 }
449 
touch_pad_filter_stop(void)450 esp_err_t touch_pad_filter_stop(void)
451 {
452     ESP_RETURN_ON_FALSE(s_touch_pad_filter, ESP_ERR_INVALID_STATE, TOUCH_TAG,  "Touch pad filter not initialized");
453     ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_ERR_INVALID_STATE, TOUCH_TAG,  "Touch pad not initialized");
454     esp_err_t ret = ESP_OK;
455     xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
456     if (s_touch_pad_filter) {
457         xTimerStop(s_touch_pad_filter->timer, portMAX_DELAY);
458     } else {
459         ESP_LOGE(TOUCH_TAG, "Touch pad filter deleted");
460         ret = ESP_ERR_INVALID_STATE;
461     }
462     xSemaphoreGive(rtc_touch_mux);
463     return ret;
464 }
465 
touch_pad_filter_delete(void)466 esp_err_t touch_pad_filter_delete(void)
467 {
468     ESP_RETURN_ON_FALSE(s_touch_pad_filter, ESP_ERR_INVALID_STATE, TOUCH_TAG,  "Touch pad filter not initialized");
469     ESP_RETURN_ON_FALSE(rtc_touch_mux, ESP_ERR_INVALID_STATE, TOUCH_TAG,  "Touch pad not initialized");
470     xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
471     if (s_touch_pad_filter) {
472         if (s_touch_pad_filter->timer) {
473             xTimerStop(s_touch_pad_filter->timer, portMAX_DELAY);
474             xTimerDelete(s_touch_pad_filter->timer, portMAX_DELAY);
475             s_touch_pad_filter->timer = NULL;
476         }
477         free(s_touch_pad_filter);
478         s_touch_pad_filter = NULL;
479     }
480     xSemaphoreGive(rtc_touch_mux);
481     return ESP_OK;
482 }
483