; 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