wires, board, ... (what every circuit needs)
Depending on the Microcontroller other resonator frequencies and
other capacitors must be used.
The sun mouse plug
The sun mouse plug has the following pinout. Original sun mice
have a plug with only 3 pins; 5 pins are missing. These missing
pins should not be used:
The Protocol
Unlike "/dev/mouse" (that uses the 3 byte Sun protocol) the
5 byte Mouse Systems protocol is used on the hardware side.
The signals coming from the mouse are the same a serial Mouse
Systems mouse would send but the logic level is inverted TTL.
This means a "0" is represented by +5V and a "1" by 0V. The
following drawing shows one byte transmitted this way:
The 5 bytes have the following meaning:
Byte 1: 10000LMR
Byte 2: X1
Byte 3: Y1
Byte 4: X2
Byte 5: Y2
The last 4 bytes are signed values that might have a value
of 10000xxx, too, so there is no possibility to detect
the first byte of the packet. On the other hand a value of
10000xxx would be such a fast mouse movement that such
values never appear so 10000xxx can be seen as indication of
the start of a new packet.
The real X movement is (X1+X2) (positive=left). The circuit
uses X2=constant=0. All movement data is transmitted over X1.
The same is true for Y1/Y2 (positive=up).
Schematics
This schematics is based on another shematics developed by me
that is used to connect PS/2 mice to the RS232 port.
The pin numbers at the MCU are valid for the DIP 40 variant of
the 89S8252. If you use another device please read the device
manual for correct pin numbers.
This schematics assumes that all port 3 pins are open-collector
bidirectional I/O pins (that may have a pull-up resistor). The
current version of the firmware assumes all pins to be in high-
impedance mode (= HIGH) on power-on. You can even use different
pins for input, output and interrupt (Ext #0, falling edge) if
the source code is modified.
You may use a soft reset button or not. If you do not use one
you must either connect pin 13 to High or modify the firmware
(normally pin 13 is connected to High using a pull-up resistor
internally !). If you do not use a soft reset button you need
a hard reset button that uses the Reset pin (pin 9). This
variant requires a 4th resistor to avoid a shortcut of the
capacitor.
Firmware source code
; PS/2 to Sun mouse converter
; Needs an (extended ?) 8051
; Copyright (c) 2003 by Martin D. J. Rosenau
;
; Memory usage:
; 1Dh: Used by the PS/2 receiver
; 1Eh..1Fh: Used by the PS/2 transmitter
; 20h: Used by the serial routine
; 21h: Bit0: PS/2 bit received (cleared by other routines)
; Bit1:
; 22h: First byte of a packet received
; 23h: First byte (button state) of the last packet translated
; 24h: Relative X movement
; 25h: Relative Y movement
; 26h..27h: Used by the main program
; 30h..33h: Serial send buffer
; 34h: Number of bytes in the serial buffer
; If N>4 the last byte is repeated (N-3) times.
; 35h..38h: Used by the serial routines
; 39h: Byte received from PS/2 port
; 3Ah..3Dh: Used by the PS/2 receiver
; 3Eh..3Fh: Used by the PS/2 transmitter
;
; Ports:
; 3.1 - Mouse data (output)
; 3.2/INT0 - PS/2 clock (TTL; IN&OUT)
; 3.3 - LOW = Reset
; 3.7 - PS/2 data (TTL; IN&OUT)
;
; Definition of the port bits
; You may change the pins; PS/2 clock
; must be the same pin as INT0 !
PS2IN bit 0B7h
PS2OUT bit 0B7h
MSRESET bit 0B3h
PS2CLOCKIN bit 0B2h
PS2CLOCKOUT bit 0B2h
SERIALOUT bit 0B1h
; Some crystal frequency dependent values
; You must change these values when
; using a different crystal !
; about MHz*(2.5) -> 60 for 24 MHz
TIME1 equ 60
; 100h-(MHz*(2.15)) -> 0CCh for 24 MHz
TIME2 equ 0CCh
; Header
sjmp start
org 3
ljmp onclockin
org 1Bh
ljmp ontimer1
org 40h
; The start of it...
start:
; Wait until an initialize
; signal is received...
clr SERIALOUT
clr 9
mov 0A8h,#0
mov C,MSRESET
jnc start
; Initialize the serial port
acall serinit
mov 34h,#0
; Clear the PS/2 port and enable it
clr 8
setb 88h
mov 3Ah,#0
mov 23h,#0
mov 24h,#0
mov 25h,#0
mov 1Dh,#0
; Send initialition data to the PS/2 mouse
mov A,#0F4h
acall ps2send
acall ps2read
mov A,#0E7h
acall ps2send
acall ps2read
mov A,#0E8h
acall ps2send
acall ps2read
mov A,#1
acall ps2send
acall ps2read
setb 0A8h
setb 9
; The working loop
; Restart the program any time RTS goes low.
waitfirst:
; Wait while a serial transmission is done
mov A,34h
jnz waitfirst
; "Reset" detected
mov C,MSRESET
jnc start
; Did the mouse position or buttons change ?
mov A,24h
jnz mousechanged
mov A,25h
jnz mousechanged
mov A,22h
xrl A,23h
anl A,#7
jz waitfirst
mousechanged:
; The mouse position changed, so a packet must be sent...
mov 26h,24h
mov 24h,#0
mov 27h,25h
mov 25h,#0
mov 23h,22h
; Buttons
mov A,#080h
mov C,18h
mov 0E2h,C
mov C,19h
mov 0E0h,C
mov C,1Ah
mov 0E1h,C
xrl A,#7
; Finish the packet
mov 30h,A
mov A,26h
; anl A,#7Fh
mov 31h,A
mov A,27h
; anl A,#7Fh
mov 32h,A
mov 33h,#0
mov 34h,#5
; Restart
sjmp waitfirst
; PS/2 clock line detected
onclockin:
mov 3Bh,A
mov 3Ch,0D0h
mov A,3Ah
jnz notfirstps2
; It is a start bit => MUST be 0 !
mov C,PS2IN
jc onclockend
mov 3Ah,#10
sjmp onclockend
notfirstps2:
dec 3Ah
dec A
jnz notstopbit
; It is a stop bit
mov C,PS2IN
jnc onclockend
mov 39h,3Dh
setb 8
mov C,9
jc onautops2
sjmp onclockend
notstopbit:
dec A
; Ignore parity
jz onclockend
mov A,3Dh
mov C,PS2IN
rrc A
mov 3Dh,A
onclockend:
mov A,3Bh
mov 0D0h,3Ch
reti
onautops2:
; Automatically process PS/2 data
mov A,1Dh
dec A
jnz isnot2
; 2nd byte
inc 1Dh
mov A,39h
add A,24h
mov 24h,A
sjmp onclockend
isnot2:
; 3rd byte
dec A
jnz isnot3
mov 1Dh,#0
mov A,39h
add A,25h
mov 25h,A
sjmp onclockend
isnot3:
; 1st byte
mov A,39h
mov C,0E3h
jnc onclockend
mov 22h,A
mov 1Dh,#1
sjmp onclockend
; Initialize the serial routine
serinit:
clr SERIALOUT
mov 0A8h,#0
mov 89h,#0
mov 8Dh,0
mov 34h,#0
mov 35h,#0
setb 8Eh
mov 0A8h,#88h
ret
; Read a single byte from the PS/2 port
ps2read:
setb 0A8h
mov C,8
jnc ps2read
mov A,39h
clr 8
ret
; Send a byte over the PS/2 port
; Disables the external interrupt.
ps2send:
clr 0A8h
mov 1Eh,A
mov 1Fh,A
; Wait some time
mov A,128
ps2waitpre:
dec A
jnz ps2waitpre
; Inhibit
clr PS2CLOCKOUT
mov A,#TIME1
ps2dowait:
dec A
jnz ps2dowait
setb PS2CLOCKOUT
clr PS2OUT
; Send all bits
mov 3Fh,#8
nextbitps2:
mov A,1Fh
rrc A
mov 1Fh,A
acall sendps2bit
dec 3Fh
mov A,3Fh
jnz nextbitps2
; Send the parity bit
mov A,1Eh
xrl A,#1
mov C,0D0h
acall sendps2bit
; Send the stop bit and receive the ACK bit
setb C
acall sendps2bit
setb C
acall sendps2bit
ackwait:
mov C,PS2IN
jnc ackwait
ret
; Send a bit (C) to the PS/2 port
sendps2bit:
mov 3Eh,0D0h
sendps21:
mov C,PS2CLOCKIN
jc sendps21
mov 0D0h,3Eh
mov PS2OUT,C
sendps22:
mov C,PS2CLOCKIN
jnc sendps22
mov 0D0h,3Eh
ret
; Timer 1 interrupt routine: Serial port
; emulation (the hardware UART is no used)
ontimer1:
; restart the timer
mov 8Dh,#TIME2
; save the accumulator
mov 37h,A
mov 38h,0D0h
; is a byte currently being sent ?
mov A,35h
jnz duringsend
; No bytes is currently being sent
; Start one ?
mov A,34h
jnz beginsend
; Exit the interrupt
ontimer1end:
mov A,37h
mov 0D0h,38h
reti
beginsend:
; begin sending a byte
mov 20h,30h
mov 30h,31h
mov 31h,32h
mov 32h,33h
dec 34h
setb SERIALOUT
; Still 9 bits to be sent (including
; 1 stop bit)
mov 35h,#9
sjmp ontimer1end
duringsend:
; What to do while transmitting a byte...
dec 35h
mov A,20h
setb C
rrc A
cpl C
mov SERIALOUT,C
mov 20h,A
sjmp ontimer1end
end
Compiled firmware
Here is the compiled firmware in HEX file format. The program is
compiled for the following configuration: