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.

Para estudiar The Zynq MPSoC Book

La lectura de este libro ha sido resultado de una serie de afortunados errores.

Tengo algo de interés en PYNQ y en ZYNQ debido a tener un a Parallella, ví el título, no sé qué zynq, pynq, machine learning y no estaba tan caro, lo comencé a leer y mencionó que estaría bueno leer antes The Zynq Book lo estudié y volví a esto. De haber leido primero TZB sin tener ya en papel este no lo hubiese leido pues TZB no me pareció nada maravilloso y segundas partes suelen ser malas.

Ese sí hubiese sido un error, The Zynq MPSoC Book parece haber sido escrito tras asimilar las críticas al primero y aunque tiene bastante de humo marketinero, la proporción es menor y los contenidos no sé muy bien si son muy superiores y más claros o la lectura de TZB me dejó en mejores condiciones.

La parte marketing incluso es útil, aprendés cosas como que un cuadróptero tiene dos hélices girando para un lado y dos para el otro y eso le permite rotar, ja!

La diferencia entre un Zynq y un Zynq MPSoC es enorme:

  • Dos cores de 32 -> cuatro cores de 64 para aplicaciones genéricas (APU).
  • FPGA Artix-7 -> FPGA Kintex-7
    • 35k-106k -> 157k-555k Flip Flops
    • 17k-53k ->  78k-277k LUTs
    • 28k-85k -> 125k-444k Logic Cells
    • 60-140 -> 265-755 36Kb Block RAM
    • 2M-5Mb -> 9M-26Mb Block RAM
    • 80-220 -> 400-2000 DSPs
  • Dos cores RealTime (RPU).
  • Graphics Processing Unit (GPU).
  • Video Codec Unit (VCU).
  • Configuration Security Unit (CSU) (*)
  • Platform Management Unit (PMU)(*) 
Desde RPU para abajo, es terreno de MPSoC.


CSU y PMU tienen cada una tres MicroBlazes en silicio ejecutándose en modo votación.

CSU se encarga del boot seguro de los procesadores.



Las descripciones y explicaciones relacionadas a como se comunican y arrancan todos estos componentes es extremadamente educativa, me ha ayudado a avanzar en la comprensión de cómo funcionan en general las computadoras.

Se explica SDx, aparentemente en los últimos cinco años la cosa ha evolucionado. La idea es que vos escribís tu programa en C/C++ y SDx analiza el código y busca oportunidades de pasar secciones a la FPGA y su interfaz.

Lo que me había quedado de TZB es que este proceso estaba a cargo tuyo.


Con respecto a la GPU y VCU se menciona que existen, pero luego nada, no recuerdo ninguna mención, lo cual es una pena pues son un tercio de la diferencia con Zynq pelado. Igual podríamos decir que como es algo común, no especial como CSU y PMU, a los cuales se los explica muy bien.


Con respecto a ML, no respeta la proporción del título, es muy superficial, se citan ejemplos externos.

A diferencia de TZB no hay una práctica propuesta, pero uno estos días veré de instanciar los ejemplos de PYNQ-Z1 a PYNQ-Z2.




Se baja gratis de https://www.zynq-mpsoc-book.com/


Conclusiones


Vale la pena leerlo y si tenés tiempo antes leer y practicar TZB.