; QEX_PPLT.asm 

; QEX PicoPlot RSSI DF program
; Uses 18F2423 chip, 14.318 MHz clock

; MODE 0 : M0 = open, M1 = open : SelfTest
; MODE 1 : M0 = gnd,  M1 = open : SteadyScan, no HDG pulse input
; MODE 2 : M0 = open, M1 = gnd  : TriggerScan, uses HDG pulse input
; MODE 3 : M0 = gnd,  M1 = gnd  : TachScan

; SelfTest messages : both LEDs = on
; ENABLE = ground : first msg = "9900"
; RSSI msgs from lookup table ( 128 msg total )
; Check ENABLE sw, loop if still grounded
; If not grounded, msg = "9900" then "9800"

; SteadyScan mode
; ENABLE = ground : first msg = "9900"
; RSSI msgs continue until ENABLE = not ground
; Then msg = "9900" followed by "9800"

; TriggerScan mode
; ENABLE = ground : start sending RSSI msgs
; HEADING = rising edge : send "9900"
; ENABLE = not ground : stop sending RSSI messages, then send "9800"

; TachScan
; ENABLE = ground : enable RSSI messages
; TACH = overflow : send one RSSI msg
; HEADING = rising edge : send "9900"
; ENABLE = not ground : disable RSSI message and send "9800"

; Pin assignments :

; AN0 ( pin 2 )  : RSSI analog  ( input )
; RA1 ( pin 3 )  : ENABLE switch ( input )
; RA3 ( pin 5 )  : M1 mode strap ( output, used as an input )
; RA4	( pin 6 )	 : TACH signal ( input )
; RC1	( pin 12 )	 : TACH prescaler bit A ( output, used as an input ) 
; RC2	( pin 13 )	 : TACH prescaler bit B ( output, used as an input )
; RC3	( pin 14 )	 : TACH prescaler bit C ( output, used as an input )
; RC4	( pin 15 )	 : MAX LED ( output )
; RC5	( pin 16 )	 : MIN LED ( output )
; TX  ( pin 17 ) : UART TX RS232 ( output )
; RB0 ( pin 21 ) : SquealTone audio output ( output )
; RB1 ( pin 22 ) : SquealTone RSSI invert sense ( input )	
; RB2 ( pin 23 ) : SquealTone RSSI invert sense ( output )
; RB4 ( pin 25 ) : M0 mode strap ( output, used as an input )
; RB5 ( pin 26 ) : HEADING switch ( input )  
; RB6 ( pin 27 ) : DITHER 1/2 LSB ( output )
; RB7 ( pin 28 ) : DITHER 1/4 LSB ( output )

; Straps A thru C : Tachometer prescaler rate :
; ( G = grounded pin, O = open or "floating" pin )
; 	Ratio		A	B	C
; 	1:1		O	O	O
; 	1:1		G	O	O
; 	4:1		O	G	O
; 	8:1		G	G	O
; 	16:1		O	O	G
; 	32:1		G	O	G
; 	64:1		O	G	G
; 	128:1		G	G	G
 
; Program constants

BAUD			equ		0x5c		;9600 baud BRG value 
							;( brgh = 1, 14.318 +0.23%)

; Port pins

#define 	DITHER_LO		PORTB,7	;Dither 1/4 LSB output ( pin 28 )
#define 	DITHER_HI		PORTB,6	;Dither 1/2 LSB output ( pin 27 )
#define 	MAX_LED		PORTC,4	;MAX RSSI LED output ( pin 15 )
#define 	MIN_LED		PORTC,5	;MIN RSSI LED output ( pin 16 )
#define 	TACH_IN		PORTA,4	;TACH signal input ( pin 6 )
#define 	HDG_IN		PORTB,5	;HDG switch input ( pin 26 )
#define 	TONE_OUT		PORTB,0	;SquealTone output ( pin 21 )
#define 	TONE_ON		T1CON,0	;SquealTone enable
#define 	ENABLE_IN		PORTA,1	;ENABLE switch input ( pin 3 )
#define 	MODE_BIT_0		PORTB,4	;MODE SELECT bit 0 input 
							;( pin 25, "M0" strap )
#define	MODE_BIT_1		PORTA,3	;MODE SELECT bit 1 input 
							;( pin 5, "M1" strap )	
#define 	SCALE_0		PORTC,1	;TACH prescaler bit 0 input 
							;( pin 12, "A" strap )
#define 	SCALE_1		PORTC,2	;TACH prescaler bit 1 input 
							;( pin 13, "B" strap )
#define 	SCALE_2		PORTC,3	;TACH prescaler bit 2 input 
							;( pin 14, "C" strap )

; Bits of the STAT_BYTE variable

#define 	TACH_INT	STAT_BYTE,0	;= 1 if tach pulse = detected
#define 	HDG_INT	STAT_BYTE,1	;= 1 if HDG sw +edge detected
#define	EN_NOW	STAT_BYTE,2	;= 1 if ENABLE switch = closed
#define	M0_NOW	STAT_BYTE,3	;= 1 if MODE 0 strap = ground
#define	M1_NOW	STAT_BYTE,4	;= 1 if MODE 1 strap = ground
#define	TS_MODE	STAT_BYTE,5	;= 1 if TachScan mode = selected
#define	SQTN_NEG	STAT_BYTE,6	;= 1 if SquealTone = negative RSSI

; Program variables

	cblock	0x00		;start of access RAM

 	W_T 				;temp storage for interrupt routine 
	STATUS_T 	
	PCLATH_T 	
	FSR_T
 	
	RELOAD			;TMR0 reload value

	STAT_BYTE			;STATUS bits flag byte

	DELAY_BYTE			;DELAY timer byte

	TONE_HI			;TMR1 hi byte reload value
	TONE_LO			;TMR1 lo byte reload value

	RSSI_HI			;RSSI hi byte ( binary )
	RSSI_LO			;lo byte
	RSSI_SUM_HI		;magnified SquealTone sum, hi byte
	RSSI_SUM_LO		;low byte

	BINHI				;inputs for BINBCD routine ( 12 bits max )
	BINLO

	BCDX1				;for binary/BCD routine calculations
	BCDX10
	BCDX100
	BCDX1K
	BCDX1T
	BCDX10T
	BCDX100T
	BCDX1KT

	TX_BUFF			;RS232 TX char buffer
	TX_DLY_LO			;RS232 char pause
	TX_DLY_HI

	ADC_DLY			;ADC measurement delay

	NDX1				;loop index 1
	NDX2				;loop index 2
	NDX3				;loop index 3

; End of variables

	endc

;-------------------------------------------------------------------
;
;
;                ASSEMBLER DIRECTIVES AND CONFIG BYTE
;
;
;-------------------------------------------------------------------


		processor	18F2423		;identify the device

		#include 	<P18f2423.inc> 	;register + bit definitions

; Configuration Registers

     CONFIG	OSC = HS             	;HS oscillator
     CONFIG	FCMEN = OFF          	;Fail-Safe Clock Monitor disabled
     CONFIG	IESO = OFF           	;Oscillator Switchover mode disabled
     CONFIG	PWRT = ON            	;PWRT enabled
     CONFIG	BOREN = OFF          	;Brown-out Reset disabled
     CONFIG	WDT = OFF            	;WDT disabled
     CONFIG	MCLRE = ON           	;MCLR pin enabled; RE3 input pin disabled
     CONFIG	LPT1OSC = OFF        	;Timer1 = higher power operation
     CONFIG	PBADEN = OFF         	;PORTB<4:0> = digital I/O on Reset
     CONFIG	CCP2MX = PORTC       	;CCP2 input/output is multiplexed with RC1
     CONFIG	STVREN = OFF         	;Stack full/underflow will not cause Reset
     CONFIG	LVP = OFF            	;Disabled
     CONFIG	XINST = OFF          	;Instruction set = Legacy mode
     CONFIG	DEBUG = OFF          	;debugger disabled, RB6 + RB7 = I/O pins
     CONFIG	CP0 = ON             	;Block 0 (0800-1FFFh) code-protected
     CONFIG	CP1 = ON             	;Block 1 (2000-3FFFh) code-protected
     CONFIG	CPB = ON             	;Boot block (0000-07FFh) code-protected
     CONFIG	CPD = ON             	;Data EEPROM code-protected
     CONFIG	WRT0 = ON            	;Block 0 (0800-1FFFh) write-protected
     CONFIG	WRT1 = ON            	;Block 1 (2000-3FFFh) write-protected
     CONFIG	WRTB = ON            	;Boot block (000-7FFh) write-protected
     CONFIG	WRTC = ON            	;Config regs (300000-3000FFh) wr-protected
     CONFIG	WRTD = ON            	;Data EEPROM write-protected
     CONFIG	EBTR0 = OFF          	;Block 0 (0800-1FFFh) no tbl rd protect
     CONFIG	EBTR1 = OFF          	;Block 1 (2000-3FFFh) no tbl rd protect
     CONFIG	EBTRB = OFF          	;Boot block (000-7FFh) no rd protect

;------------------------------------------------------------------
;
;
;                   EXECUTABLE CODE BEGINS HERE
;
;
;-------------------------------------------------------------------


;-------------------------------------------------------------------
;
;
; Coldstart routine
;
;
;-------------------------------------------------------------------

		org		0x00		;coldstart origin

CSTART	goto		MSTART	;jump to main start routine


;-------------------------------------------------------------------
;
;
; Interrupt routine
;
;
;-------------------------------------------------------------------

		org		0x08		;interrupt vector address

INT

; Save registers

		movwf 	W_T 		
		movf	 	STATUS,W 	
		movwf 	STATUS_T 	

; Identify the interrupt source : TMR0, TMR1 or PORTB ?	

		btfss		INTCON,2	;TMR0 overflow ?
		goto		INT_TMR1	;jump if not

; Interrupt came from TMR0
; ( = TACH input )

INT_TACH

		bcf		INTCON,2	;clear TMR0 interrupt flag
		movf		RELOAD,W	;get TMR0 reload value
		movwf		TMR0L		;reload TMR0

; Check if TachScan mode is selected
; If not, bypass the tach overspeed test

		btfss		TS_MODE	;TachScan mode selected ?
		goto		INT_2		;jump if not

; TachScan mode is selected
; Check if TACH_INT bit is already set ( = tach overspeed condition )

		btfss		TACH_INT	;TACH_INT = already set ?
 		goto		INT_2		;if not, jump

; TACH_INT bit is already set ( = tach overspeed condition )
; Blink both LEDs to signal this error condition
; Trap the CPU here... no reason to return from interrupt 
; ( = fault condition ) 

OVRSPD

		bsf		MAX_LED
		bsf		MIN_LED

OVRSPD_2

		decfsz	NDX1,F
		goto		OVRSPD_2
		decfsz	NDX2,F
		goto		OVRSPD_2

		bcf		MAX_LED
		bcf		MIN_LED

OVRSPD_3

		decfsz	NDX1,F
		goto		OVRSPD_3
		decfsz	NDX2,F
		goto		OVRSPD_3

		goto		OVRSPD

; TachScan mode is not selected, or tach overspeed = false 
; Continue with TACH interrupt routine
 
INT_2

		bsf		TACH_INT	;signal the TACH interrupt 
		goto		INT_DONE	;finished

; Identify the interrupt source : TMR1 or PORTB ?

INT_TMR1
		btfss		PIR1,0	;TMR1 interrupt ?
		goto		INT_PORTB	;jump if not

; Interrupt came from TMR1 ( SquealTone generator )
; Reverse the tone output bit

		btfsc		TONE_OUT	;pin 21 = low ?
		goto		INT_TMR1A	;jump if not low

		bsf		TONE_OUT	;make pin 21 = high
		goto		INT_TMR1B	;


INT_TMR1A
		bcf		TONE_OUT	;make pin 21 = low
		goto		INT_TMR1B	;


INT_TMR1B
		bcf		TONE_ON	;TMR1 = off during reload
		movf		TONE_HI,W	;reload TMR1
		movwf		TMR1H
		movf		TONE_LO,W
		movwf		TMR1L	
		bsf		TONE_ON	;turn it back on

; Clear the TMR1 interrupt flag and exit

		bcf		PIR1,0	;clear the flag
		goto		INT_DONE	;finished

; Interrupt came from PORTB
; ( = HDG switch input )

INT_PORTB

		movf		PORTB,W	;update the interrupt mask
		bcf		INTCON,0	;clear PORTB interrupt flag

		bcf		HDG_INT	;assume switch = closed
		btfsc		HDG_IN	;switch = open ?
		bsf		HDG_INT	;if true, flag it

		goto		INT_DONE	;finished

; Restore registers

INT_DONE	
		movf		STATUS_T,W
		movwf		STATUS
		movf		W_T,W

		retfie			;enable int, return


;-------------------------------------------------------------------
;
;
; Mainstart routine
;
;
;-------------------------------------------------------------------

MSTART	nop				;entry point

; Config the ADC and Vref ( 14.318 MHz )

		movlw		0x01		;ADCON0 byte
						;ADC = on
						;selected input = AN0
		movwf		ADCON0	

		movlw		0x0e		;ADCON1 byte
						;vref = vdd + vss
						;inputs AN0 only
		movwf		ADCON1

; Fast conversions : 33 uSec / conversion

		movlw		0xb5		;ADCON2 byte	
						;result = right justify
						;sample time = 16 Tad
						;clk div = 16 ( for 14.318 MHz )

		movwf		ADCON2

; Config PORT pins

		movlw		0xf7
		movwf		TRISA
		movlw		0x22
		movwf		TRISB
		movlw		0xc0
		movwf		TRISC

		bcf		INTCON2,7	;enable weak pull-ups

		movlw		0x00
		movwf		PORTA
		movlw		0x00
		movwf		PORTB
		movlw		0x01
		movwf		PORTC

; Config the UART and BRG

		movlw		0x90		;RCSTA config byte
						;serial port = enabled
						;RX data = 8 bits
						;recieve = continuous
						;address detect = off
		movwf		RCSTA	

		movlw		0x24		;TXSTA byte, BRGH = 1
						;TX data = 8 bits
						;TX = enabled
						;mode = asynchronous
		movwf		TXSTA		
		movlw		BAUD		;baud rate byte
		movwf		SPBRG		

; Start up TMR0 for TACH input pulses

		movlw		0xff		;clock source = RA4
						;clock = falling edge
						;prescaler = not used
		movwf		T0CON		;

; Identify the TACH prescaler value
; ( straps A, B and C )

		clrf		RELOAD	;

		bsf		SCALE_0	;strap A output = high
		btfss		SCALE_0	;A = high ?
		bsf		RELOAD,1	;RELOAD bit 1 = 1 if grounded
		bcf		SCALE_0	;strap A output = low

		bsf		SCALE_1	;strap B output= high
		btfss		SCALE_1	;B = high ?
		bsf		RELOAD,2	;RELOAD bit 2 = 1 if grounded
		bcf		SCALE_1	;strap B output = low

		bsf		SCALE_2	;strap C output = high
		btfss		SCALE_2	;C = high ?
		bsf		RELOAD,3	;RELOAD bit 3 = 1 if grounded
		bcf		SCALE_2	;strap C output = low

; Look-up table to find the prescaler value

		movf		RELOAD,0	;get RELOAD value
		addwf		PCL,1		;jump to table entry

		movlw		0xff 		;prescaler ratio = 1
		goto		MSTART1	;
		movlw		0xfe 		;prescaler ratio = 2
		goto		MSTART1	;
		movlw		0xfc 		;prescaler ratio = 4
		goto		MSTART1	;
		movlw		0xf8 		;prescaler ratio = 8
		goto		MSTART1	;
		movlw		0xf0 		;prescaler ratio = 16
		goto		MSTART1	;
		movlw		0xe0 		;prescaler ratio = 32
		goto		MSTART1	;
		movlw		0xc0 		;prescaler ratio = 64
		goto		MSTART1	;
		movlw		0x80 		;prescaler ratio = 128
		goto		MSTART1	;

MSTART1	
		movwf		RELOAD	;save the tach prescaler value

; Check for SquealTone reversed polarity

		bcf		SQTN_NEG	;assume RSSI = positive

		bsf		PORTB,2	;pin 23 = hi
		nop
		nop
		nop
		btfss		PORTB,1	;pin 22 = hi ?
		goto		MSTART_1A	;jump if not

		bcf		PORTB,2	;pin 23 = lo
		nop
		nop
		nop
		btfsc		PORTB,1	;pin 22 = lo ?
		goto		MSTART_1A	;jump if not

		bsf		SQTN_NEG	;RSSI = negative

; SquealTone test completed
; Make pin 23 = low ( precaution ) 

MSTART_1A

		bcf		PORTB,2	;pin 23 = lo

; Start up TMR1 for the SquealTone generator
; ( tone = off )

		movlw		0x00		;prescale = 1:1
						;clock = osc/4
						;TMR1 = off
		movwf		T1CON		;

; Initialize the variables

		movlw		0x40		;preserve SQTN_NEG bit
		andwf		STAT_BYTE,1

; Prepare for interrupts

		movf		PORTB,W	;update the interrupt mask
		bcf		INTCON,0	;clear any pending interrupt
		bsf		INTCON,3	;enable PORTB interrupts

		movf		RELOAD,W	;load TMR0 with prescale value
		movwf		TMR0L		;
		bcf		INTCON,2	;clear TMR0 interrupt flag
		bsf		INTCON,5	;enable TMR0 interrupts

		bcf		PIR1,0	;clear TMR1 interrupt flag
		bsf		PIE1,0	;enable TMR1 interrupts

		bsf		INTCON,6	;enable peripheral interrupts
		bsf		INTCON,7	;enable all interrupts

; Generate a tone "beep" for RSSI = 0000

		bsf		TONE_ON

		clrf		RSSI_LO
		clrf		RSSI_HI
		call		SQTN

		clrf		NDX1
		clrf		NDX2
		movlw		0x08
		movwf		NDX3

MSTART2
		decfsz	NDX1,1
		goto		MSTART2
		decfsz	NDX2,1
		goto		MSTART2
		decfsz	NDX3,1
		goto		MSTART2

; Generate a tone "beep" for RSSI = 8191

		movlw		0xff
		movwf		RSSI_LO
		movlw		0x1f
		movwf		RSSI_HI
		call		SQTN

		clrf		NDX1
		clrf		NDX2
		movlw		0x08
		movwf		NDX3

MSTART3
		decfsz	NDX1,1
		goto		MSTART3
		decfsz	NDX2,1
		goto		MSTART3
		decfsz	NDX3,1
		goto		MSTART3

		bcf		TONE_ON
 
; Done with start-up, proceed to main program


;-------------------------------------------------------------------
;
;
; EXEC routine
;
;
;-------------------------------------------------------------------

EXEC

; Call the various routines to generate output data

		nop				;entry point

		call		ST		;SelfTest, MODE = 0
		call		SSL		;SteadyScan-Level, MODE = 1
		call		SSE		;SteadyScan-Edge, MODE = 2
		call		TS		;TachScan, MODE = 3
		goto		EXEC		;loop


;-------------------------------------------------------------------
;
;
; SELFTEST Routine ( MODE = 0 )
;
;
;-------------------------------------------------------------------

ST		
		nop					;entry point

; Check if ENABLE switch is closed
; Check if selected MODE = 0 

		call		STAT_GET
		btfss		EN_NOW		;ENABLE sw = closed ?
		return				;exit if not
		btfsc		M0_NOW		;MODE 0 strap = open ?
		return				;exit if not
		btfsc		M1_NOW		;MODE 1 strap = open ?
		return				;exit if not

; MODE = 0 and ENABLE switch = closed
; Proceed with SelfTest
; Turn on both LEDs

		bsf		MAX_LED		;MAX LED = on
		bsf		MIN_LED		;MIN LED = on

; Turn on the SquealTone

		bsf		TONE_ON

; Load the index pointers for the test data lookup table

ST_2
		movlw		0x80
		movwf		NDX1
		clrf		NDX2

; Send a MARK message ( data = "9900" )

		call		MARK

; Get the data bytes for next RSSI message
; 128 RSSI messages, data comes from the lookup table

ST_3	
		call		TEST_HI		;get hi byte
		movwf		BINHI			;save it
		call		TEST_LO		;get lo byte
		movwf		BINLO			;save it

; Save a copy in binary format for the SquealTone routine

		movf		BINHI,0
		movwf		RSSI_HI
		movf		BINLO,0
		movwf		RSSI_LO

; Check if magnified SquealTone mode is selected

		btfsc		HDG_IN
		goto		ST_3A		;jump if not enabled

; Magnified SquealTone is selected

		call		SQTN_MAG
		goto		ST_3B

; Magnified SquealTone is not selected
; Call the regular SquealTone routine

ST_3A
		call		SQTN
		goto		ST_3B

; Generate the RSSI message and send it

ST_3B
		call		BINBCD
		call		BCDASC
		call		MESSAGE

; Check if done with this scan

		incf		NDX2,1		;point to next msg data
		decfsz	NDX1,1		;check if done
		goto		ST_3			;loop if not done

; Scan is done ( 128 RSSI messages were sent )
; Check if ENABLE switch is still closed
; Check if SelfTest mode is still selected
; If true, continue SelfTest 

		call		STAT_GET
		btfss		EN_NOW		;ENABLE sw = closed ?
		goto		ST_4			;finish if not
		btfsc		M0_NOW		;MODE 0 strap = open ?
		goto		ST_4			;finish if not
		btfsc		M1_NOW		;MODE 1 strap = open ?
		goto		ST_4			;finish if not

		goto		ST_2			;continue SelfTest

; SelfTest is finished 
; Send one more MARK message
; Then send a STOP message

ST_4	
		call		MARK
		call		STOP

; Turn off the SquealTone

		bcf		TONE_ON

; Turn off both LEDs and exit

		bcf		MAX_LED		;MAX LED = off
		bcf		MIN_LED		;MIN LED = off

		return				;done, return


;-------------------------------------------------------------------
;
;
; SSL Routine ( MODE 1 : SteadyScan, no HDG input )
;
;
;-------------------------------------------------------------------

SSL		
		nop				;entry point

; Check if ENABLE switch is closed
; Check if selected MODE = 1 

		call		STAT_GET
		btfss		EN_NOW		;ENABLE sw = closed ?
		return				;exit if not
		btfss		M0_NOW		;MODE 0 strap = ground ?
		return				;exit if not
		btfsc		M1_NOW		;MODE 1 strap = open ?
		return				;exit if not

; MODE = 1 and ENABLE switch = closed
; Turn on the SquealTone

		bsf		TONE_ON

; Send a MARK message to signal start of scan

		call		MARK

; Get RSSI reading and send it

SSL_1
		call		RSSI			;get RSSI reading
		call		MESSAGE		;send the message

; Check if magnified SquealTone mode is selected

		btfsc		HDG_IN
		goto		SSL_1A		;jump if not enabled

; Magnified SquealTone is selected

		call		SQTN_MAG
		goto		SSL_1B

; Magnified SquealTone is not selected
; Call the regular SquealTone routine

SSL_1A
		call		SQTN
		goto		SSL_1B
	
; Check if scan is finished ( ENABLE switch = open )

SSL_1B
		call		STAT_GET
		btfsc		EN_NOW		;ENABLE sw = closed ?
		goto		SSL_1			;continue RSSI reporting if true

; Scan is finished ( ENABLE switch = open )
; Send one more MARK message
; Then send a STOP message

		call		MARK
		call		STOP

; Turn off the SquealTone

		bcf		TONE_ON

; Turn off both LEDs and exit

		bcf		MAX_LED		;MAX LED = off
		bcf		MIN_LED		;MIN LED = off

		return


;-------------------------------------------------------------------
;
;
; SSE Routine ( MODE 2 : SteadyScan, with HDG input )
;
;
;-------------------------------------------------------------------

SSE		
		nop					;entry point

; Check if ENABLE switch is closed
; Check if selected MODE = 2 

		call		STAT_GET
		btfss		EN_NOW		;ENABLE sw = closed ?
		return				;exit if not
		btfsc		M0_NOW		;MODE 0 strap = open ?
		return				;exit if not
		btfss		M1_NOW		;MODE 1 strap = ground ?
		return				;exit if not

; MODE = 2 and ENABLE switch = closed
; Proceed with MODE 2 ( = starting now )
; Turn on the SquealTone

		bsf		TONE_ON

; Clear the HDG bit

		bcf		HDG_INT		;clear the flag

; Get one RSSI reading and send it

SSE_2
		call		RSSI			;get RSSI reading
		call		MESSAGE		;send the message

; Check if a HDG interrupt pulse was detected

		btfss		HDG_INT		;HDG pulse detected ?
		goto		SSE_3			;jump if not

; HDG pulse was detected
; Send a MARK message

		bcf		HDG_INT		;clear the flag
		call		MARK

; Call the SquealTone routine

SSE_3
		call		SQTN

; Check if ENABLE switch is still closed
; Check if MODE = still 2
; If true, continue RSSI reporting

		call		STAT_GET
		btfss		EN_NOW		;ENABLE sw = closed ?
		goto		SSE_4			;jump if not
		btfsc		M0_NOW		;MODE 0 strap = open ?
		goto		SSE_4			;jump if not
		btfss		M1_NOW		;MODE 1 strap = ground ?
		goto		SSE_4			;jump if not

		goto		SSE_2			;continue RSSI reporting

; MODE 2 = no longer selected and/or ENABLE switch = open
; Send a STOP message

SSE_4
		call		STOP

; Turn off the SquealTone

		bcf		TONE_ON

; Turn off both LEDs and exit

		bcf		MAX_LED		;MAX LED = off
		bcf		MIN_LED		;MIN LED = off

		return


;-------------------------------------------------------------------
;
;
; TS Routine : TachScan routine ( MODE 3 : TachScan )
;
;
;-------------------------------------------------------------------

TS
		nop					;entry point

; Check if ENABLE switch is closed
; Check if selected MODE = 3 

		call		STAT_GET
		btfss		EN_NOW		;ENABLE sw = closed ?
		return				;exit if not
		btfss		M0_NOW		;MODE 0 strap = ground ?
		return				;exit if not
		btfss		M1_NOW		;MODE 1 strap = ground ?
		return				;exit if not

; MODE = 3 and ENABLE switch = closed
; Proceed with MODE 3 ( = starting now )
; Turn on the SquealTone

		bsf		TONE_ON

; Clear the HDG interrupt bit
; Clear the TACH interrupt bit
; Set the TS_MODE bit ( = enable tach overspeed testing )

		bcf		HDG_INT		;clear the flag
		bcf		TACH_INT
		bsf		TS_MODE

; Get one RSSI reading

TS_2
		call		RSSI			;get RSSI reading

; Check if a TACH interrupt pulse was detected

		btfss		TACH_INT		;TACH pulse detected ?
		goto		TS_3			;jump if not

; TACH interrupt pulse was detected
; Send the RSSI reading
; Clear the TACH interrupt flag bit

		call		MESSAGE		;send the RSSI message
		bcf		TACH_INT		;clear the flag

; Check if a HDG interrupt pulse was detected

TS_3
		btfss		HDG_INT		;HDG pulse detected ?
		goto		TS_4			;jump if not

; HDG interrupt pulse was detected
; Clear the HDG interrupt flag bit
; Send a MARK message

		bcf		HDG_INT		;clear the flag
		call		MARK			;send the MARK message

; Call the SquealTone routine

TS_4
		call		SQTN

; Check if ENABLE switch is still closed
; Check if MODE = still 3
; If true, continue RSSI reporting

		call		STAT_GET
		btfss		EN_NOW		;ENABLE sw = closed ?
		goto		TS_5			;jump if not
		btfss		M0_NOW		;MODE 0 strap = ground ?
		goto		TS_5			;jump if not
		btfss		M1_NOW		;MODE 1 strap = ground ?
		goto		TS_5			;jump if not

		goto		TS_2			;continue RSSI reporting

; MODE 3 = no longer selected and/or ENABLE switch = open
; Send a STOP message and exit
; Clear the TS_MODE bit ( = disable tach overspeed testing )
; Turn off the SquealTone
; Turn off both LEDs and exit

TS_5
		call		STOP

		bcf		TS_MODE

		bcf		TONE_ON

		bcf		MAX_LED		;MAX LED = off
		bcf		MIN_LED		;MIN LED = off

		return


;-------------------------------------------------------------------
;
;
; STAT_GET routine ( get present status of ENABLE and MODE inputs )
;
;
;-------------------------------------------------------------------

STAT_GET

		bcf		EN_NOW		;assume ENABLE switch = open

		bsf		ENABLE_IN	
		call		DELAY
		btfss		ENABLE_IN		;switch = closed ?
		bsf		EN_NOW		;if true, flag it

		bcf		ENABLE_IN		;turn off the output

		bcf		M0_NOW		;assume MODE bit 0 = open

		bsf		MODE_BIT_0
		call		DELAY
		btfss		MODE_BIT_0		;MODE 0 pin = ground ?
		bsf		M0_NOW		;if true, flag it

		bcf		MODE_BIT_0		;turn off the output
	
		bcf		M1_NOW		;assume MODE bit 1 = open

		bsf		MODE_BIT_1
		call		DELAY
		btfss		MODE_BIT_1		;MODE 1 pin = ground ?
		bsf		M1_NOW		;if true, flag it

		bcf		MODE_BIT_1		;turn off the output

		return


;-------------------------------------------------------------------
;
;
; DELAY routine ( provide about 60 usec time delay )
;
;
;-------------------------------------------------------------------

DELAY
		clrf		DELAY_BYTE

DELAY_2
		decfsz	DELAY_BYTE,F
		goto		DELAY_2

		return


;-------------------------------------------------------------------
;
;
; MARK routine ( send a MARK message )
;
;
;-------------------------------------------------------------------

; Send a MARK message ( data = "9900" )

MARK
		movlw		0x39			;ASCII "9"
		movwf		BCDX1K
		movlw		0x39			;ASCII "9"
		movwf		BCDX100
		movlw		0x30			;ASCII "0"
		movwf		BCDX10
		movlw		0x30			;ASCII "0"
		movwf		BCDX1

		call		MESSAGE		;send it

		return				;done, return


;-------------------------------------------------------------------
;
;
; STOP routine ( send a STOP message )
;
;
;-------------------------------------------------------------------

; Send a STOP message ( data = "9800" )

STOP
;		call		STOP_DELAY
		movlw		0x39			;ASCII "9"
		movwf		BCDX1K
		movlw		0x38			;ASCII "8"
		movwf		BCDX100
		movlw		0x30			;ASCII "0"
		movwf		BCDX10
		movlw		0x30			;ASCII "0"
		movwf		BCDX1

		call		MESSAGE		;send it

		return				;done, return

; Provide extra delay to allow display refresh

STOP_DELAY
		clrf		NDX1		;start value
		clrf		NDX2
		movlw		0x08
		movwf		NDX3

SD_2		
		decfsz 	NDX1,F
		goto 		SD_2
		decfsz 	NDX2,F
		goto 		SD_2
		decfsz 	NDX3,F
		goto 		SD_2

		return


;-------------------------------------------------------------------
;
;
; RSSI routine ( get an RSSI reading )
;
;
;-------------------------------------------------------------------

RSSI		
		nop				;entry point

; Clear the ADC result registers

		clrf		BINHI
		clrf		BINLO

; Get 4 ADC readings
; Increment the dither bits for each reading

		bcf		DITHER_HI	;1/4 LSB = low
		bcf		DITHER_LO	;1/2 LSB = low
		call		ADC

		bsf		DITHER_HI	;1/4 LSB = hi
		bcf		DITHER_LO	;1/2 LSB = low
		call		ADC

		bcf		DITHER_HI	;1/4 LSB = low
		bsf		DITHER_LO	;1/2 LSB = hi
		call		ADC

		bsf		DITHER_HI	;1/4 LSB = hi
		bsf		DITHER_LO	;1/2 LSB = hi
		call		ADC

; Divide result by 2
; ( limit message length to 4 characters )

		rrcf		BINLO,F
		bcf		BINLO,7

		rrcf		BINHI,F
		btfsc		STATUS,C
		bsf		BINLO,7

		bcf		BINHI,7

; Save a copy in binary format for the SquealTone routine

		movf		BINHI,W
		movwf		RSSI_HI
		movf		BINLO,W
		movwf		RSSI_LO

; Generate the output message

		call		BINBCD
		call		BCDASC

; Update the MAX / MIN LEDs
  
RSSI_1	
		bcf		MAX_LED	;MAX LED = off
		bcf		MIN_LED	;MIN LED = off

; Check if RSSI > 7782 ( = 95% of full scale ) 
; Turn on MAX LED if true

; Check if X1K digit > 7

RSSI_1A	
		movf		BCDX1K,W	;get X1K ASCII digit
		andlw		0x0f		;change to BCD
		sublw		0x07		;subtract from 7
		btfss		STATUS,C	;greater than 7 ?
		goto		RSSI_MAX	;if true, MAX LED = on
		btfss		STATUS,Z	;equal to 7 ?
		goto		RSSI_2A	;if false, jump to MIN test

; Check if X100 digit > 7

RSSI_1B	
		movf		BCDX100,W	;get X100 ASCII digit
		andlw		0x0f		;change to BCD
		sublw		0x07		;subtract from 7
		btfss		STATUS,C	;greater than 7 ?
		goto		RSSI_MAX	;if true, MAX LED = on
		btfss		STATUS,Z	;equal to 7 ?
		goto		RSSI_2A	;if false, jump to MIN test

; Check if X10 digit > 8

RSSI_1C	
		movf		BCDX10,W	;get X10 ASCII digit
		andlw		0x0f		;change to BCD
		sublw		0x08		;subtract from 8
		btfss		STATUS,C	;greater than 8 ?
		goto		RSSI_MAX	;if true, MAX LED = on
		btfss		STATUS,Z	;equal to 8 ?
		goto		RSSI_2A	;if false, jump to MIN test

; Check if X1 digit > 2

RSSI_1D	
		movf		BCDX1,W	;get X1 ASCII digit
		andlw		0x0f		;change to BCD
		sublw		0x02		;subtract from 2
		btfss		STATUS,C	;greater than 2 ?
		goto		RSSI_MAX	;if true, MAX LED = on
		btfss		STATUS,Z	;equal to 2 ?
		goto		RSSI_2A	;if false, jump to MIN test
		goto		RSSI_MAX	;otherwise, MAX LED = on

; RSSI is 7782 or more
; Turn on MAX LED and exit

RSSI_MAX	
		bsf		MAX_LED	;MAX LED = on
		return

; RSSI is less than 7782
; Check if RSSI < 410 ( = 5% of full scale )
; Turn on MIN LED if true

; Check if X1K digit > 0

RSSI_2A	
		movf		BCDX1K,W	;get X1K ASCII digit
		andlw		0x0f		;change to BCD
		sublw		0x00		;subtract from 0
		btfss		STATUS,Z	;greater than 0 ?
		goto		RSSI_3	;if true, exit

; Check if X100 digit > 4

RSSI_2B	
		movf		BCDX100,W	;get X100 ASCII digit
		andlw		0x0f		;change to BCD
		sublw		0x04		;subtract from 4
		btfss		STATUS,C	;greater than 4 ?
		goto		RSSI_3	;if true, exit
		btfss		STATUS,Z	;equal to 4?
		goto		RSSI_MIN	;if not, MIN LED = on

; Check if X10 digit > 1

RSSI_2C	
		movf		BCDX10,W	;get X10 ASCII digit
		andlw		0x0f		;change to BCD
		sublw		0x01		;subtract from 1
		btfss		STATUS,C	;greater than 1 ?
		goto		RSSI_3	;if true, exit
		btfss		STATUS,Z	;equal to 1?
		goto		RSSI_MIN	;if not, MIN LED = on

; Check if X1 digit > 0

RSSI_2D	
		movf		BCDX1,W	;get X1 ASCII digit
		andlw		0x0f		;change to BCD
		sublw		0x00		;subtract from 0
		btfss		STATUS,C	;greater than 0 ?
		goto		RSSI_3	;if true, exit

; RSSI is 410 or less
; Turn on MIN LED and exit

RSSI_MIN	
		bsf		MIN_LED	;MIN LED = on
		return

; RSSI is less than 7783 and greater than 410
; MAX and MIN LEDs remain off
; Done with measurements, return

RSSI_3	
		return			;done, return


;-------------------------------------------------------------------
;
;
; ADC routine : Get 1 ADC measurement
;
;
;-------------------------------------------------------------------

ADC
		nop				;entry point

; Get one ADC reading
; Prepare for 20 usec delay ( settling time )

		movlw 	0x23		;20 usec delay
		movwf		ADC_DLY

ADC_2		
		decfsz	ADC_DLY,F	;loop until done
		goto 		ADC_2

; Start ADC conversion

		bsf 		ADCON0,2 	;start the conversion

; Poll the ADC until done

ADC_3		
		btfsc		ADCON0,2	;loop until done
		goto 		ADC_3

; ADC is done, add result to total

		movf		ADRESL,W	;get the low result byte
		addwf		BINLO,F	;add to total

		btfsc		STATUS,C	;carry generated ?
		incf		BINHI,F	;if true, increment BINHI

		movf		ADRESH,W	;get the high result byte
		andlw		0x0f		;bottom 4 bits only
		addwf		BINHI,F	;add to total

		return			;done, return

;-------------------------------------------------------------------
;
;
; SQTN routine : SquealTone routine 
; SQTN_MAG routine : Magnified SquealTone routine
;
;
;-------------------------------------------------------------------

SQTN		nop				;entry point

; Multiply RSSI by 4
; Put result in NDX3

		movf		RSSI_HI,0
		movwf		NDX3
		rlcf		NDX3,1
		rlcf		NDX3,1
		bcf		NDX3,7	;top bit = 0
		bcf		NDX3,0
		bcf		NDX3,1
		btfsc		RSSI_LO,6
		bsf		NDX3,0
		btfsc		RSSI_LO,7
		bsf		NDX3,1

; Check if RSSI = negative coefficient
; If true, invert the index data bits.

		btfss		SQTN_NEG	;RSSI = negative ?
		goto		SQTN_1	;jump if not

		movf		NDX3,0
		xorlw		0xff
		movwf		NDX3
		bcf		NDX3,7	;top bit = 0

; Look-up the corresponding tone bytes for TMR1 and save them

SQTN_1
		bcf		INTCON,6	;disable TMR1 interrupts
		call		SQT_HI
		movwf		TONE_HI
		call		SQT_LO
		movwf		TONE_LO
		bsf		INTCON,6	;enable TMR1 interrupts

		return

; Magnified SquealTone routine
; Multiply the RSSI value by 5
 
SQTN_MAG

		clrf		RSSI_SUM_LO
		clrf		RSSI_SUM_HI

		movf		RSSI_LO,0	;get RSSI_LO
		addwf		RSSI_SUM_LO,1
		btfsc		STATUS,C
		incf		RSSI_SUM_HI,1
		movf		RSSI_HI,0
		addwf		RSSI_SUM_HI,1

		movf		RSSI_LO,0	;get RSSI_LO
		addwf		RSSI_SUM_LO,1
		btfsc		STATUS,C
		incf		RSSI_SUM_HI,1
		movf		RSSI_HI,0
		addwf		RSSI_SUM_HI,1

		movf		RSSI_LO,0	;get RSSI_LO
		addwf		RSSI_SUM_LO,1
		btfsc		STATUS,C
		incf		RSSI_SUM_HI,1
		movf		RSSI_HI,0
		addwf		RSSI_SUM_HI,1

		movf		RSSI_LO,0	;get RSSI_LO
		addwf		RSSI_SUM_LO,1
		btfsc		STATUS,C
		incf		RSSI_SUM_HI,1
		movf		RSSI_HI,0
		addwf		RSSI_SUM_HI,1

		movf		RSSI_LO,0	;get RSSI_LO
		addwf		RSSI_SUM_LO,1
		btfsc		STATUS,C
		incf		RSSI_SUM_HI,1
		movf		RSSI_HI,0
		addwf		RSSI_SUM_HI,1

		movf		RSSI_SUM_LO,0
		movwf		RSSI_LO
		movf		RSSI_SUM_HI,0
		movwf		RSSI_HI

		goto		SQTN

			
;-------------------------------------------------------------------
;
;
; BINBCD routine : Binary to BCD conversion routine 
;
;
;-------------------------------------------------------------------

BINBCD	
		nop				;entry point

; Prepare for conversion

		clrf		BCDX1K	;clear the result registers
		clrf		BCDX100
		clrf		BCDX10
		clrf		BCDX1

; Perform conversion
; Start with MSB, end with LSB

BIN2E12	
		btfss		BINHI,4	;bit 12 = 1 ?
		goto		BIN2E11	;if not, jump

		movlw		0x04		;add 4096 to result
		movwf		BCDX1KT
		movlw		0x00
		movwf		BCDX100T
		movlw		0x09
		movwf		BCDX10T
		movlw		0x06
		movwf		BCDX1T
		call		BCDSUM

BIN2E11	
		btfss		BINHI,3	;bit 11 = 1 ?
		goto		BIN2E10	;if not, jump

		movlw		0x02		;add 2048 to result
		movwf		BCDX1KT
		movlw		0x00
		movwf		BCDX100T
		movlw		0x04
		movwf		BCDX10T
		movlw		0x08
		movwf		BCDX1T
		call		BCDSUM

BIN2E10	
		btfss		BINHI,2	;bit 10 = 1 ?
		goto		BIN2E9	;if not, jump

		movlw		0x01		;add 1024 to result
		movwf		BCDX1KT
		movlw		0x00
		movwf		BCDX100T
		movlw		0x02
		movwf		BCDX10T
		movlw		0x04
		movwf		BCDX1T
		call		BCDSUM

BIN2E9	
		btfss		BINHI,1	;bit 9 = 1 ?
		goto		BIN2E8	;if not, jump

		movlw		0x00		;add 512 to result
		movwf		BCDX1KT
		movlw		0x05
		movwf		BCDX100T
		movlw		0x01
		movwf		BCDX10T
		movlw		0x02
		movwf		BCDX1T
		call		BCDSUM

BIN2E8	
		btfss		BINHI,0	;bit 8 = 1 ?
		goto		BIN2E7	;if not, jump

		movlw		0x00		;add 256 to result
		movwf		BCDX1KT
		movlw		0x02
		movwf		BCDX100T
		movlw		0x05
		movwf		BCDX10T
		movlw		0x06
		movwf		BCDX1T
		call		BCDSUM

BIN2E7	
		btfss		BINLO,7	;bit 7 = 1 ?
		goto		BIN2E6	;if not, jump

		movlw		0x00		;add 128 to result
		movwf		BCDX1KT
		movlw		0x01
		movwf		BCDX100T
		movlw		0x02
		movwf		BCDX10T
		movlw		0x08
		movwf		BCDX1T
		call		BCDSUM

BIN2E6	
		btfss		BINLO,6	;bit 6 = 1 ?
		goto 		BIN2E5	;if not, jump

		movlw		0x00		;add 64 to result
		movwf		BCDX1KT
		movlw		0x00
		movwf		BCDX100T
		movlw		0x06
		movwf		BCDX10T
		movlw		0x04
		movwf		BCDX1T
		call		BCDSUM

BIN2E5	
		btfss		BINLO,5	;bit 5 = 1 ?
		goto		BIN2E4	;if not, jump

		movlw		0x00		;add 32 to result
		movwf		BCDX1KT
		movlw		0x00
		movwf		BCDX100T
		movlw		0x03
		movwf		BCDX10T
		movlw		0x02
		movwf		BCDX1T
		call		BCDSUM

BIN2E4	
		btfss		BINLO,4	;bit 4 = 1 ?
		goto		BIN2E3	;if not, jump

		movlw		0x00		;add 16 to result
		movwf		BCDX1KT
		movlw		0x00
		movwf		BCDX100T
		movlw		0x01
		movwf		BCDX10T
		movlw		0x06
		movwf		BCDX1T
		call		BCDSUM

BIN2E3	
		btfss		BINLO,3	;bit 3 = 1 ?
		goto		BIN2E2	;if not, jump

		movlw		0x00		;add 8 to result
		movwf		BCDX1KT
		movlw		0x00
		movwf		BCDX100T
		movlw		0x00
		movwf		BCDX10T
		movlw		0x08
		movwf		BCDX1T
		call		BCDSUM

BIN2E2	
		btfss		BINLO,2	;bit 2 = 1 ?
		goto		BIN2E1	;if not, jump

		movlw		0x00		;add 4 to result
		movwf		BCDX1KT
		movlw		0x00
		movwf		BCDX100T
		movlw		0x00
		movwf		BCDX10T
		movlw		0x04
		movwf		BCDX1T
		call		BCDSUM

BIN2E1	
		btfss		BINLO,1	;bit 1 = 1 ?
		goto		BIN2E0	;if not, jump

		movlw		0x00		;add 2 to result
		movwf		BCDX1KT
		movlw		0x00
		movwf		BCDX100T
		movlw		0x00
		movwf		BCDX10T
		movlw		0x02
		movwf		BCDX1T
		call		BCDSUM

BIN2E0	
		btfss		BINLO,0	;bit 0 = 1 ?
		return	 		;if not, return

		movlw		0x00		;add 1 to result
		movwf		BCDX1KT
		movlw		0x00
		movwf		BCDX100T
		movlw		0x00
		movwf		BCDX10T
		movlw		0x01
		movwf		BCDX1T
		call		BCDSUM

		return			;done, return

;-------------------------------------------------------------------
;
;
; BCDSUM routine : BCD sum routine
;
;
;-------------------------------------------------------------------

BCDSUM	
		nop				;entry point

; Add the two BCD X1 digits

BCDSUM1	
		clrf		WREG
		addwf		BCDX1,W	;get previous bcd x1 answer
		addwf		BCDX1T,W	;add new part
		movwf		BCDX1		;store result

		addlw		0xf6		;check if answer < 10
		btfss		STATUS,C
		goto		BCDSUM10	;jump if no carry

		incf		BCDX10,F	;carry 1 to next digit
		movlw		0x0a		;subtract 10 from bcd x1 answer
		subwf		BCDX1,F	;save it

; Add the two BCD X10 digits

BCDSUM10	
		clrf		WREG
		addwf		BCDX10,W	;get previous bcd x10 answer
		addwf		BCDX10T,W	;add new part
		movwf		BCDX10	;store result

		addlw		0xf6		;check if answer < 10
		btfss		STATUS,C
		goto		BCDSUM100	;jump if no carry

		incf		BCDX100,F	;carry 1 to next digit
		movlw		0x0a		;subtract 10 from bcd x10 answer
		subwf		BCDX10,F	;save it

; Add the two BCD X100 digits

BCDSUM100	
		clrf		WREG
		addwf		BCDX100,W	;get previous bcd x100 answer
		addwf		BCDX100T,W 	;add new part
		movwf		BCDX100	;store result

		addlw		0xf6		;check if answer < 10
		btfss		STATUS,C
		goto		BCDSUM1K	;jump if no carry

		incf		BCDX1K,F	;carry 1 to next digit
		movlw		0x0a		;subtract 10 from bcd x100 answer
		subwf		BCDX100,F	;save it

; Add the two BCD X1K digits

BCDSUM1K	
		clrf		WREG
		addwf		BCDX1K,W	;get previous bcd x1K answer
		addwf		BCDX1KT,W 	;add new part
		movwf		BCDX1K	;store result

		return			;done


;-------------------------------------------------------------------
;
;
; BCDASC routine : BCD to ASCII conversion routine
;
;
;-------------------------------------------------------------------

BCDASC	
		nop				;entry point

; Make top 4 bits = 30h ( = convert BCD to ASCII )

		movlw		0x0f		;number = bottom 4 bits only
		andwf		BCDX1K,F
		andwf		BCDX100,F
		andwf		BCDX10,F
		andwf		BCDX1,F

		movlw		0x30		;ASCII char = BCD + 0x30

		iorwf		BCDX1K,F	;convert BCDX1K to ASCII
		iorwf		BCDX100,F	;convert BCDX100 to ASCII
		iorwf		BCDX10,F	;convert BCDX10 to ASCII
		iorwf		BCDX1,F	;convert BCDX1 to ASCII
		return			;done, return


;-------------------------------------------------------------------
;
;
; MESSAGE routine : RS232 message Routine
;
;
;-------------------------------------------------------------------

MESSAGE	
		nop				;entry point

; Transmit the MSG START character ( ASCII "%" )

		movlw		0x25			;ASCII % character
		movwf		TX_BUFF
		call		CHAR

