📄 lpc32xx_touch.cpp
字号:
if (!lpc32xx_ts_init())
{
goto cleanup;
}
// Get pen sysintr value
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irqt, sizeof(irqt),
&gIntrTouch, sizeof(gIntrTouch), NULL))
{
RETAILMSG(ZONE_ERROR,
(TEXT("ERROR: TOUCH: Failed to request the touch sysintr.\r\n")));
gIntrTouch = SYSINTR_UNDEFINED;
goto cleanup;
}
s_TouchPad.predownflag = FALSE;
rc = TRUE;
cleanup:
DEBUGMSG(ZONE_FUNCTION, (TEXT("DdsiTouchPanelEnable- (rc = %d)\r\n"), rc));
return rc;
}
//------------------------------------------------------------------------------
//
// DdsiTouchPanelDisable
//
// Disable the touchscreen
//
VOID DdsiTouchPanelDisable()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("DdsiTouchPanelDisable+\r\n")));
// Close pen event and kill thread.
lpc32xx_ts_deinit();
// Release interrupts
if (gIntrTouch != SYSINTR_UNDEFINED)
{
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &gIntrTouch,
sizeof(gIntrTouch), NULL, 0, NULL);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("DdsiTouchPanelDisable-\r\n")));
}
//------------------------------------------------------------------------------
//
// DdsiTouchPanelAttach
//
//
LONG DdsiTouchPanelAttach()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("DdsiTouchPanelAttach+\r\n")));
// Increment the number of process attach calls.
s_TouchPad.nProcessAttached++;
DEBUGMSG(ZONE_FUNCTION, (TEXT("DdsiTouchPanelAttach-\r\n")));
// Return the number.
return s_TouchPad.nProcessAttached;
}
//------------------------------------------------------------------------------
//
// DdsiTouchPanelDetach
//
//
LONG DdsiTouchPanelDetach()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("DdsiTouchPanelDetach+\r\n")));
// Decrement the number of process attach calls.
s_TouchPad.nProcessAttached--;
DEBUGMSG(ZONE_FUNCTION, (TEXT("DdsiTouchPanelDetach\r\n")));
// Return the number.
return s_TouchPad.nProcessAttached;
}
//------------------------------------------------------------------------------
//
// DdsiTouchPanelGetPoint
//
// The driver handles the touchscreen interrupt via the touch MDD. When the
// touchscreen interrupt occurs, the touch MDD will call this function to
// determine the touch state.
//
void DdsiTouchPanelGetPoint(TOUCH_PANEL_SAMPLE_FLAGS *pTipStateFlags,
INT *pUncalX, INT *pUncalY)
{
TOUCHP_T TPoint;
// MDD needs us to hold on to last valid sample and previous pen state.
static INT usFilteredX = 0;
static INT usFilteredY = 0;
static DWORD dwTimeNextEvent = -1;
DEBUGMSG(ZONE_FUNCTION, (TEXT("DdsiTouchPanelGetPoint+\r\n")));
// Check if pen data are available If so, get the data.
if (lpc32xx_get_point(&TPoint))
{
if (TPoint.pendown == FALSE)
{
// If the previous pen down state was set and this is a pen up state,
// then tell the MDD the pen was released and set the MDD thread time
// back to INFINITE
if (s_TouchPad.predownflag == TRUE)
{
*pUncalX = usFilteredX;
*pUncalY = usFilteredY;
s_TouchPad.predownflag = FALSE;
*pTipStateFlags = TouchSampleValidFlag;
}
gdwTouchIstTimeout = INFINITE;
}
else
{
// Pen is currently down
if (s_TouchPad.predownflag == FALSE)
{
// Pen has just been put down
s_TouchPad.predownflag = TRUE;
}
// Save last samples
*pUncalX = usFilteredX = TPoint.xpoint;
*pUncalY = usFilteredY = TPoint.ypoint;
*pTipStateFlags = (TouchSampleValidFlag | TouchSampleDownFlag);
// Pen down timeout is 23mS, this is slightly longer than the longest
// time between touchscreen interrupts
gdwTouchIstTimeout = 23;
}
}
else
{
// By default, any sample returned will be ignored.
*pTipStateFlags = TouchSampleIgnore;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("DdsiTouchPanelGetPoint-\r\n")));
}
//------------------------------------------------------------------------------
// DdsiTouchPanelPowerHandler
//
// Power down between samples (nothing to do here)
//
void DdsiTouchPanelPowerHandler(BOOL bOff)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("DdsiTouchPanelPowerHandler\r\n")));
}
//------------------------------------------------------------------------------
//
// lpc32xx_update_samplerate
//
// Sets the sample rate of the touchscreen by adjusting the same update time
// Sample rate is based on s_TouchPad.nSampleRate.
//
BOOL lpc32xx_update_samplerate(void)
{
BOOL rc = FALSE;
// Compute update delay (the time between samples when pendown is detected)
// These are based off the 32KHz TC clock and are ok for hardcoded values
if (s_TouchPad.nSampleRate == 0)
{
s_TouchPad.pTSCREGs->tsc_utr = TSC_UTR_UPDATE_TIME(100); // About 52Hz
}
else
{
s_TouchPad.pTSCREGs->tsc_utr = TSC_UTR_UPDATE_TIME(25); // About 101Hz
}
return rc;
}
//------------------------------------------------------------------------------
//
// lpc32xx_ts_init
//
// Initializes the touchscreen controller for auto operation
//
BOOL lpc32xx_ts_init(void)
{
UINT32 tscval;
PHYSICAL_ADDRESS pa;
CLKENID_T clkinfo;
DWORD bytesret;
// Map register space
pa.QuadPart = ADC_BASE;
s_TouchPad.pTSCREGs = (LPC3250_ADCTSC_REGS_T *)
MmMapIoSpace(pa, sizeof (LPC3250_ADCTSC_REGS_T), FALSE);
if (s_TouchPad.pTSCREGs == NULL)
{
// Not mapped
RETAILMSG(ZONE_ERROR, (TEXT("lpc32xx_ts_init: Register map failure\r\n")));
return FALSE;
}
/* Enable clock to ADC block - 32KHz clock */
clkinfo.clkid = CLKPWR_ADC_CLK;
clkinfo.enable = TRUE;
if (KernelIoControl(IOCTL_LPC32XX_ENSYSCLK, &clkinfo, sizeof (clkinfo),
NULL, 0, &bytesret) == FALSE)
{
RETAILMSG(ZONE_ERROR, (TEXT("lpc32xx_ts_init: Error enabling touch clock\r\n")));
}
/* Ensure ADC is not powered */
s_TouchPad.pTSCREGs->adc_con &= ~TSC_ADCCON_POWER_UP;
/* Set the TSC FIFO depth to 4 samples of 10-bit size */
s_TouchPad.pTSCREGs->adc_con = (TSC_ADCCON_IRQ_TO_FIFO_4 |
TSC_ADCCON_X_SAMPLE_SIZE(10) | TSC_ADCCON_Y_SAMPLE_SIZE(10));
/* set TSC SEL to default state */
s_TouchPad.pTSCREGs->adc_sel = 0x284;
// min/max x/y registers
s_TouchPad.pTSCREGs->tsc_min_x = 0;
s_TouchPad.pTSCREGs->tsc_max_x = 0x3ff;
s_TouchPad.pTSCREGs->tsc_max_y = 0;
s_TouchPad.pTSCREGs->tsc_min_y = 0x3ff;
// Aux registers
s_TouchPad.pTSCREGs->tsc_aux_utr = 0;
s_TouchPad.pTSCREGs->tsc_aux_min = 0;
s_TouchPad.pTSCREGs->tsc_aux_max = 0;
// Rise Time
s_TouchPad.pTSCREGs->tsc_dtr = TSC_RTR_RISE_TIME(0x2);
// Update Time
s_TouchPad.pTSCREGs->tsc_utr = TSC_UTR_UPDATE_TIME(446);
// Delay Time
s_TouchPad.pTSCREGs->tsc_dtr = TSC_DTR_DELAY_TIME(0x2);
// Touch time
s_TouchPad.pTSCREGs->tsc_ttr = TSC_TTR_TOUCH_TIME(0x10);
// Drain X Plate time
s_TouchPad.pTSCREGs->tsc_dxp = TSC_DXP_DRAINX_TIME(0x4);
// Update the sample rate
lpc32xx_update_samplerate();
// Empty the touchscreen FIFO
while ((s_TouchPad.pTSCREGs->tsc_stat & TSC_STAT_FIFO_EMPTY) == 0)
{
tscval = s_TouchPad.pTSCREGs->tsc_fifo;
}
// TSC Auto mode enable, this also sets AUTO bit
s_TouchPad.pTSCREGs->adc_con |= TSC_ADCCON_AUTO_EN;
return TRUE;
}
//------------------------------------------------------------------------------
//
// lpc32xx_ts_deinit
//
// Disables touchscreen
//
void lpc32xx_ts_deinit(void)
{
CLKENID_T clkinfo;
DWORD bytesret;
if (s_TouchPad.pTSCREGs != NULL)
{
s_TouchPad.pTSCREGs->adc_con &= ~TSC_ADCCON_AUTO_EN;
MmUnmapIoSpace(s_TouchPad.pTSCREGs, sizeof(LPC3250_ADCTSC_REGS_T));
}
// Disable touchscreen clock
clkinfo.clkid = CLKPWR_ADC_CLK;
clkinfo.enable = FALSE;
KernelIoControl(IOCTL_LPC32XX_ENSYSCLK, &clkinfo, sizeof (clkinfo),
NULL, 0, &bytesret);
}
//------------------------------------------------------------------------------
//
// lpc32xx_fifo_empty
//
// Empty touchscreen FIFO
//
static void lpc32xx_fifo_empty(void)
{
UINT32 tsval;
// Empty FIFO
while ((s_TouchPad.pTSCREGs->tsc_stat & TSC_STAT_FIFO_EMPTY) == 0)
{
tsval = s_TouchPad.pTSCREGs->tsc_fifo;
}
}
//------------------------------------------------------------------------------
//
// lpc32xx_get_point
//
// Returns the touchscreen state
//
BOOL lpc32xx_get_point(TOUCHP_T* pPoint)
{
UINT32 tsamples, tsval, rval [16], xval [16], yval [16];
BOOL pvalid = FALSE;
if (s_TouchPad.pTSCREGs != NULL)
{
// Has touchscreen FIFO overflowed?
if ((s_TouchPad.pTSCREGs->tsc_stat & TSC_STAT_FIFO_OVRRN) != 0)
{
// FIFO overrun, toss sample
lpc32xx_fifo_empty();
}
else if ((s_TouchPad.pTSCREGs->tsc_stat & TSC_STAT_FIFO_EMPTY) == 0)
{
// Get sample data
tsamples = 0;
while ((tsamples < 16) &&
((s_TouchPad.pTSCREGs->tsc_stat & TSC_STAT_FIFO_EMPTY) == 0))
{
tsval = s_TouchPad.pTSCREGs->tsc_fifo;
xval [tsamples] = TSC_FIFO_NORMALIZE_X_VAL(tsval);
yval [tsamples] = TSC_FIFO_NORMALIZE_Y_VAL(tsval);
rval [tsamples] = tsval;
tsamples++;
}
// Data is only valid if pen is still down
pPoint->pendown = FALSE;
if ((rval [3] & TSC_FIFO_TS_P_LEVEL) == 0)
{
// Average samples 1 and 2 only, toss sample 0 and 3
if (tsamples >= 4)
{
pPoint->xpoint = 0x3FF - (INT) ((xval [1] + xval [2]) / 2);
pPoint->ypoint = 0x3FF - (INT) ((yval [1] + yval [2]) / 2);
pPoint->pendown = TRUE;
}
}
else
{
lpc32xx_fifo_empty();
}
pvalid = TRUE;
}
else
{
// Pen is released
pPoint->pendown = FALSE;
pvalid = TRUE;
lpc32xx_fifo_empty();
}
}
InterruptDone(gIntrTouch);
return pvalid;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -