;PC mouse adapter for Amiga computers
;
; use serial Pc mouse on Amiga Computers without Software driver !!
;
; 03.01.96
;
;This Program converts the microsoft and the mouse system format to amiga ones,
;three mouse buttons are supported (mouse system).
;Only hardware, it`s like an original Amiga mouse
;The Xtal frequenzy is 11.0592 Mhz, the TXD line from mouse is with a 20K
;resistor directly with the PIC 16C54 Port connected. Only three other components
;are needed for the voltage conversion: ICL7660 (voltage converter from Harris 
;semiconductor,INTERSIL) and two capacitors with 10µF. The PCB is about 3*4.5cm.
;My PC mouse needs -5V on TXD,5V on RTS and ground. 
;The adapter recognizes mouse protocoll changes automatic. I think it`s easy
;to include the Logitech protokoll but I don`t know it.
;
; see our Amiga Pic Tools Home Page:
;
; http://linux.rz.fh-hannover.de/~duesterb/
; (Pic Simulator, Pic Progger)
;
;Dirk Düsterberg, duesterb@unixserv.rz.fh-hannover.de
;
;Jahnstr.9
;31860 Emmerthal
;Germany
;
;
;thanks to Joannis Petroglou, who made this with his wonderful Tools possibel!



; Microsoft is a registered trademark of Microsoft Corp.
; Mouse Systems is  registered trademark of MSC Technologies, Inc.
; Microchip is a registered trademark of Microchip Technology
; Logitech is a registered trademark too
; This source is copyrighted to Dirk Düsterberg, no trademark






	list p=PIC16C54, r=hex, s=off

	RESET	start


	CBLOCK 08h
	  trycnt			;synctrys, which format?
	  loopcnt			;loop counter
	  bitcnt			;bit counter
	  serbuf			;serial buffer
	  RBbuf				;Port buffer
	ENDC

	CBLOCK	10h
	  byte0				;first received byte
	  byte1				;second received byte and byte 4 (mouse system)
	  byte2				;third received byte and byte 5 (mouse system)
	ENDC

RA	=	5
RB	=	6



#define	RXD	RA,1			;RXD input, bit 1 from Port A

#define	r_b	RBbuf,2			;right mouse button
#define	m_b	RBbuf,4			;middle mouse button
#define	l_b	RBbuf,6			;left mouse button

#define	H	RBbuf,0			;Horizontal Pulses
#define	HQ	RBbuf,5			;Horizontal Quadrature Pulses
#define	V	RBbuf,1			;Vertical Pulses
#define	VQ	RBbuf,7			;Vertical Quadrature Pulses


#define	c	03,0
#define	z	03,2


start	movlw	0
	tris	RB

	movlw	0ffh
	tris	RA

	clrf	RBbuf			;make butoons unpressed
	decf	RBbuf,f

	movf	RBbuf,w			;use Port buffer to prevent read from Port
	movwf	RB

	clrf	trycnt,f











;this is the routine for the microsoft format (3 bytes with 2 buttons)



micro	clrf	trycnt,f
mic	movlw	.4
	subwf	trycnt,w
	btfsc	c
	goto	mouse			;more than 3 trys? jump!
	
	call	rcb			;receive the first byte
	incf	trycnt,f
	
	movf	serbuf,w
	xorlw	11000000b		;invert bit 6 and 7 from working register
	andlw	11000000b		;clr bit 0 to 5 (buttons and coord.)
	btfss	z			;skip if w is zero
	goto	mic			;if not zero -> no match

	movf	serbuf,w		;this is the first received byte
	movwf	byte0

	bsf	m_b			;middle button not supported

	btfsc	serbuf,4		;mov buttons
	bcf	r_b
	btfss	serbuf,4
	bsf	r_b

	btfsc	serbuf,5
	bcf	l_b
	btfss	serbuf,5
	bsf	l_b

	call	rcb			;receive second byte

	
	movlw	10000000b
	xorwf	serbuf,f		;invert bit 7 from buffer
	movf	serbuf,w
	andlw	11000000b		;clr bit 0 to 5 (coord.)
	btfss	z				;skip if w is zero
	goto	mouse			;if not zero -> no match -> mouse format
		
	
	clrf	byte1

	btfss	byte0,0			;mov x6 and x7 coord. to byte1
	bcf	byte1,6
	btfsc	byte0,0
	bsf	byte1,6


	btfss	byte0,1			;mov x6 and x7 coord. to byte1
	bcf	byte1,7
	btfsc	byte0,1
	bsf	byte1,7



	movf	serbuf,w		;set rest of x coord.
	iorwf	byte1,f



	call	rcb			;receive third byte


	movlw	10000000b
	xorwf	serbuf,f		;invert bit 7 from buffer
	movf	serbuf,w
	andlw	11000000b		;clr bit 0 to 5 (coord.)
	btfss	z			;skip if w is zero
	goto	mouse			;if not zero -> no match -> mouse format

	clrf	byte2



	btfss	byte0,2			;mov y6 and y7 coord. to byte2
	bcf	byte2,6
	btfsc	byte0,2
	bsf	byte2,6



	btfss	byte0,3			;mov y6 and y7 coord. to byte2
	bcf	byte2,7
	btfsc	byte0,3
	bsf	byte2,7



	movf	serbuf,w		;set rest of y coord.
	iorwf	byte2,f

	comf	byte2,f			;fix microsoft to mouse protokoll
	incf	byte2,f			;(up and down exchanged)

	clrf	trycnt
	goto	micro



;this is the routine for the mouse system format (5 bytes with 3 buttons)


mouse	movlw	.6
	subwf	trycnt,w
	btfsc	c
	goto	micro			;more than 5 trys? jump micro!

	call	rcb			;get first of five bytes from serial mouse

	incf	trycnt,f		;one more try

;test format #10000lmr (left, middle, right) 

	movf	serbuf,w
	xorlw	10000000b		;invert bit 7 from working register
	andlw	11111000b		;clr bit 0 to 2 (buttons)
	btfss	z			;skip if w is zero
	goto	mouse			;if not zero -> no match
	
	movf	serbuf,w
	movwf	byte0



	call	rcb			;byte1, X-Axis movement data
	movf	serbuf,w
	movwf	byte1

	call	rcb			;byte2, Y-Axis movement data
	movf	serbuf,w
	movwf	byte2
	
	call	rcb			;byte3, X-Axis movement data	
	movf	serbuf,w
	movwf	byte1

	call	rcb			;byte4, Y-Axis movement data
	movf	serbuf,w
	movwf	byte2



	btfss	byte0,0			;convert to Amiga
	bcf	r_b
	btfsc	byte0,0
	bsf	r_b


	btfss	byte0,1
	bcf	m_b
	btfsc	byte0,1
	bsf	m_b


	btfss	byte0,2
	bcf	l_b
	btfsc	byte0,2
	bsf	l_b


	movf	RBbuf,w
	movwf	RB			;use Port buffer to prevent read from Port

	clrf	trycnt			

	goto	mouse







;receive routine, receive 8bits
;loop is done until byte is received




rcb	btfsc	RXD
	goto	rcshift			;startbit ?
	goto	rcb

rcshift	movlw	.8
	movwf	bitcnt

	call	whbit			;wait half bit (middle bit position)

r_it	call	wbit			;wait bit delay

	btfss	RXD			;move RXD into c
	bcf	c
	btfsc	RXD
	bsf	c

	rrf	serbuf,f		;rotate c in serbuf
	decfsz	bitcnt
	goto	r_it			;decrement bit counter (8 bits)
	comf	serbuf			;invert serbuf (RS232 -> TTL)
	call	whbit			;wait a half bit to get out from data area
	retlw	0			;back








;wait routine for one and one half bit for 1200 baud


whbit	movlw	.125
	movwf	loopcnt			;1200
do_hbit	nop
	nop
	nop
	nop
	nop
	nop
	nop
	decfsz	loopcnt
	goto	do_hbit
	retlw	0





;this routine is one bit long, it converts the axe counter to a quadrature
;modulation, every change on V,VQ,H or HQ means a mouse move


wbit	movlw	.45
	movwf	loopcnt			;quad mod is done while bit waiting

x_axe	movf	byte1,w
	btfsc	z
	goto	x_axe0			;byte1 = 0, nothing to do
	btfsc	byte1,7
	goto	_right			;jump if bit
	nop
	nop
	nop
	nop
	nop
left	decf	byte1,f			;decrement byte 1
	btfsc	H
	goto	leftx1			;jmp to x1 if H set
	btfsc	HQ
	goto	left10
	bsf	H			;set H if H and HQ clear
	goto	lback1
leftx1	btfsc	HQ			
	bcf	H			;clr H if H set and HQ set
	btfss	HQ
	bsf	HQ			;set HQ if H set and HQ clear
	goto	lback3
left10	bcf	HQ			;clear HQ if H clear and HQ set
	goto	lback2
x_axe0	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
lback1	nop
lback2	nop
lback3	movf	RBbuf,w
	movwf	RB			;use Port buffer to prevent read from Port
	goto	y_axe

_right	comf	byte1,f			;negate byte1
	incf	byte1,f

	nop
	nop

right	decf	byte1,f
	btfsc	HQ
	goto	right1x			;jmp to 1x if HQ set
	btfsc	H
	goto	right01
	bsf	HQ			;set HQ if H and HQ clear
	goto	rback1
right1x	btfsc	H			
	bcf	HQ			;clrb H if H and HQ set
	btfss	H
	bsf	H			;setb H if H clear and HQ set
	goto	rback3
right01	bcf	H			;clr H if HQ clear and H set
	goto	rback2

rback1	nop
rback2	nop
rback3	movf	RBbuf,w
	movwf	RB			;use Port buffer to prevent read from Port
	comf	byte1,f
	incf	byte1,f

	


y_axe	movf	byte2,w
	btfsc	z
	goto	y_axe0			;byte2 = 0, nothing to do
	btfsc	byte2,7
	goto	_up			;jump if bit
	nop
	nop
	nop
	nop
	nop
down	decf	byte2,f
	btfsc	VQ
	goto	down1x			;jmp to 1x if VQ set
	btfsc	V
	goto	down01
	bsf	VQ			;set VQ if V and VQ clear
	goto	dback1
down1x	btfsc	V			
	bcf	VQ			;clrb V if V and VQ set
	btfss	V
	bsf	V			;setb V if V clear and VQ set
	goto	dback3
down01	bcf	V			;clr V if VQ clear and V set
	goto	dback2
y_axe0	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
dback1	nop
dback2	nop
dback3	movf	RBbuf,w
	movwf	RB			;use Port buffer to prevent read from Port
	goto	done

_up	comf	byte2,f
	incf	byte2,f
	nop
	nop

up	decf	byte2,f
	btfsc	V
	goto	up_x1			;jmp to x1 if V set
	btfsc	VQ
	goto	up_10
	bsf	V			;set V if V and VQ clear
	goto	uback1
up_x1	btfsc	VQ			
	bcf	V			;clr V if V set and VQ set
	btfss	VQ
	bsf	VQ			;set VQ if V set and VQ clear
	goto	uback3
up_10	bcf	VQ			;clear VQ if V clear and VQ set
	goto	uback2
uback1	nop
uback2	nop
uback3	movf	RBbuf,w
	movwf	RB			;use Port buffer to prevent read from Port
	comf	byte2,f
	incf	byte2,f
	
	

done	decfsz	loopcnt
	goto	x_axe
	retlw	0	
