📄 bsptouch.cpp
字号:
// Returns:
// TRUE if successful, FALSE otherwise.
//
//-----------------------------------------------------------------------------
static BOOL BSPTouchAlloc(void)
{
BOOL rc = FALSE;
PHYSICAL_ADDRESS phyAddr;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+%s()\r\n"), __WFUNCTION__));
phyAddr.QuadPart = CSP_BASE_REG_PA_EPIT2;
// Map peripheral physical address to virtual address
g_pEPIT = (PCSP_EPIT_REG) MmMapIoSpace(phyAddr, sizeof(CSP_EPIT_REG),
FALSE);
// Check if virtual mapping failed
if (g_pEPIT == NULL)
{
DEBUGMSG(ZONE_ERROR,
(_T("BSPTouchTimerAlloc: MmMapIoSpace failed!\r\n")));
goto cleanUp;
}
rc = TRUE;
cleanUp:
if (!rc) BSPTouchDealloc();
DEBUGMSG(ZONE_FUNCTION, (TEXT("-%s()\r\n"), __WFUNCTION__));
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: BSPTouchDeinit
//
// Deinitializes the BSP-specific interfaces and data structures for
// touch support
//
// Parameters:
// None.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
void BSPTouchDeinit(void)
{
HANDLE hEvent;
DEBUGMSG(ZONE_FUNCTION, (TEXT("-%s()\r\n"), __WFUNCTION__));
// Disable timer
if (g_pEPIT != NULL) BSPTouchTimerDisable();
// Deinitialize PMIC touch interface
PmicTouchDeinit();
// If interrupt has been registered with OAL
if (gIntrTouch != SYSINTR_UNDEFINED)
{
InterruptDone( gIntrTouch );
InterruptDisable( gIntrTouch );
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &gIntrTouch, sizeof(gIntrTouch), NULL, 0, NULL);
gIntrTouch = SYSINTR_UNDEFINED;
// If the touch panel was hijacked from GWES during CETK testing,
// restore the GWES bindings to the OAL
if (gTouchEventName == gEventNameAlt)
{
gTouchEventName = gEventNamePri;
// Reenable panel
PmicTouchInit();
// Obtain SYSINTR values from the OAL for the touch interrupts.
// InterruptInitialize is called within MDD
KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &gTouchTimerIrq,
sizeof(gTouchTimerIrq), &gIntrTouch, sizeof(gIntrTouch), NULL);
hEvent = CreateEvent( NULL, FALSE, FALSE, gTouchEventName);
InterruptInitialize(gIntrTouch, hEvent, NULL, 0);
CloseHandle(hEvent);
hEvent = NULL;
gIntrTouch = SYSINTR_UNDEFINED;
}
}
// Deallocate touch data structures
BSPTouchDealloc();
DEBUGMSG(ZONE_FUNCTION, (TEXT("-%s()\r\n"), __WFUNCTION__));
}
//-----------------------------------------------------------------------------
//
// Function: BSPTouchAttach
//
// The function performs BSP-specific attachment allocations and assignments.
//
// Parameters:
// None.
//
// Returns:
// Handle to an event that will be used by the touch MDD for interrupt
// registration.
//
//-----------------------------------------------------------------------------
extern "C" HANDLE BSPTouchAttach(void)
{
gTouchEventName = gEventNamePri;
// Determine if touch is already to attached (i.e. to GWES) and
// we are trying to hijack the interrupt signaling (i.e. for TUX)
if (KernelIoControl(IOCTL_HAL_IRQ2SYSINTR, &gTouchTimerIrq,
sizeof(gTouchTimerIrq), &gIntrTouch, sizeof(gIntrTouch), NULL))
{
// If panel interrupt registered to another process
if (gIntrTouch != SYSINTR_UNDEFINED)
{
InterruptDone( gIntrTouch );
InterruptDisable( gIntrTouch );
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &gIntrTouch, sizeof(gIntrTouch), NULL, 0, NULL);
gIntrTouch = SYSINTR_UNDEFINED;
gTouchEventName = gEventNameAlt;
}
}
return CreateEvent(NULL, FALSE, FALSE, gTouchEventName);
}
//-----------------------------------------------------------------------------
//
// Function: BSPTouchInit
//
// Initializes BSP-specific interfaces and data structures for touch support
//
// Parameters:
// dwIntervalMsec
// [in] Specifies the interval in msec to be used for generating
// a periodic timer interrupt. This interval sets the sample
// rate of the touch driver.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL BSPTouchInit(DWORD dwIntervalMsec)
{
BOOL rc = FALSE;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+%s()\r\n"), __WFUNCTION__));
// Allocate touch data structures
if (!BSPTouchAlloc())
{
ERRORMSG(TRUE, (_T("BSPTouchInit: BSPTouchAlloc failed\r\n")));
goto cleanUp;
}
// Obtain SYSINTR values from the OAL for the touch interrupts.
// InterruptInitialize is called within MDD
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &gTouchTimerIrq,
sizeof(gTouchTimerIrq), &gIntrTouch, sizeof(gIntrTouch), NULL))
{
ERRORMSG(TRUE, (_T("BSPTouchInit: Failed to request the touch sysintr.\r\n")));
gIntrTouch = SYSINTR_UNDEFINED;
goto cleanUp;
}
// Initialize touch controller on PMIC
if (PmicTouchInit() != PMIC_SUCCESS)
{
ERRORMSG(TRUE, (_T("BSPTouchInit: PmicTouchInit failed\r\n")));
goto cleanUp;
}
// Initialize the touch timer
if (!BSPTouchTimerInit(dwIntervalMsec))
{
ERRORMSG(TRUE, (_T("BSPTouchInit: BSPTouchTimerInit failed\r\n")));
goto cleanUp;
}
rc = TRUE;
cleanUp:
if (!rc) BSPTouchDeinit();
DEBUGMSG(ZONE_FUNCTION, (TEXT("-%s()\r\n"), __WFUNCTION__));
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: BSPTouchGetSample
//
// This function is used to get touch screen samples from the ADS7843
// touch screen controller.
//
// Parameters:
// x
// [out] Points to x sample coordinate.
//
// y
// [out] Points to y sample coordinate.
//
// Returns:
// Current touch panel status as TOUCH_PANEL_SAMPLE_FLAGS type.
//
//-----------------------------------------------------------------------------
TOUCH_PANEL_SAMPLE_FLAGS BSPTouchGetSample(INT *x, INT *y)
{
UINT16 adc_x[3], adc_y[3];
INT32 d0, d1, d2;
static UINT16 hys_x[2];
static UINT16 hys_y[2];
static UINT32 hysIndex;
static BOOL bPenDown = FALSE;
TOUCH_PANEL_SAMPLE_FLAGS StateFlags = TouchSampleDownFlag;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+%s()\r\n"), __WFUNCTION__));
// Request touch samples from PMIC
if (PmicADCTouchRead(adc_x, adc_y) != PMIC_SUCCESS)
{
// Tell upper layers to ignore this attempt and
// clear the TouchSampleDownFlag
StateFlags = TouchSampleIgnore;
goto cleanUp;
}
// Check for pen up condition
for (int i=0; i<3; i++)
{
if ((adc_x[i] >= ADC_SAMPLE_MAX_VALUE) || (adc_y[i] >= ADC_SAMPLE_MAX_VALUE))
{
// Tell upper layers to ignore this attempt and
// clear the TouchSampleDownFlag
StateFlags = TouchSampleIgnore;
goto cleanUp;
}
}
// Calculate absolute differences between x-coordinate samples
d0 = ABS(adc_x[0] - adc_x[1]);
d1 = ABS(adc_x[1] - adc_x[2]);
d2 = ABS(adc_x[0] - adc_x[2]);
// Reject the samples if the spread is too large
if ((d0 > DELTA_X_COORD_VARIANCE) || (d1 > DELTA_X_COORD_VARIANCE) ||
(d2 > DELTA_X_COORD_VARIANCE))
{
StateFlags |= TouchSampleIgnore;
goto cleanUp;
}
// Pick the two samples closest together
if (d0 < d1)
{
if (d0 < d2)
{
// Sample 0 & 1 closest together
*x = adc_x[0] + adc_x[1];
}
else
{
// Sample 0 & 2 closest together
*x = adc_x[0] + adc_x[2];
}
}
else
{
if (d1 < d2)
{
// Sample 1 & 2 closest together
*x = adc_x[1] + adc_x[2];
}
else
{
// Sample 0 & 2 closest together
*x = adc_x[0] + adc_x[2];
}
}
// Calculate absolute differences between y-coordinate samples
d0 = ABS(adc_y[0] - adc_y[1]);
d1 = ABS(adc_y[1] - adc_y[2]);
d2 = ABS(adc_y[0] - adc_y[2]);
if ((d0 > DELTA_Y_COORD_VARIANCE) || (d1 > DELTA_Y_COORD_VARIANCE) ||
(d2 > DELTA_Y_COORD_VARIANCE))
{
StateFlags |= TouchSampleIgnore;
goto cleanUp;
}
// Pick the two samples closest together
if (d0 < d1)
{
if (d0 < d2)
{
// Sample 0 & 1 closest together
*y = adc_y[0] + adc_y[1];
}
else
{
// Sample 0 & 2 closest together
*y = adc_y[0] + adc_y[2];
}
}
else
{
if (d1 < d2)
{
// Sample 1 & 2 closest together
*y = adc_y[1] + adc_y[2];
}
else
{
// Sample 0 & 2 closest together
*y = adc_y[0] + adc_y[2];
}
}
if (!bPenDown)
{
bPenDown = TRUE;
// Prime the hysteresis buffers with average of two
// best samples from ADC
*x = *x >> 1;
*y = *y >> 1;
hys_x[0] = hys_x[1] = *x;
hys_y[0] = hys_y[1] = *y;
}
else
{
// Implement noise rejection since transition to pen up
// condition often gives us a spike in samples
if (ABS(*x - (hys_x[0] + hys_x[1])) > (DELTA_X_COORD_VARIANCE*8))
{
StateFlags |= TouchSampleIgnore;
goto cleanUp;
}
if (ABS(*y - (hys_y[0] + hys_y[1])) > (DELTA_Y_COORD_VARIANCE*8))
{
StateFlags |= TouchSampleIgnore;
goto cleanUp;
}
// Average two best samples from ADC with samples
// from hysteresis buffer
*x = (hys_x[0] + hys_x[1] + *x) >> 2;
*y = (hys_y[0] + hys_y[1] + *y) >> 2;
// Replace an entry in hysteresis buffer
hys_x[hysIndex & 0x1] = *x;
hys_y[hysIndex & 0x1] = *y;
hysIndex++;
}
// Tell upper layers that this attempt was valid
StateFlags |= TouchSampleValidFlag;
cleanUp:
// If we need to look for next pen down event
if (!(StateFlags & TouchSampleDownFlag))
{
// Place touch controller back in standby mode
if (PmicADCTouchStandby(true) != PMIC_SUCCESS)
{
ERRORMSG(1, (_T("PmicTouchStandby failed\r\n")));
}
// Make sure pen down interrupt is unmasked
if (PmicInterruptHandlingComplete(PMIC_MC13783_INT_TSI) != PMIC_SUCCESS)
{
ERRORMSG(1, (_T("PmicInterruptHandlingComplete failed\r\n")));
}
bPenDown = FALSE;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("-%s()\r\n"), __WFUNCTION__));
return StateFlags;
}
//-----------------------------------------------------------------------------
//
// Function: BSPTouchPowerHandler
//
// DESCRIPTION:
// This function enable and disable the PEN_IRQ, the function
// also disable timer during power down
//
// Parameters:
// boff - TRUE : power down
// - FALSE : power up
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
void BSPTouchPowerHandler(BOOL boff)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+%s()\r\n"), __WFUNCTION__));
if (boff)
{
}
else
{
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("-%s()\r\n"), __WFUNCTION__));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -