www.pudn.com > iMx31_WCE600.rar > keypad.c


// 
// Copyright (c) Microsoft Corporation.  All rights reserved. 
// 
// 
// Use of this source code is subject to the terms of the Microsoft end-user 
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT. 
// If you did not accept the terms of the EULA, you are not authorized to use 
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your 
// install media. 
// 
//------------------------------------------------------------------------------ 
// 
// Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved. 
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS 
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT 
// 
//------------------------------------------------------------------------------ 
// 
// File: keypad.c 
// 
// OEM Keypad routines for IPL on Freescale MX31 ADS hardware platform. 
// 
//------------------------------------------------------------------------------ 
#include "bsp.h" 
#include "keys.h" 
 
//------------------------------------------------------------------------------ 
// External Functions 
 
//------------------------------------------------------------------------------ 
// External Variables 
 
//------------------------------------------------------------------------------ 
// Defines 
#define KPP_COLUMN_INUSE        8 
#define KPP_ROW_INUSE           8 
#define KPP_COLUMN_MASK         ((0x1 << KPP_COLUMN_INUSE) -1) 
#define KPP_ROW_MASK            ((0x1 << KPP_ROW_INUSE) - 1) 
 
//------------------------------------------------------------------------------ 
// Types 
// Virtual key to bit mapping 
typedef struct 
{ 
    DWORD dwVk; 
    DWORD dwBit; 
} VKEY_TO_BIT; 
 
//------------------------------------------------------------------------------ 
// Global Variables 
 
//------------------------------------------------------------------------------ 
// Local Variables 
static PCSP_KPP_REGS g_pKPP; 
static PCSP_EPIT_REG g_pEPIT; 
 
//------------------------------------------------------------------------------ 
// Local Functions 
 
// 8x8 keypad matrix 
static UINT8 keypadVK[] = 
{ 
    //column 0 
    0, 
	VK_TSOFT1,      //SW11 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	 
    //column 1 
    0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	 
    //column 2 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
    0, 
	0, 
 
    //column 3 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
 
    //column 4 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	 
    //column 5 
	VK_TSOFT2,      //SW3 
    0, 
	0, 
	0, 
	0, 
	0, 
	0, 
    0, 
	 
    //column 6 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
 
    //column 7 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
	0, 
}; 
 
static const VKEY_TO_BIT sc_rgVkToBit[] =  
{ 
    { VK_TSOFT1,        KEY_TSOFT1 }, 
    { VK_TSOFT2,        KEY_TSOFT2 }, 
}; 
 
//------------------------------------------------------------------------------ 
// 
// Function: EPITInit 
// 
// This function initializes EPIT module for msWait() in bspcmn\waitutils.c 
// 
// Parameters: 
//      None. 
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
static void EPITInit(void) 
{ 
	g_pEPIT = (PCSP_EPIT_REG) OALPAtoUA(CSP_BASE_REG_PA_EPIT1); 
	if (g_pEPIT == NULL) 
    { 
        KITLOutputDebugString("EPITInit: EPIT1 null pointer!\r\n"); 
        return; 
    } 
     
    // Disable EPIT and clear all configuration bits 
    OUTREG32(&g_pEPIT->CR, 0); 
 
    // Assert software reset for the timer 
    OUTREG32(&g_pEPIT->CR, CSP_BITFMASK(EPIT_CR_SWR)); 
 
    // Wait for the software reset to complete 
    while (INREG32(&g_pEPIT->CR) & CSP_BITFMASK(EPIT_CR_SWR)); 
 
    // Enable timer for "free-running" mode where timer rolls 
    // over from 0x00000000 to 0xFFFFFFFF 
    OUTREG32(&g_pEPIT->CR, 
        CSP_BITFVAL(EPIT_CR_EN, EPIT_CR_EN_ENABLE) | 
        CSP_BITFVAL(EPIT_CR_ENMOD, EPIT_CR_ENMOD_RESUME) | 
        CSP_BITFVAL(EPIT_CR_OCIEN, EPIT_CR_OCIEN_DISABLE) | 
        CSP_BITFVAL(EPIT_CR_RLD, EPIT_CR_RLD_ROLLOVER) | 
        CSP_BITFVAL(EPIT_CR_PRESCALAR, 0x20) | // divide by 32 to produce 1 ms tick 
        CSP_BITFVAL(EPIT_CR_SWR, EPIT_CR_SWR_NORESET) | 
        CSP_BITFVAL(EPIT_CR_IOVW, EPIT_CR_IOVW_NOOVR) | 
        CSP_BITFVAL(EPIT_CR_DBGEN, EPIT_CR_DBGEN_ACTIVE) | 
        CSP_BITFVAL(EPIT_CR_WAITEN, EPIT_CR_WAITEN_ENABLE) | 
        CSP_BITFVAL(EPIT_CR_DOZEN, EPIT_CR_DOZEN_ENABLE) | 
        CSP_BITFVAL(EPIT_CR_STOPEN, EPIT_CR_STOPEN_ENABLE) | 
        CSP_BITFVAL(EPIT_CR_OM, EPIT_CR_OM_DICONNECT) | 
        CSP_BITFVAL(EPIT_CR_CLKSRC, EPIT_CR_CLKSRC_CKIL)); // select 32khz clock as source 
} 
 
//------------------------------------------------------------------------------ 
// 
// Function: msStall 
// 
// This function stalls system for time specified in milliseconds. 
// 
// Parameters: 
//      nMilliseconds 
//          [in] The milliseconds to stall system. 
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
static void msStall(unsigned nMilliseconds) 
{ 
    UINT32 startCount, maxCount; 
     
    if (g_pEPIT == NULL) 
    { 
        KITLOutputDebugString("msStall: ERROR - Timer not initialized\r\n"); 
        return; 
    }  	 
     
    startCount = EPIT_CNT_COUNT_MAX - INREG32(&g_pEPIT->CNT); 
    maxCount = startCount + nMilliseconds; 
     
    // wait for nMilliseconds number of ticks 
    while((EPIT_CNT_COUNT_MAX - INREG32(&g_pEPIT->CNT)) < maxCount); 
} 
 
//------------------------------------------------------------------------------ 
// 
// Function: KeypadSetClock 
// 
// This function enables or disables the clock of Keypad module. 
// 
// Parameters: 
//      bEnable 
//          [in] TRUE to enable KPP clock, otherwise disable it. 
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
static void KeypadSetClock(BOOL bEnable) 
{ 
    PCSP_CCM_REGS pCCM = OALPAtoUA(CSP_BASE_REG_PA_CCM); 
 
    if (bEnable) 
    { 
        // Enable KPP clock 
        SETREG32(&pCCM->CGR[1], 0x3 << 20); 
    } 
    else 
    { 
        // Disable KPP clock 
        CLRREG32(&pCCM->CGR[1], 0x3 << 20); 
    } 
} 
 
//------------------------------------------------------------------------------ 
// 
// Function: KeypadInit 
// 
// This function sets up the keypad module for IPL reading ULDR forcing key. 
// 
// Parameters: 
//      None.  
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
void KeypadInit(void) 
{ 
    PCSP_IOMUX_REGS pIOMUX = OALPAtoUA(CSP_BASE_REG_PA_IOMUXC); 
 
    // Configure IOMUX to request KPP pins 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_COL0, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_COL1, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_COL2, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_COL3, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_COL4, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_COL5, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_COL6, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_COL7, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_ROW0, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_ROW1, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_ROW2, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_ROW3, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_ROW4, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_ROW5, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_ROW6, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
    OAL_IOMUX_SET_MUX(pIOMUX, DDK_IOMUX_PIN_KEY_ROW7, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_FUNC); 
 
    // Enable KPP clock 
    KeypadSetClock(TRUE); 
 
    // Map KPP registers 
    g_pKPP = OALPAtoUA(CSP_BASE_REG_PA_KPP); 
 
    // Enable no. of rows in keypad (KRE = 1) 
    // Configure columns as open-drain (KCO = 1) 
    INSREG16BF(&g_pKPP->KPCR, KPP_KPCR_KRE, KPP_ROW_MASK); 
    INSREG16BF(&g_pKPP->KPCR, KPP_KPCR_KCO, KPP_COLUMN_MASK); 
 
    // Write 0's to all columns 
    INSREG16BF(&g_pKPP->KPDR, KPP_KPDR_KCD, 0); 
 
    // Configure rows as input, columns as output 
    INSREG16BF(&g_pKPP->KDDR, KPP_KDDR_KCDD, KPP_COLUMN_MASK); 
    INSREG16BF(&g_pKPP->KDDR, KPP_KDDR_KRDD, 0); 
 
    // Clear KPKD and KPSR_KPKR status flag (w1c) 
    // Clear synchronizer chain - KDSC (w1c) 
    // Enable keypad interrupt - Set KDIE, 
    // clear KRIE (avoid false release events) 
    OUTREG16(&g_pKPP->KPSR, 
        (CSP_BITFVAL(KPP_KPSR_KPP_EN, KPP_KPSR_KPP_EN_ENABLE) | 
        CSP_BITFVAL(KPP_KPSR_KPKD, KPP_KPSR_KPKD_CLEAR) | 
        CSP_BITFVAL(KPP_KPSR_KPKR, KPP_KPSR_KPKR_CLEAR) | 
        CSP_BITFVAL(KPP_KPSR_KDSC, KPP_KPSR_KDSC_CLEAR) | 
        CSP_BITFVAL(KPP_KPSR_KDIE, KPP_KPSR_KDIE_INT_ENABLE) | 
        CSP_BITFVAL(KPP_KPSR_KRIE, KPP_KPSR_KRIE_INT_DISABLE))); 
 
    // Disable KPP clock 
    KeypadSetClock(FALSE); 
 
    // Initialize EPIT for msStall() 
    EPITInit(); 
}     
 
//------------------------------------------------------------------------------ 
// 
// Function: FindBit 
// 
// This function finds the bit mask that corresponds to this virtual key. 
// 
// Parameters: 
//      dwVk 
//          [in] The virtual key. 
// 
//      rgVkToBit 
//          [in] The virtual key to bit mapping table. 
// 
//      cVkToBit 
//          [in] The size of the mapping table. 
// 
//  Returns: 
//      The bit mask that corresponds to this virtual key. 
// 
//------------------------------------------------------------------------------ 
static DWORD FindBit(DWORD dwVk, const VKEY_TO_BIT *rgVkToBit, DWORD cVkToBit)  
{ 
    DWORD dwBit = 0; 
    DWORD dwIdx; 
 
    for (dwIdx = 0; dwIdx < cVkToBit; ++dwIdx) 
    { 
        const VKEY_TO_BIT *pVkToBit = &rgVkToBit[dwIdx]; 
        if (pVkToBit->dwVk == dwVk) 
        { 
            dwBit = pVkToBit->dwBit; 
            break; 
        } 
    } 
 
    return dwBit; 
} 
 
//------------------------------------------------------------------------------ 
// 
// Function: KeypadRead 
// 
// This function returns a bit mask of the keys that are currently down. 
// 
// Parameters: 
//      None.  
// 
//  Returns: 
//      The bit mask of the keys pressed. 
// 
//------------------------------------------------------------------------------ 
DWORD KeypadRead(void) 
{ 
    UINT16 data[2][KPP_COLUMN_INUSE]; 
    DWORD ix; 
    UINT16 ic, ir, ik; 
    DWORD dwBits = 0; 
 
    // Enable KPP clock 
    KeypadSetClock(TRUE); 
 
    //-------------------------------------------------------------- 
    // Read keypad physical state 
    //-------------------------------------------------------------- 
     
    // Write '1' to all columns 
    INSREG16BF(&g_pKPP->KPDR, KPP_KPDR_KCD, KPP_COLUMN_MASK); 
 
    // Configure column as totem-pole outputs 
    INSREG16BF(&g_pKPP->KPCR, KPP_KPCR_KCO, ~KPP_COLUMN_MASK); 
 
    // Configure columns as open drain 
    INSREG16BF(&g_pKPP->KPCR, KPP_KPCR_KCO, KPP_COLUMN_MASK); 
 
    // Read all rows, we have to get same result twice 
    ix = 0; 
    do 
    { 
        // Wait debounce time on second and later meassures 
        if (ix > 0) msStall(20); 
         
        // Read all keypad columns 
        for (ic = 0; ic < KPP_COLUMN_INUSE; ic++) 
        { 
            // Set column bit to zero 
            INSREG16BF(&g_pKPP->KPDR, KPP_KPDR_KCD, ~(1 << ic)); 
             
            // Wait for outputs to settle 
            msStall(1); 
             
            // Get row status 
            data[ix&1][ic] = EXTREG16BF(&g_pKPP->KPDR, KPP_KPDR_KRD); 
        } 
         
        // Write '1' to all columns 
        INSREG16BF(&g_pKPP->KPDR, KPP_KPDR_KCD, KPP_COLUMN_MASK); 
    } while (ix++ < 1 || memcmp(data[0], data[1], sizeof(data[0]) != 0)); 
 
    //-------------------------------------------------------------- 
    // Convert physical state to virtual keys state 
    //-------------------------------------------------------------- 
    for (ic = 0, ik = 0; ic < KPP_COLUMN_INUSE; ic++) 
    { 
        // Find pressed virtual keys 
        if ((data[0][ic] & KPP_ROW_MASK) == KPP_ROW_MASK) 
        { 
            ik += KPP_ROW_INUSE; 
        } 
        else for (ir = 0; ir < KPP_ROW_INUSE; ir++, ik++) 
        { 
            if ((data[0][ic] & (1 << ir)) == 0) 
            { 
                DWORD dwVk = keypadVK[ik]; 
                DWORD dwBit = FindBit(dwVk, sc_rgVkToBit, dimof(sc_rgVkToBit)); 
                dwBits |= dwBit; 
                if (dwBit == 0) 
                    KITLOutputDebugString("KeypadRead: No bit mask for key 0x%x\r\n", dwVk); 
            } 
        } 
    } 
 
    // Disable KPP clock 
    KeypadSetClock(FALSE); 
 
    return dwBits; 
}