Classic Computer Magazine Archive COMPUTE! ISSUE 40 / SEPTEMBER 1983 / PAGE 263

All About The
Hardware Interrupt

Peter Marcotty

Using the hardware interrupt vector is not something that you can learn by reading a user's manual. This article defines it and discusses how to use it in your machine language programs.



An interrupt is a hardware event. Every 60th of a second, a clock inside the computer causes a change in voltage on one of the pins of the 6502 chip (6510 if you have a 64). This change tells the 6502 to stop (interrupt) whatever it is doing, remember how to get back to it, and go to the machine language program pointed to by the hardware interrupt vector (an address inside the computer which points to the address of a machine language program that normally "services" the interruption).
    Usually the vector sends the computer to a program that updates the screen, looks at the keyboard, and changes the value of TI$. (This is the "servicing.") No matter what you are doing in BASIC or machine language, the interrupt will happen 60 times a second unless you specifically turn it off.
    Perhaps the most effective use of the interrupt is that you can wedge a routine of your own into the process, before it goes off to its regular house keeping chores. Simply point the interrupt vector to the beginning of your routine, do whatever you want to do, and then send the computer to where it usually goes.
    In order for us to change the interrupt vector, we must stop the hardware interrupt action altogether. If it tried to jump to the location pointed to by the interrupt vector, and we had changed only one byte of the two-byte vector (remember, interrupts can happen at any time), we'd get some very undesirable results.

Implementing The Interrupt
It will be helpful if you refer to the program for your machine while reading this section.
    The first line of your program should be the SEI command. SEI stands for SEt Interrupt mask, and it will stop the computer from interrupting until you let it. After an SEI, you have about 0.009 seconds to change the interrupt vector before the computer gets impatient and crashes. Fortunately, this is plenty of time for our purposes. The next four lines take the address of our program (both the low and high byte) and put them in the hardware interrupt vector. Next we have a CLI (CLear Interrupt mask) which tells the computer it can start performing interrupts again. Finally, we have an RTS command which returns us to BASIC.
    The program does not finish running with the RTS command; in fact, it's only just beginning. Since the hardware interrupt vector now points to our own routine, every 60th of a second our main program will be run, almost without any delay in whatever else we might be doing.
    At the end of the routine that does the actual work, we cannot return from wherever we were called with a simple RTS. The screen has yet to be updated, and the keyboard hasn't been checked to see if any keys are down. We must JMP to the location where the vector usually points. That's where the servicing routine resides. The locations of the hardware interrupt vector for various computers are given in the table.
    The sample program should help you understand how your interrupt routines must be set up.
    To turn off your interrupt-driven program, you can change the pointer back to its original value, or on the VIC and 64, simply hit RUN/STOP and RESTORE.
    The example programs simply take a look at the contents of the memory location that shows what key is currently being pressed and puts it in the top left corner of the screen.
    Two programs are given for each machine. The first can be typed in with an assembler, and the second is a hexadecimal dump to be entered with a monitor. Both have exactly the same effects. To RUN the programs on a PET, type SYS 826; on a VIC or 64, SYS 828. The programs are located in the second cassette buffer, a 192-byte-area of memory that is usually safe for small machine language programs.
    Note that interrupt-driven programs will interfere with the normal operation of LOAD and .SAVE commands.

Interrupt Memory Locations
The hardware interrupt on the 64 and VIC works in exactly the same way as on the PET, although memory locations will be different.
    This table shows all the differences:


Location of
Hardware Interrupt Vector
 
Points to
Upgrade PETs 144-145 ($90-$91) $E62E
4.0 PETs 144-145 ($90-$91) $E455
64
788-789 ($314-$315) $EA31
VIC
788-789 ($315-$315) $EABF

Program 4: Hardware Interrupt Routine - VIC Version

2
4:    033C            .OPT P4,OO
6:    033C            *=   $033C
              ;VIC VERSION
10:    033C 78        SEI         ;DISABLE INTERRUPTS
20:    033D A9 49     LDA #$49    ;LOAD LOW BYTE OF ROUTINE IN LINE 80
30:    033F 8D 14 03  STA $314    ;STORE LO BYTE OF INTERRUPT VECTOR
40:    0342 A9 03     LDA #$03    ;LOAD HI BYTE OF ROUTINE IN LINE 80
50:    0344 8D 15 03  STA $315    ;STORE HI BYTE OF INTERRUPT VECTOR
60:    0347 58        CLI         ;REENABLE INTERRUPT
70:    0348 60        RTS         ;RETURN
80:    0349 A5 CB     LDA 203     ;LOAD CURRENT KEY PRESSED
90:    034B 8D 00 lE  STA $lE00   ;STORE IT ON THE SCREEN
95:    034E A9 00     LDA #0
97:    0350 8D 00 96  STA $9600   ;SET COLOR TO BLACK
1000: 0353 4C BF EA   JMP $EABF

C*

    PC  IRQ  SR AC XR YR SP
.; B780 E455 2C 34 3A 9D FA
.
.; 033C 78 A9 49 8D 14 03 A9 03
.; 0344 8D 15 03 58 60 A5 CB 8D
.; 034C 00 1E A9 00 8D 00 96 4C
.; 0354 BF EA 49 56 2E 36 34 2E


Interrupt Applications

Eric Brandon, Editorial Programmer

Interrupts can be used in many different applications, but the two most common are within utilities and games.
    Because an interrupt-driven program is in the "background" of whatever the user is doing, it is ideal for applications where we want to do something concurrent with the normal operation of the computer. Good examples of this are found in "Marquee" (COMPUTE!, February 1981), which displays a message across the top of the screen as a sort of electronic "string around your finger," and "Realtime Clock" (COMPUTE!, January 1982), which displays the time in a corner of the screen to remind you to stop playing Alien Zap and go to bed.
    Other uses for interrupt-driven utilities are programs which constantly check which keys are pressed and act accordingly. My favorite from this class is "Keyprint" (COMPUTE!, November/December 1980). Whenever you hit the & and the shift simultaneously, the computer freezes and sends whatever is on the screen to the printer.
    In games, interrupts can be used for convenience or smoothness. Suppose you want to write a space game which has a moving starfield in the background. You could worry about writing a program which simultaneously moves your spaceship, the mutant ants, and the starfield around, or you could use interrupts. It is a simple matter to write a routine which moves some stars around and to point the interrupt vector to it. Now, you can write your game safe in the knowledge that whatever is going on in your program, those stars will keep floating by.
    Best of all, when something holds up your main program for a second or two, such as a sound effect or an explosion, the back ground won't freeze up but will keep moving, making your game look "smoother" and more professional.

Program 1: Hardware Interrupt Routine - 4.0 BASIC Version (4032, 8032)
2
4:     033A            .OPT P4,OO
6:     033A            *=   $033A
               ;PET 4.0 VERSION
10:    033A 78         SEI        ;DISABLE INTERRUPTS
20:    033B A9 45      LDA #$45   ;LOAD LOW BYTE OF ROUTINE IN LINE 80
30:    033D 85 90      STA $90    ;STORE LO BYTE OF INTERRUPT VECTOR
40:    033F A9 03      LDA #$03   ;LOAD HI BYTE OF ROUTINE IN LINE 80
50:    0341 85 91      STA $91    ;STORE HI BYTE OF INTERRUPT VECTOR
60:    0343 58         CLI        ;REENABLE INTERRUPT
70:    0344 60         RTS        ;RETURN
80:    0345 A5 97      LDA 151    ;LOAD CURRENT KEY PRESSED
90:    0347 8D 00 80   STA $8000  ;STORE IT ON THE SCREEN
1000:  034A 4C 55 E4   JMP $E455

C*

    PC  IRQ  SR AC XR YR SP
.; B780 E455 2C 34 3A 9D F8
.
.; 033A 78 A9 45 85 90 A9 03 85
.; 0342 91 58 60 A5 97 8D 00 80
.; 034A 4C 55 E4 30 2C 30 30 3F



Program 2: Hardware Interrupt Routine - Upgrade ROM Version (3096, 3032)
2
4:     033A           .OPT P4,OO
6:     033A           *=   $033A
              ;PET UPGRADE (2.0) VERSION
10:    033A 78        SEI       ;DISABLE INTERRUPTS
20:    033B A9 45     LDA #$45  ;LOAD LOW BYTE OF ROUTINE IN LINE 80
30:    033D 85 90     STA $90   ;STORE LO BYTE OF INTERRUPT VECTOR
40:    033F A9 03     LDA #$03  ;LOAD HI BYTE OF ROUTINE IN LINE 80
50:    0341 85 91     STA $91   ;STORE HI BYTE OF INTERRUPT VECTOR
60:    0343 58        CLI       ;REENABLE INTERRUPT
70:    0344 60        RTS       ;RETURN
80:    0345 A5 97     LDA 151   ;LOAD CURRENT KEY PRESSED
90:    0347 8D 00 80  STA $8000 ;STORE IT ON THE SCREEN
1000:  034A 4C 2E E6  JMP $E62E

C*
    PC  IRQ  SR AC XR YR SP
.; B780 E455 2C 34 3A 9D FA
.
.; 033A 78 A9 45 85 90 A9 03 84
.; 0342 91 58 60 A5 97 8D 00 80
.; 034A 4C 2E E6 30 2C 30 30 3F



Program 3: Hardware Interrupt Routine - 64 Version
2
4:     033C            .OPT P4,OO
6:     033C            *=   $033C
               ;64 VERSION
10:    033C 78         SEI       ;DISABLE INTERRUPTS
20:    033D A9 49      LDA #$49  ;LOAD LOW BYTE OF ROUTINE IN LINE 80
30:    033F 8D 14 03   STA $314  ;STORE LO BYTE OF INTERRUPT VECTOR
40:    0342 A9 03      LDA #$03  ;LOAD HI BYTE OF ROUTINE IN LINE 80
50:    0344 8D 15 03   STA $315  ;STORE HI BYTE OF INTERRUPT VECTOR
60:    0347 58         CLI       ;REENABLE INTERRUPT
70:    0348 60         RTS       ;RETURN
80:    0349 A5 CB      LDA 203   ;LOAD CURRENT KEY PRESSED
90:    034B 8D 00 04   STA $0400 ;STORE IT ON THE SCREEN
95:    034E A9 01      LDA #1
97:    0350 8D 00 D8   STA $D800 ;SET COLOR TO WHITE
1000:  0353 4C 31 EA   JMP $EA31

C*
    PC  IRQ  SR AC XR YR SP
.; B780 E455 2C 34 3A 9D FA
.
.; 033C 78 A9 49 8D 14 03 A9 03
.; 0344 8D 15 03 58 60 A5 CB 8D
.; 034C 00 04 A9 01 8D 00 D8 4C
.; 0354 31 EA 49 56 2E 34 2E 30