As you may know, the classic NES controller was not the only NES controller that Nintedo released with the NES. These included the NES advantage, the NES Max, and the Dogbone. All of these new controllers featured turbo buttons (buttons for frame perfect spam). The thing that confuses me about this is that the controllers had no way of knowing when the NES changed frame, so how how did it know when to switch from on to off or vise versa? The reason I don't think the NES communicated this information to the controller is because controllers with turbo buttons came out after the NES, so Nintendo hadn't even thought of the concept yet, and wouldn't have been able to design the NES to work with it.
According to Standard controller#Turbo - Nesdev wiki,
A turbo controller such as the NES Max or NES Advantage is read just like a standard controller, but the user can switch some of its buttons to be toggled by an oscillator. Such an oscillator turns the button on and off at 15 to 30 Hz, producing rapid fire in games.
Here are the pictures of the controller from an overview of Dendy Junior, a Chinese Famiclone, the most popular model sold in Russia in the 90s, which was stocked with turbo controllers out of the box:
And these are schematics of encoder circuits compatible with these controllers (images are links to the origin articles). The 2nd one is a scan from the Radio journal, the top Soviet journal for radio and electronics enthusiasts that was famous for publishing hard-to-find information, including schematics for various devices.
This is the schematic for К561ИЕ10 which is DD1 in the 2nd scheme:
The 1st one, according to @duskwuff, is a free-running RC oscillator with the frequency of about 8 Hz.
The 2nd one uses a 4-digit counter on D triggers, thus switching the button each 8 controller's clock cycles. Since the triggers are edge-triggered by the same clock signals and it takes exactly 8 clock cycles to read the controller's state, this effectively switches the button between every two controller state packets.
In the case of the NES Advantage at least, the Turbo rate was adjustable, by turning the dial at the top of each button.
You are right in assuming that the NES does not communicate the start of a frame to the controller. But also, these buttons do not need to know when the frames are. All they need to do is open and close the circuit; the software will usually treat each opening and closing as an individual button press. It does not matter if this device oscillates every n frames exactly, it just needs to open and close the circuit.
A similar device exists on some modern gaming controllers as well. They include a very simple circuit which just "make it look like" the user is mashing the button.
To read a controller, the NES says to the controller "Save the current state of the buttons" then says "Send me the saved value for the next button" eight times. Each time, the controller sends the saved value for one of the buttons to the NES. The controller sends the button values in the following order: A, B, SELECT, START, up, down, left, right.
Because of the "request and report" nature of the signals, it's possible for a turbo controller to keep track of how many requests have been sent and report buttons as being on or off for an exact number of requests.
Note about frames: Games will usually get a full report from the controller once a frame, but be aware that there is no requirement to get exactly one report per frame. Some games don't bother requesting reports from the controller during parts of the game you can't control. Some games need to request multiple reports in a frame.
Nesdev Wiki has several documents:
https://wiki.nesdev.com/w/index.php/Controller_port_pinout https://wiki.nesdev.com/w/index.php/Controller_port_registers https://wiki.nesdev.com/w/index.php/Standard_controller https://wiki.nesdev.com/w/index.php/Input_devices
Putting the information in these documents together, I gather the process works like this:
- The game writes a 1 to memory address hex 4016.
- The NES sends a 1 on the OUT pins of both controller ports.
While the OUT pin is 1, the controller(s) will continually save the current state of the buttons.
The game writes a 0 to memory address hex 4016.
- The NES sends a 0 on the OUT pins of both controller ports.
- The controller(s) will stop continually saving the current state of the buttons, but keep the last saved values.
Repeat 8 times:
- The game reads memory address hex 4016 (for controller 1) or hex 4017 (for controller 2).
- The NES sends a 1 then a 0 on the CLK pin of the controller port.
- The controller changes the D0 pin to the saved value of the next button in the sequence.
- The NES reads the value from the D0 pin and presents it as the lowest bit value of the memory address being read by the game.
(The other data lines, D3 and D4, are used by other kinds of controllers like the Zapper and Power Pad. These values show up in other bits of the memory address being read by the game.)
I don't know about these controllers, but according to this, you could know when to toggle buttons by watching the shift register clock pin. Example:
- set button to on
- wait 8 clock pulses
- set button to off
- wait 8 clock pulses
- go to step 1