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

📄 lpc32xx_kb.cpp

📁 NXP LPC3000系列 wince BSP包
💻 CPP
字号:
//*********************************************************************
//* Software that is described herein is for illustrative purposes only  
//* which provides customers with programming information regarding the  
//* products. This software is supplied "AS IS" without any warranties.  
//* NXP Semiconductors assumes no responsibility or liability for the 
//* use of the software, conveys no license or title under any patent, 
//* copyright, or mask work right to the product. NXP Semiconductors 
//* reserves the right to make changes in the software without 
//* notification. NXP Semiconductors also make no representation or 
//* warranty that such application will be suitable for the specified 
//* use without further testing or modification. 
//*
//* Copyright NXP Semiconductors
//*********************************************************************
//
// lpc32xx_kb.cpp
//
// PDD for the LPC32xx matrix keyboard driver
//

#include "lpc32xx_kb.h"
#include <ceddk.h>
#include <nkintr.h>
#include <keybddbg.h>
#include <keybddr.h>
#include <keybdpdd.h>
#include <laymgr.h>
#include <keybdist.h>
#include "lpc32xx_kscan.h"
#include "lpc32xx_clkpwr.h"
#include "intr.h"

// Structure used for keyboard controller driver data
typedef struct {
	KSCAN_REGS_T *pKSCANRegs;        // Pointer to KSCAN registers
	CLKPWR_REGS_T *pCLKPWRRegs;      // Pointer to CLKPWR registers
	UINT8 keyStates [MATRIXSIZE];    // Last KSCAN states
	DWORD sysIntr;                   // Keyboard SysIntr value
	HANDLE hEvent;                   // Keyboard interrupt event flag
	HANDLE hThread;                  // Keyboard thread handle
	UINT v_uiPddId;
	PFN_KEYBD_EVENT v_pfnKeybdEvent;
} KB_DATA_T;
static KB_DATA_T kbdata; 

//------------------------------------------------------------------------------
//
// kscan_enable
//
// Enables or disables KSCAN block
//
void kscan_enable(BOOL enable)
{
	if (enable != FALSE)
	{
		// Enable KSCAN clock and clear IRQ
		kbdata.pCLKPWRRegs->clkpwr_key_clk_ctrl |= CLKPWR_KEYCLKCTRL_CLK_EN;
		kbdata.pKSCANRegs->ks_irq = 1;
	}
	else
	{
		// Clear IRQ and disable KSCAN clock
		kbdata.pKSCANRegs->ks_irq = 1;
		kbdata.pCLKPWRRegs->clkpwr_key_clk_ctrl &= ~CLKPWR_KEYCLKCTRL_CLK_EN;
	}
}

//------------------------------------------------------------------------------
//
// kscan_int_handler
//
// KSCAN interrupt handler, updates KSCAN matrix of a key change
//
void kscan_int_handler(UINT8 newStates[MATRIXSIZE])
{
	int idx = 0;

	// Read new key scan states
	for (idx = 0; idx < MATRIXSIZE; idx++)
	{
		newStates[idx] = (UINT8) kbdata.pKSCANRegs->ks_data [idx];
	}

	// Clear IRQ state
	kbdata.pKSCANRegs->ks_irq = 1;
}

//------------------------------------------------------------------------------
//
// kscanGetEvents
//
// Generates a list of raw KSCAN changes codes and states
// Raw key scan code is in the format 0bcccrrr, ccc=column, rrr=row
//
int kscanGetEvents(UINT8 rawScanCodeList[16],
				   BOOL keyUpList[16])
{
	UINT8 bitm, newEvents[MATRIXSIZE];
	int idx, innl;
	int changes = 0;

	// Get latest events
	kscan_int_handler(newEvents);

	for (idx = 0; ((idx < MATRIXSIZE) && (changes < 16)); idx++)
	{
		if (newEvents[idx] != kbdata.keyStates[idx])
		{
			// Key state has changed, determine changed key
			for (innl = 0; ((innl < MATRIXSIZE) && (changes < 16)); innl++)
			{
				bitm = newEvents[idx] & _BIT(innl);
				if (bitm != (kbdata.keyStates[idx] & _BIT(innl)))
				{
					// Save new key state
					rawScanCodeList[changes] = (UINT8) (idx << 3) |
						(UINT8) (innl);
					if (bitm == 0)
					{
						// Key was released
						keyUpList[changes] = TRUE;
					}
					else
					{
						// Key was pressed
						keyUpList[changes] = FALSE;
					}

					changes++;
				}
			}
		}
	}

	return changes;
}

