2020/01/28

Usando un touchpad con USB

Me había quedado dormido en el éxito de leer mensajes de desplazamientos sobre un touchpad recuperado de una laptop muerta, sin ningún beneficio tangible.

Para darle utilidad, necesitaría que se comporte como un mouse. Para ello aprovecharé que los teensy saben como comportarse como USBs.

Este código funciona ok eligiendo:

Tools->USB Type->"Serial + Keyboard + Mouse + Joystick"


#include <ps2.h>

PS2 touchpad(5, 3); // (clock, data)

void touchpad_init()
{
 touchpad.write(0xff);  // reset
 touchpad.read();       // ack byte
 touchpad.read();       // blank 

 touchpad.read();       // blank
 touchpad.write(0xf0);  // remote mode
 touchpad.read();       // ack
 delayMicroseconds(100);
}

void setup()
{
 Serial.begin(9600);
 touchpad_init();
 Serial.println("init");
}

void loop()
{
 char mstat, mx,  my;

 touchpad.write(0xeb);  // give me data!
 touchpad.read();       // ignore ack
 mstat = touchpad.read();
 mx = touchpad.read();
 my = touchpad.read();

 if ( mx != 0 || my != 0 ) {
   Mouse.move(mx, my);
   Serial.print(mstat, BIN);
   Serial.print("\tX=");
   Serial.print(mx, DEC);
   Serial.print("\tY=");
   Serial.print(my, DEC);
   Serial.println();  

 }
 delay(25);
}


Se puede jugar invirtiendo las posiciones de mx y my, cambiando los signos y aplicando un factor de escalamiento.

Supongo que no habrás podido dejar de notar la ausencia de botones, es que no me interesaban pues la verdad es que usar un touchpad me resulta bastante espantoso.

Luego lo pensé mejor y me dije: los botones son pulsadores, que probablemente ya tengan el debouncing resuelto.

Además hay muchas patitas, incluso en esta imagen de otro modelo se puede ver que pueden haber otras funcionalidades extra, como page up/down.





¿Quién no ha visto esos mouses que tienen muchos botones?

Si tengo un sistema embebido que necesita un touchpad y botones, capaz que me puedo ahorrar un montón de pines y debouncing si puedo identificar todos los botones que pueda soportar el chip.

Con respecto a "un montón", no hay tal, a lo sumo cuatro pues por fìn me he rendido y he consultado lo más parecido a documentación.

¿Cómo explorar esto?

Primero voy a explorar el comportamiento de los dos pines que supongo que son los botones.




Al ponerlos a tierra que es el modo que la documentación dice, obtengo esta salida:

1001    X=0    Y=0
1001    X=0    Y=0
1001    X=0    Y=0
1001    X=0    Y=0
1001    X=0    Y=0
1010    X=0    Y=0
1010    X=0    Y=0
1010    X=0    Y=0
1010    X=0    Y=0
1010    X=0    Y=0

Así que está claro, un botón es mstat[0] y el otro mstat[1]

Pensé que si no hubiese habido debouncing por hardware y se va a usar un microcontrolador en el medio, éste se puede encargar del debouncing, incluso hay un Bounce.h disponible en

 ./hardware/teensy/avr/libraries/Bounce/Bounce.cpp

pero no tiene mucho sentido ya que por el simple hecho que esté el clock ya va a filtrar



Ahora voy a probar con los botones de up y down, no, no anda, ningún Test Point genera ningún mensaje

testpointpin chipcomentario
T20 T22445V
T23 45ground
T103clock
T112data
T67left
T76right
T58up? no
T49down? no


Este es el código definitivo del loop() con los mensajes de botones del Mouse hacia el host:

void loop()
{
 char mstat, mx,  my;
 static boolean mouse_left = false;
 static boolean mouse_right = false;

 touchpad.write(0xeb);  // give me data!
 touchpad.read();       // ignore ack
 mstat = touchpad.read();
 mx = touchpad.read();
 my = touchpad.read();

 if ( mx != 0 || my != 0 ) {

   Mouse.move(mx, my);
   Serial.print(mstat, BIN);
   Serial.print("\tX=");
   Serial.print(mx, DEC);
   Serial.print("\tY=");
   Serial.print(my, DEC);
   Serial.println();
 }
 if (! mouse_left && ( 1 & mstat)) {
    Mouse.press(MOUSE_LEFT);
    Serial.println("\tLB press ");
    mouse_left = true;
  } else if (mouse_left && ! ( 1 & mstat)) {
    Mouse.release(MOUSE_LEFT);
    Serial.println("\tLB release ");
    mouse_left = false ;
  }
 if (! mouse_right && ( 2 & mstat)) {
    Mouse.press(MOUSE_RIGHT);
    Serial.println("\tRB press ");
    mouse_right = true;
  } else if (mouse_right && ! ( 2 & mstat)) {
    Mouse.release(MOUSE_RIGHT);
    Serial.print("\tRB release ");
    mouse_right = false ;
  }

 delay(25);
}


y estas las fotitos con los botones





Como dispositivo apuntador apesta, pero seguramente lo pueda usar para otra cosa, veremos.

No hay comentarios:

Publicar un comentario