【原创】彻底解决2440触摸屏跳点以及抖动问题

 

// Topic:彻底解决2440触摸屏跳点问题

// 作者:gooogleman

// 版权:gooogleman嵌入式开发板联盟wogoyixikexie@gliet.gooogleman

// 平台:wince5.0 2440 5.0 BSP (飞凌FL2440/OK2440开发板 3.5 寸LCD)

// 发布日期:2010年11月18日

// 最后修改:

//技术论坛:www.gooogleman.com 

// 注意事项:商业网站未经作者同意不能转载,并且不能删除文章的任何部分,否则追究责任!

//-------------------------------------------------------------------------------------------------

 

  其实2440触摸屏跳点问题在前一个多月已经得到解决,在我解决6410 触摸屏抖动的时候,偶然发现6410 不会任何跳点,只是抖动,后来比较2440 和6410 的触摸屏驱动写法,发现6410的比较惊异,算法避免了天外飞仙跳点。

      ooo,下班了,明天再写吧。

      ——续@2010-11-19

  我仔细比较6410 触摸屏驱动和2440 驱动,发现6410 的写法比较合理一些,最大区别是DdsiTouchPanelGetPoint函数写法,下面是2440 会跳点的写法。

  从上面可以看出,这个DdsiTouchPanelGetPoint里面只进行了一步采样,尽管采样次数大于1次,但是也绝对不能消除天外飞仙跳点。因为这几次采样时间太靠近了,所以采样值都会很相近,即使是多次采样(我曾经试过20 次,没有多大改善。),求平均值,效果也会很微小。这个情况就说明,要想触摸屏不跳点,就要消除错误的采样点,那么怎么做呢?上面每隔10ms 连续采样多次无效,原因是每次采样间隔时间太短,数据太密集,接近,导致仍然获得的是误差数据。假设想想,如果扩大采样时间间隔去采样,这样获得的数据就不会太接近就可以判断了吧?看看6410 的触摸屏驱动,果然是每隔10ms 采样两组数据的,并且这两组数据进行比较分析,误差过大就说明采样点是无效的,这样就把天外飞仙的现象去掉了。下面也贴出改好的2440 代码,希望大家有帮助。

/* :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */



PUBLIC VOID
DdsiTouchPanelGetPoint(TOUCH_PANEL_SAMPLE_FLAGS	* pTipStateFlags,
					   INT	* pUncalX,
					   INT	* pUncalY)
{
	static INT x, y;
	int TmpX = 0;
    int TmpY = 0;

	if (v_pINTregs->SUBSRCPND & (1<<IRQ_SUB_TC))		/* SYSINTR_TOUCH Interrupt Case*/
	{
		*pTipStateFlags = TouchSampleValidFlag;

		if ( (v_pADCregs->ADCDAT0 & (1 << 15)) |
			 (v_pADCregs->ADCDAT1 & (1 << 15)) )
		{
			bTSP_DownFlag = FALSE;

			DEBUGMSG(ZONE_TIPSTATE, (TEXT("up\r\n")));

			v_pADCregs->ADCTSC &= 0xff;

			*pUncalX = x;
			*pUncalY = y;

			TSP_SampleStop();
			// Test
			
			RETAILMSG(1,(TEXT("bTSP_DownFlag = FALSE...PenUP!!!\r\n")));
		}
		else 
		{
			bTSP_DownFlag = TRUE;

			//if (!TSP_GetXY(&x, &y)) 
			//	*pTipStateFlags = TouchSampleIgnore;

			//TSP_TransXY(&x, &y);

			//-----------------------add @2010.09.11-----------------------
			*pTipStateFlags |= TouchSampleIgnore;

			*pUncalX = x;
			*pUncalY = y;

			*pTipStateFlags |= TouchSampleDownFlag;

			//Test			
			RETAILMSG(1,(TEXT("bTSP_DownFlag = TRUE...PenDown!!!\r\n")));

			TSP_SampleStart();
		}

		v_pINTregs->SUBSRCPND  =  (1<<IRQ_SUB_TC);
		v_pINTregs->INTSUBMSK &= ~(1<<IRQ_SUB_TC);

		InterruptDone(gIntrTouch);
	}
	else		/* SYSINTR_TOUCH_CHANGED Interrupt Case		*/
	{
//		TSP_SampleStart();
		
		if (bTSP_DownFlag)
		{
			if (TSP_GetXY(&TmpX, &TmpY) == TRUE)
            {
                //TSP_TransXY(&TmpX, &TmpY);

                if(Touch_Pen_Filtering(&TmpX, &TmpY))
                {
                    *pTipStateFlags = TouchSampleValidFlag | TouchSampleDownFlag;
                    *pTipStateFlags &= ~TouchSampleIgnore;
                }
                else        // Invalid touch pen
                {
                    *pTipStateFlags = TouchSampleValidFlag;
                    *pTipStateFlags |= TouchSampleIgnore;
                }

                *pUncalX = x = TmpX;
                *pUncalY = y = TmpY;
            }
            else
            {
                *pTipStateFlags = TouchSampleIgnore;
            }
		}
		else
		{
			*pTipStateFlags = TouchSampleIgnore;

			TSP_SampleStop();
			
			RETAILMSG(1,(TEXT("bTSP_DownFlag = FALSE.PenDown!!!IRQ_Timer3 Interrupt\r\n")));
		}

		InterruptDone(gIntrTouchChanged);
	}

	// add by wogo at2009.03.23 why?
	SetEvent(hEventTouchInput);
}



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

    if(*px <0 && *py <0)
    {
        count = 0;
        return FALSE;
    }
    else
    {
        count++;
    }

    if (count > 2)
    {
        // apply filtering rule
        count = 2;

        // average between x,y[0] and *px,y
        TmpX = (x[0] + *px)>>1;
        TmpY = (y[0] + *py)>>1;

        // 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]);

        Filter_Margin = (x[1] > x[0]) ? (x[1]-x[0]) : (x[0]-x[1]);
        Filter_Margin += (y[1] > y[0]) ? (y[1]-y[0]) : (y[0]-y[1]);
        Filter_Margin += TSP_FILTER_LIMIT;

        if ((dx > Filter_Margin) || (dy > Filter_Margin)) {
            // 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 // (count > 2)
    { // 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;

}

  现在测试2440 的触摸屏,我们会惊奇的发现,真的没有天外飞仙跳点了,不过又引入了一个新的问题,触摸屏抖动!以前的那种写法采样时间间隔短,数据集中,是不会抖动的,现在数据差异大,触摸屏抖动的相当的厉害了!怎么办呢?这个时候增大采样次数求平均值会有一些效果,不过还是不能完全消除抖动的!现在就要用一个简单的算法了:就是采样八个点,然后从小到大排序之后,把最大和最小值去掉,因为这两个值通常都是在受力不均的时候产生的,不是真实的值,所以丢了,再求剩余几个点的平均值,这样就可以完美的消除触摸屏抖动了,下面贴出代码,希望大家也来改进一下。

PRIVATE BOOL
TSP_GetXY(INT *px, INT *py)
{
	int i,j,k,temp;
	//INT xsum, ysum;
	//int x, y;
	int dx, dy;
	int x[TSP_SAMPLE_NUM], y[TSP_SAMPLE_NUM];

	//xsum = ysum = 0;
	EnterCriticalSection(&g_csTouchADC);
	for (i = 0; i < TSP_SAMPLE_NUM; i++)
	{
		v_pADCregs->ADCTSC = (0<<8)|(1<<7)|(1<<6)|(0<<5)|(1<<4)|(1<<3)|(1<<2)|(0);			
		v_pADCregs->ADCCON |= (1 << 0);				/* Start Auto conversion				*/

		while (v_pADCregs->ADCCON & 0x1);				/* check if Enable_start is low			*/
		while (!(v_pADCregs->ADCCON & (1 << 15)));		/* Check ECFLG							*/

		x[i] = (0x3ff & v_pADCregs->ADCDAT1);
		y[i] = 0x3ff - (0x3ff & v_pADCregs->ADCDAT0);

		//x[i] = D_XPDATA_MASK(v_pADCregs->ADCDAT1);
        //y[i] = D_YPDATA_MASK(v_pADCregs->ADCDAT0);
		//xsum += x;
		//ysum += y;
	}
	
	//*px = xsum / TSP_SAMPLE_NUM;
	//*py = ysum / TSP_SAMPLE_NUM;

	v_pADCregs->ADCTSC = (1<<8)|(1<<7)|(1<<6)|(0<<5)|(1<< 4)|(0<<3)|(0<<2)|(3);	

	
	LeaveCriticalSection(&g_csTouchADC);

	//--------------------------------------------------------------
	// if mask it ,very tremble work not well
    for (j = 0; j < TSP_SAMPLE_NUM -1; ++j)
    {
        for (k = j+1; k < TSP_SAMPLE_NUM; ++k)
        {
            if(x[j]>x[k])
            {
                temp = x[j];
                x[j]=x[k];
                x[k]=temp;
            }

            if(y[j]>y[k])
            {
                temp = y[j];
                y[j]=y[k];
                y[k]=temp;
            }
        }
    }

	//dx = (*px > x) ? (*px - x) : (x - *px);
	//dy = (*py > y) ? (*py - y) : (y - *py);
	
	*px = (x[2] + ((x[3]+x[4])<<1) + (x[3]+x[4]) + x[5]);
	*py = (y[2] + ((y[3]+y[4])<<1) + (y[3]+y[4]) + y[5]);
	
	if ((*px & 0x7) > 3) 
		*px = (*px>>3) + 1;
	else *px = *px>>3;
	
	if ((*py & 0x7) > 3) 
		*py = (*py>>3) + 1;
	else *py = *py>>3;

	dx = x[5] - x[2];
    dy = y[5] - y[2];

	return ((dx > TSP_INVALIDLIMIT || dy > TSP_INVALIDLIMIT) ? FALSE : TRUE);
}

  好了,方法就是这么多了,This is it ,下面贴出效果图,收工!

wince 2440 完美解决触摸屏跳点抖动源码
http://www.gooogleman.com/forum.php?mod=viewthread&tid=507&fromuid=3

/* :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */
/* :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */



PUBLIC VOID
DdsiTouchPanelGetPoint(TOUCH_PANEL_SAMPLE_FLAGS	* pTipStateFlags,
					   INT	* pUncalX,
					   INT	* pUncalY)
{
	static INT x, y;

	if (v_pINTregs->SUBSRCPND & (1<<IRQ_SUB_TC))		/* SYSINTR_TOUCH Interrupt Case*/
	{
		*pTipStateFlags = TouchSampleValidFlag;

		if ( (v_pADCregs->ADCDAT0 & (1 << 15)) |
			 (v_pADCregs->ADCDAT1 & (1 << 15)) )
		{
			bTSP_DownFlag = FALSE;

			DEBUGMSG(ZONE_TIPSTATE, (TEXT("up\r\n")));

			v_pADCregs->ADCTSC &= 0xff;

			*pUncalX = x;
			*pUncalY = y;

			TSP_SampleStop();
			// Test
			
			RETAILMSG(1,(TEXT("bTSP_DownFlag = FALSE...PenUP!!!\r\n")));
		}
		else 
		{
			bTSP_DownFlag = TRUE;

			if (!TSP_GetXY(&x, &y)) 
				*pTipStateFlags = TouchSampleIgnore;

			TSP_TransXY(&x, &y);

			*pUncalX = x;
			*pUncalY = y;

			*pTipStateFlags |= TouchSampleDownFlag;

			//Test			
			RETAILMSG(1,(TEXT("bTSP_DownFlag = TRUE...PenDown!!!\r\n")));

			TSP_SampleStart();
		}

		v_pINTregs->SUBSRCPND  =  (1<<IRQ_SUB_TC);
		v_pINTregs->INTSUBMSK &= ~(1<<IRQ_SUB_TC);

		InterruptDone(gIntrTouch);
	}
	else		/* SYSINTR_TOUCH_CHANGED Interrupt Case		*/
	{
//		TSP_SampleStart();
		
		if (bTSP_DownFlag)
		{
			INT  tx, ty;
			INT  dx, dy;

			if (!TSP_GetXY(&tx, &ty)) 
				*pTipStateFlags = TouchSampleIgnore;
			else 
			{
				
				RETAILMSG(1,(TEXT("bTSP_DownFlag = TRUE.PenDown!!!IRQ_Timer3 Interrupt\r\n")));
				TSP_TransXY(&tx, &ty);
// insert by mostek@dstcorp.com
#define X_ERRV	0x3bf
#define Y_ERRV	0x4ff

				if ((tx == X_ERRV) && (ty == Y_ERRV))
				{
					tx = x;
					ty = y;
				} 
// =================== mostek
				dx = (tx > x) ? (tx - x) : (x - tx);
				dy = (ty > y) ? (ty - y) : (y - ty);

				if (dx > TSP_CHANGE || dy > TSP_CHANGE)
				{
					*pUncalX = x = tx;
					*pUncalY = y = ty;

					//DEBUGMSG(ZONE_TIPSTATE, (TEXT("down-c-v %x %x\r\n"), x, y));
					*pTipStateFlags = TouchSampleValidFlag | TouchSampleDownFlag;
				}
				else
				{
					*pUncalX = x;
					*pUncalY = y;

					DEBUGMSG(ZONE_TIPSTATE, (TEXT("down-c %x %x\r\n"), x, y));

					*pTipStateFlags = TouchSampleIgnore;
				}
			}
		}
		else
		{
			*pTipStateFlags = TouchSampleIgnore;

			TSP_SampleStop();
			
			RETAILMSG(1,(TEXT("bTSP_DownFlag = FALSE.PenDown!!!IRQ_Timer3 Interrupt\r\n")));
		}

		InterruptDone(gIntrTouchChanged);
	}

	// add by wogo at2009.03.23 why?
	SetEvent(hEventTouchInput);
}


//-------------------------------------------------------------------------------------------------
原文地址:https://www.cnblogs.com/gooogleman/p/1881017.html