CIA1: Temporización

Una forma sencilla de conseguir un “cronómetro” es mediante un contador. Un contador es un registro que, partiendo de cero, va incrementando su valor a intervalos regulares. De este modo, cuando termine el intervalo de tiempo a medir, se para el contador y se analiza su valor. Y dado que el período de tiempo entre incrementos será conocido, esto permite calcular fácilmente el tiempo transcurrido: tiempo = valor del contador x período entre incrementos.

Otra variante de lo anterior es la “cuenta atrás”. El mecanismo es muy parecido. En este caso, el contador se carga con un valor inicial y se va decrementando a intervalos regulares. Cuando el contador llega a 0, se activa algún “flag” o se genera una interrupción.

Esta forma de esperar un tiempo es mucho más interesante que el típico bucle de espera implementado por programa:

Retardo

En primer lugar, el tiempo de espera de un bucle es difícil de conocer y controlar con precisión. Habría que analizar el número de ciclos de reloj que consume todo el bucle (o cada iteración), y multiplicarlo por el tiempo que dura cada ciclo de reloj (el inverso de la frecuencia de reloj). Pero es que, además, mientras el 6510 ejecuta el bucle de espera no puede ejecutar otra cosa; son ciclos de reloj desperdiciados durante la espera.

Sin embargo, si la espera o cuenta atrás la controla otro registro (un registro del CIA1), el 6510 puede seguir ejecutando otras tareas útiles y, cuando termine el tiempo establecido, se ejecutará una rutina de interrupción. Por tanto, es un enfoque mucho más interesante.

De hecho, este es el mecanismo que utiliza el sistema operativo del C64. Un registro genera interrupciones 60 veces por segundo, y esas interrupciones se utilizan para escanear el teclado y realizar otras tareas.

Por claridad, repetimos aquí los registros del CIA1 que tienen que ver con temporización:

REGISTRO DIRECCIÓN FUNCIÓN
TIMALO $dc04 Contador A. Parte menos significativa (low).
TIMAHI $dc05 Contador A. Parte más significativa (high).
TIMBLO $dc06 Contador B. Parte menos significativa (low).
TIMBHI $dc07 Contador B. Parte más significativa (high).
CIAICR $dc0d Registro de control de interrupciones.

Bit 0: 1=contador A llega a 0.

Bit 1: 1=contador B llega a 1.

Bit 2: 1=alarma TOD.

Bit 7: 1=cualquier flag activo.

CIACRA $dc0e Registro de control del contador A.

Bit 0: 1=arrancar; 0=parar.

Bit 3: 1=one-shot; 0=free-running.

Bit 5: 1=reloj externo; 0=reloj interno.

CIACRB $dc0f Registro de control del contador B.

Bit 0: 1=arrancar; 0=parar.

Bit 3: 1=one-shot; 0=free-running.

Bit 6,5: 01=reloj externo; 00=reloj interno; 10=contador A pasa por 0.

Bit 7: 1=alarma TOD.

Contadores A y B:

En primer lugar, tenemos los contadores A y B, ambos de 16 bits (TIMAHI-TIMALO y TIMBHI-TIMBLO). Sirven para controlar intervalos de tiempo como hemos descrito, funcionando en modo “cuenta atrás”.

Se cargan con el valor inicial deseado mediante la instrucción “sta”, y se van decrementando una vez arrancados. Se pueden leer con la instrucción “lda”, en cuyo caso devuelven por qué valor van.

Registros de control de los contadores A y B:

En segundo lugar, tenemos los registros de control asociados a esos contadores (CIACRA y CIACRB), que sirven para arrancar y parar los contadores, seleccionar los diferentes modos de funcionamiento, seleccionar la señal de tiempo que produce los decrementos, etc.

Para arrancar un contador hay que poner a 1 el bit 0 de CIACRA/CIACRB. Para parar un contador hay que poner a 0 ese mismo bit.

Respecto a los modos de funcionamiento, tenemos el modo “one shot” (bit 3 = 1) y el modo “free running” (bit 3 = 0). Con el primero el contador sólo cuenta una vez y se para al llegar a 0. Con el segundo, el contador cuenta una y otra vez, hasta que se cambie su configuración.

Por último, respecto a la señal de reloj que produce los decrementos, ésta puede ser el reloj interno del C64 (bit 5 = 0) o una señal de reloj externa (bit 5 = 1) que se aplique al pin CNT del puerto de usuario.

El reloj interno del C64 tiene una frecuencia de 0,985 MHz en el modelo PAL (Europa) y de 1,023 MHz en el modelo NTSC (América). Es decir, los ciclos de reloj son de 1,02 y 0,97 microsegundos, respectivamente.

En el caso del contador B, y sólo en este caso, es posible configurarlo para que se decremente cada vez que el contador A pase por 0. Es decir, es posible concatenar los dos contadores A y B como si fueran un único contador de 32 bits. De este modo se consigue contabilizar intervalos de tiempo muy largos, algo más de una hora si la fuente de reloj utilizada es la interna (2^32 intervalos de 1,02 microsegundos = 1,21 horas).

Esta configuración se consigue con bit 6 = 1 y bit 5 = 0 del CIACRB.

Registro de control de las interrupciones:

En tercer lugar, tenemos el registro de control de interrupciones (CIAICR), que es donde están los “flags” que señalizan que los contadores A o B han llegado a 0, y donde se configuran las interrupciones deseadas.

Cuando el contador A llega a 0 se activa el bit 0 de CIAICR, y cuando el contador B llega a 0 se activa el bit 1. Para detectar estos flags habrá que ejecutar la instrucción “lda CIAICR”, en cuyo caso todos los flags se vuelven a poner a 0 automáticamente.

El bit 7 de CIAICR se activa siempre que cualquiera de los “flags” (los otros bits de CIAICR) esté activado.

Para configurar las interrupciones deseadas, habrá que ejecutar la instrucción “sta CIAICR”, donde, en función del valor del acumulador:

  • Si el bit 7 vale 1: los bits 0…6 que estén a 1 activarán las interrupciones cuando los flags correspondientes de CIAICR pasen a estar activados.
  • Si el bit 7 vale 0: los bits 0…6 que estén a 1 desactivarán las interrupciones de los flags correspondientes de CIAICR.

En ambos casos (bit 7 = 0 o 1) los restantes bits a 0 a cargar en CIAICR ni activan ni desactivan interrupciones. Simplemente, no modifican la configuración de las interrupciones.

Contador segundos-1


Programa de ejemplo: Prog57

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s