620 lines
16 KiB
NASM
620 lines
16 KiB
NASM
;*****************************************************************************
|
|
; PS2Atari_v1_4.asm *
|
|
; PS2 PC mouse to Atari / Amiga mouse converter by Tom Kirk March 2010 *
|
|
; Version 1.3 *
|
|
;*****************************************************************************
|
|
; *
|
|
; Enables a PS2 PC mouse to be used with Atari / Amiga computers using *
|
|
; the circuit in circuit.bmp with a PIC16F84(A)/C84 micrcontroller. *
|
|
; *
|
|
; Assembled using Microchip MPLAB and MPASM. *
|
|
; Disable case sensitivity under build options. *
|
|
; *
|
|
;*****************************************************************************
|
|
; Version 1.4 July 2010 *
|
|
; Unused Pin RA4 now correctly set as an imput. *
|
|
; (Pin is tied to +5V on PCB for easier PCB routing.) *
|
|
; My oversight when transfering from prototype to PCB. *
|
|
; Thanks to Luciano for informing me. *
|
|
; *
|
|
; Version 1.3 March 2010 *
|
|
; Corrected a bug in button routine preventing both buttons being active *
|
|
; together under certain conditions. *
|
|
; Thanks to Oliver Fleischmann for informing me. *
|
|
; (Can't believe it taken 6 Years for this bug to show itself!!) *
|
|
; *
|
|
; Version 1.2 June 07 *
|
|
; Changed left/right button outputs to fake open collector. *
|
|
; Needed to stop conflits when using a joystick pluged into other port. *
|
|
; *
|
|
; Version 1.1 August 04 *
|
|
; Added support for Amiga. *
|
|
; *
|
|
;*****************************************************************************
|
|
|
|
|
|
; list directive to define processor
|
|
list p=16F84A
|
|
|
|
; processor specific variable definitions
|
|
#include <p16F84A.inc>
|
|
|
|
; define config bits
|
|
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
|
|
|
|
;4 MHz Clock
|
|
|
|
;************************ Input output usage ********************
|
|
|
|
; RA0 Atari / Amiga select i/p
|
|
; RA1 PS2 mouse data
|
|
; RA2 PS2 mouse clock
|
|
; RA3 Not used
|
|
; RA4 Not used
|
|
|
|
; RB0 Atari XA / Amiga XA o/p
|
|
; RB1 Atari XB / Amiga YB o/p
|
|
; RB2 Atari YA / Amiga YA o/p
|
|
; RB3 Atari YB / Amiga XB o/p
|
|
; RB4 Left button o/p
|
|
; RB5 Right button o/p
|
|
; RB6 Not used
|
|
; RB7 Not used
|
|
|
|
;*******************************************************************
|
|
|
|
|
|
;********** I/O port equates **************
|
|
|
|
|
|
ps2data equ 1 ;ps2 mouse data signal
|
|
ps2clk equ 2 ;ps2 mouse clock signal
|
|
|
|
|
|
;********** User register equates *********
|
|
|
|
temp equ 0ch ;Temporary storage
|
|
byte1 equ 0dh ;Byte 1 store
|
|
byte2 equ 0eh ;Byte 2 store
|
|
byte3 equ 0fh ;Byte 3 store
|
|
xinc equ 010h ;last x increment read
|
|
yinc equ 011h ;last y increment read
|
|
xlow equ 012h ;low byte of 16 bit x counter
|
|
xhigh equ 013h ;high byte of 16 bit x counter
|
|
ylow equ 014h ;low byte of 16 bit y counter
|
|
yhigh equ 015h ;high byte of 16 bit y counter
|
|
xpat equ 016h ;x pattern position
|
|
ypat equ 017h ;y pattern position
|
|
bcnt equ 018h ;bit counter
|
|
brec equ 019h ;byte received
|
|
timer equ 01ah ;timer counter
|
|
parity equ 01bh ;parity store
|
|
flag equ 01ch ;flag bits (bit 0 = ack error flag)
|
|
; (bit 1 = parity error flag)
|
|
; (bit 2 = middle button pressed flag)
|
|
; (bit 3 = middle state flag)
|
|
; (bit 4 = left button flag)
|
|
|
|
;*****************************************************************************************
|
|
|
|
;***** initialise program *******
|
|
|
|
reset clrwdt
|
|
bcf status,rp0 ;set page0
|
|
clrf intcon ;disable interupts
|
|
bsf status,rp0
|
|
movlw 084h ;set tmr0 to int clk,prescale/32
|
|
movwf option_reg
|
|
bcf status,rp0
|
|
clrf porta ;all porta outputs will be low when enabled
|
|
movlw 0h ;set mouse buttons and x y start levels
|
|
movwf portb
|
|
bsf status,rp0
|
|
movlw 017h ;set porta bit 3 as an unused output
|
|
movwf trisa
|
|
movlw 030h ;set portb bit 4 and 5 as inputs (left/right button o/ps open collector)
|
|
movwf trisb
|
|
bcf status,rp0
|
|
|
|
clrf byte1 ;set start up values
|
|
clrf byte2
|
|
clrf byte3
|
|
clrf xinc
|
|
clrf yinc
|
|
clrf xlow
|
|
clrf xhigh
|
|
clrf ylow
|
|
clrf yhigh
|
|
clrf xpat
|
|
clrf ypat
|
|
clrf flag
|
|
|
|
|
|
;***************** set up ps2 mouse *********************
|
|
|
|
|
|
start call ps2read ;read power up self test report
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movlw 0aah ;correct ?
|
|
subwf brec,w
|
|
btfss status,z
|
|
goto restart ;no so jump
|
|
|
|
call ps2read ;read power up pc mouse id
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movlw 0h ;correct ?
|
|
subwf brec,w
|
|
btfss status,z
|
|
goto restart ;no so jump
|
|
|
|
restart movlw 0ffh ;send reset pc mouse command
|
|
call ps2wri
|
|
btfsc flag,0 ;ack bit?
|
|
goto restart ;no so jump
|
|
|
|
call ps2read ;ack returned
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movlw 0fah ;correct ?
|
|
subwf brec,w
|
|
btfss status,z
|
|
goto restart ;no so jump
|
|
|
|
call ps2read ;read self test report
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movlw 0aah ;correct ?
|
|
subwf brec,w
|
|
btfss status,z
|
|
goto restart ;no so jump
|
|
|
|
call ps2read ;read pc mouse id
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movlw 0h ;correct ?
|
|
subwf brec,w
|
|
btfss status,z
|
|
goto restart ;no so jump
|
|
|
|
movlw 0f4h ;send enable reporting command
|
|
call ps2wri
|
|
btfsc flag,0 ;ack bit?
|
|
goto restart ;no so jump
|
|
|
|
call ps2read ;ack returned
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movlw 0fah ;correct ?
|
|
subwf brec,w
|
|
btfss status,z
|
|
goto restart
|
|
|
|
movlw 0f3h ;send set sample rate command
|
|
call ps2wri
|
|
btfsc flag,0 ;ack bit?
|
|
goto restart ;no so jump
|
|
|
|
call ps2read ;ack returned
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movlw 0fah ;correct ?
|
|
subwf brec,w
|
|
btfss status,z
|
|
goto restart
|
|
|
|
movlw 028h ;send sample rate (40)
|
|
call ps2wri
|
|
btfsc flag,0 ;ack bit?
|
|
goto restart ;no so jump
|
|
|
|
call ps2read ;ack returned
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movlw 0fah ;correct ?
|
|
subwf brec,w
|
|
btfss status,z
|
|
goto restart
|
|
|
|
;******************* Main program loop ****************************
|
|
|
|
main call ps2read ;read 3 byte pc mouse packet
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movf brec,w
|
|
movwf byte1
|
|
call ps2read
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movf brec,w
|
|
movwf byte2
|
|
call ps2read
|
|
btfsc flag,1 ;parity error?
|
|
goto restart ;yes so jump
|
|
movf brec,w
|
|
movwf byte3
|
|
|
|
;adjust the 16 bit x counter
|
|
|
|
clrf temp ;use temp as high byte
|
|
btfsc byte1,4 ;extend sign bit into high byte
|
|
decf temp,f
|
|
|
|
movf byte2,w ;add low bytes
|
|
addwf xlow,f
|
|
btfsc status,c ;add carry to high
|
|
incf xhigh,f
|
|
movf temp,w ;add high bytes
|
|
addwf xhigh,f
|
|
|
|
;adjust the 16 bit y counter
|
|
|
|
clrf temp ;use temp as high byte
|
|
btfsc byte1,5 ;extend sign bit into high byte
|
|
decf temp,f
|
|
|
|
movf byte3,w ;add low bytes
|
|
addwf ylow,f
|
|
btfsc status,c ;add carry to high
|
|
incf yhigh,f
|
|
movf temp,w ;add high bytes
|
|
addwf yhigh,f
|
|
|
|
;left button
|
|
|
|
btfss byte1,0 ;is the left pc mouse button pressed
|
|
goto lbutt ;no so jump
|
|
bsf flag,4 ;set left button flag
|
|
goto nbutt
|
|
lbutt bcf flag,4 ;reset left button flag
|
|
|
|
;right button
|
|
|
|
nbutt btfss byte1,1 ;is the right pc mouse button pressed
|
|
goto rbutt ;no so jump
|
|
bcf portb,5 ;set right button as pressed
|
|
bsf status,rp0 ;by setting pin as a low output
|
|
bcf trisb,5
|
|
bcf status,rp0
|
|
goto mbut
|
|
rbutt bsf status,rp0 ;set right button as not pressed
|
|
bsf trisb,5 ;by setting pin as an input
|
|
bcf status,rp0
|
|
|
|
;middle button
|
|
|
|
mbut btfss byte1,2 ;check if middle button pressed
|
|
goto mbutt ;jump if not
|
|
btfsc flag,2 ;check middle button pressed flag
|
|
goto mbex ;set so jump
|
|
movlw 08h ;toggle middle state flag
|
|
xorwf flag,f
|
|
bsf flag,2 ;set middle button pressed flag
|
|
goto mbex
|
|
|
|
mbutt btfss flag,2
|
|
goto mbex
|
|
bcf flag,2 ;reset middle button pressed flag
|
|
mbex
|
|
|
|
btfsc flag,3 ;check middle state flag
|
|
goto setlb ;jump if set
|
|
btfsc flag,4 ;check left button flag
|
|
goto setlb ;jump if set
|
|
bsf status,rp0 ;no flags set so set left buuton not pressed
|
|
bsf trisb,4 ;by setting pin as an input
|
|
bcf status,rp0
|
|
goto main
|
|
setlb bcf portb,4 ;set left button pressed
|
|
bsf status,rp0 ;by setting pin as a low output
|
|
bcf trisb,4
|
|
bcf status,rp0
|
|
goto main
|
|
|
|
|
|
;***************************** Subs *****************************************
|
|
|
|
;***** Read a byte from the ps2 mouse ******
|
|
|
|
ps2read btfss porta,ps2data ;data low ?
|
|
goto ps2r1 ;yes so start reading data
|
|
call trans ;no so do emulated mouse move
|
|
clrf tmr0 ;clear rtcc before delay
|
|
|
|
oned btfss porta,ps2data ;data low ?
|
|
goto ps2r1 ;yes so start reading data
|
|
movlw 0dh ;delay between emulated mouse moves
|
|
subwf tmr0,w
|
|
btfss status,z
|
|
goto oned ;not done so jump
|
|
goto ps2read ;check again
|
|
|
|
ps2r1 call wlow ;wait until clock goes low for start bit
|
|
|
|
call whigh ;wait until clock is high
|
|
|
|
movlw 08h ;read 8 data bits
|
|
movwf bcnt
|
|
clrf parity ;clear parity counter
|
|
|
|
ps2r2 call wlow ;wait until clock is low
|
|
bcf status,c ;clear carry flag
|
|
btfss porta,ps2data ;data bit set ?
|
|
goto ps2r3 ;no so jump
|
|
incf parity,f ;yes so inc the parity counter
|
|
bsf status,c ;set carry bit
|
|
ps2r3 rrf brec,f ;shift carry into destination
|
|
|
|
call whigh ;wait until clock is high
|
|
|
|
decfsz bcnt,f ;finished the 8 bits?
|
|
goto ps2r2 ;no so do again
|
|
|
|
call wlow ;for the parity bit
|
|
btfsc porta,ps2data ;parity bit set?
|
|
incf parity,f ;yes so inc the parity counter
|
|
bcf flag,1 ;clear flag (no error)
|
|
btfss parity,0 ;check calculated parity
|
|
bsf flag,1 ;set flag (parity error!)
|
|
call whigh
|
|
|
|
call wlow ;for the stop bit
|
|
call whigh
|
|
|
|
return ;and exit
|
|
|
|
;***** Write a byte to the ps2 mouse ******
|
|
|
|
ps2wri movwf brec ;speed not important at this point so
|
|
movwf temp ;calculate parity seperate for sake of
|
|
movlw 08h ;clarity
|
|
movwf bcnt
|
|
clrf parity
|
|
ps2w1 rrf temp,f ;shift bit into carry
|
|
movlw 01h ;preset for bit set
|
|
btfss status,c ;test carry
|
|
clrw ;bit zero so no addition
|
|
addwf parity,f ;update parity
|
|
decfsz bcnt,f ;any more bits to do?
|
|
goto ps2w1 ;yes so jump
|
|
comf parity,f ;only intrested in bit 0.
|
|
;parity bit is complement of bit 0
|
|
|
|
movlw 08h ;bit count to 8
|
|
movwf bcnt
|
|
|
|
call clkl ;set clock low
|
|
|
|
movlw 021h ;wait 100 uS
|
|
movwf temp
|
|
ps2ww decfsz temp,f
|
|
goto ps2ww
|
|
|
|
call datl ;set data low
|
|
nop ;wait 5 uS
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
call clkh ;set clock high
|
|
|
|
ps2w2 call wlow ;wait for clock to go low
|
|
rrf brec,f ;rotate bit into carry for testing
|
|
btfss status,c
|
|
goto ps2w3 ;jump if bit is low
|
|
call dath ;set data high
|
|
goto ps2w4
|
|
ps2w3 call datl ;set data low
|
|
ps2w4 call whigh ;wait for clock to go high
|
|
|
|
decfsz bcnt,f ;any more bits to send?
|
|
goto ps2w2 ;yes so jump
|
|
|
|
call wlow ;wait for clock to go low
|
|
btfss parity,0 ;send parity bit
|
|
goto ps2w5
|
|
call dath
|
|
goto ps2w6
|
|
ps2w5 call datl
|
|
ps2w6 call whigh
|
|
|
|
call wlow ;send stop bit
|
|
call dath
|
|
call whigh
|
|
|
|
call wlow ;read ack from mouse
|
|
bcf flag,0
|
|
btfsc porta,ps2data
|
|
bsf flag,0
|
|
call whigh
|
|
|
|
return
|
|
|
|
|
|
;******* wait for ps2 clock to go low **********
|
|
|
|
wlow btfsc porta,ps2clk
|
|
goto wlow
|
|
return
|
|
|
|
|
|
;******* wait for ps2 clock to go high **********
|
|
|
|
whigh btfss porta,ps2clk
|
|
goto whigh
|
|
return
|
|
|
|
|
|
;******* set ps2 clock low *********************
|
|
|
|
clkl bsf status,rp0
|
|
bcf trisa,ps2clk
|
|
bcf status,rp0
|
|
return
|
|
|
|
|
|
;******* set ps2 clock high ********************
|
|
|
|
clkh bsf status,rp0
|
|
bsf trisa,ps2clk
|
|
bcf status,rp0
|
|
return
|
|
|
|
|
|
;******* set ps2 data low *********************
|
|
|
|
datl bsf status,rp0
|
|
bcf trisa,ps2data
|
|
bcf status,rp0
|
|
return
|
|
|
|
|
|
;******* set ps2 data high *********************
|
|
|
|
dath bsf status,rp0
|
|
bsf trisa,ps2data
|
|
bcf status,rp0
|
|
return
|
|
|
|
|
|
|
|
;********* emulate mouse move ***************************
|
|
|
|
;move the emulated mouse by one step in the x direction if needed
|
|
|
|
trans movf xlow,w ;is the x counter zero?
|
|
iorwf xhigh,w
|
|
btfsc status,z
|
|
goto ymove ;no so jump to y direction
|
|
|
|
btfsc xhigh,7 ;is the x counter positive or negative?
|
|
goto xneg ;jump if negative
|
|
|
|
incf xpat,f ;increment the pattern list position
|
|
movlw 04h ;test if end of pattern list
|
|
subwf xpat,w
|
|
btfsc status,z
|
|
clrf xpat ;end of pattern list so reset
|
|
movlw 0ffh ;subtract 1 from the 16 bit counter by adding ffffh
|
|
addwf xlow,f
|
|
btfsc status,c ;add carry to high byte
|
|
incf xhigh,f
|
|
addwf xhigh,f
|
|
goto ymove ;exit to y direction
|
|
|
|
xneg decf xpat,f ;decrement the pattern list position
|
|
movlw 0ffh ;test if end of pattern list
|
|
subwf xpat,w
|
|
btfss status,z
|
|
goto xno
|
|
movlw 03h ;end of pattern list so reset
|
|
movwf xpat
|
|
xno movlw 01h ;add 1 to the 16 bit counter
|
|
addwf xlow,f
|
|
btfsc status,c ;add carry to high byte
|
|
incf xhigh,f
|
|
|
|
;move the emulated mouse by one step in the y direction if needed
|
|
|
|
ymove movf ylow,w ;is the y counter zero?
|
|
iorwf yhigh,w
|
|
btfsc status,z
|
|
goto out ;no so jump to output pattern
|
|
|
|
btfsc yhigh,7 ;is the y counter positive or negative?
|
|
goto yneg ;jump if negative
|
|
|
|
incf ypat,f ;increment the pattern list position
|
|
movlw 04h ;test if end of pattern list
|
|
subwf ypat,w
|
|
btfsc status,z
|
|
clrf ypat ;end of pattern list so reset
|
|
movlw 0ffh ;subtract 1 from the 16 bit counter by adding ffffh
|
|
addwf ylow,f
|
|
btfsc status,c ;add carry to high byte
|
|
incf yhigh,f
|
|
addwf yhigh,f
|
|
goto out ;exit to output pattern
|
|
|
|
yneg decf ypat,f ;decrement the pattern list position
|
|
movlw 0ffh ;test if end of pattern list
|
|
subwf ypat,w
|
|
btfss status,z
|
|
goto yno
|
|
movlw 03h ;end of pattern list so reset
|
|
movwf ypat
|
|
yno movlw 01h ;add 1 to the 16 bit counter
|
|
addwf ylow,f
|
|
btfsc status,c ;add carry to high byte
|
|
incf yhigh,f
|
|
|
|
;output new x and y patterns
|
|
|
|
out btfsc porta,0 ;test if set for atari
|
|
goto amiga
|
|
|
|
movf xpat,w ;get the x pattern bits
|
|
bsf pclath,1 ;set page 2
|
|
call pattx
|
|
movwf temp ;store the pattern in temp
|
|
movf ypat,w ;get the y pattern bits
|
|
call patty
|
|
clrf pclath ;set page 0
|
|
iorwf temp,f ;store the pattern in temp
|
|
|
|
goto outpat
|
|
|
|
amiga movf xpat,w ;get the x pattern bits
|
|
bsf pclath,1 ;set page 2
|
|
call apatx
|
|
movwf temp ;store the pattern in temp
|
|
movf ypat,w ;get the y pattern bits
|
|
call apaty
|
|
clrf pclath ;set page 0
|
|
iorwf temp,f ;store the pattern in temp
|
|
|
|
outpat movf temp,w ;get patterns
|
|
andlw 0fh ;ensure high nibble stays zero
|
|
movwf portb ;ouput patterns
|
|
|
|
|
|
return
|
|
|
|
|
|
;*************** pattern lists **************
|
|
|
|
org 0200h
|
|
|
|
;atari patterns
|
|
pattx addwf pcl,f
|
|
retlw 0
|
|
retlw 1
|
|
retlw 3
|
|
retlw 2
|
|
|
|
patty addwf pcl,f
|
|
retlw 0
|
|
retlw 4
|
|
retlw 0ch
|
|
retlw 8
|
|
|
|
;amiga patterns
|
|
apatx addwf pcl,f
|
|
retlw 0
|
|
retlw 1
|
|
retlw 9
|
|
retlw 8
|
|
|
|
apaty addwf pcl,f
|
|
retlw 0
|
|
retlw 4
|
|
retlw 6
|
|
retlw 2
|
|
|
|
;*******************************************************************************
|
|
|
|
END
|
|
|
|
|