/**************************************************************************//** * @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 #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;iKRF[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;iKPF[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] 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] pkeyQueue The FIFO queue of the key press/release status. * @param[in] u32MaxKeyCnt Maximum key counts in the key queue. * * @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; /* 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) { uint32_t freq[] = {__HXT, __LIRC, __HIRC, 0}; if(ms >= 1398) ms = 1398; KPI->DLYCTL = 0x1F | ((freq[(CLK->CLKSEL3 & CLK_CLKSEL3_KPISEL_Msk) >> CLK_CLKSEL3_KPISEL_Pos] / 1000)*ms << 8); } /** * @brief Set key scan timing for internal pull-up * * @details The internal pull-up is weak and slow. To use it, the key scan timing need to slow down. */ void KPI_EnableSlowScan() { /* It is slow enough when using LIRC clock source */ if((CLK->CLKSEL3 & CLK_CLKSEL3_KPISEL_Msk) == CLK_CLKSEL3_KPISEL_LIRC) return; KPI->CTL = (KPI->CTL & (~KPI_CTL_DBCLKSEL_Msk)) | (5 << KPI_CTL_DBCLKSEL_Pos); KPI->DLYCTL = (KPI->DLYCTL & (~0xff)) | 127; } /*@}*/ /* end of group KPI_EXPORTED_FUNCTIONS */ /*@}*/ /* end of group KPI_Driver */ /*@}*/ /* end of group Standard_Driver */