;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 Ioannes 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






	DEVICE PIC16C54,HS_OSC,WDT_OFF,PROTECT_OFF

	RESET	start



trycnt	=	08h			;synctrys, which format?
loopcnt	=	09h			;loop counter

bitcnt	=	0ah			;bit counter
serbuf	=	0bh			;serial buffer

RBbuf	=	0ch			;Port buffer

RXD	=	RA.1			;RXD input, bit 1 from Port A

byte0	=	10h			;first received byte
byte1	=	11h			;second received byte and byte 4 (mouse system)
byte2	=	12h			;third received byte and byte 5 (mouse system)



r_b	=	RBbuf.2			;right mouse button
m_b	=	RBbuf.4			;middle mouse button
l_b	=	RBbuf.6			;left mouse button

H	=	RBbuf.0			;Horizontal Pulses
HQ	=	RBbuf.5			;Horizontal Quadrature Pulses
V	=	RBbuf.1			;Vertical Pulses
VQ	=	RBbuf.7			;Vertical Quadrature Pulses


start	mov	!RB,#00h
	mov	!RA,#0FFh

	clr	RBbuf			;make butoons unpressed
	dec	RBbuf

	mov	RB,RBbuf		;use Port buffer to prevent read from Port
	
	clr	trycnt











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



micro	clr	trycnt
mic	csb	trycnt,#4
	jmp	mouse			;more than 3 trys? jump!
	
	call	rcb			;receive the first byte
	inc	trycnt
	
	mov	w,serbuf
	xor	w,#11000000b		;invert bit 6 and 7 from working register
	and	w,#11000000b		;clr bit 0 to 5 (buttons and coord.)
	sz				;skip if w is zero
	jmp	mic			;if not zero -> no match

	mov	byte0,serbuf		;this is the first received byte


	setb	m_b			;middle button not supported
	movb	r_b,/serbuf.4		;mov buttons
	movb	l_b,/serbuf.5

	call	rcb			;receive second byte

	
	xor	serbuf,#10000000b	;invert bit 7 from buffer
	mov	w,serbuf
	and	w,#11000000b		;clr bit 0 to 5 (coord.)
	sz				;skip if w is zero
	jmp	mouse			;if not zero -> no match -> mouse format
		
	
	clr	byte1

	movb	byte1.6,byte0.0		;mov x6 and x7 coord. to byte1
	movb	byte1.7,byte0.1

	or	byte1,serbuf		;set rest of x coord.





	call	rcb			;receive third byte

	
	xor	serbuf,#10000000b	;invert bit 7 from buffer
	mov	w,serbuf
	and	w,#11000000b		;clr bit 0 to 5 (coord.)
	sz				;skip if w is zero
	jmp	mouse			;if not zero -> no match -> mouse format

	clr	byte2

	movb	byte2.6,byte0.2		;mov y6 and y7 coord. to byte2
	movb	byte2.7,byte0.3

	or	byte2,serbuf		;set rest of y coord.
	neg	byte2			;fix microsoft to mouse protokoll
					;(up and down exchanged)
	clr	trycnt
	jmp	micro



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


mouse	csb	trycnt,#6
	jmp	micro			;more than 5 trys? jump micro!

	call	rcb			;get first of five bytes from serial mouse

	inc	trycnt			;one more try

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

	mov	w,serbuf
	xor	w,#10000000b		;invert bit 7 from working register
	and	w,#11111000b		;clr bit 0 to 2 (buttons)
	sz				;skip if w is zero
	jmp	mouse			;if not zero -> no match
	
	mov	byte0,serbuf



	call	rcb			;byte1, X-Axis movement data
	mov	byte1,serbuf

	call	rcb			;byte2, Y-Axis movement data
	mov	byte2,serbuf
	
	call	rcb			;byte3, X-Axis movement data	
	mov	byte1,serbuf

	call	rcb			;byte4, Y-Axis movement data
	mov	byte2,serbuf

	movb	r_b,byte0.0		;convert to Amiga
	movb	m_b,byte0.1
	movb	l_b,byte0.2
	mov	RB,RBbuf		;use Port buffer to prevent read from Port

	clr	trycnt			

	jmp	mouse







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




rcb	jb	RXD,rcshift		;startbit ?
	jmp	rcb
rcshift	mov	bitcnt,#8
	call	whbit			;wait half bit (middle bit position)

r_it	call	wbit			;wait bit delay
	movb	c,RXD			;move RXD into c
	rr	serbuf			;rotate c in serbuf
	djnz	bitcnt,r_it		;decrement bit counter (8 bits)
	not	serbuf			;invert serbuf (RS232 -> TTL)
	call	whbit			;wait a half bit to get out from data area
	ret				;back








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


whbit	mov	loopcnt,#125		;1200
do_hbit	nop
	nop
	nop
	nop
	nop
	nop
	nop
	djnz	loopcnt,do_hbit
	ret





;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	mov	loopcnt,#45		;quad mod is done while bit waiting
x_axe	mov	w,byte1
	snz
	jmp	x_axe0			;byte1 = 0, nothing to do
	jb	byte1.7,_right		;jump if bit
	nop
	nop
	nop
	nop
	nop
left	dec	byte1			;decrement byte 1
	snb	H
	jmp	leftx1			;jmp to x1 if H set
	snb	HQ
	jmp	left10
	setb	H			;set H if H and HQ clear
	jmp	lback1
leftx1	snb	HQ			
	clrb	H			;clr H if H set and HQ set
	sb	HQ
	setb	HQ			;set HQ if H set and HQ clear
	jmp	lback3
left10	clrb	HQ			;clear HQ if H clear and HQ set
	jmp	lback2
x_axe0	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
lback1	nop
lback2	nop
lback3	mov	RB,RBbuf		;use Port buffer to prevent read from Port
	jmp	y_axe

_right	neg	byte1

	nop
	nop

right	dec	byte1
	snb	HQ
	jmp	right1x			;jmp to 1x if HQ set
	snb	H
	jmp	right01
	setb	HQ			;set HQ if H and HQ clear
	jmp	rback1
right1x	snb	H			
	clrb	HQ			;clrb H if H and HQ set
	sb	H
	setb	H			;setb H if H clear and HQ set
	jmp	rback3
right01	clrb	H			;clr H if HQ clear and H set
	jmp	rback2

rback1	nop
rback2	nop
rback3	mov	RB,RBbuf		;use Port buffer to prevent read from Port
	neg	byte1

	


y_axe	mov	w,byte2
	snz
	jmp	y_axe0			;byte2 = 0, nothing to do
	jb	byte2.7,_up		;jump if bit
	nop
	nop
	nop
	nop
	nop
down	dec	byte2
	snb	VQ
	jmp	down1x			;jmp to 1x if VQ set
	snb	V
	jmp	down01
	setb	VQ			;set VQ if V and VQ clear
	jmp	dback1
down1x	snb	V			
	clrb	VQ			;clrb V if V and VQ set
	sb	V
	setb	V			;setb V if V clear and VQ set
	jmp	dback3
down01	clrb	V			;clr V if VQ clear and V set
	jmp	dback2
y_axe0	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
dback1	nop
dback2	nop
dback3	mov	RB,RBbuf		;use Port buffer to prevent read from Port
	jmp	done

_up	neg	byte2

	nop
	nop

up	dec	byte2
	snb	V
	jmp	up_x1			;jmp to x1 if V set
	snb	VQ
	jmp	up_10
	setb	V			;set V if V and VQ clear
	jmp	uback1
up_x1	snb	VQ			
	clrb	V			;clr V if V set and VQ set
	sb	VQ
	setb	VQ			;set VQ if V set and VQ clear
	jmp	uback3
up_10	clrb	VQ			;clear VQ if V clear and VQ set
	jmp	uback2
uback1	nop
uback2	nop
uback3	mov	RB,RBbuf		;use Port buffer to prevent read from Port
	neg	byte2
	
	

done	djnz	loopcnt,x_axe
	ret
