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