//------------------------------------------------------------------------------
//
// KB_LPC32XX_GetEventEx2
//
// Process keypad events
//
static UINT KB_LPC32XX_GetEventEx2(UINT uiPddId,
								   UINT32 rguiScanCode[16],
								   BOOL rgfKeyUp[16])
{
	UINT8 bitm, newEvents[MATRIXSIZE];
	int idx, innl;
	int changes = 0;

	// Get latest events
	kscan_int_handler(newEvents);

	for (idx = 0; ((idx < MATRIXSIZE) && (changes < 16)); idx++)
	{
		if (newEvents[idx] != kbdata.keyStates[idx])
		{
			// Key state has changed, determine changed key
			for (innl = 0; ((innl < MATRIXSIZE) && (changes < 16)); innl++)
			{
				bitm = newEvents[idx] & _BIT(innl);
				if (bitm != (kbdata.keyStates[idx] & _BIT(innl)))
				{
					// Save new key state
					rguiScanCode[changes] = (UINT8) (idx << 3) |
						(UINT8) (innl);
					if (bitm == 0)
					{
						// Key was released
						rgfKeyUp[changes] = TRUE;
					}
					else
					{
						// Key was pressed
						rgfKeyUp[changes] = FALSE;
					}

					changes++;
				}
			}

			// Save new state
			kbdata.keyStates[idx] = newEvents[idx];
		}
	}

	return changes;
}

//------------------------------------------------------------------------------
//
// KB_LPC32XX_Thread
//
// KSCAN handler thread
//
void KB_LPC32XX_Thread(void *pData)
{
    KEYBD_IST keyPadIst;

	// Enable KSCAN interrupt
	InterruptDone(kbdata.sysIntr);

	// Setup keypad thread
    keyPadIst.hevInterrupt = kbdata.hEvent;
    keyPadIst.dwSysIntr_Keybd = kbdata.sysIntr;
    keyPadIst.uiPddId = kbdata.v_uiPddId;
    keyPadIst.pfnGetKeybdEvent = KB_LPC32XX_GetEventEx2;
    keyPadIst.pfnKeybdEvent = kbdata.v_pfnKeybdEvent;

	// No return from this function
	KeybdIstLoop(&keyPadIst);
}

