* ------------------------------------------------------------------------- *
* Serial.asm -- Hardware level serial access routines.
* Copyright by Justin V. McCormick 1988
* ------------------------------------------------------------------------- *

	include "macros.i"


serdatr		EQU	$dff018
serdat		EQU	$dff030
intreq		EQU	$dff09C
intena		EQU	$dff09A

CLR_RFB		EQU	$0800
SET_RFB		EQU	$8800

	XLVO	Forbid
	XLVO	Disable
	XLVO	Permit
	XLVO	Enable

* ------------------------------------------------------------------------- *
* SerialRead(buffer, bufsize)
*   UBYTE *buffer;
*   LONG bufsize;
*   
* Reads bufsize bytes from the serial port, puts them in buffer.
* ------------------------------------------------------------------------- *
	xdef	_SerialRead
_SerialRead:
	link	a5,#0
	movem.l	d2-d7/a2-a3,-(sp)

	SYS	Forbid,4
	SYS	Disable

	movea.l	8(a5),a3	;Grab pointer to output buffer
	move.l	12(a5),d7	;Number of bytes to read
	movea.l	#serdatr,a2	;Grab pointer to serial data receive register
	moveq	#0,d0		;Clear out work register
	move.w	#CLR_RFB,intena	;Don't want RFB interrupts to bother us

	move.w	#CLR_RFB,intreq	;Receive buffer not full yet

	moveq	#14,d1
	move.l	#500000,d2	;Max wait for char delay
	move.l	d2,d3		;Set timeout delay

1$
	move.w	(a2),d0		;Grab serdatr info
	btst.l	d1,d0		;Is Receive Buffer Full?
	 bne.s	2$		;Yep
	subq.l	#1,d3
	 bgt.s	1$		;Loop some more
	bra.s	3$		;Max timeout! exit

2$
	move.b	d0,(a3)+	;Stash this byte
	move.w	#CLR_RFB,intreq	;Clear RFB flag
	move.l	d2,d3		;Reset timeout counter

	subq.l	#1,d7		;One more byte done
	 bgt.s	1$		;Grab next one

3$
	SYS	Enable
	SYS	Permit

	movem.l	(sp)+,d2-d7/a2-a3
	unlk	a5
	rts

* ------------------------------------------------------------------------- *
* SerialWrite(buffer, bufsize)
*   UBYTE *buffer;
*   LONG bufsize;
*   
* Writes bufsize bytes from buffer to the serial port.
* ------------------------------------------------------------------------- *
	xdef	_SerialWrite
_SerialWrite:
	link	a5,#0
	movem.l	d2-d7/a2-a3,-(sp)

	movea.l	8(a5),a3	;Grab pointer to input buffer
	move.l	12(a5),d7	;Number of bytes to write
	movea.l	#serdatr,a2	;Grab pointer to serial data receive register
	movea.l	#serdat,a1	;Grab pointer to serial data xmit register

	move.w	#1,intena	;Don't want TBE interrupts to occur
	move.w	#$8001,intreq	;Transmit buffer starts empty

	move.l	#100000,d2	;Max wait for char delay
	move.l	d2,d3		;Set timeout delay
	move.l	#$0100,d0	;Initialize data out

	moveq	#13,d1		;TBE test bit

1$
	move.b	(a3)+,d0	;Grab a byte from the buffer
	move.w	d0,(a1)		;Start sending it

33$
	move.w	(a2),d4		;Grab serdatr info
	btst.l	d1,d4		;Is Transmit buffer empty yet?
	 bne.s	2$		;Yep

	subq.l	#1,d3
	 bgt.s	33$		;Loop some more
	bra.s	3$		;Max timeout! buffer won't empty, so exit

2$
	move.w	#1,intreq	;Clear TBE flag
	move.l	d2,d3		;Reset timeout counter

	subq.l	#1,d7		;One more byte done
	 bgt.s	1$		;Grab next one

3$

	movem.l	(sp)+,d2-d7/a2-a3
	unlk	a5
	rts
	

* ------------------------------------------------------------------------- *
	end
