#58309 - Tobin - Sat Oct 22, 2005 2:11 pm
After a long morning I finally have written an accurate touchscreen code. The one coming with ndslib is not good enough for e.g. drag 'n drop (the sprite is flickering and it never stays where you have released it). The problem is, that the first few readings after a touch or a release give weird results. So we have to wait a few ms in the case of a touch before we set the IPC flag and in the case of a release we have to return an older position.
Here is the code for the arm7 vblank interrupt handler:
To read the current position I use the median of some reads. The median is better than the average, because outlier will not influence the result.
To set the IPC entries (setTouchIPC) I use the code from touchReadXY(). My code is not optimized and maybe there is a better choice of the parameters, but it works perfect for my purpose. Hope this helps.
Here is the code for the arm7 vblank interrupt handler:
Code: |
#define ABS(x) ((x) < 0) ? -(x) : (x) void VblankHandler(void) { static int heartbeat = 0; static const int savePad = 3; static int oldX[3], oldY[3], oldKeys; static int firsttouch; uint16 but=0, z1=0, z2=0, batt=0, aux=0; int t1=0, t2=0; uint32 temp=0; uint8 ct[sizeof(IPC->curtime)]; u32 i; bool cleanread=false; // Update the heartbeat heartbeat++; // Read the touch screen but = REG_KEYXY; if (!(but & (1<<6))) { cleanread = updateTouch(); if (((oldKeys & (1<<6)) != 0)) firsttouch = heartbeat; } ... // Update the IPC struct IPC->heartbeat = heartbeat; IPC->touchZ1 = z1; IPC->touchZ2 = z2; IPC->battery = batt; IPC->aux = aux; //just released if (((oldKeys & (1<<6)) == 0) && (!cleanread)){ setTouchIPC (oldX[0], oldY[0]); IPC->buttons = REG_KEYXY & ~(1<<6); } else if (cleanread){ for (i=0; i<savePad - 1; i++){ oldX[i]=oldX[i+1]; oldY[i]=oldY[i+1]; } oldX[savePad-1] = nx; oldY[savePad-1] = ny; setTouchIPC (oldX[savePad - 2], oldY[savePad - 2]); } if (abs(heartbeat - firsttouch) < 4){ //we have to wait IPC->buttons = but | REG_KEYXY | (1<<6); } else IPC->buttons = but | REG_KEYXY; oldKeys = but | REG_KEYXY; ... |
To read the current position I use the median of some reads. The median is better than the average, because outlier will not influence the result.
Code: |
static int nx, ny; static bool updateTouch(){ int c = 7; int i,j; int x[c]; int y[c]; int temp; for (i=0; i<c; i++){ if (!(REG_KEYXY & (1<<6))){ x[i] = touchRead(TSC_MEASURE_X); y[i] = touchRead(TSC_MEASURE_Y); } else return false; } //Bubblesort for (i=0;i<c-1;i++){ for (j=0;j<c-1;j++){ if (x[j]>x[j+1]){ temp = x[j];x[j] = x[j+1];x[j+1] = temp; } if (y[j]>y[j+1]){ temp = y[j];y[j] = y[j+1];y[j+1] = temp; } } } //Take the median nx = x[(c-1)/2]; ny = y[(c-1)/2]; return true; } |
To set the IPC entries (setTouchIPC) I use the code from touchReadXY(). My code is not optimized and maybe there is a better choice of the parameters, but it works perfect for my purpose. Hope this helps.