⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keypad.c

📁 keypad source code for samsung SC2410
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -