Teclado

 
Hardware
Modo 13h
Retrazado Vertical
Primitivas
La Paleta
Pantallas Virtuales
Sprites
Tablas Prefedifinidas
Efectos
Texto
Formatos gráficos
Periféricos
Optimizaciones
Herramientas
Cursos
Links
Foro
Correo Electrónico
En esta sección veremos como programar el teclado, que hoy en día es un elemento imprescindible en la computación.

Si alguna vez han intentado mover una imagen por la pantalla, por ejemplo un muñeco en un juego, y quisieron moverlo en diagonal con los cursores, seguramente no han podido ya que no habrán tenido idea de como hacer para detectar más de una tecla simultáneamente. Pues bien esto es lo que veremos ahora.

Cuando pulsamos una tecla hasta que tenemos el valor ASCII suceden muchas cosas dentro de nuestro PC. Cuando se pulsa una tecla, hay un chip que está en  nuestro teclado llamado 8048, el cual detecta un cambio de corriente y gracias a esto, el chip será capaz de calcular  la  posición de la tecla. Según donde se encuentre ubicada la tecla el chip dará un código u otro, el cual será  transmitido al computador a través del puerto 60h. Alguien  puede pensar que estos códigos son los ASCII, pero no es así, ya que estos códigos no tienen  nada  que  ver  con  los  que  nos  devuelven. A  estos  códigos  se  es conocen por  el  nombre de SCAN-CODES y por  regla en todos los teclados son iguales. El  encargado de recoger este código es otro chip que se conoce con el nombre de 8042 y es el que genera la IRQ1, la cual tiene  una rutina ubicada en  la interrupción 9h, y lo que hace es  leer el código de la tecla que lee como hemos dicho antes del puerto 60h y después dicha rutina lo que hace es convertir ese código a ASCII y ponerlo en el buffer del teclado que se encuentra en los primeros 64 Kb  de la memoria junto con otras variables de la BIOS y que tiene una longitud de 16 bytes o caracteres. Es por eso que cuando instalamos el famoso “keyb sp”  en el computador  nos sale la “ñ” o la “'ç” al apretar las teclas correspondientes, ya que lo que hace no es más que sustituir la rutina original (la de fábrica) por otra propia encargada de poner cada carácter ASCII donde le corresponde. Cuando ya tenemos el código  ASCII (las rutinas de la BIOS se encargan de convertir el código a ASCII) lo podremos leer a través de  las  funciones de  la interrupción 16h. Pero esto a nosotros no nos interesa mucho, ya que no podremos leer más de una tecla a la vez con  estas funciones y además sólo nos informan si una tecla ha sido o no pulsada. Lo que tendremos que hacer  será  sustituir  el controlador actual de la interrupción 9h, por uno propio que nos irá informando de las teclas que hay sido pulsadas en cada instante que nosotros deseemos.

Para poder colocar nuestra nueva rutina, lo que tendremos que hacer es mediante la interrupción 21h de los servicios del DOS, sustituir nuestra  rutina por la actual, y esto lo haremos con la función 25h cuyos argumentos son en AH el número de subfunción (25h) y en AL en número de interrupción que queremos cambiar (09h) y finalmente en DX el offset a dicha interrupción. Pero antes deberemos salvar con la función 35h de la misma interrupción  los  vectores de  la interrupción actualmente instalada, para poder restaurarlos al finalizar nuestro programa.

INTERRUPCION 21h

Función 25h 

Entrada:   ah      = 25h
                  al       = Número de interrupción
                  ds:dx = Un puntero de tipo far (segmento:desplazamiento) en donde está la
                                nueva rutina de interrupciones. 

Función 35h 

Entrada:    ah  = 35h
                   al   = Número de interrupción.

Salida:      es:bx = Un puntero de tipo far, la actual rutina de la interrupción
 

En lenguaje C esto lo realizaríamos con las funciones que nos proporciona nuestro compilador, ya que es un lenguaje de alto nivel, no hace falta que siempre vayamos  a llamar a la interrupciones mediante ensamblador, ya que hay funciones que hacen lo mismo, a través de las interrupciones, pero de una forma más fácil para el programador. Nosotros, por ejemplo, lo haríamos de la siguiente forma:
 

void interrupt(*Anterior9h)(); // Aqui se guardan los vectores antiguos

// Instala la nueva interrupcion 9h
void InstalaTeclado(void)
{
    int i;

    // Borramos buffer del teclado
    for(i=0; i<128; i++)  tecla[i]=0;

    Anterior9h=getvect(0x09);    // Guardamos en Anterior9h los vectores
    setvect(0x09, IntTeclado);    // y la sustituimos por la nueva

    HayIntTeclado=1;
}

// Desinstala nuestra rutina de la interrupcion 9h y restaura la original
void DesinstalaTeclado(void)
{
    if (HayIntTeclado)
        setvect(0x09, Anterior9h);
    HayIntTeclado=NO;
}

 Como ven, lo que hacemos es declarar una función de tipo interrupción para guardar allí los antiguos vectores que sustituiremos después por los nuestros y después los hemos salvados en este, pues los cambiamos por nuestra nueva  interrupción, pero ¿qué es lo que hará esta interrupción? Controlará el teclado y nos informará de que teclas se están pulsando. Para ir  resulte bien, la rutina tendrá que estar escrita en ensamblador, así conseguiremos  mayor velocidad (mayor respuesta del teclado).

Lo primero que haremos será leer del puerto 60h, ya que si se ha ejecutado esta interrupción es porque hay un código que debemos recoger, por que se ha pulsado una  tecla. Una cosa muy importante que no hemos dicho, es que hay dos tipos diferentes de códigos: los códigos  Release y los códigos Make. Cuando pulsamos una tecla el teclado envía un código, pero ¿cómo sabemos cuando se ha soltado una tecla?, pues lo sabemos por que cuando se suelta una tecla, el teclado también nos envía un código. Esta característica nos será de grandísima utilidad, ya que lo que haremos será, crearnos una tabla de bytes:

unsigned char tecla[128]; 

Cada posición corresponderá a una tecla, y que pondremos en nuestra nueva posición a uno. Es por eso que en la primera rutina que vimos, colocamos todos estos valores a cero lo que significa que ninguna tecla está pulsada. Si el código es MAKE querrá decir que se ha pulsado  una tecla, y por lo tanto pondremos a uno la posición que nos  indique el código y si  por el contrario se trata de un código RELEASE  pues pondremos a cero dicha posición. Más adelante veremos una lista donde se puede observar a que tecla corresponde cada código, pues solo tenemos que crear una lista de constantes para cada valor. Por ejemplo si queremos detectar la tecla espacio haríamos lo siguiente:

if(tecla[KEY_ESPACIO]==1) tecla_apretada();

o por ejemplo poner pixeles mientras se apreta la tecla Enter:

while(tecla[KEY_ENTER]==1) 
    PutPixel(random(320), random(200), random(255), DIR_VGA);

Como hemos dicho, leemos un código y ponemos en la tabla un 0 o un 1 dependiendo de si se trata  de un código Make o de un Release. Pero ¿cómo sabemos si  es uno o otro? Pues si el valor leído es mayor de 128 se trata de un código RELEASE, es decir se ha soltado una tecla, y si no pues se trata de un código MAKE. 

Ahora veremos como nos quedaría la rutina en ensamblador para la nueva interrupción:
 

void interrupt IntTeclado(void)
{
    asm in al, 0x60                    // Leemos un byte del puerto 60h
    asm mov bl, al                    // bl=al
    asm and bl, 01111111b        // Borramos bit numero 7 de bl
    asm and al, 10000000b        // Borramos todos lo bits de al menos el 7

    asm cmp al, 128                  // ¿Esta activado el bit 7?
    asm je TECLA_SOLTADA    // Entonces esta tecla se ha soltado

    tecla[_BL]=SI;                      // Tecla pulsada
    asm jmp FIN_RUTINA          // Vamos al final de nuestra rutina

TECLA_SOLTADA:                   // Tecla soltada...
    tecla[_BL]=NO;                    // Metemos el valor 0 en el lugar correspondiente

FIN_RUTINA:
    asm mov al, 20h                  // Enviamos el byte 20h al puerto 20h para
    asm out 20h, al                    // que sepa que hemos terminado
}

Una cosa que no hemos dicho es que al acabar la interrupción deberemos enviar el valor 20h al puerto 20h, para que así sepa que hemos terminado, es  muy  importante hacer esto, ya que si no, no nos funcionará.

Haz click aquí para ver una lista de los códigos SCAN más utilizados.



Ejemplo
 

Librería gráfica: vgalib.h
Librería teclado: teclado.h
 

En el ejemplo se podrá ver la utilización de las nuevas rutinas para manejar el teclado. Con el movimiento de los cursores de podrá mover un punto o dibujar una línea. Presionando Enter se borrará la pantalla.
 

Ver ejemplo 
 
 

Bajar todo Bajar todo (37.4 Kb)


Volver a periféricos
1
Hosted by www.Geocities.ws

1