LIST Q = 37		;disables truncation errors
                                                                        
device	SX28,oschs2,turbo,stackx,optionx

freq	50_000_000

IRC_CAL	IRC_FAST

; ** Baud Rates for UART 1 **
U1B1200		;baud rate of 1.2 Kbps

; ** Baud Rates for UART 2  **
U2B9600		;baud rate of 9.6 kbps
	
		id	'2UART VP'		;
		reset	resetEntry		; set reset vector



	;*********************************************************************************************
	;--------------------------------------Macro's------------------------------------------------
	; Macro: _bank
	; Sets the bank appropriately for all revisions of SX.
	;
	; This is required since the bank instruction has only a 3-bit operand, it cannot be used to 
	; access all 16 banks of the SX48/52.  FSR.7 (SX48/52bd production release) needs to be set 
	; appropriately, depending on the bank address being accessed. This macro fixes this.
	;
	; So, instead of using the bank instruction to switch between banks, use _bank instead.
	;*********************************************************************************************

_bank	macro	1
  noexpand
	bank	\1
	
  expand
		clrb	fsr.7
  noexpand

 endm

	;*********************************************************************************************
	; Macro: _mode
	; Sets the MODE register appropriately for all revisions of SX.
	;
	; This is required since the MODE (or MOV M,#) instruction has only a 4-bit operand. 
	; The SX28AC use only 4 bits of the MODE register, however the SX48/52BD have 
	; the added ability of reading or writing some of the MODE registers, and therefore use
	; 5-bits of the MODE register. The  MOV M,W instruction modifies all 8-bits of the 
	; MODE register, so this instruction must be used on the SX48/52BD to make sure the MODE
	; register is written with the correct value. This macro fixes this.
	;
	; So, instead of using the MODE or MOV M,# instructions to load the M register, use
	;  _mode instead.
	;********************************************************************************************* 

_mode	macro	1

  noexpand
	
  expand
		mov	m,#\1    	;loads the M register correctly for the SX18AC, SX20AC
					;and SX28AC
  noexpand

endm

	;*********************************************************************************************
        ; INCP/DECP macros for incrementing/decrementing pointers to RAM
        ; used to compensate for incompatibilities between SX28AC and SX52BD
	;*********************************************************************************************

INCP macro 1				; Increments a pointer to RAM
		
		setb  \1.4		; If SX18 or SX28AC,keep bit 4 of the pointer = 1
					; to jump from $1f to $30,etc
endm

DECP macro 1				; Decrements a pointer to RAM

		clrb   \1.4		; If SX18 or SX28AC, forces rollover to next bank
		dec    \1		; if it rolls over. (skips banks with bit 4 = 0)
		setb   \1.4             ; Eg: $30 ---> $20 ---> $1f ---> $1f 
		                        ; AND: $31 ---> $21 ---> $20 ---> $30
endm

	;*********************************************************************************************
        ; Error generating macros
        ; Used to generate an error message if the label is intentionally moved into the second page.
        ; Use for lookup tables.
	;*********************************************************************************************

tablestart	macro	0		; Generates an error message if code that MUST be in
					; the first half of a page is moved into the second half
	if $ & $100
		ERROR      'Must be located in the first half of a page.'
	endif
endm

tableEnd	macro	0		; Generates an error message if code that MUST be in
					; the first half of a page is moved into the second half

	if $ & $100
		ERROR      'Must be located in the first half of a page.'
	endif
endm

;*********************************************************************************************
;--------------------------------------- Memory Organization ---------------------------------
;*********************************************************************************************

;*********************************************************************************************
;------------------------------- Data Memory address definitions------------------------------
; These definitions ensure the proper address is used for banks 0 - 7 for 2K SX devices
; (SX28) and 4K SX devices (SX48/52). 
;*********************************************************************************************

global_org	=	$08
bank0_org	=	$10
bank1_org	=	$30
bank2_org	=	$50
bank3_org	=	$70
bank4_org	=	$90
bank5_org	=	$B0
bank6_org	=	$D0
bank7_org	=	$F0


;*********************************************************************************************
;-------------------------------- Global Register definitions---------------------------------
; NOTE: Global data memory starts at $0A on SX48/52 and $08 on SX18/20/28.
;*********************************************************************************************

	org     global_org

flags0		equ	global_org + 0		; stores bit-wise operators like flags 
						; and function-enabling bits (semaphores)
;-----------------------------VP: RS232 Receive-----------------------------------------------
rs232Tx1Flag	equ	flags0.0		;indicates that UART1 is transmitting if set or not transmitting if reset
rs232Tx2Flag	equ	flags0.1		;indicates that UART2 is transmitting if set or not transmitting if reset
rs232Rx1Flag	equ	flags0.2		;indicates that UART1 has received a byte if set 
rs232Rx2Flag	equ	flags0.3		;indicates that UART2 has received a byte if set 

isrTemp0	equ	global_org + 1		; Interrupt Service Routine's temp register.  
						; Don't use this register in the mainline.

localTemp0	equ	global_org + 2		; temporary storage register
						; Used by first level of nesting
						; Never guaranteed to maintain data

localTemp1	equ	global_org + 3		; temporary storage register	
						; Used by second level of nesting
						; or when a routine needs more than one 
						; temporary global register.	

localTemp2	equ	global_org + 4		; temporary storage register
						; Used by third level of nesting or by
						; main loop routines that need a loop 
						; counter, etc.

;*********************************************************************************************
;--------------------------- RAM Bank Register definitions------------------------------------
;*********************************************************************************************

	;*********************************************************************************
	; Bank 0
	;*********************************************************************************

		org     bank0_org

bank0		=	$

	;*********************************************************************************
	; Bank 1
	;*********************************************************************************

		org     bank1_org

bank1			=	$
rs232TxBank		=       $	;UART Transmit bank
rs232Tx1High		ds      1	;High Byte to be  transmitted
rs232Tx1Low		ds      1	;Low  Byte to be transmitted
rs232Tx1Count		ds      1	;counter to keep track of the bits sent
rs232Tx1Divide		ds      1	;xmit timing counter
rs232Tx1Byte		ds	1	;store the byte to be sent in this buffer

rs232Tx2High		ds      1	;High Byte to be  transmitted
rs232Tx2Low		ds      1	;Low  Byte to be transmitted
rs232Tx2Count		ds      1	;counter to keep track of the bits sent
rs232Tx2Divide		ds      1	;xmit timing counter
rs232Tx2Byte		ds	1	;store the byte to be sent in this buffer

MultiplexBank		=	$	;Multipler Bank
isrMultiplex 	  	ds      1  	;Used to jump between the ISR Threads when
					; an Interrupt occurs

	;*********************************************************************************
	; Bank 2
	;*********************************************************************************

		org     bank2_org

bank2			=	$
rs232RxBank		=	$

rs232Rx1Count		ds      1	;counter to keep track of the number of bits received
rs232Rx1Divide		ds      1	;receive timing counter
rs232Rx1Byte		ds      1	;buffer for incoming byte
rs232Byte1		ds	1	;Used by serial routines

rs232Rx2Count		ds      1	;counter to keep track of the number of bits received
rs232Rx2Divide		ds      1	;receive timing counter
rs232Rx2Byte		ds      1	;buffer for incoming byte
rs232Byte2		ds	1	;used by serial routines

	;*********************************************************************************
	; Bank 3
	;*********************************************************************************

		org     bank3_org

bank3		=	$

	;*********************************************************************************
	; Bank 4
	;*********************************************************************************

		org     bank4_org

bank4		=	$

	;*********************************************************************************
	; Bank 5
	;*********************************************************************************

		org     bank5_org

bank5		=	$

	;*********************************************************************************
	; Bank 6
	;*********************************************************************************

		org     bank6_org

bank6		=	$

	;*********************************************************************************
	; Bank 7
	;*********************************************************************************

		org     bank7_org

bank7		=	$



;*****************************************************************************************
;---------------------------------- Port Assignment --------------------------------------
;*****************************************************************************************

RA_latch	equ	%00000000		;SX28/48/52 port A latch init ;intial value after reset
RA_DDIR		equ	%11111111		;SX28/48/52 port A DDIR value ;0=Output,1=Input
RA_LVL		equ	%00000000		;SX28/48/52 port A LVL value ;0=CMOS,1=TTL
RA_PLP		equ	%00000000		;SX28/48/52 port A PLP value ;0=Enable,1=Disable

RB_latch	equ	%10001000		;SX28/48/52 port B latch init ;intial value after reset
RB_DDIR		equ	%01110111		;SX28/48/52 port B DDIR value ;0=Output,1=Input
RB_ST		equ	%11111111		;SX28/48/52 port B ST value ;0=Enable,1=Disable
RB_LVL		equ	%00000000		;SX28/48/52 port B LVL value ;0=CMOS,1=TTL
RB_PLP		equ	%11001100		;SX28/48/52 port B PLP value ;0=Enable,1=Disable

RC_latch	equ	%00000000		;SX28/48/52 port C latch init ;intial value after reset
RC_DDIR		equ	%11111111		;SX28/48/52 port C DDIR value ;0=Output,1=Input
RC_ST		equ	%11111111		;SX28/48/52 port C ST value ;0=Enable,1=Disable
RC_LVL		equ	%00000000		;SX28/48/52 port C LVL value ;0=CMOS,1=TTL
RC_PLP		equ	%00000000		;SX28/48/52 port C PLP value ;0=Enable,1=Disable


;*********************************************************************************************
;--------------------------------- Pin Definitions -------------------------------------------
;*********************************************************************************************

rs232Rxpin1      equ     rb.6			;UART1 receive input
rs232Txpin1      equ     rb.7			;UART1 transmit output

rs232Rxpin2      equ     rb.2			;UART2 receive input
rs232Txpin2      equ     rb.3			;UART2 transmit output

;*********************************************************************************************
;---------------------------------- Program constants ----------------------------------------
;*********************************************************************************************

;*********************************************************************************************
;	UART Constants values
;*********************************************************************************************

intPeriod	= -217
UARTfs		= 230400			
	
Num		= 4				; Number of times ISR thread1 is called in the 
						; ISRMultiplexer 
IFDEF  U1B1200
	UARTBaud1	= 1200

UARTDivide1	= (UARTfs/(UARTBaud1*Num))		;48	
UARTStDelay1 	= UARTDivide1 +(UARTDivide1/2)+1

IFDEF  U2B9600
	UARTBaud2	= 9600

UARTDivide2	= (UARTfs/(UARTBaud2*Num))		;6
UARTStDelay2 	= UARTDivide2 +(UARTDivide2/2)+1


;*********************************************************************************************
; SX28AC Mode addresses
; *On SX28, all registers addressed via mode are write only, with the exception of
; CMP and WKPND which do an exchange with W.
;*********************************************************************************************

;------------------------------------------Exchange addresses---------------------------------

CMP		equ	$08		;Exchange Comparator enable/status register with W
WKPND		equ	$09		;Exchange MIWU/RB Interrupts pending with W

;-----------------------------------------Port setup (read) addresses-------------------------

WKED_W		equ	$0A		;Write MIWU/RB Interrupt edge setup, 1 = falling, 0 = rising
WKEN_W		equ	$0B		;Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 = disabled
ST_W		equ	$0C		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
LVL_W		equ	$0D		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
PLP_W		equ	$0E		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
DDIR_W		equ	$0F		;Write Port Direction

ENDIF

;*********************************************************************************************
;--------------------------------- Program memory ORG defines --------------------------------
;*********************************************************************************************

INTERRUPT_ORG		equ	$0	; Interrupt must always start at location zero
RESETENTRY_ORG		equ	$1FB	; The program will jump here on reset
SUBROUTINES_ORG		equ	$200	; The subroutines are in this location
STRINGS_ORG		equ	$300	; The strings are in the location $300
PAGE3_ORG		equ	$400	; Page 3 is empty
MAINPROGRAM_ORG		equ	$600	; The main program is in the lastpage of program memory

;*********************************************************************************************
		org	INTERRUPT_ORG        ; First location in program memory.
;*********************************************************************************************

;*********************************************************************************************
;----------------------------------- Interrupt Service Routine -------------------------------
; Note 1: The interrupt code must always originate at address $0.
;	  Interrupt Frequency = (Cycle Frequency / -(retiw value))  
;	  For example: With a retiw value of -217 and an oscillator frequency 
;	  of 50MHz, this code runs every 4.32us.
; Note 2: Mode Register 'M' is not saved in SX 28 but saved in SX 52 when an Interrupt
;	  occurs. If the code is to run on a SX 28 and 'M' register is used in the ISR, 
;	  then the 'M' register has to be saved at the Start of ISR and restored at the 
;	  End of ISR.
;*********************************************************************************************
		org     $0
interrupt					;3

;*********************************************************************************************
; Interrupt
; Interrupt Frequency = (Cycle Frequency / -(retiw value))  For example:
; With a retiw value of -217 and an oscillator frequency of 50MHz, this code runs
; every 4.32us.
;*********************************************************************************************

;*********************************************************************************************
;--------------------------------------------VP:VP Multitasker--------------------------------
; Virtual Peripheral Multitasker : up to 16 individual threads, each running at the 
; (interrupt rate/16). Change them below:
;Input variable(s): isrmultiplex: variable used to choose threads
;Output variable(s): None,executes the next thread
;Variable(s) affected: isrmultiplex
;Flag(s) affected: None
;Program Cycles: 9 cycles (turbo mode)
;*********************************************************************************************

                _bank          Multiplexbank        ;
                inc            isrMultiplex         ; toggle interrupt rate
                mov            w,isrMultiplex       ;

;*********************************************************************************************
; The code between the tableStart and tableEnd statements MUST be completely within the first
; half of a page. The routines it is jumping to must be in the same page as this table.
;*********************************************************************************************

         tableStart                                 ; Start all tables with this macro
                jmp            pc+w                 ;
                jmp            isrThread1           ;
                jmp            isrThread2           ;
                jmp            isrThread3           ;  
                jmp            isrThread4           ; 
                jmp            isrThread1           ;
                jmp            isrThread5           ;
                jmp            isrThread6           ;  
                jmp            isrThread7           ; 
                jmp            isrThread1           ; 
                jmp            isrThread8           ;
                jmp            isrThread9           ;
                jmp            isrThread10          ;  
                jmp            isrThread1           ; 
                jmp            isrThread11          ; 
                jmp            isrThread12          ;
                jmp            isrThread13          ;
         tableEnd                                   ; End all tables with this macro.   

;*********************************************************************************************
;VP: VP Multitasker
; ISR TASKS
;*********************************************************************************************

isrThread1                                          ; Serviced at ISR rate/4

;*********************************************************************************************
; Virtual Peripheral: Universal Asynchronous Receiver Transmitter (UART) These routines send
; and receive RS232 serial data, and are currently configured (though modifications can be 
; made) for the popular "No parity-checking, 8 data bit, 1 stop bit" (N,8,1) data format.
;
; The VP below has 2 UARTS implemented - UART1 & UART2. Both the UARTs can work at independent 
; Baud Rates.
;
; RECEIVING: The rs232Rx1flag & rs232Rx2flag are set high whenever a valid byte of data has 
; been received and it is the calling routine's responsibility to reset this flag once the
; incoming data has been collected.
;
; TRANSMITTING: The transmit routine requires the data to be inverted and loaded 
; (rs232Txhigh+rs232Txlow) register pair (with the inverted 8 data bits stored in
; rs232Txhigh and rs232Txlow bit 7 set high to act as a start bit). Then the number of bits
; ready for transmission (10=1 start + 8 data + 1 stop) must be loaded into the rs232Txcount
; register. As soon as this latter is done, the transmit routine immediately begins sending
; the data. This routine has a varying execution rate and therefore should always be
; placed after any timing-critical virtual peripherals such as timers,
; adcs, pwms, etc.
; Note: The transmit and receive routines are independent and either may be removed for each
;	of the UARTs. The initial "_bank rs232TxBank" & "_bank rs232RxBank" (common)
;	instruction is kept for Transmit & Receive routines.
;       Input variable(s) : 	rs232Tx1Low (only high bit used), rs232Tx1High, rs232Tx1Count
;				If rs232Tx1Flag SET, then transmit on UART1
;				rs232Tx2Low (only high bit used), rs232Tx2High, rs232Tx2Count
;				If rs232Tx2Flag SET, then transmit on UART2
;       Output variable(s) : 	rs232Rx1Flag, rs232Rx1Byte
;				rs232Rx2Flag, rs232Rx2Byte
;       Variable(s) affected : 	rs232Tx1Divide, rs232Rx1Divide, rs232Rx1Count
;				rs232Tx2Divide, rs232Rx2Divide, rs232Rx2Count
;       Flag(s) affected : 	rs232Tx1Flag, rs232Tx2Flag
;				rs232Rx1Flag, rs232Rx1Flag
;	Program cycles: 	22 worst case for Tx, 23 worst case for Rx
;	Variable Length?  	Yes.
;*********************************************************************************************
UART1
rs232Transmit
		_bank	rs232TxBank		;2 switch to serial register bank
		
		sb 	rs232Tx1FLag		;1
		jmp	rs232Receive1		;1
		decsz	rs232Tx1Divide		;1 only execute the transmit routine
		jmp	rs232Receive1		;1 
		mov	w,#UARTDivide1		;1 load UART1 baud rate (50MHz)
		mov	rs232Tx1Divide,w	;1  
		test    rs232Tx1Count		;1 are we sending?
		snz				;1  
		jmp	rs232Receive1		;1 

:txbit		clc                             ;1 yes, ready stop bit
		rr      rs232Tx1High		;1  and shift to next bit
		rr      rs232Tx1Low		;1  
		dec     rs232Tx1Count		;1 decrement bit counter
		snb	rs232Tx1Low.6		;1 output next bit
		clrb	rs232TxPin1		;1  
		sb	rs232Tx1Low.6		;1  
		setb	rs232TxPin1		;1  
		test    rs232Tx1Count		;1 are we sending?
		snz				;1  
		clrb	rs232Tx1Flag		;1,22

rs232Receive1
		_bank	rs232RxBank		;2
	        sb	rs232RxPin1		;1 get current rx bit
	        clc				;1  
	        snb	rs232RxPin1		;1  
	        stc				;1  
		test    rs232Rx1Count           ;1 currently receiving byte?
		sz				;1  
		jmp	:rxbit                  ;1 if so, jump ahead
		mov     w,#9                    ;1 in case start, ready 9 bits

		mov     rs232Rx1Count,w		;1 it is, so renew bit count
		mov     w,#UARTStDelay1		;1 ready 1.5 bit periods (50MHz)		
		mov     rs232Rx1Divide,w	;1  
:rxbit          decsz	rs232Rx1Divide		;1 middle of next bit?
          	jmp	:rs232RxOut1		;1 
		mov	w,#UARTDivide1		;1 yes, ready 1 bit period (50MHz)
		mov	rs232Rx1Divide,w	;1  
		dec     rs232Rx1Count           ;1 last bit?
		sz                              ;1 if not
		rr      rs232Rx1Byte            ;1  then save bit
		snz                             ;1 if so,
		setb    rs232Rx1Flag           ;1,23  then set flag
:rs232RxOut1

UART2
		_bank	rs232TxBank		;2 switch to serial register bank
		sb	rs232Tx2flag		;1
		jmp	rs232Receive2		;1
		decsz	rs232Tx2Divide		;1 only execute the transmit routine
		jmp	rs232Receive2		;1 
		mov	w,#UARTDivide2		;1 load UART2 baud rate (50MHz)
		mov	rs232Tx2Divide,w	;1  
		test    rs232Tx2Count		;1 are we sending?
		snz				;1
		jmp	rs232Receive2		;1 

:txbit		stc                             ;1 yes, ready stop bit
		rr      rs232Tx2High		;1  and shift to next bit
		rr      rs232Tx2Low		;1  
		dec     rs232Tx2Count		;1 decrement bit counter
		snb	rs232Tx2Low.6		;1 output next bit
		clrb	rs232TxPin2		;1  
		sb	rs232Tx2Low.6		;1  
		setb	rs232TxPin2		;1  
		test    rs232Tx2Count		;1 are we sending?
		snz				;1  
		clrb	rs232Tx2Flag		;1,22

rs232Receive2
		_bank	rs232RxBank		;2
	        sb	rs232RxPin2		;1 get current rx bit
	        clc				;1  
	        snb	rs232RxPin2		;1  
	        stc				;1  
		test    rs232Rx2Count           ;1 currently receiving byte?
		sz				;1  
		jmp	:rxbit                  ;1 if so, jump ahead
		mov     w,#9                    ;1 in case start, ready 9 bits
		sc				;1 skip ahead if not start bit
		mov     rs232Rx2Count,w		;1 it is, so renew bit count
		mov     w,#UARTStDelay2		;1 ready 1.5 bit periods (50MHz)		
		mov     rs232Rx2Divide,w	;1  
:rxbit          decsz	rs232Rx2Divide		;1 middle of next bit?
          	jmp	:rs232RxOut2		;1 
		mov	w,#UARTDivide2		;1 yes, ready 1 bit period (50MHz)
		mov	rs232Rx2Divide,w	;1  
		dec     rs232Rx2Count           ;1 last bit?
		sz                              ;1 if not
		rr      rs232Rx2Byte            ;1  then save bit
		snz                             ;1 if so,
		setb    rs232Rx2Flag           	;1,23  then set flag
:rs232RxOut2

UARTOut

;*********************************************************************************************
;===================================== PUT YOUR OWN VPs HERE==================================
; Virtual Peripheral: 
;
;	Input variable(s): 
;	Output variable(s): 
;	Variable(s) affected: 
;	Flag(s) affected: 
;*********************************************************************************************
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread2					; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread3                                      ; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread4                                      ; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread5                                      ; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread6                                      ; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread7                                      ; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread8                                      ; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread9                                      ; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread10                                     ; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread11                                     ; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread12                                     ; Serviced at ISR rate/16
;---------------------------------------------------------------------------------------------
		jmp		isrOut		; 7 cycles until mainline program resumes execution
;---------------------------------------------------------------------------------------------
isrThread13                                     ; Serviced at ISR rate/16
                                               	; This thread must reload the isrMultiplex register
               _bank	Multiplexbank
                mov	isrMultiplex,#255	;reload isrMultiplex so isrThread1 will be run on the
                                                ; next interrupt.
                jmp	isrOut           	; 7 cycles until mainline program resumes execution
						; This thread must reload the isrMultiplex register
                                                ; since it is the last one to run in a rotation.
;---------------------------------------------------------------------------------------------
isrOut

;*********************************************************************************
; Set Interrupt Rate
;*********************************************************************************

isr_end	
		mov	w,#intPeriod	;refresh RTCC on return
						;(RTCC = 217, no. of instructions executed in the ISR)
		retiw				;return from the interrupt
						
;*****************************************************************************************
; End of the Interrupt Service Routine
;*****************************************************************************************

;*****************************************************************************************
; RESET VECTOR 
;*****************************************************************************************

;*****************************************************************************************
;----------------------------------------Reset Entry------------------------------------
;*****************************************************************************************

	org 	RESETENTRY_ORG

resetEntry					; Program starts here on power-up
   		page 	_resetEntry
		jmp	_resetEntry

;*****************************************************************************************
;-----------------------------------------UART Subroutines--------------------------------
;*****************************************************************************************

	org	SUBROUTINES_ORG

;*****************************************************************************************
; 	Function	: getbyte
; 	INPUTS		: rs232RX1Flag,rs232Rx2Flag
; 	OUTPUTS		: Received byte in rs232Rx1Byte or rs232Rx2Byte
; 	Get byte via serial port and echo it back to the serial port
;*****************************************************************************************
getbyte		

getbyte1	
		_bank	rs232RxBank		; switch to rs232 bank
		sb	rs232RX1Flag		; check if byte has been received by UART1
		jmp	getbyte2
		clrb    rs232Rx1Flag		; reset the receive flag
		mov     w,rs232Rx1Byte		; store byte (copy using W)
		mov	rs232Byte1,w		

getbyte2	sb	rs232Rx2Flag		; check if byte has been received by UART2
		jmp	:out
		clrb    rs232Rx2Flag	
		mov	w,rs232Rx2Byte	
		mov	rs232Byte2,w
:out		retp

;****************************************************************************************
; 	Function	: sendbyte
;	INPUTS		: rs232Tx1Flag set, rs232Tx1Byte - the byte to be sent via UART1
;			  rs232Tx2Flag set, rs232Tx2Byte- the byte to be sent via UART2
; 	OUTPUTS		: Outputs The byte via RS-232 UART1/UART2
; 	Send byte via serial port
;
;	Note: Before calling a sendbyte in Main, it should be ensured that respective 
;	      flag of the UART rs232Tx1Flag/rs232Tx2Flag is CLEAR, and if clear then a
;	      byte can be sent, then the respective UART flag must be SET.		
;****************************************************************************************
sendbyte    

sendbyte1	
		_bank    rs232TxBank
		test	rs232Tx1Count
		sz
		jmp	sendbyte2		

		sb	rs232Tx1Flag
		jmp	sendbyte2
	
 	     	mov	w,rs232Tx1Byte
		not     w			; ready bits (inverse logic)
		mov     rs232Tx1High,w          ; store data byte
		setb    rs232Tx1Low.7           ; set up start bit
		mov     w,#10			; 1 start + 8 data + 1 stop bit
		mov     rs232Tx1Count,w
				
sendbyte2	test	rs232Tx2Count
		sz
		jmp	sendbyte1
			
		sb	rs232Tx2Flag
		jmp	:out
		
		mov	w,rs232Tx2Byte
		not	w
		mov     rs232Tx2High,w          ; store data byte
		setb    rs232Tx2Low.7           ; set up start bit
		mov     w,#10			; 1 start + 8 data + 1 stop bit
		mov     rs232Tx2Count,w
:out		retp                            ; leave and fix page bits

;*********************************************************************************
; 	Function	: sendstring1
;			  Care should be taken that the srings are located within program 
;			  memory locations $300-$3ff as the area 
; 	INPUTS		: 'w', The address of a null-terminated string in program memory
; 	OUTPUTS		: outputs the string via RS-232 UART1
; 			Send string pointed to by address in W register
;	Note:	This routine is a locking routine in the sense that the function returns
;		to 'main' (the calling function) only after all the bytes of the string
;		are transmitted (until 00H is encountered).
;*********************************************************************************
sendstring1	_bank	rs232TxBank
 		mov     localTemp1,w            ; store string address

:string		test	rs232Tx1Count
		sz
		jmp	:string
		
		setb	rs232Tx1Flag		; SET flag for UART1
		mov	w,#STRINGS_ORG>>8	; with indirect addressing
		mov	m,w
		mov     w,localTemp1            ; read next string character
		iread                           ; using the mode register
		test    w                       ; are we at the last char?
		snz                             ; if not=0, skip ahead
		jmp	:out                    ; yes, leave & fix page bits
		_bank	rs232TxBank
		mov	rs232Tx1Byte,w
		call    sendByte1              	; not 0, so send character
		_bank	rs232TxBank
		inc     localTemp1              ; point to next character
		jmp     :string             	; loop until done

:out		clrb	rs232Tx1Flag	
		mov	w,#$1F			; reset the mode register
		mov	m,w
		retp

;*********************************************************************************
; 	Function	: sendstring2
;			  Care should be taken that the srings are located within program 
;			  memory locations $300-$3ff as the area 
; 	INPUTS		: 'w', The address of a null-terminated string in program memory
; 	OUTPUTS		: outputs the string via RS-232 UART2
; 			Send string pointed to by address in W register
;	Note:	This routine is a locking routine in the sense that the function returns
;		to 'main' (the calling function) only after all the bytes of the string
;		are transmitted (until 00H is encountered).
;*********************************************************************************

sendstring2	_bank	rs232TxBank
 		mov     localTemp1,w           ; store string address

:string		test	rs232Tx2Count
		sz
		jmp	:string
		
		setb	rs232Tx2Flag		; SET flag for UART2
		mov	w,#STRINGS_ORG>>8	; with indirect addressing
		mov	m,w
		mov     w,localTemp1            ; read next string character
		iread                           ; using the mode register
		test    w                       ; are we at the last char?
		snz                             ; if not=0, skip ahead
		jmp	:out                    ; yes, leave & fix page bits
		_bank	rs232TxBank
		mov	rs232Tx2Byte,w
		call    sendByte2               ; not 0, so send character
		_bank	rs232TxBank
		inc     localTemp1              ; point to next character
		jmp     :string             	; loop until done

:out		clrb	rs232Tx2Flag
		mov	w,#$1F			; reset the mode register
		mov	m,w
		retp

;******************************************************************************************
org    STRINGS_ORG     ; This label defines where strings are kept in program space.
;******************************************************************************************

;******************************************************************************************
;------------------------------------------ String Data -----------------------------------
;******************************************************************************************

;VP: RS232 Transmit

_welcome	dw	$54, 191, 7, 131, 140, 7, 198, 7, 148, 7, 134, 8, 191, 139, 148, 0
_zero		dw	167, 7, 128, 7, 149, 164, 0
_one		dw	147, 14, 136, 8, 141, 0
_two		dw	8, 191, 162, 0
_three		dw	8, 190, 148, 8, 128, 0
_four		dw	186, 7, 137, 153, 0
_five		dw	186, 157, 166, 0
_six		dw	8, 187, 129, 14, 194, 7, 187, 0
_seven 		dw	8, 187, 7, 131, 166, 131, 141, 0
_eight		dw	154, 4, 191, 0
_nine		dw	141, 14, 157, 141, 0 
_point		dw 	7, 199, 7, 156, 15, 141, 15, 191, 0
_desee		dw	8, 174, 128, 128, 5, 6, 8, 187, 128, 128, 0
_asee		dw	8, 154, 1, 6, 8, 187, 26, 2, 128, 128, 0
_volts		dw	166, 26, 1, 164, 26, 1, 146, 193, 0
_amps		dw	133, 133, 140, 140, 199, 199, 8, 193, 0
_temper		dw	191, 7, 131, 140, 7, 0, 198, 7, 148, 7, 134, 8, 191, 139, 148,0	
_milli		dw	140, 129, 145, 145, 128, 128, 0
_micro		dw	140, 140, 157, 196, 196, 7, 148, 136, 8, 137, 0
_kilo		dw	194, 7, 128, 14, 146, 137, 0
_mega		dw	22, 88, 23, 5,0
_nano		dw	14, 141, 7, 131, 0, 141, 141, 164,0
_hertz		dw	183, 14, 148, 191, 193, 0
_negative	dw	141, 130, 178, 133, 191, 129, 166, 0
_henries	dw	184, 131, 131, 141, 141, 148, 148, 128, 15, 193, 0
_celcius	dw	187, 130, 145, 187, 7, 128, 7, 134, 187, 0
_farad		dw	186, 186, 132, 132, 14, 148, 132, 132, 15, 175, 187, 0
_ohms		dw	164, 140, 15, 193,0
_cap		dw	7, 195, 132, 132, 0, 199, 0, 132, 187, 129, 191, 132, 141, 187, 0

	org	PAGE3_ORG
		jmp	$

;******************************************************************************************
;------------------------------------------ Main Program ----------------------------------
;	 Program execution begins here on power-up or after a reset
;******************************************************************************************

	org	MAINPROGRAM_ORG
     
_resetEntry

;******************************************************************************************
;------------------------------- Initialise all port configuration ------------------------
;******************************************************************************************

		_mode	ST_W			;point MODE to write ST register
		mov     w,#RB_ST            	;Setup RB Schmitt Trigger, 0 = enabled, 1 = disabled
		mov	!rb,w		
		mov     w,#RC_ST            	;Setup RC Schmitt Trigger, 0 = enabled, 1 = disabled
		mov	!rc,w	
 
		_mode	LVL_W			;point MODE to write LVL register
		mov     w,#RA_LVL            	;Setup RA CMOS or TTL levels, 1 = TTL, 0 = CMOS
		mov	!ra,w		 
		mov     w,#RB_LVL            	;Setup RB CMOS or TTL levels, 1 = TTL, 0 = CMOS
		mov	!rb,w		
		mov     w,#RC_LVL            	;Setup RC CMOS or TTL levels, 1 = TTL, 0 = CMOS
		mov	!rc,w	
 
		_mode	PLP_W			;point MODE to write PLP register
		mov     w,#RA_PLP            	;Setup RA Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!ra,w		 
		mov     w,#RB_PLP            	;Setup RB Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!rb,w		
		mov     w,#RC_PLP            	;Setup RC Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!rc,w	

		_mode	DDIR_W			;point MODE to write DDIR register
		mov	w,#RA_DDIR		;Setup RA Direction register, 0 = output, 1 = input		
		mov	!ra,w	
		mov	w,#RB_DDIR		;Setup RB Direction register, 0 = output, 1 = input
		mov	!rb,w			
		mov	w,#RC_DDIR		;Setup RC Direction register, 0 = output, 1 = input
		mov	!rc,w			

		mov     w,#RA_latch          	;Initialize RA data latch
		mov     ra,w		
		mov     w,#RB_latch         	;Initialize RB data latch
		mov     rb,w		
		mov     w,#RC_latch          	;Initialize RC data latch
		mov     rc,w		


;*********************************************************************************************************
;---------------------------------------------Clear all Data RAM locations--------------------------------
;**********************************************************************************************************

					;SX18/20/28 RAM clear routine
		clr	fsr			;reset all ram banks
:zeroRam	sb	fsr.4			;are we on low half of bank?
		setb	fsr.3			; To clear from 08 - Global Registers
		clr	ind			;clear using indirect addressing
		incsz	fsr			;repeat until done
		jmp	:zeroRam


;*********************************************************************************
; Initialize program/VP registers
;*********************************************************************************

		_bank 	rs232TxBank		;select rs232 bank
		mov 	w,#UARTDivide1		;load rs232Tx1Divide with UART1 baud rate
		mov 	rs232Tx1Divide,w
		
		mov 	w,#UARTDivide2		;load rs232Tx1Divide with UART2 baud rate
		mov 	rs232Tx1Divide,w
		
;*********************************************************************************
; Setup and enable RTCC interrupt, WREG register, RTCC/WDT prescaler
;*********************************************************************************

RTCC_ON		=	%10000000		;Enables RTCC at address $01 (RTW hi)
						;*WREG at address $01 (RTW lo) by default
RTCC_ID		=	%01000000		;Disables RTCC edge interrupt (RTE_IE hi)
						;*RTCC edge interrupt (RTE_IE lo) enabled by default
RTCC_INC_EXT	=	%00100000		;Sets RTCC increment on RTCC pin transition (RTS hi)
						;*RTCC increment on internal instruction (RTS lo) is default
RTCC_FE		=	%00010000		;Sets RTCC to increment on falling edge (RTE_ES hi)
						;*RTCC to increment on rising edge (RTE_ES lo) is default
RTCC_PS_ON	=	%00000000		;Assigns prescaler to RTCC (PSA lo)
RTCC_PS_OFF	=	%00001000		;Assigns prescaler to WDT (PSA hi)
PS_000		=	%00000000		;RTCC = 1:2, WDT = 1:1
PS_001		=	%00000001		;RTCC = 1:4, WDT = 1:2
PS_010		=	%00000010		;RTCC = 1:8, WDT = 1:4
PS_011		=	%00000011		;RTCC = 1:16, WDT = 1:8
PS_100		=	%00000100		;RTCC = 1:32, WDT = 1:16
PS_101		=	%00000101		;RTCC = 1:64, WDT = 1:32
PS_110		=	%00000110		;RTCC = 1:128, WDT = 1:64
PS_111		=	%00000111		;RTCC = 1:256, WDT = 1:128

OPTIONSETUP	equ	RTCC_PS_OFF|PS_111	; the default option setup for this program.
		mov	w,#OPTIONSETUP		; setup option register for RTCC interrupts enabled 
		mov	!option,w		; and prescaler assigned to WDT.
		jmp	@mainLoop

;*****************************************************************************************
;-------------------------------------- MAIN PROGRAM CODE --------------------------------
;*****************************************************************************************

mainLoop	
		mov	w, #_welcome
		setb	rs232Tx1Flag
		call	@sendstring2

		jmp 	mainloop1	
mainloop1


		jmp	mainloop1

;*****************************************************************************************
END		;End of program code
;*****************************************************************************************
