;tone8kf.asm

;File history
;tone -orig file downloaded from BATC 6apr98 - author: Brian Kelly GW6BWX
;tone8k- changed for specific repeater needs
;tone8kb-corrected fault on squelch test
;tone8kc-f-corrected delayloop timing

;Hardware details
;PIC chip pin out info (view from top):

;		  	RA2	oo U	o   RA1
;		  	RA3	o	o   RA0 
;		  	RA4	o	o   xtl
;MCLR		  	Reset	o	o   xtl
;Ground		  	Gnd	o	o   +5v
;Tone out	  	RB0	o	o   RB7
;Key		  	RB1	o	o   RB6
;Inverse key	  	RB2	o	o   RB5
;Message in progress	RB3	o	o   RB4


;Clock uses 4MHz crystal
;RA0-4 are inputs
;	RA0,  This input for beacon ON - use as "enable" pin
;	RA1,  This input to reset 5min timer when repeater is opened. (rising edge resets counter)
;	RA2,  
;	RA3,  
;	RA4  
;	RB0-4 are outputs
;	RB0	Tone bit - Square wave morse tone output 
;		The interrupt program toggles this bit if RB1 is set.	
;	RB1	Tone enable bit (controls interrupt & front panel LED - follows key envelope)
;		this output is used to drive the key input for CW mode
;	RB2	Duplicate =RB1 Tone envelope - drives LED only - to avoid loading keyer output 
;	RB3	Message in progress (PTT output during CW ID)
;	RB4	Output is inverse of RB2 (inverse key)
;**************************************************************************************
;Assembler instructions
;**************************************************************************************
;Define processor configuration
	list    P=16F84, R=HEX, C=132
					;(P) processor=16c84,
					;(R) default radix is hexadecimal,
					;(C) 132 column listings,

	__CONFIG H'3FF1'		;Configure for XT Crystal clock, 
					; no watchdog, no start timer.
;-----------------------------------------------

;Define registers & data locations
RTCC    	equ     1h              ; F1 reg is counter/timer for interrupt (sets tone frequency)
PC     		equ     2h              ; F2 reg is program counter
STATUS  	equ     3h              ; F3 reg is STATUS Reg.
PORTA  	equ     5h              ; IO port assignments.
PORTB  	equ     6h
INTCON  	equ     0BH             ; interrupt control register
OPTREG		equ	81H		; option register
TRISA  		equ     85H             ; RA direction/tristate register
TRISB   	equ     86H             ; RB direction/tristate register

msg             equ     10H             ;message data byte
msg_ptr         equ     11H             ;address of message data byte
bitcount        equ     12H             ;number of times msg has been shifted
output_ctrl     equ     13H             ;output bits,0=output (tone),1=tone enable (inverted for keyer),
					;2=LED drive,3=message in progress (PTT),4-7 unused
w_save          equ     14H             ;temp store for W register
speed1		equ	15H		;delay
speed2		equ	16H
speed3		equ	17H
speed4		equ	18H
freq		equ	19H             ;contents set tone frequency
wpm		equ	1AH        	;contents set morse speed	      
input_store	equ	1BH		;old values of PORTA

;------------------------------------------------

;Define constants
W       equ     0             ;pseudo destination, result in w.  
			      ;Note: w=0 is predefined
			      ;     also f=1 
same    equ     1             ;pseudo destination, back in source
Z       equ     2             ;zero bit in status register
C       equ     0             ;carry bit in status register
	      ;


;---------------------------------------------------------------------

;Define program start addresses
	org     0                       ;reset address in 16F84

reset   goto 	init

	org     4
	goto 	interrupt

;**************************************************************************************
;Program instructions
;**************************************************************************************
;Interrupt routine - generates tone frequency when required
interrupt
	bcf 	INTCON,2		;clear RTCC interrupt flag
	movwf 	w_save                  ;save W register contents
	movf 	output_ctrl,W		;retrieve output_ctrl bits
	btfss 	output_ctrl,1		;check the tone enable bit
	goto 	end_interrupt		;straight back if tone not enabled
	xorlw 	B'00000001'		;toggle tone bit if tone enabled
	movwf 	output_ctrl		;save it back	

end_interrupt
	movwf 	PORTB			;write bits to the port
	movfw 	freq			;pre-load RTCC with freq value
	movwf 	RTCC			; which controls time to next int
	movf 	w_save,W		;restore original W contents
	retfie

