// Topic:徹底解決2440觸摸屏跳點問題
// 作者:gooogleman
// 版權:桂林電子科技大學一系科協[email protected]
// 平臺: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 [email protected] |
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 |
} |