Interrupts
Assembler coding - Lesson 9
An Interrupt is a process that INTERRUPTS the processor's operation at that instant in time to execute another piece of code.
For example assume that you were running some software that monitored 100 hotel rooms to see if the fire alarm or something had gone off. If one had you execute some more code to ring the fire department. This type of coding is SLOW, it is termed POLLING. Here we are continually checking each room to see if the alarm has been set (It uses all the processing time, and we can't do anything else).
A better way to do this would be to have the alarms wired to the processors interrupt pin. An Interrupt then occurs which halts processor operation at that point in time (Note that before an Interrupt occurred, the processor could have been doing something else as it was not tied up POLLING). Now the interrupt has occurred and the processor calls an Interrupt Routine, this routine could then check which hotel alarm has been set and act accordingly.
Of course this method is external, i.e. hardwired, we will be generating interrupts internally, but you can see now what an interrupt is.
I mentioned that when an interrupt is generated it executes an Interrupt Routine at that instant in time. This means it leaves whatever code it was doing and jumps to the interrupt routine. When the interrupt routine is finished, you Return from the Interrupt Routine back to where you left the original code. The interrupt routine may well include code that overwrites your values in the accumulator and X & Y registers. You therefore need to place these values in a special place in memory called the STACK. You place these values on the STACK at the very beginning of the interrupt routine, and then the very last thing you do in your interrupt routine is to take the values back out of STACK and place them back into the registers where they came from.
The STACK is 256 bytes long and is located in memory at address 0100 Hex to 01FF Hex. The STACK is termed:
LIFO - Last In First Out
This means that whatever you place in the stack last, will be taken out first.
For example, here's the beginning and end of a interrupt routine:
PHA - Here we push the accumulator onto the stack
TXA - Here we transfer the X reg to Accumulator
PHA - Push accumulator onto stack
TYA - Transfer Y reg to Accumulator
PHA - Push accumulator onto stack
...
...
PLA - Pull value from stack into accumulator
TAY - Transfer accumulator to Y register
PLA - Pull value from stack into accumulator
TAX - Transfer accumulator to X register
PLA - Pull value from stack into accumulator
Can you see that we must do it this way otherwise all the values would be in the wrong registers.
Also remember that this is only needed if you are writing over your original register values. This method can also be used in other parts of your program to keep track of your register values.
Ok, back to actual interrupts.
There are 4 types of interrupts on the C64, these are:
RASTER - (This is what we are going to be using)
SPRITE to BACKGROUND collision
SPRITE to SPRITE collision
LIGHT PEN
Each of these interrupts is located at 53273 or $D019.
Raster - BIT 0
Sprite to Background - BIT 1
Sprite to Sprite - BIT 2
Light Pen - BIT 4
BIT 7 of $D019 (53273) is the IRQ and is set for all interrupts
The C64 generates an interrupt 60 times a second, this is used to check the keyboard etc., and when an interrupt has occurred the processor checks Bit 4 of the status register which is the BRK flag. If this is set then the program jumps to vector at locations $0316 & $0317. If BIT 4 is not set then the interrupt is an IRQ (Interrupt Request) and then the program jumps to the vector stored at locations $0314 & $0315.
A vector is the location which holds the address of where your Interrupt Routine is located at. You will notice that there are 2 vector addresses. One holds the Low Byte of your interrupt routine, whilst the other holds the high byte.
Where:
$0314 = Low Byte
$0315 = High Byte
Example
The location $0314 Holds the Value 00 (Hex)
The location $0315 Holds the value 10 (Hex)
The location of your interrupt routine would therefore placed at $1000 (Hex) or 4096 (Decimal)
(NOTE - You place the interrupt routine code at this location yourself)
Raster Lines
Your TV or monitor screen is composed of SCAN lines (raster lines). This is the way the picture is produced.
The monitor or TV is really a CRT (Cathode Ray Tube) which has a Phosphorus coated screen. At the back of the screen is an Electron Gun which fires electrons along the Tube to the screen. An electron hitting the phosphorus screen causes visible light (what you see). The gun is fired across your screen and then moves slightly down, across again, then down etc, etc. The gun is firing continuously each place where it fires is one pixel. The amount the gun moves down is 0-262 on PAL TV's and 0-312 on NTSC. This value is greater than 255 and so the register $D012 is used to hold the lower 8 bits, while $D011 holds the 9th bit. All this happens so fast that the screen looks like it does to you.
Ok enough talk lets do an example program. You will learn more by looking and then trying the code for yourself.
This example will split the screen into 3 parts. Each part will have a different background and border colour so you can see whats happened.
10 ORG 8192
20 SEI
30 LDA #147
40 JSR $FFD2
50 LDA #$7F
60 STA $DC0D
70 LDA #00
80 STA $D012
90 STA IRQCOUNT
100 LDA (UPARROW)IRQ - YOU JUST TYPE THE UP ARROW
110 STA $0315
120 LDA #IRQ
130 STA $0314
140 LDA $D01A
150 ORA #01
160 STA $D01A
165 CLI
170 LOOP JMP LOOP
180 IRQ LDA #01
190 STA $D019
200 LDA $D011
210 AND #$7F
220 STA $D011
230 LDA IRQCOUNT
240 BEQ INT1
250 CMP #01
260 BEQ INT2
270 JMP RESET
280 INT1 LDA #100
290 STA $D012
300 INC IRQCOUNT
310 LDA #02
320 STA 53280
330 STA 53281
340 JMP $EA31
350 INT2 LDA #200
360 STA $D012
370 INC IRQCOUNT
380 LDA #03
390 STA 53280
400 STA 53281
410 JMP $FEBC
420 RESET LDA #00
430 STA IRQCOUNT
440 STA $D012
450 LDA #05
460 STA 53280
470 STA 53281
480 JMP $FEBC
490 IRQCOUNT DFB 00
Right lets have a look at the explanation:
10 ORG 8192 - Where to place in memory
20 SEI - This disables interrupts until we are ready to accept them by setting up first
30 LDA #147
40 JSR $FFD2 - Clear Screen
50 LDA #$7F
60 STA $DC0D - These turn off CIA interrupts (BIT 7 = 0)
70 LDA #00
80 STA $D012 - Set first raster at 0
90 STA IRQCOUNT - Set a flag to hold count so we know where we are
100 LDA (UPARROW)IRQ
110 STA $0315 - Set the high byte of the interrupt routine called IRQ
120 LDA #IRQ
130 STA $0314 - Set the low byte of the interrupt routine
140 LDA $D01A
150 ORA #01
160 STA $D01A - The last 3 lines enable raster interrupts (BIT 0 = 1)
165 CLI - Enable interrupts again cos we have now got setup (
170 LOOP JMP LOOP - Continuous Loop
This next part is the Interrupt Routine called IRQ (this is the address stored at the vectors $0314 & $0315)
180 IRQ LDA #01
190 STA $D019 - These 2 lines cause the raster interrupt (BIT 0 = 1)
200 LDA $D011
210 AND #$7F
220 STA $D011 - These last 3 clear the 8th BIT of the raster
230 LDA IRQCOUNT - Here we find the position of the program to go to
240 BEQ INT1 - Branch here if IRQCOUNT = 0
250 CMP #01
260 BEQ INT2 - Branch here if IRQCOUNT = 1
270 JMP RESET - If IRQCOUNT is not equal 0 or 1 then jump to RESET
280 INT1 LDA #100 - The first position
290 STA $D012 - We set the raster position to 100 down the screen
300 INC IRQCOUNT - +1 to the flag (now = 1)
310 LDA #02
320 STA 53280
330 STA 53281 - Change the colours of the background and borders to RED
340 JMP $EA31 - Jump to ROM (Main entry IRQ point)
350 INT2 LDA #200 - Position 2
360 STA $D012 - We have set the raster to occur at position 200 down the screen
370 INC IRQCOUNT - +1 to flag again (now = 2)
380 LDA #03
390 STA 53280
400 STA 53281 - Change colours of border & background
410 JMP $FEBC - Jump to ROM (Exit Interrupt)
420 RESET LDA #00 - 3rd position
430 STA IRQCOUNT - And so we now reset the flag to zero as all positions are done
440 STA $D012 - We also set the raster back to zero
450 LDA #05
460 STA 53280
470 STA 53281 - Again we change the colours of the border and background
480 JMP $FEBC - And again jump to ROM (Exit Interrupt)
490 IRQCOUNT DFB 00 - This is the memory location for IRQCOUNT
Well that about raps it up. Now you can see that on each of those positions you could have 8 sprites in each, and different direction scrolls or whatever takes your fancy.
We will do some kind of program like that later, but in the next lesson we will learn how to do raster colour bars.