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