📄 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.
//
/*
* Todo:
* debounce is not completed
* not all keypads are programmed.
*/
#include <windows.h>
#include <s3c2410x.h>
#include <nkintr.h>
UINT32 g_KeypadIrq[4] = {IRQ_EINT0, // for K10, K11, K12, K16
IRQ_EINT2, // for K7, K8, K9, K15
IRQ_EINT11, // EINT11 for K4, K5, K6, K14
IRQ_EINT19 // EINT19 for K1, K2, K3, K13
};
UINT32 g_KeypadSysIntr[4] = {SYSINTR_UNDEFINED,
SYSINTR_UNDEFINED,
SYSINTR_UNDEFINED,
SYSINTR_UNDEFINED};
static HANDLE g_hKeypadIntrEvent[4];
static volatile S3C2410X_IOPORT_REG *v_pIOPregs;
enum {KSCAN0 = 1, KSCAN1 = 2, KSCAN2 = 4, KSCAN3 = 8};
BOOL WINAPI
DllEntry(HANDLE hInstDll,
DWORD dwReason,
LPVOID lpvReserved)
{
switch ( dwReason )
{
case DLL_PROCESS_ATTACH:
RETAILMSG(1, (TEXT("Keypad : DLL_PROCESS_ATTACH\r\n")));
DisableThreadLibraryCalls((HMODULE) hInstDll);
break;
}
return (TRUE);
}
static BOOL
KPD_InitializeAddresses(void)
{
BOOL RetValue = TRUE;
RETAILMSG(1, (TEXT("+ KPD_initalizeAddress \r\n")));
/* IO Register Allocation */
v_pIOPregs = (volatile S3C2410X_IOPORT_REG *)VirtualAlloc(0,
sizeof(S3C2410X_IOPORT_REG),
MEM_RESERVE,
PAGE_NOACCESS);
if (v_pIOPregs == NULL) {
ERRORMSG(1,(TEXT("KPD_initalizeAddress : VirtualAlloc failed!\r\n")));
RetValue = FALSE;
} else {
if (!VirtualCopy((PVOID)v_pIOPregs,
(PVOID)(S3C2410X_BASE_REG_PA_IOPORT >> 8),
sizeof(S3C2410X_IOPORT_REG),
PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) {
RETAILMSG(1, (TEXT("KPD_initalizeAddress : VirtualCopy failed!\r\n")));
RetValue = FALSE;
}
}
if (!RetValue) {
RETAILMSG (1, (TEXT("KPD_initalizeAddress : Fail!!\r\n") ));
if (v_pIOPregs)
VirtualFree((PVOID) v_pIOPregs,
0,
MEM_RELEASE);
v_pIOPregs = NULL;
} else
RETAILMSG (1, (TEXT("KPD_initalizeAddress Success\r\n")));
RETAILMSG(1, (TEXT("- KPD_initalizeAddress \r\n")));
return(RetValue);
}
static void
KPD_EnableInterrupt(void)
{
v_pIOPregs->GPFCON &= ~(0x3 << 0); /* clear GPF0 */
v_pIOPregs->GPFCON |= (0x2 << 0); /* program GPF0 as EINT0 */
v_pIOPregs->EXTINT0 &= ~(0x7 << 0); /* clear EINT0 */
v_pIOPregs->EXTINT0 |= (0x2 << 0); /* Configure EINT0 as falling edge triggered 01x */
v_pIOPregs->GPFCON &= ~(0x3 << 4); /* clear GPF2 */
v_pIOPregs->GPFCON |= (0x2 << 4); /* program GPF2 as EINT2 */
v_pIOPregs->EXTINT0 &= ~(0x7 << 8); /* clear EINT2 */
v_pIOPregs->EXTINT0 |= (0x2 << 8); /* Configure EINT2 as falling edge triggered 01x */
v_pIOPregs->GPGCON &= ~(0x3 << 6); /* clear GPG3 */
v_pIOPregs->GPGCON |= (0x2 << 6); /* program GPG3 as EINT11 */
v_pIOPregs->EXTINT1 &= ~(0x7 << 12); /* clear EINT11 */
v_pIOPregs->EXTINT1 |= (0x2 << 12); /* Configure EINT11 as falling edge triggered 01x */
v_pIOPregs->GPGCON &= ~(0x3 << 22); /* clear GPG11 */
v_pIOPregs->GPGCON |= (0x2 << 22); /* program GPG11 as EINT19 */
v_pIOPregs->EXTINT2 &= ~(0x7 << 12); /* clear EINT19 */
v_pIOPregs->EXTINT2 |= (0x2 << 12); /* Configure EINT19 as falling edge triggered 01x */
}
static void
KPD_SetKscanLow(void)
{
v_pIOPregs->GPECON &= ~(0x3 << 22); /* clear GPE11 */
v_pIOPregs->GPECON |= (0x1 << 22); /* Set GPE11 as output */
v_pIOPregs->GPEDAT &= ~(0x1 << 11); /* set GPE11 as 0 */
v_pIOPregs->GPGCON &= ~(0x3 << 12); /* clear GPG6 */
v_pIOPregs->GPGCON |= (0x1 << 12); /* set GPG6 as output */
v_pIOPregs->GPGDAT &= ~(0x1 << 6); /* set GPG6 as 0 */
v_pIOPregs->GPECON &= ~(0x3 << 26); /* clear GPE13 */
v_pIOPregs->GPECON |= (0x1 << 26); /* set GPE13 as output */
v_pIOPregs->GPEDAT &= ~(0x1 << 13); /* set GPE13 as 0 */
v_pIOPregs->GPGCON &= ~(0x3 << 4); /* clear GPG2 */
v_pIOPregs->GPGCON |= (0x1 << 4); /* set GPG2 as output */
v_pIOPregs->GPGDAT &= ~(0x1 << 2); /* set GPG2 as 0 */
}
static int
KPD_ReadKscan(void)
{
int ret = 0;
v_pIOPregs->GPECON &= ~(0x3 << 22); /* clear GPE11 for read*/
((v_pIOPregs->GPEDAT >> 11) & 0x1)? (ret += KSCAN0) : (ret); /* read GPE11 */
v_pIOPregs->GPGCON &= ~(0x3 << 12); /* clear GPG6 */
((v_pIOPregs->GPGDAT >> 6) & 0x1)? (ret += KSCAN1) : (ret); /* set GPG6 */
v_pIOPregs->GPECON &= ~(0x3 << 26); /* clear GPE13 */
((v_pIOPregs->GPEDAT >> 13) & 0x1)? (ret += KSCAN2) : (ret); /* set GPE13 */
v_pIOPregs->GPGCON &= ~(0x3 << 4); /* clear GPG2 */
((v_pIOPregs->GPGDAT >> 2) & 0x1)? (ret += KSCAN3) : (ret); /* set GPG2 as 0 */
return ret;
}
static int
KPD_DebounceReadKscan(void)
{
int ret = 0;
ret = KPD_ReadKscan();
Sleep(50); //sleep for 20ms
if (ret != KPD_ReadKscan())
return 0;
else
return ret;
}
static BOOL
KPD_IsPushed(VOID)
{
RETAILMSG(1, (TEXT("KPD_IsPushed : keypad is pushed\r\n")));
return TRUE;
}
DWORD
KPD_IntrThread0(PVOID pArg)
{
RETAILMSG(1, (TEXT("+ KPD_IntrThread0\r\n")));
KPD_InitializeAddresses();
// KPD_SetKscanLow();
KPD_EnableInterrupt();
g_hKeypadIntrEvent[0] = CreateEvent(NULL,
FALSE, //the system automatically resets the state to nonsignaled after a single waiting thread has been released
FALSE, //the initial state of the event object. If TRUE, the initial state is signaled; otherwise, it is nonsignaled.
NULL);
if (g_hKeypadIntrEvent[0] == NULL) {
RETAILMSG(1, (TEXT("KPD_IntrThread0 : CreateEvent return failure\r\n")));
return FALSE;
}
// Request a SYSINTR value from the OAL.
//
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, // [in] I/O control code
&g_KeypadIrq[0], // [out] Pointer to a buffer that contains the data required to perform the operation
sizeof(UINT32), // [in] Size, in bytes, of the buffer pointed to by lpInBuf.
&g_KeypadSysIntr[0], // [out] Pointer to a buffer that receives the output data for the operation
sizeof(UINT32), // [in] size of the buffer pointed to by g_KeypadSysIntr
NULL)) { // an operation produces no output data
RETAILMSG(1, (TEXT("KPD_IntrThread0 : Failed to request sysintr value for power button interrupt.\r\n")));
return 0;
}
RETAILMSG(1,(TEXT("KPD_IntrThread0 : Mapped Irq 0x%x to SysIntr 0x%x.\r\n"), g_KeypadIrq[0], g_KeypadSysIntr[0]));
if (!(InterruptInitialize(g_KeypadSysIntr[0], // Interrupt identifier to be associated with this interrupt service thread (IST)
g_hKeypadIntrEvent[0], // Event to be signaled when the interrupt is triggered
0,
0))) {
RETAILMSG(1, (TEXT("KPD_IntrThread0 : Interrupt initialize failed.\r\n")));
return 0;
}
while (1)
{
KPD_SetKscanLow();
WaitForSingleObject(g_hKeypadIntrEvent[0], INFINITE);
// KPD_IsPushed();
switch (KPD_DebounceReadKscan()) {
case KSCAN0:
RETAILMSG(1, (TEXT("keypad K10 is pressed\r\n")));
break;
case KSCAN1:
RETAILMSG(1, (TEXT("keypad K11 is pressed\r\n")));
break;
case KSCAN2:
RETAILMSG(1, (TEXT("keypad K12 is pressed\r\n")));
break;
case KSCAN3:
RETAILMSG(1, (TEXT("keypad K16 is pressed\r\n")));
break;
default:
//RETAILMSG(1, (TEXT("unknown keypad is pressed\r\n")));
break;
}
InterruptDone(g_KeypadSysIntr[0]);
}
}
DWORD
KPD_IntrThread1(PVOID pArg)
{
RETAILMSG(1, (TEXT("+ KPD_IntrThread1\r\n")));
KPD_InitializeAddresses();
// KPD_SetKscanLow();
KPD_EnableInterrupt();
g_hKeypadIntrEvent[1] = CreateEvent(NULL,
FALSE, //the system automatically resets the state to nonsignaled after a single waiting thread has been released
FALSE, //the initial state of the event object. If TRUE, the initial state is signaled; otherwise, it is nonsignaled.
NULL);
if (g_hKeypadIntrEvent[1] == NULL) {
RETAILMSG(1, (TEXT("KPD_IntrThread1 : CreateEvent return failure\r\n")));
return FALSE;
}
// Request a SYSINTR value from the OAL.
//
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, // [in] I/O control code
&g_KeypadIrq[1], // [out] Pointer to a buffer that contains the data required to perform the operation
sizeof(UINT32), // [in] Size, in bytes, of the buffer pointed to by lpInBuf.
&g_KeypadSysIntr[1], // [out] Pointer to a buffer that receives the output data for the operation
sizeof(UINT32), // [in] size of the buffer pointed to by g_KeypadSysIntr
NULL)) { // an operation produces no output data
RETAILMSG(1, (TEXT("KPD_IntrThread1 : Failed to request sysintr value for power button interrupt.\r\n")));
return 0;
}
RETAILMSG(1,(TEXT("KPD_IntrThread1 : Mapped Irq 0x%x to SysIntr 0x%x.\r\n"), g_KeypadIrq[1], g_KeypadSysIntr[1]));
if (!(InterruptInitialize(g_KeypadSysIntr[1], // Interrupt identifier to be associated with this interrupt service thread (IST)
g_hKeypadIntrEvent[1], // Event to be signaled when the interrupt is triggered
0,
0))) {
RETAILMSG(1, (TEXT("KPD_IntrThread1 : Interrupt initialize failed.\r\n")));
return 0;
}
while (1)
{
KPD_SetKscanLow();
WaitForSingleObject(g_hKeypadIntrEvent[1], INFINITE);
// KPD_IsPushed();
switch (KPD_DebounceReadKscan()) {
case KSCAN0:
RETAILMSG(1, (TEXT("keypad K7 is pressed\r\n")));
break;
case KSCAN1:
RETAILMSG(1, (TEXT("keypad K8 is pressed\r\n")));
break;
case KSCAN2:
RETAILMSG(1, (TEXT("keypad K9 is pressed\r\n")));
break;
case KSCAN3:
RETAILMSG(1, (TEXT("keypad K15 is pressed\r\n")));
break;
default:
//RETAILMSG(1, (TEXT("unknown keypad is pressed\r\n")));
break;
}
InterruptDone(g_KeypadSysIntr[1]);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -