1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
|
/**************************************************************************//**
* @file kpi.c
* @version V3.00
* @brief KPI driver source file
*
* @copyright SPDX-License-Identifier: Apache-2.0
* @copyright (C) 2021 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include "NuMicro.h"
/** @addtogroup Standard_Driver Standard Driver
@{
*/
/** @addtogroup KPI_Driver KPI Driver
@{
*/
/** @addtogroup KPI_EXPORTED_FUNCTIONS KPI Exported Functions
@{
*/
static KPI_KEY_T *s_pKeyQueue = 0;
static volatile uint32_t s_u32MaxKeyCnt = 0;
static volatile uint32_t s_u32FirstKey = 0;
static volatile uint32_t s_u32LastKey = 0;
__WEAK void KPI_KeyHandler(KPI_KEY_T key)
{
uint32_t u32Next;
/* Move last to next available space */
u32Next = s_u32LastKey + 1;
if (u32Next >= s_u32MaxKeyCnt)
u32Next = 0; // buffer wrap
if (u32Next == s_u32FirstKey)
return; // Queue full
/* Push key to the queue */
s_pKeyQueue[s_u32LastKey] = key;
s_u32LastKey = u32Next;
}
void KPI_IRQHandler()
{
int32_t i, j, idx, r;
uint32_t u32KeyPress[2], u32KeyRelease[2], status;
uint32_t row, col, mask;
KPI_KEY_T key;
/* cache key events ASAP */
status = KPI->STATUS;
u32KeyPress[0] = KPI->KPF[0];
u32KeyPress[1] = KPI->KPF[1];
u32KeyRelease[0] = KPI->KRF[0];
u32KeyRelease[1] = KPI->KRF[1];
if (status & KPI_STATUS_KIF_Msk)
{
/* Get current row/column setting */
row = ((KPI->CTL & KPI_CTL_KROW_Msk) >> KPI_CTL_KROW_Pos) + 1;
col = ((KPI->CTL & KPI_CTL_KCOL_Msk) >> KPI_CTL_KCOL_Pos) + 1;
/* Deal with the key evernts */
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
/* Identify the specified key bit */
idx = (i < 4) ? 0 : 1;
r = i - idx * 4;
mask = 1ul << (r * 8 + j);
/* Key Release */
if (status & KPI_STATUS_KRIF_Msk)
{
if (u32KeyRelease[idx] & mask)
{
/* Clean event */
KPI->KRF[idx] = mask;
/* Record the key */
key.x = i;
key.y = j;
key.st = KPI_RELEASE;
/* call handler */
KPI_KeyHandler(key);
}
}
}
}
/* Deal with the key evernts */
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
/* Identify the specified key bit */
idx = (i < 4) ? 0 : 1;
r = i - idx * 4;
mask = 1ul << (r * 8 + j);
/* Key Press */
if (status & KPI_STATUS_KPIF_Msk)
{
if (u32KeyPress[idx] & mask)
{
/* Clean event */
KPI->KPF[idx] = mask;
/* Record the key */
key.x = i;
key.y = j;
key.st = KPI_PRESS;
/* call handler */
KPI_KeyHandler(key);
}
}
}
}
}
if (status & KPI_STATUS_TKRIF_Msk)
{
/* Clear flag */
KPI->STATUS = KPI_STATUS_TKRIF_Msk;
printf("Three key press!!\n");
}
}
/**
* @brief Open Keypad interface
*
* @param[in] kpi The pointer of the specified KPI module.
* @param[in] u32Rows The number of key rows for key scan. it could be 2 ~ 6.
* @param[in] u32Columns The number of key columns for key scan. it could be 1 ~ 8.
* @param[in] keyQueue The FIFO queue of the key press/release status.
*
* @retval 0 Sucessful
* @retval -1 Failure
*
* @details The function is used to set row and column of keypad and start to key scan.
*/
int32_t KPI_Open(uint32_t u32Rows, uint32_t u32Columns, KPI_KEY_T *pkeyQueue, uint32_t u32MaxKeyCnt)
{
/* Key ROW limitation */
if ((u32Rows < 2) || (u32Rows > 6))
return -1;
/* Key COLUMN limitation */
if (u32Columns > 8)
return -1;
/* Enable KPI Clock */
CLK->APBCLK2 |= CLK_APBCLK2_KPICKEN_Msk;
/* Seleck KPI Clock Source */
CLK->CLKSEL3 |= CLK_CLKSEL3_KPISEL_HIRC;
/* Reset KPI */
SYS->IPRST3 |= SYS_IPRST3_KPIRST_Msk;
SYS->IPRST3 ^= SYS_IPRST3_KPIRST_Msk;
/* Set KPI */
KPI->CTL = ((u32Rows - 1) << KPI_CTL_KROW_Pos) | ((u32Columns - 1) << KPI_CTL_KCOL_Pos) |
KPI_CTL_KIEN_Msk | KPI_CTL_KPIEN_Msk | KPI_CTL_KRIEN_Msk |
(3 << KPI_CTL_DBCLKSEL_Pos) |
KPI_CTL_KPEN_Msk;
NVIC_EnableIRQ(KPI_IRQn);
/* Set up the queue of key */
s_pKeyQueue = pkeyQueue;
s_u32MaxKeyCnt = u32MaxKeyCnt;
s_u32FirstKey = 0;
s_u32LastKey = 0;
return 0;
}
/**
* @brief Close Keypad interface
*
* @details The function is used to stop and close key pad.
*/
void KPI_Close()
{
/* Disable Keypad */
KPI->CTL = 0;
}
/**
* @brief Detect any key press
*
*
* @retval 1 Key pressed
* @retval 0 No key pressed
*
* @details The function is used to check if any key pressed.
*/
int32_t KPI_kbhit()
{
if (s_u32FirstKey != s_u32LastKey)
return 1;
return 0;
}
/**
* @brief Get pressed/released key
*
* @return return the pressed key information. If no key pressed, return key index is 0xff, 0xff.
*
* @details The function is get the key pressed or key released.
*/
KPI_KEY_T KPI_GetKey()
{
KPI_KEY_T key = {0xff, 0xff, 0xffff};
/* Check if queue is empty */
if (s_u32FirstKey != s_u32LastKey)
{
/* Pop the key from queue */
key = s_pKeyQueue[s_u32FirstKey++];
/* Wrap around check */
if (s_u32FirstKey >= s_u32MaxKeyCnt)
s_u32FirstKey = 0;
}
return key;
}
/**
* @brief Set key sample time
*
* @param[in] ms The key sample time in milliseconds.
*
* @details The function is used to set key sample time. The maximum time is 1398 milliseconds.
*/
void KPI_SetSampleTime(uint32_t ms)
{
if (ms >= 1398)
ms = 1398;
KPI->DLYCTL = 0x1F | ((__HIRC / 1000) * ms << 8);
}
/*@}*/ /* end of group KPI_EXPORTED_FUNCTIONS */
/*@}*/ /* end of group KPI_Driver */
/*@}*/ /* end of group Standard_Driver */
|