gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Touchscreen code

#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:
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.

#58319 - wintermute - Sat Oct 22, 2005 4:43 pm

Have you tried the latest touch code?

The most recent interation takes a weighted average of several readings and works pretty well for me. It does need some more work to discard readings in some situations though.

We intend to move away from the IPC struct in due course so depending on that is not recommended.

#58329 - Tobin - Sat Oct 22, 2005 6:45 pm

wintermute wrote:
Have you tried the latest touch code?

The most recent interation takes a weighted average of several readings and works pretty well for me. It does need some more work to discard readings in some situations though.

I have tried it and it does not work well in the cases described above.

I highly recommend to discard the readings short after a touch or a release.

#58330 - Mollusk - Sat Oct 22, 2005 6:51 pm

Wouldn't it be even better to discard depending on the pressure ? A new touch or a release has a very soft pressure, so that could maybe be a way to discriminate
_________________
PAlib official forum : http://www.palib.info
PAlib official tutorials: http://www.palib.info/wiki
Updates, help, code examples, tutorials, etc...

#58338 - tepples - Sat Oct 22, 2005 7:38 pm

Mollusk wrote:
Wouldn't it be even better to discard depending on the pressure ? A new touch or a release has a very soft pressure, so that could maybe be a way to discriminate

The threshold between a soft pressure and a hard pressure varies per make and model of touch screen (therefore it varies per DS), and it's not stored in the calibration part of the firmware.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#58466 - jandujar - Sun Oct 23, 2005 8:30 pm

can you apply this fixes on PA_lib?
_________________
http://jandujar.homelinux.com
http://www.dsrobot.com

#58468 - Mollusk - Sun Oct 23, 2005 8:33 pm

of course :)
_________________
PAlib official forum : http://www.palib.info
PAlib official tutorials: http://www.palib.info/wiki
Updates, help, code examples, tutorials, etc...

#58542 - wintermute - Mon Oct 24, 2005 2:19 pm

tepples wrote:
Mollusk wrote:
Wouldn't it be even better to discard depending on the pressure ? A new touch or a release has a very soft pressure, so that could maybe be a way to discriminate

The threshold between a soft pressure and a hard pressure varies per make and model of touch screen (therefore it varies per DS), and it's not stored in the calibration part of the firmware.


I think this might also vary depending on whether the plastic film has been removed from the touchscreen. Most people complaining about the "accuracy" of the libnds code appear not to have removed this film which appears to distort the readings at the edges.

Claims have been made that Pictochat works fine with the film still in place but that application doesn't read from the edges of the screen.

#58669 - KiwiBoi - Tue Oct 25, 2005 6:34 am

wintermute wrote:
I think this might also vary depending on whether the plastic film has been removed from the touchscreen. Most people complaining about the "accuracy" of the libnds code appear not to have removed this film which appears to distort the readings at the edges.

Claims have been made that Pictochat works fine with the film still in place but that application doesn't read from the edges of the screen.

Most 4-wire resistive touch screens get rather non-linear near the edges, it's a common thing.

Also, does anyone know which controller they are using for the touch screen (if any)? Is it that TI one that also does audio?

#58672 - Dwedit - Tue Oct 25, 2005 6:59 am

Don't know, but it does do audio.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#58673 - KiwiBoi - Tue Oct 25, 2005 7:03 am

Dwedit wrote:
Don't know, but it does do audio.

I'll compare some of the #defines in ndslib with the datasheets I have at work tomorrow then.

I don't suppose there is a BOM or something for the DS floating about at all?

#58674 - tepples - Tue Oct 25, 2005 7:07 am

I hope those aren't NDAtasheets...
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#58676 - wintermute - Tue Oct 25, 2005 8:29 am

KiwiBoi wrote:
wintermute wrote:
I think this might also vary depending on whether the plastic film has been removed from the touchscreen. Most people complaining about the "accuracy" of the libnds code appear not to have removed this film which appears to distort the readings at the edges.

Claims have been made that Pictochat works fine with the film still in place but that application doesn't read from the edges of the screen.

Most 4-wire resistive touch screens get rather non-linear near the edges, it's a common thing.

Also, does anyone know which controller they are using for the touch screen (if any)? Is it that TI one that also does audio?


That's kind of why I put "accuracy" in quotes. The distortion I'm talking about is allegedly a difference of around 30 pixels at top left and dropping to just under 10 at bottom left. We're having a lot of trouble getting touch code to behave well on all units.

http://focus.ti.com/docs/prod/folders/print/tsc2046.html

and apparently

http://www.asahi-kasei.co.jp/akm/en/product/ak4181a/ak4181a.html

on later DS versions

#58682 - KiwiBoi - Tue Oct 25, 2005 10:27 am

One thing you could try, besides debouncing, is to read, say, the X axis first, then the Y then read the X again and check it is within a small limit of the first x reading (this will depend on the ADC bit size), 30 or so seems good at 10bits. This ensures it wasn't a bounce or brief hit that would throw your measurements out.

EDIT: Also, give it some time to settle when switching plates. I don't know if there are any external caps on the lines in the DS but there is sure to be some capacitance somewhere.

tepples: No, just regular ones :)