Egghead.page Logo

How the Commodore 64 Handles Hardware Interrupt Requests

This article provides a technical overview of the interrupt request mechanism within the Commodore 64 computer system. It details how the MOS 6510 processor interacts with peripheral chips like the VIC-II and CIA to manage hardware signals. Readers will learn about the specific interrupt vectors, the role of the Kernal ROM in default handling, and the step-by-step process the CPU executes when an external device demands attention.

The 6510 CPU and Interrupt Lines

At the heart of the Commodore 64 is the MOS 6510 microprocessor, a variant of the famous 6502 chip. This CPU manages hardware interruptions primarily through two dedicated pins: the Interrupt Request (IRQ) and the Non-Maskable Interrupt (NMI). The IRQ line is the most frequently used pathway for hardware devices. When a device pulls the IRQ line low, the CPU completes its current instruction, checks the Interrupt Disable flag in the status register, and if interrupts are enabled, it initiates the interrupt sequence. The NMI line is reserved for critical events that cannot be ignored, such as a system reset or specific user port signals, and bypasses the Interrupt Disable flag.

The Role of CIA and VIC-II Chips

Hardware interrupts in the Commodore 64 generally originate from two main integrated circuits: the VIC-II video chip and the Complex Interface Adapter (CIA) chips. The VIC-II generates raster interrupts, which trigger when the electron beam reaches a specific line on the screen. These are essential for splitting screens, changing colors mid-frame, and synchronizing music players. The CIA chips, specifically CIA 1, handle system timing and peripheral communication. CIA 1 Timer A is configured to generate an interrupt 60 times per second (in NTSC regions), serving as the system clock that drives the Kernal’s internal timers and keyboard scanning routine.

The Interrupt Vector Table

When the 6510 CPU acknowledges an IRQ, it needs to know where to find the code responsible for handling the event. It looks at a specific location in memory known as the interrupt vector table. For standard IRQs, the CPU reads a 16-bit address from memory locations $FFFE and $FFFF. In a stock Commodore 64, these locations point to the Kernal ROM’s default IRQ handler routine. For NMIs, the CPU consults the vector at $FFFA and $FFFB. This indirection allows advanced programmers to replace the default system handler with custom code by simply poking new addresses into these vector locations.

The Kernal IRQ Handler

The default interrupt handler resides in the Kernal ROM at address $EA31. When triggered, this routine performs several housekeeping tasks before returning control to the main program. It first checks the CIA 1 interrupt status register to see if the timer caused the request. If so, it increments the system clock variables stored in RAM. It then checks the VIC-II status register to determine if a raster interrupt occurred. Finally, it scans the keyboard matrix and checks for RS-232 activity. Once all sources are serviced, the handler executes an RTI (Return from Interrupt) instruction, which restores the processor status and program counter, resuming the main program exactly where it left off.

Acknowledging and Clearing Interrupts

A critical aspect of handling interrupts on the Commodore 64 is acknowledging the hardware source. Unlike some modern systems, the 6502 CPU does not automatically clear the interrupt signal. The software handler must explicitly read or write to the status registers of the CIA or VIC-II chips to clear the interrupt flag. If the handler fails to clear the flag, the interrupt line remains active, causing the CPU to immediately re-enter the interrupt routine upon execution of the RTI instruction. This leads to a system lockup known as an interrupt loop. Therefore, proper register management is essential for stable hardware interaction.