FreeCalypso > hg > fc-magnetite
view src/cs/drivers/drv_app/kpd/board/kpd_scan_functions.c @ 108:94170d82d926
configs/l1reconst: rebuild l1_pei.lib from source
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 05 Oct 2016 22:46:22 +0000 |
parents | 945cf7f506b2 |
children | 385841ccb7f8 |
line wrap: on
line source
/** * @file kpd_scan_functions.c * * Implementation of hardware keypad interface functions. * These functions implement the keypad interface with the windows. * * @author Laurent Sollier (l-sollier@ti.com) * @version 0.1 */ /* * History: * * Date Author Modification * ------------------------------------ * 10/10/2001 L Sollier Create * * * (C) Copyright 2001 by Texas Instruments Incorporated, All Rights Reserved */ #include "board.cfg" #include "nucleus.h" /* used for HISR */ #include "kpd/kpd_scan_functions.h" #include "kpd/kpd_cfg.h" #include "kpd/kpd_physical_key_def.h" #include "kpd/kpd_messages_i.h" #include "kpd/kpd_env.h" #include "rvf/rvf_api.h" #include "rvm/rvm_use_id_list.h" #include "rvf/rvf_env.h" #if (CHIPSET == 12) #include "inth/sys_inth.h" #else #include "armio/armio.h" #include "inth/iq.h" #endif #include "memif/mem.h" #if (CHIPSET == 12) #define KBR_CTRL_REG (MEM_KEYBOARD + 0x00) /* KBR control reg */ #define KBR_DEBOUNCING_TIME (MEM_KEYBOARD + 0x02) /* KBR debouncing time reg */ #define KBR_STATE_MACHINE_STATUS (MEM_KEYBOARD + 0x0E) /* KBR state machine status reg */ #define KBR_IN (MEM_KEYBOARD + 0x10) /* KBR inputs (rows) */ #define KBR_OUT (MEM_KEYBOARD + 0x12) /* KBR outputs (columns) */ #endif #if (CHIPSET == 12) #define KP_ROW_IN KBR_IN #define KP_COL_OUT KBR_OUT #else #define KP_ROW_IN ARMIO_KBR_IN #define KP_COL_OUT ARMIO_KBR_OUT #endif #if (BOARD == 7) #define KP_ROWS 5 #define KP_COLS 4 const T_KPD_PHYSICAL_KEY_ID keypad_layout[KP_ROWS][KP_COLS]= { /* Layout of B-Sample */ {KPD_PKEY_SOFT_LEFT, KPD_PKEY_UP, KPD_PKEY_DOWN, KPD_PKEY_SOFT_RIGHT}, {KPD_PKEY_1, KPD_PKEY_2, KPD_PKEY_3, KPD_PKEY_GREEN}, {KPD_PKEY_4, KPD_PKEY_5, KPD_PKEY_6, KPD_PKEY_NULL}, {KPD_PKEY_7, KPD_PKEY_8, KPD_PKEY_9, KPD_PKEY_NULL}, {KPD_PKEY_STAR, KPD_PKEY_0, KPD_PKEY_DIESE,KPD_PKEY_NULL}, }; #elif ((BOARD == 8) || (BOARD == 9)) #define KP_ROWS 5 #define KP_COLS 4 const T_KPD_PHYSICAL_KEY_ID keypad_layout[KP_ROWS][KP_COLS]= { /* Layout of C-Sample */ {KPD_PKEY_UP, KPD_PKEY_GREEN,KPD_PKEY_SOFT_RIGHT,KPD_PKEY_DOWN}, {KPD_PKEY_1, KPD_PKEY_2, KPD_PKEY_3, KPD_PKEY_SOFT_LEFT}, {KPD_PKEY_4, KPD_PKEY_5, KPD_PKEY_6, KPD_PKEY_NULL}, {KPD_PKEY_7, KPD_PKEY_8, KPD_PKEY_9, KPD_PKEY_NULL}, {KPD_PKEY_STAR, KPD_PKEY_0, KPD_PKEY_DIESE, KPD_PKEY_NULL}, }; #elif ((BOARD == 40) || (BOARD == 41) || (BOARD == 42) || (BOARD == 43)) #define KP_ROWS 5 #define KP_COLS 5 const T_KPD_PHYSICAL_KEY_ID keypad_layout[KP_ROWS][KP_COLS]= { /* Layout of D-Sample and E-Sample */ {KPD_PKEY_GREEN, KPD_PKEY_VOL_DOWN, KPD_PKEY_VOL_UP,KPD_PKEY_SOFT_LEFT, KPD_PKEY_LEFT}, {KPD_PKEY_1, KPD_PKEY_2, KPD_PKEY_3, KPD_PKEY_REC, KPD_PKEY_RIGHT}, {KPD_PKEY_4, KPD_PKEY_5, KPD_PKEY_6, KPD_PKEY_SOFT_RIGHT, KPD_PKEY_UP}, {KPD_PKEY_7, KPD_PKEY_8, KPD_PKEY_9, KPD_PKEY_NULL, KPD_PKEY_DOWN}, {KPD_PKEY_STAR, KPD_PKEY_0, KPD_PKEY_DIESE, KPD_PKEY_NULL, KPD_PKEY_NAV_CENTER}, }; #endif #define KP_ACTIVATE(i) (~(1<<i)) #define KP_IS_ACTIVE(rows,i) ((rows & (1<<i)) == 0) #define KP_ALL_OFF 0x1F #define KP_ALL_ON 0 extern T_KPD_ENV_CTRL_BLK* kpd_env_ctrl_blk; typedef struct { NU_HISR hisr; char hisr_stack[512]; } T_HISR_INFOS; static T_HISR_INFOS hisr_infos = {0}; /** * @name Functions implementation * */ /*@{*/ #if (CHIPSET == 12) /** kpd_init_ctrl_reg : Initialize the Control register */ void kpd_init_ctrl_reg(const UINT8 software_nreset, const T_KPD_Nsoftware_mode nsoftware_mode, const T_KPD_PTV ptv, const T_KPD_EnableDetection long_key_process_en, const T_KPD_EnableDetection time_out_empty_en, const T_KPD_EnableDetection time_out_long_key_en, const T_KPD_EnableDetection repeat_mode_en) { volatile UINT16 status_reg; status_reg = *(volatile UINT16*) KBR_STATE_MACHINE_STATUS; if ( (status_reg != KPD_TEST_TIMER_DEBOUNCING) && (status_reg != KPD_TEST_TIMER_LONG_KEY) && (status_reg != KPD_TEST_TIMER_TIME_OUT) && (status_reg != KPD_TEST_TIMER_REPEAT_KEY) ) { /* The PTV can be programmed since the timer is not running */ *(volatile UINT16*) KBR_CTRL_REG = (software_nreset | nsoftware_mode << 1 | ptv << 2 | long_key_process_en << 5 | time_out_empty_en << 6 | time_out_long_key_en << 7 | repeat_mode_en << 8); } else { /* The PTV must not be programmed when the timer is running */ SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 0, 1, software_nreset); SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 1, 1, nsoftware_mode); SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 5, 1, long_key_process_en); SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 6, 1, time_out_empty_en); SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 7, 1, time_out_long_key_en); SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 8, 1, repeat_mode_en); } } /** kpd_software_reset : reset software */ void kpd_software_reset(void) { volatile UINT16 mem_reg; mem_reg = (*(volatile UINT16*) KBR_CTRL_REG) & 0xFFFE; *(volatile UINT16*) KBR_CTRL_REG = mem_reg; } /** kpd_set_debouncing_time : Set the desired value of debouncing time */ void kpd_set_debouncing_time(const UINT8 debouncing_time) { *(volatile UINT16*) KBR_DEBOUNCING_TIME = debouncing_time; } #endif /* #if (CHIPSET == 12) */ /** * function: hisr_entry */ static void hisr_entry(void) { T_RVF_MB_STATUS mb_status; T_KPD_KEY_PRESSED_MSG* msg_key_pressed; T_KPD_PHYSICAL_KEY_ID key; /* Reserve memory for message */ mb_status = rvf_get_buf (kpd_env_ctrl_blk->prim_id, sizeof(T_KPD_KEY_PRESSED_MSG), (void **) &msg_key_pressed); if (mb_status != RVF_RED) /* Memory allocation success */ { /* Fill the message */ msg_key_pressed->hdr.msg_id = KPD_KEY_PRESSED_MSG; /* Virtual key id is not yet known */ msg_key_pressed->value = KPD_PKEY_NULL; if (mb_status == RVF_GREEN) msg_key_pressed->key_to_process = TRUE; else msg_key_pressed->key_to_process = FALSE; /* Send message to the keypad task */ rvf_send_msg(kpd_env_ctrl_blk->addr_id, msg_key_pressed); } else { KPD_SEND_TRACE("KPD: Not enough memory to send new key pressed", RV_TRACE_LEVEL_ERROR); kpd_acknowledge_key_pressed(); } } /** * function: kpd_initialize_keypad_hardware */ void kpd_initialize_keypad_hardware(void) { /* HISR creation */ NU_Create_HISR(&hisr_infos.hisr, "KPD_HISR", hisr_entry, 2, hisr_infos.hisr_stack, sizeof(hisr_infos.hisr_stack)); #if (CHIPSET == 12) /* Init control register ; hardware decoding */ kpd_init_ctrl_reg(1, HARDWARE_DECODING, KPD_CLK_DIV32, KPD_DETECTION_DISABLED, KPD_DETECTION_DISABLED, KPD_DETECTION_DISABLED, KPD_DETECTION_DISABLED); /* Debouncing time = 64ms */ kpd_set_debouncing_time(0x3F); #endif /* Activate all outputs */ *(volatile UINT16*) KP_COL_OUT = KP_ALL_ON; /* Unmask keypad interrupt */ #if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41)) AI_UnmaskIT (ARMIO_MASKIT_KBD); #elif (CHIPSET == 12) F_INTH_ENABLE_ONE_IT(C_INTH_KEYBOARD_IT); #else IQ_Unmask (IQ_ARMIO); #endif } /** * function: kpd_key_handler */ void kpd_key_handler(void) { /* If keypad is not started, return immediately */ if ( (kpd_env_ctrl_blk == 0) || (kpd_env_ctrl_blk->swe_is_initialized == FALSE) ) { kpd_acknowledge_key_pressed(); } else { /* Mask keypad interrupt until key is released */ #if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41)) AI_MaskIT (ARMIO_MASKIT_KBD); #elif (CHIPSET == 12) F_INTH_DISABLE_ONE_IT(C_INTH_KEYBOARD_IT); #else IQ_Mask(IQ_ARMIO); #endif /* Activate HISR to process the key event */ NU_Activate_HISR(&hisr_infos.hisr); } } /** * function: kpd_acknowledge_key_pressed */ void kpd_acknowledge_key_pressed(void) { /* Unmask keypad interrupt */ #if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41)) AI_UnmaskIT (ARMIO_MASKIT_KBD); #elif (CHIPSET == 12) F_INTH_ENABLE_ONE_IT(C_INTH_KEYBOARD_IT); #else IQ_Unmask (IQ_ARMIO); #endif } /* * delay * * Wait a while to let bus settle * Magic value found by trial and error * */ static void delay(void) { volatile int i; for (i=0;i<10;i++) ; } /** * function: kpd_scan_keypad */ T_KPD_PHYSICAL_KEY_ID kpd_scan_keypad(void) { int row, col; volatile UINT16 rows; /* Activate all columns to find if any row is active */ *(volatile UINT16*) KP_COL_OUT = KP_ALL_ON; delay(); rows = (*(volatile UINT16*) KP_ROW_IN) & 0x1F; if (rows == KP_ALL_OFF) return KPD_PKEY_NULL; /* Deactivate all columns */ *(volatile UINT16*) KP_COL_OUT = KP_ALL_OFF; /* Activate 1 column at a time */ for (col = 0; col < KP_COLS; col++) { *(volatile UINT16*) KP_COL_OUT = (KP_ACTIVATE(col)); delay(); /* Find which row is active */ rows = (*(volatile UINT16*) KP_ROW_IN) & 0x1F; if (rows != KP_ALL_OFF) { for (row = 0; row < KP_ROWS; row++) { /* first active row */ if ( KP_IS_ACTIVE(rows,row)) { /* Reactivate all columns */ *(volatile UINT16*) KP_COL_OUT = KP_ALL_ON; /* DO NOT remove this comment. It allows to simply define the link physical layout and physical key Id (for a new keypad) */ //KPD_SEND_TRACE_PARAM("KPD: Keypad layout check ", keypad_layout[row][col], RV_TRACE_LEVEL_DEBUG_HIGH); return keypad_layout[row][col]; } } } } /* No row was active - Reactivate all columns and return */ *(volatile UINT16*) KP_COL_OUT = KP_ALL_ON; return KPD_PKEY_NULL; } /*@}*/