; Ejemplo de ISR con tabla de vectores que gestiona un contador de ticks, minutos y segundos. ORG 40000 call CLS ; Generamos una tabla de 257 valores "$a1" desde $fe00 a $ff00 ld hl, $fe00 ld a, $a1 ; A = $a1 ld (hl), a ; Cargamos $a1 en $fe00 ld de, $fe01 ; Apuntamos DE a $fe01 ld bc, 256 ; Realizamos 256 ldi para copiar $a1 ldir ; en toda la tabla de vectores de int. ; Activamos im2 con nuestra ISR di ld a, $fe ; Definimos la tabla a partir de $fe00. ld i, a im 2 ; Saltamos a im2 ei jr ImprimirNumero ; Hacemos la 1a impresion: "00:00" Bucle: ld a, (clock_changed) and a jr z, Bucle ; Si clock_changed no vale 1, no hay ; que imprimir el mensaje ; Si estamos aqui es que clock_changed = 1... lo reseteamos ; e imprimimos por pantalla la información como MM:SS xor a ld (clock_changed), a ; clock_changed = 0 ImprimirNumero: ld de, 0 call CursorAt ld a, (minutes) ; Imprimimos minutos + ":" + segundos call PrintNum2digits ld a, ":" rst 16 ld a, (seconds) call PrintNum2digits jr Bucle ; Repetir indefinidamente clock_changed DB 0 ticks DB 0 seconds DB 0 minutes DB 0 pause DB 0 abs_ticks DW 0 timer DW 0 POSICION_DETRAS_DEL_MAIN EQU $ ;----------------------------------------------------------------------- ; Con este ORG $a1a1 nos aseguramos de que la ISR sera ensamblada ; por el ensamblador a partir de esta direccion, que es donde queremos ; que este ubicada para que el salto del procesador sea a la ISR. ; Asi pues, todo lo que siga a este ORG se ensamblara para cargarse ; a partir de la direccion $a1a1 de la RAM. ; ; Se ha elegido $a1a1 para que esté en el bloque de 16K que empieza ; en 32768, es decir, fuera de la contented memory y fuera del bloque ; de paginación 128K. ORG $a1a1 ;----------------------------------------------------------------------- ; Rutina de ISR : incrementa ticks 50 veces por segundo, y el resto ; de las variables de acuerdo al valor de ticks. ;----------------------------------------------------------------------- CLOCK_ISR_ASM_ROUTINE: push af push hl ld a, (pause) or a jr nz, clock_isr_fin ; Si pause==1, no continuamos la ISR ld hl, (abs_ticks) inc hl ld (abs_ticks), hl ; Incrementamos abs_ticks (absolutos) ld hl, (timer) dec hl ld (timer), hl ; Decrementamos timer (ticks absolutos) ld a, (ticks) inc a ld (ticks), a ; Incrementamos ticks (50 veces/seg) cp 50 jr c, clock_isr_fin ; if ticks < 50, fin de la ISR ; si ticks >= 50, cambiar seg:min xor a ld (ticks), a ; ticks = 0 ld a, 1 ld (clock_changed), a ; ha cambiado el numero de segundos ld a, (seconds) inc a ld (seconds), a ; seconds = segundos +1 cp 60 jr c, clock_isr_fin ; si segundos < 60 -> salir de la ISR xor a ; si segundos == 60 -> inc minutos ld (seconds), a ; seconds = 0 ld a, (minutes) inc a ld (minutes), a ; minutes = minutos + 1 cp 60 jr c, clock_isr_fin ; si minutos >= 60 -> resetear minutos xor a ld (minutes), a ; minutes = 0 clock_isr_fin: pop hl pop af ei reti ; Si vamos a colocar mas codigo en el fichero ASM detra de la ISR; este sera ; ensamblado en direcciones a partir de $a1a1 a partir del final de la ISR en ; memoria. Como seguramente no queremos esto, es mejor ubicar la ISR con su ; ORG $a1a1 al final del listado o bien colocar otro ORG antes de la siguiente ; rutina a ensamblar, usando un EQU $ previo para poder continuar ; Con el "POSICION_DETRAS_DEL_MAIN EQU $" de antes de la ISR, nos guardamos ; la posición de ese punto de ensamblado, y ahora continuamos a partir de ahí: ORG POSICION_DETRAS_DEL_MAIN INCLUDE "utils.asm" END 40000