1 /***************************************************************************//**
2 * @file
3 * @brief Keyscan (KEYSCAN) peripheral API
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 #ifndef SL_HAL_KEYSCAN_H
32 #define SL_HAL_KEYSCAN_H
33
34 #include "em_device.h"
35
36 #if defined(KEYSCAN_COUNT) && (KEYSCAN_COUNT > 0)
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41
42 #include <stdbool.h>
43 #include "sl_hal_keyscan_compat.h"
44 #include "sl_enum.h"
45
46 /***************************************************************************//**
47 * @addtogroup keyscan
48 * @{
49 ******************************************************************************/
50
51 /*******************************************************************************
52 ********************************* ENUM ************************************
53 ******************************************************************************/
54
55 /// KEYSCAN configuration delay values
SL_ENUM(sl_hal_keyscan_delay_t)56 SL_ENUM(sl_hal_keyscan_delay_t) {
57 SL_HAL_KEYSCAN_DELAY_2MS = 0, ///< 2 ms delay.
58 SL_HAL_KEYSCAN_DELAY_4MS, ///< 4 ms delay.
59 SL_HAL_KEYSCAN_DELAY_6MS, ///< 6 ms delay.
60 SL_HAL_KEYSCAN_DELAY_8MS, ///< 8 ms delay.
61 SL_HAL_KEYSCAN_DELAY_10MS, ///< 10 ms delay.
62 SL_HAL_KEYSCAN_DELAY_12MS, ///< 12 ms delay.
63 SL_HAL_KEYSCAN_DELAY_14MS, ///< 14 ms delay.
64 SL_HAL_KEYSCAN_DELAY_16MS, ///< 16 ms delay.
65 SL_HAL_KEYSCAN_DELAY_18MS, ///< 18 ms delay.
66 SL_HAL_KEYSCAN_DELAY_20MS, ///< 20 ms delay.
67 SL_HAL_KEYSCAN_DELAY_22MS, ///< 22 ms delay.
68 SL_HAL_KEYSCAN_DELAY_24MS, ///< 24 ms delay.
69 SL_HAL_KEYSCAN_DELAY_26MS, ///< 26 ms delay.
70 SL_HAL_KEYSCAN_DELAY_28MS, ///< 28 ms delay.
71 SL_HAL_KEYSCAN_DELAY_30MS, ///< 30 ms delay.
72 SL_HAL_KEYSCAN_DELAY_32MS ///< 32 ms delay.
73 };
74
75 /*******************************************************************************
76 ******************************* STRUCTS ***********************************
77 ******************************************************************************/
78
79 /// KEYSCAN configuration structure.
80 typedef struct {
81 uint32_t clock_divider; ///< Clock divider value.
82 uint8_t column_number; ///< Number of columns to set for keyscan (maximum 8).
83 uint8_t row_number; ///< Number of rows to set for keyscan (maximum 6).
84 sl_hal_keyscan_delay_t scan_delay; ///< Scan delay.
85 sl_hal_keyscan_delay_t debounce_delay; ///< Debounce delay.
86 sl_hal_keyscan_delay_t stable_delay; ///< Stable delay.
87 bool single_press_enable; ///< Enable Single Press feature.
88 bool auto_start_enable; ///< Enable auto-start feature.
89 } sl_hal_keyscan_config_t;
90
91 /// Suggested default values for KEYSCAN configuration structure.
92 #define KEYSCAN_CONFIG_DEFAULT \
93 { \
94 0x1387F, /* Clock divider default value = 79999. */ \
95 3u, /* 3 columns by default. */ \
96 6u, /* 6 rows by default. */ \
97 SL_HAL_KEYSCAN_DELAY_2MS, /* value 0 = 2ms Scan Delay*/ \
98 SL_HAL_KEYSCAN_DELAY_2MS, /* value 0 = 2ms Debounce Delay */ \
99 SL_HAL_KEYSCAN_DELAY_2MS, /* value 0 = 2ms Row Stable Delay */ \
100 false, /* Multi-press by default.*/ \
101 false, /* No auto-start by default. */ \
102 }
103
104 /*******************************************************************************
105 ***************************** PROTOTYPES **********************************
106 ******************************************************************************/
107
108 /***************************************************************************//**
109 * Initializes KEYSCAN module.
110 *
111 * @param[in] p_config A pointer to the KEYSCAN initialization structure
112 * variable.
113 ******************************************************************************/
114 void sl_hal_keyscan_init(const sl_hal_keyscan_config_t *p_config);
115
116 /***************************************************************************//**
117 * Enables KEYSCAN module.
118 ******************************************************************************/
119 void sl_hal_keyscan_enable(void);
120
121 /***************************************************************************//**
122 * Disables KEYSCAN module.
123 *
124 * @note The disabling of the module could take some time. This function will
125 * not wait for the disabling to finish before returning. Use the function
126 * sl_hal_keyscan_wait_ready to wait for the module to be fully disable.
127 ******************************************************************************/
128 void sl_hal_keyscan_disable(void);
129
130 /***************************************************************************//**
131 * Waits for the KEYSCAN to complete reseting or disabling procedure.
132 ******************************************************************************/
sl_hal_keyscan_wait_ready(void)133 __STATIC_INLINE void sl_hal_keyscan_wait_ready(void)
134 {
135 while ((KEYSCAN->SWRST & _KEYSCAN_SWRST_RESETTING_MASK) || (KEYSCAN->EN & _KEYSCAN_EN_DISABLING_MASK) || (KEYSCAN->STATUS & _KEYSCAN_STATUS_SYNCBUSY_MASK)) {
136 // Wait for resetting, for disabling or for all synchronizations to finish
137 }
138 }
139
140 /***************************************************************************//**
141 * Waits for the KEYSCAN to complete all synchronization of register changes
142 * and commands.
143 ******************************************************************************/
sl_hal_keyscan_wait_sync(void)144 __STATIC_INLINE void sl_hal_keyscan_wait_sync(void)
145 {
146 while ((KEYSCAN->EN != 0U) && (KEYSCAN->STATUS & KEYSCAN_STATUS_SYNCBUSY)) {
147 // Wait for all synchronizations to finish
148 }
149 }
150
151 /***************************************************************************//**
152 * Starts KEYSCAN scan.
153 *
154 * @note This function will send a start command to the KEYSCAN peripheral.
155 * The sl_hal_keyscan_wait_sync function can be used to wait for the start
156 * command to be executed.
157 *
158 * @note This function requires the KEYSCAN to be enabled.
159 ******************************************************************************/
sl_hal_keyscan_start_scan(void)160 __STATIC_INLINE void sl_hal_keyscan_start_scan(void)
161 {
162 sl_hal_keyscan_wait_sync();
163 KEYSCAN->CMD = KEYSCAN_CMD_KEYSCANSTART;
164 sl_hal_keyscan_wait_ready();
165 }
166
167 /***************************************************************************//**
168 * Stops the KEYSCAN scan.
169 *
170 * @note This function will send a stop command to the KEYSCAN peripheral.
171 * The sl_hal_keyscan_wait_sync function can be used to wait for the stop
172 * command to be executed.
173 *
174 * @note This function requires the KEYSCAN to be enabled.
175 ******************************************************************************/
sl_hal_keyscan_stop_scan(void)176 __STATIC_INLINE void sl_hal_keyscan_stop_scan(void)
177 {
178 sl_hal_keyscan_wait_sync();
179 KEYSCAN->CMD = KEYSCAN_CMD_KEYSCANSTOP;
180 sl_hal_keyscan_wait_ready();
181 }
182
183 /***************************************************************************//**
184 * Restores KEYSCAN to its reset state.
185 *
186 * @note The resetting of the module could take some time. This function will
187 * not wait for the resetting to finish before returning. Use the function
188 * sl_hal_keyscan_wait_ready to wait for the module to be fully reset.
189 ******************************************************************************/
190 void sl_hal_keyscan_reset(void);
191
192 /***************************************************************************//**
193 * Gets KEYSCAN STATUS register value.
194 *
195 * @return Current STATUS register value.
196 ******************************************************************************/
sl_hal_keyscan_get_status(void)197 __STATIC_INLINE uint32_t sl_hal_keyscan_get_status(void)
198 {
199 return KEYSCAN->STATUS;
200 }
201
202 /***************************************************************************//**
203 * Enables one or more KEYSCAN interrupts.
204 *
205 * @note Depending on the use, a pending interrupt may already be set prior to
206 * enabling the interrupt. To ignore a pending interrupt, consider using
207 * sl_hal_keyscan_clear_interrupts prior to enabling the interrupt.
208 *
209 * @param[in] flags KEYSCAN interrupt sources to enable.
210 * Use a set of interrupt flags OR-ed together to set
211 * multiple interrupt sources.
212 ******************************************************************************/
sl_hal_keyscan_enable_interrupts(uint32_t flags)213 __STATIC_INLINE void sl_hal_keyscan_enable_interrupts(uint32_t flags)
214 {
215 KEYSCAN->IEN_SET = flags;
216 }
217
218 /***************************************************************************//**
219 * Disables one or more KEYSCAN interrupts.
220 *
221 * @param[in] flags KEYSCAN interrupt sources to disable.
222 * Use a set of interrupt flags OR-ed together to disable
223 * multiple interrupt sources.
224 ******************************************************************************/
sl_hal_keyscan_disable_interrupts(uint32_t flags)225 __STATIC_INLINE void sl_hal_keyscan_disable_interrupts(uint32_t flags)
226 {
227 KEYSCAN->IEN_CLR = flags;
228 }
229
230 /***************************************************************************//**
231 * Clears one or more pending KEYSCAN interrupts.
232 *
233 * @param[in] flags KEYSCAN interrupt sources to clear.
234 * Use a set of interrupt flags OR-ed together to clear
235 * multiple interrupt sources.
236 ******************************************************************************/
sl_hal_keyscan_clear_interrupts(uint32_t flags)237 __STATIC_INLINE void sl_hal_keyscan_clear_interrupts(uint32_t flags)
238 {
239 KEYSCAN->IF_CLR = flags;
240 }
241
242 /***************************************************************************//**
243 * Gets pending KEYSCAN interrupt flags.
244 *
245 * @note Event bits are not cleared by using this function.
246 *
247 * @return Pending KEYSCAN interrupt sources.
248 * Returns a set of interrupt flags OR-ed together for multiple
249 * interrupt sources.
250 ******************************************************************************/
sl_hal_keyscan_get_interrupts(void)251 __STATIC_INLINE uint32_t sl_hal_keyscan_get_interrupts(void)
252 {
253 return KEYSCAN->IF;
254 }
255
256 /***************************************************************************//**
257 * Gets enabled and pending KEYSCAN interrupt flags.
258 * Useful for handling more interrupt sources in the same interrupt handler.
259 *
260 * @note Interrupt flags are not cleared by using this function.
261 *
262 * @return Pending and enabled KEYSCAN interrupt sources.
263 * The return value is the bitwise AND of
264 * - the enabled interrupt sources in KEYSCAN_IEN and
265 * - the pending interrupt flags KEYSCAN_IF.
266 ******************************************************************************/
sl_hal_keyscan_get_enabled_interrupts(void)267 __STATIC_INLINE uint32_t sl_hal_keyscan_get_enabled_interrupts(void)
268 {
269 return KEYSCAN->IF & KEYSCAN->IEN;
270 }
271
272 /***************************************************************************//**
273 * Sets one or more pending KEYSCAN interrupts from Software.
274 *
275 * @param[in] flags KEYSCAN interrupt sources to set to pending.
276 * Use a set of interrupt flags OR-ed together to set
277 * multiple interrupt sources.
278 ******************************************************************************/
sl_hal_keyscan_set_interrupts(uint32_t flags)279 __STATIC_INLINE void sl_hal_keyscan_set_interrupts(uint32_t flags)
280 {
281 KEYSCAN->IF_SET = flags;
282 }
283
284 /** @} (end addtogroup keyscan) */
285
286 #ifdef __cplusplus
287 }
288 #endif
289
290 #endif /* defined(KEYSCAN_COUNT) && (KEYSCAN_COUNT > 0) */
291 #endif /* SL_HAL_KEYSCAN_H */
292