📄 tchpdd.cpp
字号:
//****************************************************************************
LONG DdsiTouchPanelDetach()
{
DEBUGMSG(ZONE_INIT|| ZONE_PDD,(TEXT("DdsiTouchPanelDetach\r\n")));
return(0);
}
//****************************************************************************
//
// @doc EX_TOUCH_DDSI EXTERNAL DRIVERS DDSI TOUCH_PANEL
//
// @func void | DdsiTouchPanelGetPoint |
// Returns the most recently acquired point and its associated tip state
// information.
//
// @parm PDDSI_TOUCHPANEL_TIPSTATE | pTipState |
// Pointer to where the tip state information will be returned.
// @parm PLONG | pUnCalX |
// Pointer to where the x coordinate will be returned.
// @parm PLONG | pUnCalY |
// Pointer to where the y coordinate will be returned.
//
// @comm
// Implmented in the PDD.
//
// Currently the scenario is that we configure the TSPX interrupt for a pen down. On a
// pen down interrupt we start a timer which will interrupt the driver almost 100 times
// a second. At the end of servicing each interrupt we query the status of the pen and
// change the state accordingly.
//****************************************************************************
VOID DdsiTouchPanelGetPoint(TOUCH_PANEL_SAMPLE_FLAGS *pTipStateFlags,INT *pUncalX,INT *pUncalY)
{
//DEBUGMSG(ZONE_POINT || ZONE_PDD,(TEXT("DdsiTouchPanelGetPoint\r\n")));
// static BOOL bPreviousDown = FALSE;
BOOL bPreviousDown = (*pTipStateFlags & TouchSamplePreviousDownFlag);
TouchStruct sTouch;
BOOL bCurrentInterruptMode = gbInterruptMode;
ULONG ulXDiff, ulYDiff;
static ULONG ulUpCount = 0;
ULONG ulInvPressure;
//
// Change to Polling mode.
//
if(gbInterruptMode)
{
TouchPollingMode();
}
//
// Read the touch values and calculate the current pressure.
//
GetTouchValues(&sTouch);
ulInvPressure = CalculateInvPressure(&sTouch);
//
// Check to see if the point is valid. If the resistance is below
// the minimum resistance then the point is probably valid.
//
if( ulInvPressure< gulMinInvPressure)
{
if(bPreviousDown )
{
//
// If the difference between samples is too great, ignore the sample.
//
ulXDiff = abs(gulLastX - sTouch.ulX);
ulYDiff = abs(gulLastY - sTouch.ulY);
if (ulXDiff <gulMaxChange && ulYDiff <gulMaxChange)
{
*pTipStateFlags = TouchSampleValidFlag | TouchSampleDownFlag;
}
else
{
*pTipStateFlags = TouchSampleValidFlag | TouchSampleIgnore;
}
}
else
{
*pTipStateFlags = TouchSampleValidFlag | TouchSampleDownFlag;
}
*pUncalX = sTouch.ulX;
*pUncalY = sTouch.ulY;
gulLastX = sTouch.ulX;
gulLastY = sTouch.ulY;
ulUpCount = 0;
}
//
// If the Resistance is less than the MaxInvPressure but greater than
// the MinInvPressure, disregard the point because it may be
// errouneous.
//
//
else if(ulInvPressure< gulMaxInvPressure)
{
*pTipStateFlags = TouchSampleValidFlag | TouchSampleIgnore;
}
//
// The absence of the down flag means that the user picked up the pen.
//
else if(bPreviousDown)
{
ulUpCount++;
if(ulUpCount<2)
{
*pTipStateFlags = TouchSampleValidFlag | TouchSampleIgnore;
}
else
{
*pTipStateFlags = TouchSampleValidFlag;
TouchInterruptMode();
//
// Set the done interrupt flag.
//
InterruptDone(gIntrTouch);
}
}
//
// Pen was previously up so ignore the sample.
//
else
{
*pTipStateFlags = TouchSampleValidFlag | TouchSampleIgnore;
//
// Go back to Interrupt mode.
//
TouchInterruptMode();
//
// Set the done interrupt flag.
//
InterruptDone(gIntrTouch);
}
}
//****************************************************************************
//
// @func VOID | DdsiTouchPanelPowerHandler |
// System power state notification.
//
// @parm BOOL | bOff | TRUE, the system is powering off; FALSE, the system is powering up.
//
// @comm
// This routine is called in a kernel context and may not make any system
// calls whatsoever. It may read and write its own memory and that's about
// it. This routine is called by the MDD and also serves as an internal
// helper routine for touch enable/disable.
//
// @devnote This routine will run in kernel context, and may not make
// any system calls. If you can any subroutines inside here, make sure
// that they also follow this restriction.
//
//****************************************************************************
void DdsiTouchPanelPowerHandler(BOOL bOff)
{
(bOff);
}
BOOL TouchPanelInitializeCursor()
{
return TRUE;
}
//****************************************************************************
// GetTouchValues
//****************************************************************************
// Gets the X, Y, Z1 and Z2 values from the touch sceen. Z1 and Z2 allow
// us to measure the pressure sensitivity.
//
//
static void GetTouchValues( TouchStruct *pTouch)
{
//LARGE_INTEGER li[6];
//static LARGE_INTEGER liLast;
//BOOL b;
//
// Get the Z1 and Z2 values for pressure measurements.
// The Screen does not need to be discharged between the Z values.
//
//b = QueryPerformanceCounter(&li[0]);
pTouch->ulZ1 = ADCGetData(SWITCH_Z1, 2, 200);
//b = QueryPerformanceCounter(&li[1]);
pTouch->ulZ2 = ADCGetData(SWITCH_Z2, 2, 200);
//b = QueryPerformanceCounter(&li[2]);
//
// Read the X and Y values.
//
//b = QueryPerformanceCounter(&li[3]);
//b = QueryPerformanceCounter(&li[4]);
pTouch->ulY = ADCGetData(SWITCH_Y, 4, 20);
//b = QueryPerformanceCounter(&li[5]);
pTouch->ulX = ADCGetData(SWITCH_X, 4, 20);
//
// Let the screen discharge.
//
*TOUCH_TSDIRECT = SWITCH_DISCHARGE;
#if 0
RETAILMSG
(
1,
(
TEXT("%d, %d, %d %d\r\n"),
(ULONG)(li[1].QuadPart - li[0].QuadPart),
(ULONG)(li[5].QuadPart - li[0].QuadPart),
(ULONG)(li[0].QuadPart - liLast.QuadPart),
gulTouchSampleRate
)
);
liLast.QuadPart = li[0].QuadPart;
#endif // 0
}
//****************************************************************************
// ADCGetData
//****************************************************************************
// ulADCSwitch - Value of the switch settings needed to read the ADC
//
//
inline ULONG ADCGetData(ULONG ulADCSwitch, ULONG ulSamples, ULONG ulMaxDiff)
{
ULONG ulResult;
ULONG ulValue;
ULONG ulCount;
ULONG ulLowest;
ULONG ulHighest ;
ULONG ulSum;
ULONG ulAve;
//
// Program the lock register.
//
*TOUCH_TSSWLOCK = 0xAA;
//
// Clear the touch settings.
//
*TOUCH_TSDIRECT = ulADCSwitch;
//
// Through away the first sample.
//
do
{
ulResult = *TOUCH_TSXYRESULT;
}while(!(ulResult & TSXYRESULT_SDR));
//
// Delay 800 uS.
//
DelayuS(1000);
do
{
//
//Initialize our values.
//
ulLowest = 0xfffffff;
ulHighest = 0;
ulSum = 0;
for(ulCount = 0; ulCount <ulSamples; ulCount ++)
{
//
// Read the touch screen four more times and average.
//
do
{
ulResult = *TOUCH_TSXYRESULT;
}while(!(ulResult& TSXYRESULT_SDR));
ulValue = (ulResult & TSXYRESULT_AD_MASK) >>TSXYRESULT_AD_SHIFT;
ulValue = ((ulValue >> 4) + ((1 + TSXYRESULT_X_MASK)>>1)) & TSXYRESULT_X_MASK;
//
// Add up the values.
//
ulSum +=ulValue;
//
// Get the lowest and highest values.
//
if(ulValue <ulLowest)
{
ulLowest = ulValue;
}
if(ulValue >ulHighest)
{
ulHighest = ulValue;
}
}
}
while(ulHighest - ulLowest > ulMaxDiff);
//
// Calculate the Average value.
//
ulAve = ulSum / ulSamples;
return ulAve;
}
//****************************************************************************
// DischargeScreen.
//****************************************************************************
// Discharges the screen plates.
//
//
inline void DischargeScreen(void)
{
//
// Program the lock register.
//
*TOUCH_TSSWLOCK = 0xAA;
//
// Clear the touch settings.
//
*TOUCH_TSDIRECT = SWITCH_DISCHARGE;
//
// Perform the delay in
//
Sleep(2);
}
//****************************************************************************
// CalculateInvPressure
//****************************************************************************
// Is the Touch Valid. Touch is not valid if the X or Y value is not
// in range and the pressure is not enough.
//
// Touch resistance can be measured by the following formula:
//
// Rx * X * Z2
// Rtouch = --------- * (-- - 1)
// 4096 Z1
//
// This is simplified in the ration of Rtouch to Rx. The lower the value, the
// higher the pressure.
//
// Z2
// InvPressure = X * (-- - 1)
// Z1
//
static ULONG CalculateInvPressure(TouchStruct *pTouch)
{
ULONG ulInvPressure;
//
// Check to see if the point is valid.
//
if( pTouch->ulZ1 < MIN_Z1_VALUE)
{
ulInvPressure = 0x10000;
}
//
// Can omit the pressure calculation if you need to get rid of the division.
//
else
{
ulInvPressure = ((pTouch->ulX * pTouch->ulZ2) / pTouch->ulZ1) - pTouch->ulX;
}
DEBUGMSG
(
ZONE_POINT,
(
TEXT("IsTouchValid X = 0x%03x, Y = 0x%03x, Z1 = 0x%03x, Z2 = 0x%03x, p = 0x%08x.\r\n"),
pTouch->ulX,
pTouch->ulY,
pTouch->ulZ1,
pTouch->ulZ2,
ulInvPressure
)
);
return ulInvPressure;
}
//****************************************************************************
// TouchInterruptMode
//****************************************************************************
// Sets the touch screen to interrupt mode.
//
//
static void TouchInterruptMode(void)
{
//
// clear the touch enable bit in syscon.
//
HalWriteCommonReg(CSC_DEVCFG, DEVCFG_TIN, 0);
//
// Enable the touch polling interrupt.
//
*TOUCH_TSSETUP = gulSetup | TSSETUP_EN;
//
// Set the timer to interrupt only when a touch occurs.
//
gdwTouchIstTimeout = INFINITE;
//
// The the flag to show that we are in interrupt mode.
//
gbInterruptMode = TRUE;
//
// Initialize the second program setup register to zero.
//
*TOUCH_TSSETUP2 = TSSETUP2_DEFAULT;
}
//****************************************************************************
// TouchPollingMode
//****************************************************************************
// Sets the touch screen to Polling mode.
//
//
static void TouchPollingMode(void)
{
//
// Enable the touch polling interrupt.
//
*TOUCH_TSSETUP = gulSetup;
//
// Enable touch to start out with.
//
HalWriteCommonReg(CSC_DEVCFG, DEVCFG_TIN, DEVCFG_TIN);
//
// Set the timer to interrupt every 10 Milliseconds.
//
// 1000 mSec 1
// ------------------- * ------------------------------- - Sample Delay (MSec)
// 1 Sec Touch Sample Rate (Sample/Sec)
//
gdwTouchIstTimeout = (1000/gulTouchSampleRate) - SAMPLE_DELAY;
//
// The the flag to show that we are in interrupt mode.
//
gbInterruptMode = FALSE;
}
//****************************************************************************
// ReadRegistryValue
//****************************************************************************
// Read the DWORD Registry Value
//
//
DWORD ReadRegistryValue(HKEY hKey, PTSTR szValueName, DWORD dwDefault)
{
LONG lStatus;
ULONG ulReturnValue;
DWORD dwValType = REG_DWORD;
DWORD dwValLen = 4;
lStatus = RegQueryValueEx( hKey, szValueName, NULL, &dwValType, (PBYTE)&ulReturnValue, &dwValLen);
if ((lStatus != ERROR_SUCCESS) || (dwValType != REG_DWORD))
{
ulReturnValue = dwDefault;
}
return ulReturnValue;
}
//****************************************************************************
// DelayuS
//****************************************************************************
// Delays using timer 2.
// ulDelay - Delay in MicroSeconds.
//
static void DelayuS(ULONG ulDelay)
{
//
// Initialize the timer.
//
*TIM_TIMER2CONTROL = TIMERCONTROL_CLKSEL | TIMERCONTROL_ENABLE;
*TIM_TIMER2LOAD = (TIMER_508KHZ_FREQ * ulDelay) /1000000;
*TIM_TIMER2CLEAR = 0;
//
// Wait until the interrupt fires.
//
WaitForSingleObject(ghTimer2Event, INFINITE);
//
// Disable the timer and clear the interupt.
//
*TIM_TIMER2CONTROL = 0;
*TIM_TIMER2CLEAR = 0;
InterruptDone(SYSINTR_TIMER2);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -