;***************************************************************************
;
;	RS232 Test Interface V1.02
;	==========================
;
;	written by Peter Luethi, 26.03.1999, Dietikon, Switzerland
;	http://www.electronic-engineering.ch
;	last update: 16.01.2005
;
;	V1.02:	Fixed copy/paste issue of ISR context store/restore
;		(nobody is perfect): Erroneously erased INTCON,INTF
;		clearing, resulting in endless ISR calling...
;		Re-structured entire ISR and RS232 echo sub-routines
;		(11.04.2004)
;
;	V1.01:	ISR context restore improvements (21.11.1999)
;
;	V1.00:	Initial release (26.3.1999)
;
;	This code and accompanying files may be distributed freely and
;	modified, provided this header with my name and this notice remain
;	intact. Ownership rights remain with me.
;	You may not sell this software without my approval.
;
;	This software comes with no guarantee or warranty except for my
;	good intentions. By using this code you agree to indemnify me from
;	any liability that might arise from its use.
;
;
;	SPECIFICATIONS:
;	===============
;	Processor:			Microchip PIC 16F84A
;	Clock Frequency:		4.00 MHz XT
;	Throughput:			1 MIPS
;	Baud Rate:			depends on the module included
;	Code Size of entire Program:	approx. 235 instruction words
;	Required Hardware:		MAX 232
;
;
;	DESCRIPTION:
;	============
;	Developed and tested on PIC 16F84A, executeable on all interrupt
;	featured PICs.
;	Program handles all aspects of RS232
;		Transmission (Register TXD) and
;		Reception (register RXD) through interrupts (PortB0 IRQ).
;	The microcontroller sends feedback of received characters back to
;	the terminal window.
;
;	Program shows the implementation and function of the modules
;	m_bank.asm, m_wait.asm, and m_rs096.asm on the PIC16F84A.
;
;***************************************************************************

;***** COMPILATION MESSAGES & WARNINGS *****

	ERRORLEVEL -207 	; found label after column 1
	ERRORLEVEL -302 	; register in operand not in bank 0

;***** PROCESSOR DECLARATION & CONFIGURATION *****

	PROCESSOR 16F84A
	#include "p16f84a.inc"
	
	; embed Configuration Data within .asm File.
	__CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC

;***** MEMORY STRUCTURE *****

	ORG     0x00			; processor reset vector
  	goto    MAIN

	ORG     0x04			; interrupt vector
	goto	ISR			; Interrupt Service Routine (ISR)

;***** PORT DECLARATION *****

	#define	TXport	PORTA,0x00	; RS232 output port, could be
	#define	TXtris	TRISA,0x00	; any active push/pull port

;***** CONSTANT DECLARATION *****

	CONSTANT BASE = 0x0C		; base address of user file registers	

;***** REGISTER DECLARATION *****

	FLAGreg	equ	BASE+d'7'
	#define	RSflag	FLAGreg,0x00	; RS232 data reception flag

	TXD	equ	BASE+d'8'	; TX-Data register
	RXD	equ	BASE+d'9'	; RX-Data register

	W_TEMP	equ	BASE+d'10'	; context register (ISR)
	STATUS_TEMP equ	BASE+d'11'	; context register (ISR)
	PCLATH_TEMP equ	BASE+d'12'	; context register (ISR)
	FSR_TEMP equ	BASE+d'13'	; context register (ISR)

;***** INCLUDE FILES *****

	#include "..\..\m_bank.asm"
	#include "..\..\m_wait.asm"
	#include "..\..\m_rs096.asm"	; specify desired RS232 module

;***** MACROS *****

;***** SUB-ROUTINES *****

RSservice 
	SEND	TAB
	SEND	'E'
	SEND	'c'
	SEND	'h'
	SEND	'o'
	SEND	':'
	SEND	TAB
	movfw	RXD		; get RS232 data
	SENDw			; transmit across RS232
	SEND	CR		; Carriage Return
	SEND	LF		; Line Feed
	; end of RS232 service (echo & display)
	bcf	RSflag		; reset RS232 data reception flag
	bsf	INTCON,INTE	; re-enable RB0/INT interrupt
	RETURN

;***** INTERRUPT SERVICE ROUTINE *****

ISR	;************************
	;*** ISR CONTEXT SAVE ***
	;************************

	bcf	INTCON,GIE	; disable all interrupts
	btfsc	INTCON,GIE	; assure interrupts are disabled
	goto	ISR
	movwf	W_TEMP		; context save: W
	swapf	STATUS,W	; context save: STATUS
	movwf	STATUS_TEMP	; context save
	clrf	STATUS		; bank 0, regardless of current bank
	movfw	PCLATH		; context save: PCLATH
	movwf	PCLATH_TEMP	; context save
	clrf	PCLATH		; page zero, regardless of current page
	bcf	STATUS,IRP	; return to bank 0
	movfw	FSR		; context save: FSR
	movwf	FSR_TEMP	; context save
	;*** context save done ***

	;**************************
	;*** ISR MAIN EXECUTION ***
	;**************************
	
	;*** check origin of interrupt ***
	btfsc	INTCON,INTF	; check for RB0/INT interrupt
	goto	_ISR_RS232	; if set, there was a keypad stroke

	; catch-all
	goto	ISRend		; unexpected IRQ, terminate execution of ISR

	;******************************
	;*** RS232 DATA ACQUISITION ***
	;******************************
_ISR_RS232
	; first, disable interrupt source
	bcf	INTCON,INTE	; disable RB0/INT interrupt
	; second, acquire RS232 data
	RECEIVE			; macro of RS232 software reception
	bsf	RSflag		; enable RS232 data reception flag
	goto	_ISR_RS232end	; terminate RS232 ISR properly

	;***********************************
	;*** CLEARING OF INTERRUPT FLAGS ***
	;***********************************
	; NOTE: Below, I only clear the interrupt flags! This does not
	; necessarily mean, that the interrupts are already re-enabled.
	; Basically, interrupt re-enabling is carried out at the end of
	; the corresponding service routine in normal operation mode.
	; The flag responsible for the current ISR call has to be cleared
	; to prevent recursive ISR calls. Other interrupt flags, activated
	; during execution of this ISR, will immediately be served upon
	; termination of the current ISR run.
_ISR_RS232error
	bsf	INTCON,INTE	; after error, re-enable IRQ already here
_ISR_RS232end
	bcf	INTCON,INTF	; clear RB0/INT interrupt flag
	;goto	ISRend		; terminate execution of ISR

	;*****************************************
	;*** ISR TERMINATION (CONTEXT RESTORE) ***
	;*****************************************

ISRend	movfw	FSR_TEMP	; context restore
	movwf	FSR		; context restore
	movfw	PCLATH_TEMP	; context restore
	movwf	PCLATH		; context restore
	swapf	STATUS_TEMP,W	; context restore
	movwf	STATUS		; context restore
	swapf	W_TEMP,F	; context restore
	swapf	W_TEMP,W	; context restore
	RETFIE			; enable global interrupt (INTCON,GIE)

;***** END OF INTERRUPT SERVICE ROUTINE *****


;************** MAIN **************

MAIN	
	clrf	INTCON		; reset interrupts (disable all)	
	RS232init		; RS232 initialization
	clrf	FLAGreg		; initialize all flags

	SEND	CR		; Carriage Return
	SEND	LF		; Line Feed
	SEND	'R'
	SEND	'S'
	SEND	'2'
	SEND	'3'
	SEND	'2'
	SEND	' '
	SEND	'T'
	SEND	'e'
	SEND	's'
	SEND	't'
	SEND	' '
	SEND	'I'
	SEND	'n'
	SEND	't'
	SEND	'e'
	SEND	'r'
	SEND	'f'
	SEND	'a'
	SEND	'c'
	SEND	'e'
	SEND	':'
	SEND	' '
	SEND	'P'
	SEND	'I'
	SEND	'C'
	SEND	'1'
	SEND	'6'
	SEND	'F'
	SEND	'8'
	SEND	'4'
	SEND	' '
	SEND	'c'
	SEND	'o'
	SEND	'n'
	SEND	'n'
	SEND	'e'
	SEND	'c'
	SEND	't'
	SEND	'e'
	SEND	'd'
	SEND	'.'
	SEND	'.'
	SEND	'.'
	SEND	CR		; Carriage Return
	SEND	LF		; Line Feed
	SEND	LF		; Line Feed

LOOP	btfsc	RSflag		; check RS232 data reception flag
	call	RSservice	; if set, call RS232 echo & LCD display routine
	goto	LOOP

	END

