;
		; Interrupt based USART1 routines
		;
		; John E. Andrews
		; Feb 24th, 1998
		;
		;**********************************************************************
InitU1	; initialize USART1 
		;**********************************************************************
		;
		; This sets up the peripheral USART1 to provide buffered, line based, 
		;  interrupt driven, transmit and receive. The functions UART1Rx and 
		;  UART1Tx are called from the peripheral interrupt vector.
		;  These functions are terminated by a return to the peripheral isr
		;  which restores context and performs the retfie. 
		; This function, InitU1, and the routine to start interrupt based 
		;  buffer transission, StartTx are called by inline code.
		;
		; ***** Variable and symbol declarations for UART1 *****
		; 
	cblock							; declare bank 0 variables
		u1Flags						; UART1 semaphore flags
	endc
		;
		; bit flag definitions for u1Flags
	RxRdy		equ	0				; new data from UART1 for inline code
	RstRxPtr	equ	1				; isr should reset its buffer pointer
	TxRdy		equ	2				; new data for UART1 from inline code
		;
		; select gpr bank containing Rx buffer, pointers and flags
		movlr	0					; select gpr bank 0
		movlw	rxBuffer-1			; load prestart of Rx buffer
		movwf	rxPtr				;  into Rx buffer pointer
		clrf	u1Flags				; clear all semaphors
		bsf		u1Flags, RstRxPtr	; tell isr to reset Rx pointer
		bcf		u1Flags, RxRdy		; clear data ready flag
		;
		; init peripheral
		movlb	0					; select SFR bank for USART1
		movlw	0x20				; select TxEN, 8 bit, asynch
		movwf	TXSTA1				; for USART1 Tx
		movlw	0x90				; select SPEN, RxEN, continuous Rx
		movwf	RCSTA1				; for USART1 Rx
		movlw	(Dev_Freq/(64*9600))-1	; select 9600 
		movwf	SPBRG1				; for USART1 baud rate
		;
		; init interupts for USART1
		movlb	1					; select sfr bank 1
		bsf		PIE1, RC1IE			; enable Rx int
		return
		;
		;**********************************************************************
UART1Rx	; UART1 receiver interrupt service routine
		;**********************************************************************
		;
		; Receive characters into buffer until CR is received. Then set 
		;  RxRdy bit in u1Flags register to inform inline code that a line 
		;  is ready. Once the inline code has finished with the buffer it sets
		;  RstRxPtr to cause the isr buffer pointer, intRxPtr, to be set equal
		;  to the inline code buffer pointer, rxPtr, it then clears RxRdy
		;  allowing the isr to reset and begin accumulating a new buffer.
		;
		; This function 
		;  must be terminated by a return to the peripheral isr which restores
		;  context and performs the retfie. 
		;
		; The following macro causes this function to be called by the 
		;  peripheral interrupt routine when the RC1IF flag is set. This macro
		;  must be placed immediately following the label at the beginning of 
		;  the isr function and prior to any executable code. 
		;
		;  include bit testing at the peripheral int vector at assembly time
	InstallISR	1, PIR1, RC1IF		; install isr for uart1 rx
		;
		; ***** Variable and symbol declarations for UART1 Rx isr *****
		; 
	rxBufferSize	equ 40			; size of buffer for UART1 Rx data
		;
	cblock							; declare bank 0 variables
		; UART1 Rx buffer, allow extra char for 0 fil by command parser
		rxBuffer:	rxBufferSize+1
		rxPtr						; pointer into Rx buffer used by inline code
		intRxPtr					; pointer into Rx buffer used by isr
	endc
		;
		; ***** Executable code for USRT1 Rx isr *****
		;
		; select gpr bank containing Rx buffer, pointers and flags
		movlr	0					; select gpr bank 0
		; select sfr bank containing UART1 registers
		movlb	0					; select sfr bank 0
		;
		; if buffer has data ready then read Rx data into bit bucket
		btfss	u1Flags, RxRdy		; skip if buffer has whole line ready
		goto	RstRx				; otherwise test for buffer reset
		movfp	RCREG1, WREG		; read Rx data into bit bucket
		return						; return to restore context and exit isr
		;
RstRx	; reset isr uart Rx buffer pointer to equal inline code pointer
		btfss	u1Flags, RstRxPtr	; skip if reset requested
		goto	ReadRx				; otherwise continue to buffer Rx data
		movfp	rxPtr, WREG			; fetch inline buffer ptr
		movwf	intRxPtr			; reset isr Rx pointer
		bcf		u1Flags, RstRxPtr	; clear pointer rst flag
		;
ReadRx	; point to next buffer entry and copy in Rx character
		incf	intRxPtr			; inc isr Rx pointer
		movfp	intRxPtr, FSR0		; load FSR0
		movfp	RCREG1, INDF0		; read Rx data into buffer
		;
		; process special characters
		;
		; if a LF was received echo it then throw it away
		movlw	0x0A				; test for LF
		cpfseq	INDF0				; if equal then skip
		goto	RxNotLF				; otherwise jump to not LF
		movpf	INDF0, TXREG1		; echo it back to the term
		decf	intRxPtr			; backup isr pointer deleting LF
		return						; return to restore context and exit isr
RxNotLF	; if here then character was not LF
		;
		; if a backspace was received then backup
		movlw	0x08				; test for backspace
		cpfseq	INDF0				; if equal skip
		goto	RxNotBS				; otherwise jump to not BS
		decf	intRxPtr			; backup over backspace char
		; this prevents backing up past the beginning of the buffer
		movlw	rxBuffer-1			; load prestart of Rx buffer
		cpfsgt	intRxPtr			; skip if current pointer greater
		return						; return to restore context and exit isr
		decf	intRxPtr			; otherwise backup over prior char
		movpf	INDF0, TXREG1		; and echo it back to the term
		return						; return to restore context and exit isr
RxNotBS	; if here then character was not backspace
		;
		; if a CR was received then pass buffer to inline code
		movlw	0x0D				; test for CR
		cpfseq	INDF0				; if equal then skip
		goto	RxNotCR				; otherwise jump to not CR
		movpf	INDF0, TXREG1		; echo it back to the term
		bsf		u1Flags, RxRdy		; set flag indicating data ready
		return						; return to restore context and exit isr
RxNotCR	; if here then character was not CR
		;
		; character was not LF or backspace or CR, test for last buffer addr
		movlw	rxBuffer+rxBufferSize-1	; load last buffer addr
		cpfseq	intRxPtr			; skip if interrupt pointer is equal
		movpf	INDF0, TXREG1		; otherwise echo it back to the term
		cpfslt	intRxPtr			; skip if interrupt pointer is less than
		; otherwise data was placed in last buffer location and is not a CR
		decf	intRxPtr			; so backup isr pointer
		return						; return to restore context and exit isr
		;
		;**********************************************************************
StartTx	; Kick start UART1 transmitter interrupt service routine
		;**********************************************************************
		;
		; Initialize flags and pointers for interrupt based UART1 transmit
		;  and load first byte of buffer into TXREG1 to start transmit.
		; This function is called by inline code to setup and start UART1 Tx.
		; Exit is accomplished by a return.
		;
		; ***** Variables for UART1 Tx *****
		; 
	cblock							; declare bank 0 variables
		txPtr						; pointer into Tx buffer used by inline code
		intTxPtr					; pointer into Tx buffer used by isr
	endc
		;
		; ***** Executable code for UART1 Tx kick start *****
		; 
		movwf	txPtr				; load output buffer addr into txPtr
		; select sfr bank containing UART1 registers
		movlb	0					; select sfr bank 0
		; wait for any ongoing buffered Tx activity to complete
		btfsc	u1Flags, TxRdy		; skip when Tx buffer empty
		goto	$-1					; until then wait
		; reset isr uart Tx buffer pointer to equal inline code pointer
		movfp	txPtr, WREG			; fetch inline buffer ptr
		movwf	intTxPtr			; reset isr Tx pointer
		movwf	FSR0				; load FSR0
		tstfsz	INDF0				; test for null char
		goto	$+2					; if not null keep going
		return						; otherwise return w/o starting Tx
		bsf		u1Flags, TxRdy		; set flag indicating buffer is ready
		movpf	INDF0, TXREG1		; put first byte into Tx reg
		movlb	1					; select sfr bank 1 for PIE register
		bsf		PIE1, TX1IE			; enable Tx int
		return						; Tx started, return 
		;
		;**********************************************************************
UART1Tx	; UART1 transmitter interrupt service routine
		;**********************************************************************
		;
		; Transmit characters from buffer until 0 or \ is detected. If 0 is
		;  detected then the end of the buffer has been reached, the TxRdy
		;  flag is cleared informing inline code that the buffer is available.
		;  If the \ character is detected then an escape sequence is indicated 
		;  and the next char is interpreted and the control char sent. If the 
		;  next char is not a known escape character then the \ and the char
		;  are output as text.
		;
		; This function 
		;  must be terminated by a return to the peripheral isr which restores
		;  context and performs the retfie. 
		;
		; The following macro causes this function to be called by the 
		;  peripheral interrupt routine when the TX1IF flag is set. This macro
		;  must be placed immediately following the label at the beginning of 
		;  the isr function and prior to any executable code. 
		;
		;  include bit testing at the peripheral int vector at assembly time
	InstallISR	1, PIR1, TX1IF		; install isr for uart1 tx
		;
		; ***** Executable code for UART1 Tx isr *****
		;
		; select gpr bank containing Rx buffer, pointers and flags
		movlr	0					; select gpr bank 0
		; select sfr bank containing UART1 registers
		movlb	0					; select sfr bank 0
		;
		; if buffer has no data ready then exit
		btfss	u1Flags, TxRdy		; skip if buffer holds data
		return						; return to restore context and exit isr
		;
TestTx	; point to next buffer entry
		incf	intTxPtr			; inc isr Tx pointer
		movfp	intTxPtr, FSR0		; load FSR0
		;
		; process special characters
		;
		; test for 0 indicating end of tx buffer data
		tstfsz	INDF0				; is next char 0?
		goto	TxNot0				; if not keep checking
		bcf		u1Flags, TxRdy		; otherwise clear Tx data ready flag
		movlb	1					; select sfr bank 1 for PIE register
		bcf		PIE1, TX1IE			; disable Tx int
		return						; return to restore context and exit isr
TxNot0	; if here then buffer character is not 0
		;
		; test for escape sequence character
		movlw	'\\'				; load escape sequence character
		cpfseq	INDF0				; is next char \?
		goto	WriteTx				; if not write it
		incf	intTxPtr			; otherwise inc isr Tx pointer
		movfp	intTxPtr, FSR0		; load FSR0
		; determine which special character is requested
		cpfseq	INDF0				; is next char also \?
		goto	$+3					; if not keep checking
		movwf	TXREG1				; otherwise output it
		return						; return to restore context and exit isr
		movlw	'a'					; load bell escape character
		cpfseq	INDF0				; is next char a?
		goto	$+4					; if not keep checking
		movlw	0x07				; otherwise load bell character
		movwf	TXREG1				; and output it
		return						; return to restore context and exit isr
		movlw	'b'					; load backspace escape character
		cpfseq	INDF0				; is next char b?
		goto	$+4					; if not keep checking
		movlw	0x08				; otherwise load backspace character
		movwf	TXREG1				; and output it
		return						; return to restore context and exit isr
		movlw	'f'					; load form feed escape character
		cpfseq	INDF0				; is next char f?
		goto	$+4					; if not keep checking
		movlw	0x0C				; otherwise load form feed character
		movwf	TXREG1				; and output it
		return						; return to restore context and exit isr
		movlw	'n'					; load new line escape character
		cpfseq	INDF0				; is next char n?
		goto	$+4					; if not keep checking
		movlw	0x0A				; otherwise load new line character
		movwf	TXREG1				; and output it
		return						; return to restore context and exit isr
		movlw	'r'					; load carriage return escape character
		cpfseq	INDF0				; is next char r?
		goto	$+4					; if not keep checking
		movlw	0x0D				; otherwise load carriage return character
		movwf	TXREG1				; and output it
		return						; return to restore context and exit isr
		movlw	't'					; load tab escape character
		cpfseq	INDF0				; is next char t?
		goto	$+4					; if not keep checking
		movlw	0x09				; otherwise load tab character
		movwf	TXREG1				; and output it
		return						; return to restore context and exit isr
		movlw	'v'					; load vertical tab escape character
		cpfseq	INDF0				; is next char v?
		goto	$+4					; if not keep checking
		movlw	0x0B				; otherwise load vertical tab character
		movwf	TXREG1				; and output it
		return						; return to restore context and exit isr
		; otherwise output \ char and exit
		movlw	'\\'				; load \
		movwf	TXREG1				; and output it
		decf	intTxPtr			; dec isr Tx pointer to prep for next int
		; on next Tx int non-escape char after \ will be output
		return						; return to restore context and exit isr
		; 
WriteTx	; not end of buffer or escape so output next char from buffer
		movpf	INDF0, TXREG1		; write Tx data into buffer
		return						; return to restore context and exit isr

;

Interested:

Questions: