/******************************************************************************* @file kscan.c @brief Contains all functions support for key scan driver @version 0.0 @date 13. Nov. 2017 @author Ding SDK_LICENSE *******************************************************************************/ #include "rom_sym_def.h" #include #include "clock.h" #include "OSAL.h" #include "kscan.h" #include "pwrmgr.h" #include "error.h" #include "gpio.h" #include "uart.h" #include "bus_dev.h" #include "log.h" #include "jump_function.h" typedef struct { bool enable; kscan_Cfg_t cfg; uint16_t key_state[MULTI_KEY_NUM<<1]; uint8_t pin_state[NUM_KEY_ROWS]; uint8_t kscan_task_id; uint16_t timeout_event; } kscan_Ctx_t; static kscan_Ctx_t m_kscanCtx; static kscan_Key_t m_keys[MAX_KEY_NUM]; static uint8_t reScan_flag=0; //PRIVATE FUNCTIONS static void kscan_hw_config(void); static void hal_kscan_config_row(KSCAN_ROWS_e row); static void hal_kscan_config_col(KSCAN_COLS_e col); static void kscan_sleep_handler(void); static void kscan_wakeup_handler(void); static void get_key_matrix(uint16_t* key_matrix); static void rmv_ghost_key(uint16_t* key_matrix); static kscan_Evt_t kscan_compare_key(uint16_t* key_pre, uint16_t* key_nxt); static void hal_kscan_clear_config(void); extern void hal_gpioin_set_flag(gpio_pin_e pin); #define TIMEOUT_DELTA 10 /************************************************************************************** @fn hal_kscan_init @brief This function process for key scan initial input parameters @param None. output parameters @param None. @return None. **************************************************************************************/ int hal_kscan_init(kscan_Cfg_t cfg, uint8 task_id, uint16 event) { if(m_kscanCtx.enable) return PPlus_ERR_INVALID_STATE; m_kscanCtx.cfg = cfg; m_kscanCtx.kscan_task_id = task_id; m_kscanCtx.timeout_event = event; m_kscanCtx.enable = TRUE; kscan_hw_config(); JUMP_FUNCTION(KSCAN_IRQ_HANDLER) = (uint32_t)&hal_KSCAN_IRQHandler; hal_pwrmgr_register(MOD_KSCAN, kscan_sleep_handler, kscan_wakeup_handler); return PPlus_SUCCESS; } /************************************************************************************** @fn hal_kscan_clear_config @brief This function process for key scan clear config input parameters @param None. output parameters @param None. @return None. **************************************************************************************/ void hal_kscan_clear_config() { subWriteReg(&(AP_IOMUX->keyscan_in_en),10,0,0);//iomux:key_scan_in_en and key_scan_out_en subWriteReg(&(AP_IOMUX->keyscan_out_en),11,0,0); subWriteReg((&AP_KSCAN->ctrl0), 13, 2, 0);//kscan:mattrix scan outputs and mattrix scan inputs subWriteReg((&AP_KSCAN->mk_in_en), 10, 0, 0); } void __attribute__((used)) hal_KSCAN_IRQHandler() { uint16_t key_nxt[MULTI_KEY_NUM<<1]; if(reScan_flag==1) reScan_flag=0; osal_stop_timerEx(m_kscanCtx.kscan_task_id, m_kscanCtx.timeout_event);//todo get_key_matrix(key_nxt); if(m_kscanCtx.cfg.ghost_key_state == IGNORE_GHOST_KEY) rmv_ghost_key(key_nxt); if(m_kscanCtx.cfg.evt_handler) { kscan_Evt_t evt = kscan_compare_key(m_kscanCtx.key_state, key_nxt); if(evt.num>0) m_kscanCtx.cfg.evt_handler(&evt); } memcpy(m_kscanCtx.key_state, key_nxt, sizeof(uint16_t)*(MULTI_KEY_NUM<<1)); osal_start_timerEx(m_kscanCtx.kscan_task_id, m_kscanCtx.timeout_event, (2*m_kscanCtx.cfg.interval+TIMEOUT_DELTA));//todo } void hal_kscan_timeout_handler() { if(reScan_flag==0) { // LOG("kscan_reScan\n\r"); hal_kscan_clear_config(); reScan_flag=1; kscan_hw_config(); osal_start_timerEx(m_kscanCtx.kscan_task_id, m_kscanCtx.timeout_event, m_kscanCtx.cfg.interval+TIMEOUT_DELTA); } else if(reScan_flag==1) { //LOG("kscan_timeout_handler\n\r"); osal_stop_timerEx(m_kscanCtx.kscan_task_id, m_kscanCtx.timeout_event); uint16_t key_nxt[MULTI_KEY_NUM<<1]; memset(&key_nxt[0],0,sizeof(uint16_t)*(MULTI_KEY_NUM<<1)); //all register must be 0.teedy add 2019/01/23 //get_key_matrix(key_nxt); //no need to read the register,because keyScan didn't update the register .teedy add 2019/01/23 if(m_kscanCtx.cfg.ghost_key_state == IGNORE_GHOST_KEY) rmv_ghost_key(key_nxt); if(m_kscanCtx.cfg.evt_handler) { kscan_Evt_t evt = kscan_compare_key(m_kscanCtx.key_state, key_nxt); m_kscanCtx.cfg.evt_handler(&evt); } memcpy(m_kscanCtx.key_state, key_nxt, sizeof(uint16_t)*(MULTI_KEY_NUM<<1)); reScan_flag=0; hal_pwrmgr_unlock(MOD_KSCAN); } } static void kscan_hw_config(void) { kscan_Cfg_t* cfg = &(m_kscanCtx.cfg); hal_clk_gate_enable(MOD_KSCAN); hal_kscan_clear_config(); for(uint8_t i=0; ikey_rows[i]); for(uint8_t i=0; ikey_cols[i]); subWriteReg((&AP_KSCAN->ctrl0),20,20,NOT_IGNORE_MULTI_KEY); subWriteReg((&AP_KSCAN->ctrl0),23,23,SENCE_LOW);//SENCE_HIGH subWriteReg((&AP_KSCAN->ctrl0),31,24,cfg->interval); NVIC_SetPriority((IRQn_Type)KSCAN_IRQn, IRQ_PRIO_HAL); NVIC_EnableIRQ((IRQn_Type)KSCAN_IRQn); subWriteReg((&AP_KSCAN->ctrl0),1,1,1);//kscan int enable subWriteReg((&AP_KSCAN->ctrl0),0,0,1);//kscan enable } /************************************************************************************** @fn hal_kscan_config_row @brief This function process for setting key row pin input parameters @param KSCAN_ROWS_e row output parameters @param None. @return None. **************************************************************************************/ static void hal_kscan_config_row(KSCAN_ROWS_e row) { gpio_pin_e row_pin = (gpio_pin_e)KSCAN_ROW_GPIO[row]; hal_gpio_fmux(row_pin, Bit_DISABLE); hal_gpio_pull_set(row_pin,GPIO_PULL_UP_S); subWriteReg(&(AP_IOMUX->keyscan_in_en),row,row,1); subWriteReg((&AP_KSCAN->mk_in_en),row,row, 1); } /************************************************************************************** @fn hal_kscan_config_col @brief This function process for setting key scan col pin input parameters @param KSCAN_COLS_e col output parameters @param None. @return None. **************************************************************************************/ static void hal_kscan_config_col(KSCAN_COLS_e col) { gpio_pin_e col_pin = (gpio_pin_e)KSCAN_COL_GPIO[col]; hal_gpio_fmux(col_pin, Bit_DISABLE); hal_gpio_pull_set(col_pin,GPIO_PULL_UP_S); subWriteReg(&(AP_IOMUX->keyscan_out_en),col,col,1); subWriteReg((&AP_KSCAN->ctrl0),(col+2),(col+2), 1); } static void kscan_sleep_handler(void) { gpio_polarity_e pol; hal_kscan_clear_config(); for(uint8_t i=0; ikeyscan_out_en),m_kscanCtx.cfg.key_cols[i],m_kscanCtx.cfg.key_cols[i],0); hal_gpioin_set_flag(col_pin); hal_gpio_pull_set(col_pin, GPIO_PULL_DOWN); hal_gpio_pin_init(col_pin, GPIO_INPUT); } for(uint8_t i=0; ikeyscan_in_en),m_kscanCtx.cfg.key_rows[i],m_kscanCtx.cfg.key_rows[i],0); hal_gpioin_set_flag(row_pin); hal_gpio_pull_set(row_pin, GPIO_PULL_UP); hal_gpio_pin_init(row_pin, GPIO_INPUT); pol = hal_gpio_read(row_pin) ? POL_FALLING:POL_RISING; hal_gpio_wakeup_set(row_pin, pol); m_kscanCtx.pin_state[i] = pol; } } static void kscan_wakeup_handler(void) { for(uint8_t i=0; ikeyscan_out_en),m_kscanCtx.cfg.key_cols[i],m_kscanCtx.cfg.key_cols[i],0); hal_gpio_pull_set(col_pin, GPIO_PULL_DOWN); hal_gpio_pin_init(col_pin, GPIO_INPUT); } for(uint8_t i=0; ikeyscan_in_en),m_kscanCtx.cfg.key_rows[i],m_kscanCtx.cfg.key_rows[i],0); hal_gpio_pull_set(row_pin, GPIO_PULL_UP);//teddy add 20190122 hal_gpio_pin_init(row_pin, GPIO_INPUT); } for(uint8_t i=0; imkc[i])) & 0x0000FFFF); uint16_t high = (read_reg(&(AP_KSCAN->mkc[i])) & 0xFFFF0000) >> 16; key_matrix[i*2] = low; key_matrix[i*2+1] = high; } } /************************************************************************************** @fn rmv_ghost_key @brief This function process for removing ghost key input parameters @param uint16_t* key_matrix output parameters @param None. @return None. **************************************************************************************/ static void rmv_ghost_key(uint16_t* key_matrix) { uint16_t mix_final = 0; for (uint8_t i=0; i