/***************************************************************************//** * @file * @brief Keyscan (KEYSCAN) peripheral API ******************************************************************************* * # License * Copyright 2024 Silicon Laboratories Inc. www.silabs.com ******************************************************************************* * * SPDX-License-Identifier: Zlib * * The licensor of this software is Silicon Laboratories Inc. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * ******************************************************************************/ #ifndef SL_HAL_KEYSCAN_H #define SL_HAL_KEYSCAN_H #include "em_device.h" #if defined(KEYSCAN_COUNT) && (KEYSCAN_COUNT > 0) #ifdef __cplusplus extern "C" { #endif #include #include "sl_hal_keyscan_compat.h" #include "sl_enum.h" /***************************************************************************//** * @addtogroup keyscan * @{ ******************************************************************************/ /******************************************************************************* ********************************* ENUM ************************************ ******************************************************************************/ /// KEYSCAN configuration delay values SL_ENUM(sl_hal_keyscan_delay_t) { SL_HAL_KEYSCAN_DELAY_2MS = 0, ///< 2 ms delay. SL_HAL_KEYSCAN_DELAY_4MS, ///< 4 ms delay. SL_HAL_KEYSCAN_DELAY_6MS, ///< 6 ms delay. SL_HAL_KEYSCAN_DELAY_8MS, ///< 8 ms delay. SL_HAL_KEYSCAN_DELAY_10MS, ///< 10 ms delay. SL_HAL_KEYSCAN_DELAY_12MS, ///< 12 ms delay. SL_HAL_KEYSCAN_DELAY_14MS, ///< 14 ms delay. SL_HAL_KEYSCAN_DELAY_16MS, ///< 16 ms delay. SL_HAL_KEYSCAN_DELAY_18MS, ///< 18 ms delay. SL_HAL_KEYSCAN_DELAY_20MS, ///< 20 ms delay. SL_HAL_KEYSCAN_DELAY_22MS, ///< 22 ms delay. SL_HAL_KEYSCAN_DELAY_24MS, ///< 24 ms delay. SL_HAL_KEYSCAN_DELAY_26MS, ///< 26 ms delay. SL_HAL_KEYSCAN_DELAY_28MS, ///< 28 ms delay. SL_HAL_KEYSCAN_DELAY_30MS, ///< 30 ms delay. SL_HAL_KEYSCAN_DELAY_32MS ///< 32 ms delay. }; /******************************************************************************* ******************************* STRUCTS *********************************** ******************************************************************************/ /// KEYSCAN configuration structure. typedef struct { uint32_t clock_divider; ///< Clock divider value. uint8_t column_number; ///< Number of columns to set for keyscan (maximum 8). uint8_t row_number; ///< Number of rows to set for keyscan (maximum 6). sl_hal_keyscan_delay_t scan_delay; ///< Scan delay. sl_hal_keyscan_delay_t debounce_delay; ///< Debounce delay. sl_hal_keyscan_delay_t stable_delay; ///< Stable delay. bool single_press_enable; ///< Enable Single Press feature. bool auto_start_enable; ///< Enable auto-start feature. } sl_hal_keyscan_config_t; /// Suggested default values for KEYSCAN configuration structure. #define KEYSCAN_CONFIG_DEFAULT \ { \ 0x1387F, /* Clock divider default value = 79999. */ \ 3u, /* 3 columns by default. */ \ 6u, /* 6 rows by default. */ \ SL_HAL_KEYSCAN_DELAY_2MS, /* value 0 = 2ms Scan Delay*/ \ SL_HAL_KEYSCAN_DELAY_2MS, /* value 0 = 2ms Debounce Delay */ \ SL_HAL_KEYSCAN_DELAY_2MS, /* value 0 = 2ms Row Stable Delay */ \ false, /* Multi-press by default.*/ \ false, /* No auto-start by default. */ \ } /******************************************************************************* ***************************** PROTOTYPES ********************************** ******************************************************************************/ /***************************************************************************//** * Initializes KEYSCAN module. * * @param[in] p_config A pointer to the KEYSCAN initialization structure * variable. ******************************************************************************/ void sl_hal_keyscan_init(const sl_hal_keyscan_config_t *p_config); /***************************************************************************//** * Enables KEYSCAN module. ******************************************************************************/ void sl_hal_keyscan_enable(void); /***************************************************************************//** * Disables KEYSCAN module. * * @note The disabling of the module could take some time. This function will * not wait for the disabling to finish before returning. Use the function * sl_hal_keyscan_wait_ready to wait for the module to be fully disable. ******************************************************************************/ void sl_hal_keyscan_disable(void); /***************************************************************************//** * Waits for the KEYSCAN to complete reseting or disabling procedure. ******************************************************************************/ __STATIC_INLINE void sl_hal_keyscan_wait_ready(void) { while ((KEYSCAN->SWRST & _KEYSCAN_SWRST_RESETTING_MASK) || (KEYSCAN->EN & _KEYSCAN_EN_DISABLING_MASK) || (KEYSCAN->STATUS & _KEYSCAN_STATUS_SYNCBUSY_MASK)) { // Wait for resetting, for disabling or for all synchronizations to finish } } /***************************************************************************//** * Waits for the KEYSCAN to complete all synchronization of register changes * and commands. ******************************************************************************/ __STATIC_INLINE void sl_hal_keyscan_wait_sync(void) { while ((KEYSCAN->EN != 0U) && (KEYSCAN->STATUS & KEYSCAN_STATUS_SYNCBUSY)) { // Wait for all synchronizations to finish } } /***************************************************************************//** * Starts KEYSCAN scan. * * @note This function will send a start command to the KEYSCAN peripheral. * The sl_hal_keyscan_wait_sync function can be used to wait for the start * command to be executed. * * @note This function requires the KEYSCAN to be enabled. ******************************************************************************/ __STATIC_INLINE void sl_hal_keyscan_start_scan(void) { sl_hal_keyscan_wait_sync(); KEYSCAN->CMD = KEYSCAN_CMD_KEYSCANSTART; sl_hal_keyscan_wait_ready(); } /***************************************************************************//** * Stops the KEYSCAN scan. * * @note This function will send a stop command to the KEYSCAN peripheral. * The sl_hal_keyscan_wait_sync function can be used to wait for the stop * command to be executed. * * @note This function requires the KEYSCAN to be enabled. ******************************************************************************/ __STATIC_INLINE void sl_hal_keyscan_stop_scan(void) { sl_hal_keyscan_wait_sync(); KEYSCAN->CMD = KEYSCAN_CMD_KEYSCANSTOP; sl_hal_keyscan_wait_ready(); } /***************************************************************************//** * Restores KEYSCAN to its reset state. * * @note The resetting of the module could take some time. This function will * not wait for the resetting to finish before returning. Use the function * sl_hal_keyscan_wait_ready to wait for the module to be fully reset. ******************************************************************************/ void sl_hal_keyscan_reset(void); /***************************************************************************//** * Gets KEYSCAN STATUS register value. * * @return Current STATUS register value. ******************************************************************************/ __STATIC_INLINE uint32_t sl_hal_keyscan_get_status(void) { return KEYSCAN->STATUS; } /***************************************************************************//** * Enables one or more KEYSCAN interrupts. * * @note Depending on the use, a pending interrupt may already be set prior to * enabling the interrupt. To ignore a pending interrupt, consider using * sl_hal_keyscan_clear_interrupts prior to enabling the interrupt. * * @param[in] flags KEYSCAN interrupt sources to enable. * Use a set of interrupt flags OR-ed together to set * multiple interrupt sources. ******************************************************************************/ __STATIC_INLINE void sl_hal_keyscan_enable_interrupts(uint32_t flags) { KEYSCAN->IEN_SET = flags; } /***************************************************************************//** * Disables one or more KEYSCAN interrupts. * * @param[in] flags KEYSCAN interrupt sources to disable. * Use a set of interrupt flags OR-ed together to disable * multiple interrupt sources. ******************************************************************************/ __STATIC_INLINE void sl_hal_keyscan_disable_interrupts(uint32_t flags) { KEYSCAN->IEN_CLR = flags; } /***************************************************************************//** * Clears one or more pending KEYSCAN interrupts. * * @param[in] flags KEYSCAN interrupt sources to clear. * Use a set of interrupt flags OR-ed together to clear * multiple interrupt sources. ******************************************************************************/ __STATIC_INLINE void sl_hal_keyscan_clear_interrupts(uint32_t flags) { KEYSCAN->IF_CLR = flags; } /***************************************************************************//** * Gets pending KEYSCAN interrupt flags. * * @note Event bits are not cleared by using this function. * * @return Pending KEYSCAN interrupt sources. * Returns a set of interrupt flags OR-ed together for multiple * interrupt sources. ******************************************************************************/ __STATIC_INLINE uint32_t sl_hal_keyscan_get_interrupts(void) { return KEYSCAN->IF; } /***************************************************************************//** * Gets enabled and pending KEYSCAN interrupt flags. * Useful for handling more interrupt sources in the same interrupt handler. * * @note Interrupt flags are not cleared by using this function. * * @return Pending and enabled KEYSCAN interrupt sources. * The return value is the bitwise AND of * - the enabled interrupt sources in KEYSCAN_IEN and * - the pending interrupt flags KEYSCAN_IF. ******************************************************************************/ __STATIC_INLINE uint32_t sl_hal_keyscan_get_enabled_interrupts(void) { return KEYSCAN->IF & KEYSCAN->IEN; } /***************************************************************************//** * Sets one or more pending KEYSCAN interrupts from Software. * * @param[in] flags KEYSCAN interrupt sources to set to pending. * Use a set of interrupt flags OR-ed together to set * multiple interrupt sources. ******************************************************************************/ __STATIC_INLINE void sl_hal_keyscan_set_interrupts(uint32_t flags) { KEYSCAN->IF_SET = flags; } /** @} (end addtogroup keyscan) */ #ifdef __cplusplus } #endif #endif /* defined(KEYSCAN_COUNT) && (KEYSCAN_COUNT > 0) */ #endif /* SL_HAL_KEYSCAN_H */