Our Hardware is broken up into a few sub-categories: Nintendo 8 interface, Nintendo 64 interface, Display interface, and timers.
The Nintendo 8 and Nintendo 64 interfaces were mainly constructed using a series of clocks generated using the system clock, which runs at 20MHz. In order to implement these successfully, it was necessary to create a 1MHz clock (1 microsecond period), ~17 kHz clock (6 microsecond period), 10MHz clock, and ~60Hz clock. The interface is designed to begin the sampling sequence on every rising edge of the 60Hz clock. An interrupt is generated on the falling edge, which tells the processor that the data is ready. The amount of time between the rising and falling edge is more than ample to perform the sampling sequences on the controllers. The Nintendo 8 provides 8 bits of data during each sampling sequence (A, B, select, start, up, down, left, right) and the Nintendo 64 controller provides 32 bits of data (each of the 10 buttons + 4 directions + 2 unused bits followed by 16 bits for the "analog" stick. For more information on the sampling sequences, see the Nintendo 64 and Nintendo 8 device links above.
Auto-detection of the controllers was enabled through the use of our controller ports. The input/output wires of the controllers were put into a more standardized interface to allow each player to plug their respective controller, whether N8 or N64, into one port. The N64 has one bi-directional data line that we split into 2 lines, one for input and one for output. This allowed us to have a shared input data line on the interface, which then enabled us to auto-detect the type of controller used, since the data coming across this line to the processor would be different depending on which signals we sent through the port.
The display interface is responsible for generating carefully-timed signals that allow 3 forms of communication with the display: reads, writes, and resets (a variation on a write). Within the read and write schemes, there are also data and command transfers. Reads and writes are distinguished based on the read/write signal generated by the processor. Resets, commands, and data transfers are distinguished using the address lines. For example, a write to the address 0x3F00100 would call for a reset, while a write to 0x3F00000 would indicate a data write and a write to 0x3F00200 would define a command write. A 10MHz clock was also generated within the hardware scheme to aid in timing.
The timers we used after each player dropped a piece were processor timers and dealt with in software.