quinta-feira, 22 de maio de 2014

Emulador de teclado genérico - Parte 5

Parte 5: Interface PS/2 e firmware

Para ler o teclado PS/2 o caminho mais natural (pelo menos para mim) é utilizar um microcontrolador. A quantidade de pinos de I/O necessária é de 2 pinos para o teclado mais 3 pinos para os sinais dos registradores de deslocamento (Dados, Clock e Transfer). Isso abre bastante o leque de possibilidades, pois inclui até mesmo dos pequenos microcontroladores de 8 pinos.

Existem inúmeras bibliotecas prontas para ler a interface PS/2 disponíveis na Internet, para diversas linhas de microcontroladores.  Porém grande parte das bibliotecas que vi eram orientadas a fornecer o código ASCII de uma tecla pressionada, abstraindo o mecanismo dos 'make codes' e 'break codes'. Isso pode ser adequado para transmitir os caracteres através de uma linha serial, mas para emular uma matriz de teclado isso não serve pois precisamos reproduzir o estado da tecla na matriz do teclado emulado, e não o evento de seu pressionamento.

Escolhi utilizar um ATTiny85 pois tenho alguns de estoque aqui. Além disso eles são muito baratos, mas também poderia ter utilizado um PIC ou HC908.

Para a prova de conceito eu utilizei um Arduino com a biblioteca 'ps2' da autoria de Chris J. Kiick pois ela fornece na saída os scancodes enviados pelo teclado.

O estado da matriz do teclado foi mapeada bit a bit num vetor de 8 bytes inicializado com 0xFF, pois as teclas pressionadas estão em nível zero.

char Keymap[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

Os bit 0..4 de cada um dos elementos da matriz keymap correspondem às linhas D0..D4 do teclado, enquanto que as linhas de endereço A8..A15 correspondem aos elementos 0..7 da matriz.

Dessa forma a tecla 'CAPS SHIFT' está mapeada no bit 0 do elemento 0, a tecla '5' está no bit 4 do elemento 3 e assim por diante.

O proximo passo foi associar os scancodes do PC nas linhas e colunas da matriz do TK. Para isso eu utilizei uma tabela de equivalências no seguinte formato:



Os bits 0-2 correspondem à linha. Os bits 3-5 correspondem à coluna (tecla).

Exemplo: A tecla 'A' fica no bit 0 da linha 1, portanto quando eu receber o make code da tecla A do teclado PS2 eu vou zerar o bit 0 do elemento 1. Já a tecla 'R' fica no bit 3 do elemento 2
Tecla  SCANCODE  Keymap (binário)
'A'    0x1C      00.000.001 ou 0x01
'R'    0x2D      00.011.010 0u 0x1A

Os bits 6 e 7 correspondem ao pressionamento conjunto das teclas CAPS SHIFT e SYMBOL SHIFT. Isso foi feito para permitir mapear teclas compostas.

Exemplo: Quando eu receber o Scancode da tecla 'Backspace' eu devo ativar ao mesmo tempo CAPS SHIFT  que está no bit 0 da linha 0 e também a tecla '0' (zero) que está no bit 0 da linha 4. Dessa forma a associação fica: 
Tecla  SCANCODE  Keymap (binário)
BKSP   0x66      10.000.100 ou 0x84


As teclas estendidas são tratadas em separado, pois não não muitas (basicamente as setas).

Finalmente, o algoritmo de funcionamento é o seguinte:

  • Aguarda um Scancode
  • Usa o scancode como entrada numa tabela de 'scancodes x keymaps'
  • Se for um make code zera o(s) bit(s) correspondende na matriz
  • Se for um break code liga o(s) bit(s) correspondende na matriz
  • Envia a matriz serialmente para o registrador de deslocamento

Que em código equivale ao seguinte trecho




Nenhum comentário: