;File history
;tone -orig file downloaded from BATC 6apr98 - author: Brian Kelly GW6BWX
;tone8g- Much simplified for IK6GZM's repeater - CW output after 8 min time delay
;tone8h- revised time delay SRs


;Hardware details
;PIC chip pin out info (view from top):

;		  RA2	oo U	o   RA1
;		  RA3	o	o   RA0 
;		  RA4	o	o   +5v
;		  Reset	o	o   xtl
;		  Gnd	o	o   xtl
;		  RB0	o	o   RB7
;		  RB1	o	o   RB6
;		  RB2	o	o   RB5
;		  RB3	o	o   RB4


;Clock uses 4MHz crystal
;RA0-4 are inputs
;	RA0,  This input for beacon ON - use as "enable" pin
;	RA1,  
;	RA2,  
;	RA3,  
;	RA4  
;	RB0-3 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 inverted RB1 Tone envelope - drives LED only - to avoid loading keyer output 
;	RB3	Message in progress (PTT output during CW ID)
;----------------------------------------------

;Define processor configuration
	list    P=16C84, 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	1AH        	;contents set tone frequency	      
wpm		equ	1BH		;contents set morse speed



;------------------------------------------------

;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 16C84

reset   goto 	init

	org     4
	goto 	interrupt
;==========================================================


;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

;==========================================================

;Main Program routine
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'10'			;set tone freq (H'10' gives 1000Hz tone)
					;to reduce the tone freq significantly it will 
					;be necessary to invoke the RTCC prescaler 
	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'			;set port A pins to input mode
	movwf TRISA
	movlw B'10000000'		;no pull-ups,f/4 to RTCC,prescale 000
	movwf OPTREG
	bcf STATUS,5  			;switch to page 0
	movlw B'00100000'		;RTCC rollover int enabled (not global)
	movwf INTCON

test_input:
	btfss	PORTA,0			;is chip enabled?
	goto	test_input		;go back to start of main routine
	call 	delay8min		;					


ID:					;then send ID
	bsf 	output_ctrl,3		;set msg in progress indicator (PTT)
	call	output_ID		;send ID - no checks for enable bit during sending
	bcf 	output_ctrl,3		;reset msg in progress indicator (PTT)
	goto	test_input		;loop back to repeat whole process again

; End of main routine

;*******************************************************************************
;SUBROUTINES                                                                   *
;*******************************************************************************	

delay8min					
	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'00'			; -each bit = 200ms,  Decimal 25 (5sec)= Hex 19
	movwf 	speed3
	movlw	H'09'			;the number in here is "mins required plus 1" in Hex
	movwf 	speed4
	goto	delayloop

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
	decfsz 	speed4,same		
	goto 	delayloop
	return

;********************************************************************
;ID SUBROUTINES
output_ID 
	movlw H'00'
	call msg_loc
	movwf msg_ptr
	bsf INTCON,7			;global interrupt enable

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
	bcf output_ctrl,1		;reset the tone enable bit
	bsf output_ctrl,2		;set the dup. tone enable bit
	bcf INTCON,7			;clear the global interrupt
	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'		;pause
	retlw	B'10100011'		;IK6GZM
	retlw	B'10101110'
	retlw	B'00111010'
	retlw	B'10101000'
	retlw	B'11101110'
	retlw	B'10001110'
	retlw	B'11101010'
	retlw	B'00111011'
	retlw	B'10000000'		;end padded out with zero's	
	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:

;G6GXK/P as a binary string is:
;111011101000 11101010101000 111011101000 11101010111000 111010111000 
;1110101011101000 10111011101000  (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:
;11101110	
;10001110	
;10101010	
;00111011	
;10100011	
;10101011	
;10001110	
;10111000 	
;11101010	
;11101000	
;10111011	
;101000 		(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

;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