;==========================================================
;initialize
init
	clrf 	output_ctrl		;start with everything disabled
	clrf 	msg
	clrf 	msg_ptr
 	clrf 	bitcount
	clrf 	w_save
	clrf 	STATUS
	clrf 	PORTA
	clrf 	PORTB
	clrf 	RTCC
	movlw 	H'30'			;set tone freq (H'30' gives 600Hz tone)
					;(H'83' gives 1000Hz tone)
	movwf 	freq		
	movlw 	H'80'			;set wpm (H'80' gives 100ms per dot width, approx 12wpm)
	movwf 	wpm		
	clrw
	bsf 	STATUS,5  		;switch to page 1
	movlw 	H'00'			;all port B to o/p mode
	movwf 	TRISB			;      
	movlw 	H'1F'			;all port A pins to input mode
	movwf 	TRISA
	movlw 	B'10000001'		;no pull-ups,prescale 001 = Xtal/16 to RTCC,
	movwf 	OPTREG
	bcf 	STATUS,5  		;switch to page 0
	movlw 	B'00100000'		;RTCC rollover int enabled (not global)
	movwf 	INTCON

;start of main program routine
test_input:
	btfsc	PORTA,0			;is chip enabled?
	goto	send_ID

	goto	test_input		;loop back to start of main routine

send_ID:
					;send morse ID
	bsf 	INTCON,7		;global interrupt enable
	bsf	output_ctrl,3		;set PTT, message in progress
	bsf	PORTB,3
	call	output_ID		;send ID - once started this cannot be stopped - no checks
	bcf 	output_ctrl,3		;reset msg in progress indicator (PTT off)
	bcf	PORTB,3
	bcf 	INTCON,7		;clear global interrupt	

delay5min
	clrf	speed1
	clrf 	speed2			;Initialize timer counters
	movlw 	H'39'			; 
	movwf 	speed3			;
	movlw 	H'06'			;
	movwf	speed4

delayloop2:
	decfsz 	speed1,same			
	goto 	delayloop2		;loop until time has elapsed		
	decfsz 	speed2,same		
	goto 	delayloop2		;loop until time has elapsed

enable_check:
	btfss	PORTA,0			;check every 200ms - is chip enabled?
	goto	test_input		;if it's not, return and go back to start of main routine
					;if it is, carry on for another 200ms
squelch_check					
	btfss	PORTA,1			;check every 200ms - is repeater Squelch open (high on A1)?
	goto	reset_old_bit
	btfss	input_store,1		;OK open now, but was it open at the last check?
	goto	set_old_bit		;no, go back to start
	goto	continue		;yes, just continue			
	
set_old_bit:
	bsf	input_store,1
	goto	test_input		;exit routine to start

reset_old_bit
	bcf	input_store,1

continue:
	decfsz 	speed3,same		
	goto 	delayloop2		;loop until time has elapsed
	decfsz	speed4,same
	goto	delayloop2		;loop until time has elapsed
	goto	test_input		;loop back to repeat whole process again


;end of main routine

;*******************************************************************************
;SUBROUTINES                                                                   *
;*******************************************************************************	


delay5sec					
	clrf 	speed1			;speed1 and speed2 set to 00 for 200ms basic delay
	movlw 	H'00'			; - changing these has little effect!!
	movwf 	speed2			; - because they are not reset for each loop 
	movlw 	H'19'			; -each bit = 200ms,  Decimal 25 (5sec)= Hex 19
	movwf 	speed3
	goto	delayloop

delay200ms					
	clrf 	speed1			;speed1 and speed2 set to 00 for 200ms basic delay
	movlw 	H'00'			; - changing these has little effect!!
	movwf 	speed2			; - because they are not reset for each loop 
	movlw 	H'01'			; -each bit = 200ms,  Decimal 1 (200ms)= Hex 01
	movwf 	speed3
delayloop:
	decfsz 	speed1,same		
	goto 	delayloop			
	decfsz 	speed2,same		
	goto 	delayloop
	btfss	PORTA,0			;check every 200ms - is chip enabled?
	return				;if it's not, return and go back to start of main routine
	decfsz 	speed3,same		;if it is, carry on for another 200ms
	goto 	delayloop		;loop until time has elapsed
	return

;**********************

set_tone:

	bsf 	output_ctrl,1		;set the tone enable bit
	bcf 	output_ctrl,2		;reset the dup. tone enable bit
	return

tone_off:		
	bcf 	output_ctrl,1		;reset the tone enable bit
	bsf 	output_ctrl,2		;set the dup. tone enable bit
	call	delay200ms
	call	delay200ms
	return

;**********************

;ID SUBROUTINES
output_ID 
	movlw H'00'
	call msg_loc
	movwf msg_ptr

