1 // Copyright 2016-2018 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
15 #include <stdlib.h>
16 #include <ctype.h>
17 #include "sdkconfig.h"
18 #include "esp_types.h"
19 #include "esp_log.h"
20 #include "sys/lock.h"
21 #include "soc/soc_pins.h"
22 #include "esp_osal/esp_osal.h"
23 #include "esp_osal/semphr.h"
24 #include "esp_osal/timers.h"
25 #include "esp_intr_alloc.h"
26 #include "driver/rtc_io.h"
27 #include "driver/touch_pad.h"
28 #include "driver/rtc_cntl.h"
29 #include "driver/gpio.h"
30 #include "hal/touch_sensor_types.h"
31 #include "hal/touch_sensor_hal.h"
32
33 static const char *TOUCH_TAG = "TOUCH_SENSOR";
34 #define TOUCH_CHECK(a, str, ret_val) ({ \
35 if (!(a)) { \
36 ESP_LOGE(TOUCH_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
37 return (ret_val); \
38 } \
39 })
40 #ifdef CONFIG_IDF_TARGET_ESP32
41 #define TOUCH_CHANNEL_CHECK(channel) do { \
42 TOUCH_CHECK(channel < SOC_TOUCH_SENSOR_NUM && channel >= 0, "Touch channel error", ESP_ERR_INVALID_ARG); \
43 } while (0);
44 #else // !CONFIG_IDF_TARGET_ESP32
45 #define TOUCH_CHANNEL_CHECK(channel) do { \
46 TOUCH_CHECK(channel < SOC_TOUCH_SENSOR_NUM && channel >= 0, "Touch channel error", ESP_ERR_INVALID_ARG); \
47 TOUCH_CHECK(channel != SOC_TOUCH_DENOISE_CHANNEL, "TOUCH0 is internal denoise channel", ESP_ERR_INVALID_ARG); \
48 } while (0);
49 #endif // CONFIG_IDF_TARGET_ESP32
50
51 #define TOUCH_GET_IO_NUM(channel) (touch_sensor_channel_io_map[channel])
52
53 _Static_assert(TOUCH_PAD_MAX == SOC_TOUCH_SENSOR_NUM, "Touch sensor channel number not equal to chip capabilities");
54
55 extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
56 #define TOUCH_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
57 #define TOUCH_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
58
touch_pad_isr_deregister(intr_handler_t fn,void * arg)59 esp_err_t touch_pad_isr_deregister(intr_handler_t fn, void *arg)
60 {
61 return rtc_isr_deregister(fn, arg);
62 }
63
touch_pad_set_voltage(touch_high_volt_t refh,touch_low_volt_t refl,touch_volt_atten_t atten)64 esp_err_t touch_pad_set_voltage(touch_high_volt_t refh, touch_low_volt_t refl, touch_volt_atten_t atten)
65 {
66 TOUCH_CHECK(((refh < TOUCH_HVOLT_MAX) && (refh >= (int )TOUCH_HVOLT_KEEP)), "touch refh error",
67 ESP_ERR_INVALID_ARG);
68 TOUCH_CHECK(((refl < TOUCH_LVOLT_MAX) && (refh >= (int )TOUCH_LVOLT_KEEP)), "touch refl error",
69 ESP_ERR_INVALID_ARG);
70 TOUCH_CHECK(((atten < TOUCH_HVOLT_ATTEN_MAX) && (refh >= (int )TOUCH_HVOLT_ATTEN_KEEP)), "touch atten error",
71 ESP_ERR_INVALID_ARG);
72
73 const touch_hal_volt_t volt = {
74 .refh = refh,
75 .refl = refl,
76 .atten = atten,
77 };
78 TOUCH_ENTER_CRITICAL();
79 touch_hal_set_voltage(&volt);
80 TOUCH_EXIT_CRITICAL();
81
82 return ESP_OK;
83 }
84
touch_pad_get_voltage(touch_high_volt_t * refh,touch_low_volt_t * refl,touch_volt_atten_t * atten)85 esp_err_t touch_pad_get_voltage(touch_high_volt_t *refh, touch_low_volt_t *refl, touch_volt_atten_t *atten)
86 {
87 touch_hal_volt_t volt = {0};
88 TOUCH_ENTER_CRITICAL();
89 touch_hal_get_voltage(&volt);
90 TOUCH_EXIT_CRITICAL();
91 *refh = volt.refh;
92 *refl = volt.refl;
93 *atten = volt.atten;
94
95 return ESP_OK;
96 }
97
touch_pad_set_cnt_mode(touch_pad_t touch_num,touch_cnt_slope_t slope,touch_tie_opt_t opt)98 esp_err_t touch_pad_set_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t slope, touch_tie_opt_t opt)
99 {
100 TOUCH_CHECK(touch_num < SOC_TOUCH_SENSOR_NUM, "Touch channel error", ESP_ERR_INVALID_ARG);
101 TOUCH_CHECK(slope < TOUCH_PAD_SLOPE_MAX, "touch slope error", ESP_ERR_INVALID_ARG);
102 TOUCH_CHECK(opt < TOUCH_PAD_TIE_OPT_MAX, "touch opt error", ESP_ERR_INVALID_ARG);
103
104 const touch_hal_meas_mode_t meas = {
105 .slope = slope,
106 .tie_opt = opt,
107 };
108 TOUCH_ENTER_CRITICAL();
109 touch_hal_set_meas_mode(touch_num, &meas);
110 TOUCH_EXIT_CRITICAL();
111
112 return ESP_OK;
113 }
114
touch_pad_get_cnt_mode(touch_pad_t touch_num,touch_cnt_slope_t * slope,touch_tie_opt_t * opt)115 esp_err_t touch_pad_get_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t *slope, touch_tie_opt_t *opt)
116 {
117 TOUCH_CHECK(touch_num < SOC_TOUCH_SENSOR_NUM, "Touch channel error", ESP_ERR_INVALID_ARG);
118
119 touch_hal_meas_mode_t meas = {0};
120 TOUCH_ENTER_CRITICAL();
121 touch_hal_get_meas_mode(touch_num, &meas);
122 TOUCH_EXIT_CRITICAL();
123 *slope = meas.slope;
124 *opt = meas.tie_opt;
125
126 return ESP_OK;
127 }
128
touch_pad_io_init(touch_pad_t touch_num)129 esp_err_t touch_pad_io_init(touch_pad_t touch_num)
130 {
131 TOUCH_CHANNEL_CHECK(touch_num);
132 gpio_num_t gpio_num = TOUCH_GET_IO_NUM(touch_num);
133 rtc_gpio_init(gpio_num);
134 rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED);
135 rtc_gpio_pulldown_dis(gpio_num);
136 rtc_gpio_pullup_dis(gpio_num);
137 return ESP_OK;
138 }
139
touch_pad_fsm_start(void)140 esp_err_t touch_pad_fsm_start(void)
141 {
142 TOUCH_ENTER_CRITICAL();
143 touch_hal_start_fsm();
144 TOUCH_EXIT_CRITICAL();
145 return ESP_OK;
146 }
147
touch_pad_fsm_stop(void)148 esp_err_t touch_pad_fsm_stop(void)
149 {
150 TOUCH_ENTER_CRITICAL();
151 touch_hal_stop_fsm();
152 TOUCH_EXIT_CRITICAL();
153 return ESP_OK;
154 }
155
touch_pad_set_fsm_mode(touch_fsm_mode_t mode)156 esp_err_t touch_pad_set_fsm_mode(touch_fsm_mode_t mode)
157 {
158 TOUCH_CHECK((mode < TOUCH_FSM_MODE_MAX), "touch fsm mode error", ESP_ERR_INVALID_ARG);
159
160 TOUCH_ENTER_CRITICAL();
161 touch_hal_set_fsm_mode(mode);
162 TOUCH_EXIT_CRITICAL();
163 #ifdef CONFIG_IDF_TARGET_ESP32
164 if (mode == TOUCH_FSM_MODE_TIMER) {
165 touch_pad_fsm_start();
166 } else {
167 touch_pad_fsm_stop();
168 }
169 #endif
170 return ESP_OK;
171 }
172
touch_pad_get_fsm_mode(touch_fsm_mode_t * mode)173 esp_err_t touch_pad_get_fsm_mode(touch_fsm_mode_t *mode)
174 {
175 touch_hal_get_fsm_mode(mode);
176 return ESP_OK;
177 }
178
touch_pad_sw_start(void)179 esp_err_t touch_pad_sw_start(void)
180 {
181 TOUCH_ENTER_CRITICAL();
182 touch_hal_start_sw_meas();
183 TOUCH_EXIT_CRITICAL();
184 return ESP_OK;
185 }
186
187 #ifdef CONFIG_IDF_TARGET_ESP32
touch_pad_set_thresh(touch_pad_t touch_num,uint16_t threshold)188 esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint16_t threshold)
189 {
190 TOUCH_CHANNEL_CHECK(touch_num);
191 TOUCH_ENTER_CRITICAL();
192 touch_hal_set_threshold(touch_num, threshold);
193 TOUCH_EXIT_CRITICAL();
194 return ESP_OK;
195 }
196 #else // !CONFIG_IDF_TARGET_ESP32
touch_pad_set_thresh(touch_pad_t touch_num,uint32_t threshold)197 esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint32_t threshold)
198 {
199 TOUCH_CHANNEL_CHECK(touch_num);
200 TOUCH_CHECK(touch_num != SOC_TOUCH_DENOISE_CHANNEL,
201 "TOUCH0 is internal denoise channel", ESP_ERR_INVALID_ARG);
202 TOUCH_ENTER_CRITICAL();
203 touch_hal_set_threshold(touch_num, threshold);
204 TOUCH_EXIT_CRITICAL();
205 return ESP_OK;
206 }
207 #endif // CONFIG_IDF_TARGET_ESP32
208
209 #ifdef CONFIG_IDF_TARGET_ESP32
touch_pad_get_thresh(touch_pad_t touch_num,uint16_t * threshold)210 esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint16_t *threshold)
211 {
212 TOUCH_CHANNEL_CHECK(touch_num);
213 touch_hal_get_threshold(touch_num, threshold);
214 return ESP_OK;
215 }
216 #else // !CONFIG_IDF_TARGET_ESP32
touch_pad_get_thresh(touch_pad_t touch_num,uint32_t * threshold)217 esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint32_t *threshold)
218 {
219 TOUCH_CHANNEL_CHECK(touch_num);
220 TOUCH_CHECK(touch_num != SOC_TOUCH_DENOISE_CHANNEL,
221 "TOUCH0 is internal denoise channel", ESP_ERR_INVALID_ARG);
222 touch_hal_get_threshold(touch_num, threshold);
223 return ESP_OK;
224 }
225 #endif // CONFIG_IDF_TARGET_ESP32
226
touch_pad_get_wakeup_status(touch_pad_t * pad_num)227 esp_err_t touch_pad_get_wakeup_status(touch_pad_t *pad_num)
228 {
229 touch_hal_get_wakeup_status(pad_num);
230 TOUCH_CHANNEL_CHECK(*pad_num);
231 return ESP_OK;
232 }
233
touch_pad_get_status(void)234 uint32_t IRAM_ATTR touch_pad_get_status(void)
235 {
236 uint32_t status = 0;
237 touch_hal_read_trigger_status_mask(&status);
238 return status;
239 }
240
touch_pad_clear_status(void)241 esp_err_t IRAM_ATTR touch_pad_clear_status(void)
242 {
243 touch_hal_clear_trigger_status_mask();
244 return ESP_OK;
245 }
246