There are four types of interrupts which can occur with the 6502 microprocessor:
6502 interrupts
On the 400/800 the chip reset occurs only upon power-up and causes the computer to do a cold start. On later models, pressing [SYSTEM RESET] will cause a chip reset but the computer then does a warm start. On the 400/800, the [SYSTEM RESET] key generates a NMI interrupt.
This is a synopsis of the cold start routine.
The difference between cold start and warm start is the condition of the warm start flag, WARMST, [$0008]. If this flag is 0 a complete cold start is executed. If the flag is anything other than 0 then only the warm start part of the warm start/cold start code is executed.
NMI interrupts are generated by the following conditions:
When an NMI interrupt occurs, the hardware register NMIST [$D40F] is examined to determine what type of interrupt occurred. The computer is then directed through the proper ram vector to service the interrupt.
The computer makes no use of DLIs. The ram vector points to an RTI instruction.
There are two stages to the VBI service routine. The second stage is only done if a critical function was not interrupted.
Stage 1 (VBI)
The real time clock, RTCLOK [$0012 - $0014], is incremented.
The attract mode variables are processed.
System timer 1 is decremented. If it goes to zero the computer JSRs through system time-out vector 1.
Stage 2 (VBI)
The hardware registers are loaded with the data in their shadow registers.
System timer 2 is decremented. If it goes to zero the computer JSRs through the system time-out vector 2.
System timers 3, 4, and 5 are decremented. If a timer goes to zero the computer sets system timer flags 3, 4, and/or 5.
If auto-repeat is active, the auto-repeat process is done.
The keyboard debounce timer is decremented if not 0.
Information at the controller port registers is read, processed and placed in the proper shadow registers.
[SYSTEM RESET] INTERRUPT
If a [SYSTEM RESET] interrupt is generated on the 400/800 the computer jumps to the warm start routine.
When an IRQ interrupt occurs the hardware register IRQST [$D20E], the PIA status registers, PACTL [$D302] and PBCTL [$D303] are examined to determine what caused the interrupt.
For each interrupt, the 6502 accumulator is pushed to the stack. The computer is then directed to the proper ram vector to service the interrupt.
The operating system doesn't use software interrupts. The software interrupt vector points to a PLA followed by an RTI.
Interrupt vectors Label address type function VDSLST $0200 NMI DLI Points to an RTI VVBLKI $0222 NMI stage 1 VBI VVBLKD $0224 NMI return-from-interrupt routine CDTMA1 $0226 NMI time-out 1 (used by SIO) CDTMA2 $0228 NMI time-out 2 (not used by OS) VPRCED $0202 IRQ not used (points to PLA,RTI) VINTER $0204 IRQ not used (PLA,RTI) VKEYBD $0208 IRQ keyboard interrupt VSERIN $020A IRQ used by Serial I/O routine VSEROR $020C IRQ used by SIO VSEROC $020E IRQ used by SIO VTIMR1 $0210 IRQ not used by OS (PLA,RTI) VTIMR2 $0212 IRQ not used by OS (PLA,RTI) VTIMR4 $0214 IRQ ? VIMIRQ $0216 IRQ main IRQ code VBREAK $0206 BRK unused by OS (PLA,RTI)
The following timers are updated during vertical blank (VBI) as noted above. If a timer is decremented to 0 the computer jumps through it's associated vector or sets it's associated flag.
Label address flag/vector RTCLOK $0012 3 byte clock ($0012 = MSB) CDTMV1 $0218 CDTMA1 $0226 vector (SIO time-out) CDTMV2 $021A CDTMA2 $0228 vector CDTMV3 $021C CDTMF3 $022A flag CDTMV4 $021E CDTMF4 $022C flag CDTMV5 $0220 CDTMF5 $022E flag
There are two registers on the antic chip which control interrupts. These registers can be used to disable interrupts if necessary. There are also two associated interrupt status registers.
The IRQ enable and status registers use the same address. The result is that reading the register does not reveal the enabled interrupts but the interrupts pending. IRQ interrupt enable data should usually be written to the OS shadow first. Reading the OS shadow tells which interrupts are enabled.
Non maskable interrupt enable NMIEN $D40E 7 6 5 4 3 2 1 0 ----------------- | | | not used | ----------------- bit 7 1 = DLI enabled 6 1 = VBI enabled Non maskable interrupt status NMIST $D40F 7 6 5 4 3 2 1 0 ----------------- | | | | not used| ----------------- bit 7 1 = DLI pending 6 1 = VBI pending 5 1 = [SYSTEM RESET] key pending Interrupt request enable IRQEN $D20E 7 6 5 4 3 2 1 0 ----------------- | | | | | | | | | ----------------- bit 7 1 = [BREAK] key interrupt enable 6 1 = keyboard interrupt enable 5 1 = serial input interrupt enable 4 1 = serial output interrupt enable 3 1 = serial output-finished interrupt enable 2 1 = timer 4 interrupt enable 1 1 = timer 2 interrupt enable 0 1 = timer 1 interrupt enable IRQEN has a shadow register, POKMSK [$0010 (A)]. Interrupt request status IRQST $D20E 7 6 5 4 3 2 1 0 ----------------- | | | | | | | | | ----------------- bit 7 1 = [BREAK] key interrupt pending 6 1 = keyboard interrupt pending 5 1 = serial input interrupt pending 4 1 = serial output interrupt pending 3 1 = serial output-finished interrupt pending 2 1 = timer 4 interrupt pending 1 1 = timer 2 interrupt pending 0 1 = timer 1 interrupt pending
Writing any number to WSYNC [$D40A (54282)] will cause the computer to stop and wait for the next TV horizontal sync.
It is wise to use DLIs one TV line before needed then writing to WSYNC. This will keep other interrupts from causing DLIs to be serviced late. This can cause a DLI to change something in the middle of a scan line.
Useful database variables and OS equates POKMSK $0010 (16): IRQEN shadow IRQEN $D20E (53774): enables IRQs when written to IRQST $D20E (53774); gives IRQs waiting when read PACTL $D302 (54018): bit 7 (read) peripheral A interrupt status bit 0 (write) peripheral A interrupt enable PBCTL $D303 (54019): bit 7 (read) peripheral B interrupt status bit 0 (write) peripheral B interrupt enable WSYNC $D40A (54282): wait for horizontal sync NMIEN $D40E (54286): NMI enable NMIST $D40F (54287): NMI status