1 /*
2 * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*******************************************************************************
8 * NOTICE
9 * The ll is not public api, don't use in application code.
10 * See readme.md in hal/include/hal/readme.md
11 ******************************************************************************/
12
13 // The Lowlevel layer for Touch Sensor
14
15 #pragma once
16
17 #include <stdlib.h>
18 #include <stdbool.h>
19 #include "hal/misc.h"
20 #include "soc/touch_sensor_periph.h"
21 #include "soc/sens_struct.h"
22 #include "soc/rtc_io_struct.h"
23 #include "soc/rtc_cntl_struct.h"
24 #include "hal/touch_sensor_types.h"
25
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30
31 //Some register bits of touch sensor 8 and 9 are mismatched, we need to swap the bits.
32 #define TOUCH_LL_BIT_SWAP(data, n, m) (((data >> n) & 0x1) == ((data >> m) & 0x1) ? (data) : ((data) ^ ((0x1 <<n) | (0x1 << m))))
33 #define TOUCH_LL_BITS_SWAP(v) TOUCH_LL_BIT_SWAP(v, TOUCH_PAD_NUM8, TOUCH_PAD_NUM9)
34
35 /**
36 * Swap the number of touch8 and touch9.
37 *
38 * @touch_num Touch channel num.
39 */
touch_ll_num_wrap(touch_pad_t touch_num)40 static inline touch_pad_t touch_ll_num_wrap(touch_pad_t touch_num)
41 {
42 if (touch_num == TOUCH_PAD_NUM8) {
43 return TOUCH_PAD_NUM9;
44 } else if (touch_num == TOUCH_PAD_NUM9) {
45 return TOUCH_PAD_NUM8;
46 }
47 return touch_num;
48 }
49
50 /**
51 * Set touch sensor measurement time.
52 *
53 * @param meas_time The duration of the touch sensor measurement.
54 * t_meas = meas_time / (8MHz), the maximum measure time is 0xffff / 8M = 8.19 ms.
55 */
touch_ll_set_meas_time(uint16_t meas_time)56 static inline void touch_ll_set_meas_time(uint16_t meas_time)
57 {
58 //touch sensor measure time= meas_cycle / 8Mhz
59 HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_meas_delay, meas_time);
60 //the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD
61 HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_xpd_wait, SOC_TOUCH_PAD_MEASURE_WAIT_MAX);
62 }
63
64 /**
65 * Get touch sensor measurement time.
66 *
67 * @param meas_time Pointer to accept measurement cycle count.
68 */
touch_ll_get_meas_time(uint16_t * meas_time)69 static inline void touch_ll_get_meas_time(uint16_t *meas_time)
70 {
71 *meas_time = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_meas_delay);
72 }
73
74 /**
75 * Set touch sensor sleep time (interval of measurement).
76 *
77 * @param sleep_time The touch sensor will sleep after each measurement.
78 * sleep_cycle decide the interval between each measurement.
79 * t_sleep = sleep_cycle / (RTC_SLOW_CLK frequency).
80 * The approximate frequency value of RTC_SLOW_CLK can be obtained using `rtc_clk_slow_freq_get_hz` function.
81 */
touch_ll_set_sleep_time(uint16_t sleep_time)82 static inline void touch_ll_set_sleep_time(uint16_t sleep_time)
83 {
84 //touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK( can be 150k or 32k depending on the options)
85 HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl2, touch_sleep_cycles, sleep_time);
86 }
87
88 /**
89 * Get touch sensor sleep time.
90 *
91 * @param sleep_time Pointer to accept sleep cycle count.
92 */
touch_ll_get_sleep_time(uint16_t * sleep_time)93 static inline void touch_ll_get_sleep_time(uint16_t *sleep_time)
94 {
95 *sleep_time = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_ctrl2, touch_sleep_cycles);
96 }
97
98 /**
99 * Set touch sensor high voltage threshold of chanrge.
100 * The touch sensor measures the channel capacitance value by charging and discharging the channel.
101 * So the high threshold should be less than the supply voltage.
102 *
103 * @param refh The high voltage threshold of chanrge.
104 */
touch_ll_set_voltage_high(touch_high_volt_t refh)105 static inline void touch_ll_set_voltage_high(touch_high_volt_t refh)
106 {
107 RTCIO.touch_cfg.drefh = refh;
108 }
109
110 /**
111 * Get touch sensor high voltage threshold of chanrge.
112 * The touch sensor measures the channel capacitance value by charging and discharging the channel.
113 * So the high threshold should be less than the supply voltage.
114 *
115 * @param refh The high voltage threshold of chanrge.
116 */
touch_ll_get_voltage_high(touch_high_volt_t * refh)117 static inline void touch_ll_get_voltage_high(touch_high_volt_t *refh)
118 {
119 *refh = (touch_high_volt_t)RTCIO.touch_cfg.drefh;
120 }
121
122 /**
123 * Set touch sensor low voltage threshold of discharge.
124 * The touch sensor measures the channel capacitance value by charging and discharging the channel.
125 *
126 * @param refl The low voltage threshold of discharge.
127 */
touch_ll_set_voltage_low(touch_low_volt_t refl)128 static inline void touch_ll_set_voltage_low(touch_low_volt_t refl)
129 {
130 RTCIO.touch_cfg.drefl = refl;
131 }
132
133 /**
134 * Get touch sensor low voltage threshold of discharge.
135 * The touch sensor measures the channel capacitance value by charging and discharging the channel.
136 *
137 * @param refl The low voltage threshold of discharge.
138 */
touch_ll_get_voltage_low(touch_low_volt_t * refl)139 static inline void touch_ll_get_voltage_low(touch_low_volt_t *refl)
140 {
141 *refl = (touch_low_volt_t)RTCIO.touch_cfg.drefl;
142 }
143
144 /**
145 * Set touch sensor high voltage attenuation of chanrge. The actual charge threshold is high voltage threshold minus attenuation value.
146 * The touch sensor measures the channel capacitance value by charging and discharging the channel.
147 * So the high threshold should be less than the supply voltage.
148 *
149 * @param refh The high voltage threshold of chanrge.
150 */
touch_ll_set_voltage_attenuation(touch_volt_atten_t atten)151 static inline void touch_ll_set_voltage_attenuation(touch_volt_atten_t atten)
152 {
153 RTCIO.touch_cfg.drange = atten;
154 }
155
156 /**
157 * Get touch sensor high voltage attenuation of chanrge. The actual charge threshold is high voltage threshold minus attenuation value.
158 * The touch sensor measures the channel capacitance value by charging and discharging the channel.
159 * So the high threshold should be less than the supply voltage.
160 *
161 * @param refh The high voltage threshold of chanrge.
162 */
touch_ll_get_voltage_attenuation(touch_volt_atten_t * atten)163 static inline void touch_ll_get_voltage_attenuation(touch_volt_atten_t *atten)
164 {
165 *atten = (touch_volt_atten_t)RTCIO.touch_cfg.drange;
166 }
167
168 /**
169 * Set touch sensor charge/discharge speed(currents) for each pad.
170 * If the slope is 0, the counter would always be zero.
171 * If the slope is 1, the charging and discharging would be slow. The measurement time becomes longer.
172 * If the slope is set 7, which is the maximum value, the charging and discharging would be fast.
173 * The measurement time becomes shorter.
174 *
175 * @note The higher the charge and discharge current, the greater the immunity of the touch channel,
176 * but it will increase the system power consumption.
177 * @param touch_num Touch pad index.
178 * @param slope touch pad charge/discharge speed(currents).
179 */
touch_ll_set_slope(touch_pad_t touch_num,touch_cnt_slope_t slope)180 static inline void touch_ll_set_slope(touch_pad_t touch_num, touch_cnt_slope_t slope)
181 {
182 RTCIO.touch_pad[touch_num].dac = slope;
183 }
184
185 /**
186 * Get touch sensor charge/discharge speed(currents) for each pad.
187 * If the slope is 0, the counter would always be zero.
188 * If the slope is 1, the charging and discharging would be slow. The measurement time becomes longer.
189 * If the slope is set 7, which is the maximum value, the charging and discharging would be fast.
190 * The measurement time becomes shorter.
191 *
192 * @param touch_num Touch pad index.
193 * @param slope touch pad charge/discharge speed(currents).
194 */
touch_ll_get_slope(touch_pad_t touch_num,touch_cnt_slope_t * slope)195 static inline void touch_ll_get_slope(touch_pad_t touch_num, touch_cnt_slope_t *slope)
196 {
197 *slope = (touch_cnt_slope_t)RTCIO.touch_pad[touch_num].dac;
198 }
199
200 /**
201 * Set initial voltage state of touch channel for each measurement.
202 *
203 * @param touch_num Touch pad index.
204 * @param opt Initial voltage state.
205 */
touch_ll_set_tie_option(touch_pad_t touch_num,touch_tie_opt_t opt)206 static inline void touch_ll_set_tie_option(touch_pad_t touch_num, touch_tie_opt_t opt)
207 {
208 touch_pad_t touch_pad_wrap = touch_ll_num_wrap(touch_num);
209 RTCIO.touch_pad[touch_pad_wrap].tie_opt = opt;
210 }
211
212 /**
213 * Get initial voltage state of touch channel for each measurement.
214 *
215 * @param touch_num Touch pad index.
216 * @param opt Initial voltage state.
217 */
touch_ll_get_tie_option(touch_pad_t touch_num,touch_tie_opt_t * opt)218 static inline void touch_ll_get_tie_option(touch_pad_t touch_num, touch_tie_opt_t *opt)
219 {
220 touch_pad_t touch_pad_wrap = touch_ll_num_wrap(touch_num);
221 *opt = (touch_tie_opt_t)RTCIO.touch_pad[touch_pad_wrap].tie_opt;
222 }
223
224 /**
225 * Set touch sensor FSM mode.
226 * The measurement action can be triggered by the hardware timer, as well as by the software instruction.
227 *
228 * @param mode FSM mode.
229 */
touch_ll_set_fsm_mode(touch_fsm_mode_t mode)230 static inline void touch_ll_set_fsm_mode(touch_fsm_mode_t mode)
231 {
232 SENS.sar_touch_ctrl2.touch_start_fsm_en = 1;
233 SENS.sar_touch_ctrl2.touch_start_en = 0;
234 SENS.sar_touch_ctrl2.touch_start_force = mode;
235 }
236
237 /**
238 * Get touch sensor FSM mode.
239 * The measurement action can be triggered by the hardware timer, as well as by the software instruction.
240 *
241 * @param mode FSM mode.
242 */
touch_ll_get_fsm_mode(touch_fsm_mode_t * mode)243 static inline void touch_ll_get_fsm_mode(touch_fsm_mode_t *mode)
244 {
245 *mode = (touch_fsm_mode_t)SENS.sar_touch_ctrl2.touch_start_force;
246 }
247
248 /**
249 * Start touch sensor FSM timer.
250 * The measurement action can be triggered by the hardware timer, as well as by the software instruction.
251 *
252 * @param mode FSM mode.
253 */
touch_ll_start_fsm(void)254 static inline void touch_ll_start_fsm(void)
255 {
256 RTCCNTL.state0.touch_slp_timer_en = 1;
257 }
258
259 /**
260 * Stop touch sensor FSM timer.
261 * The measurement action can be triggered by the hardware timer, as well as by the software instruction.
262 *
263 * @param mode FSM mode.
264 */
touch_ll_stop_fsm(void)265 static inline void touch_ll_stop_fsm(void)
266 {
267 RTCCNTL.state0.touch_slp_timer_en = 0;
268 }
269
270 /**
271 * Trigger a touch sensor measurement, only support in SW mode of FSM.
272 */
touch_ll_start_sw_meas(void)273 static inline void touch_ll_start_sw_meas(void)
274 {
275 SENS.sar_touch_ctrl2.touch_start_en = 0;
276 SENS.sar_touch_ctrl2.touch_start_en = 1;
277 }
278
279 /**
280 * Set touch sensor interrupt threshold.
281 *
282 * @note Refer to `touch_pad_set_trigger_mode` to see how to set trigger mode.
283 * @param touch_num touch pad index.
284 * @param threshold threshold of touchpad count.
285 */
touch_ll_set_threshold(touch_pad_t touch_num,uint16_t threshold)286 static inline void touch_ll_set_threshold(touch_pad_t touch_num, uint16_t threshold)
287 {
288 touch_pad_t tp_wrap = touch_ll_num_wrap(touch_num);
289 if (tp_wrap & 0x1) {
290 HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], l_thresh, threshold);
291 } else {
292 HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], h_thresh, threshold);
293 }
294 }
295
296 /**
297 * Get touch sensor interrupt threshold.
298 *
299 * @param touch_num touch pad index.
300 * @param threshold pointer to accept threshold.
301 */
touch_ll_get_threshold(touch_pad_t touch_num,uint16_t * threshold)302 static inline void touch_ll_get_threshold(touch_pad_t touch_num, uint16_t *threshold)
303 {
304 touch_pad_t tp_wrap = touch_ll_num_wrap(touch_num);
305 if (threshold) {
306 *threshold = (tp_wrap & 0x1 ) ?
307 HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], l_thresh) :
308 HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], h_thresh);
309 }
310 }
311
312 /**
313 * Set touch sensor interrupt trigger mode.
314 * Interrupt can be triggered either when touch value is less than
315 * threshold or when touch value is more than threshold.
316 *
317 * @param mode Touch sensor interrupt trigger mode.
318 */
touch_ll_set_trigger_mode(touch_trigger_mode_t mode)319 static inline void touch_ll_set_trigger_mode(touch_trigger_mode_t mode)
320 {
321 SENS.sar_touch_ctrl1.touch_out_sel = mode;
322 }
323
324 /**
325 * Get touch sensor interrupt trigger mode.
326 * Interrupt can be triggered either when touch value is less than
327 * threshold or when touch value is more than threshold.
328 *
329 * @param mode Touch sensor interrupt trigger mode.
330 */
touch_ll_get_trigger_mode(touch_trigger_mode_t * mode)331 static inline void touch_ll_get_trigger_mode(touch_trigger_mode_t *mode)
332 {
333 *mode = (touch_trigger_mode_t)SENS.sar_touch_ctrl1.touch_out_sel;
334 }
335
336 /**
337 * Set touch sensor interrupt trigger source. There are two sets of touch signals.
338 * Set1 and set2 can be mapped to several touch signals. Either set will be triggered
339 * if at least one of its touch signal is 'touched'. The interrupt can be configured to be generated
340 * if set1 is triggered, or only if both sets are triggered.
341 *
342 * @param src Touch sensor interrupt trigger source.
343 */
touch_ll_set_trigger_source(touch_trigger_src_t src)344 static inline void touch_ll_set_trigger_source(touch_trigger_src_t src)
345 {
346 SENS.sar_touch_ctrl1.touch_out_1en = src;
347 }
348
349 /**
350 * Get touch sensor interrupt trigger source.
351 *
352 * @param src Pointer to accept touch sensor interrupt trigger source.
353 */
touch_ll_get_trigger_source(touch_trigger_src_t * src)354 static inline void touch_ll_get_trigger_source(touch_trigger_src_t *src)
355 {
356 *src = (touch_trigger_src_t)SENS.sar_touch_ctrl1.touch_out_1en;
357 }
358
359 /**
360 * Enable touch sensor channel. Register touch channel into touch sensor measurement group.
361 * The working mode of the touch sensor is simultaneous measurement.
362 * This function will set the measure bits according to the given bitmask.
363 *
364 * @note If set this mask, the FSM timer should be stop firsty.
365 * @note The touch sensor that in scan map, should be deinit GPIO function firstly.
366 * @param enable_mask bitmask of touch sensor scan group.
367 * e.g. TOUCH_PAD_NUM1 -> BIT(1)
368 * @return
369 * - ESP_OK on success
370 */
touch_ll_set_channel_mask(uint16_t enable_mask)371 static inline void touch_ll_set_channel_mask(uint16_t enable_mask)
372 {
373 SENS.sar_touch_enable.touch_pad_worken |= TOUCH_LL_BITS_SWAP(enable_mask);
374 }
375
376 /**
377 * Get touch sensor channel mask.
378 *
379 * @param enable_mask bitmask of touch sensor scan group.
380 * e.g. TOUCH_PAD_NUM1 -> BIT(1)
381 */
touch_ll_get_channel_mask(uint16_t * enable_mask)382 static inline void touch_ll_get_channel_mask(uint16_t *enable_mask)
383 {
384 *enable_mask = TOUCH_LL_BITS_SWAP(SENS.sar_touch_enable.touch_pad_worken);
385 }
386
387 /**
388 * Disable touch sensor channel by bitmask.
389 *
390 * @param enable_mask bitmask of touch sensor scan group.
391 * e.g. TOUCH_PAD_NUM1 -> BIT(1)
392 */
touch_ll_clear_channel_mask(uint16_t disable_mask)393 static inline void touch_ll_clear_channel_mask(uint16_t disable_mask)
394 {
395 SENS.sar_touch_enable.touch_pad_worken &= TOUCH_LL_BITS_SWAP(~disable_mask);
396 }
397
398 /**
399 * Set touch sensor group mask.
400 * Touch pad module has two sets of signals, 'Touched' signal is triggered only if
401 * at least one of touch pad in this group is "touched".
402 * This function will set the register bits according to the given bitmask.
403 *
404 * @param set1_mask bitmask of touch sensor signal group1, it's a 10-bit value
405 * @param set2_mask bitmask of touch sensor signal group2, it's a 10-bit value
406 */
touch_ll_set_group_mask(uint16_t group1_mask,uint16_t group2_mask)407 static inline void touch_ll_set_group_mask(uint16_t group1_mask, uint16_t group2_mask)
408 {
409 SENS.sar_touch_enable.touch_pad_outen1 |= TOUCH_LL_BITS_SWAP(group1_mask);
410 SENS.sar_touch_enable.touch_pad_outen2 |= TOUCH_LL_BITS_SWAP(group2_mask);
411 }
412
413 /**
414 * Get touch sensor group mask.
415 *
416 * @param set1_mask pointer to accept bitmask of touch sensor signal group1, it's a 10-bit value
417 * @param set2_mask pointer to accept bitmask of touch sensor signal group2, it's a 10-bit value
418 */
touch_ll_get_group_mask(uint16_t * group1_mask,uint16_t * group2_mask)419 static inline void touch_ll_get_group_mask(uint16_t *group1_mask, uint16_t *group2_mask)
420 {
421 *group1_mask = TOUCH_LL_BITS_SWAP(SENS.sar_touch_enable.touch_pad_outen1);
422 *group2_mask = TOUCH_LL_BITS_SWAP(SENS.sar_touch_enable.touch_pad_outen2);
423 }
424
425 /**
426 * Clear touch sensor group mask.
427 *
428 * @param set1_mask pointer to accept bitmask of touch sensor signal group1, it's a 10-bit value
429 * @param set2_mask pointer to accept bitmask of touch sensor signal group2, it's a 10-bit value
430 */
touch_ll_clear_group_mask(uint16_t group1_mask,uint16_t group2_mask)431 static inline void touch_ll_clear_group_mask(uint16_t group1_mask, uint16_t group2_mask)
432 {
433 SENS.sar_touch_enable.touch_pad_outen1 &= TOUCH_LL_BITS_SWAP(~group1_mask);
434 SENS.sar_touch_enable.touch_pad_outen2 &= TOUCH_LL_BITS_SWAP(~group2_mask);
435 }
436
437 /**
438 * Get the touch sensor status, usually used in ISR to decide which pads are 'touched'.
439 *
440 * @param status_mask The touch sensor status. e.g. Touch1 trigger status is `status_mask & (BIT1)`.
441 */
touch_ll_read_trigger_status_mask(uint32_t * status_mask)442 static inline void touch_ll_read_trigger_status_mask(uint32_t *status_mask)
443 {
444 *status_mask = TOUCH_LL_BITS_SWAP(SENS.sar_touch_ctrl2.touch_meas_en);
445 }
446
447 /**
448 * Clear all touch sensor status.
449 */
touch_ll_clear_trigger_status_mask(void)450 static inline void touch_ll_clear_trigger_status_mask(void)
451 {
452 SENS.sar_touch_ctrl2.touch_meas_en_clr = 1;
453 }
454
455 /**
456 * To enable touch pad interrupt.
457 */
touch_ll_intr_enable(void)458 static inline void touch_ll_intr_enable(void)
459 {
460 RTCCNTL.int_ena.rtc_touch = 1;
461 }
462
463 /**
464 * To disable touch pad interrupt.
465 */
touch_ll_intr_disable(void)466 static inline void touch_ll_intr_disable(void)
467 {
468 RTCCNTL.int_ena.rtc_touch = 0;
469 }
470
471 /**
472 * To clear touch pad interrupt.
473 */
touch_ll_intr_clear(void)474 static inline void touch_ll_intr_clear(void)
475 {
476 RTCCNTL.int_clr.rtc_touch = 1;
477 }
478
479 /**
480 * Get touch sensor raw data (touch sensor counter value) from register. No block.
481 *
482 * @param touch_num touch pad index.
483 * @return touch_value pointer to accept touch sensor value.
484 */
touch_ll_read_raw_data(touch_pad_t touch_num)485 static inline uint32_t touch_ll_read_raw_data(touch_pad_t touch_num)
486 {
487 touch_pad_t tp_wrap = touch_ll_num_wrap(touch_num);
488 return ((tp_wrap & 0x1) ? HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[tp_wrap / 2], l_val) :
489 HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[tp_wrap / 2], h_val));
490 }
491
492 /**
493 * Get touch sensor measure status. No block.
494 *
495 * @return
496 * - If touch sensors measure done.
497 */
touch_ll_meas_is_done(void)498 static inline bool touch_ll_meas_is_done(void)
499 {
500 return (bool)SENS.sar_touch_ctrl2.touch_meas_done;
501 }
502
503 #ifdef __cplusplus
504 }
505 #endif
506