' USART routines by Eric James and Larry Bradley  January, 2004
' USART support variables 
==================================================================================
Const USART_RXBUF_SIZE = 24                 ' The size of the send and receive 
USART buffer
Dim Banka rxBuf(24)   As uByte              ' The input buffer
Dim Banka rxBufStart As uByte
Dim Banka rxBufCount As uByte

Const USART_TXBUF_SIZE = 24        	' The size of the send and receive USART 
buffer
Dim Banka txBuf(25)  As uByte         ' The output buffer
Dim Banka txBufStart As uByte		' Starting pointer to remove data
Dim Banka txBufCount As uByte     	' # of chars in the buffer at present

Dim Banka UsartStatus   As uByte
Dim txfull 		@ usartStatus.0 As Boolean
Dim rxempty 	@ usartStatus.1 As Boolean
Dim rxOverRun	@ usartStatus.2 As Boolean

Sub ISR() IntHigh
	' <summary>
	'	This ISR handels the following interrupts
	'	<ul>
	'		<li>	USART RX to copy data from the USART to the rxBuf array
	'		<li>	USART TX to send data from the txBuf into the USART
	' </summary>
	
	Dim savedFSR As uInteger	' <var name="savedFSR"> Store FSR's if needed </var>
	Dim nxt As uByte
	If RCIE=1 And RCIF=1 Then	
	
		If rxBufCount >= USART_RXBUF_SIZE Then
			' Argh! No room in the buffer
			' Get the character so the USART doesn't overrun
			WREG = RCREG
			rxOverRun = 1
		Else
			' Get next buffer location, handling wrap if necessary
			nxt = rxBufStart + rxBufCount
			If nxt >= USART_RXBUF_SIZE Then
				nxt = nxt - USART_RXBUF_SIZE
			End If
			rxBuf(nxt) = RCREG				' Get char from USART into buffer
			rxBufCount = rxBufCount + 1		' incr char count
		End If
	End If
	
	
	If TXIE=1 And TXIF=1 Then	
		' USART TX BUFF EMPTY interrupt	
		If txBufCount = 0 Then
			' Nothing to send, just disable the TX interrupt
			TXIE = 0	
		Else
			savedFSR = FSR0
			TXREG = txBuf(txBufStart)
			FSR0 = savedFSR
			txBufCount = txBufCount - 1		
			txBufStart = txBufStart + 1
			' Check for buffer wrap and reset start pointer if necessary
			If txBufStart = USART_TXBUF_SIZE Then	
				txBufStart = 0
			End If
		End If		

	End If
	
End Sub

' 
**********************************************************************************
' Interrupt Driven USART support routines
' 
**********************************************************************************

Sub USARTinit()
	' Enhanced USART Configuration:
	'==============================
	' Mode: Asynchronus
	' Fosc: 4000000
	' Baud: 9600
	' Bits: 8
	' BRGH: High
	' Address Detect: OFF
  	 TXSTA = 0x24
 	 RCSTA = 0x90
 	 BAUDCTL = 0x0		' For an enhance USART device such as the 18F1320
 	 SPBRG = 0x19

	' Initialize the buffer pointers and counters
	' This isn't necessary if RAM is cleared by other means
	txBufStart  = 0
	txBufCount  = 0
	rxBufStart  = 0
	rxBufCount  = 0
	UsartStatus = 0

	RCIE = 1	' turn receive interrupts on
	PEIE = 1	' turn on perepherial interrupts
	GIE  = 1	' turn on global interrupts

End Sub

Function getChar()
	' <summary>
	'	Receive a character from the USART if something is ready, set rxEmpty flag 
to 0<p>
	'	Return 0 if nothing is ready, set rxEmpty flag = 1
	'   Use of the flag rather than the zero char allows you to receive a x'00' 
character
	' </summary>
	
	Dim ret As uByte 
	
	If rxBufCount = 0 Then
		' Nothing to get ... just return a 0
		rxEmpty = 1
		ret = 0
	Else
		ret = rxBuf(rxBufStart)		' Get next char
		
		' Incr buffer pointer, handling wrap if necessary
		rxBufStart = rxBufStart + 1
		If rxBufStart >= USART_RXBUF_SIZE Then
			rxBufStart = 0
		End If
		
		rxBufCount = rxBufCount - 1
		rxEmpty = 0
	End If
	
End Function ret



Function putChar(ch As uByte)
	' <summary>
	'	Place a character in the USART transmit buffer and return a 1<p>
	'	If the buffer is full, then do nothing, and return a 0
	' </summary>
	
	' On entry, txBufStart:   -> next empty buffer location
	'           txBufCount: # of chars in TX buffer
	'
	' If buffer is full, then routine returns a 0, else a 1
	
	Dim RC As uByte
	Dim nxt As uByte
	
	TXIE=0	' Disable TX interrupts while playing with pointers
	
	If txBufCount >= USART_TXBUF_SIZE Then
		' Buffer is full - can't send anything yet
		txFull = 1
		RC = 0
	Else
		nxt = txBufStart + txBufCount		' Next free buffer spot
		If nxt >= USART_TXBUF_SIZE Then
			' Buffer wrap - reset
			nxt = nxt - USART_TXBUF_SIZE
		End If
		txBufCount = txBufCount + 1
		txBuf(nxt) = ch
		RC = 1
		txFull = 0
	End If
	
	
	TXIE=1					' enable transmit interrupts
End Function RC

Sub putString(s As String)
	' <summary>
	'	Place a string in the USART transmit buffer
	' </summary>
	
	FSR2=Addr(s)
	While INDF2<>0
		If putchar(POSTINC2) = 0 Then	
			wreg = POSTDEC2		' reset FSR2 to the unsent char and try again
		End If
	End While
	
End Sub