421 lines
9.2 KiB
NASM
421 lines
9.2 KiB
NASM
; ******************************************************************
|
|
; PS/2 Mouse to Amiga/Atari ST Mouse Converter
|
|
; ---------------------------------------------
|
|
;
|
|
; Version: V1.1 (02-Feb-2018)
|
|
; Author : P. Iocco <paolo.iocco@gmail.com>
|
|
; ******************************************************************
|
|
|
|
; ******************************************************************
|
|
; schematic ATARI ST
|
|
;
|
|
; +°--\ /---+
|
|
; -|RA2 RA1|<--|10K|<--+5V (data)
|
|
; -|RA3 RA0|<--|10K|<--+5V (clk)
|
|
; -|RA4 O2|<----RC Oscillator
|
|
; +5V--|50K|-->|RES O1|-
|
|
; GND-------->|5 14|<--------+5V
|
|
; RB DB.9---->|RB0 RB7|-
|
|
; LB DB.6---->|RB1 RB6|-
|
|
; YB DB.4---->|RB2 RB5|-----DB.1 XB
|
|
; YA DB.3---->|RB3 RB4|-----DB.2 XA
|
|
; +---------+
|
|
;
|
|
;
|
|
; ********** Includes **********************************************
|
|
|
|
list p=pic16f84
|
|
__config _CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC ; _RC_OSC
|
|
|
|
INCLUDE "P16F84.INC" ; include le definizioni standard
|
|
|
|
|
|
|
|
W equ 0x00
|
|
F equ 0x01
|
|
STATUS equ 0x03
|
|
PORTA equ 0x05
|
|
PORTB equ 0x06
|
|
RP0 equ 0x05
|
|
Z equ 0x02
|
|
C equ 0x00
|
|
|
|
; ********** register definitions **********************************
|
|
rdbyte equ 0x0c ; byte to receive
|
|
wrbyte equ 0x0e ; byte to write
|
|
parity equ 0x0d ; parity bit is held here
|
|
ps2bit equ 0x0f ; help for 8 data bits to byte conversion
|
|
byte1 equ 0x10 ; 1st byte of mouse data packet
|
|
byte2 equ 0x11 ; 2nd byte of mouse data packet
|
|
byte3 equ 0x12 ; 3rd byte of mouse data packet
|
|
delcnt equ 0x15 ; delay counter
|
|
XB equ 5 ; PORTB,5 --> DB9.1
|
|
XA equ 4 ; PORTB,4 --> DB9.2
|
|
YA equ 3 ; PORTB,3 --> DB9.3
|
|
YB equ 2 ; PORTB,2 --> DB9.4
|
|
LB equ 1 ; PORTB,1 --> Left Button - DB9.6
|
|
RB equ 0 ; Right Button - PORTB,0 --> DB9.9
|
|
CLK equ 0 ; PORTA,0 Clock Pin
|
|
DAT equ 1 ; PORTA,1 Data pin
|
|
|
|
; ******************************************************************
|
|
; ********** main routine ******************************************
|
|
org 0
|
|
|
|
setup:
|
|
BANKSEL TRISA ; page 1
|
|
bcf TRISA,CLK ; port A, bit 0 is output (clk)
|
|
bsf TRISA,DAT ; port A, bit 1 is input (data)
|
|
clrf TRISB ; port B is all outputs
|
|
BANKSEL PORTB ; page 0
|
|
movlw 0xc3 ; Buttons: 1; Positions: 0
|
|
movwf PORTB ; port B all pins to 1
|
|
bcf PORTA,CLK ; inhibit transmission
|
|
|
|
; --------------------------------------------------------
|
|
main:
|
|
;call ReadByte ; Mouse ID
|
|
;movf rdbyte,W
|
|
;sublw 0xaa
|
|
;btfsc STATUS, Z
|
|
;goto errore
|
|
;call ReadByte ; Mouse ID
|
|
;movf rdbyte,W
|
|
;sublw 0x00
|
|
;btfsc STATUS, Z
|
|
;goto errore
|
|
|
|
movlw 0xff ; Reset Mouse
|
|
movwf wrbyte
|
|
call WriteByte
|
|
call ReadByte ; Mouse ack
|
|
movf rdbyte,W
|
|
sublw 0xfa
|
|
btfsc STATUS, Z
|
|
goto errore
|
|
call ReadByte ; Mouse ID
|
|
movf rdbyte,W
|
|
sublw 0xaa
|
|
btfsc STATUS, Z
|
|
goto errore
|
|
call ReadByte ; Mouse ID
|
|
movf rdbyte,W
|
|
sublw 0x00
|
|
btfsc STATUS, Z
|
|
goto errore
|
|
|
|
movlw 0xf0 ; Enter remote mode
|
|
movwf wrbyte
|
|
call WriteByte
|
|
call ReadByte ; Mouse ack
|
|
movf rdbyte,W
|
|
sublw 0xfa
|
|
btfsc STATUS, Z
|
|
goto errore
|
|
|
|
loop:
|
|
movlw 0xeb
|
|
movwf wrbyte
|
|
call WriteByte ; Position Request
|
|
call ReadByte
|
|
movf rdbyte,W
|
|
movf byte1
|
|
call ReadByte
|
|
movf rdbyte,W
|
|
movf byte2
|
|
call ReadByte
|
|
movf rdbyte,W
|
|
movf byte3
|
|
|
|
call CONV
|
|
goto loop
|
|
|
|
errore:
|
|
goto errore
|
|
|
|
; ---- Delay 10us ----
|
|
DEL10:
|
|
nop ; delay 10us
|
|
return
|
|
|
|
; ---- Delay 200us ----
|
|
DEL200:
|
|
movlw 0x05 ; 10us*5+6us
|
|
movwf delcnt
|
|
DEL_L:
|
|
decfsz delcnt
|
|
goto DEL_L
|
|
return
|
|
|
|
; ---- Delay 200us ----
|
|
DEL2P:
|
|
nop ; 1 Cycle= 10us
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
return
|
|
|
|
; ***************************************************************
|
|
; * conversion to Atari/Amiga format *
|
|
; ***************************************************************
|
|
|
|
; ------------- Buttons -----------------------------------------
|
|
CONV:
|
|
btfsc byte1,0 ; left button
|
|
bcf PORTB,LB
|
|
btfss byte1,0
|
|
bsf PORTB,LB
|
|
btfsc byte1,1 ; right button
|
|
bcf PORTB,RB
|
|
btfss byte1,1
|
|
bsf PORTB,RB
|
|
|
|
; ------------- Movement ----------------------------------------
|
|
MOVE:
|
|
movf byte1,W ; overflow X or Y
|
|
andlw 0xC0
|
|
btfss STATUS,Z
|
|
return
|
|
movf byte2,W ; movement conversion
|
|
andlw 0xff
|
|
btfss STATUS,Z
|
|
call MOVEX
|
|
movf byte3,W
|
|
andlw 0xff
|
|
btfss STATUS,Z
|
|
call MOVEY
|
|
return
|
|
MOVEX:
|
|
btfss byte1,4
|
|
goto LEFT
|
|
goto RIGHT
|
|
MOVEY:
|
|
btfss byte1,5
|
|
goto DOWN
|
|
goto UP
|
|
|
|
; ----------------------------------------------------------------
|
|
LEFT:
|
|
call DEL2P ; send H and HQ for left movement
|
|
bsf PORTB,XA ;
|
|
call DEL2P
|
|
bsf PORTB,XB ;
|
|
call DEL2P
|
|
bcf PORTB,XA ;
|
|
call DEL2P
|
|
bcf PORTB,XB ;
|
|
decfsz byte2
|
|
goto LEFT
|
|
return
|
|
; ----------------------------------------------------------------
|
|
RIGHT:
|
|
call DEL2P ; send H and HQ for right movement
|
|
bsf PORTB,XB ;
|
|
call DEL2P
|
|
bsf PORTB,XA ;
|
|
call DEL2P
|
|
bcf PORTB,XB ;
|
|
call DEL2P
|
|
bcf PORTB,XA ;
|
|
incfsz byte2
|
|
goto RIGHT
|
|
return
|
|
; ----------------------------------------------------------------
|
|
UP:
|
|
call DEL2P ; send V and VQ for up movement
|
|
bsf PORTB,YB ;
|
|
call DEL2P
|
|
bsf PORTB,YA ;
|
|
call DEL2P
|
|
bcf PORTB,YB ;
|
|
call DEL2P
|
|
bcf PORTB,YA ;
|
|
incfsz byte3
|
|
goto UP
|
|
return
|
|
; ----------------------------------------------------------------
|
|
DOWN:
|
|
call DEL2P ; send V and VQ for down movement
|
|
bsf PORTB,YA ;
|
|
call DEL2P
|
|
bsf PORTB,YB ;
|
|
call DEL2P
|
|
bcf PORTB,YA ;
|
|
call DEL2P
|
|
bcf PORTB,YB ;
|
|
decfsz byte3
|
|
goto DOWN
|
|
return
|
|
|
|
|
|
; ***************************************************************
|
|
; * PS2 common functions *
|
|
; ***************************************************************
|
|
WaitClockLO:
|
|
btfsc PORTA,CLK
|
|
goto WaitClockLO
|
|
return
|
|
|
|
WaitClockHI:
|
|
btfss PORTA,CLK
|
|
goto WaitClockHI
|
|
return
|
|
|
|
; --------------------------------------------
|
|
; PS2 ReadByte Procedure
|
|
; --------------------------------------------
|
|
ReadByte:
|
|
clrf rdbyte ;ReadByte = 0
|
|
banksel TRISA ;Dir PS2Clock In
|
|
bsf TRISA,0 ;release clock
|
|
call DEL10 ;Wait 25 us
|
|
call DEL10
|
|
banksel ps2bit ;PS2Bit = 0
|
|
clrf ps2bit
|
|
|
|
;Give device time to respond. If no response after 200 us, exit
|
|
WaitMouseAnswer: ;Do While PS2Clock = On
|
|
btfss PORTA,CLK
|
|
goto rdStartBit
|
|
movf ps2bit,W ;If PS2Bit > 200 Then
|
|
sublw 200
|
|
btfss STATUS, C
|
|
goto ReadByteDone ;Goto ReadByteDone
|
|
call DEL10 ;Wait 10 us
|
|
movlw 10 ;PS2Bit += 10
|
|
addwf ps2bit,F
|
|
goto WaitMouseAnswer ;Loop
|
|
|
|
;Start bit
|
|
rdStartBit: ;If PS2Data = ON Then Goto ReadByteDone
|
|
btfsc PORTA,DAT
|
|
goto ReadByteDone ;if not start bit --> discard
|
|
call WaitClockHI ;Wait Until PS2Clock = ON
|
|
clrf ps2bit
|
|
|
|
rdBytesSeq: ;For PS2Bit = 1 to 8
|
|
incf ps2bit,F
|
|
call WaitClockLO ;wait until PS2Clock = OFF
|
|
rrf rdbyte,F ;ROTATE ReadByte RIGHT
|
|
bcf rdbyte,7 ;ReadByte.7 = PS2Data
|
|
btfsc PORTA,DAT
|
|
bsf rdbyte,7
|
|
call WaitClockHI ;wait until PS2Clock = ON
|
|
movlw 8
|
|
subwf ps2bit,W
|
|
btfss STATUS, C
|
|
goto rdBytesSeq ;Next
|
|
|
|
call WaitClockLO ;wait until PS2Clock = OFF
|
|
call WaitClockHI ;wait until PS2Clock = ON
|
|
call WaitClockLO ;wait until PS2Clock = OFF
|
|
call WaitClockHI ;wait until PS2Clock = ON
|
|
|
|
ReadByteDone:
|
|
banksel TRISA ;DIR PS2Clock Out
|
|
bcf TRISA,0
|
|
banksel PORTA ;Set PS2Clock Off
|
|
bcf PORTA,CLK ;inhibit
|
|
call DEL2P ;Wait 200 us
|
|
return
|
|
|
|
; --------------------------------------------
|
|
; PS2 WriteByte Procedure
|
|
; --------------------------------------------
|
|
WriteByte:
|
|
banksel TRISA ;Dir PS2Data Out
|
|
bcf TRISA,DAT
|
|
banksel PORTA ;Set PS2Data Off
|
|
bcf PORTA,DAT
|
|
call DEL10 ;Wait 10 us
|
|
banksel TRISA ;Dir PS2Clock In
|
|
bsf TRISA,CLK
|
|
banksel ps2bit ;PS2Bit = 0
|
|
clrf ps2bit
|
|
|
|
WaitMouseAck: ;Do While PS2Clock = On
|
|
btfss PORTA,CLK
|
|
goto PrepareWrite
|
|
;Wait up to 20 ms for device to pull clock down
|
|
clrf parity
|
|
SysForLoop2:
|
|
incf parity,F
|
|
call DEL10 ;Wait 10 us
|
|
btfss PORTA,CLK ;If PS2Clock = Off Then Exit Do
|
|
goto PrepareWrite
|
|
movlw 10
|
|
subwf parity,W
|
|
btfss STATUS, C
|
|
goto SysForLoop2 ;Next
|
|
incf ps2bit,F ;PS2Bit += 1
|
|
movf ps2bit,W ;If PS2Bit > 200 Then Goto WriteByteDone
|
|
sublw 200
|
|
btfss STATUS, C
|
|
goto WriteByteDone
|
|
goto WaitMouseAck ;Loop
|
|
|
|
PrepareWrite:
|
|
clrf parity ;parity = 0
|
|
clrf ps2bit ;ps2bit = 0
|
|
|
|
WriteBit: ;For PS2Bit = 1 to 8
|
|
incf ps2bit,F
|
|
btfsc wrbyte,0 ;If wrbyte.0 = Off then
|
|
goto write_1
|
|
bcf PORTA,DAT ;Set PS2Data off
|
|
goto rotate
|
|
write_1:
|
|
bsf PORTA,DAT ;Set PS2Data on
|
|
incf parity,F ;PS2Parity += 1
|
|
rotate:
|
|
rrf wrbyte,F ;ROTATE PS2Byte RIGHT
|
|
call WaitClockHI ;Wait until PS2Clock = On
|
|
call WaitClockLO ;wait until PS2Clock = Off
|
|
movlw 8
|
|
subwf ps2bit,W
|
|
btfss STATUS, C
|
|
goto WriteBit ;Next
|
|
|
|
WriteParity:
|
|
btfss parity,0 ;If parity.0 = off then Set PS2Data on
|
|
bsf PORTA,DAT
|
|
btfsc parity,0 ;If parity.0 = on then Set PS2Data off
|
|
bcf PORTA,DAT
|
|
call WaitClockHI ;wait until PS2Clock = On
|
|
call WaitClockLO ;wait until PS2Clock = Off
|
|
|
|
banksel TRISA ;Dir PS2Data In
|
|
bsf TRISA,1
|
|
banksel PORTA
|
|
PS2DatAck: ;Wait Until PS2Data = Off
|
|
btfsc PORTA,DAT
|
|
goto PS2DatAck
|
|
call WaitClockLO ;wait until PS2Clock = OFF
|
|
call WaitClockHI ;wait until PS2Clock = ON
|
|
|
|
WriteByteDone:
|
|
banksel TRISA ;Dir PS2Clock Out
|
|
bcf TRISA,0
|
|
banksel PORTA ;Set PS2Clock Off
|
|
bcf PORTA,CLK
|
|
call DEL2P ;Wait 200 us
|
|
return
|
|
|
|
end
|
|
|