Problemas del emulador de teclado Arduino PS / 2

10

Sí, he buscado en los foros Arduino.cc y aquí. Sí, he encontrado los artículos sobre la biblioteca ps2dev. Sí, he leído (bueno, algunos lo he leído) el artículo definitivo de la interfaz PS / 2 en este sitio web . Sí, tengo esto funcionando, un poco. Necesito algunas ideas para dar el salto al pleno funcionamiento. :)

No, no puedo simplemente emular un teclado USB HID y dejarlo así: debe ser una emulación de teclado PS / 2. Sí, estoy enviando señales adecuadas de hacer y romper, incluso maneja combinaciones de teclas muy complicadas. Tal como está ahora, tengo un código escrito para mi Arduino como se publica a continuación (técnicamente un Freeduino 1.22), y he enviado pulsaciones de teclas a través del monitor serie o terminal PuTTY, así como con un práctico envoltorio / controlador Python que envía La información del código de escaneo PS / 2, y en general me hace la vida mucho más fácil, también quita parte de la carga del Arduino.

En este momento, tengo un boceto ejecutándose en el Arduino que emula un teclado PS / 2. Naturalmente, tengo que arrancar mi máquina "objetivo" (máquina en la que se conecta PS / 2 Plug), y veo que tiene lugar el "apretón de manos". Arrancar en WinDoze, abrir el bloc de notas y conducir pulsaciones de teclas a la pantalla (con éxito) utilizando mi "controlador" de Python. (El controlador simplemente tiene lugar en el terminal Serial Monitor / PuTTY y lee / escribe en el puerto serie usando un módulo llamado PySerial.) Todo esto se hace en un AMD en el "objetivo" de la placa base ASUS.

Ahora, el objetivo es hacer que funcione en mi Intel en el "objetivo" basado en la placa base Intel, lo enchufo, arranco y no tengo dados. Entonces, modifiqué un poco el boceto para intentar tener una idea de lo que realmente está sucediendo con mi pequeño amigo Ardy. La versión después de las modificaciones se muestra a continuación. Según tengo entendido (el código fue "prestado" de otra publicación en el foro de Arduino.cc, aquí ) Intentará establecer una conexión con el "objetivo" a través de PS / 2 primero, parpadeando el LED a bordo en un período de .5 segundos hasta el Se establece la conexión. El objetivo de Intel no supera el parpadeo de 0,5 segundos y la conexión en serie nunca se establece con el "host".

Mi pregunta es esta: ¿hay una diferencia importante en la forma en que los teclados ps / 2 establecen comunicación con su máquina de destino? ¿Es realmente una diferencia de diseño o debería buscar algo más básico que es el problema aquí? Escuché algo sobre la necesidad de resistencias pull-up en las entradas de datos / reloj, pero eso debería manejarse en el código, especialmente porque FUNCIONA en otro objetivo, solo que no es en el que necesito trabajar.

¿Algunas ideas? Me encantaría que esto funcione lo antes posible: voy a seguir depurando, cualquier sugerencia o sugerencia sería muy apreciada. A todos se les dará una consideración completa porque necesito algunos ojos nuevos sobre este tema. ¿Quizás se necesita una mejor implementación en la biblioteca ps2dev?

#include "ps2dev.h" // to emulate a PS/2 device

// Orange = 2
// Blue = 3
// Red = 5V (3 in)
// Black = GND (4 in)
// EXT Power, USB for COM only

PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock)
int enabled = 0; // pseudo variable for state of "keyboard"
boolean serialConnected = false;
int incomingByte = 0;

void ack() {
  //acknowledge commands
  while(keyboard.write(0xFA));
}

int kbdCmd(int command) {
  unsigned char val;
  switch (command) {
  case 0xFF: //reset
    ack();
    //the while loop lets us wait for the host to be ready
    while(keyboard.write(0xAA)!=0);
    break;
  case 0xFE: //resend
    ack();
    break;
  case 0xF6: //set defaults
    //enter stream mode
    ack();
    break;
  case 0xF5: //disable data reporting
    //FM
    enabled = 0;
    ack();
    break;
  case 0xF4: //enable data reporting
    //FM
    enabled = 1;
    ack();
    break;
  case 0xF3: //set typematic rate
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xF2: //get device id
    ack();
    keyboard.write(0xAB);
    keyboard.write(0x83);
    break;
  case 0xF0: //set scan code set
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xEE: //echo
    //ack();
    keyboard.write(0xEE);
    break;
  case 0xED: //set/reset LEDs
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  }
}

void connectHost() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
}

void setup() {
  pinMode(13, OUTPUT);
  //establish serial connection with host
  Serial.begin(9600);
  // establish ps/2 connection with target
  while(keyboard.write(0xAA)!=0){
    digitalWrite(13, HIGH);
    delay(500); 
    digitalWrite(13, LOW);
    delay(500);
  }
  delay(100);  
  
  connectHost();
  Serial.println("\nSerial Host Connected");
  Serial.flush();
}

void loop() {
  unsigned char c;
  if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) {
    if(digitalRead(3)==LOW){
      Serial.println("pin 3  is LOW");
    } else {
      Serial.println("pin 2 is LOW");
    }
    while(keyboard.read(&c));
    kbdCmd(c);
    Serial.print("Target: 0x");
    Serial.println(c, HEX);
  }  
  else {//if host device wants to send a command:
    //echo ASCII code from terminal and write to ps/2
    if(Serial.available() > 0) {
      incomingByte = Serial.read();
      keyboard.write(incomingByte);      
      Serial.print("Host: 0x");
      Serial.print(incomingByte, HEX);
      Serial.print(" ");
      Serial.print(incomingByte);
      Serial.print(" ");
      Serial.println(incomingByte, BIN);
    }
  }
}
chisaipete
fuente
Algunas preguntas: "Sketch" es Arduino-lingo para "programa"? Este controlador de Python es independiente de la máquina de destino, ¿verdad? Su problema es que funciona en una máquina de destino y no en la otra, ¿verdad? ¿Intentó arrancar el objetivo que no funciona con un teclado PS / 2 conectado y luego intercambiarlo con el Arduino?
AndreKR
Sí, programa Sketch == en Ardu-lingo. Intenté esto y no pareció funcionar (pero necesito modificar el boceto para que no espere los ACK del objetivo antes de enviar caracteres). Te avisaré cuando tenga la oportunidad de probarlo. mas tarde, hoy.
chisaipete
Por lo tanto, probé el programa como sugirió, ¡y funciona! Al final, me gustaría poder encender y apagar el objetivo con el emulador de teclado instalado y poder cambiar la configuración del BIOS con él. Entonces, ¿estoy pensando que el apretón de manos de inicio está apagado?
chisaipete
Si probablemente. ¿Vio la secuencia de inicialización en la parte inferior de computer-engineering.org/ps2keyboard ? Comenzaría comparando mi secuencia con eso.
AndreKR
1
Lo siento, he dejado que este hilo se vuelva obsoleto: no he tenido tiempo de probar la solución de AndreKR. Además, no estoy usando resistencias pullup, por lo que es difícil determinar qué extremo no tiene resistencias pullup :)
chisaipete

Respuestas:

5

Según tengo entendido, conectas tu Arduino a dos máquinas de destino diferentes y en una funciona y en la otra no.

Parece que hay una diferencia entre los requisitos de inicialización de las dos máquinas. En esta página, en la parte inferior, hay una lista de una posible secuencia de inicialización. Comience comparando su inicialización con esa.

Será mucho más fácil usando un analizador lógico. Estoy usando Intronix Logicport , pero hay otros más baratos y mejores, aunque no al mismo tiempo.

Aprovechar un autobús de colección abierta es un poco engorroso porque no ves qué dispositivo está hablando. Sin embargo, si coloca una resistencia en serie al final donde no está el pullup , puede saber por el nivel de voltaje qué dispositivo está sosteniendo el bus. Cada bus de colector abierto (como PS / 2) necesita resistencias pullup, generalmente están integradas en la PC. Puede ver los diferentes niveles de voltaje fácilmente en un DSO. Con solo un LA, debe grabar dos veces con diferentes voltajes de umbral.

AndreKR
fuente
La decisión de a quién dar la recompensa fue más difícil de lo que esperaba, pero su respuesta obtuvo la mayor cantidad de votos y prefiero un poco. Hubiera preferido recompensar a todos!
Kortuk
3

Dado que su proyecto funciona con una placa base y no con otra, parece tener un caso clásico de "cumplimiento de especificaciones parciales", en su proyecto, y tal vez incluso en una de las placas base. Pero la mayoría de los teclados funcionarán con cualquier placa base, por lo que una implementación robusta debería ser portátil. El desafío es que tendrás que descubrir por qué el tuyo no lo es.

Es posible que pueda hacer esto simplemente mirando el problema y pensando en cómo se supone que funciona (tal vez después de un descanso, o un día la respuesta lo golpee en la ducha), pero será más efectivo si puede monitorear Que esta pasando. Para problemas eléctricos, eso significa un alcance, para los protocolos, un analizador lógico. Hay algunas opciones baratas disponibles en esa área, por ejemplo, la placa "pirata de bus" que tiene alguna capacidad específica para el protocolo de teclado o algo basado en FPGA que podría tener un búfer de captura más largo (ver sump.org).

Otra cosa que podría intentar sería usar otro dispositivo, ya sea un microcontrolador o un FPGA, para construir un host de teclado y usarlo para probar su proyecto hacia los límites de la especificación.

Chris Stratton
fuente
2

No he mirado la biblioteca ps2dev para ver exactamente cómo funciona, pero una cosa me llama la atención.

Por el momento, se realiza un solo intento de conectarse a la computadora "host". Cuando eso falla, se espera un segundo entero (LED encendido 0.5s, LED apagado 0.5s) antes de hacer otro intento.

Si la placa base Intel no está esperando el tiempo suficiente para la detección del teclado, es posible que nunca obtenga el intento de conexión antes de continuar con su secuencia de arranque.

Si disminuye el tiempo de espera para decir 0.1s (cambie las líneas de retraso (500) a retraso (50)) puede que tenga suerte.

Si no, intente aún más rápido. Demonios, incluso pruébalo sin demora y ve cómo funciona

Majenko
fuente