Colin Fahey
1. Introduction
This article describes how a PS/2 mouse can be emulated by a BASIC Stamp computer.
This exploration is informal.

The interior of an old-style (moving ball) computer mouse: the
"Microsoft Intellimouse" (I replaced the optical sensors with long
wires.)
A mouse has two axes: "X" and "Y". When the mouse is moved
"horizontally", the "X" wheel inside the mouse rotates. When the mouse
is moved "vertically" (upon a surface), the "Y" wheel inside the mouse
rotates. For arbitrary mouse motion, the "X" and "Y" wheels move
according to the "horizontal" and "vertical" components of the mouse
motion.

Optical interruptor wheels inside the mouse
Notice the holes in the wheels inside the mouse. When the wheel
rotates, the infra-red (IR) light emitted by an IR Light Emitting Diode
(LED) is interrupted repeatedly, at a rate proportional to the rate of
wheel rotation. Thus, the mouse knows how many "increments" (also
called "ticks") the mouse axis has moved in a particular time period.
Determining the direction of movement involves the use of 2
light sensors, located very close together, along an axis parallel to
the movement of the wheel. (Both sensors are in a single 3-pin
component shown below.)

Mouse IR light sensor (has two IR detectors in a single package)
The center pin of the package is the positive collector voltage;
The left and right pins are the left and right sensor output emitters.
Let us name the two sensors in the package "A" and "B". Suppose the
wheel is initially at a rotation angle such that the IR light is
blocked from reaching both sensors.
As the wheel rotates, the IR light from the emitter will eventually be
able to pass through a hole in the wheel and reach one of the two
sensors, such as sensor "A". If the wheel continues rotating in the
same direction, eventually the second sensor, "B", will be able to
received IR light. If the wheel continues rotating in the same
direction, eventually the IR light will be blocked from reaching sensor
"A". If the wheel continues rotating in the same direction, eventually
the IR light will be blocked from reaching sensor "B".
Thus, the sequence is:
(A,B): ..., (0,0), (1,0), (1,1), (0,1), ...
If the wheel rotates in the opposite direction, the 4-term sequence
shown above will be reversed, starting from the current status.
With these two sensor signals we can determine rate of rotation, and the direction.

The circuit board of the Microsoft Intellimouse
To understand more about how the mouse circuitry interprets the light
sensors and communicates with the personal computer (PC) (via PS/2
signals), I studied the circuit board.
The microchip has the following name printed upon it: SPCP05A.
A search of the Internet for the word "SPCP05A" indicates that the chip
is manufactured by a company named "Sunplus Technology Co.".
Information about the "SPCP05A" microchip can be acquired from that
company.
Here are the technical specifications of the "SPCP05A" microchip:
The following image shows the signals of the pins of the "SPCP05A (PS/2 3D mouse)" microchip.

Signals of the pins of the "SPCP05A (PS/2 3D mouse)" microchip
The "SPCP05A" is actually a tiny computer! It has an instruction set,
and RAM, and ROM, and internal timers, etc. In fact, the description
of the "SPCP05A" microchip in the information provided by Sunplus Co.
scarcely refers to the specific use of the microchip for "computer
mouse" circuits. This chip is a versatile microcontroller.
I studied the circuit traces on the circuit board of the Microsoft Intellimouse to form the following approximate schematic:

Approximate schematic of the Microsoft Intellimouse (I am missing a few capacitors, but this schematic is almost perfect.)
Bui Van Chu, in Australia, read my article and sent me a more complete schematic, which appears in the following image.

The PS/2 mouse schematic, sent to me by Bui Van Chu from Australia
The circuit is very simple.
The mouse buttons (left, middle, right) go directly to inputs on the microchip.
The three pairs of light sensors, ({ "X", "Y", "Z" }, for { horizontal
movement, vertical movement, and middle mouse wheel }) send signals
directly to other inputs on the chip.
The PS/2 signals DATA and CLK (clock) also correspond to I/O signals on the chip.
I understood the schematic as soon as I finished drawing it (by following traces on the circuit board).
One thing I didn't initially understand was the way the IR LEDs were
connected to the microchip (pin 16 : "PB1"), instead of their negative
terminals (cathode) simply being connected directly to ground. This is important!
2. My first attempt to control mouse movement
The following comments refer to motion along a single axis (such as the "X", or horizontal, axis).
The first thing I tried was moving an object between the IR LED and the
sensor pair -- to simulate the effect of the rotating wheel within the
mouse. This worked. I could cause the mouse cursor to move around the
screen by simply moving an obstacle through the IR light beam
repeatedly, in the same direction.
Next, I removed the 3-pin sensor part from the mouse circuit board, and
attached wires to circuit board in place of the sensor. I manually
connected a wire to the positive voltage to simulate sensor activity.
I connected the two signals to the power according to the following
pattern (such that "0" represents "off", and "1" represents "on"):
(0,0), (1,0), (1,1), (0,1), ...
This worked. I could move the mouse cursor on the screen by this
tedious connecting and disconnecting of wires in the pattern shown
above. Reversing the pattern from the current status in the sequence
would move the cursor in the opposite direction.
Because things were going so well, I decided to connect the wires to
relays (controlled by RS-232). This would essentially allow me to do
exactly what I did with loose wires: connect the sensor signals to the
power terminal in the appropriate sequence. The only difference would
be the fact that the human (me) wouldn't have to do the tedious
connecting and disconnecting.
But...it didn't work!
After a lot of adjusting of resistors and capacitors, etc, I made a strange discovery: If I was touching certain terminals in the circuit, it worked perfectly! The solution to this mystery appears in the next section.
3. The infra-red (IR) light must be modulated
After some frustrating experiments I had a new thought: The IR light
might be pulsing at a high frequency, and the chip might expect to
receive this frequency. Constant light (or my simulated constant
sensor output) might be rejected. I was somewhat perplexed by the fact
that the ambient light of a halogen floor lamp was acceptable, but I
knew that even incandescent lamps have detectable modulation.
I tried pulsing an IR LED at high frequency and blocking the sensors according to the expected pattern. It worked!
That was it! The IR LEDs in the mouse circuit board must be flashing
at high speed, and the microchip must expect this flashing in addition
to the relatively low rate of light interruption by the rotating wheel
(with holes).
By pulsing the IR LEDs, and expecting this pulsing in an unblocked
sensor output signal, the chip can reject any ambient IR signals from
interfering with mouse operation. For example, stray light from other
(constant) IR sources won't interefere with the mouse.
I connected an audio amplifier to the sensor output, and then I let the
sensor take in the ambient light cast by my halogen floor lamp. I
heard a distinct tone (60 Hz). When I dimmed the lamp, the tone grew
faint, and finally stopped when the light was off. So, this sensor
easily picks up the 60 Hz modulation in the incandescent bulb of my
halogen floor lamp!
Looking, now, at the schematic of the PS/2 mouse circuit board, the
significance of the IR LEDs being connected to a pin on the microchip
(instead of to the direct current) is obvious. The microchip controls
the flashing of the IR LEDs through the I/O pin, and the microchip can
correlate its intention to flash the ID LEDs with the received sensor
inputs, and thus reject any stray signals (due to non-flashing IR
light). (However,correlation isn't necessary. Simply detecting a
minimum number of flashing counts could be a threshold for accepting
sensor input.)
4. IR sensors with bandpass filters
You can find special IR sensors, packaged in transistor-like form with
three leads, that are "tuned" to specific modulated IR light
frequencies (e.g., 38 kHz).

Tuned IR light sensor (maximum sensitivity to 38 kHz light modulation)
Bandpass circuitry is contained within the device, along with the IR photo-transistors.
So, the IR LED can generally be pulsed at a frequency of 38 kHz so that
the sensor will receive the light and let the electrical signal go to
the sensor outputs.
To convey information, the light from the IR LED can be interrupted at
a relatively low rate (e.g., 1 to 100 times per second). This
low-frequency pulsing is in conjunction with the steady high-frequency
pulsing; i.e., the low-frequency pulsing can be regarded as modulating
the high-frequency pulsing. The high-frequency pulsing is like a
"carrier wave" upon which the information signal (the relatively
low-frequency modulation) is carried.
However, I verified that the IR sensors in the Microsoft Intellimouse do not
have such modulation filtering. However, the circuit does require that
the IR light be modulated in some manner, in addition to the
low-frequency interruptions of light by the wheel with holes.
The following sketch illustrates the difference in sensor signals for
constant IR LED light and flashing IR LED light for the different
phases of mouse wheel turning.

Sensor output signals for the constant IR light case and the flashing IR light case.
5. Simulating mouse input using a BASIC Stamp computer
The "BASIC Stamp 2" computer has sufficient programmability to
implement the PS/2 protocol. Therefore, the "BASIC Stamp 2" computer
can be connected directly to the PS/2 port of a personal computer (PC)
and can emulate a PS/2 mouse or keyboard.
5.1 The PS/2 protocol
In the years 1998 through 2003, the majority of personal computers had PS/2 ports for the mouse and keyboard.
The PS/2 port has 4 signals: (1) CLOCK; (2) DATA; (3) +5V; (4) GROUND.
The PS/2 port allows devices to send data to the host, and the host may
send data to the devices. All parties on a PS/2 port (typically just a
device and the host) must share the signals and must detect if another
party is currently using the signals.
How can signals be shared? A signal (such as CLOCK or DATA) is usually
"floating" high, meaning that the signal is connected to a positive
voltage through a resistor with high resistance (e.g., 4 kilo-Ohms).
Thus the signal is interpreted as a logical "high" by all listening
parties. Any party can pull the line low (via TTL logic) when the
party intends to send data. When a party finishes sending a packet, it
lets go of the signals indefinitely, so they float high again.
To send data from a device (e.g., mouse or keyboard) to the personal
computer (PC), you must send data in 11-bit packets, consisting of the
following bits: (1) start bit ("0"); (2) 8 data bits (LSB first); (3)
parity bit ("odd" parity); (4) stop bit ("1"). Note that "odd parity"
is when the total number of "1" bits in the data bits and parity bit
combined is an odd number.
The following diagram illustrates the transmission of a single data packet:

PS/2 protocol : device to host (PC) packet
The DATA line should be set to the proper value before bringing the
CLOCK line low. The DATA value should remain set until the CLOCK line
is returned back to high. When the CLOCK line is confirmed to be high,
the DATA value can be changed to the next bit value.
The typical clock speed is relatively slow, about 10 kHz to 17 kHz.
That is 100 microseconds down to 70 microseconds for each clock
period.
The scenario of the host (PC) sending data to a device is similar to the device sending data to the host, but in all cases the device
controls the CLOCK signal during data transmission itself. Also, a
data bit sent from the host (upon device setting CLOCK low) should be
latched when the device lets the CLOCK signal make a transition to
high.
An Internet search will reveal many descriptions of PS/2 signals and details about the protocol.
5.2 PS/2 mouse data packets
When the computer boots up, the operating system starts and eventually
communicates with the mouse to determine the type of mouse. By default
the mouse may behave like a generic PS/2 mouse. However, if the
operating system determines that the mouse is actually a "3D PS/2"
mouse (e.g., a mouse with a wheel), it can tell the mouse to change to
the 3D PS/2 mouse protocol.
When you move the mouse, or press or release mouse buttons, the mouse
circuitry sends data to the host (PC), indicating what state changes
have occured since the previous state indication.
The generic PS/2 mouse sends the following three packets to the host:
------------------------
D7 D6 D5 D4 D3 D2 D1 D0 (The D0 bit (LSB) is sent first)
------------------------
(1) YV XV YS XS 1 0 R L (overflow, sign, buttons)
(2) X7 X6 X5 X4 X3 X2 X1 X0 (X movement; -128 to +127)
(3) Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 (Y movement; -128 to +127)
L = Left Button State (1 = pressed down)
R = Right Button State (1 = pressed down)
XS = Direction of X movement (1 = LEFT)
YS = Direction of Y movement (1 = UP)
XV = Overflow of X movement value (1 = X overflow occured)
YV = Overflow of Y movement value (1 = Y overflow occured)
X7,...,X0 : X movement; 8-bit 2's-complement signed byte (-128 to +127)
Y7,...,Y0 : Y movement; 8-bit 2's-complement signed byte (-128 to +127)
Here are examples of data sent to the host (PC):
------------------------------------------------
(The least-significant bit of each data byte is sent first.)
Move Left 1 unit : 0x18, 0xFF, 0x00
Move Right 1 unit : 0x08, 0x01, 0x00
Move Down 1 unit : 0x28, 0x00, 0xFF
Move Up 1 unit : 0x08, 0x00, 0x01
Press Left Button : 0x09, 0x00, 0x00
Release Left Button : 0x08, 0x00, 0x00
Press Right Button : 0x0C, 0x00, 0x00
Release Right Button : 0x08, 0x00, 0x00
It is very common to have a "3D PS/2" mouse (e.g., with a mouse wheel
that also acts as a middle button). Such a mouse sends four data
packets to the host (PC).
------------------------
D7 D6 D5 D4 D3 D2 D1 D0 (The D0 bit (LSB) is sent first)
------------------------
(1) YV XV YS XS 1 M R L (overflow, sign, buttons)
(2) X7 X6 X5 X4 X3 X2 X1 X0 (X movement; -128 to +127)
(3) Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 (Y movement; -128 to +127)
(4) Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 (Z movement; -128 to +127)
This is very similar to the generic PS/2 mouse,
with a few additions:
M = Middle Button State (1 = pressed down)
Z7,...,Z0 : Mouse wheel movement; 8-bit 2's-complement signed byte
(The Z value is forced to a range of -8 to +7)
5.3 My first circuit to simulate a PS/2 mouse
The following schematic was my first working technique to get my "BASIC
Stamp 2" computer to send PS/2 mouse data to the host (PC).

Schematic of circuit to allow the BASIC Stamp computer to send PS/2 packets to the host (PC).
Note that this circuit electrically isolates my BASIC Stamp computer
from the host (PC) computer. Also note that this circuit is just to
satisfy the electrical requirements of PS/2 data transmission (from device to host). Thus, I can send PS/2 keyboard messages using this same circuit if I plug in to the PS/2 keyboard port on the host (PC)!
Since receiving signals is generally non-invasive (i.e.,
listening doesn't interfere with electrical signals), the only thing
required to allow the "BASIC Stamp" computer to receive the PS/2 CLOCK
and DATA signals is a direct connection from those signals to other
BASIC Stamp I/O pins (configured to be inputs). I'd try some kind of
buffering -- but I definitely can't use an opto-isolator directly,
since that would put a load on the "floating" signals (thus "sinking"
them!). I could use the +5V to power a buffer, then then use the
buffer output to drive opto-isolators that ultimately send signals to
the BASIC Stamp I/O pins (configured as inputs).
The following image shows my BASIC Stamp 2 computer connected to a circuit matching the schematic above.

BASIC Stamp 2 computer connected to a PS/2 mouse port via an opto-isolator circuit.
The following BASIC Stamp 2 program, written in the PBASIC programming
language, was my first successful attempt to control the PS/2 mouse via
the BASIC Stamp 2 computer.
The program simply makes the mouse cursor move along a small diagonal line.
'====================================================================
'{$STAMP BS2} 'STAMP directive (specifies a BS2)
DIR0 = %1 'Set pin 0 to OUTPUT
DIR1 = %1 'Set pin 1 to OUTPUT
OUT0 = %0 'Set DATA line high (pin low)
OUT1 = %0 'Set CLOCK line high (pin low)
tempData VAR BYTE
tempParity VAR BYTE
'--------------------------------------------------------------------
MainLoop:
tempCounter VAR WORD
FOR tempCounter = 0 TO 10
tempData = $28
GOSUB TransmitPacket
tempData = $01
GOSUB TransmitPacket
tempData = $ff
GOSUB TransmitPacket
tempData = $00
GOSUB TransmitPacket
PAUSE 100
NEXT
FOR tempCounter = 0 TO 10
tempData = $18
GOSUB TransmitPacket
tempData = $ff
GOSUB TransmitPacket
tempData = $01
GOSUB TransmitPacket
tempData = $00
GOSUB TransmitPacket
PAUSE 100
NEXT
GOTO MainLoop
STOP
'--------------------------------------------------------------------
TransmitPacket:
GOSUB ComputeParity 'First, compute parity
tempData = ~tempData 'Invert data bits
tempParity = ~tempParity 'Invert parity bit
'==== Start Bit ====
OUT0 = %1 'Set data line low (output high)
PULSOUT 1, 25 ' Pulse line 1 for (25*2) = 50 usec
'==== Data Bits ====
OUT0 = tempData.BIT0
PULSOUT 1, 25
OUT0 = tempData.BIT1
PULSOUT 1, 25
OUT0 = tempData.BIT2
PULSOUT 1, 25
OUT0 = tempData.BIT3
PULSOUT 1, 25
OUT0 = tempData.BIT4
PULSOUT 1, 25
OUT0 = tempData.BIT5
PULSOUT 1, 25
OUT0 = tempData.BIT6
PULSOUT 1, 25
OUT0 = tempData.BIT7
PULSOUT 1, 25
'==== Parity Bit ====
OUT0 = tempParity.BIT0
PULSOUT 1, 25
'==== Stop Bit (high) ====
OUT0 = %0 ' pin low is DATA high
PULSOUT 1, 25
PAUSE 1 ' Necessary? Provides 1 msec gap between packets...
RETURN
'--------------------------------------------------------------------
ComputeParity:
tempParity = $01
tempParity = tempParity + tempData.BIT0
tempParity = tempParity + tempData.BIT1
tempParity = tempParity + tempData.BIT2
tempParity = tempParity + tempData.BIT3
tempParity = tempParity + tempData.BIT4
tempParity = tempParity + tempData.BIT5
tempParity = tempParity + tempData.BIT6
tempParity = tempParity + tempData.BIT7
tempParity = tempParity & $01
RETURN
'====================================================================
This program works perfectly. I let it run for hours, and it
flawlessly made the mouse cursor move between two exact locations on
the screen. This is what I was looking for: precise control of the
mouse so that I can interact with software.
After searching the Internet I discovered that someone else used a
BASIC Stamp computer to interface PS/2 (simulating a keyboard). This
person used the PBASIC instruction SHIFTOUT to handle the CLOCK and
DATA signals, which is really great. This would make my
"TransmitPacket" subroutine much shorter, perhaps 5 lines of code
total!
I also saw that other people used TTL buffers, with inputs connected
directly from PS/2 signals (CLOCK and DATA), and outputs connected
directly to pins on the microcontroller chip. In the same circuit,
output lines from the microcontroller went directly to the base pins on
transistors which had their collectors connected directly to the PS/2
signals. All of this direct coupling of different circuits seems like
a bad idea to me, lest one circuit fry the other. I don't know what
I'd do if I fried the PS/2 port on my PC. Buy a new motherboard, I
guess! An excuse to upgrade. I don't think a PS/2 port motherboard
meltdown is likely, but I did instantly shutdown my computer when I
accidentally short-circuited the +5V and GROUND signals going to the
PS/2 mouse. Maybe it's a feature! I could add a new button to the
mouse that just short-circuits the mouse power for instant shutdown of
the PC. ;-)
Here's the link to the information regarding the use of SHIFTOUT for the PS/2 protocol:
Look for the following link:
KEYBTST.ZIP gives a very basic program for the parallax
-----------
BASIC stamp II, to send key-codes to the PC's keyboard port.
It also gives a write-up of the XT and AT keyboard interfaces
(although IMO some details could be wrong / different to the
keyboards I've looked at).
Locally-cached copy of the file:
keybtst.zip
10655 bytes
MD5: c5667557f96db53fb878bd11bfbe4f74
The following link provides more information regarding PS/2 mouse interfacing: