tchpdd.cpp

来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C++ 代码 · 共 1,273 行 · 第 1/3 页

CPP
1,273
字号
// Implemented in the PDD.
//

LONG
DdsiTouchPanelAttach(
    VOID
    )
{
	RETAILMSG(TCHPDD_TEST,(_T("TOUCHP::DdsiTouchPanelAttach\r\n")));
	
    return( 1 );
}


//
// @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
    )
{
	RETAILMSG(TCHPDD_TEST,(_T("TOUCHP::DdsiTouchPanelDetach\r\n")));

    return ( 0 );
}

#define COODI_Y

//
// @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.
//
#if ( LCD_TYPE == TFT640_480 )
	#define TOUCH_MAX_X 1000
	#define TOUCH_MIN_X 30
	#define TOUCH_MAX_Y 980
	#define TOUCH_MIN_Y 30

	#define TOUCH_X	640
	#define TOUCH_Y	480
#else 
#if (S3C24A0A)
	#define TOUCH_MAX_X 890 //955 //950
	#define TOUCH_MIN_X 120 //100 //90
	#define TOUCH_MAX_Y 890 //925 //960
	#define TOUCH_MIN_Y 90 //70 //50

	#define TOUCH_X	240
	#define TOUCH_Y	320
#else
	#define TOUCH_MAX_X 890 //955 //950
	#define TOUCH_MIN_X 130 //100 //90
	#define TOUCH_MAX_Y 920 //925 //960
	#define TOUCH_MIN_Y 140 //70 //50

	#define TOUCH_X	240
	#define TOUCH_Y	320
#endif	
#endif
#define TOUCH_ERR	15
static int second = 0;

VOID Touch_CoordinateConversion(INT *px, INT *py)
{
	INT TmpX, TmpY;
	INT TmpX0, TmpY0;

	TmpX0 = *px; TmpY0 = *py;

	TmpX = (*px >= TOUCH_MAX_X) ? (TOUCH_MAX_X) : *px;
	TmpY = (*py >= TOUCH_MAX_Y) ? (TOUCH_MAX_Y) : *py;
	
	TmpX -= TOUCH_MIN_X;
    TmpY -= TOUCH_MIN_Y;
    
    TmpX = (TmpX) ? TmpX : 0;
    TmpY = (TmpY) ? TmpY : 0;

#if (!S3C24A0A)
	*px = (TOUCH_X - (TmpX * TOUCH_X) / (TOUCH_MAX_X-TOUCH_MIN_X))*4;
	*py = ((TmpY * TOUCH_Y) / (TOUCH_MAX_Y-TOUCH_MIN_Y))*4;
#else
	*px = (TOUCH_X - (TmpX * TOUCH_X) / (TOUCH_MAX_X-TOUCH_MIN_X))*4;
	*py = ((TmpY * TOUCH_Y) / (TOUCH_MAX_Y-TOUCH_MIN_Y))*4;
#endif	

	*px = (*px >= TOUCH_X*4)? (TOUCH_X*4 - 1) : *px;
	*py = (*py >= TOUCH_Y*4)? (TOUCH_Y*4 - 1) : *py;

#if (TCHPDD_TEST)	
	RETAILMSG(1, (TEXT("first *px,y = (%d, %d)\r\n"), TmpX0, TmpY0));
	RETAILMSG(1, (TEXT("TOUCH_MAX_X : %d\r\n"), TOUCH_MAX_X));
	RETAILMSG(1, (TEXT("TOUCH_MAX_Y : %d\r\n"), TOUCH_MAX_Y));
	RETAILMSG(1, (TEXT("TOUCH_MIN_X : %d\r\n"), TOUCH_MIN_X));
	RETAILMSG(1, (TEXT("TOUCH_MIN_Y : %d\r\n"), TOUCH_MIN_Y));
	RETAILMSG(1, (TEXT("TOUCH_X     : %d\r\n"), TOUCH_X));
	RETAILMSG(1, (TEXT("TOUCH_Y     : %d\r\n"), TOUCH_Y));	
	RETAILMSG(1, (TEXT("last  *px,y = (%d, %d)\r\n"), *px, *py));	
#endif

	return;
}


VOID
DdsiTouchPanelGetPoint(
	TOUCH_PANEL_SAMPLE_FLAGS	*pTipStateFlags,
	INT							*pUncalX,
	INT							*pUncalY
    )
{
	ULONG status;
//	USHORT ioAdcCntr, intrMask;
    static int SampleCount = 0;
    static TOUCH_PANEL_SAMPLE_FLAGS PrevStateFlags = TouchSampleIgnore;
    static INT PrevX = 0;
    static INT PrevY = 0;
    TOUCH_PANEL_SAMPLE_FLAGS TmpStateFlags;
    INT TmpX = 0;
    INT TmpY = 0;
    static int i = 0;

	RETAILMSG(TCHPDD_TEST,(_T("DdsiTouchPanelGetPoint\r\n")));
	
    // Read the status passed back by the HAL
//    status = READ_REGISTER_ULONG( &(v_pDriverGlobals->tch.status) );
    status = v_pDriverGlobals->tch.status;
	i++;
	RETAILMSG(TCHPDD_TEST,(_T("TCHPDD::0x%X - %d\r\n"), i, i));
	
    if(status == TOUCH_PEN_UP) {
		RETAILMSG(TCHPDD_TEST,(_T("status = TOUHC_PEN_UP\r\n")));
		*pTipStateFlags = TouchSampleValidFlag;
		*pUncalX = PrevX;
		*pUncalY = PrevY;
		
		InterruptDone( gIntrTouchChanged );
	} 
	else if(status == TOUCH_PEN_DOWN) {
		
		RETAILMSG(TCHPDD_TEST,(_T("status = TOUHC_PEN_DOWN\r\n")));
		*pTipStateFlags |= TouchSampleIgnore;
		*pUncalX = PrevX;
		*pUncalY = PrevY;

		// now start timer1 (oneshot)
		Touch_Timer0_Setup();

		InterruptDone( gIntrTouchChanged );
		
	} else {
		
		RETAILMSG(TCHPDD_TEST,(_T("status etc -> get touch sample\r\n")));

		if ( (v_pADCregs->ADCDAX & 0x8000) || (v_pADCregs->ADCDAY & 0x8000) )
		{
			v_pADCregs->ADCTSC = 0xD3;	// Set stylus down interrupt
			*pTipStateFlags = TouchSampleValidFlag;
			*pUncalX = PrevX;
			*pUncalY = PrevY;
			InterruptDone( gIntrTouchChanged );
		}
		else {
			
			// <Auto X-Position and Y-Position Read>

			for (i =0; i < NUMBER_SAMPLES_PER_POINT; i++) {
				v_pADCregs->ADCTSC = (0<<8)|(13<<4)|(1<<3)|(1<<2)|(0);
				v_pADCregs->ADCCON |= 0x1;	// Start Auto conversion

				while(v_pADCregs->ADCCON & 0x1);	//check if Enable_start is low
				while(!(0x8000&(v_pADCregs->ADCCON)));	// Check ECFLG
#if (!S3C24A0A)
				xbuf[i] = 0x3ff & v_pADCregs->ADCDAX;
				ybuf[i] = 0x3ff & v_pADCregs->ADCDAY;
#else
				xbuf[i] = 0x3ff & v_pADCregs->ADCDAX;
				ybuf[i] = 0x3ff & v_pADCregs->ADCDAY;
#endif

			}	

			v_pADCregs->ADCTSC=(0<<8)|(13<<4)|(0<<3)|(0<<2)|1;//for returning to X-position....

	 		PddpTouchPanelEvaluateSamples( &TmpStateFlags, &TmpX, &TmpY);

			v_pADCregs->ADCTSC = 0xd3; //for waiting interruupt
	
			Touch_CoordinateConversion(&TmpX, &TmpY);    

			if (Touch_Pen_filtering(&TmpX, &TmpY)) // Valid touch pen
		        {
		    		RETAILMSG(TCHPDD_TEST, (TEXT("valid touch pen\r\n")));
				*pTipStateFlags = TouchSampleValidFlag | TouchSampleDownFlag;			
				*pTipStateFlags &= ~TouchSampleIgnore;
			}
			else	// Invalid touch pen 
			{
		    		RETAILMSG(TCHPDD_TEST, (TEXT("invalid touch pen\r\n")));
				*pTipStateFlags = TouchSampleValidFlag;
				*pTipStateFlags |= TouchSampleIgnore;				
			}		

			*pUncalX = PrevX = TmpX;
			*pUncalY = PrevY = TmpY;

	   		InterruptDone( gIntrTouch );
	
			RETAILMSG(0, (TEXT("0 - (%d, %d) 0x%X\r\n"), *pUncalX, *pUncalY, *pTipStateFlags));
		}
	}

    return;
}

#define FILTER_LIMIT 25

static BOOL
Touch_Pen_filtering(INT *px, INT *py)
{
	BOOL RetVal = TRUE;
	// TRUE  : Valid pen sample
	// FALSE : Invalid pen sample
	static int count = 0;
	static INT x[2], y[2];
	INT TmpX, TmpY;
	INT dx, dy;

	count++;

	if (count > 2) 
	{ 
		// apply filtering rule
		count = 2;
		
		// average between x,y[0] and *px,y
		TmpX = (x[0] + *px) / 2;
		TmpY = (y[0] + *py) / 2;
		
		// difference between x,y[1] and TmpX,Y
		dx = (x[1] > TmpX) ? (x[1] - TmpX) : (TmpX - x[1]);
		dy = (y[1] > TmpY) ? (y[1] - TmpY) : (TmpY - y[1]);
		
		if ((dx > FILTER_LIMIT) || (dy > FILTER_LIMIT)) {

			// Invalid pen sample

			*px = x[1];
			*py = y[1]; // previous valid sample
			RetVal = FALSE;
			count = 0;
			
		} else {
			// Valid pen sample
			x[0] = x[1]; y[0] = y[1];		
			x[1] = *px; y[1] = *py; // reserve pen samples
			
			RetVal = TRUE;
		}
		
	} else { // till 2 samples, no filtering rule
	
		x[0] = x[1]; y[0] = y[1];		
		x[1] = *px; y[1] = *py; // reserve pen samples
		
		RetVal = FALSE;	// <- TRUE jylee 2003.03.04 
	}
	
	return RetVal;
}



/*++

 @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
	)
{
	RETAILMSG(1,(_T("DdsiTouchPanelPowerHandler\r\n")));
	
    // Set flag so we know to avoid system calls
    bInPowerHandler = TRUE;

    if (bOff) {
        TouchPanelPowerOff();
    }
    else {
        TouchPanelPowerOn();
        PddpSetupPenDownIntr(TRUE);
    }

    bInPowerHandler = FALSE;
}

static void
TouchPanelPowerOff()
{
    // Powering down, stop DMA and power off touch screen
    RETAILMSG(1,(TEXT("Touch Power Off\r\n")));
}


static void
TouchPanelPowerOn()
{
    DWORD tmp = 0;

    //
    // Setup ADC register
    //
    RETAILMSG(1,(TEXT("Touch Power On\r\n")));
    // Down Int, YMON:1, nYPON:1, XMON:0;nXPON:1, Pullup:1, Auto Conv.,Waiting.
    // XP pullup En,Normal,Waiting for interrupt mode
    	// v_pADCregs->ADCTSC = (0<<8)|(13<<4)|(0<<3)|(0<<2)|(3);
	v_pADCregs->ADCDLY = ADC_DELAY_TIME;	//default value for delay.    
    	// v_pADCregs->ADCCON = (1<<14)|(ADCPRS<<6)|(0<<3)|(0<<2)|(0<<1)|0;
    	v_pADCregs->ADCCON =	(1 << 14) |		//A/D Converter Enable	
				(ADCPRS	<<  6) |	// Prescaler Setting
				(0 <<  3) |		// Analog Input Channel : 0
				(0 <<  2) |		// Normal Operation Mode
				(0 <<  1) |		// Disable Read Start
				(0 <<  0);		// No Operation

	v_pADCregs->ADCTSC =	(0 << 8) |	// UD_Sen
				(1 <<  7) |	// YMON  1 (YM = GND)
				(1 <<  6) |	// nYPON 1 (YP Connected AIN[n])
				(0 <<  5) |	// XMON  0 (XM = Z)
				(1 <<  4) |	// nXPON 1 (XP = AIN[7])
				(0 <<  3) |	// Pull Up Disable
				(0 <<  2) |	// Normal ADC Conversion Mode
				(3 <<  0);	// Waiting Interrupt
    RETAILMSG(1,(TEXT("Touch Init.. done\r\n")));

	return ;
}


static BOOL Touch_Timer0_Setup(void) 
{
	unsigned int TmpTCON;

    //
    // We use Timer1 of PWM as OS Clock.

    RETAILMSG(TCHPDD_TEST,(TEXT("Touch_Timer0_Setup\r\n")));

    // Disable Timer1 Init..
    v_pINTregs->INTMSK |= BIT_TIMER1;     // Mask timer1 interrupt.
    v_pINTregs->SRCPND = BIT_TIMER1;     // Clear pending bit
    v_pINTregs->INTPND = BIT_TIMER1;

    v_pPWMregs->TCFG0 = (v_pPWMregs->TCFG0 & ~(0xff)) | (TOUCH_TIMER_PRESCALER); 
    // prescaler value = 24 + 1

  	v_pPWMregs->TCFG1 &= ~(0xf0);
#if( TOUCH_TIMER_DIVIDER == 2 )
  	v_pPWMregs->TCFG1  |=  (0   << 4);		/* 1/2							*/
#elif ( TOUCH_TIMER_DIVIDER == 4 )
  	v_pPWMregs->TCFG1  |=  (1   << 4);		/* 1/4							*/
#elif ( TOUCH_TIMER_DIVIDER == 8 )
  	v_pPWMregs->TCFG1  |=  (2   << 4);		/* 1/8							*/
#elif ( TOUCH_TIMER_DIVIDER == 16 )
  	v_pPWMregs->TCFG1  |=  (3   << 4);		/* 1/16							*/
#endif

    v_pPWMregs->TCNTB1 = (10 * (S3C24A0_PCLK / (TOUCH_TIMER_PRESCALER+1) / TOUCH_TIMER_DIVIDER)) / 1000;	
	
	RETAILMSG(0,(_T("TCHPDD::TIMER1 COUNT VALUE=%d\r\n"), v_pPWMregs->TCNTB1));							
    v_pPWMregs->TCMPB1 = 0;   	

	TmpTCON = v_pPWMregs->TCON;	// get TCON value to temp TCON register
	v_pPWMregs->TCON = (TmpTCON & ~(0xf00)) | (0x200);	// stop, one-shot, inverter off, TCNTB1 update
	v_pPWMregs->TCON = (TmpTCON & ~(0xf00)) | (0x100);	// start

    v_pINTregs->INTMSK &= ~BIT_TIMER1;    
 
 	return TRUE;   
}

⌨️ 快捷键说明

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