Code:
'
'***********************************************************************************
'* *
'* PS2 Mouse Interpreter *
'* *
'* Microchip Pic 16F628 @ 3.57MHz *
'* *
'***********************************************************************************
'
'
DEFINE OSC 3 '
DEFINE NO_CLRWDT ' watchdog is cleared manually
'
DEFINE HSER_RCSTA 90h ' enable hardware serial receiver
DEFINE HSER_TXSTA 20h ' enable hardware serial transmitter (24h)
DEFINE HSER_BAUD 2400 '
'
' -------------------------------------
' PS/2 Mouse to Amiga Mouse Converter
' v1.0 (30-Jun-2001)
‘ ported to 16F628A Brek Martin 2015.
' -------------------------------------
' Copyright 2001 Nevenko Baricevic
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU General Public License for more details.
' You should have received a copy of the GNU General Public License
' along with this program. If not, see <http://www.gnu.org/licenses/>.
‘
‘
‘ *** Pic Basic / Pro users don’t declare any variables before these
‘ *** to ensure the assembler variables are all placed in Bank 0.
‘
' ---------- registers definition -----------
bytebuf var byte' ; byte to receive or send
parity var byte' ; parity bit is held here
parcnt var byte' ; counter for calculating parity
roller var byte' ; help for 8 data bits to byte conversion
pack1 var byte' ; 1st byte of mouse data packet
pack2 var byte' ; 2nd byte of mouse data packet
pack3 var byte' ; 3rd byte of mouse data packet
xrot var byte' ; rotation byte for H and HQ
yrot var byte' ; rotation byte for V and VQ
delcnt var byte' ; delay counter
serbufa var byte' ; serial output buffer
serbufb var byte
serbufc var byte
‘ --------- main routine -----------
main:
@ movlw 0x07
@ movwf CMCON
@ bsf STATUS,RP0 ; page 1
@ bcf TRISA,3 ; new mouse output
@ bsf TRISA,2 ; port A, bit 2 is input
@ bsf TRISA,1 ; port A, bit 1 is input
@ bcf TRISA,0 ; port A, bit 0 is output to LED
@ clrf TRISB ; port B is all outputs
@ bcf STATUS,RP0 ; page 0
@ bsf PORTA,0
@ movlw 0xff ; was ff
@ movwf PORTB ; port B all pins to 1
@ movlw 0x2d ; put b'00101101' to xrot and yrot
@ movwf _xrot
@ movwf _yrot
@ call _REC ; receive byte from mouse
@ call _INHIB ; pull CLK low to inhibit furhter sending
@ movf _bytebuf,W
@ xorlw 0xaa ; if it's $AA mouse self test passed
@ btfss STATUS,Z
@ goto _IERROR
@ call _REL ; release CLK (allow mouse to send)
@ call _REC ; receive byte from mouse
@ call _INHIB
@ movf _bytebuf,W
@ xorlw 0x00 ; mouse ID code should be $00
@ btfss STATUS,Z
@ goto _IERROR
@ movlw 0xf4 ; "Enable Data Reporting" command to mouse
@ movwf _bytebuf
@ call _NEWPAR ; get parity for $F4
@ call _REL
@ call _DEL200
@ call _SEND ; send command to mouse
@ call _REC ; receive acknowledge ($FA) from mouse)
@ call _INHIB
@ movf _bytebuf,W
@ xorlw 0xfa
@ btfss STATUS,Z
@ goto _IERROR
@ call _REL
CHK:
@ call _REC ; receive byte1 from mouse packet
@ call _INHIB
@ movf _bytebuf,W
@ movwf _pack1
@ call _REL
@ call _REC ; receive byte2 from mouse packet
@ call _INHIB
@ movf _bytebuf,W
@ movwf _pack2
@ call _REL
@ call _REC ; receive byte3 from mouse packet
@ call _INHIB
@ movf _bytebuf,W
@ movwf _pack3
@ call _CONV
@ call _REL
@ goto _CHK ; receive another packet
' --------------------------------------------------------
PERROR:
@ nop
RERROR:
@ nop
IERROR:
@ nop
E_LOOP:
@ goto _E_LOOP
' --------------------------------------------------------
DEL10:
@ nop ; delay 10us
@ return
DEL200:
@ movlw 0x32 ; delay 200us
@ movwf _delcnt
DEL2:
@ decfsz _delcnt
@ goto _DEL2
@ return
' --------- byte receiving subroutine -------------
REC:
@ btfsc PORTA,2 ; wait clock (start bit)
@ goto _REC
RL1:
@ btfss PORTA,2
@ goto _RL1
@ call _RECBIT ; receive 8 data bits
@ call _RECBIT
@ call _RECBIT
@ call _RECBIT
@ call _RECBIT
@ call _RECBIT
@ call _RECBIT
@ call _RECBIT
RL2:
@ btfsc PORTA,2 ; receive parity bit
@ goto _RL2
@ btfsc PORTA,1
@ goto _RL3
@ bcf _parity,0
RL4:
@ btfss PORTA,2 ; receive stop bit
@ goto _RL4
STP:
@ btfsc PORTA,2
@ goto _STP
@ btfss PORTA,1
@ goto _RERROR
RL8:
@ btfss PORTA,2
@ goto _RL8
@ return
RL3:
@ bsf _parity,0
@ goto _RL4
' ---------- bit receiving subroutine ------------
RECBIT:
@ btfsc PORTA,2
@ goto _RECBIT
@ movf PORTA,W
@ movwf _roller
@ rrf _roller
@ rrf _roller
@ rrf _bytebuf
RL5:
@ btfss PORTA,2
@ goto _RL5
@ return
' ---------- subroutines -----------------
INHIB:
@ call _CLKLO ; inhibit mouse sending (CLK low)
@ call _DEL200
@ return
REL:
@ call _CLKHI ; allow mouse to send data
@ return
CLKLO:
@ bsf STATUS,RP0 ; CLK low
@ bcf TRISA,2
@ bcf STATUS,RP0
@ bcf PORTA,2
@ return
CLKHI:
@ bsf STATUS,RP0 ; CLK high
@ bsf TRISA,2
@ bcf STATUS,RP0
@ return
DATLO:
@ bsf STATUS,RP0 ; DATA low
@ bcf TRISA,1
@ bcf STATUS,RP0
@ bcf PORTA,1
@ return
DATHI:
@ bsf STATUS,RP0 ; DATA high
@ bsf TRISA,1
@ bcf STATUS,RP0
@ return
' ------------- send to mouse --------------
SEND:
@ call _INHIB ; CLK low
@ call _DEL10
@ call _DATLO ; DATA low
@ call _DEL10
@ call _REL ; CLK high
SL1:
@ btfsc PORTA,2 ; wait for CLK
@ goto _SL1
@ call _SNDBIT ; send 8 data bits
SS1:
@ btfss PORTA,2
@ goto _SS1
SS2:
@ btfsc PORTA,2
@ goto _SS2
@ call _SNDBIT
SS3:
@ btfss PORTA,2
@ goto _SS3
SS4:
@ btfsc PORTA,2
@ goto _SS4
@ call _SNDBIT
SS5:
@ btfss PORTA,2
@ goto _SS5
SS6:
@ btfsc PORTA,2
@ goto _SS6
@ call _SNDBIT
SS7:
@ btfss PORTA,2
@ goto _SS7
SS8:
@ btfsc PORTA,2
@ goto _SS8
@ call _SNDBIT
SS9:
@ btfss PORTA,2
@ goto _SS9
SS10:
@ btfsc PORTA,2
@ goto _SS10
@ call _SNDBIT
SS11:
@ btfss PORTA,2
@ goto _SS11
SS12:
@ btfsc PORTA,2
@ goto _SS12
@ call _SNDBIT
SS13:
@ btfss PORTA,2
@ goto _SS13
SS14:
@ btfsc PORTA,2
@ goto _SS14
@ call _SNDBIT
SS15:
@ btfss PORTA,2
@ goto _SS15
SS16:
@ btfsc PORTA,2
@ goto _SS16
@ call _SNDPAR ; send parity bit
SS17:
@ btfss PORTA,2
@ goto _SS17
SS18:
@ btfsc PORTA,2
@ goto _SS18
@ call _DATHI ; release bus
SL4:
@ btfss PORTA,2
@ goto _SL4
SL5:
@ btfsc PORTA,2
@ goto _SL5
@ btfsc PORTA,1
@ goto _RERROR
SL7:
@ btfss PORTA,2
@ goto _SL7
SL8:
@ btfss PORTA,1
@ goto _SL8
@ return
' -------------- subroutines --------------
SNDBIT:
@ rrf _bytebuf ; send data bit
@ btfsc STATUS,C
@ goto _DHIGH
@ call _DATLO
SL2:
@ return
DHIGH:
@ call _DATHI
@ goto _SL2
SNDPAR:
@ btfsc _parity,0 ; send parity bit
@ goto _PHIGH
@ call _DATLO
SP1:
@ return
PHIGH:
@ call _DATHI
@ goto _SP1
CLCPAR:
@ movlw 0 ; calculate parity bit
@ movwf _parcnt
@ btfsc _bytebuf,0
@ incf _parcnt
@ btfsc _bytebuf,1
@ incf _parcnt
@ btfsc _bytebuf,2
@ incf _parcnt
@ btfsc _bytebuf,3
@ incf _parcnt
@ btfsc _bytebuf,4
@ incf _parcnt
@ btfsc _bytebuf,5
@ incf _parcnt
@ btfsc _bytebuf,6
@ incf _parcnt
@ btfsc _bytebuf,7
@ incf _parcnt
@ return
NEWPAR:
@ call _CLCPAR
@ btfss _parcnt,0
@ goto _PARONE
@ bcf _parity,0
@ return
PARONE:
@ bsf _parity,0
@ return
CHKPAR:
@ call _CLCPAR ; check parity
@ movf _parcnt,W
@ andlw 0x01
@ movwf _parcnt
@ movf _parity,W
@ xorwf _parcnt
@ btfss STATUS,Z
@ return
@ call _PERROR
@ return
' --------------- conversion to Amiga format --------------
CONV:
@ btfsc _pack1,0 ; left button
@ goto _LPRESS
@ bsf PORTB,6
@ bsf PORTB,7
CON1:
@ btfsc _pack1,1 ; right button
@ goto _RPRESS
@ bsf PORTB,0
@ bsf PORTA,0
CON2:
@ btfsc _pack1,2 ; middle button
@ goto _MPRESS
@ bsf PORTB,1
MOVE:
‘ Pic BASIC / Pro code to send serial here
serbufa = pack1'
serbufb = pack2'
serbufc = pack3'
HSEROUT [" : ",BIN8 serbufa," ",BIN8 serbufb," ",BIN8 serbufc,13,10]
‘
@ movf _pack2,W ; movement conversion
@ andlw 0xff
@ btfss STATUS,Z
@ call _MOVEX
@ movf _pack3,W
@ andlw 0xff
@ btfss STATUS,Z
@ call _MOVEY
@ return
LPRESS:
@ bcf PORTB,6
@ btfsc _pack1,2
@ bcf PORTB,7
@ goto _CON1
RPRESS:
@ bcf PORTB,0
@ btfsc _pack1,2
@ bcf PORTA,0
@ goto _CON2
MPRESS:
@ bcf PORTB,1
@ goto _MOVE
MOVEX:
@ btfss _pack1,4
@ goto _LEFT
@ goto _RIGHT
MOVEY:
@ btfss _pack1,5
@ goto _DOWN
@ goto _UP
LEFT:
@ call _DEL200 ; send H and HQ for left movement
@ rlf _xrot
@ btfss STATUS,C
@ goto _LH0
@ goto _LH1
LH0:
@ bcf _xrot,0
@ bcf PORTB,4
@ goto _LHQ
LH1:
@ bsf _xrot,0
@ bsf PORTB,4
LHQ:
@ rlf _xrot
@ btfss STATUS,C
@ goto _LHQ0
@ goto _LHQ1
LHQ0:
@ bcf _xrot,0
@ bcf PORTA,3
@ goto _LONE
LHQ1:
@ bsf _xrot,0
@ bsf PORTA,3
LONE:
@ decfsz _pack2
@ goto _LEFT
@ return
RIGHT:
@ call _DEL200 ; send H and HQ for right movement
@ rrf _xrot
@ btfss STATUS,C
@ goto _RHQ0
@ goto _RHQ1
RHQ0:
@ bcf _xrot,7
@ bcf PORTA,3
@ goto _RH
RHQ1:
@ bsf _xrot,7
@ bsf PORTA,3
RH:
@ rrf _xrot
@ btfss STATUS,C
@ goto _RH0
@ goto _RH1
RH0:
@ bcf _xrot,7
@ bcf PORTB,4
@ goto _RONE
RH1:
@ bsf _xrot,7
@ bsf PORTB,4
RONE:
@ incfsz _pack2
@ goto _RIGHT
@ return
UP:
@ call _DEL200 ; send V and VQ for up movement
@ rlf _yrot
@ btfss STATUS,C
@ goto _UV0
@ goto _UV1
UV0:
@ bcf _yrot,0
@ bcf PORTB,5
@ goto _UVQ
UV1:
@ bsf _yrot,0
@ bsf PORTB,5
UVQ:
@ rlf _yrot
@ btfss STATUS,C
@ goto _UVQ0
@ goto _UVQ1
UVQ0:
@ bcf _yrot,0
@ bcf PORTB,3
@ goto _UONE
UVQ1:
@ bsf _yrot,0
@ bsf PORTB,3
UONE:
@ incfsz _pack3
@ goto _UP
@ return
DOWN:
@ call _DEL200 ; send V and VQ for down movement
@ rrf _yrot
@ btfss STATUS,C
@ goto _DVQ0
@ goto _DVQ1
DVQ0:
@ bcf _yrot,7
@ bcf PORTB,3
@ goto _DV
DVQ1:
@ bsf _yrot,7
@ bsf PORTB,3
DV:
@ rrf _yrot
@ btfss STATUS,C
@ goto _DV0
@ goto _DV1
DV0:
@ bcf _yrot,7
@ bcf PORTB,5
@ goto _DONE
DV1:
@ bsf _yrot,7
@ bsf PORTB,5
DONE:
@ decfsz _pack3
@ goto _DOWN
@ return
@ end
' --------------------------------------------------------
Cheers, Art.
Bookmarks