ADAPTADOR DE RATÓN PS2 - SNES

Esta página expone una introducción al manejo de un ratón de ordenador ps2, con vistas a construir un circuito para poder usarlo en una Super Nintendo.

Por David Senabre, Junio 2006


1ª PARTE
Interfaz de ratón protocolo PS2


 El protocolo PS2 es un protocolo serie bidirectional, síncrono, que usa 2 líneas, una de reloj, y otra de datos. Estas líneas son de tipo colector abierto, luego pueden tomar el valor lógico 0, o alta impedancia. Luego, para conectar las líneas de datos y reloj al PIC, o a cualquier controlador, se deben usar resitencias de pull. El valor exacto de las mismas no es crítico. Uno más alto ofrece un menor consumo, mientras que uno más bajo da tiempos de subida más cortos.

Las especificaciones recomiendan valores entre 1k y 10kOhms.

Yo he probado con 100kOhms con éxito, al igual que con 4.7kOmhs.

Las señales son compatibles con TTL, y la alimentación del ratón debe estar comprendida entre 4.5 y 5.5V de continua.

 

El estado de “idle” del bus es cuando ambas líneas están en alta impedancia, luego las resistencias de pull-up subirán la línea a +5V.

La señal de reloj la genera el dispositivo, en este caso, el ratón.

El control del bus lo tiene, como norma general, el controlador.

 

Cuando el controlador quiere detener la comunicación , sólo tiene que forzar la línea de reloj a 0, durante un tiempo. Eso indica al dispositivo que debe detener la transmisión de datos, si es el caso.

Si cuando el controlador ha bajado la señal de reloj, baja la de datos, y posteriormente libera el reloj, el dispositivo lo entenderá como unapetición de envío de datos . Entonces empezará a generar la señal de reloj, con la cuál el controlador deberá enviar, de forma síncrona, cada bit de información.

 

La información se envía en paquetes, que transmiten un byte, pero que están compuestos por más bits que sirve de sirven para dar robustez a la comunicación.

1 bit de comienzo. Siempre a 0.

8 bits de datos. Primero el menos significativo.

1 bits de paridad impar.

1 bit de stop. Siempre a 1.

 

Y sólo cuando la comunicación es del controlador al dispositivo, 1 bits de reconocimiento. Cuando el controlador ha enviado los 11 bits, espera a que el dispositivo baje el reloj y la línea de datos, y los libere. Esto significa que ha reconocido y aceptado el dato enviado.

La sincronización con el reloj cambia en función del sentido.

Si la información la manda el controlador, el bit es válido en el flanco de subida.

Si la información la manda el dispositivo, el bit es válido en el flanco de bajada.

Según las especificaciones, el frecuencia del reloj está entre los 10 y los 16KHz, dentro de las posibilidades del PIC 16F84A, 16F628 y el resto de la gama, funcionando a 4MHz. La temporización es crítica.

 

Cuando el dispositivo tiene que enviar información, primero se asegura de que la señal de reloj esté libre durante al menos 50 us. Si en algún momento el controlador baja la señal, inhibiera la transmisión, y habrá que reenviar los datos cuando se libere.

 

El ratón informa del desplazamiento en cada dirección, X e Y, así como del estado de cada botón (pulsado o no). Periódicamente, comprueba el estado de cada una de estás entradas, y las almacena internamente para mandarlas al controlador.

El movimiento en X y Y se codifica con 9 bits en complemento a 2, además de un bit de overflow. Por tanto, el rango de posibles valores que puede tomar es -256..255

 

Esta información se envía en un paquete de 3 bytes, y el movimiento reportado representa el número de pasos detectados desde el último paquete enviado, es decir, muestra desplazamiento relativo.

Se puede cambiar por medio de comandos enviados al ratón, su resolución, el número de pasos que detecta por mm recorrido, y un factor de escala.

Si no se especifica nada, por defecto al encenderse, toma estos valores;

* Frecuencia de 100 muestras /s

* Resolución de 4 pasos por mm.

* Sin escalado.

OverflowY

OverflowX

Signo Y

Signo X

1

Botón cen

Botón der

Botón izq

Desplazamiento en X

Desplazamiento en Y

Formato del paquete de movimiento

Recordar que cada paquete es en realidad un conjunto de 11 bits (los 8 de cada byte, más bit de inicio y parada, y paridad).

 

El ratón puede funcionar en varios modos. Entre ellos destaca el “stream” y el “remoto”.

En el primero, el ratón refresca su estado y lo envía a intervalos regulares, tal y como he comentado hasta ahora. En el segundo, sólo hace esto cuando recibe la orden del controlador, de modo que se puede controlar de forma precisa y asíncrona, el momento en el que el ratón debe muestrear su desplazamiento y el estado de los botones, y también cuando enviará esta información a través de los 3 paquetes que acabo de mencionar.

 

Por otra parte el ratón se controla a base de comandos, que no son más que paquetes enviados por el controlador, cuyo byte indica un código de operación.

Ejemplos son:

0xFF: Reset.

0xF6: Valores por defecto.

0xF5: Desactivar envío de información (el ratón deja de informar en modo “stream”).

0xF4: Activar el envío de información.

0xF3: Establecer un nuevo periodo de muestreo.

0xF2: Solicitar el ID del dispositivo, para identificación. Un ratón estándar dará 0.

0xF0: Entrar en modo “remoto”

0xEA: Entrar en modo “stream”

0xEB: Pide el paquete de movimiento en modo “remoto”.

0xE9: Pide el paquete de estado al ratón.

 

El ratón responde con el byte 0xFA de reconocimiento cuando recibe y acepta un comando.

Al encenderse, o recibir un reset, responde con 0xAA y 0x00 (este último byte es el ID, que podría ser distinto para algún dispositivo PS2 diferente).


2ª PARTE
Primer proyecto: Obtener el estado del ratón con un PIC 16F84A


Ahora me centraré exclusivamente en las pruebas que yo he hecho.

He usado 2 entradas del puerto A del PIC para conectar las líneas de reloj y datos del ratón. Y he usado 6 pines del puerto B para mostrar por LEDs la dirección del desplazamiento del ratón, y los botones izquierdo y derecho.

Por mayor comodidad, nada más alimentar el circuito, el PIC manda un comando de reset, para asegurarse, y pone a trabajar al ratón en modo “remoto”, de manera que únicamente mandará información sobre movimiento y botones cuando el PIC se lo pida, con el comando 0xEB.

El esquema del programa es básicamente un bucle que lee el estado, lo procesa, y lo muestra por los LEDs.

 

Como quería trabajar en este proyecto en casa, tuve que hacerme con los componentes necesarios.

* Una placa de prototipos.

* Un PIC 16F84A, cristal de cuarzo y condensadores.

* Ratón PS2 estándar.

* Multímetro con frecuenciómetro.

* Resistencias de pull-up de 100kOhms.

* Herramientas varias.

 

Es muy difícil de trabajar en este proyecto sin una manera de registrar qué ocurre durante la ejecución del PIC. Porque al principio no funciona nada, y no se puede saber qué ocurre. Así que para monitorear el estado de las líneas empecé usando unos cables soldados a un conector de puerto paralelo, y un pequeño programa escrito por mi en Delphi, para leer el estado y guardarlo en un archivo en el PC.

Monté el circuito en la placa de prototipos, y conecté el ratón PS2 cortando su conector y soldando en los cables una tira de pines cuadrados machos.

El PIC usa un reloj de 4MHz y un par de condensadores de 20uF.

No ha resultado nada sencillo conseguir que funcione por primera vez el circuito, ya que no es una tarea fácil en absoluto, cuando no se tiene experiencia. Así que el poder monitorear las líneas de datos y reloj fue vital. Finalmente conseguí prestado un analizador lógico que se conecta al PC a través de USB, cuyo precio es prohibitivo, y tomé los diagramas de tiempo durante la ejecución, para adjuntarlas en este documento.

En primer lugar, comentaré los problemas que tuve y la solución que le di, hasta conseguir que funcionara lo mínimo, como para saber que el PIC y el ratón se comunicaban.

 

En primer lugar, cuando se quiere enviar datos al ratón, hay que bajar la señal de reloj durante más de 100us. Luego la de datos, y luego soltar el reloj.

Es importante hacer bien esta secuencia, o el ratón no comenzará a generar el reloj.

La secuencia se ver en el diagrama. Como puede verse, el reloj está bajo durante más de 100us. Después de bajar la señal de datos, no la vuelvo a liberar, a espera del primer pulso de reloj.

Luego hay que estar alerta, para ver cuando el ratón da el primer pulso (la línea baja). Pero un problema que tuve fue el bit de inicio. El ratón genera 10 pulsos, y falta uno para los 11 que hay que transmitir. La clave es que el bit de inicio se envía cuando se pide el tren de pulsos (mirar el diagrama de arriba). Al subir la señal de reloj, manteniendio baja la de datos, se ha mandado ya un 0, que es el bit de inicio, y ahora ya se pueden usar el resto de los 10 pulsos que generará el ratón, para enviar el byte, el bit de paridad y de fin.

Después se van sacando los bits uno a uno.

Para ello ha escrito una subrutina que usa 2 registros del PIC, uno para almacenar los 8 bits del dato, otro para la paridad y el bit de stop. Luego se va rotando y sacando por el carry al pin 0 del puerto A, elegido para ser el de datos para poder usar simples rotaciones primero a derechas, desde los registros, luego a izquierdas al puerto A.

Aquí está el diagrama de tiempos al enviar un comando 0xEB. El reloj lo genera el ratón. Los datos los envía el PIC. Al final puede verse el bit de reconocimiento enviado por el ratón (los últimos pulsos de reloj y datos).

Cuando ya se han enviado todos los bits, hay que liberar ambas lineas y quedar a la espera, porque el ratón dará un pulso en ellas, como acabo de decir. Eso significa que recibió el paquete. No significa que el paquete lo haya procesado y sea correcto, sino sólo que recibió los bits.

Cuando los interprete, mandará un paquete con el byte 0xFA si lo proceso y lo aceptó, o 0xFC si hubo error (el comando no existe, error en el formato, opción no soportada, bit de paridad incorrecto,...)

Cuando el ratón envía el reconocimiento 0xFA

Como puede verse, el dato es válido en el flanco de bajada.

Cuando es el PIC el que envía, como en el diagrama anterior, puede verse que es al contrario, el PIC actualiza el bit nada más pasa el flanco de bajada, a la espera de que vuelva a subir.

Los bits que reflejan el estado de los botones se ponen a 1 cuando están pulsados.

 

El primer circuito que hice usaba 6 de los bits del puerto B del PIC para mostrar el estado actual del desplazamiento y los botones. Un led se enciende cuando hay movimiento a la izquierda, otro a la derecha, otro arriba y otro abajo, y dos leds muestran el estado de los botones izquierdo y derecho.

Aprovechando que el PIC sólo pueda entregar una cantidad pequeña de corriente por sus terminales de I/O, conecto los LEDs directamente, y los enciendo colocando un 1 en el puerto, y apago al escribir un 0.