Surviving Restore key presses while using CIA 2 timer NMIs
by White Flame
The /NMI pulse from the restore key seems to be longer than 1 frame. When this happens, the CIA 2 interrupt source doesn't cause the NMI to trigger, so the timer never gets ACKed, and NMIs appear to stop as /NMI is locked low, even though the timer is still running.
Restore _______________2 ____________________ key \_________________________/ CIA timer 1 3 events | | | | ______ ____________ CIA /IRQ \_/ACK ACK \________________________________________ ______ ______ /NMI NMI\_/ NMI\______________________________________________
At location 1, a normal timer interrupt occurs, drawing /NMI low. The processor runs the NMI handler, which ACKs the timer, releasing the /NMI line to its default high state. When the Restore key is pressed at location 2, the NMI handler is called and can detect that the CIA did not cause the NMI. However, NMI is not released by the time the next timer event occurs. This event will ground the /NMI line, but it's already still grounded from the Restore key, so the processor doesn't see the falling-edge event. The CIA timer keeps running, but since one of the timer events was never ACKed, the /NMI stays low indefinitely.
There are a couple of ways to resolve this. The simplest one is simply to periodically ACK the CIA timer from the main non-interrupt code, which will eventually release the CIA's /NMI assertion if a timer ACK is missed due to the Restore key. A few timer events will have been lost, but the CPU will start to receive NMI events again after the Restore key pulse has ended. When the timer is periodically ACKed by the main code, it can check to see if the timer interrupt was actually asserting, and trigger code to handle the lost-event case when the NMI comes back online.
The redundant ACKs will not interfere with NMI triggering. However, there is the slight possibility that the they will read the CIA interrupt register (thus clearing it) as the NMI occurs, in which case the NMI handler will think that the CIA didn't trigger it. If there is only one NMI input source (disregarding the Restore key) and the failsafe ACKs are happening, you shouldn't have to read the bits of the interrupt register. If there are multiple input sources and they must be distinguished, keeping a more complex watchdog routine in the main code would be required that ACKs the timer only when it notices that NMIs are not occurring.
Restore _______________ ______________________________ key \_________________________/ Failsafe ACKs A A A A CIA timer events | | | | | ______ ____________ _______ ____ ____________ ___ CIA /IRQ \_/ \______/ \_________/ \_/ \_/ ______ ______ ____ ____________ ___ /NMI NMI\_/ NMI\______________________________/ NMI\_/ NMI\_/