Plus Too Keyboard and Mouse
Digging further into the Plus Too design details, the next systems to consider are the keyboard and mouse. I plan to use a PS2-type keyboard and mouse, since they both communicate with a fairly simple serial protocol that’s easy to work with. The downside of PS2 input devices is that they’re growing less common, having been mostly replaced with USB devices now. They also require a 5V power supply, whereas everything else in the Plus Too will run at 3.3V. Perhaps a future version of the Plus Too might add USB input support with a microcontroller serving as a USB host, but for now PS2 is it.
PS2 Mouse
A standard PS2 mouse uses a bidirectional serial interface to communicate with the computer. The details of arbitrating control of the clock and data lines to determine the direction of a transfer make the interface more complex than a one-way serial connection, but there are many good examples found online that explain the process well. When power is first applied, the mouse enters a passive state. The first thing the computer must do is send the mouse a command instructing it to enter “stream mode”, which is accomplished by sending the command byte $F4. The mouse acknowledges the command by sending the byte $FE.
Once the mouse enters stream mode, it will send a 3-byte update packet to the computer whenever the mouse position or button state change. This packet contains the current state of the left, middle, and right mouse buttons, as well as two 9-bit signed values indicating how far the mouse has moved in X and Y since the last packet. The mouse only reports these movement deltas, not its current position in absolute terms. A delta of 1 unit in X or Y represents a physical movement of about 1/4 of a millimeter.
Chapter 10 of the book FPGA Prototyping by Verilog Examples is entirely devoted to the development of a PS2 mouse interface, freeing me from the need to write one myself.
Mac Plus Mouse
The Mac Plus mouse operates differently from a PS2 mouse. The Plus mouse is a dumb device with five wires connected to it: one to the mouse button, and four others connected to rotary quadrature encoders for the mouse ball (two for the X axis and two for the Y axis). The quadrature encoder lines send square wave trains to the Mac that change with the velocity and direction of the mouse. These quadrature signals are interpreted by the OS software to determine mouse movement deltas, and ultimately mouse position.
This presents a problem, because the PS2 mouse operates one level of abstraction above the Plus mouse. Quadrature encoded data is not available from the PS2 mouse, and so can’t be provided to the Mac OS running on the Plus Too hardware.
Mouse Hardware Simulation
One solution would be to generate fake quadrature data in the FPGA, based on the movement deltas reported by the PS2 mouse. If the Ps2 mouse reported a movement of +3 on the X axis, the FPGA would need to synthesize 3 cycles of quadrature square waves, with the appropriate phase relationships between the 4 quadrature signals to indicate positive X axis movement. This would also require simulating the portions of the Mac’s VIA and SCC serial controller to which the mouse signals are connected. One quadrature signal on each axis triggers an SCC interrupt, which is 68000 interrupt #2. Any state change for these signals will trigger an interrupt. The remaining quadrature signals and the mouse button are sampled passively through the VIA on port B. State changes for these signals will not trigger an interrupt, but they are tested inside the mouse interrupt handler (quadrature signals) and VBLANK interrupt handler (mouse button).
Mouse Cheating
While direct simulation of the mouse hardware should work, it could be tedious to implement, especially considering the simulation of VIA and SCC behavior needed. An alternative solution is to make use of knowledge about the Mac OS, and directly poke mouse bytes into the location in memory where the mouse driver would normally store them. In the case of the classic Mac OS, the low memory global MTemp at location $000828 stores the position from the most recent mouse interrupt. The FPGA address decoder could be modified to create a “hole” in RAM at this address, so that it was actually implemented as a register in the FPGA. When the OS software went to fetch the mouse position from memory, it would actually get it from the PS2 interface circuit in the FPGA. The mouse interrupt would never be invoked, yet the position of the mouse would still magically continue to be tracked by the OS. This would free me from having to worry about quadrature signals, or simulating any mouse-related VIA or SCC behavior.
This solution seems a bit questionable, but it’s the method used by at least one popular Mac emulator, and is reportedly compatible with virtually all Mac software. I will probably use this solution, at least at first. The drawback is that it’s not a true replica of the actual Mac hardware, but a software-level cheat. If someone discovered a new version of Mac OS that worked differently or stored the mouse position at a different memory location, then this solution wouldn’t work. It’s possible that a real-world alternative OS (Unix for Mac 68K?) might not work with this solution either. But since the locations of the relevant low memory globals are hard-coded in ROM, any hypothetical incompatible OS or program would have to go to the length of patching the ROM mouse driver and replacing it with a custom, incompatible one. That seems very unlikely, so I think it’s safe to rely on this solution.
PS2 Keyboard
A PS2 keyboard uses a similar serial connection to a mouse. Technically it’s a bidirectional connection, but in practice there’s no need to send anything to the keyboard, so it can be implemented as a one-way serial connection. When a key is pressed, the keyboard immediately sends a “make” scan code. When a key is released, the keyboard sends another “break” scan code. What makes things challenging is that scan codes are variable length, have no obvious correlation to keys that were pressed, and have no consistent correlation between make and break codes for the same key. Keeping track of it all requires a state machine and a scan code translation table. FPGA Prototyping by Verilog Examples chapter 9 describes the design of a PS2 keyboard interface.
Mac Plus Keyboard
The Mac Plus keyboard operates somewhat differently. It uses a bidirectional connection, and the keyboard only transmits keypress information when explicitly instructed to by the Mac. The Mac OS sends an “Inquiry” command to the keyboard every 1/4 second. If the keyboard has any keypress data in its internal buffer, it immediately returns it. If the buffer is empty, and no keys are pressed within the next 1/2 second, the keyboard responds with a NULL keypress.
The keyboard protocol also defines an “Instant” command that omits the 1/2 second timeout, as well as a “Model Number” query and a command to trigger a self-test. All of these will need to be simulated, since the Mac OS ROM routines use them all.
Plus keyboard scan codes are somewhat more sensible than for PS2 keyboards. All scan codes are a single byte. Bit 7 distinguishes between key-down and key-up events, and bits 6-1 indicate the specific key. Bit 0 is not used and is always set to 1.
The physical connection to the Mac keyboard uses a bidirectional serial connection very similar to the PS2 keyboard.
Plus Too Keyboard
The Plus Too keyboard module will need state machines to handle both the PS2 and the Mac interfaces, as well as tables for both sets of scan codes to facilitate translation between them. It will also need an internal buffer to hold scan codes received from the PS2 side until the next 1/4 second interval when an “Inquiry” command is received.
Some PS2 keyboard keys have no Mac equivalent (function keys, Home, etc). These will need to be silently thrown away by the keyboard module.
The Mac OS implements key repeating in software. If enough time elapses after a KeyDown without a corresponding KeyUp, the OS begins to generate additional virtual keypresses of the same key. In contrast, key repeating is performed in hardware by a PS2 keyboard, and the repeats are sent as additional “make” scan codes. The Plus Too keyboard module will need to suppress these, by keeping track of which keys are currently pressed down, and ignoring any further make codes for those keys.
Although the real Mac hardware uses a serial connection to communicate with the keyboard, at the OS level all keyboard communication is performed byte-by-byte, using a register in the VIA. When a full byte has been received from the keyboard, the VIA signals the “data ready” interrupt, and an OS routine fetches the byte from a memory-mapped location. This is convenient, because it means the Plus Too keyboard module can work at the byte level, by responding to read/write requests at the appropriate memory-mapped locations, and won’t need to simulate the details of the serial connection.
Read 2 comments and join the conversation2 Comments so far
Leave a reply. For customer support issues, please use the Customer Support link instead of writing comments.
The PS/2 scan codes started out as very sensible back in the original PC days, much more sensible, actually, than the Mac Plus codes.
The complications come from the need to improve things while keeping backwards compatibility.
Since you don’t actually need all the fancy keys that came with the AT keyboard, you can ignore all the complicated stuff in the PS/2 keyboard interface (which is really just the AT keyboard with a better plug).
Basically, you can ignore everything that starts with E0 and E1.
The PS/2 hardware autorepeat is programmable by sending the right command to the keyboard. As far as I recall, you can even switch it off completely — I don’t know if that is easier than suppressing the extra ‘make’ scan codes from the autorepeat.
In other words, I don’t think you actually need to track the keydown state (or much of any state at all) in the converter.
Btw, it might be a good idea to send a reset command to the PS/2 keyboard on startup (or if you somehow detect that it has just been plugged in).
Anything that wouldn’t work with your PS/2 adaptations also wouldn’t work on ADB Macs like the SE. The only software I know like this is Apple Smalltalk-80 0.7.