; Transmit the RSSI data

		movf		BCDX1K,W		;X1K digit ASCII character
		movwf		TX_BUFF
		call		CHAR

		movf		BCDX100,W		;X100 digit ASCII character
		movwf		TX_BUFF
		call		CHAR

		movf		BCDX10,W		;X10 digit ASCII character
		movwf		TX_BUFF
		call		CHAR

		movf		BCDX1,W		;X1 digit ASCII character
		movwf		TX_BUFF
		call		CHAR

; Transmit ASCII <cr> ( end of message )

		movlw		0x0d			;ASCII <cr>
		movwf		TX_BUFF
		call		CHAR

		return				;done

;-------------------------------------------------------------------
;
;
; CHAR : Character transmit routine
;
;
;-------------------------------------------------------------------

; Send a single ASCII character 

CHAR		
		nop				;entry point

; Check if previous character transmission is completed
		
		btfss		PIR1,TXIF	;check if finished
		goto		CHAR		;if not, loop 

; Wait before proceeding ( extra delay between characters )

		clrf		TX_DLY_LO	;start value
		movlw		0x10
;		movlw		0x30		;experimental, "extra" delay
		movwf		TX_DLY_HI

CHAR1		
		decfsz 	TX_DLY_LO,F
		goto 		CHAR1
		decfsz 	TX_DLY_HI,F
		goto 		CHAR1

; Transmit one ASCII character

		movf		TX_BUFF,W	;get the saved character
		movwf		TXREG		;send the character

		return			;done, return	


;-------------------------------------------------------------------
;
;
; LookUp Table routines are here
;
;
;-------------------------------------------------------------------

; Get hi byte of test pattern data

TEST_HI
		movlw		HIGH HTAB	;HTAB	address hi byte
		movwf		PCLATH	;prepare for jump

		movf		NDX2,W	;get index value
		addwf		NDX2,W	;double it
		movwf		PCL		;jump to table entry

; Get lo byte of test pattern data

TEST_LO
		movlw		HIGH LTAB	;LTAB	address hi byte
		movwf		PCLATH	;prepare for jump

		movf		NDX2,W	;get index value
		addwf		NDX2,W	;double it
		movwf		PCL		;jump to table entry

; Get hi byte of SquealTone data
 
SQT_HI
		movlw		HIGH TONE_HTAB	;address hi byte
		movwf		PCLATH	;prepare for jump

		movf		NDX3,W	;get index value
		addwf		NDX3,W	;double it
		movwf		PCL		;jump to table entry

; Get lo byte of SquesalTone data

SQT_LO
		movlw		HIGH TONE_LTAB	;address hi byte
		movwf		PCLATH	;prepare for jump

		movf		NDX3,W	;get index value
		addwf		NDX3,W	;double it
		movwf		PCL		;jump to table entry


;-------------------------------------------------------------------
;
;
; Test data look-up table ( hi byte )
;
;
;-------------------------------------------------------------------

		org		0x0a00	;HTAB origin

HTAB		
		retlw		0x06	 	;
		retlw		0x05	 	;
		retlw		0x04	 	;
		retlw		0x05	 	;
		retlw		0x06	 	;
		retlw		0x06	 	;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x06 		;
		retlw		0x06 		;
		retlw		0x06 		;
		retlw		0x05 		;
		retlw		0x03 		;
		retlw		0x05 		;
		retlw		0x06 		;
		retlw		0x06 		;
		retlw		0x06 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x06 		;
		retlw		0x06 		;
		retlw		0x05 		;
		retlw		0x04 		;
		retlw		0x05 		;
		retlw		0x06 		;
		retlw		0x06 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x08 		;
		retlw		0x08		;
		retlw		0x08 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x07 		;
		retlw		0x06 		;
		retlw		0x05 		;
		retlw		0x06 		;
		retlw		0x07 		;
		retlw		0x08 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x0a 		;
		retlw		0x0b 		;
		retlw		0x0b 		;
		retlw		0x0c 		;
		retlw		0x0c 		;
		retlw		0x0d 		;
		retlw		0x0d 		;
		retlw		0x0e 		;
		retlw		0x0e 		;
		retlw		0x0e 		;
		retlw		0x0e 		;
		retlw		0x0f 		;
		retlw		0x0f 		;
		retlw		0x0f 		;
		retlw		0x0f 		;
		retlw		0x0f 		;
		retlw		0x0f 		;
		retlw		0x0f 		;
		retlw		0x0f 		;
		retlw		0x0f 		;
		retlw		0x0f 		;
		retlw		0x0e 		;
		retlw		0x0e 		;
		retlw		0x0e 		;
		retlw		0x0e 		;
		retlw		0x0d 		;
		retlw		0x0d 		;
		retlw		0x0c 		;
		retlw		0x0c 		;
		retlw		0x0b 		;
		retlw		0x0b 		;
		retlw		0x0a 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x08 		;
		retlw		0x07 		;
		retlw		0x06 		;
		retlw		0x05 		;
		retlw		0x06 		;
		retlw		0x07 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x09 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x08 		;
		retlw		0x07 		;
		retlw		0x07 		;
		retlw		0x06 		;
		retlw		0x06 		;


;-------------------------------------------------------------------
;
;
; Test data look-up table ( low byte )
;
;
;-------------------------------------------------------------------

		org		0x0c00	;LTAB origin

LTAB		
		retlw		0x62	 	;
		retlw		0x90 		;
		retlw		0xa3 		;
		retlw		0xd2 		;
		retlw		0x78 		;
		retlw		0xf0 		;
		retlw		0x4d 		;
		retlw		0x95 		;
		retlw		0xcb 		;
		retlw		0xf2 		;
		retlw		0x0c 		;
		retlw		0x19 		;
		retlw		0x19 		;
		retlw		0x0e 		;
		retlw		0xf8 		;
		retlw		0xd6 		;
		retlw		0xa9 		;
		retlw		0x71 		;
		retlw		0x2c 		;
		retlw		0xdb 		;
		retlw		0x79 		;
		retlw		0x01 		;
		retlw		0x62 		;
		retlw		0xec 		;
		retlw		0x62 		;
		retlw		0x01 		;
		retlw		0x79 		;
		retlw		0xdb 		;
		retlw		0x2c 		;
		retlw		0x71 		;
		retlw		0xa9 		;
		retlw		0xd6 		;
		retlw		0xf8 		;
		retlw		0x0e 		;
		retlw		0x19 		;
		retlw		0x19 		;
		retlw		0x0c 		;
		retlw		0xf2 		;
		retlw		0xcb 		;
		retlw		0x95 		;
		retlw		0x4d 		;
		retlw		0xf0 		;
		retlw		0x78 		;
		retlw		0xd2 		;
		retlw		0xa3 		;
		retlw		0x90 		;
		retlw		0x62 		;
		retlw		0xff 		;
		retlw		0x81 		;
		retlw		0xef 		;
		retlw		0x4c 		;
		retlw		0x9c 		;
		retlw		0xde 		;
		retlw		0x12 		;
		retlw		0x39 		;
		retlw		0x52 		;
		retlw		0x5d 		;
		retlw		0x59 		;
		retlw		0x44 		;
		retlw		0x1e 		;
		retlw		0xe3 		;
		retlw		0x92 		;
		retlw		0x24 		;
		retlw		0x8f 		;
		retlw		0xbf 		;
		retlw		0x5d 		;
		retlw		0x04 		;
		retlw		0x50 		;
		retlw		0x4c 		;
		retlw		0x23 		;
		retlw		0xe3 		;
		retlw		0x93 		;
		retlw		0x35 		;
		retlw		0xcb 		;
		retlw		0x55 		;
		retlw		0xd5 		;
		retlw		0x4b 		;
		retlw		0xb6 		;
		retlw		0x16 		;
		retlw		0x6d 		;
		retlw		0xb9 		;
		retlw		0xfa 		;
		retlw		0x30 		;
		retlw		0x5c 		;
		retlw		0x7d 		;
		retlw		0x93 		;
		retlw		0x9e 		;
		retlw		0x9e 		;
		retlw		0x93 		;
		retlw		0x7d 		;
		retlw		0x5c 		;
		retlw		0x30 		;
		retlw		0xfa 		;
		retlw		0xb9 		;
		retlw		0x6d 		;
		retlw		0x16 		;
		retlw		0xb6 		;
		retlw		0x4b 		;
		retlw		0xd5 		;
		retlw		0x55 		;
		retlw		0xcb 		;
		retlw		0x35 		;
		retlw		0x93 		;
		retlw		0xe3 		;
		retlw		0x23 		;
		retlw		0x4c 		;
		retlw		0x50 		;
		retlw		0x04 		;
		retlw		0x5d 		;
		retlw		0xbf 		;
		retlw		0x8f 		;
		retlw		0x24 		;
		retlw		0x92 		;
		retlw		0xe3 		;
		retlw		0x1e 		;
		retlw		0x44 		;
		retlw		0x59 		;
		retlw		0x5d 		;
		retlw		0x52 		;
		retlw		0x39 		;
		retlw		0x12 		;
		retlw		0xde 		;
		retlw		0x9c 		;
		retlw		0x4c 		;
		retlw		0xef 		;
		retlw		0x81 		;
		retlw		0xff 		;
		retlw		0x62 		;


;-------------------------------------------------------------------
;
;
; Squealtone look-up table ( hi byte )
;
;
;-------------------------------------------------------------------

		org		0x1000	;origin

TONE_HTAB		
		retlw 	0xdd
		retlw 	0xdd
		retlw 	0xde
		retlw 	0xde
		retlw 	0xdf
		retlw 	0xdf
		retlw 	0xe0
		retlw 	0xe0
		retlw 	0xe1
		retlw 	0xe1
		retlw 	0xe2
		retlw 	0xe2
		retlw 	0xe3
		retlw 	0xe3
		retlw 	0xe4
		retlw 	0xe4
		retlw 	0xe5
		retlw 	0xe5
		retlw 	0xe6
		retlw 	0xe6
		retlw 	0xe6
		retlw 	0xe7
		retlw 	0xe7
		retlw 	0xe8
		retlw 	0xe8
		retlw 	0xe8
		retlw 	0xe9
		retlw 	0xe9
		retlw 	0xe9
		retlw 	0xea
		retlw 	0xea
		retlw 	0xea
		retlw 	0xeb
		retlw 	0xeb
		retlw 	0xeb
		retlw 	0xec
		retlw 	0xec
		retlw 	0xec
		retlw 	0xed
		retlw 	0xed
		retlw 	0xed
		retlw 	0xee
		retlw 	0xee
		retlw 	0xee
		retlw 	0xef
		retlw 	0xef
		retlw 	0xef
		retlw 	0xef
		retlw 	0xf0
		retlw 	0xf0
		retlw 	0xf0
		retlw 	0xf0
		retlw 	0xf1
		retlw 	0xf1
		retlw 	0xf1
		retlw 	0xf1
		retlw 	0xf2
		retlw 	0xf2
		retlw 	0xf2
		retlw 	0xf2
		retlw 	0xf2
		retlw 	0xf3
		retlw 	0xf3
		retlw 	0xf3
		retlw 	0xf3
		retlw 	0xf3
		retlw 	0xf4
		retlw 	0xf4
		retlw 	0xf4
		retlw 	0xf4
		retlw 	0xf4
		retlw 	0xf5
		retlw 	0xf5
		retlw 	0xf5
		retlw 	0xf5
		retlw 	0xf5
		retlw 	0xf5
		retlw 	0xf6
		retlw 	0xf6
		retlw 	0xf6
		retlw 	0xf6
		retlw 	0xf6
		retlw 	0xf6
		retlw 	0xf7
		retlw 	0xf7
		retlw 	0xf7
		retlw 	0xf7
		retlw 	0xf7
		retlw 	0xf7
		retlw 	0xf7
		retlw 	0xf8
		retlw 	0xf8
		retlw 	0xf8
		retlw 	0xf8
		retlw 	0xf8
		retlw 	0xf8
		retlw 	0xf8
		retlw 	0xf8
		retlw 	0xf8
		retlw 	0xf9
		retlw 	0xf9
		retlw 	0xf9
		retlw 	0xf9
		retlw 	0xf9
		retlw 	0xf9
		retlw 	0xf9
		retlw 	0xf9
		retlw 	0xf9
		retlw 	0xfa
		retlw 	0xfa
		retlw 	0xfa
		retlw 	0xfa
		retlw 	0xfa
		retlw 	0xfa
		retlw 	0xfa
		retlw 	0xfa
		retlw 	0xfa
		retlw 	0xfa
		retlw 	0xfa
		retlw 	0xfb
		retlw 	0xfb
		retlw 	0xfb
		retlw 	0xfb
		retlw 	0xfb
		retlw 	0xfb
		retlw 	0xfb
		retlw 	0xfb
		retlw 	0xfb


;-------------------------------------------------------------------
;
;
; Squealtone look-up table ( lo byte )
;
;
;-------------------------------------------------------------------

		org		0x1200	;origin

TONE_LTAB		
		retlw 	0x27
		retlw 	0xb7
		retlw 	0x45
		retlw 	0xd1
		retlw 	0x5a
		retlw 	0xe1
		retlw 	0x66
		retlw 	0xe9
		retlw 	0x6a
		retlw 	0xe8
		retlw 	0x65
		retlw 	0xe0
		retlw 	0x58
		retlw 	0xcf
		retlw 	0x44
		retlw 	0xb6
		retlw 	0x27
		retlw 	0x97
		retlw 	0x04
		retlw 	0x70
		retlw 	0xda
		retlw 	0x42
		retlw 	0xa8
		retlw 	0x0d
		retlw 	0x70
		retlw 	0xd2
		retlw 	0x32
		retlw 	0x91
		retlw 	0xee
		retlw 	0x49
		retlw 	0xa3
		retlw 	0xfc
		retlw 	0x53
		retlw 	0xa9
		retlw 	0xfd
		retlw 	0x50
		retlw 	0xa2
		retlw 	0xf2
		retlw 	0x41
		retlw 	0x8f
		retlw 	0xdb
		retlw 	0x27
		retlw 	0x71
		retlw 	0xba
		retlw 	0x01
		retlw 	0x48
		retlw 	0x8d
		retlw 	0xd2
		retlw 	0x15
		retlw 	0x57
		retlw 	0x98
		retlw 	0xd8
		retlw 	0x17
		retlw 	0x55
		retlw 	0x92
		retlw 	0xce
		retlw 	0x09
		retlw 	0x43
		retlw 	0x7c
		retlw 	0xb4
		retlw 	0xec
		retlw 	0x22
		retlw 	0x58
		retlw 	0x8c
		retlw 	0xc0
		retlw 	0xf3
		retlw 	0x25
		retlw 	0x57
		retlw 	0x87
		retlw 	0xb7
		retlw 	0xe6
		retlw 	0x14
		retlw 	0x42
		retlw 	0x6e
		retlw 	0x9b
		retlw 	0xc6
		retlw 	0xf0
		retlw 	0x1a
		retlw 	0x44
		retlw 	0x6c
		retlw 	0x94
		retlw 	0xbc
		retlw 	0xe2
		retlw 	0x08
		retlw 	0x2e
		retlw 	0x53
		retlw 	0x77
		retlw 	0x9b
		retlw 	0xbe
		retlw 	0xe0
		retlw 	0x02
		retlw 	0x24
		retlw 	0x44
		retlw 	0x65
		retlw 	0x85
		retlw 	0xa4
		retlw 	0xc3
		retlw 	0xe1
		retlw 	0xff
		retlw 	0x1c
		retlw 	0x39
		retlw 	0x56
		retlw 	0x71
		retlw 	0x8d
		retlw 	0xa8
		retlw 	0xc3
		retlw 	0xdd
		retlw 	0xf7
		retlw 	0x10
		retlw 	0x29
		retlw 	0x41
		retlw 	0x5a
		retlw 	0x71
		retlw 	0x89
		retlw 	0xa0
		retlw 	0xb6
		retlw 	0xcd
		retlw 	0xe3
		retlw 	0xf8
		retlw 	0x0d
		retlw 	0x22
		retlw 	0x37
		retlw 	0x4b
		retlw 	0x5f
		retlw 	0x72
		retlw 	0x86
		retlw 	0x98
		retlw 	0xab


;-------------------------------------------------------------------
;
;
; End of code
;
;
;-------------------------------------------------------------------

		end		


