📄 keypad.cpp
字号:
// Disable key release interrupts and re-enable key depress interrupts.
gpKpp->KPSR |= (bmKPSR_KDIE | bmKPSR_KPKR | bmKPSR_KPKD | bmKPSR_KDSC);
}
else
{
DEBUGMSG(KEY_ERROR_MSG|KEY_DEBUG_MSG, (TEXT("\r\nKEY_IntrThread: undesired interrupt! KPSR 0x%04x.\r\n"), tempKPSR));
gpKpp->KPSR |= (tempKPSR | bmKPSR_KPKD | bmKPSR_KPKR | bmKPSR_KDSC | bmKPSR_KRSS);
}
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("InterruptDone!\r\n")));
LeaveCriticalSection(&ghKppLock);
InterruptDone(SYSINTR_KPP);
}
}//中断处理函数处理完毕
/***********************************************************************
*
* FUNCTION: Key_Init 初始化,启动中断服务.该部分是我们参考的重点
*
* DESCRIPTION: This function is to initialize the KPP
* and start a interrupt thread for keypad
*
* NOTE:
*
* PARAMETERS:
*
* RETURNS:
*
**********************************************************************/
DWORD KEY_Init(DWORD dwContext)
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_Init: dwContext = 0x%x\r\n"), dwContext));
//------------------------------------------------
//map KPP memory space,为了让中断服务线程IST在用户模式下访问设备,必须要访问一个物理存储区
//使用VirtualAlloc函数保留一块虚拟存储区,返回的是该区的指针
//申请成功后,使用VirtualCopy函数将这个块的存储区和物理内存的一块映射起来.
//------------------------------------------------
if(gpKpp == NULL)
{
gpKpp = (pKppReg_t) VirtualAlloc( 0,
sizeof(kppReg_t),
MEM_RESERVE,
PAGE_NOACCESS); //申请虚拟存储区,从0开始,保留并且不许访问
if(gpKpp == NULL)
{
ERRORMSG(KEY_DEBUG_MSG|KEY_ERROR_MSG, (TEXT("KEY_Init: KPP memory space VirtualAlloc failed!\r\n")));
return 0;
}
else
{
if (!VirtualCopy (gpKpp,
(LPVOID)GET_V_ADDR_REG(KPP_BASE, 0),
sizeof(kppReg_t),
(PAGE_READWRITE | PAGE_NOCACHE)) )
{
ERRORMSG(KEY_DEBUG_MSG|KEY_ERROR_MSG, (TEXT("KEY_Init: KPP memory sapce VirtualCopy failed!\r\n")));
return 0;
} //建立映射关系,GET_V_ADDR_REG得到的是键值的物理存储区
}
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_Init: KPP memory space bind successful! \r\n")));
}
//------------------------------------------------
//Initialize KPP hardware according to IC Spec (V1.4)
//------------------------------------------------
//enable KPP
gpKppPmuClass= new PmuClass;
gpKppPmuClass->EnableKpp(TRUE); //新建立一个PMU的派生类并使能KPP
//以下是键盘扫描
// Enable no. of rows in keypad (KRE = 1)
// Configure columns as open-drain (KCO = 1)
SET_2BITS(gpKpp->KPCR, KPCR_KRE, KPP_ROW_MASK, KPCR_KCO, KPP_COLUMN_MASK);
// Write 0's to all columns
SET_BITS(gpKpp->KPDR, KPDR_KCD, 0);
// Configure rows as input, columns as output
SET_2BITS(gpKpp->KDDR, KDDR_KCDD, KPP_COLUMN_MASK, 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)
gpKpp->KPSR = \
SET_VALUE(KPSR_KPP_EN, 1) |
SET_VALUE(KPSR_KPKD, 1) |
SET_VALUE(KPSR_KPKR, 1) |
SET_VALUE(KPSR_KDSC, 1) |
SET_VALUE(KPSR_KDIE, 1) |
SET_VALUE(KPSR_KRIE, 0) ;
//------------------------------------------------
//Setup and start interrupt
//------------------------------------------------
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); //设置当前线程优先级
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_Init: CreateEvent\r\n")));
ghIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL); //创建一个无名事件,并返回该事件的句柄
if (ghIntrEvent == NULL)
{
ERRORMSG(KEY_ERROR_MSG|KEY_DEBUG_MSG, (TEXT("KEY_Init: CreateEvent failed\r\n")));
return 0;
}
if(!InterruptInitialize(SYSINTR_KPP, ghIntrEvent, NULL, NULL)) //初始化硬件中断,分别是中断号\中断触发事件\数据区指针\数据区大小
{
CloseHandle(ghIntrEvent);//如果中断初始化失败,则关闭事件
ghIntrEvent = NULL;
ERRORMSG(KEY_ERROR_MSG|KEY_DEBUG_MSG, (TEXT("KEY_Init: Interrupt initialization failed! \r\n")));
return 0;
}
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_Init: CreateThread\r\n")));//建立线程
ghIntrThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)KEY_IntrThread, NULL, 0, NULL); //调用上面设计的中断服务线程,返回一个新线程的句柄line87
if (ghIntrThread == NULL)
{
ERRORMSG(KEY_ERROR_MSG|KEY_DEBUG_MSG, (TEXT("KEY_Init: Failed to create KEY Interrupt Service Thread\r\n")));
return 0;
}
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_Init: Exit Initialization\r\n")));
return 0x5678;
}//初始化完成,全部正常返回0x5678
/***********************************************************************
*
* FUNCTION: Key_Deinit
*
* DESCRIPTION: This function is to clearup when dll is unloaded.
*
* NOTE:
*
* PARAMETERS:
*
* RETURNS:
*
**********************************************************************/
BOOL KEY_Deinit(DWORD dwContext)
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("+KEY_Deinit: dwContext = 0x%x\r\n"), dwContext));
InterruptDisable(SYSINTR_KPP); //卸载后不再响应中断
if (ghIntrThread != NULL)
{
CloseHandle(ghIntrThread);//关闭中断线程
ghIntrThread = NULL;
}
if (ghIntrEvent != NULL)
{
CloseHandle(ghIntrEvent);//事件也关闭
ghIntrEvent = NULL;
}
gpKpp->KPSR = 0;
if(gpKpp != NULL)
{
VirtualFree (gpKpp, 0, MEM_RELEASE);//释放缓存区
gpKpp = NULL;
}
gpKppPmuClass->EnableKpp(FALSE);//屏蔽KPP
delete gpKppPmuClass;//删除并释放资源
gpKppPmuClass = NULL;
// the device manager does not check the return code
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("-KEY_Deinit\r\n"), dwContext));
return TRUE;
}
//----------------------------------------------------------------------------
//The following codes do nothing at all
//----------------------------------------------------------------------------
/*---------------------------------------------------------------------------*/
DWORD KEY_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode)
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("+KEY_Open: dwData = 0x%x, dwAccess = 0x%x, dwShareMode = 0x%x\r\n"), dwData, dwAccess, dwShareMode));
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("-KEY_Open\r\n")));
return dwData;
}
/*---------------------------------------------------------------------------*/
BOOL KEY_Close(DWORD Handle)
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("+KEY_Close: Handle = 0x%x\r\n"), Handle));
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("-KEY_Close: Handle = 0x%x\r\n"), Handle));
return TRUE;
}
/*---------------------------------------------------------------------------*/
// do not make any Win32 calls! (including retail messages)
void KEY_PowerDown(void)
{
// trap suspend events not initiated by keypad.
KppSuspend = TRUE;
keyDown[KPP_POWER_COL] |= (1 << KPP_POWER_ROW);
// Configure keypad to generate interrupts for wake keys only
SET_2BITS(gpKpp->KPCR, KPCR_KCO, KPP_WAKEUP_COL_MASK, KPCR_KRE, KPP_WAKEUP_ROW_MASK);
SET_BITS(gpKpp->KPDR, KPDR_KCD, ~KPP_COLUMN_MASK);
SET_2BITS(gpKpp->KDDR, KDDR_KCDD, KPP_WAKEUP_COL_MASK, KDDR_KRDD, ~KPP_WAKEUP_ROW_MASK);
gpKpp->KPSR |= (bmKPSR_KDIE | bmKPSR_KPKD | bmKPSR_KPKR | bmKPSR_KDSC | bmKPSR_KRSS);
}
/*---------------------------------------------------------------------------*/
// do not make any Win32 calls! (including retail messages)
void KEY_PowerUp(void)
{
// prepare to resume by either re-opening the device or resetting it to closed
// Restore keypad configuration and
// enable key up interrupts for handling of resume keys.
SET_2BITS(gpKpp->KPCR, KPCR_KCO, KPP_COLUMN_MASK, KPCR_KRE, KPP_ROW_MASK);
SET_BITS(gpKpp->KPDR, KPDR_KCD, ~KPP_COLUMN_MASK);
SET_2BITS(gpKpp->KDDR, KDDR_KCDD, KPP_COLUMN_MASK, KDDR_KRDD, ~KPP_ROW_MASK);
gpKpp->KPSR = (bmKPSR_KPP_EN | bmKPSR_KRIE | bmKPSR_KPKR | bmKPSR_KRSS);
}
/*---------------------------------------------------------------------------*/
DWORD KEY_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes)
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_Read: Handle = 0x%x, pBuffer = 0x%x, dwNumBytes = 0x%x\r\n"), Handle, pBuffer, dwNumBytes));
return 0;
}
//this debug message could be used by us,我们可以参考这样的调试信息
/*---------------------------------------------------------------------------*/
DWORD KEY_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes)
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_Write: Handle = 0x%x, pBuffer = 0x%x, dwNumBytes = 0x%x\r\n"), Handle, pBuffer, dwNumBytes));
return 0;
}
/*---------------------------------------------------------------------------*/
DWORD KEY_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod)
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_Seek: Handle = 0x%x, lDistance = 0x%x, dwMoveMethod = 0x%x\r\n"), Handle, lDistance, dwMoveMethod));
return (DWORD) -1;
}
/*---------------------------------------------------------------------------*/
BOOL KEY_IOControl(DWORD Handle, DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize,
PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("+KEY_IOControl: Handle = 0x%x, dwIoControlCode = 0x%x\r\n"), Handle, dwIoControlCode));
return TRUE;
}
/*---------------------------------------------------------------------------*/
BOOL WINAPI KEY_DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_DllEntry: DLL_PROCESS_ATTACH\r\n")));
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(KEY_DEBUG_MSG, (TEXT("KEY_DllEntry: DLL_PROCESS_DETACH\r\n")));
break;
}
// return TRUE for success
return TRUE;
}
/*********************************************************************
PRIVATE FUNCTIONS
*********************************************************************/
/*********************************************************************
*
* FUNCTION: kppHandleWakeKeys
*
* DESCRIPTION: This function what wake keys(non power key)
* are depressed and handles accordingly.
*
* PARAMETERS: current keypad row/col matrix data
*
* RETURNS: None
*
********************************************************************/
static void kppHandleWakeKeys(UINT8 *keys)
{
UINT8 iCol;
UINT8 iRow;
UINT8 iRowMask;
UINT8 index;
for(iCol = 0; iCol < KPP_COLUMN_INUSE; iCol++)
{
for(iRow = 0, iRowMask = 1; iRow < KPP_ROW_INUSE; iRow++, iRowMask <<= 1)
{
if(iRowMask & keys[iCol])
{
index = iCol * KPP_ROW_INUSE + iRow;
if(index != KPP_POWER_BUTTON_INDEX)
{
if(ExtraKeyCodeSequenceTable[index] != 0)
keybd_event(ExtraKeyCodeSequenceTable[index], index, 0, 0);
keybd_event(KeyCodeSequenceTable[index], index, 0, 0);
}
}
}
}
}
/*********************************************************************
END OF FILE
*********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -