;****************************************************************************
;* Copyright 1991 MBARI                                                     *
;****************************************************************************
;* $Header: ring.s,v 4.4 2001/06/19 12:15:02 oasisa Exp $			    *
;* Summary  : Ring Buffer Routines for OASIS Microcontroller		    *
;* Filename : ring.s							    *
;* Author   : Robert Herlien						    *
;* Project  : OASIS Mooring Controller                                      *
;* $Revision: 4.4 $							    *
;* Created  : 11/10/91							    *
;*									    *
;* MBARI provides this documentation and code "as is", with no warranty,    *
;* express or implied, of its quality or consistency. It is provided without*
;* support and without obligation on the part of the Monterey Bay Aquarium  *
;* Research Institute to assist in its use, correction, modification, or    *
;* enhancement. This information should not be published or distributed to  *
;* third parties without specific written permission from MBARI.            *
;*									    *
;****************************************************************************
;
$TITLE("Ring Buffer Routines")
;
RING		MODULE

$INCLUDE(..\C196\INCLUDE\8096.INC)
$INCLUDE(OASIS.INC)
;
;*****************************************************************************
;
PUBLIC	ring_init		;Init ring buffer function
PUBLIC	ring_flush		;Flush ring buffer function
PUBLIC	ring_put		;Put byte to ring buffer function
PUBLIC	ring_get		;Get byte from ring buffer function
PUBLIC	ring_entries		;Return number of bytes in ring buffer
PUBLIC	ring_getn		;Get multiple bytes from ring buffer


;******************** Ring Buffer Structure *********************************
;
BASE_PTR	EQU	0		;First word is ptr to base of buffer
GET_PTR		EQU	2		;Get pointer - Output to caller
PUT_PTR		EQU	4		;Put pointer - Input from caller
END_PTR		EQU	6		;Pointer to end of buffer + 1

			CSEG

;*****************************************************************************
; RING_INIT - Initialize Ring Buffer
;
; Void ring_init( Ring *ring_ptr, Byte *buffer, Nat16 size );
;
ring_init:
	pushf
	ld	tmp2, 4[SP]
	ld	plmreg, 6[SP]
	st	plmreg, BASE_PTR[tmp2]
	st	plmreg, GET_PTR[tmp2]
	st	plmreg, PUT_PTR[tmp2]
	add	plmreg, 8[SP]
	st	plmreg, END_PTR[tmp2]
	popf
	ret


;*****************************************************************************
; RING_FLUSH - Discard all bytes in Ring Buffer
;
; Void ring_flush( Ring *ring_ptr );
;
ring_flush:
	pushf
	ld	tmp2, 4[SP]
	ld	plmreg, BASE_PTR[tmp2]
	st	plmreg, GET_PTR[tmp2]
	st	plmreg, PUT_PTR[tmp2]
	popf
	ret


;*****************************************************************************
; RING_PUT - Put a byte in ring buffer
;	     Returns number bytes of room left in ring buffer
;	     Zero means no room for byte, error
;
; Int16 ring_put( Ring *ring_ptr, Byte byte )
;

ring_put:
	ld	tmp2, 2[SP]
	ld	plmreg, GET_PTR[tmp2]
	ld	tmp4,  PUT_PTR[tmp2]
	sub	plmreg, tmp4
	jh	rp1
	add	plmreg, END_PTR[tmp2]
	sub	plmreg, BASE_PTR[tmp2]
rp1:
	dec	plmreg
	jle	rp_ret
	ldb	tmp6, 4[SP]
	stb	tmp6, [tmp4]+
	cmp	tmp4, END_PTR[tmp2]
	jnc	rp2
	ld	tmp4, BASE_PTR[tmp2]
rp2:
	st	tmp4, PUT_PTR[tmp2]
rp_ret:
	ret


;*****************************************************************************
; RING_GET - Get a byte from ring buffer
;	     Returns byte fetched, or ERROR if ring empty
;
; Int16 ring_get( Ring *ring_ptr )
;
ring_get:
	ldbse	plmreg, #0ffh
	ld	tmp2, 2[SP]
	ld	tmp4, GET_PTR[tmp2]
	cmp	tmp4, PUT_PTR[tmp2]
	je	rg_ret
	ldbze	plmreg, [tmp4]+
	cmp	tmp4, END_PTR[tmp2]
	jnc	rg1
	ld	tmp4, BASE_PTR[tmp2]
rg1:
	st	tmp4, GET_PTR[tmp2]
rg_ret:
	ret


;*****************************************************************************
; RING_ENTRIES - Return number of bytes in ring buffer
;
; Int16 ring_entries( Ring *ring_ptr )
;
ring_entries:
        ld	tmp2, 2[SP]
        ld	plmreg,PUT_PTR[tmp2]
        sub	plmreg, GET_PTR[tmp2] 
        jc	re1
        add	plmreg, END_PTR[tmp2]
        sub	plmreg, BASE_PTR[tmp2]
re1:
	ret


;*****************************************************************************
; RING_GETN_SUB - Subroutine for ring_getn
;	Move one chunk of ring buffer
;
;	Inputs: tmp2 = Current GET PTR into ring buffer
;		tmp4 = Current PUT PTR into user buffer
;		tmp6 = Size of this chunk of ring buffer
;		8[SP] = size of user request
;		bytesMoved = number of bytes we've already moved
;
;	Output: Adds number of bytes actually moved to bytesMoved
;		Returns updated GET and PUT ptrs
;
ring_getn_sub:
	ld	tmp0, 8[SP]
	sub	tmp0, bytesMoved
	bnh	rgns_ret
	cmp	tmp6, tmp0
	bnh	rgns1
	ld	tmp6, tmp0
rgns1:
	cmp	tmp6, R0
	be	rgns_ret
	add	bytesMoved, tmp6
rgns_loop:
	ldb	tmp0, [tmp2]+
	stb	tmp0, [tmp4]+
	djnzw	tmp6, rgns_loop
rgns_ret:
	ret
	

;*****************************************************************************
; RING_GETN - Get N bytes from ring buffer
;	      Returns number of bytes fetched
;
; Int16 ring_getn( Ring *ring_ptr, Byte *p, Nat16 n )
;
ring_getn:
	ld	tmp0, 2[SP]
	ld	tmp2, GET_PTR[tmp0]
	ld	tmp4, 4[SP]
	st	R0, bytesMoved
	ld	tmp6, PUT_PTR[tmp0]
	sub	tmp6, tmp2
	bc	rgn_topPart
	ld	tmp6, END_PTR[tmp0]
	sub	tmp6, tmp2
	scall	ring_getn_sub
	ld	tmp0, 2[SP]
 	ld	tmp2, BASE_PTR[tmp0]
	st	tmp2, GET_PTR[tmp0]
	ld	tmp6, PUT_PTR[tmp0]
	sub	tmp6, tmp2
rgn_topPart:
	scall	ring_getn_sub
rgn_ret:
	ld	tmp0, 2[SP]
	st	tmp2, GET_PTR[tmp0]
	ld	plmreg, bytesMoved
	ret
	

;*****************************************************************************
;  Scratch registers for ring_getn
;
		RSEG

bytesMoved:	dsw	1

	
	END
