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