彻底解决2440触摸屏跳点以及抖动问题
// Topic:彻底解决2440触摸屏跳点问题
// 作者:gooogleman
// 版权:桂林电子科技大学一系科协wogoyixikexie@gliet.gooogleman
// 平台:wince5.0 2440 5.0 BSP (飞凌FL2440开发板)
// 发布日期: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 代码,希望大家有帮助。
001 | /* :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */ |
002 | |
003 | |
004 | |
005 | PUBLIC VOID |
006 | DdsiTouchPanelGetPoint(TOUCH_PANEL_SAMPLE_FLAGS * pTipStateFlags, |
007 | INT * pUncalX, |
008 | INT * pUncalY) |
009 | { |
010 | static INT x, y; |
011 | int TmpX = 0; |
012 | int TmpY = 0; |
013 | |
014 | if (v_pINTregs->SUBSRCPND & (1<<IRQ_SUB_TC)) /* SYSINTR_TOUCH Interrupt Case*/ |
015 | { |
016 | *pTipStateFlags = TouchSampleValidFlag; |
017 | |
018 | if ( (v_pADCregs->ADCDAT0 & (1 << 15)) | |
019 | (v_pADCregs->ADCDAT1 & (1 << 15)) ) |
020 | { |
021 | bTSP_DownFlag = FALSE; |
022 | |
023 | DEBUGMSG(ZONE_TIPSTATE, (TEXT( "up/r/n" ))); |
024 | |
025 | v_pADCregs->ADCTSC &= 0xff; |
026 | |
027 | *pUncalX = x; |
028 | *pUncalY = y; |
029 | |
030 | TSP_SampleStop(); |
031 | // Test |
032 | |
033 | RETAILMSG(1,(TEXT( "bTSP_DownFlag = FALSE...PenUP!!!/r/n" ))); |
034 | } |
035 | else |
036 | { |
037 | bTSP_DownFlag = TRUE; |
038 | |
039 | //if (!TSP_GetXY(&x, &y)) |
040 | // *pTipStateFlags = TouchSampleIgnore; |
041 | |
042 | //TSP_TransXY(&x, &y); |
043 | |
044 | //-----------------------add @2010.09.11----------------------- |
045 | *pTipStateFlags |= TouchSampleIgnore; |
046 | |
047 | *pUncalX = x; |
048 | *pUncalY = y; |
049 | |
050 | *pTipStateFlags |= TouchSampleDownFlag; |
051 | |
052 | //Test |
053 | RETAILMSG(1,(TEXT( "bTSP_DownFlag = TRUE...PenDown!!!/r/n" ))); |
054 | |
055 | TSP_SampleStart(); |
056 | } |
057 | |
058 | v_pINTregs->SUBSRCPND = (1<<IRQ_SUB_TC); |
059 | v_pINTregs->INTSUBMSK &= ~(1<<IRQ_SUB_TC); |
060 | |
061 | InterruptDone(gIntrTouch); |
062 | } |
063 | else /* SYSINTR_TOUCH_CHANGED Interrupt Case */ |
064 | { |
065 | // TSP_SampleStart(); |
066 | |
067 | if (bTSP_DownFlag) |
068 | { |
069 | if (TSP_GetXY(&TmpX, &TmpY) == TRUE) |
070 | { |
071 | //TSP_TransXY(&TmpX, &TmpY); |
072 | |
073 | if (Touch_Pen_Filtering(&TmpX, &TmpY)) |
074 | { |
075 | *pTipStateFlags = TouchSampleValidFlag | TouchSampleDownFlag; |
076 | *pTipStateFlags &= ~TouchSampleIgnore; |
077 | } |
078 | else // Invalid touch pen |
079 | { |
080 | *pTipStateFlags = TouchSampleValidFlag; |
081 | *pTipStateFlags |= TouchSampleIgnore; |
082 | } |
083 | |
084 | *pUncalX = x = TmpX; |
085 | *pUncalY = y = TmpY; |
086 | } |
087 | else |
088 | { |
089 | *pTipStateFlags = TouchSampleIgnore; |
090 | } |
091 | } |
092 | else |
093 | { |
094 | *pTipStateFlags = TouchSampleIgnore; |
095 | |
096 | TSP_SampleStop(); |
097 | |
098 | RETAILMSG(1,(TEXT( "bTSP_DownFlag = FALSE.PenDown!!!IRQ_Timer3 Interrupt/r/n" ))); |
099 | } |
100 | |
101 | InterruptDone(gIntrTouchChanged); |
102 | } |
103 | |
104 | // add by wogo at2009.03.23 why? |
105 | SetEvent(hEventTouchInput); |
106 | } |
107 | |
108 | |
109 | |
110 | static BOOL |
111 | Touch_Pen_Filtering( INT *px, INT *py) |
112 | { |
113 | BOOL RetVal = TRUE; |
114 | // TRUE : Valid pen sample |
115 | // FALSE : Invalid pen sample |
116 | INT Filter_Margin; |
117 | static int count = 0; |
118 | static INT x[2], y[2]; |
119 | INT TmpX, TmpY; |
120 | INT dx, dy; |
121 | |
122 | if (*px <0 && *py <0) |
123 | { |
124 | count = 0; |
125 | return FALSE; |
126 | } |
127 | else |
128 | { |
129 | count++; |
130 | } |
131 | |
132 | if (count > 2) |
133 | { |
134 | // apply filtering rule |
135 | count = 2; |
136 | |
137 | // average between x,y[0] and *px,y |
138 | TmpX = (x[0] + *px)>>1; |
139 | TmpY = (y[0] + *py)>>1; |
140 | |
141 | // difference between x,y[1] and TmpX,Y |
142 | dx = (x[1] > TmpX) ? (x[1] - TmpX) : (TmpX - x[1]); |
143 | dy = (y[1] > TmpY) ? (y[1] - TmpY) : (TmpY - y[1]); |
144 | |
145 | Filter_Margin = (x[1] > x[0]) ? (x[1]-x[0]) : (x[0]-x[1]); |
146 | Filter_Margin += (y[1] > y[0]) ? (y[1]-y[0]) : (y[0]-y[1]); |
147 | Filter_Margin += TSP_FILTER_LIMIT; |
148 | |
149 | if ((dx > Filter_Margin) || (dy > Filter_Margin)) { |
150 | // Invalid pen sample |
151 | *px = x[1]; |
152 | *py = y[1]; // previous valid sample |
153 | RetVal = FALSE; |
154 | count = 0; |
155 | } |
156 | else |
157 | { |
158 | // Valid pen sample |
159 | x[0] = x[1]; y[0] = y[1]; |
160 | x[1] = *px; y[1] = *py; // reserve pen samples |
161 | |
162 | RetVal = TRUE; |
163 | } |
164 | } |
165 | else // (count > 2) |
166 | { // till 2 samples, no filtering rule |
167 | x[0] = x[1]; y[0] = y[1]; |
168 | x[1] = *px; y[1] = *py; // reserve pen samples |
169 | |
170 | RetVal = FALSE; // <- TRUE jylee 2003.03.04 |
171 | } |
172 | |
173 | return RetVal; |
174 | |
175 | } |
现在测试2440 的触摸屏,我们会惊奇的发现,真的没有天外飞仙跳点了,不过又引入了一个新的问题,触摸屏抖动!以前的那种写法采样时间间隔短,数据集中,是不会抖动的,现在数据差异大,触摸屏抖动的相当的厉害了!怎么办呢?这个时候增大采样次数求平均值会有一些效果,不过还是不能完全消除抖动的!现在就要用一个简单的算法了:就是采样八个点,然后从小到大排序之后,把最大和最小值去掉,因为这两个值通常都是在受力不均的时候产生的,不是真实的值,所以丢了,再求剩余几个点的平均值,这样就可以完美的消除触摸屏抖动了,下面贴出代码,希望大家也来改进一下。
01 | PRIVATE BOOL |
02 | TSP_GetXY( INT *px, INT *py) |
03 | { |
04 | int i,j,k,temp; |
05 | //INT xsum, ysum; |
06 | //int x, y; |
07 | int dx, dy; |
08 | int x[TSP_SAMPLE_NUM], y[TSP_SAMPLE_NUM]; |
09 | |
10 | //xsum = ysum = 0; |
11 | EnterCriticalSection(&g_csTouchADC); |
12 | for (i = 0; i < TSP_SAMPLE_NUM; i++) |
13 | { |
14 | v_pADCregs->ADCTSC = (0<<8)|(1<<7)|(1<<6)|(0<<5)|(1<<4)|(1<<3)|(1<<2)|(0); |
15 | v_pADCregs->ADCCON |= (1 << 0); /* Start Auto conversion */ |
16 | |
17 | while (v_pADCregs->ADCCON & 0x1); /* check if Enable_start is low */ |
18 | while (!(v_pADCregs->ADCCON & (1 << 15))); /* Check ECFLG */ |
19 | |
20 | x[i] = (0x3ff & v_pADCregs->ADCDAT1); |
21 | y[i] = 0x3ff - (0x3ff & v_pADCregs->ADCDAT0); |
22 | |
23 | //x[i] = D_XPDATA_MASK(v_pADCregs->ADCDAT1); |
24 | //y[i] = D_YPDATA_MASK(v_pADCregs->ADCDAT0); |
25 | //xsum += x; |
26 | //ysum += y; |
27 | } |
28 | |
29 | //*px = xsum / TSP_SAMPLE_NUM; |
30 | //*py = ysum / TSP_SAMPLE_NUM; |
31 | |
32 | v_pADCregs->ADCTSC = (1<<8)|(1<<7)|(1<<6)|(0<<5)|(1<< 4)|(0<<3)|(0<<2)|(3); |
33 | |
34 | |
35 | LeaveCriticalSection(&g_csTouchADC); |
36 | |
37 | //-------------------------------------------------------------- |
38 | // if mask it ,very tremble work not well |
39 | for (j = 0; j < TSP_SAMPLE_NUM -1; ++j) |
40 | { |
41 | for (k = j+1; k < TSP_SAMPLE_NUM; ++k) |
42 | { |
43 | if (x[j]>x[k]) |
44 | { |
45 | temp = x[j]; |
46 | x[j]=x[k]; |
47 | x[k]=temp; |
48 | } |
49 | |
50 | if (y[j]>y[k]) |
51 | { |
52 | temp = y[j]; |
53 | y[j]=y[k]; |
54 | y[k]=temp; |
55 | } |
56 | } |
57 | } |
58 | |
59 | //dx = (*px > x) ? (*px - x) : (x - *px); |
60 | //dy = (*py > y) ? (*py - y) : (y - *py); |
61 | |
62 | *px = (x[2] + ((x[3]+x[4])<<1) + (x[3]+x[4]) + x[5]); |
63 | *py = (y[2] + ((y[3]+y[4])<<1) + (y[3]+y[4]) + y[5]); |
64 | |
65 | if ((*px & 0x7) > 3) |
66 | *px = (*px>>3) + 1; |
67 | else *px = *px>>3; |
68 | |
69 | if ((*py & 0x7) > 3) |
70 | *py = (*py>>3) + 1; |
71 | else *py = *py>>3; |
72 | |
73 | dx = x[5] - x[2]; |
74 | dy = y[5] - y[2]; |
75 | |
76 | return ((dx > TSP_INVALIDLIMIT || dy > TSP_INVALIDLIMIT) ? FALSE : TRUE); |
77 | } |
好了,方法就是这么多了,This is it ,下面贴出效果图,收工!
wince 2440 完美解决触摸屏跳点抖动源码
http://www.gooogleman.com/forum.php?mod=viewthread&tid=507&fromuid=3
001 | /* :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */ |
002 | /* :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */ |
003 | |
004 | |
005 | |
006 | PUBLIC VOID |
007 | DdsiTouchPanelGetPoint(TOUCH_PANEL_SAMPLE_FLAGS * pTipStateFlags, |
008 | INT * pUncalX, |
009 | INT * pUncalY) |
010 | { |
011 | static INT x, y; |
012 | |
013 | if (v_pINTregs->SUBSRCPND & (1<<IRQ_SUB_TC)) /* SYSINTR_TOUCH Interrupt Case*/ |
014 | { |
015 | *pTipStateFlags = TouchSampleValidFlag; |
016 | |
017 | if ( (v_pADCregs->ADCDAT0 & (1 << 15)) | |
018 | (v_pADCregs->ADCDAT1 & (1 << 15)) ) |
019 | { |
020 | bTSP_DownFlag = FALSE; |
021 | |
022 | DEBUGMSG(ZONE_TIPSTATE, (TEXT( "up/r/n" ))); |
023 | |
024 | v_pADCregs->ADCTSC &= 0xff; |
025 | |
026 | *pUncalX = x; |
027 | *pUncalY = y; |
028 | |
029 | TSP_SampleStop(); |
030 | // Test |
031 | |
032 | RETAILMSG(1,(TEXT( "bTSP_DownFlag = FALSE...PenUP!!!/r/n" ))); |
033 | } |
034 | else |
035 | { |
036 | bTSP_DownFlag = TRUE; |
037 | |
038 | if (!TSP_GetXY(&x, &y)) |
039 | *pTipStateFlags = TouchSampleIgnore; |
040 | |
041 | TSP_TransXY(&x, &y); |
042 | |
043 | *pUncalX = x; |
044 | *pUncalY = y; |
045 | |
046 | *pTipStateFlags |= TouchSampleDownFlag; |
047 | |
048 | //Test |
049 | RETAILMSG(1,(TEXT( "bTSP_DownFlag = TRUE...PenDown!!!/r/n" ))); |
050 | |
051 | TSP_SampleStart(); |
052 | } |
053 | |
054 | v_pINTregs->SUBSRCPND = (1<<IRQ_SUB_TC); |
055 | v_pINTregs->INTSUBMSK &= ~(1<<IRQ_SUB_TC); |
056 | |
057 | InterruptDone(gIntrTouch); |
058 | } |
059 | else /* SYSINTR_TOUCH_CHANGED Interrupt Case */ |
060 | { |
061 | // TSP_SampleStart(); |
062 | |
063 | if (bTSP_DownFlag) |
064 | { |
065 | INT tx, ty; |
066 | INT dx, dy; |
067 | |
068 | if (!TSP_GetXY(&tx, &ty)) |
069 | *pTipStateFlags = TouchSampleIgnore; |
070 | else |
071 | { |
072 | |
073 | RETAILMSG(1,(TEXT( "bTSP_DownFlag = TRUE.PenDown!!!IRQ_Timer3 Interrupt/r/n" ))); |
074 | TSP_TransXY(&tx, &ty); |
075 | // insert by mostek@dstcorp.com |
076 | #define X_ERRV 0x3bf |
077 | #define Y_ERRV 0x4ff |
078 | |
079 | if ((tx == X_ERRV) && (ty == Y_ERRV)) |
080 | { |
081 | tx = x; |
082 | ty = y; |
083 | } |
084 | // =================== mostek |
085 | dx = (tx > x) ? (tx - x) : (x - tx); |
086 | dy = (ty > y) ? (ty - y) : (y - ty); |
087 | |
088 | if (dx > TSP_CHANGE || dy > TSP_CHANGE) |
089 | { |
090 | *pUncalX = x = tx; |
091 | *pUncalY = y = ty; |
092 | |
093 | //DEBUGMSG(ZONE_TIPSTATE, (TEXT("down-c-v %x %x/r/n"), x, y)); |
094 | *pTipStateFlags = TouchSampleValidFlag | TouchSampleDownFlag; |
095 | } |
096 | else |
097 | { |
098 | *pUncalX = x; |
099 | *pUncalY = y; |
100 | |
101 | DEBUGMSG(ZONE_TIPSTATE, (TEXT( "down-c %x %x/r/n" ), x, y)); |
102 | |
103 | *pTipStateFlags = TouchSampleIgnore; |
104 | } |
105 | } |
106 | } |
107 | else |
108 | { |
109 | *pTipStateFlags = TouchSampleIgnore; |
110 | |
111 | TSP_SampleStop(); |
112 | |
113 | RETAILMSG(1,(TEXT( "bTSP_DownFlag = FALSE.PenDown!!!IRQ_Timer3 Interrupt/r/n" ))); |
114 | } |
115 | |
116 | InterruptDone(gIntrTouchChanged); |
117 | } |
118 | |
119 | // add by wogo at2009.03.23 why? |
120 | SetEvent(hEventTouchInput); |
121 | } |