;*****************************************************************************************
;
; Revision History:
;	v1	working single byte echo to the same port.  50mhz at 3x or 75mhz at 4x
;	v2	working 16byte buffers.  code cleanup
;	v3	code tidy-up
;	v4	32byte buffers on uart1 & 2!
;*****************************************************************************************

; uncomment for SX-processor selection
;SX18_20
SX28
IRC_CAL		IRC_FAST

; uncomment to use new board pin-out
JB_NEW_BOARD

;SX18AC or SX20AC device directives for SX-Key
IFDEF SX18_20				
	device	SX18,OSCHS3,turbo,stackx,optionx
ENDIF

;SX28AC device directives for SX-Key		
IFDEF SX28				
	device	SX28,OSCHS3,turbo,stackx,optionx
ENDIF

;freq	75_000_000
freq	50_000_000

; UART1 baud rate selector - uncomment for selection - RS232
UART1_115200
;UART1_57600
;UART1_38400
;UART1_19200

; UART2 baud rate selector - uncomment for selection - RS485
UART2_115200
;UART2_57600
;UART2_38400
;UART2_19200

reset	reset_entry		; set reset vector

;*****************************************************************************************
; Macros
;*****************************************************************************************

;*********************************************************************************
; 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. For this reason FSR.4 (for SX48/52BD/ES)
; or 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
	bank	\1

	IFDEF SX48_52
	  IFDEF SX48_52_ES
	    IF \1 & %00010000		;SX48BD/ES and SX52BD/ES (engineering sample) bank instruction
		setb	fsr.4		;modifies FSR bits 5,6 and 7. FSR.4 needs to be set by software.
	    ENDIF
	  ELSE
	    IF \1 & %10000000		;SX48BD and SX52BD (production release) bank instruction 
		setb	fsr.7		;modifies FSR bits 4,5 and 6. FSR.7 needs to be set by software.
	    ELSE
		clrb	fsr.7
	    ENDIF
	  ENDIF
	ENDIF
	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 SX18/20/28AC 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
	IFDEF SX48_52
		mov	w,#\1		;loads the M register correctly for the SX48BD and SX52BD
		mov	m,w
	ELSE
		mov	m,#\1		;loads the M register correctly for the SX18AC, SX20AC
					;and SX28AC
	ENDIF
	endm

;*****************************************************************************************
; Global Register definitions
;*****************************************************************************************
IFDEF SX48_52
		org     $0A			;global data memory starts at $0A on SX48/52
ELSE
		org     $08			;global data memory starts at $08 on SX18/20/28
ENDIF

data_tx_temp	equ	$0A
data_rx_temp	equ	$0B
delay1		equ	$0C
flags		equ	$0F		; Flags to indicate various things..
active_uart_isr_flag 	equ	flags.0 ; used by isr to switch between uart1 and uart2.

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

;*********************************************************************************
; Bank 0	This bank is used to store the UART variables
;*********************************************************************************
IFDEF SX48_52
		org     $00	;bank 0 address on SX52
ELSE
		org	$10	;bank 0 address on SX28
ENDIF

SERIAL1		=       $	;UART bank 1
tx_high		ds      1	;hi byte to transmit
tx_low		ds      1	;low byte to transmit
tx_count	ds      1	;number of bits sent
tx_divide	ds      1	;xmit timing (/16) counter
rx_count	ds      1	;number of bits received
rx_divide	ds      1	;receive timing counter
rx_byte		ds      1	;buffer for incoming byte
string		ds	1	;used by send_string to store the address in memory
BufferCount	ds	1
BufferHead	ds	1
BufferTail	ds	1
headtemp	ds	1
tailtemp	ds	1
ser_flags	ds	1
rx_flag		equ	ser_flags.1	; Indicates the reception of a bit from the UART


;*********************************************************************************
; Bank 1
;*********************************************************************************
IFDEF SX48_52
		org     $10	;bank 1 address on SX52
ELSE
		org	$30	;bank 1 address on SX28
ENDIF

SERIAL2		=       $	;UART bank 2
; This bank will be used as a mirror of SERIAL1. This bank will contrain all the same registers
; as SERIAL1 as when a bank switch occurs the reqisters are simply an offset.

;*********************************************************************************
; Bank 2
;*********************************************************************************
IFDEF SX48_52
		org     $20	;bank 2 address on SX52
ELSE
		org	$50	;bank 2 address on SX28
ENDIF

bank2		=	$
FIFOA1		ds	16


;*********************************************************************************
; Bank 3
;*********************************************************************************
IFDEF SX48_52
		org     $30	;bank 3 address on SX52
ELSE
		org	$70	;bank 3 address on SX28
ENDIF

bank3		=	$
FIFOA2		ds	16

;*********************************************************************************
; Bank 4
;*********************************************************************************
IFDEF SX48_52
		org     $40	;bank 4 address on SX52
ELSE
		org	$90	;bank 4 address on SX28
ENDIF

bank4		=	$
FIFOB1		ds	16

;*********************************************************************************
; Bank 5
;*********************************************************************************
IFDEF SX48_52
		org     $50	;bank 5 address on SX52
ELSE
		org	$B0	;bank 5 address on SX28
ENDIF

bank5		=	$
FIFOB2		ds	16

;*********************************************************************************
; Bank 6
;*********************************************************************************
IFDEF SX48_52
		org     $60	;bank 6 address on SX52
ELSE
		org	$D0	;bank 6 address on SX28
ENDIF

bank6		=	$


;*********************************************************************************
; Bank 7
;*********************************************************************************
IFDEF SX48_52
		org     $70	;bank 7 address on SX52
ELSE
		org	$F0	;bank 7 address on SX28
ENDIF

bank7		=	$


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

RA_init		equ	%1100		;SX18/20/28/48/52 port A latch init
RA_io		equ	%1100		;SX18/20/28/48/52 port A DDIR value

;IFDEF JB_NEW_BOARD
RB_init		equ	%10000001	;SX18/20/28/48/52 port B latch init
RB_io		equ	%01111000	;SX18/20/28/48/52 port B DDIR value
;ELSE
;    RB_init		equ	%10001000	;SX18/20/28/48/52 port B latch init
;    RB_io		equ	%01110100	;SX18/20/28/48/52 port B DDIR value
;ENDIF

RC_init		equ	%11111111	;SX18/20/28/48/52 port C latch init
RC_io		equ	%11111111	;SX18/20/28/48/52 port C DDIR value

;*********************************************************************************
; Pin Definitions
;*********************************************************************************
;UART1
;rts_pin1	equ	rb.4	;UART 1 RTS input
;cts_pin1	equ	rb.5	;UART 1 CTS output
rx_pin1         equ     rb.6	;UART 1 receive input
tx_pin1         equ     rb.7	;UART 1 transmit output

; LEDs
GreenTrafficLED	equ	ra.0	; GREEN TRI-LED
RedTrafficLED	equ	ra.1	; RED TRI-LED

;IFDEF JB_NEW_BOARD
    ;UART2 - RS485 - NEW BOARD LAYOUT
    tx_pin2         	equ     rb.0	;DI
    RS485DE		equ	rb.1	;DE
    RS485RE		equ	rb.2	;RE
    rx_pin2         	equ     rb.3	;RO
;ELSE
;    ;UART2 - RS485 - OLD BOARD LAYOUT
;    RS485RE		equ	rb.0	;RE 
;    RS485DE		equ	rb.1	;DE
;    rx_pin2         	equ     rb.2	;RX
;    tx_pin2         	equ     rb.3	;TX
;ENDIF

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

; 1/50000000 = 20ns
; 1/75000000 = 13ns
;
; 1/115200 = 8.68us
; 1/115200 = 8.68 / 4 = 1.085us
; 
; 20ns * 108 = 2.16us * 2 = 4.34us (with delay of 2) (2 times oversampling) = 8.68us
; 13ns * 166 = 2.158us * 2 = 4.316us
; 13ns * 83 = 1.07us * 2 = 2.14us (with delay of 4) (4 times oversampling) = (4*) = 8.56us
; 8.68 * 1.5 = 13.02us
; 13.02 / 2.14 = 6.18
; 8.68 / 2.14 =  4.05
;
; 3 * sampleing @ 50mhz
; int = 73
; 
; ***************** ISR ***********************

;int_period		equ	83	; 75mhz
int_period		=	73	; 50mhz

; **************** RS485 **********************

startbytevalue		=	250	; start byte value
stopbytevalue		=	251	; stop byte value
mynetworkaddress	=	1	; network address

; **************** UART1 **********************

IFDEF UART1_19200
	uart1_baud	=	12	;#baud_rate_192
	uart1_st_delay	=	19	;#start_delay_192
ENDIF

IFDEF UART1_38400
	uart1_baud	=	6	;#baud_rate_384
	uart1_st_delay	=	10	;#start_delay_384
ENDIF

IFDEF UART1_57600
	uart1_baud	=	4	;#baud_rate_576
	uart1_st_delay	=	6	;#start_delay_576
ENDIF

IFDEF UART1_115200
	uart1_baud 	=	3	;baud_rate_1152
	uart1_st_delay	=	5	;start_delay_1152
ENDIF

; **************** UART2 **********************

IFDEF UART2_19200
	uart2_baud	=	12	;#baud_rate_192
	uart2_st_delay	=	19	;#start_delay_192
ENDIF

IFDEF UART2_38400
	uart2_baud	=	6	;#baud_rate_384
	uart2_st_delay	=	10	;#start_delay_384
ENDIF

IFDEF UART2_57600
	uart2_baud	=	4	;#baud_rate_576
	uart2_st_delay	=	6	;#start_delay_576
ENDIF

IFDEF UART2_115200
	uart2_baud 	=	3	;baud_rate_1152
	uart2_st_delay	=	5	;start_delay_1152
ENDIF


; *** 115200 baud - 75,000,000 with int=83 (4 times sample)
;baud_rate_115		=	4			;for 115200 baud rate generation
;start_delay_115	=	6

; *** 115200 baud - 50,000,000 with int=73 (3 times sample)
;baud_rate_115		=	3
;start_delay_115	=	5


;*****************************************************************************************
; Interrupt Service Routine
;*****************************************************************************************
; Note: 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.34us.
;*****************************************************************************************
		org     $0
interrupt					;3

;*********************************************************************************
; 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.
; RECEIVING: The rx_flag is 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 (tx_high+tx_low) register pair (with the inverted 8 data bits
; stored in tx_high and tx_low 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 tx_count 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, if not needed, to reduce execution time and memory usage,
;	as long as the initial "BANK serial" (common) instruction is kept.
;
;       Input variable(s) : tx_low (only high bit used), tx_high, tx_count
;       Output variable(s) : rx_flag, rx_byte
;       Variable(s) affected : tx_divide, rx_divide, rx_count
;       Flag(s) affected : rx_flag
;	Size : Transmit - 15 bytes + 1 byte shared with receive code
;		Receive - 20 bytes + 1 byte shared with transmit code
;       Timing For Single UART pass (turbo) : 
;	       Transmit - (a) [not sending] 9 cycles
;			  (b) [sending] 19 cycles
;			  + 1 cycle shared with RX code ("bank" instr.)
;		Receive - (a) [not receiving] 9 cycles
;			  (b) [start receiving] 16 cycles
;			  (c) [receiving, awaiting bit] 13 cycles
;			  (d) [receiving, bit ready] 17 cycles
;*********************************************************************************

		jb	active_uart_isr_flag,do_uart2

do_uart1	setb	active_uart_isr_flag
:transmit	_bank	SERIAL1			;switch to serial register bank
		decsz	tx_divide		;only execute the transmit routine
		jmp	:receive		; 
		mov	w,#uart1_baud		;load UART baud rate (50MHz)
		mov	tx_divide,w		; 
		test    tx_count		;are we sending?
		snz				; 
		jmp	:receive		;
		clc                             ;yes, ready stop bit
		rr      tx_high			; and shift to next bit
		rr      tx_low			; 
		dec     tx_count		;decrement bit counter
		snb	tx_low.6		;output next bit
		clrb	tx_pin1			; 
		sb	tx_low.6		; 
		setb	tx_pin1			; 
:receive        sb	rx_pin1			;get current rx bit
	        clc				; 
	        snb	rx_pin1			; 
	        stc				; 
		test    rx_count                ;currently receiving byte?
		sz				; 
		jmp	:rxbit                  ;if so, jump ahead
		mov     w,#9                    ;in case start, ready 9 bits
		sc				;skip ahead if not start bit
		mov     rx_count,w              ;it is, so renew bit count
		mov     w,#uart1_st_delay	;ready 1.5 bit periods (50MHz)
		mov     rx_divide,w		; 
:rxbit          decsz	rx_divide		;middle of next bit?
          	jmp	:rxdone			;
		mov	w,#uart1_baud		;yes, ready 1 bit period (50MHz)
		mov	rx_divide,w		; 
		dec     rx_count                ;last bit?
		sz                              ;if not
		rr      rx_byte                 ; then save bit
		snz                             ;if so,
		setb    rx_flag                 ; then set flag
:rxdone						; else, exit

		jnb	rx_flag,isr_end		;

		mov	data_rx_temp,rx_byte	;
		clrb	rx_flag			;

		snb  	buffercount.5           ; If FIFO is "full", no action
		jmp	isr_end			;
		jb	bufferhead.4,:fifoA2	;

	  	mov  	w, #FIFOA1              ; Indirectly address the FIFO-Buffer
	  	add  	w, bufferHead           ;   using the Head pointer
	  	mov  	fsr, w			;
	  	mov  	ind, data_rx_temp       ; Save the value to the FIFO
		_bank	SERIAL1			;
		jmp	:writeend		;

:fifoA2
		mov	headtemp,bufferhead	;
		clrb	bufferhead.4		; clear the 16
	  	mov  	w, #FIFOA2              ; Indirectly address the FIFO-Buffer
		add	w,bufferhead		;
	  	mov  	fsr, w			;
	  	mov  	ind, data_rx_temp       ; Save the value to the FIFO
		_bank	SERIAL1			;
		mov	bufferhead,headtemp	;

:writeend
	 	inc  	bufferHead              ; Point Head to next free storage
	  	clrb 	bufferHead.5            ; If Head = 32, "circle" around to 0
	  	inc  	buffercount             ; Increment the item count

		jmp	isr_end


do_uart2	clrb	active_uart_isr_flag
:transmit	_bank	SERIAL2			;switch to serial register bank
		decsz	tx_divide		;only execute the transmit routine
		jmp	:receive		; 
		mov	w,#uart2_baud		;load UART baud rate (50MHz)
		mov	tx_divide,w		; 
		test    tx_count		;are we sending?
		snz				; 
		jmp	:receive		;
		clc                             ;yes, ready stop bit
		rr      tx_high			; and shift to next bit
		rr      tx_low			; 
		dec     tx_count		;decrement bit counter
		snb	tx_low.6		;output next bit
		clrb	tx_pin2			; 
		sb	tx_low.6		; 
		setb	tx_pin2			; 
:receive        sb	rx_pin2			;get current rx bit
	        clc				; 
	        snb	rx_pin2			; 
	        stc				; 
		test    rx_count                ;currently receiving byte?
		sz				; 
		jmp	:rxbit                  ;if so, jump ahead
		mov     w,#9                    ;in case start, ready 9 bits
		sc				;skip ahead if not start bit
		mov     rx_count,w              ;it is, so renew bit count
		mov     w,#uart2_st_delay	;ready 1.5 bit periods (50MHz)
		mov     rx_divide,w		; 
:rxbit          decsz	rx_divide		;middle of next bit?
          	jmp	:rxdone			;
		mov	w,#uart2_baud		;yes, ready 1 bit period (50MHz)
		mov	rx_divide,w		; 
		dec     rx_count                ;last bit?
		sz                              ;if not
		rr      rx_byte                 ; then save bit
		snz                             ;if so,
		setb    rx_flag                 ; then set flag
:rxdone						; else, exit
	
		jnb	rx_flag,isr_end		;

		mov	data_rx_temp,rx_byte	;
		clrb	rx_flag			;

		snb  	buffercount.5           ; If FIFO is "full", no action
		jmp	isr_end			;
		jb	bufferhead.4,:fifoB2	;
	
	  	mov  	w, #FIFOB1              ; Indirectly address the FIFO-Buffer
	  	add  	w, bufferHead           ;   using the Head pointer
	  	mov  	fsr, w			;
	  	mov  	ind, data_rx_temp       ; Save the value to the FIFO
		_bank	SERIAL2			;
		jmp	:writeend		;

:fifoB2
		mov	headtemp,bufferhead	;
		clrb	bufferhead.4		; clear the 16
	  	mov  	w, #FIFOB2              ; Indirectly address the FIFO-Buffer
		add	w,bufferhead		;
	  	mov  	fsr, w			;
	  	mov  	ind, data_rx_temp       ; Save the value to the FIFO
		_bank	SERIAL2			;
		mov	bufferhead,headtemp	;

:writeend
	 	inc  	bufferHead              ; Point Head to next free storage
	  	clrb 	bufferHead.5            ; If Head = 32, "circle" around to 0
	  	inc  	buffercount             ; Increment the item count

;*********************************************************************************
; Set Interrupt Rate
;*********************************************************************************
isr_end		mov	w,#-int_period		;refresh RTCC on return
		retiw				;return from the interrupt
						; = 1/(int_period*RTCC prescaler*1/50MHz)
						; = 1/(217*1*20ns) = 4.34us
;*********************************************************************************
; End of the Interrupt Service Routine
;*********************************************************************************

;*********************************************************************************
; RESET VECTOR 
;*********************************************************************************
;*********************************************************************************
; Program execution begins here on power-up or after a reset
;*********************************************************************************
reset_entry		
;*********************************************************************************
; Initialise all port configuration
;*********************************************************************************

		_mode	$0f			; point MODE to write DDIR
						;*(5-bit value used to ensure correct value
						; for SX48/52, only 4-bits of this value are
						; used on SX18/20/28)
		mov     w,#RA_init            	; Initialize data latches for
		mov     ra,w			; port A.
		mov	w,#RA_io		; Initialize data direction register for		
		mov	!ra,w			; port A.
		mov     w,#RB_init          	; Initialize data latches for
		mov     rb,w			; port B.
		mov	w,#RB_io		; Initialize data direction register for
		mov	!rb,w			; port B.

IFDEF SX28
		mov     w,#RC_init          	; Initialize data latches for
		mov     rc,w			; port C.
		mov	w,#RC_io		; Initialize data direction register for
		mov	!rc,w			; port C.
ENDIF

;*********************************************************************************
; Clear all Data RAM locations
;*********************************************************************************
		clr	fsr			;reset all ram banks
:zero_ram	sb	fsr.4			;are we on low half of bank?
		setb	fsr.3			;If so, don't touch regs 0-7
		clr	ind			;clear using indirect addressing
		incsz	fsr			;repeat until done
		jmp	:zero_ram

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


;*********************************************************************************
; 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 RTCC (PSA lo)
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

mov	w,#RTCC_ON | RTCC_PS_OFF	;setup option register
mov	!option,w
jmp	@main

;*****************************************************************************************
; MAIN PROGRAM CODE 
;*****************************************************************************************
main

;		_bank	SERIAL1
;		mov	w,#_hello		; Send greating to user on UART
;		call	@send_string
;		mov	w,#_instructions	; Send instructions
;		call	@send_string

;		_bank	SERIAL2
;		mov	w,#_hello		; Send greating to user on UART
;		call	@send_string
;		mov	w,#_instructions	; Send instructions
;		call	@send_string

		clrb	RS485RE
		setb	RS485DE


testBuffer1	_bank	SERIAL1			; Select UART port 1
		test	buffercount
		sz
		jmp	@senddataserial1

testBuffer2	_bank	SERIAL2			; Select UART port 2
		test	buffercount
		sz
		jmp	@senddataserial2

		jmp	testBuffer1

org	$300
;*****************************************************************************************
; String data (for RS-232 output)
;*****************************************************************************************
_hello          dw      'SX UART Demo',0
_instructions	dw	13,10,'Enter some characters and they will be echod to your terminal',13,10,'>',0
_enter_hex	dw	13,10,' Enter Value : ',0

;*****************************************************************************************
; senddataserial1
;*****************************************************************************************
senddataserial1

		_bank	SERIAL1			;

	  	test 	buffercount             ; If FIFOCnt = 0, the
	  	snz                           	;  FIFO is "empty",
		jmp	@testbuffer2           	;  no action
		jb	buffertail.4,:fifoA2	;

	  	mov  	w, #FIFOA1              ; Indirectly address the FIFO-Puffer
	  	add  	w, bufferTail           ;  using the Head pointer 
	  	mov  	fsr, w                  ; 
	  	mov  	data_tx_temp, ind       ; Read the value from the FIFO
		_bank	SERIAL1			;
		jmp	:readend		;

:fifoA2
		mov	tailtemp,buffertail	;
		clrb	buffertail.4		;
	  	mov  	w, #FIFOA2              ; Indirectly address the FIFO-Puffer
	  	add  	w, bufferTail           ;  using the Head pointer 
	  	mov  	fsr, w                  ; 
	  	mov  	data_tx_temp, ind       ; Read the value from the FIFO
		_bank	SERIAL1			;
		mov	buffertail,tailtemp	;

:readend
	  	inc  	bufferTail              ; Set Tail to next location
	  	clrb 	bufferTail.5            ; If Tail = 16, "circle" around to 0
	  	dec  	buffercount             ; Decrement the item count

		_bank	SERIAL2
		mov	w,data_tx_temp		;
		call	@send_byte		;

		_bank	SERIAL1			;
		test	buffercount		; keep sending till buffer empty
		sz				;
		jmp	senddataserial1		;

		jmp	@testBuffer2



;*****************************************************************************************
; senddataserial2
;*****************************************************************************************
senddataserial2

		_bank	SERIAL2			;

	  	test 	buffercount             ; If FIFOCnt = 0, the
	  	snz                           	;  FIFO is "empty",
		jmp	@testbuffer1           	;  no action
		jb	buffertail.4,:fifoB2	;

	  	mov  	w, #FIFOB1              ; Indirectly address the FIFO-Puffer
	  	add  	w, bufferTail           ;  using the Head pointer 
	  	mov  	fsr, w                  ; 
	  	mov  	data_tx_temp, ind       ; Read the value from the FIFO
		_bank	SERIAL2			;
		jmp	:readend		;

:fifoB2
		mov	tailtemp,buffertail	;
		clrb	buffertail.4		;
	  	mov  	w, #FIFOB2              ; Indirectly address the FIFO-Puffer
	  	add  	w, bufferTail           ;  using the Head pointer 
	  	mov  	fsr, w                  ; 
	  	mov  	data_tx_temp, ind       ; Read the value from the FIFO
		_bank	SERIAL2			;
		mov	buffertail,tailtemp	;

:readend
	  	inc  	bufferTail              ; Set Tail to next location
	  	clrb 	bufferTail.5            ; If Tail = 16, "circle" around to 0
	  	dec  	buffercount             ; Decrement the item count

		_bank	SERIAL1
		mov	w,data_tx_temp		;
		call	@send_byte		;

		_bank	SERIAL2			;
		test	buffercount		; keep sending till buffer empty
		sz				;
		jmp	senddataserial2		;

		jmp	@testBuffer1


org	$400
;*********************************************************************************
; UART Subroutines
;*********************************************************************************

;*********************************************************************************
; Function: send_byte
; Send byte via serial port
; INPUTS:
;	w 	-	The byte to be sent via RS-232
; OUTPUTS:
; 	outputs the byte via RS-232
;*********************************************************************************
send_byte
:wait        	test    tx_count                ;wait for not busy
		sz
		jmp	:wait                   ;

		not     w                       ;ready bits (inverse logic)
		mov     tx_high,w               ; store data byte
		setb    tx_low.7                ; set up start bit
		mov     w,#10			;1 start + 8 data + 1 stop bit
		mov     tx_count,w
		retp                            ;leave and fix page bits


;*********************************************************************************
; Function: send_string
; Send string pointed to by address in W register
; INPUTS:
;	w	-	The address of a null-terminated string in program
;			memory
; OUTPUTS:
; 	outputs the string via RS-232
;*********************************************************************************
send_string	
 		mov     string,w                ;store string address
:loop        	mov     w,string                ;read next string character
		mov     m,#3                    ;with indirect addressing (set to $300)
		iread                           ;using the mode register
		test    w                       ;are we at the last char?
		snz                             ;if not=0, skip ahead
		jmp	:exit			;yes, leave & fix page bits
		mov     m,#$0f                  ;reset the mode register to RX directions
		call    send_byte               ;not 0, so send character
		inc     string                  ;point to next character
		jmp     :loop                   ;loop until done
:exit		mov     m,#$0f                   ;reset the mode register
		retp


;*********************************************************************************
; Function: Delay
;*********************************************************************************
wdelay1		
		mov	delay1,#200
wdelay2
		nop
		nop
		decsz	delay1
		jmp 	wdelay2
		retp


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