;-------------------------------------- ; PS/2 Mouse Host ; ; This was writen to support a 3-button, 2-axis PS/2 mouse with scroll wheel. It is based ; on information found on Adam Chapweske's web site at: ; ; http://panda.cs.ndsu.nodak.edu/%7Eachapwes/PICmicro/mouse/mouse.html ; http://panda.cs.ndsu.nodak.edu/%7Eachapwes/PICmicro/PS2/ps2.htm ; ; The web site is an excellent resouce for dealing with the PS/2 protocol and it is ; HIGHLY recomended you visit it. ; ; This code works, but I still consider it to be incomplete since not all features ; of the PS/2 protocol have been added and/or fully tested. The parity check for ; data received from the mouse is not finished. Some of the code that [I think] is ; needed to implement this feature is in the subroutine "ReceiveByte". There are 3 lines ; of code in that subroutine that are commented out, they are what I started for the ; parity check. There is also no code to check for error commands received from the ; mouse, and there is no code to send error commands to the mouse. But, even without these ; features, everything seems to work as it should. ; ; THIS HAS ONLY BEEN TESTED WITH A 3-BUTTON/SCROLL WHEEL MICROSOFT INTELLIMOUSE!! ; But in theory, it should support a standard 2-button mouse with no scroll wheel ; as is. I have been able to setup up the mouse I tested this code with to operate ; as a 2-button mouse with no scroll wheel by commenting out the scroll wheel check ; in the subroutine "Initialize Mouse" ; ; It should also be noted that I am about as far from being an expert at programing SX chips ; as anybody can be. Since this was my very first attempt at writing any code from scratch ; I am fairly certain that this code can be optimised further. It is free to use by anybody ; for any reason. Use it as is, or change it, modify it, do whatever you want with it. List Q = 37 DEVICE SX28l, TURBO, STACKX, OSCHS2 IRC_CAL IRC_FAST FREQ 4_000_000 RESET MAIN ClockLine EQU RA.0 ;this is the clock line DataLine EQU RA.1 ;this is the data line ORG $08 TxByte DS 1 BitCount DS 1 ParityBit DS 1 ParityCount DS 1 TempVar DS 1 ORG $10 RxBytes EQU $ RxByte1 DS 1 RxByte2 DS 1 RxByte3 DS 1 RxByte4 DS 1 RxTemp DS 1 ORG $30 Counters EQU $ Counter1 DS 1 Counter2 DS 1 Counter3 DS 1 Counter4 DS 1 Counter5 DS 1 ;------------------------------------------------ ; Send one byte to mouse ;------------------------------------------------ SendByte CLRB ClockLine ;set Clock line low MOV !RA, #%1110 ;set ClockLine as OUTPUT CALL Delay100 ;wait 100 microseconds CLRB DataLine ;bring the Data line low MOV !RA, #%1100 ;set DataLine as OUTPUT SETB ClockLine ;set Clock line high MOV !RA, #%1101 ;set ClockLine as INPUT MOV BitCount, #8 ;sets number of bits to send JB ClockLine, $ ;wait for clock line to go low SETB DataLine ;set DataLine high :TxLoop JB ClockLine, $ ;wait for Clock line to go low RR TxByte ;get next bit to send, store in carry flag SNC ;if bit being sent is high, ParityCount is increased... INC ParityCount ; this keeps track of all the high bits, used for parity check SC ;if bit being sent is 0... CLRB DataLine ; set Data Line low SNC ;if bit being sent is 1... SETB DataLine ; set Data Line high JNB ClockLine, $ ;wait for Clock Line to go high DECSZ BitCount ;decrease BitCount JMP :TxLoop ;if BitCount > 0 loop again JB ClockLine, $ ;wait for Clock Line to go low SB ParityCount.0 ;if bit 0 of ParityCount is 0... SETB DataLine ; set Data Line high SNB ParityCount.0 ;if bit 0 of ParityCoundt is 1... CLRB DataLine ; set DataLine low MOV !RA, #%1111 ;set DataLine as INPUT JB ClockLine, $ ;wait for clockline to go low JB DataLine, $ ;Wait dataline to go low, this is acknowledge bit JNB ClockLine, $ ;wait for clockline to go high JNB DataLine, $ ;wait for dataline to go high CLR TxByte CLR ParityCount RETP ;------------------ DONE ;------------------------------------------------ ; Recieve one byte from mouse ;------------------------------------------------ ReceiveByte MOV BitCount, #8 ;sets the number of bits to receive BANK Rxbytes CLR RxTemp JB ClockLine, $ ;wait for the clockline to go low JB DataLine, $ ;wait for the dataline to go low, this is start bit :RxLoop JNB ClockLine, $ ;wait for clockline to go high JB Clockline, $ ;wait for clockline to go low MOVB C, DataLine ;get next bit and store it in carry flag ; SNB C ;if the bit received was high, ParityCount is increased ; INC ParityCount ; high bits are counted for parity check RR RxTemp ;store received bit into RxByte DECSZ BitCount ;decrease BitCount, if it equals zero, byte has been received JMP :RXLoop ;if BitCount is > 0 loop again JNB ClockLine, $ ;wait for clockline to go high JB Clockline, $ ;wait for clockline to go low ; MOVB C, DataLine ;receive parity bit, used for parity check..not implemented yet JNB ClockLine, $ ;wait for clockline to go high JB Clockline, $ ;wait for clockline to go low, stop bit JNB ClockLine, $ ;end of byte, wait for clockline to go high CLR ParityBit CLR ParityCount RETP ;------------------ DONE ;------------------------------------------------ ; misc subroutines ;------------------------------------------------ Delay100 BANK Counters ;delay 100(ish) microseconds. the delay is padded a bit MOV Counter1, #110 ;and can be set longer but it must NOT be set lower than DJNZ Counter1, $ ;100 microseconds. it is required for sending commands ;to the mouse RETP ;------------------ DONE ;------------------------------------------------ ; Initialize Mouse ; Attempts to intialize mouse with 3 buttons, scroll wheel, and 2 axis. The mouse ; must have a scroll wheel for this to happen. If not, mouse will be intiallized ; as standard PS/2 mouse (2 buttons, 2 axis) NOTE: Standard 2-button mice have not ; been tested yet and further changes may need to be made to the code in order for ; them to work correctly. ;------------------------------------------------ InitializeMouse CLR Flags MOV Txbyte, #$FF ;send reset CALL Sendbyte CALL ReceiveByte ;acknowledge byte from mouse...ignor it CALL ReceiveByte ;bat completion from mouse...ignor it CALL ReceiveByte ;mouse id from mouse...ignor it ;------------------------<|start of scroll wheel check MOV TxByte, #$F3 ;<| send set sample rate change CALL SendByte ;<| CALL ReceiveByte ;<| acknowledge byte from mouse...ignor it MOV TxByte, #$C8 ;<| send sample rate 200 CALL SendByte ;<| CALL ReceiveByte ;<| acknowledge byte from mouse...ignor it MOV TxByte, #$F3 ;<| send set sample rate change CALL SendByte ;<| CALL ReceiveByte ;<| acknowledge byte from mouse...ignor it MOV TxByte, #$64 ;<| send sample rate 100 CALL SendByte ;<| CALL ReceiveByte ;<| acknowledge byte from mouse...ignor it MOV TxByte, #$F3 ;<| send set sample rate change CALL SendByte ;<| CALL ReceiveByte ;<| acknowledge byte from mouse...ignor it MOV TxByte, #$50 ;<| send sample rate 80 CALL SendByte ;<| CALL ReceiveByte ;<| acknowledge byte from mouse...ignor it MOV TxByte, #$F2 ;<| get device type CALL SendByte ;<| CALL ReceiveByte ;<| acknowledge byte from mouse... ignor it CALL ReceiveByte ;<| device ID from mouse, 00 = 2-buttons, 03 = 3-button & scroll wheel ;------------------------<|end of scroll wheel check MOV TxByte, #$E8 ;set resolution CALL SendByte CALL ReceiveByte ;acknowledge byte from mouse...ignor it MOV TxByte, #$03 ;set resolution to 8 counts/mm CALL SendByte CALL ReceiveByte ;acknowledge byte from mouse...ignor it MOV TxByte, #$F3 ;send set sample rate change CALL SendByte CALL ReceiveByte ;acknowledge byte from mouse...ignor it ;remove the ';' from one of the following 4 lines ; MOV TxByte, #$28 ;set sample rate 40 slow ; MOV TxByte, #$50 ;set sample rate 80 not as slow ; MOV TxByte, #$64 ;set sample rate 100 default ; MOV TxByte, #$C8 ;set sample rate 200 full throttle CALL SendByte CALL ReceiveByte ;acknowledge byte from mouse.. ignor it MOV TxByte, #$F4 ;send enable data reporting, this is required for... CALL SendByte ; STREAMING MODE CALL ReceiveByte ;acknowledge byte from mouse.. ignor it MOV TxByte, #$F0 ;<| send command to enter REMOTE MODE. to setup mouse for CALL SendByte ;<| STREAMING MODE comment out these three lines CALL ReceiveByte ;<| RETP ;------------------ DONE ;------------------------------------------------ ; Get data packet from mouse ; By default this will fetch a 4-byte data packet, which is needed for ; mice that have 3 buttons and a scroll whell. A 2-button mouse will ; send a 3-byte data packet. If using a 2-button mouse, comment out the ; last 2 lines (before the RETP instruction). ;------------------------------------------------ GetData BANK RxBytes CALL ReceiveByte ;get first byte in data packet MOV RxByte1, RxTemp ;store byte in RxByte1 CALL ReceiveByte ;get second byte in data packet MOV RxByte2, RxTemp ;store byte in RxByte2 CALL ReceiveByte ;get third byte in data packet MOV RxByte3, RxTemp ;store byte in RxByte3 CALL ReceiveByte ;<|get forth byte in data packet (if it exists) MOV RxByte4, RxTemp ;<|store byte in byte4 RETP ;------------------ DONE ;------------------------------------------------ ; MAIN LOOP ;------------------------------------------------ MAIN CALL InitializeMouse :Loop MOV TxByte, #$EB ;<|send READ DATA request to mouse. this is required to get... CALL SendByte ;<| data packets when the mouse is setup for REMOTE MODE. CALL ReceiveByte ;<|acknowledge byte from mouse...ignor it ;to use the poormans fix below for STREAMING MODE, comment ;out the 3 lines line above. ; JB ClockLine, $ ;This is the poorman's fix for not having an inturrupt routine ;for using the mouse in STREAMING MODE. In streaming mode, the ;start of an incoming data packet is the mouse bringing the ;Clock Line low. This simply loops until that happens. To use ;the poormans fix, comment out the first 3 lines the main ;program :loop, and comment out the last 3 lines of ;InitializeMouse subroutine, and un-comment this line. CALL GetData ;gets the data packet from the mouse, used for REMOTE and... ; STREAMING MODE ;[INSERT CODE HERE TO DO SOMETHING USEFUL WITH MOUSE DATA] JMP :Loop