Modern mice for old computers (part one)

(Read Part Zero if you haven’t already! This isn’t a high-gloss American TV series, so we can’t afford to do one of those “previously, on Oddlboke” clip section.)

The Prototype Circuit

A circuit that accepts data in one format and spits it out in another is exactly the kind of thing suited to a microcontroller. I like the Arduino (and have lots lying around the office) so that’s what I’m going to use here.

Another quality diagram from an engineer with no artistic ability.

Not much to see, really! I’m using:

  • an Arduino Uno (though most any type would do!)
  • a PS/2 socket (to which I’ve soldered some jumper wires to I can plug it into breadboards or the Arduino)
  • a cable from an Archimedes mouse
A pain in the butt to solder, unless you're a sinky Young Person who can still see. :(

10-way mini DIN plug, as used for the Archimedes mouse. A pain in the butt to solder, unless you’re a young whippersnapper who still has decent eyesight and a steady hand.

If you don’t have such a cable then you need to get hold of a 10-way mini DIN plug (I tend to get them from eBay). You’ll also need a length of multiway cable: 9-way, or 8-way screened (you use the screen as the 0v line).

If you’re reading this article because the mouse you’re replacing is for a computer other than an Archimedes, then you’ll be substituting a different connector anyway.

The Software

Download this zip file (5K), unzip it and open the ino file in the Arduino editor. You should find there’s three tabs in the editor – PS2_to_Quadrature_Mouse, MyPS2.cpp and MyPS2.h.

It might help to have it open while you read the notes below.

Reading the PS/2 mouse

The MyPS2 class is based on the Arduino’s existing library for reading PS/2 mice. I’ve modified it quite a lot, because as things stood it wasn’t very resilient when dealing with the mouse being disconnected. So I’ve added a lot of timeout code: if this happens, the code pauses for a second before re-initialising the mouse.

I haven’t read into the library in as much detail as I would like. Of the collection of eight mice I pulled from my PC-spares drawer, only one of them wouldn’t work with this library. Given time, I’d like to roll my own library so I’m very sure of the protocol, and hopefully make it a bit more solid.

Creating the quadrature signal

When you move a mouse (or trackball) on an axis, it turns a spinner, which alternately breaks the infra-led light being shone at a sensor. This pulsing tells the host computer that the spinner is moving.

But that only describes how fast it is spinning – not which direction. To address this, there’s a second sensor on the same spinner, but slightly offset. This produces two “out of phase” pulses.

By monitoring both pulses and checking which one is ahead of the other, the host computer can tell both how fast it is spinning, and in which direction.

quadrature_phases

The two channels may be in four different combinations – hence “quadrature”.

To implement this behaviour in the Arduino, we assign channels 1 and 2 (in the above diagram) to a digital output each. We consider each combination of high and low as a “phase” (the numbers 1 to 4). To move a step in a certain direction, we just go to the next phase, wrapping around. And to move a step backwards, we instead move back to the previous phase.

The code loop

The code loops by repeatedly reading movement from the PS/2 mouse. First it updates the mouse digital pins to reflect what the PS/2 mouse reported. Then, if the mouse has moved since the last check, those movements are recreated on the quadrature pins by cycling through the phases.

Mouse buttons

The mouse buttons in an Arc mouse are wired active-low. That is: when not pressed, the connections are pulled high by a pullup resistor. When the button is pressed, the connection is pulled to 0v.

To fake it with an Arduino, we just wire the pins designated for buttons directly to digital outputs on the Arduino, remembering to invert the logic.

Pin Assignments on the Arduino

The Arduino Uno has a clock-speed of 16MHz; meanwhile, the PS/2 data only runs at a maximum of 30kHz, and the quadrature output is much slower than that. So we can use pretty-much any digital IO pins for the project. The ones I’ve used are set as constants at the top of the code, so they’re easy to change if needed (for example: to simplify track layout when designing your own PCB).

Also, if you find that an axis is reversed (down is up or right is left) then all you need to do is swap the two wires over for that axis. And if you’ve already built your circuit, then the easiest way to do it is by swapping those constants instead.

First Test

Here is a picture of my first test in action: (click to see a larger version)

(Click to see larger version.)

The green plug at the top-left is the PS/2 mouse – actually, it’s one of those USB-to-PS/2 adaptors that most mice come with. Note that these adaptors contain no components – they’re just wiring. The mouse decides whether it should be speaking USB or PS/2 when it first powers-up.

Wiring for an Archimedes mouse

The grey cable on the right is harvested from an Archimedes mouse. The IDC plug you can see is how it connects to the little PCB inside the mouse. For this test I just removed it from the board, and short jumper wires to connect it to the Uno. The RiscPC I’m testing it with is out of shot.

Here are the pinouts for that plug:

Note that I’m not using the +5v pin for this test, as the Uno is being powered by my PC’s USB port. But when building a proper version of this circuit, you’ll want this pin to power it.

Coming Next …

This article has gone on for far longer than I had intended! Sorry, I do tend to waffle. But if you’re looking to get a mouse working on your RiscPC and you have the parts to hand, then these should be enough notes to get you started.

In the next part I’ll document the PCB I’ve made (my “proper” solution) and talk about wiring for other computer types.

Links