//------------------------------------------------------------------------------
//
// KB_LPC32XX_Setup
//
// Sets up the KSCAN block
//
BOOL KB_LPC32XX_Setup(void)
{
	PHYSICAL_ADDRESS pa;
	DWORD irq, threadID;
	BOOL sts = FALSE;

	// Setup initial values
	kbdata.pCLKPWRRegs = NULL;
	kbdata.pKSCANRegs = NULL;
	kbdata.sysIntr = SYSINTR_UNDEFINED;
	kbdata.hEvent = NULL;

	// Map pointers to KSCAN and CLKPWR blocks
	pa.QuadPart = CLK_PM_BASE;
	kbdata.pCLKPWRRegs = (CLKPWR_REGS_T *) MmMapIoSpace(pa,
		sizeof (CLKPWR_REGS_T), FALSE);
	pa.QuadPart = KSCAN_BASE;
	kbdata.pKSCANRegs = (KSCAN_REGS_T *) MmMapIoSpace(pa,
		sizeof (KSCAN_REGS_T), FALSE);
	if ((kbdata.pCLKPWRRegs == NULL) || (kbdata.pKSCANRegs == NULL))
	{
		RETAILMSG(1, (TEXT("KSCAN: Error mapping registers\r\n")));
		goto cleanup;
	}

	// Enable clocking for the KSCAN block
	kscan_enable(TRUE);

	// Clear KSCAN IRQ and get initial matrix
	kscan_int_handler(kbdata.keyStates);

	// Get sysIntr value mapped to the IRQ
	irq = OAL_INTR_IRQ_KEY;
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irq, sizeof(irq),
		&kbdata.sysIntr, sizeof(kbdata.sysIntr), NULL))
    {
        RETAILMSG(1, 
            (TEXT("KSCAN: Failed to request the sysintr.\r\n")));

        kbdata.sysIntr = SYSINTR_UNDEFINED;
        goto cleanup;
    }

	// Create event handle
	kbdata.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (kbdata.hEvent == NULL)
	{
        RETAILMSG(1, 
            (TEXT("KSCAN: Failed to create handler event.\r\n")));
		goto cleanup;
	}

	// Initialize the SSP interrupt
	if (InterruptInitialize(kbdata.sysIntr, kbdata.hEvent,
		NULL, 0) == FALSE) {
		// Cannot initialize interrupt
        RETAILMSG(1, 
			(TEXT("KSCAN: Cannot initialize interrupt\r\n")));
        goto cleanup;
	}

	// Start the KSCAN thread
	kbdata.hThread =  CreateThread(NULL, 0,
		(LPTHREAD_START_ROUTINE) KB_LPC32XX_Thread, NULL, 0, &threadID);
	if (kbdata.hThread == NULL)
	{
		RETAILMSG(1,
			(TEXT("KSCAN: Error creating handler thread!\r\n")));
        goto cleanup;
    }

	// Setup KSCAN timing and debounce values
	kbdata.pKSCANRegs->ks_fast_tst = KSCAN_FTST_USE32K_CLK;
	kbdata.pKSCANRegs->ks_matrix_dim = KSCAN_MSEL_SELECT(MATRIXSIZE);
	kbdata.pKSCANRegs->ks_deb = MATRIXDEBCYCLES;
	kbdata.pKSCANRegs->ks_scan_ctl = MATRIXDELCYCLES;
 
	sts = TRUE;

cleanup:
	if (sts == FALSE)
	{
		if (kbdata.hEvent != NULL)
		{
			CloseHandle(kbdata.hEvent);
		}
		if (kbdata.sysIntr != SYSINTR_UNDEFINED)
		{
			KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &kbdata.sysIntr,
		        sizeof(kbdata.sysIntr), NULL, 0, NULL);
		}
		if (kbdata.pKSCANRegs != NULL)
		{
	        MmUnmapIoSpace((PVOID) kbdata.pKSCANRegs, sizeof (KSCAN_REGS_T));
		}
		if (kbdata.pCLKPWRRegs != NULL)
		{
	        MmUnmapIoSpace((PVOID) kbdata.pCLKPWRRegs, sizeof (CLKPWR_REGS_T));
		}
	}

	return sts;
}

//------------------------------------------------------------------------------
//
// KB_LPC32XX_PowerHandler
//
// Keyboard PDD power handler function
//
static void KB_LPC32XX_PowerHandler(UINT uiPddId,
									BOOL fTurnOff)
{
	if (uiPddId == kbdata.v_uiPddId)
	{
		if (fTurnOff == FALSE)
		{
			kscan_enable(TRUE);
		}
		else
		{
			kscan_enable(FALSE);
		}
	}
}

//------------------------------------------------------------------------------
//
// KBLPC32xxPdd
//
// PDD structure used for MDD
//
static KEYBD_PDD KBLPC32xxPdd =
{
  MATRIX_PDD,
  MATRIXTYPE,
  KB_LPC32XX_PowerHandler,
  NULL
};

//------------------------------------------------------------------------------
//
// KB_PHY3250_Entry
//
// Keyboard PDD entry point
//
BOOL WINAPI KB_LPC32XX_Entry(UINT uiPddId,
							 PFN_KEYBD_EVENT pfnKeybdEvent,
							 PKEYBD_PDD *ppKeybdPdd)
{
	// Return additional PDD data
	*ppKeybdPdd = &KBLPC32xxPdd;

	// Save PDD ID and event callback
	kbdata.v_uiPddId = uiPddId;
	kbdata.v_pfnKeybdEvent = pfnKeybdEvent;

	// Initialize the KSCAN hardware and return
	return KB_LPC32XX_Setup();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -