Files
2023-03-13 08:36:51 +00:00

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