Reading switches is the easiest part of this process. The switches are organized into banks of 8, and each bank is energized by a different switch strobe. The lines U10A:PA0-PA4 are the strobes and the return values are read on U10B:PB0-PB7. A closed switch appears as a 1 and an open switch is 0. The DIP switch banks are read in the same way, but those are strobed by U10A:PA5-PA7 and U10B:CB2.
The switches are debounced in software to eliminate errant signals, and there’s enough documentation in the Bally Theory of Pinball to figure out precisely how that can be done. Over the course of three passes through the 120Hz interrupt, if a switch is read as Open, Closed, Closed, it is considered to be a valid switch hit. Any other combination is invalid. This helps the machine filter noise and only register one close event for each ball hit.
There’s also hardware helping to settle the signals on the switch returns. Each return line has a capacitor to ground that filters out the higher frequency signals. Because of these capacitors, the switch strobes have to be held high for a period of time before the capacitors will charge enough for the value to appear on U10B:PB0-PB7. Experimentally, I found that the switches can be reliably read after 80µs. Because we need to waste time before the lamps can be latched, it seems natural to put this switch-reading code before the lamp strobes in the 120Hz interrupt, although that’s not how the M6800 implementation works.
To accomplish the software debouncing, three states of the switches need to be compared: now, last time through, and two times ago. In the Arduino implementation, I refer to these as “SwitchesNow”, “SwitchesMinus1”, and “SwitchesMinus2”. To find valid closures, we only need to look for (SwitchesNow & SwitchesMinus1) & ~SwitchesMinus2. If that byte has a value, then one of the switches in the bank has a valid closure. To pass that event to the game loop, the Arduino implementation uses a switch stack.
One exception to the software debouncing is made for the solenoids that need really fast reactions (pop bumpers and slingshots). For switches associated with those solenoids, as soon as a switch moves from Open to Closed, the solenoid is triggered. If the signal turns out to be noise (the next read shows it Open again), then the solenoid is turned back off immediately. To accomplish this, the Arduino implementation flags “Starting Closures” and “Valid Closures” and puts solenoid hits on the stack right in the ISR.
My apologies that I didn’t trigger off the same 120Hz line that I showed on the previous captures. There’s no good way to clip onto that line and I got tired of holding the probe to U10:Pin18.
It’s easier to see the switch read in the Arduino implementation because U10B:PB0 is cleaner and the switch read happens very early in the 120Hz ISR.