Table of Contents (click on a link to jump to that web page)
- Part 1 – What is an IRQ and when would I use it?
- Part 2 – Overview with an example program
- Part 3 – Can my IRQ run without effecting BASIC?
- Part 4 – Simpler ways to use interrupts on the CoCo
- Part 5 – Advanced interrupt settings and using CoCo 3 specific interrupts
Hello I’ve decided to write some posts that describe how to use IRQs on the CoCo. This was one of the last things about assembly language programming that I learned and has been a mystery to me for years. With the assistance of some very knowledgeable and helpful people on the CoCo mailing list I was able to figure out how to set up an IRQ on the CoCo 3. Recently I was working on my MIDI to CoCo converter program and I wanted to output the data with an option that would include the player that could be run from an IRQ. I was having trouble getting it working on the CoCo 1 and I started doubting my understanding. So I turned to the internet for some help but there wasn’t much in the way of example code for setting up and handling IRQs. It turned out that my problem was a typo and that my program code was OK after all. But since I discovered there isn’t too much info on IRQs for the CoCo that I should write up a blog and share what I’ve learned about them for others and to help myself in the future when I start second guessing myself again why my program doesn’t work the way I think it should.
I did find some great info on page 10 of CoCo Clipboard Magazine Volume 2 Issue 6 July/August 1989 by Kraig Brockschmidt
On with the info you came here for…
What is an interrupt request?
An Interrupt Request literally “interrupts” the CPU from processing it’s normal program execution and jumps to another routine and once that other routine is complete it jumps right back to the program code it was already executing.
How do users make an interrupt happen?
A user makes an interrupt happen when they are typing on the keyboard or pressing a joystick button or presses the power on or reset button.
Are those the only interrupts the 6809 has?
No, there are three software interrupts called SWI,SWI2 and SWI3 and four hardware interrupts which are called IRQ, FIRQ, NMI and RESET
When would I use a software interrupt?
Software Interrupts are used mainly in OS-9 where the registers are loaded with values needed for a function prior to a SWI2 instruction and the byte right after the SWI2 holds the function identifier. Since the interrupt pushes all the registers onto the stack the function can pull them off the stack to use them then return execution to the users program.
Another use for software interrupts is when debugging some machine code. This isn’t necessary these days with powerful tools such as MAME’s debugger. But at the system level a program like Zbug could use a SWI command as a breakpoint and when the program reaches the SWI Zbug’s interrupt handling routine would present all the register values to the user since they are automatically pushed onto the stack.
When would I use the hardware interrupts (IRQ, FIRQ, NMI and RESET)?
These are examples of different things that can trigger a hardware interrupt:
- Joystick Button being pressed
- Keyboard button being pressed or released
- RS-232 status line changes
- Cartridge interrupt signal – Color BASIC uses FIRQ to vector control to a ROM-PAK if pins 7 & 8 of the cartridge port are connected together by a cartridge.
- NMI pin is connected only to the cartridge port. The Disk Operating System (DOS) uses the NMI to vector out of data transfers between the CPU and the Floppy Disk Controller.
- Vertical SYNC just occurred
- Horizontal SYNC just occurred
- Disk Drive Motor starts or stops
- CoCo 3 has an internal timer that counts down, when it reaches zero an interrupt occurs
- Reset switch or power on causes a RESET interrupt
I mentioned the RESET interrupt above because it might be useful for a programmer to change the RESET interrupt (Vector) address to be something different like restarting a game. Or showing a blue screen to see if the artifact colours match what the game needs.
How does the CPU know where to return once it jumps to an interrupt request?
When an interrupt request is triggered the CPU pushes the Condition Code (CC) register on the stack and the Program Counter (PC) on the stack. Depending on which type of interrupt is triggered the CPU will also push the rest of the registers on the stack. If the CPU is going to push all the registers on the stack it will first set the E flag of the Condition Code register. This let’s the CPU know that at the end of the interrupt request routine (where the RTI instruction is used) that it should restore all the registers and not just the CC and PC.
Which interrupts backup all the registers and which don’t?
The IRQ, NMI and all the software interrupts backup all the registers. The FIRQ only backups the CC and the PC.
Why doesn’t the FIRQ backup all the registers?
The name of the FIRQ is Fast Interrupt Request and is given that name because it executes faster then a regular IRQ. It’s faster because the FIRQ doesn’t use as many CPU cycles, it doesn’t backup and restore all the registers each time its triggered. The programmer must make sure to backup and restore the registers that the routine uses.
How does the CPU know where the interrupt is located in memory?
This is an example of how an IRQ interrupt works:
- The CPU is running through your program then an IRQ is triggered.
- The CPU finishes executing the instruction it is at.
- It sets the E flag of the CC register indicating to restore all registers when the RTI instruction is processed.
- The CPU backs up all the registers onto the stack.
- Then it looks at the address $FFF8 and $FFF9 to find out what address it should jump to for the IRQ. This is hard coded in the CoCo 1 and 2 to address $010C which has a JMP instruction that points to the IRQ routine.
- This RAM at address at $010C-$010E can be changed by the user so it points to the users own interrupt request routine.
- The IRQ code gets executed and when the code is finished it uses an RTI instruction.
- Since the E flag of the CC register is set with an IRQ the CPU will then restore all the registers back to how they were just before the IRQ was triggered. This includes the Program Counter (PC) to return the CPU back to the address where it was executing your program from and continues as if nothing happened.
This is an example of how an FIRQ interrupt works similar to the IRQ except in Bold below:
- The CPU is running through your program then an FIRQ is triggered.
- The CPU finishes executing the instruction it is at.
- The CPU backs up only the CC and the PC onto the stack.
- Then it looks at the address $FFF6 and $FFF7 to find out what address it should jump to for the FIRQ. This is hard coded in the CoCo 1 and 2 to address $010F which has a JMP instruction that points to the FIRQ routine.
- This RAM at address at $010F-$0111 can be changed by the user so it points to the users own interrupt request routine.
- The FIRQ code gets executed and when the code is finished it uses an RTI instruction.
- Since the E flag of the CC register is not set with an FIRQ the CPU will then restore only the CC and PC to return the CPU back to the address where it was executing your program from and continues as if nothing happened.
Which interrupts get used the most and why?
If you are writing your own assembly programs on the CoCo you will generally be using the IRQ and the FIRQ. Any of the user interrupts can be defined as an IRQ or FIRQ and it’s up to the programmer to decide which to use and when.
Generally you would use the VSYNC interrupt to know when the computer has finished updating the screen which is the best time to move an object on the screen. For example in a game. This will limit tearing or noticeable glitches on the screen. A programmer can also program what is called double buffering using the VSYNC and would have two copies of the screen data in RAM. When the VSYNC is triggered you switch to the other screen. Then you move your characters around in the background (not shown) screen. Then when the VSYNC is triggered again you switch to other screen that had it’s characters updated, etc..
Since the VSYNC is a constant value (60 Hz in NTSC countries and 50 Hz is PAL countries) it can be used in sound generating routines.
On the CoCo 3 you have a Timer interrupt that is very handy for different things one is to use it for audio sample playback using an FIRQ. You set the Timer value and when it reaches zero the FIRQ is triggered and the Timer value is reset to your programmed value so it will constantly be triggered over and over. The FIRQ routine sends a value to the CoCo’s DAC each time it is triggered. The flexibility of the CoCo 3’s Timer allows you to control the sample speed and how much CPU usage will be used for audio playback.
Are there any other 6809 instructions that are specific to interrupts?
There are two more instructions that a programmer can use relating to interrupts. They are:
- CWAI #$XX – Halts the CPU and sets the E flag of the CC and saves all the accumulators and registers to the stack then waits for an interrupt to happen. Since it already has backed up all the registers it is faster once the Interrupt is triggered.
- SYNC – The CPU stops processing instructions and waits until an interrupt occurs. Typically this is used with the interrupts masked so the interrupts aren’t used they simply trigger program execution to start again with the instruction after the SYNC command. The palette command on the CoCo 3’s Super Extended Color BASIC uses the SYNC command to make sure the “sparkles” don’t happen when you change the palette values on the screen ($E62A-$E633)
Interrupts sound neat, can you show me exactly how to setup an IRQ?
I will go over that in the next part of this series…
See you in the next post, Glen