PS2 mouse and BASIC Stamp computer
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: 
(Technical specifications of the "SPCP05A" microchip)
1125022 bytes
MD5: 359a9210275e021cc19a5e2391499dc5
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. 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



    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

    FOR tempCounter = 0 TO 10
    tempData = $18
    GOSUB TransmitPacket
    tempData = $ff
    GOSUB TransmitPacket
    tempData = $01
    GOSUB TransmitPacket
    tempData = $00
    GOSUB TransmitPacket
    PAUSE 100

    GOTO MainLoop




    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...




    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


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:

10655 bytes
MD5: c5667557f96db53fb878bd11bfbe4f74
The following link provides more information regarding PS/2 mouse interfacing:
contact information