1 /**************************************************************************//**
2 * @file tk.c
3 * @version V3.00
4 * @brief Touch key driver source file
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10
11 /** @addtogroup Standard_Driver Standard Driver
12 @{
13 */
14
15 /** @addtogroup TK_Driver TK Driver
16 @{
17 */
18
19
20 /** @addtogroup TK_EXPORTED_FUNCTIONS TK Exported Functions
21 @{
22 */
23
24
25 /**
26 * @brief Enable touch key function
27 * @param None
28 * @return None
29 * @note This function will enable touch key function and initial idle and polarity state as GND first for all scan keys
30 * \hideinitializer
31 */
32
TK_Open(void)33 void TK_Open(void)
34 {
35 TK->SCANC |= TK_SCANC_TK_EN_Msk;
36
37 /* Set idle and polarity state as GND */
38 TK->IDLSC = 0;
39 TK->IDLSC1 = 0;
40 TK->POLSEL = 0;
41 if( ((SYS->PDID&0x01925000) == 0x01925000) || ((SYS->PDID&0x01D23140) == 0x01D23140) || ((SYS->PDID&0x01F31000) == 0x01F31000) )
42 {
43 //for M258G || TC8260 || M2L31
44 TK->IDLSC1 = 0;
45 TK->POLSEL1 = 0;
46 }
47 TK->POLC &= ~(TK_POLC_IDLS16_Msk | TK_POLC_POL16_Msk);
48 }
49
50 /**
51 * @brief Disable touch key function
52 * @param None
53 * @return None
54 * \hideinitializer
55 */
TK_Close(void)56 void TK_Close(void)
57 {
58 TK->SCANC &= ~TK_SCANC_TK_EN_Msk;
59 }
60
61 /**
62 * @brief Set touch key scan mode
63 * @param[in] u32Mode Single ,periodic or all key scan mode
64 * - \ref TK_SCAN_MODE_SINGLE
65 * - \ref TK_SCAN_MODE_PERIODIC
66 * - \ref TK_SCAN_MODE_ALL_KEY
67 * - \ref TK_SCAN_MODE_PERIODIC_ALL_KEY
68 * @return None
69 * @details This function is used to set touch key scan mode.
70 * @note If touch key controller sets as periodic mode, touch key will be trigger scan by Timer0. So Timer0 must be enabled and operated in periodic mode.
71 * If touch key controller sets as single scan mode, touch key can be trigger scan by calling TK_START_SCAN().
72 * \hideinitializer
73 */
TK_SetScanMode(uint32_t u32Mode)74 void TK_SetScanMode(uint32_t u32Mode)
75 {
76 TK->SCANC &= ~TK_SCANC_TRG_EN_Msk;
77 TK->REFC &= ~TK_REFC_SCAN_ALL_Msk;
78
79 if (u32Mode == TK_SCAN_MODE_PERIODIC)
80 {
81 //TK->SCANC |= u32Mode; /* Replace by TK_TriggerMode() */
82 }
83 else if (u32Mode == TK_SCAN_MODE_ALL_KEY)
84 {
85 TK->REFC |= u32Mode;
86 }
87 else if (u32Mode == TK_SCAN_MODE_PERIODIC_ALL_KEY)
88 {
89 //TK->SCANC |= TK_SCANC_TRG_EN_Msk;
90 TK->REFC |= TK_REFC_SCAN_ALL_Msk;
91 }
92 }
93
94 /**
95 * @brief Configure touch key trigger source
96 * @param[in] u32Src Trigger TK Source
97 * - \ref TK_SCAN_TRIGGER_SOURCE_TMR0
98 * - \ref TK_SCAN_TRIGGER_SOURCE_TMR1
99 * - \ref TK_SCAN_TRIGGER_SOURCE_TMR2
100 * - \ref TK_SCAN_TRIGGER_SOURCE_TMR3
101 * - \ref TK_SCAN_TRIGGER_SOURCE_LPTMR0
102 * - \ref TK_SCAN_TRIGGER_SOURCE_LPTMR1
103 * - \ref TK_SCAN_TRIGGER_SOURCE_TICKTMR0
104 * - \ref TK_SCAN_TRIGGER_SOURCE_TICKTMR2
105 * @return None
106 */
TK_TriggerMode(uint32_t u32Src)107 void TK_TriggerMode(uint32_t u32Src)
108 {
109 TK->SCANC = (TK->SCANC & ~TK_SCANC_TRG_EN_Msk) | u32Src;
110 }
111
112 /**
113 * @brief Configure touch key scan sensitivity
114 * @param[in] u32PulseWidth Sensing pulse width
115 * - \ref TK_SENSE_PULSE_1
116 * - \ref TK_SENSE_PULSE_2
117 * - \ref TK_SENSE_PULSE_4
118 * - \ref TK_SENSE_PULSE_8
119 * - \ref TK_SENSE_PULSE_250NS
120 * - \ref TK_SENSE_PULSE_500NS
121 * @param[in] u32SenseCnt Sensing count
122 * - \ref TK_SENSE_CNT_128
123 * - \ref TK_SENSE_CNT_255
124 * - \ref TK_SENSE_CNT_511
125 * - \ref TK_SENSE_CNT_1023
126 * - \ref TK_SENSE_CNT_8
127 * - \ref TK_SENSE_CNT_16
128 * - \ref TK_SENSE_CNT_32
129 * - \ref TK_SENSE_CNT_64
130 * @param[in] u32AVCCHSel voltage selection
131 * - \ref TK_AVCCH_1_DIV_16
132 * - \ref TK_AVCCH_1_DIV_8
133 * - \ref TK_AVCCH_3_DIV_16
134 * - \ref TK_AVCCH_1_DIV_4
135 * - \ref TK_AVCCH_5_DIV_16
136 * - \ref TK_AVCCH_3_DIV_8
137 * - \ref TK_AVCCH_7_DIV_16
138 * - \ref TK_AVCCH_1_DIV_2
139 * @return None
140 * @details This function is used to configure touch key scan sensitivity.
141 * \hideinitializer
142 */
TK_ConfigSensitivity(uint32_t u32PulseWidth,uint32_t u32SenseCnt,uint32_t u32AVCCHSel)143 void TK_ConfigSensitivity(uint32_t u32PulseWidth, uint32_t u32SenseCnt, uint32_t u32AVCCHSel)
144 {
145 TK->REFC = (TK->REFC & ~(TK_REFC_SENSET_Msk | TK_REFC_PULSET_Msk)) | (u32PulseWidth | u32SenseCnt);
146 TK_SET_AVCCH(u32AVCCHSel);
147 }
148
149 /**
150 * @brief Set touch key capacitor bank polarity
151 * @param[in] u32CapBankPolSel capacitor bank polarity selection
152 * - \ref TK_CAP_BANK_POL_SEL_GND
153 * - \ref TK_CAP_BANK_POL_SEL_AVCCH
154 * - \ref TK_CAP_BANK_POL_SEL_VDD
155 * @return None
156 * @details This function is used to set touch key capacitor bank polarity.
157 * \hideinitializer
158 */
TK_SetCapBankPol(uint32_t u32CapBankPolSel)159 void TK_SetCapBankPol(uint32_t u32CapBankPolSel)
160 {
161 TK->POLC = (TK->POLC & ~TK_POLC_POL_CAP_Msk) | (u32CapBankPolSel << TK_POLC_POL_CAP_Pos);
162 }
163
164 /**
165 * @brief Configure touch key polarity
166 * @param[in] u32Mask Combination of touch keys which need to be configured
167 * @param[in] u32PolSel touch key polarity selection
168 * - \ref TK_TKn_POL_SEL_GND
169 * - \ref TK_TKn_POL_SEL_AVCCH
170 * - \ref TK_TKn_POL_SEL_VDD
171 * @return None
172 * @details This function is used to configure touch key polarity.
173 * \hideinitializer
174 */
TK_SetTkPol(uint32_t u32Mask,uint32_t u32PolSel)175 void TK_SetTkPol(uint32_t u32Mask, uint32_t u32PolSel)
176 {
177 uint32_t i;
178
179 /* TK0 ~ TK15 Polarity Sel */
180 for (i = 0 ; i < 16 ; i++)
181 {
182 if ((1ul << i) & u32Mask)
183 {
184 TK->POLSEL = (TK->POLSEL & ~(TK_POLSEL_POL0_Msk << (i * 2))) | (u32PolSel << (i * 2));
185 }
186 }
187
188 /* TK16's Polarity Sel is special */
189 i = 16;
190 if ((1ul << i) & u32Mask)
191 {
192 TK->POLC = (TK->POLC & ~(TK_POLC_POL16_Msk << 2)) | (u32PolSel<<2);
193 }
194
195 /* TK17 ~ TK26 Polarity Sel */
196 for (i = 17 ; i < 26 ; i++)
197 {
198 if ((1ul << i) & u32Mask)
199 {
200 TK->POLSEL1 = (TK->POLSEL1 & ~(TK_POLSEL_POL0_Msk << ((i - 17) * 2))) | (u32PolSel << ((i - 17) * 2));
201 }
202 }
203 }
204
205 /**
206 * @brief Enable the polarity of specified touch key(s)
207 * @param[in] u32Mask Combination of enabled scan keys. Each bit corresponds to a touch key
208 * Bit 0 represents touch key 0, bit 1 represents touch key 1...
209 * @return None
210 * @details This function is used to enable the polarity of specified touch key(s).
211 * \hideinitializer
212 */
TK_EnableTkPolarity(uint32_t u32Mask)213 void TK_EnableTkPolarity(uint32_t u32Mask)
214 {
215 TK->POLC |= ((u32Mask & 0x1FFFF) << TK_POLC_POLEN0_Pos);
216 if( ((SYS->PDID&0x01925000) == 0x01925000) || ((SYS->PDID&0x01D23140) == 0x01D23140) || ((SYS->PDID&0x01F31000) == 0x01F31000) )
217 {
218 //for M258G || TC8260 || M2L31
219 TK->POLC1 |= (u32Mask >> 17);
220 }
221 }
222
223 /**
224 * @brief Disable the polarity of specified touch key(s)
225 * @param[in] u32Mask Combination of enabled scan keys. Each bit corresponds to a touch key
226 * Bit 0 represents touch key 0, bit 1 represents touch key 1...
227 * @return None
228 * @details This function is used to disable the polarity of specified touch key(s).
229 * \hideinitializer
230 */
TK_DisableTkPolarity(uint32_t u32Mask)231 void TK_DisableTkPolarity(uint32_t u32Mask)
232 {
233 TK->POLC &= ~((u32Mask & 0x1FFFF) << TK_POLC_POLEN0_Pos);
234 if( ((SYS->PDID&0x01925000) == 0x01925000) || ((SYS->PDID&0x01D23140) == 0x01D23140) || ((SYS->PDID&0x01F31000) == 0x01F31000) )
235 {
236 //for M258G || TC8260 || M2L31
237 TK->POLC1 &= ~(u32Mask >> 17);
238 }
239 }
240
241 /**
242 * @brief Set complement capacitor bank data of specified touch key
243 * @param[in] u32TKNum Touch key number. The valid value is 0~16.
244 * @param[in] u32CapData Complement capacitor bank data. The valid value is 0~0xFF.
245 * @return None
246 * @details This function is used to set complement capacitor bank data of specified touch key.
247 * \hideinitializer
248 */
TK_SetCompCapBankData(uint32_t u32TKNum,uint32_t u32CapData)249 void TK_SetCompCapBankData(uint32_t u32TKNum, uint32_t u32CapData)
250 {
251 if(u32TKNum <= 16)
252 {
253 *(__IO uint32_t *)(&(TK->CCBD0) + ((u32TKNum % 17) >> 2)) &= ~(TK_CCBD0_CCBD0_Msk << ((u32TKNum % 17) % 4 * 8));
254 *(__IO uint32_t *)(&(TK->CCBD0) + ((u32TKNum % 17) >> 2)) |= (u32CapData << ((u32TKNum % 17) % 4 * 8));
255 }
256 else
257 {
258 *(__IO uint32_t *)(&(TK->CCBD5) + ((u32TKNum % 17) >> 2)) &= ~(TK_CCBD0_CCBD0_Msk << ((u32TKNum % 17) % 4 * 8));
259 *(__IO uint32_t *)(&(TK->CCBD5) + ((u32TKNum % 17) >> 2)) |= (u32CapData << ((u32TKNum % 17) % 4 * 8));
260 }
261 }
262
263 /**
264 * @brief Set complement capacitor bank data of reference touch key
265 * @param[in] u32CapData Complement capacitor bank data. The valid value is 0~0xFF.
266 * @return None
267 * @details This function is used to set complement capacitor bank data of reference touch key.
268 * \hideinitializer
269 */
TK_SetRefKeyCapBankData(uint32_t u32CapData)270 void TK_SetRefKeyCapBankData(uint32_t u32CapData)
271 {
272 /* In M258, each channel has own reference capacitor data. The function will be used if SCAN_ALL */
273 TK->CCBD4 = (TK->CCBD4 & ~TK_CCBD4_CCBD_ALL_Msk) | (u32CapData << TK_CCBD4_CCBD_ALL_Pos);
274 }
275
276 /**
277 * @brief Set reference capacitor bank data of specified touch key
278 * @param[in] u32TKNum: Touch key number. The valid value is 0~25.
279 * @param[in] u32CapData: Complement capacitor bank data. The valid value is 0~0xFF.
280 * @return None
281 * @details This function is used to set complement capacitor bank data of reference touch key.
282 */
283
TK_SetRefCapBankData(uint32_t u32TKNum,uint32_t u32CapData)284 void TK_SetRefCapBankData(uint32_t u32TKNum, uint32_t u32CapData)
285 {
286 if(u32TKNum <= 16)
287 {
288 *(__IO uint32_t *)(&(TK->REFCBD0) + ((u32TKNum % 17) >> 2)) &= ~(TK_REFCBD0_CBD0_Msk << ((u32TKNum % 17) % 4 * 8));
289 *(__IO uint32_t *)(&(TK->REFCBD0) + ((u32TKNum % 17) >> 2)) |= (u32CapData << ((u32TKNum % 17) % 4 * 8));
290 }
291 else
292 {
293 *(__IO uint32_t *)(&(TK->REFCBD5) + ((u32TKNum % 17) >> 2)) &= ~(TK_REFCBD0_CBD0_Msk << ((u32TKNum % 17) % 4 * 8));
294 *(__IO uint32_t *)(&(TK->REFCBD5) + ((u32TKNum % 17) >> 2)) |= (u32CapData << ((u32TKNum % 17) % 4 * 8));
295 }
296 }
297
298 /**
299 * @brief Set high and low threshold of specified touch key for threshold control interrupt
300 * @param[in] u32TKNum Touch key number. The valid value is 0~16.
301 * @param[in] u32HighLevel High level for touch key threshold control. The valid value is 0~0xFF.
302 * @return None
303 * @details This function is used to set high and low threshold of specified touch key for threshold control interrupt.
304 * \hideinitializer
305 */
TK_SetScanThreshold(uint32_t u32TKNum,uint32_t u32HighLevel)306 void TK_SetScanThreshold(uint32_t u32TKNum, uint32_t u32HighLevel)
307 {
308 if(u32TKNum <= 16)
309 {
310 *(__IO uint32_t *)(&(TK->THC01) + ((u32TKNum % 17) >> 1)) &= ~((TK_THC01_HTH0_Msk) << (((u32TKNum % 17) & 0x1) * 16));
311 *(__IO uint32_t *)(&(TK->THC01) + ((u32TKNum % 17) >> 1)) |= (u32HighLevel << (TK_THC01_HTH0_Pos + ((u32TKNum % 17) & 0x1) * 16));
312 }
313 else
314 {
315 *(__IO uint32_t *)(&(TK->THC17) + ((u32TKNum % 17) >> 1)) &= ~((TK_THC01_HTH0_Msk) << (((u32TKNum % 17) & 0x1) * 16));
316 *(__IO uint32_t *)(&(TK->THC17) + ((u32TKNum % 17) >> 1)) |= (u32HighLevel << (TK_THC01_HTH0_Pos + ((u32TKNum % 17) & 0x1) * 16));
317 }
318 }
319
320 /**
321 * @brief Enable touch key scan interrupt
322 * @param[in] u32Msk Interrupt type selection.
323 * - \ref TK_INT_EN_SCAN_COMPLETE
324 * - \ref TK_INT_EN_SCAN_COMPLETE_LEVEL_TH
325 * @return None
326 * @details This function is used to enable touch key scan interrupt.
327 * @note It need disable the enabled interrupt type first by TK_DisableInt() before to change enabled interrupt type.
328 * \hideinitializer
329 */
TK_EnableInt(uint32_t u32Msk)330 void TK_EnableInt(uint32_t u32Msk)
331 {
332 TK->INTEN |= u32Msk;
333 }
334
335 /**
336 * @brief Disable touch key scan interrupt
337 * @param[in] u32Msk Interrupt type selection.
338 * - \ref TK_INT_EN_SCAN_COMPLETE
339 * - \ref TK_INT_EN_SCAN_COMPLETE_LEVEL_TH
340 * @return None
341 * @details This function is used to disable touch key scan interrupt.
342 * @note It need disable the enabled interrupt type first by TK_DisableInt() before to change enabled interrupt type.
343 * \hideinitializer
344 */
TK_DisableInt(uint32_t u32Msk)345 void TK_DisableInt(uint32_t u32Msk)
346 {
347 TK->INTEN &= ~u32Msk;
348 }
349
350 /**
351 * @brief To disable all channels
352 * @param[in] None
353 * @return None
354 * @details This function is used to disable all channels for key scan.
355 */
TK_DisableAllChannel(void)356 void TK_DisableAllChannel(void)
357 {
358 TK->SCANC &= ~(0x1FFFF);
359 if( ((SYS->PDID&0x01925000) == 0x01925000) || ((SYS->PDID&0x01D23140) == 0x01D23140) || ((SYS->PDID&0x01F31000) == 0x01F31000) )
360 {
361 //for M258G || TC8260 || M2L31
362 TK->SCANC1 &= ~(0x1F);
363 }
364 }
365
366
367 /**
368 * @brief To clear all interrupts that were caused if the conversion TK data over the high threshold.
369 * @param[in] None
370 * @return None
371 * @details This function is used to clear all interrupts that were caused if the conversion TK data over the high threshold.
372 */
TK_ClearTKIF(void)373 void TK_ClearTKIF(void)
374 {
375 TK->STA |= 0x1FFFFC3UL;
376 if( ((SYS->PDID&0x01925000) == 0x01925000) || ((SYS->PDID&0x01D23140) == 0x01D23140) || ((SYS->PDID&0x01F31000) == 0x01F31000) )
377 {
378 //for M258G || TC8260 || M2L31
379 TK->STA1 |= 0x1FUL;
380 }
381 }
382
383 /**
384 * @brief To enable scan all function to wake up system by any touch keys as low power mode
385 * @param[in] u8RefcbAll: The value co-works with u8CcbAll to make conversion all enabled touch keys' data - TKDATALL close to 0.
386 * @param[in] u8CcbAll: The value co-works with u8RefcbAll to make conversion all enabled touch keys' data - TKDATALL close to 0.
387 * @param[in] u8HThAll: Threshold to wake up system by any touch keys as low power mode
388 * @return None
389 * @details The u8RefcbAll and u8CcbAll are the calibration values was generate by calibration flow
390 * The flow makes the TKDATALL close to 0 after scan all enabled all touch keys.
391 */
TK_EnableScanAll(uint8_t u8RefcbAll,uint8_t u8CcbAll,uint8_t u8HThAll)392 void TK_EnableScanAll(uint8_t u8RefcbAll, uint8_t u8CcbAll, uint8_t u8HThAll)
393 {
394 TK->REFC |= TK_REFC_SCAN_ALL_Msk;
395 TK->REFCBD4 = (TK->REFCBD4 & (~TK_REFCBD4_CBD_ALL_Msk)) | (u8RefcbAll << TK_REFCBD4_CBD_ALL_Pos);
396 TK->CCBD4 = (TK->CCBD4 & (~TK_CCBD4_CCBD_ALL_Msk)) | (u8CcbAll << TK_CCBD4_CCBD_ALL_Pos);
397 TK->THC16 = (TK->THC16 & (~TK_THC16_HTH_ALL_Msk)) | (u8HThAll << TK_THC16_HTH_ALL_Pos);
398 }
399
400 /**
401 * @brief To disable scan all function to wake up system by any touch keys as low power mode
402 * @param[in] None
403 * @return None
404 */
TK_DisableScanAll(void)405 void TK_DisableScanAll(void)
406 {
407 TK->REFC &= ~TK_REFC_SCAN_ALL_Msk;
408 }
409
410 /**
411 * @brief To assign a TK channel as reference channel
412 * @param[in] u32TKChanBitMsk: Channel mask
413 * @return None
414 * @details The reference channel's voltage will compare with TK channel's as operation
415 *
416 */
TK_SetReferenceChannel(uint32_t u32TKChanBitMsk)417 void TK_SetReferenceChannel(uint32_t u32TKChanBitMsk) /* Single bit can be set */
418 {
419 if(u32TKChanBitMsk <= 0x10000)
420 {
421 TK->REFC = (TK->REFC & 0xFFFE0000) | u32TKChanBitMsk;
422 TK->REFC1 = 0x0;
423 }
424 else
425 {
426 TK->REFC = 0;
427 TK->REFC1 = (u32TKChanBitMsk >> 17);
428 }
429 }
430
431 /**
432 * @brief To assign enabled TK channels mask
433 * @param[in] u32TKChanBitMsk: Enabled channels mask
434 * @return None
435 * @details
436 *
437 */
TK_EnableChannel(uint32_t u32TKChanBitMsk)438 void TK_EnableChannel(uint32_t u32TKChanBitMsk) /* Multiple bits can be set */
439 {
440 TK->SCANC = (TK->SCANC & ~0x1FFFF) | (u32TKChanBitMsk & 0x1FFFF);
441 TK->SCANC1 = u32TKChanBitMsk >> 17;
442 }
443
444 /**
445 * @brief To assign disabled TK channels mask
446 * @param[in] u32TKChanBitMsk: Disable channels mask
447 * @return None
448 * @details
449 *
450 */
TK_DisableChannel(uint32_t u32TKChanBitMsk)451 void TK_DisableChannel(uint32_t u32TKChanBitMsk) /* Multiple bits can be set */
452 {
453 if( (u32TKChanBitMsk&0x1FFFF) != 0)
454 TK->SCANC &= ~(u32TKChanBitMsk&0x1FFFF);
455 if( (u32TKChanBitMsk >> 17) != 0)
456 TK->SCANC1 &= ~(u32TKChanBitMsk>>17);
457 }
458
459 /**
460 * @brief Clear the specifiy TK channel mask interrupt flags
461 * @param[in] u32TKChanBitMsk: Clear TK channels mask
462 * @return None
463 * @details
464 *
465 */
TK_ClearTKIFBitMask(uint32_t u32TKChanBitMsk)466 void TK_ClearTKIFBitMask(uint32_t u32TKChanBitMsk) /* Multiple bits can be set */
467 {
468 if( (u32TKChanBitMsk & 0x1FFFF) != 0x0)
469 {
470 TK->STA = (u32TKChanBitMsk & 0x1FFFF) << 8; /* Write one clear */
471 }
472 if( (u32TKChanBitMsk >> 17) != 0x0)
473 {
474 TK->STA1 = (u32TKChanBitMsk >> 17); /* Write one clear */
475 }
476 }
477
478 /**
479 * @brief Checking if the specifiy TK channel number interrupt flag occurs
480 * @param[in] u8TKNum: Disable channels number. Value from 0 ~ max TK number
481 * @return None
482 * @details
483 *
484 */
TK_CheckTKIF(uint8_t u8TKNum)485 uint32_t TK_CheckTKIF(uint8_t u8TKNum)
486 {
487 uint32_t u32Ret = 0;
488 if(u8TKNum <= 16)
489 {
490 if( TK->STA & ((1<<u8TKNum)<<8) )
491 u32Ret = 1;
492 else
493 u32Ret = 0;
494 }
495 else
496 {
497 if( TK->STA1 & (1<<(u8TKNum-17)) )
498 u32Ret = 1;
499 else
500 u32Ret = 0;
501 }
502 return u32Ret;
503 }
504
505 /*@}*/ /* end of group TK_EXPORTED_FUNCTIONS */
506
507 /*@}*/ /* end of group TK_Driver */
508
509 /*@}*/ /* end of group Standard_Driver */
510