msg_loop
	call msgtable			;read byte from message table
	movwf msg			;save in msg
	sublw H'FF'			;check if terminator char 'FF'
	btfsc STATUS,Z			;skip if not
	goto	end_ID			;return if terminator
	movlw H'09'			;initialize bit shift counter
	movwf bitcount

bit_loop
	decfsz bitcount,same		;count shifts down to zero
	goto send_bit			;send bit if more to process
	incf msg_ptr,same		;otherwise try next message byte
	movf msg_ptr,w
	goto msg_loop

send_bit
	bcf STATUS,C			;clear carry
	rlf msg,same			;shift MSB into carry
	btfss STATUS,C			;see if MSB in "msg" was set
	goto no_tone
					;send tone
	bsf output_ctrl,1		;set the tone enable bit
	bcf output_ctrl,2		;reset the dup. tone enable bit

slow_down
	call delay			;send tone for specified period
	goto bit_loop			;send next bit

no_tone
	bcf output_ctrl,1		;reset the tone enable bit
	bsf output_ctrl,2		;set the dup. tone enable bit
	goto slow_down

end_ID
	bsf output_ctrl,1		;clear (set) the tone enable bit
	bcf output_ctrl,2		;clear the dup. tone enable bit
	return

;           *********************
delay					;sets bit (dot) time
	clrf speed1
	movfw wpm			;depends on defined wpm setting
	movwf speed2
delay_loop
	decfsz speed1,same
	goto delay_loop
	decfsz speed2,same
	goto delay_loop
	return
;            *********************

msg_loc
	addwf PC,same
	retlw msg_1 - msgtable - 1


;            *********************
msgtable
	addwf PC,same
msg_1   retlw   B'00000000'
	retlw	B'11101010'		;DE
	retlw	B'00100000'
	retlw	B'00111010'		;XE3MSL
	retlw	B'10111000'
	retlw	B'10001010'
	retlw	B'10111011'
	retlw	B'10001110'
	retlw	B'11100010'
	retlw	B'10100010'
	retlw	B'11101010'
	retlw	B'00111011'		;,
	retlw	B'10101011'
	retlw	B'10111000'
	retlw	B'00001000'		;EK16TL
	retlw	B'11101011'
	retlw	B'10001011'
	retlw	B'10111011'
	retlw	B'10111000'
	retlw	B'11101010'
	retlw	B'10100011'
	retlw	B'10001011'
	retlw	B'10101000'
	retlw	B'00000000'		;(zeros added at end to pad out)
	retlw	B'11111111'		;end of message code


;********************************************************************
;INFORMATION

;To customise with own callsign- use text editor to assemble a string of binary code
;from the table below.  Then break up the string into eight bit bytes
;and put after a 'retlw   B' command.  For example:

;DE XE3MSL, EK16TL as a binary string is:
;1110101000 1  0000000
;11101010111000 1000 1010101110111000 1110111000 10101000 101110101000 1110111010101110111000
;1000 111010111000 10111011101110111000 11101010101000 111000 101110101000		
;(the gaps would not normally be there
;they have been left in to help understanding of how the binary is assembled
;from each coded character)

;Split into eight bit bytes:


;11101010
;00100000
;00111010
;10111000
;10001010
;10111011
;10001110
;11100010
;10100010
;11101010
;00111011
;10101011
;10111000
;00001000
;11101011
;10001011
;10111011
;10111000
;11101010
;10100011
;10001011
;10101000
;00000000		;(zeros added at end to pad out)
;11111111		;(end of message code at end)

; ************************************************************************************
;DATA

;Morse Code in digital format for easy copying to text string

;A-10111000		N-11101000
;B-111010101000		O-11101110111000
;C-111010101101000	P-10111011101000
;D-1110101000		Q-1110111010111000
;E-1000			R-1011101000
;F-101011101000		S-10101000
;G-111011101000		T-111000
;H-1010101000		U-1010111000
;I-101000		V-101010111000
;J-1011101110111000	W-101110111000
;K-111010111000		X-11101010111000
;L-101110101000		Y-1110101110111000
;M-1110111000		Z-11101110101000

;1-10111011101110111000		6-11101010101000
;2-101011101110111000		7-1110111010101000
;3-1010101110111000		8-111011101110101000
;4-10101010111000		9-11101110111011101000
;5-101010101000			0-1110111011101110111000

;/-1110101011101000

;Sp-0000000
;comma-1110111010101110111000
;HEX values:
;0000=0	0001=1	0010=2	0011=3	0100=4	0101=5	0110=6	0111=7	
;1000=8	1001=9	1010=A	1011=B	1100=C	1101=D	1110=E	1111=F
;----------------------------------------------------------------


;==========================================================

	END
