📄 tchpdd.cpp
字号:
apAACI_WriteRegister(0x78, 0xca01);
// apAACI_WriteRegister(0x78, 0xc001);
// Init GPIO control structure.
pGpioHead = (PGPIO_REGS)(&GpioStruc);
PhysicalAddress.HighPart = 0;
PhysicalAddress.LowPart = GPIO8_BASE; //PHYS_GPIO6_BASE
pGpioHead = (PGPIO_REGS)MmMapIoSpace( PhysicalAddress, sizeof(GPIO_REGS), FALSE);
if(pGpioHead == NULL)
{
RETAILMSG(1, (TEXT("GIO_Init: Error GPIO2 MmMapIoSpace failed\r\n")));
return FALSE;
}
pGpioHead->dwGPIODir &= (~0x01);
pGpioHead->dwGPIOIE &= (~0x01);
pGpioHead->dwGPIOIC |= 0x01;
DEBUGMSG(1, (TEXT("GIO_Init: Intr disable\r\n")));
Sleep(1); // sleep for 1ms to alow screen to recharge
PddpSetupPenDownIntr(TRUE);
ResetEvent(hTouchPanelEvent); // clear down interrupt event (belt and braces)
#ifndef HIVE
TouchPanelRegInit();
TouchPanelRegLoad();
TouchPanelRegDeinit();
RETAILMSG( TRUE, (TEXT("Touchscreen: DdsiTouchPanelEnable-\r\n")) );
#endif
return( TRUE ); // we always succeed
}
// @doc EX_TOUCH_DDSI EXTERNAL DRIVERS DDSI TOUCH_PANEL
//
// @func ULONG | DdsiTouchPanelDisable |
// Powers down the touch panel device.
//
// @comm
// Implemented in the PDD.
//
VOID
DdsiTouchPanelDisable(
VOID
)
{
DEBUGMSG(1, (_T("Touchscreen: DdsiTouchPanelDisable\r\n")));
PddpTouchPanelDeallocateVm();
if (pGpioHead != NULL)
{
MmUnmapIoSpace(pGpioHead, sizeof(GPIO_REGS));
pGpioHead = NULL;
}
if (g_AudioRegBase!= NULL)
{
MmUnmapIoSpace(g_AudioRegBase, AACI_HWREGS_SIZE);
g_AudioRegBase = NULL;
}
if(g_evtSignal)
CloseHandle(g_evtSignal);
}
//
// @doc EX_TOUCH_DDSI EXTERNAL DRIVERS DDSI TOUCH_PANEL
//
// @func LONG | DdsiTouchPanelAttach |
// This routine no longer does anything. All functionallity has been moved
// from here into DdsiTouchPanelEnable to allow this code to be statically
// linked with GWE rather than existing as a DLL. Technically, when built
// as a DLL we should keep an attach count and only allow touh.dll to be
// loaded once. But, since we are loaded at boot time by GWE, there is
// no real concern about multiple loads (unless gwe has a bug!).
//
// @rdesc
// Always returns 0
//
// @comm
// Implemented in the PDD.
//
LONG
DdsiTouchPanelAttach(
VOID
)
{
return( 0 );
}
//
// @doc EX_TOUCH_DDSI EXTERNAL DRIVERS DDSI TOUCH_PANEL
//
// @func LONG | DdsiTouchPanelDetach |
// See the descrition for attach. All functionallity has been moved into
// DdsiTouchPanelDisable.
//
// @rdesc
// The updated global counter. If the initializations failed, the returned
// count is 0.
//
// @comm
// Implemented in the PDD.
//
LONG
DdsiTouchPanelDetach(
VOID
)
{
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.
//
//const SAMPLE INITSAMPLES ={TouchSampleIgnore,0,0};
BOOL PrevTipUp=TRUE;
VOID
DdsiTouchPanelGetPoint(
TOUCH_PANEL_SAMPLE_FLAGS *pTipStateFlags,
INT *pUncalX,
INT *pUncalY
)
{
// DEBUGMSG(1, (TEXT("Touchscreen: DdsiTouchPanelGetPoint\r\n")));
ULONG status;
static int SampleCount = 0;
TOUCH_PANEL_SAMPLE_FLAGS TmpStateFlags;
INT TmpX = 0;
INT TmpY = 0;
// First check if the pen was down
if (PddpTouchPanelPenDown())
{
status=TOUCH_PEN_DOWN;
}
else
{
status=TOUCH_PEN_UP;
}
// By default, any sample returned will be ignored
*pTipStateFlags = TouchSampleIgnore;
// int PrevTipUp_temp = PrevTipUp?1:0;
// DEBUGMSG(1, (_T("Touchscreen: DdsiTouchPanelGetPoint - PrevTipUp:%d\r\n"), PrevTipUp_temp));
// Handle the interrupt appropriately.
// The possible causes of the interrupt are
// - Pen down event
// - Pen up event
// - Pen coordinate sample ready.
if ((status == TOUCH_PEN_DOWN) && (PrevTipUp))
{
// DEBUGMSG(1, (TEXT("DdsiTouchPanelGetPoint - Pen has gone down!!.\r\n") ) );
// RETAILMSG(1, (TEXT("DdsiTouchPanelGetPoint - Pen has gone down!!.\r\n") ) );
// We ONLY get here by a pen down GPIO interrupt
// Pen has gone down - enable the timer and disable the pen down interrupt.
PddpSetupPenDownIntr(FALSE);
// the timer will trigger the same response as the PENIRQ line, thus
// setting up a timer callback
// DEBUGMSG(1, (TEXT("DdsiTouchPanelGetPoint - Running Timer\r\n") ) );
// Set user input event
SetEvent(g_evtSignal);
pTimer->Timer0.InterruptClear = 1;
pTimer->Timer0.Control = pTimer->Timer0.Control | (TimerControlEnable);
// The position returned is to be ignored
for (unsigned long irg=0;irg<PENUP_SAMPLE_REJECT;irg++)
{
iPipe[irg].Flags=TouchSampleIgnore;
}
// don't give TouchSampleDown here for cases where the pen touch is really brief!
*pTipStateFlags = TouchSampleIgnore;
PrevTipUp =FALSE;
/*
DEBUGMSG(1, (TEXT("DdsiTouchPanelGetPoint - Sending Pen down to MDD \r\n") ) );
if (*pTipStateFlags & TouchSampleValidFlag) {
DEBUGMSG(1, (TEXT("PenDown-Valid sample. X = 0x%4X, Y = 0x%4X, Flags = 0x%4X\r\n"),
*pUncalX, *pUncalY,*pTipStateFlags) );
} else {
DEBUGMSG(1, (TEXT("PenDown-Invalid sample. X = 0x%4X, Y = 0x%4X, Flags = 0x%4X\r\n"),
*pUncalX, *pUncalY,*pTipStateFlags) );
}
*/
}
else if (status == TOUCH_PEN_UP)
{
// DEBUGMSG(1, (TEXT("DdsiTouchPanelGetPoint - Pen has gone up.\r\n") ) );
// Pen has gone up
// We only get here by a timer call
// But as the pen is now up we ought to remove the ability of the timer thread
// DEBUGMSG(1, (TEXT("DdsiTouchPanelGetPoint - Disabling Timer\r\n") ) );
pTimer->Timer0.Control = pTimer->Timer0.Control & ~(TimerControlEnable);
pTimer->Timer0.InterruptClear = 1;
// Pen up is indicated by the absence of TouchSampleDownFlag in
// the TipStateFlags. Where available, the most recent valid x
// and y coords are returned with the pen up state. It appears
// from the PeRP driver that this these coords are not important,
// however.
// Only report a pen up if the last valid thing reported wasn't
// a pen up (to ensure that GWE doesn't get multiple pen up events)
if ((iPipe[0].Flags & TouchSampleDownFlag) &&
(iPipe[0].Flags & TouchSampleValidFlag) &&
(SampleCount >= TOUCH_NUM_REJECT))
{
// we have to show previous valid sample and pen up
*pTipStateFlags = TouchSampleValidFlag;
*pUncalX = iPipe[0].Xval;
*pUncalY = iPipe[0].Yval;
// DEBUGMSG(1, (TEXT("PenUP-Sending pen up to MDD\r\n") ) );
}
else
{
// DEBUGMSG(1, (TEXT("Pen is up, but was never down to system \r\n") ) );
*pTipStateFlags = TouchSampleIgnore;
/* if(fp==NULL)
fp = fopen("\\NandFlash\\debugpa.txt", "r+");
if(fp)
{
fprintf(fp, "N ");
fflush(fp);
fclose(fp);
}
*/ }
// Clear the previous state storage
iPipe[0].Flags = TouchSampleIgnore;
iPipe[0].Xval = iPipe[0].Yval = 0;
SampleCount = 0;
PrevTipUp =TRUE;
// Re-enable that GPIO line for interrupts (no timer)
PddpSetupPenDownIntr(TRUE);
/* if (*pTipStateFlags & TouchSampleValidFlag) {
DEBUGMSG(1, (TEXT("Valid sample. X = 0x%4X, Y = 0x%4X, Flags = 0x%4X\r\n"),
*pUncalX, *pUncalY,*pTipStateFlags) );
} else {
DEBUGMSG(1, (TEXT("Invalid sample. X = 0x%4X, Y = 0x%4X, Flags = 0x%4X\r\n"),
*pUncalX, *pUncalY,*pTipStateFlags) );
}
*/
}
else
{
// New pen coordinate sample is ready
// We only get here by a timer thread event - but as we want these to
// continue - so do nothing to it!
// We always return the previously sampled X and Y coords.
// This ensures that if a pen up occurs, we won't return an
// (x,y) pair that was sampled at the same time as the pen up.
// Not doing this results in the ends of some lines having a tail
// as the pen went up after pen up sampling but before x,y sampling
*pTipStateFlags = iPipe[0].Flags;
*pUncalX = iPipe[0].Xval;
*pUncalY = iPipe[0].Yval;
if(*pUncalX <10 || *pUncalY <10)
{
*pTipStateFlags = TouchSampleIgnore;
/* if(fp==NULL)
fp = fopen("\\NandFlash\\debug.txt", "w+");
if(fp)
{
if(TouchSampleIgnore!=iPipe[0].Flags)
fprintf(fp, "flag %d tSI %d ",iPipe[0].Flags,TouchSampleIgnore);
fflush(fp);
}
*/ }
// DEBUGMSG(1, (TEXT("DdsiTouchPanelGetPoint sample. X = 0x%4X, Y = 0x%4X, Flags = 0x%4X\r\n"),
// iPipe[0].Xval, iPipe[0].Yval, iPipe[0].Flags) );
PrevTipUp =FALSE;
// Get the coordinates
// The pen is down, but the coordinates are still by default ignored
TmpStateFlags = TouchSampleDownFlag | TouchSampleIgnore;
// Get and ev baluate the coordinates. If they are OK, the state flags
// will be altered to indicate that they are valid.
PddpTouchPanelEvaluateSamples( &TmpStateFlags, &TmpX, &TmpY);
// To work around hardware problems, ignore first few samples
// left in for possible future use
if( SampleCount < TOUCH_NUM_REJECT ) {
SampleCount++;
*pTipStateFlags = TouchSampleIgnore;
TmpStateFlags = TouchSampleIgnore;
}
// If this is a valid sample, remember it
if (TmpStateFlags & TouchSampleValidFlag)
{
for (int i=0;i<(PENUP_SAMPLE_REJECT-1); i++)
{
iPipe[i] = iPipe[i+1];
}
iPipe[i].Flags= TmpStateFlags;
iPipe[i].Xval = TmpX;
iPipe[i].Yval = TmpY;
// DEBUGMSG(1, (TEXT("iPipe value: i= %d iPipe[i].Xval= %d, iPipe[i] = %d, iPipe[i].Flags = %d\r\n"),
// i, iPipe[i].Xval, iPipe[i].Yval, iPipe[i].Flags) );
}
/*
if (*pTipStateFlags & TouchSampleValidFlag) {
DEBUGMSG(1, (TEXT("Valid sample. X = 0x%4X, Y = 0x%4X, Flags = 0x%4X\r\n"),
*pUncalX, *pUncalY,*pTipStateFlags) );
} else {
DEBUGMSG(1, (TEXT("ELSE-Invalid sample. X = 0x%4X, Y = 0x%4X, Flags = 0x%4X\r\n"),
*pUncalX, *pUncalY,*pTipStateFlags) );
}
*/ }
ResetEvent(hTouchPanelEvent);
pTimer->Timer0.Load = OEM_COUNT_1MS * MS_BETWEEN_READINGS;
pTimer->Timer0.InterruptClear = 1;
InterruptDone(gIntrTouch);
InterruptDone(gIntrTouchChanged);
return;
}
/*++
@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
)
{
#ifndef HIVE
TouchPanelRegInit();
TouchPanelRegSave();
TouchPanelRegDeinit();
RETAILMSG(1, (TEXT("Touchscreen: DdsiTouchPanelPowerHandler-\r\n")));
#endif
}
static inline void
TouchPanelPowerOff()
{
// the Touchscreen will automatically power down between samples, so
// no further work to be done here
// If the ^PenIRQ line was pulled up using GPIO instead of Vcc then
// it could be turned off here
}
static void
TouchPanelPowerOn()
{
// as we don't do anything above then we can't do anything here
}
#define TOUCHP_READ 2
#define TOUCHP_WRITE 3
static int apAACI_ReadRegister(volatile int reg)
{
#ifdef WAV_DEBUG
USHORT ret;
USHORT data = reg;
ULONG size;
if(!g_AudioRegBase)return FALSE;
if(hd_9712 != INVALID_HANDLE_VALUE)
DeviceIoControl(hd_9712, TOUCHP_READ, (BYTE*)&data, sizeof(USHORT), &ret, NULL, &size, NULL);
if(fp)
{
fprintf(fp, "touchp read: reg = %x, res=%x\n", reg, ret);
}
return ret;
#else
int timer;
unsigned int data;//, stat;
if(!g_AudioRegBase)return FALSE;
ENTERMUTEX;
timer = AACI_TIMEOUT;
//先放数据,再放地址
while ((*((DWORD*)(g_AudioRegBase + AACI_SLFR)) & AACI_SL1TXBUSY) && timer) {//等待slot1 的传送寄存器空闲
udelay(10);
timer--;
}
//先放数据,再放地址
*((DWORD*)(g_AudioRegBase + AACI_SL2TX)) = 0;
//地址为8BIT,所以应该放在20位中的高8位,所以要向右移12位
*((DWORD*)(g_AudioRegBase + AACI_SL1TX)) = (reg << 12) | 0x80000;
timer = LOOP_TIME;
while(((*((DWORD*)(g_AudioRegBase+AACI_SLFR)) & 0x100) == 0) && timer){//当退出这个循环的时候表示数据已经接收到了
udelay(10);
timer--;
}
data = (*((DWORD*)(g_AudioRegBase+AACI_SL2RX)) >> 4);
RELEASEMUTEX;
return data;
#endif
}
// Write a value to a CODEC control register
static int apAACI_WriteRegister(volatile int reg, int value)
{
#ifdef WAV_DEBUG
PARA para;
para.reg = reg;
para.data = value;
int ret;
if(!g_AudioRegBase)return FALSE;
if(hd_9712 != INVALID_HANDLE_VALUE)
DeviceIoControl(hd_9712, TOUCHP_WRITE, (BYTE*)¶, sizeof(PARA), &ret, NULL, NULL, NULL);
return TRUE;
#else
int timer;
if(!g_AudioRegBase)return FALSE;
//AACI_SLFR ---#define AACI_SL1TXBUSY 0x0002---Slot 1 transceive busy????
// Wait for TX1/2 not to be busy
timer = LOOP_TIME;
ENTERMUTEX;
while ((*((DWORD*)(g_AudioRegBase+AACI_SLFR)) & AACI_SL1TXBUSY) && timer) {//等待slot1 的传送寄存器空闲
udelay(10);
timer--;
}
// Note: the data value must be setup before the address
*((DWORD*)(g_AudioRegBase+AACI_SL2TX)) = value << 4;//数据寄存器
*((DWORD*)(g_AudioRegBase+AACI_SL1TX)) = reg << 12;//地址寄存器
RELEASEMUTEX;
if (timer)
return TRUE;
else
return FALSE;
#endif
}
void udelay(unsigned int usec)
{
int i;
i = usec *33;
while(i--);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -