FreeCalypso > hg > leo2moko-debug
diff chipsetsw/drivers/drv_app/kpd/board/kpd_scan_functions.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chipsetsw/drivers/drv_app/kpd/board/kpd_scan_functions.c Mon Jun 01 03:24:05 2015 +0000 @@ -0,0 +1,375 @@ +/** + * @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; +} + + +/*@}*/