📄 bspkeypad.cpp
字号:
0, // Scan Code 0xE05B
0, // Scan Code 0xE05C
0, // Scan Code 0xE05D
0, // Scan Code 0xE05E
0, // Scan Code 0xE05F
0, // Scan Code 0xE060
0, // Scan Code 0xE061
0, // Scan Code 0xE062
0, // Scan Code 0xE063
0, // Scan Code 0xE064
0, // Scan Code 0xE065
0, // Scan Code 0xE066
0, // Scan Code 0xE067
0, // Scan Code 0xE068
VK_END, // Scan Code 0xE069
0, // Scan Code 0xE06A
VK_LEFT, // Scan Code 0xE06B
VK_HOME, // Scan Code 0xE06C
0, // Scan Code 0xE06D
0, // Scan Code 0xE06E
0, // Scan Code 0xE06F
VK_INSERT, // Scan Code 0xE070
VK_DELETE, // Scan Code 0xE071
VK_DOWN, // Scan Code 0xE072
0, // Scan Code 0xE073
VK_RIGHT, // Scan Code 0xE074
VK_UP, // Scan Code 0xE075
0, // Scan Code 0xE076
0, // Scan Code 0xE077
0, // Scan Code 0xE078
0, // Scan Code 0xE079
VK_NEXT, // Scan Code 0xE07A
0, // Scan Code 0xE07B
VK_SNAPSHOT, // Scan Code 0xE07C
VK_PRIOR, // Scan Code 0xE07D
VK_CANCEL, // Scan Code 0xE07E
0, // Scan Code 0xE07F
};
static ScanCodeToVKeyData scvkEngUS =
{
0,
ScanCodeTableFirst,
ScanCodeTableLast,
ScanCodeToVKeyTable
};
static ScanCodeToVKeyData scvkE0EngUS =
{
0xE000,
E0ScanCodeTableFirst,
E0ScanCodeTableLast,
E0ScanCodeToVKeyTable
};
static ScanCodeToVKeyData *rgscvkKPPEngUSTables[] =
{
&scvkEngUS, &scvkE0EngUS
};
// There is currently no Key Remapping being performed.
// If key remapping is needed, this structure definition
// will need to be moved down below the Remap function.
static DEVICE_LAYOUT dlKPPEngUs =
{
sizeof(DEVICE_LAYOUT),
KPP_PDD,
rgscvkKPPEngUSTables,
dim(rgscvkKPPEngUSTables),
NULL, //KPPUsRemapVKey,
};
//------------------------------------------------------------------------------
// Local Functions
BOOL BSPKppSetClockGatingMode(BOOL startClocks);
static UINT KppScanSequence(UINT32 rguiScanCode[16], BOOL rgfKeyUp[16], BOOL allowSysCalls);
static void KppRestoreRegState();
static void KppSaveRegState();
static void KppBusyWait(DWORD waitTime);
//------------------------------------------------------------------------------
//
// Function: KPPUsRemapVKey
//
// Remapping function for the keypad. Called from the layout manager.
// Returns the number of remapped events placed in pRmpKbdEvents
// Call with pRmpKbdEvents == NULL anc cMaxRmpKbdEvents == 0 to get the
// maximum size necessary for pRmpKbdEvents buffer.
//
// Parameters:
// pKbdEvents -
// [in] List of events to remap.
//
// cKbdEvents -
// [in] Count of events in pKbdEvents
//
// pRmpKbdEvents -
// [out] Buffer where remapped events will be placed
//
// cMaxRmpKbdEvents -
// [in] Maximum number of remapped events
//
// Returns:
// The number of remapped events.
//
//------------------------------------------------------------------------------
static UINT WINAPI KPPUsRemapVKey(
const KEYBD_EVENT *pKbdEvents,
UINT cKbdEvents,
KEYBD_EVENT *pRmpKbdEvents,
UINT cMaxRmpKbdEvents
)
{
static BOOL fFnDown = FALSE;
UINT cRmpKbdEvents = 0;
SETFNAME(_T("KPPUsRemapVKey"));
DEBUGMSG(ZONE_FUNCTION, (TEXT("++%s\r\n"), pszFname));
if (pRmpKbdEvents == NULL)
{
// 1 to 1 mapping
DEBUGCHK(cMaxRmpKbdEvents == 0);
return cKbdEvents;
}
DEBUGCHK(pKbdEvents != NULL);
if (cMaxRmpKbdEvents < cKbdEvents)
{
DEBUGMSG(ZONE_ERROR, (_T("%s: Buffer is not large enough!\r\n"),
pszFname));
return 0;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("--%s\r\n"), pszFname));
return cRmpKbdEvents;
}
//------------------------------------------------------------------------------
//
// Function: KPPLayout
//
// This function initializes the device layout for the EVB keypad.
//
// Parameters:
// None.
//
// Returns:
// TRUE if success, FALSE if failure.
//
//------------------------------------------------------------------------------
extern "C" BOOL KPPLayout(PDEVICE_LAYOUT pDeviceLayout)
{
BOOL fRet = FALSE;
DEBUGCHK(pDeviceLayout != NULL);
if (pDeviceLayout->dwSize != sizeof(DEVICE_LAYOUT))
{
RETAILMSG(1, (_T("KPPLayout: data structure size mismatch\r\n")));
goto Leave;
}
// Make sure that the Sc->Vk tables are the sizes that we expect
DEBUGCHK(dim(ScanCodeToVKeyTable) == (1 + ScanCodeTableLast - ScanCodeTableFirst));
*pDeviceLayout = dlKPPEngUs;
fRet = TRUE;
Leave:
return fRet;
}
#ifdef DEBUG
// Verify function declaration against the typedef.
static PFN_DEVICE_LAYOUT_ENTRY v_pfnDeviceLayout = KPPLayout;
#endif
//------------------------------------------------------------------------------
//
// Function: BSPKppRegInit
//
// Initializes the keypad port registers.
//
// Parameters:
// None.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void BSPKppRegInit()
{
KPP_FUNCTION_ENTRY();
// Enable KPP clocks to access KPP registers
BSPKppSetClockGatingMode(TRUE);
// Enable no. of rows in keypad (KRE = 1)
// Configure columns as open-drain (KCO = 1)
INSREG16(&g_pKPP->KPCR, CSP_BITFMASK(KPP_KPCR_KRE),
CSP_BITFVAL(KPP_KPCR_KRE, KPP_ROW_MASK));
INSREG16(&g_pKPP->KPCR, CSP_BITFMASK(KPP_KPCR_KCO),
CSP_BITFVAL(KPP_KPCR_KRE, KPP_COLUMN_MASK));
// Write 0's to all columns
INSREG16(&g_pKPP->KPDR, CSP_BITFMASK(KPP_KPDR_KCD),
CSP_BITFVAL(KPP_KPDR_KCD, 0));
// Configure rows as input, columns as output
INSREG16(&g_pKPP->KDDR, CSP_BITFMASK(KPP_KDDR_KCDD),
CSP_BITFVAL(KPP_KDDR_KCDD, KPP_COLUMN_MASK));
INSREG16(&g_pKPP->KDDR, CSP_BITFMASK(KPP_KDDR_KRDD),
CSP_BITFVAL(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)));
DEBUGMSG(ZONE_PDD, (TEXT("End of Init method - ctrl: %x status: %x direction: %x data: %x\r\n"),
g_pKPP->KPCR, g_pKPP->KPSR, g_pKPP->KDDR, g_pKPP->KPDR));
// Disable KPP clocks for Power Management
BSPKppSetClockGatingMode(FALSE);
KPP_FUNCTION_EXIT();
}
//------------------------------------------------------------------------------
//
// Function: BSPKPPGetScanCodes
//
// This function gets the scan codes and key events from the KPP.
//
// Parameters:
// rguiScanCode[16] -
// [out] An array of scan codes for each key event detected.
//
// rgfKeyUp[16] -
// [out] An array of booleans telling, for each key event,
// whether the key has gone up or down.
//
// Returns:
// The number of key events.
//
//------------------------------------------------------------------------------
UINT BSPKPPGetScanCodes(UINT32 rguiScanCode[16], BOOL rgfKeyUp[16])
{
UINT eventCount;
KPP_FUNCTION_ENTRY();
// Enable KPP clocks to access registers
// during key scan sequence
BSPKppSetClockGatingMode(TRUE);
KppSaveRegState();
eventCount = KppScanSequence(rguiScanCode, rgfKeyUp, TRUE);
if (g_SysSuspend)
{
KppRestoreRegState();
g_SysSuspend = FALSE;
// Call scan sequence again with restored KPP register
// state to assure that we read the correct scan codes.
eventCount = KppScanSequence(rguiScanCode, rgfKeyUp, TRUE);
}
// Disable KPP clocks for Power Management
BSPKppSetClockGatingMode(FALSE);
// Wait, so that we do not immediately trigger another keypad
// interrupt upon completing the scan sequence and returning
// the scan codes.
Sleep(9);
KPP_FUNCTION_EXIT();
return eventCount;
}
//------------------------------------------------------------------------------
//
// Function: KppScanSequence
//
// This function scans the keypad matrix, compiling a list of key events.
//
// Parameters:
// rguiScanCode[16] -
// [out] An array of scan codes for each key event detected.
//
// rgfKeyUp[16] -
// [out] An array of booleans telling, for each key event,
// whether the key has gone up or down.
//
// allowSysCalls -
// [in] A boolean variable telling us whether or not we can
// make system calls. This is needed for the case when we are
// entering suspend and cannot make system calls.
//
// Returns:
// The number of key events.
//
//------------------------------------------------------------------------------
static UINT KppScanSequence(UINT32 rguiScanCode[16], BOOL rgfKeyUp[16], BOOL allowSysCalls)
{
static BOOL notInitialized = TRUE; // Set to false after initialization.
static CRITICAL_SECTION g_hKppLock;
UINT16 tempKPSR; // KPSR value read at start of scan sequence
UINT16 kpsrWrVal = 0;
UINT8 iRowMask;
UINT8 iColMask;
UINT8 iCol;
UINT8 iRow;
UINT8 evCnt = 0;
UINT8 index;
UINT8 rowData;
BOOL isKeyDown = FALSE;
KPP_FUNCTION_ENTRY();
// Initialize variables the first time this method is called
if (notInitialized)
{
// Do not execute initialization again
notInitialized = FALSE;
// create KPP critical section
InitializeCriticalSection(&g_hKppLock);
// Initialise key status to all release '1' and clear key down status.
memset(kppStatus, KPP_ROW_MASK, sizeof(kppStatus));
memset(keyDown, 0, sizeof(keyDown));
memset(prevDownTime, 0, sizeof(prevDownTime));
memset(keyDownSent, 0, sizeof(keyDownSent));
}
if (allowSysCalls)
{
EnterCriticalSection(&g_hKppLock);
}
// Read keypad status register
tempKPSR = INREG16(&g_pKPP->KPSR);
DEBUGMSG(ZONE_PDD, (TEXT("Before scan, tempKPSR 0x%04x, KPSR 0x%04x. \r\n"),
tempKPSR, INREG16(&g_pKPP->KPSR)));
// Disable interrupts while processing.
INSREG16(&g_pKPP->KPSR, CSP_BITFMASK(KPP_KPSR_KDIE),
CSP_BITFVAL(KPP_KPSR_KDIE, KPP_KPSR_KDIE_INT_DISABLE));
INSREG16(&g_pKPP->KPSR, CSP_BITFMASK(KPP_KPSR_KRIE),
CSP_BITFVAL(KPP_KPSR_KRIE, KPP_KPSR_KRIE_INT_DISABLE));
if(CSP_BITFEXT(tempKPSR, KPP_KPSR_KPKD) && CSP_BITFEXT(tempKPSR, KPP_KPSR_KDIE))
{
// At least 1 key depressed
DEBUGMSG(ZONE_PDD,
(TEXT("Depress interrupt, KPSR 0x%04x. \r\n"), tempKPSR));
// Write '1' to all columns
INSREG16(&g_pKPP->KPDR, CSP_BITFMASK(KPP_KPDR_KCD),
CSP_BITFVAL(KPP_KPDR_KCD, KPP_COLUMN_MASK));
// Configure column as totem-pole outputs
INSREG16(&g_pKPP->KPCR, CSP_BITFMASK(KPP_KPCR_KCO),
CSP_BITFVAL(KPP_KPCR_KCO, ~KPP_COLUMN_MASK));
// Configure columns as open drain
INSREG16(&g_pKPP->KPCR, CSP_BITFMASK(KPP_KPCR_KCO),
CSP_BITFVAL(KPP_KPCR_KCO, KPP_COLUMN_MASK));
// Scan key map for changes
for(iCol = 0, iColMask = 1; iCol < KPP_COLUMN_INUSE && !g_SysSuspend; iCol++, iColMask <<= 1)
{
// Write '0' for this column.
INSREG16(&g_pKPP->KPDR, CSP_BITFMASK(KPP_KPDR_KCD),
CSP_BITFVAL(KPP_KPDR_KCD, ~iColMask));
// Wait required to allow row outputs to propagate
if (allowSysCalls)
{
Sleep(1);
}
else
{
KppBusyWait(1);
}
// Get current key status & handle accordingly
rowData = KPP_ROW_MASK & EXTREG16(&g_pKPP->KPDR,
CSP_BITFMASK(KPP_KPDR_KRD), KPP_KPDR_KRD_LSH);
for(iRow = 0, iRowMask = 1; iRow < KPP_ROW_INUSE && !g_SysSuspend; iRow++, iRowMask <<= 1)
{
if((rowData & iRowMask) ^ (kppStatus[iCol] & iRowMask))
{
// Key status changed. Send event accordingly.
index = iCol * KPP_ROW_INUSE + iRow;
if((rowData & iRowMask))
{
// Key status changed to released.
// Handle briefly pressed keys.
if(!(kppStatus[iCol] & iRowMask) && !(keyDown[iCol] & iRowMask))
{
// Key depressed very briefly, less than 1 debounce period.
DEBUGMSG(ZONE_PDD, (TEXT("Changed: depressed < 1 period.\r\n")));
}
else
{
rguiScanCode[evCnt] = IntermediateScanCode[index];
rgfKeyUp[evCnt] = TRUE;
evCnt++;
keyDown[iCol] &= ~iRowMask;
keyDownSent[index] = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -