Communication with a PS/2 mouse

using a PIC 16F84

You are the visitor n.

Fare click qui per la versione Italiana

Best view with 1024x768

     


Back to Home Page

E-mail address



Similar topics on this site:

PIC 16F84 F.F. Evaluation Board
PIC - PS/2 mouse interfacing and communication
Connecting a microcontroller to RS-232 ports and PS/2 devices
 
 
Introduction

As explained in the article Host - PS/2 mouse hardware communication on this site, to test the protocol needed to communicate with a PS/2 mouse I have interfaced it with a properly programmed PIC 16F84.

If you are interested in a more complete program, written for a PIC 16F877 but suitable for many other PIC microcontrollers, you can have a look at the article PIC - PS/2 mouse interfacing and communication on this site.

Pay attention: PS/2 devices are different from serial mice, concerning both communication protocol and electrical levels; in PS/2 mice levels used for supply and data exchange are 0 and +5V, in serial mice we instead find the RS-232 levels, +12V and -12V. This article is concerning a PS/2 mouse. The PIC too must receive a +5V supply. In particular, common (or ground) pins of PIC and PS/2 mouse must be connected together; the same for +5V pins.

To connect the mouse and the microcontroller together I suggest a flying PS/2 plug, to which you can connect the four needed wires. Such wires can then be carried to a prototype board and connected on it to the wires coming from the proper PIC's pins. To operate the PIC I have used the version previous to the one described in the article PIC 16F84 F.F. Evaluation Board on this site. For connections refer to the article about Host - PS/2 mouse hardware communication, to the PS/2 connector pin-out and to the first lines of the assembler list below. If in this way the mouse shouldn't show any sign of life, connect two pull-up resistors between data and clock and +5V supply (that, I repeat, must be the same for the microcontroller and the mouse). Proper values are around 3-10 KOhm.

Take care to connections, to avoid unpleasant damages to devices! Instead of damaging a PIC or a mouse, if you are not really sure of acting correctly you can write me.

Acknowledgement and disclaimers

The material contained in these pages is the result of preliminary tests, project developement and verify carried on by the undersigned in first person.

I guarantee the absolute originality of the material, though obviously not excluding that on the net it could be possible to find something analogous.

Being this material at free disposal of whoever desires it, it is absolutely forbidden any form of use for commercial purposes. I don't assume, of course, any responsibilty for possible direct or indirect damages to things or persons deriving by the use of the informations contained in this article.

PIC and Microchip are registered trademarks.

The assembler program.

Below you can find the list of the assembler program. As you can see watching it, it is substantially a set of routines I have written to send command to the mouse and to receive its answers. As it is a program I have used to carry on some tests, it is not optimized, neither concerning memory usage, nor concerning other aspects. It also contains some sections I used only to check the correspondence between the real protocol and the one described in some other papers on the net (I recognized an important difference about parity; you can find the correct description of the communication protocol in the article Host - PS/2 mouse hardware communication on this site). To show which section of the program is currently executed and eventual error conditions, I used different kinds of blinking of a LED connected to the PIC (for whom who doesn't know it, a series resistor between the PIC's pin and the LED is needed; proper values are from 330 Ohm to 1 KOhm). Values used for waiting cycles refers to a clock frequency of 4 MHz, that is 1 million instructions per second. Data sent from the mouse about motion and switches status are not used. If you wish, to you now the task to use my routines making them suitable for your applications. Good luck!

 

;page 1

; filename: mouseps2.asm
;
;
; receives data in a serial way from a
; PS/2 mouse;
; lines used are two: clock and data.

; As these lines should be open collector,
; according to the PS/2 protocol,
; RA2 (Clock) and RA3 (Data) are used as
; LOW output when it's to the host to drive
; them, while when they must be HIGH or
; when they have to be driven by the mouse
; they are set as inputs.

; RA0 (Clock) and RA1 (Data) are used
; as inputs to test Clock and Data lines.

; RB0 is used (as output) for giving the user
; informations about the communication
; status and about reception errors (as an example, with a LED)

PROCESSOR 16F84

RADIX DEC

__CONFIG 3FF1H

; XT

; /PWRO enable

; WDT disable

INCLUDE "P16F84.INC"

TOCS EQU 05H

CIN EQU 0
DIN EQU 1
COUT EQU 2
DOUT EQU 3
STBIT EQU 0
ENDBIT EQU 1

RA0 EQU 0
RA1 EQU 1
RA2 EQU 2
RA3 EQU 3
RA4 EQU 4
RB0 EQU 0
RB1 EQU 1
RB2 EQU 2
RB3 EQU 3
RB4 EQU 4
RB5 EQU 5
RB6 EQU 6
RB7 EQU 7

ORG 0CH

count RES 1

; page 2

cbit RES 1
cbyte RES 1
delay1 RES 1
delay2 RES 1
delay3 RES 1
byteo RES 1
byteio RES 1
bytein RES 1
parbit RES 1
byte1 RES 1
byte2 RES 1
byte3 RES 1
byte4 RES 1
serv RES 1

hexd0 RES 1
hexd1 RES 1
hexd2 RES 1
decd0 RES 1
decd1 RES 1
decd2 RES 1
currd RES 1

number RES 1
workdi RES 1
servst RES 1
servw RES 1
servir RES 1

; WARNING: always keep at 0 the RP0 bit
; of the STATUS register ( selection of bank 0)
; to read the TMR0, set that bit just when needed
; and then set it again to 0

ORG 00H

goto start

ORG 50H

start

bsf STATUS,RP0

; RB1-7: INPUT
; RB0: INPUT

movlw 11111111B
movwf TRISB

; RA4 :INPUT (unused)
; RA3, RA2 : INPUT
; RA1, RA0 : INPUT

movlw 11111111B
movwf TRISA
bcf STATUS,RP0

; page 3

; disables Clock and Data

movlw 11111111B
movwf PORTA
movlw 11111111B
movwf PORTB
bsf STATUS,RP0

; assigns fosc/4 to TMR0

bcf OPTION_REG,TOCS

; assigns the prescaler to TMR0 with value 256
; (111)

; bsf OPTION_REG,PSA
; bsf OPTION_REG,PS2
; bsf OPTION_REG,PS1
; bsf OPTION_REG,PS0
bcf STATUS,RP0

; movlw 00H
; movwf hexd2
; movwf hexd1
; movwf hexd0
; movwf decd2
; movwf decd1
; movwf decd0
; movwf number
; movwf servst
; movwf servw
; movwf serv
; movlw 00H
; movwf currd
; movwf workdi
; movlw 00H
; movwf count

movlw 00H
movwf TMR0

; waits 1 s

call del1s

; signals three times "sent command"
; to indicate the start of operations

call cmdsnt
call cmdsnt
call cmdsnt

; sends RESET command (FFH)

movlw 0FFH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt

; page 4

; waits 1s

call del1s

; sends ENABLE command (F4H)

movlw 0F4H
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt

; waits 1 s

call del1s

; sends DEFAULT SETTINGS command
; (F6H)

movlw 0F6H
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt

call del1s

; requests data transmission (EBH)

movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt

call del1s

; requests data transmission (EBH)

movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt

call del1s

; sets stream mode (EAH)

movlw 0EAH
movwf byteo
movwf byteio

; page 5

call cmdts
call sendby
call cmdsnt
call del1s

; requests data transmission (EBH) after
; stream mode setting

movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s

; continuous data reception (every 100 ms)

datain
call del.1s

; requests data transmission (EBH)

movlw 0EBH
movwf byteo
movwf byteio
call sendby
call recby
movf byteio,W
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte4
call recby
movf byteio,W
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte3
call recby
movf byteio,W
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte2
call recby
movf byteio,W

; page 6

xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte1
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
bsf PORTB,RB0
call del10m
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
bcf PORTB,RB0
goto datain
goto fine

recby

; data reception - returns the received byte in
; bytein; if an error of any kind
; has occurred, returns
; byteio=11111111B, otherwise byteio=0

movlw 00H
movwf bytein
movlw 08H
movwf cbit

waitst

; waits for the clock to go to 0 and inserts
; as bit number 0 of byteio
; the bit on RA1 (Data)
; waits start bit (RA1 pin)

movf PORTA,W
btfsc PORTA,RA0
goto waitst

; sets high RB0 pin when
; reception starts

bsf STATUS,RP0
bcf TRISB,0
bcf STATUS,RP0
bsf PORTB,RB0
movwf serv
rrf serv,W
andlw 00000001B
xorlw STBIT
andlw 00000001B
call wcup

; pag.7

; if start bit is different from STBIT signals
; an error

btfsc STATUS,Z
goto stbok
call estb
movlw 0FFH
movwf byteio
goto endrec

stbok

movlw 08H
movwf cbit
movlw 00H
movwf byteio

; riceve gli 8 bit

waitb

movf PORTA,W
btfsc PORTA,RA0
goto waitb
movwf serv
rrf serv,W
andlw 00000001B
btfsc STATUS,Z
goto carry0

carry1

bsf STATUS,C
goto storeb

carry0

bcf STATUS,C

storeb

rrf byteio,F
call wcup
decfsz cbit
goto waitb
movf byteio,W
movwf bytein

; receives parity bit

waitpy

movf PORTA,W
btfsc PORTA,RA0
goto waitpy
movwf serv
call wcup

; calculates the parity of the byte in byteio
; and returns it in parbit

call pargen
rrf serv,W
andlw 00000001B
xorwf parbit,W
btfss W,0
goto pbok
call eparb
movlw 0FFH
movwf byteio
goto endrec

; page 8

pbok

nop

; waits for the stop bit

waitsb

movf PORTA,W
btfsc PORTA,RA0
goto waitsb
movwf serv
rrf serv,W
andlw 00000001B
xorlw ENDBIT
andlw 00000001B
call wcup

; if the stop bit is different from ENDBITsignals
; an error

btfsc STATUS,Z
goto ebok
call eendb
movlw 0FFH
movwf byteio
goto endrec

ebok

bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
bsf PORTB,RB0

; if byteio = FFH it means that an error
; has occurred; if the programs arrives here
; it means that the byte (anyway put in bytein)
; has been correctly received

movlw 00H
movwf byteio

endrec

return

; not necessary

goto fine

; calculates the parity of the byte in byteio
; and returns it in parbit

pargen

movlw 08H
movwf cbit
movlw 00H

pcycle

xorwf byteio,W
bcf STATUS,C
rrf byteio,F
decfsz cbit
goto pcycle

; page 9

andlw 00000001B
movwf parbit
return

; sends on PORTA,DOUT the L.S.bit
; of the w register: if a 0 has to be set,
; puts it on PORTA,DOUT and sets that
; pin as an output;
; if a 1 has to be set, puts it on porta
; (but it's not need) and sets that pin
; as an input

outbit

andlw 1H
btfsc STATUS,Z
goto outz
goto outuno

outz

bcf STATUS,RP0
bcf PORTA,DOUT
bsf STATUS,RP0
bcf TRISA,DOUT
bcf STATUS,RP0
goto endss

outuno

bsf STATUS,RP0
bsf TRISA,DOUT
bcf STATUS,RP0
bsf PORTA,DOUT

endss

return

; waits for the clock (PORTA,CIN) to change from
; low to high

wcup

btfss PORTA,CIN
goto wcup
return

; waits for the clock (PORTA,CIN) to change from
; high to low

wcdown

btfsc PORTA,CIN
goto wcdown
return

; waits for data (PORTA,DIN) to change
; from low to high

wdup

btfss PORTA,DIN
goto wdup
return

; waits for data (PORTA,DIN) to change
; from high to low

wddown

btfsc PORTA,DIN
goto wddown
return

; pag.10

; error in start bit reception (difference from
; STBIT constant)
; sets alternately 1 and 0 on RB0 8 times, with a period
; of about 0.2 sec, about 1 sec in the whole

estb

bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 08H
movwf count

cycle2

movlw 00H
movwf delay1
movwf delay2
btfss count,0
goto ozero
goto ouno

ozero

bcf PORTB,RB0
goto cycle3

ouno

bsf PORTB,RB0

cycle3

decfsz delay1
goto cycle3
decfsz delay2
goto cycle3
decfsz count
goto cycle2
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return

; error in start bit reception (difference from
; STBIT constant)
; sets alternately 1 and 0 on RB0 16 times, with a period
; of about 0.1 sec, about 1.5 sec in the whole

eparb

bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 10H
movwf count

cycle4

movlw 00H
movwf delay1
movlw 80H
movwf delay2
btfss count,0
goto ozero1
goto ouno1

; page 11

ozero1

bcf PORTB,RB0
goto cycle5

ouno1

bsf PORTB,RB0

cycle5

decfsz delay1
goto cycle5
decfsz delay2
goto cycle5
decfsz count
goto cycle5
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return

; error in stop bit reception (difference from
; ENDBIT constant);
; sets alternately 1 and 0 on RB0 32 times, with a period
; of about 0.05 sec, about 1.5 sec in the whole

eendb

bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 20H
movwf count

cycle6

movlw 00H
movwf delay1
movlw 40H
movwf delay2
btfss count,0
goto ozero2
goto ouno2

ozero2

bcf PORTB,RB0
goto cycle7

ouno2

bsf PORTB,RB0

cycle7

decfsz delay1
goto cycle7
decfsz delay2
goto cycle7
decfsz count
goto cycle6
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return

; page 12

; command sent - sets alternately 1 and 0 on RB0 2 times,
; with a period of
; about 0.5 sec, about 1 sec in the whole

cmdsnt

bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 02H
movwf count

cycle8

movlw 00H
movwf delay1
movlw 00H
movwf delay2
movlw 02H
movwf delay3
btfsc count,0
goto ozero3
goto ouno3

ozero3

bcf PORTB,RB0
goto cycle9

ouno3

bsf PORTB,RB0

cycle9

decfsz delay1
goto cycle9
decfsz delay2
goto cycle9
decfsz delay3
goto cycle9
decfsz count
goto cycle8
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return

; receives in byteo and byteio the byte to send

sendby

bcf STATUS,RP0
bsf PORTB,0
bsf STATUS,RP0
bcf TRISB,0
bcf STATUS,RP0

; forces clock to 0 and waits about 200 us
; in order to do this, sets to 0 and configures
; the pin PORTA,COUT as an output

bcf STATUS,RP0
bcf PORTA,COUT

; page 13

bsf STATUS,RP0
bcf TRISA,COUT
bcf STATUS,RP0

; puts 42H in delay1 (about 200 us)

movlw 42H
movwf delay1

cycle1

decfsz delay1
goto cycle1
movlw STBIT
call outbit

; releases clock

bsf STATUS,RP0
bsf TRISA,COUT
bcf STATUS,RP0
bsf PORTA,COUT
call wcup
call wcdown
movlw 08H
movwf cbit

detbit

bcf STATUS,C
rrf byteo,F
btfss STATUS,C
goto bitz
goto bituno

bitz

movlw 00H
goto callob

bituno

movlw 01H
callob
call outbit
call wcup
call wcdown
decfsz cbit
goto detbit
call pargen
movf parbit,W

; TESTS PARITY INVERSION

xorlw 00000001B
call outbit
call wcup
call wcdown

; page 14

movlw ENDBIT
call outbit
call wddown
call wcdown
call wdup
call wcup
return

; delay routine of about 1 ms

del1ms

movlw 02H
movwf delay2
movlw 0A0H
movwf delay1

cyc21

decfsz delay1
goto cyc21
decfsz delay2
goto cyc21
return

; delay routine of about 10 ms

del10m

movlw 0DH
movwf delay2
movlw 00H
movwf delay1

cyc51

decfsz delay1
goto cyc51
decfsz delay2
goto cyc51
return

; delay routine of about 100 ms

del.1s

movlw 0A0H
movwf delay2
movlw 00H
movwf delay1

cyc41

decfsz delay1
goto cyc41
decfsz delay2
goto cyc41
return

; delay routine of about 1 s

del1s

; page 15

movlw 05H
movwf delay3
movlw 00H
movwf delay2
movwf delay1

cyc11

decfsz delay1
goto cyc11
decfsz delay2
goto cyc11
decfsz delay3
goto cyc11
return

; indicates that a command is about to be sent - sets RB0
; to 1 with a pulse of about 0.1 sec and then
; 0 for 0.1 sec

cmdts

bsf STATUS,RP0

; page 16

bcf TRISB,RB0
bcf STATUS,RP0
bsf PORTB,RB0
movlw 00H
movwf delay1
movlw 00H
movwf delay2

cyc31

decfsz delay1
goto cyc31
decfsz delay2
goto cyc31
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
call del.1s
return

fine

END

 

Have a nice work!
 

If you want to contact me for informations and suggestions:

f_iacopetti@libero.it

 
Last update: 20 December 2001, 19.05 HyperCounter