;******************************************************************************
;*********   DDS(AD9851) RF-GENERATOR (1Hz-35MHz) CONTROLLED BY A   ***********
;******     PIC16F877A MICROCONTROLLER. A 4x4 KEYPAD, AN LCD DISPLAY,  ********
;*****   A ROTARY ENCODER AND SOME SWITCHES ARE USED AS HUMAN INTERFACE.  *****
;****************************************************************************** 
; AUTHOR: F.KLINKER,PA3DDN,21-07-2010.
; e-mail: pa3ddn@amsat.org
;
; FILE	:C:\PICprogs\sweepgen_v14.asm
;
; DESCRIPTION:
; The generator is based on the use of a PIC16F877A microcontroller, using a
; 4x4 keypad, a 2x16 LCD display, some switches and a rotary encoder as human
; interfaces . The AD9851 DDS chip is the RF device.
;
; Using the generator is a rather rigid menu-driven operation as will be clear
; from the description below:
;
; After start-up the following message is displayed during a few seconds:
;                            =DDS-GENERATOR=
;                             = 1Hz-35MHz = 
; Then the main menu 
;                            A=MODE  B=FSTART 
;                            C=FSTEP D=CHECK
; will appear on the screen.
; The buttons A,B,C,and D on the keypad are now activated.
;
; The A button selects the MODE menu: SWEEP=1,CW=2,and SINGLE-SHOT=3.
;
; The B button selects the start frequency menu FSTART for the input of FSTART
; while the display shows the frequency in kHz. The use of # terminates the 
; input. The use of the B button is required for all modes.
;
; The C button selects the frequency step menu FSTEP, again with the display
; showing the inserted frequency in kHz and with # used to terminate the input.
; Again the use of the C button is required for all modes even for the CW mode
; where a default value of 1kHz is used when starting.  
;
; The D button selects the test menu. It signals the absence of a start
; frequency and/or of the frequency step. If all is correct and the mode is
; SWEEP or SINGLE-SHOT the start frequency, the frequency step and the
; calculated value of the stop frequency after 250 steps are subsequently 
; displayed during 2 seconds.Of course, in the CW mode no stop frequency is
; calculated and displayed. Only the start frequency and the frequency step are
; displayed during 2 seconds after pushing the D button.
;
; The test menu concludes with the message: OK? YES=1 NO=0.
; If it is not OK then 0 is put in and the program returns to the main menu 
; and corrections can be carried out using the A,B and C buttons and the 
; corresponding menu. 
; If all is OK and 1 is pressed, control is transferred to the S1 to S4 buttons
; near the LCD display for starting and stopping the selected mode.
;
; If the mode is SWEEP the display will show SWP SPEED= 100 .After pushing S1
; to start, the sweep wil be carried out at maximum speed. RF is generated and
; the RF ON led is lit.
; Pushbuttons S2 (>) and S3 (<) (SPEED/STEP) can be used to increase or decrease
; thespeed respectively, where 100 indicates the maximum and 1 the minimum 
; speed. In fact, the indication is in percentage of maximum speed.
; In the SWEEP mode a marker can be switched on or off by S5 (MARKER ON).
; The marker consists of a bright spot on the scope display which can be moved
; over the trace by the rotary encoder (CW FREQ/MARKER).
; The frequency corresponding to the position of the marker is displayed on the
; bottom line of the LCD display which then shows:
; 				SWP SPEED=100
; 				xx,xxx.xxx kHzMKR
; S4 (STOP) can be used to leave the SWEEP mode and to return to the main menu.
;                      
; The SINGLE-SHOT mode is just one single trace of the SWEEP mode. It can be
; started with S1 (START) and the speed of it can be adjusted in the same way
; as in the SWEEP, using S2 (>) and S3 (<) (SPEED/STEP). 
; The marker is not used in this mode.
; S4 (STOP) can be used to leave the SINGLE-SHOT mode and to return to the main
; menu.
;
; When the CW mode has been selected the display will show:
;                            CW   STEP= 1k
;                            xx,xxx.xxx kHz   
; the bottom line showing the start frequency.
; The CW mode is entered directly from the check menu (D button) without the use
; of S1 (START). The DDS starts immediately on the displayed frequency and the
; yellow (RF ON) led is illuminated.The rotary encoder (CW FREQ/MARKER) is used
; for tuning.
; In this mode the generator can be tuned over nearly the full range, the lower
; limit being less than or equal to the frequency step value and the upper limit
; being the maximum frequency of 35MHz.  
; The frequency step size, which is set at 1kHz at the start, can be changed 
; using S2 (>) or S3 (<) over the range 1Hz-10Hz-100Hz-1kHz-10kHz-100kHz-1MHz.
; Again, S4 (STOP) can be used to leave the CW mode and to return to the main
; menu.
;
; When returning to the main menu, all settings i.e. start frequency, frequency
; step and mode remain stored or can be changed if required. To start again the
; check menu has to be invoked again by pushing the D button on the keypad.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;
; Acknowledgements:
;
; My sincere thanks go to a number of very friendly persons who allowed me 
; to use and modify their software.  
;
; Firstly, there is Alan, M0PUB, who kindly provided the assembly code of
; the QRP2004 project of which I have borrowed many interesting ideas.
; The QRP2004 assembly code was made available under the following conditions:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copyright (c) MPC Data Limited, 1998 - 2006                                ;
;                                                                            ;
; LICENSE CONDITIONS                                                         ;
; ------------------                                                         ;
;                                                                            ;
; Redistribution and use in source and binary forms, with or without         ;
; modification, are permitted provided that the following conditions         ; 
; are met:                                                                   ;
; 1. Redistributions of source code must retain the copyright notice,        ;
; this list of conditions and the following disclaimer.                      ;
; 2. Redistributions in binary form must reproduce the copyright notice,     ;
; this list of conditions and the following disclaimer in the documentation  ;
; and/or other materials provided with the distribution.                     ;
; 3. All advertising materials mentioning features or use of this            ;
; software must display the following acknowledgement:                       ;
;   This product includes software developed by MPC Data Limited,            ;
;   Bradford-on-Avon, England                                                ;
;                                                                            ;
; DISCLAIMER                                                                 ; 
; ----------                                                                 ;
;                                                                            ;
; THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR         ;
; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  ;
; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.    ;
; IN NO EVENT SHALL MPC DATA LIMITED OR THE AUTHOR BE LIABLE FOR ANY DIRECT, ;
; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES         ; 
; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,        ;
; STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN   ;
; ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY; 
; OF SUCH DAMAGE.                                                            ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	
; Secondly, there is Craig Johnson, AA0ZZ, who gladly gave his permission to 
; use and modify some routines of his "HF VFO with AD9854 DDS,version 5.19b" 
; software. 
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Finally, Johan Bodin, SM6LKM, from whose "AD9832_4.asm" software I borrowed
; the rotary encoder routines. 
; Unfortunately, no contact could be established with Johan. 
;	                      
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;******************************************************************************
;****************        PIC TYPE AND CONFIGURATION           *****************
;****************************************************************************** 

	#include P16F877A.INC
	LIST P=16F877A
	
	__CONFIG 0x3F72		;CP OFF,DEBUG OFF,WRT ENAB,CPD EE OFF,LVP OFF,
				;BOREN ENAB,PWRT ENAB,WDT OFF,HS OSC.

;******************************************************************************
;****************               USER VARIABLES                *****************
;****************************************************************************** 

 		CBLOCK 0x20	
	BCD_0			;BCD output of bin2BCD (32-bits binary  
	BCD_1			;to 10-digit BCD number).
	BCD_2			;Also input for show_freq.
	BCD_3			;
	BCD_4			;
;
	BCD_count		;Loopcounter in bin2BCD.
	BCD_temp		;Temporary register in bin2BCD.
;
	count			;Loopcounter in dblcpy and wait2s. 
;	
	d1100m			;Loopcounter in wait100ms.			
	d12m			;Loopcounter in wait2ms.
	d2100m			;Loopcounter in wait100ms.	
	d22m			;Loopcounter in wait2ms.
	d3100m			;Loopcounter in wait100ms.	
	d50u			;Loopcounter in wait50us.
;
	dacca_0			;32-bits number in dbladd, fstart_entry, 
	dacca_1			;fstep_entry and prep_regs.
	dacca_2			;
	dacca_3			;
;
	daccc_0			;32-bits number in calc_dds_word,dbladd,
	daccc_1			;fstart_entry,fstep_entry,test_entry,run,
	daccc_2			;marker_gen,prep_regs and check_fhigh.
	daccc_3			;
;
	del_fact		;delay factor(loopcounter) in run,speed_s2,
;				;speed_s3,wait_var.
	dwv1			;loopcounter in wait_var.				
	dwv2			;loopcounter in wait_var.
;
	enc_cntd		;loopcounter in read_enc.
	enc_cnti		;loopcounter in read_enc.
	enctmp			;temporary register in read_enc.
;
	flags_0			;flag register containing PROC_FLAG,MODE_FLAG,
;				;FSTART_FLAG,FSTEP_FLAG,FIRST_TIME,DDS_REGF,
;				;S2_FLAG and S3_FLAG.
;
	flags_1			;flag register containing SSHOT_FLAG,STOP_FLAG,
;				;MAX_FREQ_FLAG,MARKER_FLAG 
;
	freq_0			;32-bits number used as input for bin2BCD to
	freq_1			;display the frequency in fstart_entry,
	freq_2			;fstep_entry,test_entry,run and marker_gen.
	freq_3			;
;
	fstart_0		;32-bits number containing the start frequency
	fstart_1		;in fstart_entry,test_entry and prep_regs.
	fstart_2		;
	fstart_3		;
;
	fstep_0			;32-bits number containing the frequency step
	fstep_1			;(increment) in fstep_entry,test_entry end
	fstep_2			;prep_regs.
	fstep_3			;
;
	fzero			;byte counter in test_entry
;
	hund			;hundreds digit in show_3digs and byte2bcd.
;
	lastkey			;temporary key input storage in mode_entry,
;				;fstart_entry,fstep_entry and test_entry.
	loopcnt			;loopcounter in send_dds.
	lpcnt			;loopcounter in fstart_entry,fstep_entry,
;				;test_entry,run and marker_gen.
	lpcnt_mod		;loopcounter in test_entry,run and marker_gen.
;
 	marker			;marker position byte in read_enc and
;				;marker_gen.
	max_freq_0		;32-bits number representing the maximum
	max_freq_1		;frequency of 35,000,000 Hz in start/main,test_
	max_freq_2		;entry and check_fhigh.
	max_freq_3		;
;
	mult_count 		;loopcounter in calc_dds_word.
;
	nsteps			;number of steps (250) 
;
	oned			;ones digit in show_3digs and byte2bcd.
;
	osc_temp_0		;32-bits number for temporary storage of dds
	osc_temp_1		;calibration factor (oscal) in calc_dds_word.
	osc_temp_2		;
	osc_temp_3		;
;
	oscal_0			;32-bits number containing the dds calibration
	oscal_1			;factor in start/main and calc_dds_word.
	oscal_2			;
	oscal_3			;
;
	prevenc			;previous encoder state in read_enc.
;
        result_0		;40-bits number containing the result of the          
        result_1          	;multiplication of the frequency in Hz and
        result_2          	;the dds calibration factor in calc_dds_word
        result_3          	;and load_dds.
        result_4    		;
;
	rptcount		;loopcounter in start/main.
;
	speed_sel		;speed selector index in select_speed,run,
;				;speed_s2,speed_s3,wait_var.
	speed_ind		;speed indicator in % of maximum speed in
;				;select_speed,run.
	step_ind		;stepsize indicator (1-7,for 1Hz-1MHz)
;				;used in run_step
	temp_0			;16-bits word controlling the dds used in
	temp_1			;load_dds and send_dds.
;
	temp_del		;loopcounter in wait_var.
	temp_lcd		;temporary storage in data2lcd and cmd2lcd.
	tend			;tens digit in show_3digs and byte2bcd.
	tmp			;temporary storage in dblcpy.
	tmp16:2			;16-bits word used as temporary storage in
;				;dblcpy.
	tmpk			;temporary storage of key value in start/main,
;				;readKey,mode_entry,fstart_entry,fstep_entry
;				;and test_entry.
		ENDC

;*****************************************************************************
;****************            PORTS DEFINITIONS                ****************
;***************************************************************************** 

#define	LCD_EN		PORTA,0		;LCD ENABLE 			OUTPUT 
#define	LCD_CD		PORTA,1		;LCD COMMAND-DATA (RS)		OUTPUT  
                  		        ;LCD R/W HARD-WIRED FOR WRITE
#define	DDS_WCLK	PORTA,2		;DDS W_CLOCK			OUTPUT
#define DDS_FQUD	PORTA,3		;DDS FQ_UD 			OUTPUT
#define	DDS_RESET	PORTA,4		;DDS RESET 			OUTPUT

#define	MKR_UP		PORTB,0		;MARKER UP CONTACT OF ENCODER	INPUT
#define	MKR_DWN		PORTB,1		;MARKER DOWN CONTACT OF ENCODER	INPUT
#define	MARKER_OUT	PORTB,2		;MARKER FREQUENCY OUTPUT PULSE	OUTPUT 
#define	S5_MARKER	PORTB,3		;MARKER ON/OFF SWITCH 		INPUT 

;FOR 4 BITS LCD CONTROL ONLY D4-D7 ARE REQUIRED
#define	LCD_D4		PORTB,4		;LCD DATA 			OUTPUT 
#define	LCD_D5		PORTB,5		;LCD DATA 			OUTPUT 
#define	LCD_D6		PORTB,6		;LCD DATA 			OUTPUT 
#define	LCD_D7		PORTB,7		;LCD DATA 			OUTPUT 

;PORTC IS DDS_DATA OUTPUT 

#define	S1_START	PORTA,5		;START/STEP BUTTON		INPUT
					;OR SWEEP_RESET PULSE		OUTPUT									
#define	S2_FAST		PORTE,0		;FASTER SWEEP BUTTON 		INPUT
#define	S3_SLOW		PORTE,1		;SLOWER SWEEP BUTTON 		INPUT
#define	S4_STOP		PORTE,2		;STOP SWEEP/STEP BUTTON 	INPUT

#define	KEY_OUT4	PORTD,0		;KEYPAD				OUTPUT 
#define	KEY_IN1		PORTD,1		;KEYPAD				INPUT 
#define	KEY_IN2		PORTD,2		;KEYPAD				INPUT 
#define	KEY_IN3		PORTD,3		;KEYPAD				INPUT 
#define	KEY_IN4		PORTD,4		;KEYPAD				INPUT 
#define	KEY_OUT1	PORTD,5		;KEYPAD				OUTPUT
#define	KEY_OUT2	PORTD,6		;KEYPAD				OUTPUT 
#define	KEY_OUT3	PORTD,7		;KEYPAD				OUTPUT 

;******************************************************************************
;****************          KEYPAD DEFINITIONS 4x4             *****************
;****************************************************************************** 

#define KEY_IN_MASK 0x1E

#define STAR_KEY		.10         ; Key code for * key
#define ZERO_KEY		.11         ; Key code for '0' key
#define HASH_KEY 		.12         ; Key code for # key
#define	A_KEY			.13	    ; Key code for A key
#define	B_KEY			.14	    ; Key code for B key
#define	C_KEY			.15	    ; Key code for C key
#define	D_KEY			.16	    ; Key code for D key

#define	NO_KEY			.99
#define KEY_DEBOUNCE_TIME	.20
#define	RPT_INIT		0xFF	


;******************************************************************************
;****************       SPECIAL FUNCTIONS DEFINITIONS         *****************
;****************************************************************************** 
#define _C STATUS,0
#define _Z STATUS,2

#define	PROC_FLAG 		flags_0,0
#define	MODE_FLAG		flags_0,1
#define	FSTART_FLAG		flags_0,2
#define	FSTEP_FLAG		flags_0,3	
#define	FIRST_TIME		flags_0,4
#define	DDS_REGF		flags_0,5
#define	S2_FLAG			flags_0,6
#define	S3_FLAG			flags_0,7
#define SSHOT_FLAG		flags_1,0
#define	STOP_FLAG		flags_1,1
#define	MAX_FREQ_FLAG	flags_1,2
#define	MARKER_FLAG		flags_1,3
#define	FREQ_UP_FLAG	flags_1,4
#define	FREQ_DWN_FLAG	flags_1,5
#define	ICH_FLAG		flags_1,6



;****************************************************************************
;**************   RESET VECTOR (16F877A resets to 0x00)   ******************* 
;**************           AND INTERRUPT VECTOR            ******************* 
;****************************************************************************

        ORG     0x0000
        goto    start

;interrupt vector     
        ORG     0x0004 
stop:
		goto	stop

;****************************************************************************
;****************************   read_enc    *********************************
;****************************************************************************
;F.Klinker,11-11-2009.
;Routine copied from Johan Bodin's (SM6LKM) ad9832_4.asm file and modified

read_enc:
	bcf	FREQ_DWN_FLAG	;clear step flags
	bcf	FREQ_UP_FLAG
				
	movf	PORTB,w		; read current encoder state into...
	andlw	B'00000011'	; select encoder bits
	movwf	enctmp		; ...enctmp (bits 0 and 1)

	bcf	enctmp,2	; copy previous encoder state into...
	btfsc	prevenc,0	; ...enctmp (bits 2 and 3)
	bsf	enctmp,2
	bcf	enctmp,3
	btfsc	prevenc,1
	bsf	enctmp,3

	movwf	prevenc		; save current encoder state for next
                                ; tick

	movf	enctmp,w	; get combination of previous and new
				; state
	andlw	0x0F		; remove garbage from upper nibble
	addwf	PCL,f		; bounce in jump table below

	goto	enc_done	; 00 -> 00 = no change
	goto	enc_inc		; 00 -> 01 = increment
	goto	enc_dec		; 00 -> 10 = decrement
	goto	enc_done	; 00 -> 11 = illegal, ignore
	goto	enc_dec		; 01 -> 00 = decrement
	goto	enc_done	; 01 -> 01 = no change
	goto	enc_done	; 01 -> 10 = illegal, ignore
	goto	enc_inc		; 01 -> 11 = increment
	goto	enc_inc		; 10 -> 00 = increment
	goto	enc_done	; 10 -> 01 = illegal, ignore
	goto	enc_done	; 10 -> 10 = no change
	goto	enc_dec		; 10 -> 11 = decrement
	goto	enc_done	; 11 -> 00 = illegal, ignore
	goto	enc_dec		; 11 -> 01 = decrement
	goto	enc_inc		; 11 -> 10 = increment
	goto	enc_done	; 11 -> 11 = no change

#if ($ > .256)
 error "Jump table out of permissible memory area"
#endif

enc_dec:
	decfsz	enc_cnti,f		;there are 4 pulses between the
					;detents, effort
	goto	enc_done		;to remove them

	btfsc	MODE_FLAG		;test for step mode
	goto	step_dwn		;yes it is 
					;no it is sweep mode
	movf	marker,w		;check if marker is less than 
	subwf	nsteps,w		;nsteps
	btfsc	_Z
	goto	enc_done		;it is equal, do nothing (high
					; end of range)
					;it is less so increase marker
	incf	marker,f		;lpcnt in freq loop decreases 
					;with increasing frequency,so 
					;marker has to increase here
	goto	res_cnti

step_dwn:	              	
	bsf	FREQ_DWN_FLAG
	bcf	FREQ_UP_FLAG	
		
res_cnti:
	movlw	D'4'		;reset the pulse counter			
	movwf	enc_cnti
	goto	enc_done		

enc_inc:
	decfsz	enc_cntd,f	;there are 4 pulses between the detents
	goto	enc_done	;effort to remove them

	btfsc	MODE_FLAG	;test for step mode
	goto	step_up		;yes it is 
				;no it is sweep mode
	movf	marker,w	;check if marker is greater than 1
	sublw	D'1'
	btfsc	_Z
	goto	enc_done	;it is 1, do nothing (low end of range)
				;it is greater so decrease it
	decf	marker,f	;lpcnt in freq loop decreases with 
				;increasing frequency,so marker has to
				;decrease here
	goto	res_cntd

step_up:
	bsf	FREQ_UP_FLAG
	bcf	FREQ_DWN_FLAG	
		
res_cntd:
	movlw	D'4'		;reset the pulse counter
	movwf	enc_cntd
	goto	enc_done	

enc_done:
	return

;******************************************************************************
;**************************      select_speed       ***************************
;******************************************************************************
;F.Klinker,06-12-2009 
;22-07-2010: del_fact values updated.

select_speed:
	movf	speed_sel,w		
	addwf	PCL,f	;perform table lookup to define
	goto	D0 	;del_fact,the delay factor in wait_var, and
	goto	D1	;speed_ind the value for the speed (in % of the
	goto	D2	;maximum) as shown on the lcd display
	goto	D5
	goto	D10
	goto	D20
	goto	D50
	goto	D100

#if ($ > .256)
 error "Jump table out of permissible memory area"
#endif

D0:
;speedsel equals 0 thus cleart del_fact and set speed_ind to 100 (%)
	clrf	del_fact
	movlw	D'100'
	movwf	speed_ind
	return		

D1:
	movlw	D'1'
	movwf	del_fact
	movlw	D'50'
	movwf	speed_ind
	return

D2:
	movlw	D'2'
	movwf	del_fact
	movlw	D'33'
	movwf	speed_ind
	return

D5:
	movlw	D'4'
	movwf	del_fact
	movlw	D'20'
	movwf	speed_ind
	return

D10:
	movlw	D'9'
	movwf	del_fact
	movlw	D'10'
	movwf	speed_ind
	return

D20:
	movlw	D'19'
	movwf	del_fact
	movlw	D'5'
	movwf	speed_ind
	return

D50:
	movlw	D'49'
	movwf	del_fact
	movlw	D'2'
	movwf	speed_ind
	return

D100:
	movlw	D'99'
	movwf	del_fact
	movlw	D'1'
	movwf	speed_ind
	return




;******************************************************************************
;************************     START and  MAIN LOOP     ************************      
;******************************************************************************

start:
	call	init_all

mainloop:

	call	lcd_cl
	movlw	'A'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'M'
	call	data2lcd
	movlw	'O'
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'B'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'F'
	call	data2lcd
	movlw	'S'	
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'A'	
	call	data2lcd
	movlw	'R'
	call	data2lcd 
	movlw	'T'
	call	data2lcd 

	movlw	0x0C		;make cursor invisible
	call	cmd2lcd

	movlw	0xC0		; Write on second line 							
        call    cmd2lcd		    

	movlw	'C'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'F'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'E'	
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	' '	
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'C'
	call	data2lcd
	movlw	'H'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'C'	
	call	data2lcd
	movlw	'K'
	call	data2lcd 


;start of local loop to leave the lcd display out of the loop while
;waiting, returns from the main routines are to the top mainloop.
;purpose: to make a stable display

mainloop1
	bcf	STOP_FLAG	;requires clearing after "stop"
						;return from using S4

;check keypad, in this part only the A,B,C and D button are used

	call    readKey
	btfsc   _Z
	goto 	clr_proc_flag

;   Here when a key is pressed (key number in tmp, 1 - 16).
;	If it has *just* been pressed, then ignore it for a little
;	while to avoid key-bounce - this is easily implemented by
;	taking advantage of the auto-repeat processing.

	movf    tmpk, W
	xorwf   lastkey, W      ;Is this a different key from last time ?
	btfsc   _Z
	goto    keyrepeat       ;No, so do autorepeat processing

;	Here if either a key had just been pressed OR we have detected a
;	different key from last time. Either way, set a short auto-repeat
;	interval and ignore for now. This provides effective key-debouncing.

	movf	tmpk, W
	movwf	lastkey			; Register new key
	movlw	KEY_DEBOUNCE_TIME
	movwf	rptcount		; Schedule for repeating soon...
	goto	keydone			; ..but don't actually process it yet.

;   Here if the same key is still held down. Check if it is time to
;   auto-repeat

keyrepeat:
	decf    rptcount, F
	btfss   _Z
	goto    keydone         ; Not time to auto-repeat, so do other checks

;   Here if we have a key press to act upon

proctest:
	btfsc	PROC_FLAG		; proc_flag is set when key has been 
	goto	keydone			; processed and key is still pressed

keyproc:
	movf    tmpk, W
	movwf   lastkey         ; Remember which key is now pressed
	bsf	PROC_FLAG	; Set proc_flag to prevent repeated processing
				; when key is kept pressed
	movlw   RPT_INIT
	movwf   rptcount        ; Reset auto-repeat counter for next time

;   Process a key press via jump table. The simple mechanism used here
;   relies on the whole of the jump table being in the bottom 256 words
;   of program store - hence the compile-time check at the end!!!

	movf    lastkey, W

actkey:
	addwf   PCL, F		
	goto    act_0			;0 At this place
	goto	act_1			;1 do nothing with
	goto    act_2			;2 numeric output
	goto    act_3			;3 
	goto    act_4			;4 Only the A,B,C
	goto    act_5			;5 and D keys are
	goto    act_6			;6 used to select
	goto    act_7			;7 the various data
	goto    act_8			;8 entry modes
	goto    act_9			;9
	goto    act_special1		;10 '*' key
	goto    mainloop1	        ;11 Invalid
	goto    act_special2		;12 '#' key
	goto	mode_entry		;13 'A' key
	goto	startfreq_entry		;14 'B' key
	goto	freqstep_entry		;15 'C' key
	goto	test_freqs		;16 'D' key
    	goto    mainloop1

#if ($ > .256)
 error "Jump table out of permissible memory area"
#endif

act_0:					;do nothing on numeric keys
	goto mainloop1
act_1:
	goto mainloop1
act_2:
	goto mainloop1
act_3:
	goto mainloop1
act_4:
	goto mainloop1
act_5:
	goto mainloop1
act_6:
	goto mainloop1
act_7:
	goto mainloop1
act_8:
	goto mainloop1
act_9:
	goto mainloop1
act_special1
	goto	mainloop1

act_special2					
	goto 	mainloop1		

mode_entry:
	call 	mode			; A is mode entry, sweep, single 
	goto	mainloop		; step, or single sweep

startfreq_entry:
	call	fstart_entry		; B is fstart entry
	goto	mainloop

freqstep_entry:
	call	fstep_entry		; C is fstep entry
	goto 	mainloop

test_freqs:
	call	test_entry		; D is test entry
	goto 	mainloop

nokey:
	movlw	NO_KEY
	movwf	lastkey			;no key press to process

clr_proc_flag
	bcf	PROC_FLAG

keydone:
	goto	mainloop1	




;******************************************************************************
;**************************        init_PIC         ***************************
;****************************************************************************** 

init_PIC:
	bsf	STATUS,RP0		;SWITCH TO REGISTER BANK 1 	
	movlw	0x06			;SET ALL A PINS TO DIGITAL!!!!!!!!!!!!
	movwf	ADCON1			; ,,  ,,  ,,  ,,    ,,    !!!!!!!!!!!!
	movlw	B'00100000'		;PORT A0 to A4 OUTPUTS 
					;(LCD COMMAND and DDS)
	movwf	TRISA			;PORT A5 INPUT (SWITCH S1)MAY BE 
					;CHANGED LATER TO OUTPUT FOR 
					;SWEEP_RESET 
	movlw	B'00001011'		;PORT B4-B7 OUTPUTS (LCD DATA),B2 
					;MARKER OUT
	movwf	TRISB	          	;PORT B0,B1 and B3 INPUTS (ROTARY
					;SWITCH FOR MARKER POSITION and
					;SWITCH FOR MARKER ON/OFF)
	movlw	B'00000000'		;PORT C OUTPUT (DDS_DATA)
	movwf	TRISC			;
	movlw	B'00011110'		;PORT D0 AND D5-D7 OUTPUTS,D1-D4 
					;INPUTS(KEYPAD)
	movwf	TRISD 
	movlw	B'00000111'		;PORT E0 to E2 INPUTS (SWITCHES 
					;S2 to S4)
	movwf	TRISE

	bcf	STATUS,RP0		;SWITCH TO REGISTER BANK 0 

	movlw	B'00000000'
	movwf	PORTA			;ALL COMMAND LINES LCD ARE LOW

        return


;*****************************************************************************
;************************         lcd_init4            ***********************
;*****************************************************************************

lcd_init4:
	call 	wait100ms		;WAIT 100 MSEC AFTER LCD POWER UP

	movlw	0x38			;8 BIT,2 LINES,5x7 FONT
;	movwf	PORTB			;FUNCTION SET 
;	call 	strobc
	call	cmd2lcd
	call	wait2ms

	movlw	0x38			;8 BIT,2 LINES,5x7 FONT
;	movwf	PORTB			;FUNCTION SET 
;	call 	strobc
	call	cmd2lcd
	call	wait2ms

	movlw	0x38			;8 BIT,2 LINES,5x7 FONT
;	movwf	PORTB			;FUNCTION SET 
;	call 	strobc
	call	cmd2lcd
	call	wait2ms

	movlw	0x28			;now we can command it to the proper 
	call 	cmd2lcd			;mode: 4 bits, 2lines, 5x7font

;;;;;;;;;;;;;;;;;;only top line of text, so try again;;;;;;;;;;;;;;;;;;;;;;;;;;
	movlw	0x28			;now we can command it to the proper
	call 	cmd2lcd			;mode: 4 bits, 2lines, 5x7font
;;;;;;;;;;;;;;;;;;;;;;;;;;it works but why????;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	movlw	0x08			;now blank the display (according 
	call	cmd2lcd			;to manual)

	movlw	0x0C			;and restore it with cursor hidden
	call 	cmd2lcd
	movlw	0x0E			;DISPLAY ON,CURSOR ON
	call	cmd2lcd
		
	call	lcd_cl			;CLEAR DISPLAY,CURSOR TO HOME POSITION
	
	movlw	0x06			;ENTRY MODE,DISPLAY SHIFT OFF,INCREMENT 
	call	cmd2lcd			;ADDRESS COUNTER

	return

;******************************************************************************
;************************         init_dds             ************************
;******************************************************************************
;	Initialize AD9851 chip

init_dds:
	bsf	DDS_RESET	;	
	nop
	nop
	bcf	DDS_RESET	

	return

;******************************************************************************
;************************         stop_dds             ************************
;******************************************************************************
;	Let AD9851 dds sleep

stop_dds:
	bsf	DDS_RESET

	return

;*****************************************************************************
;************************           lcd_cl             ***********************
;*****************************************************************************

lcd_cl:
	movlw	0x01			;CLEAR DISPLAY,CURSOR TO HOME POSITION
	call 	cmd2lcd
	return


;*****************************************************************************
;************************           data2lcd           ***********************
;************************      WRITE DATA TO LCD       ***********************
;*****************************************************************************
 
data2lcd:
	movwf	temp_lcd		;MOVE DATA TO TEMP
	andlw	0xF0			;REMOVE RIGHT HAND 4 BITS
	movwf	PORTB			;MOVE 4 BITS DATA TO PORTB
	call 	strobd	

	swapf	temp_lcd,w		;GET BITS 0-3 AS BITS 4-7 IN W
	andlw	0xF0			;REMOVE RIGHT HAND 4 BITS
	movwf	PORTB			;MOVE 4 BITS DATA TO PORTB
	call 	strobd	
	call	wait50us

	return

;*****************************************************************************
;************************           cmd2lcd            ***********************
;************************    WRITE COMMAND TO LCD      ***********************
;*****************************************************************************

cmd2lcd:
	movwf	temp_lcd		;MOVE DATA TO TEMP
	andlw	0xF0			;REMOVE RIGHT HAND 4 BITS
	movwf	PORTB			;MOVE 4 BITS DATA TO PORTB
	call 	strobc	

	swapf	temp_lcd,w		;GET BITS 0-3 AS BITS 4-7 IN W
	andlw	0xF0			;REMOVE RIGHT HAND 4 BITS
	movwf	PORTB			;MOVE 4 BITS DATA TO PORTB
	call 	strobc	
	call	wait2ms

	return

;*****************************************************************************
;************************           strobc             ***********************
;*****************************************************************************

strobc:
	bcf	LCD_CD			;SET COMMAND/DATA TO COMMAND
	bsf	LCD_EN			;RAISE STROBE LINE
	nop				;MINIMUM DELAY 220 ns
	nop
	bcf	LCD_EN			;LOWER STROBE LINE
	nop
	nop				;MINIMUM 280 ns DELAY

	return

;*****************************************************************************
;************************           strobd             ***********************
;*****************************************************************************

strobd:
	bsf	LCD_CD			;SET COMMAND/DATA TO DATA
	bsf	LCD_EN			;RAISE STROBE LINE
	nop				;MINIMUM DELAY 220 ns
	nop
	bcf	LCD_EN			;LOWER STROBE LINE
	nop
	nop				;MINIMUM 280 ns DELAY

	return

;*****************************************************************************
;************************           bin2BCD             **********************
;*****************************************************************************
; *                                                                          *
; * Purpose:  This subroutine converts a 32 bit binary number to a 10 digit  *
; *           BCD number.  The input value taken from freq(0 to 3) is        *
; *           preserved.  The output is in BCD(0 to 4). Each byte holds =>   *
; *           (hi_digit,lo_digit); most significant digits are in BCD_4.     *
; *           This routine is a modified version of one described in         *
; *           MicroChip application note AN526.                              *
; * Input:    The value in freq_0 ... freq_3                                 *
; * Output:   The BCD number in BCD_0 ... BCD_4                              *
;*****************************************************************************

bin2BCD
        movlw   0x20              ; Set loop counter
        movwf   BCD_count         ;   to 32
        clrf    BCD_0             ; Clear output
        clrf    BCD_1             ;   "     "
        clrf    BCD_2             ;   "     "
        clrf    BCD_3             ;   "     "
        clrf    BCD_4             ;   "     "

bin_loop
        bcf     STATUS,C          ; Clear carry bit in STATUS
;
; Rotate bits in freq bytes.  Move from LS byte (freq_0) to next byte freq_1).
; Likewise, move from freq_1 to freq_2 and from freq_2 to freq_3.
;
        rlf     freq_0,f          ; Rotate left, 0 -> LS bit, MS bit -> Carry
        rlf     freq_1,f          ; Rotate left, Carry->LS bit, MS bit->Carry
        rlf     freq_2,f          ; Rotate left, Carry->LS bit, MS bit->Carry
        rlf     freq_3,f          ; Rotate left, Carry->LS bit, MS bit->Carry
        btfsc   STATUS,C          ; Is Carry clear?If so,skip next instruction
        bsf     freq_0,0          ; Carry is set so wrap and set bit0 in freq_0
;
; Build BCD bytes. Move into LS bit of BCD bytes (LS of BCD_0) from MS bit of
; freq_3 via the Carry bit.
;
        rlf     BCD_0,f           ; Rotate left, Carry->LS bit, MS bit->Carry
        rlf     BCD_1,f           ; Rotate left, Carry->LS bit, MS bit->Carry
        rlf     BCD_2,f           ; Rotate left, Carry->LS bit, MS bit->Carry
        rlf     BCD_3,f           ; Rotate left, Carry->LS bit, MS bit->Carry
        rlf     BCD_4,f           ; Rotate left, Carry->LS bit, MS bit->Carry
        decf    BCD_count,f       ; Decrement loop count
        btfss   STATUS,Z          ; Is loop count now zero?
        goto    adjust            ; No, go to adjust
        return                    ; Yes, EXIT
;============================================================================
adjust
; Internal subroutine, called by bin2BCD main loop only
;
; As BCD bytes are being built, make sure the nibbles do not grow larger than 9
; If a nibble gets larger than 9, increment to next higher nibble.
; (If the LS nibble of a byte overflows, increment the MS nibble of that byte.)
; (If the MS nibble of a byte overflows, increment the LS nibble of next byte.)
;
        movlw   BCD_0             ; Get pointer to BCD_0
        movwf   FSR               ; Put pointer in FSR for indirect addressing
        call    adj_BCD           ;
        incf    FSR,f             ; Move indirect addressing pointer to BCD_1
        call    adj_BCD           ;
        incf    FSR,f             ; Move indirect addressing pointer to BCD_2
        call    adj_BCD           ;
        incf    FSR,f             ; Move indirect addressing pointer to BCD_3
        call    adj_BCD           ;
        incf    FSR,f             ; Move indirect addressing pointer to BCD_4
        call    adj_BCD           ;
        goto    bin_loop          ; Back to main loop of bin2BCD
;============================================================================
adj_BCD
; Internal subroutine, called by adjust only
        movlw   3                 ; Add 3
        addwf   INDF,w            ;   to LS digit
        movwf   BCD_temp          ; Save in temp
        btfsc   BCD_temp,3        ; Is LS digit + 3 > 7  (Bit 3 set)
        movwf   INDF              ; Yes, save incremented value as LS digit
        movlw   0x30              ; Add 3
        addwf   INDF,w            ;   to MS digit
        movwf   BCD_temp          ; Save as temp
        btfsc   BCD_temp,7        ; Is MS digit + 3 > 7  (Bit 7 set)
        movwf   INDF              ; Yes, save incremented value as MS digit

        return                    ; Return to adjust subroutine


;*****************************************************************************
;************************          show_freq            **********************
;*****************************************************************************
; * Purpose:  Display the frequency setting on the LCD.                      *
; *           Initial value is 14,025.000 kHz (14 characters)                *
; * Input:    The values in BCD_4 ... BCD_0                                  *
; * Output:   The number displayed on the LCD                                *
;*****************************************************************************

show_freq
;		call	lcd_cl
;       movlw   0x81       	; Point the LCD to first LCD digit location
;modification,12-08-2009

	movlw	0xC0	; Write on second line (first is used for commands)							
        call    cmd2lcd	    ; Send starting digit location to LCD
;
; Running 4-bit mode, so need to send Most Significant Nibble first.
;
; Extract and send "XXXX" from byte containing "XXXXYYYY"
;  - Swap halves to get YYYYXXXX
;  - Mask with 0x0F to get 0000XXXX
;  - Add ASCII bias (0030XXXX)
;
        swapf   BCD_3,w           ; Swap 10MHz BCD digit into lower nibble of W
        andlw   0x0F              ; Mask for lower nibble only (0000XXXX)
        btfss   STATUS,Z          ; Is this digit a zero?
        goto    digit_non_zero    ; No, go and construct the non-zero digit
        movlw   ' '               ; Yes,pick up a ASCII space character instead
        goto    send_it           ;   and go send it

digit_non_zero 
        addlw   0x30              ; Add offset for ASCII char set (0030XXXX)

send_it
        call    data2lcd          ; Send byte in W to LCD
;
; Extract and send "YYYY" from byte containing "XXXXYYYY"
;   - Mask with 0x0F to get 0000YYYY
;   - Add offset for ASCII character set in LCD  (0030YYYY)
;
        movf    BCD_3,w           ; Put 1MHz BCD digit into lower nibble of W
        andlw   0x0F              ; Mask for lower nibble only (0000YYYY)
        addlw   0x30              ; Add offset for ASCII char set (0030YYYY)
        call    data2lcd          ; Send byte in W to LCD
;
        movlw   ','               ; Get a comma
        call    data2lcd          ; Send byte in W to LCD
;
        swapf   BCD_2,w           ; Swap 100KHzBCD digit into lower nibble of W
        andlw   0x0F              ; Mask for lower nibble only (0000XXXX)
        addlw   0x30              ; Add offset for ASCII char set (0030XXXX)
        call    data2lcd          ; Send byte in W to LCD
;
        movf    BCD_2,w           ; Put 10KHz BCD digit into lower nibble of W
        andlw   0x0F              ; Mask for lower nibble only (0000YYYY)
        addlw   0x30              ; Add offset for ASCII char set (0030YYYY)
        call    data2lcd          ; Send byte in W to LCD
;
        swapf   BCD_1,w           ; Swap 1KHz BCD digit into lower nibble of W
        andlw   0x0F              ; Mask for lower nibble only (0000XXXX)
        addlw   0x30              ; Add offset for ASCII char set (0030XXXX)
        call    data2lcd          ; Send byte in W to LCD
;
        movlw   '.'               ; Set up W with ASCII Period
        call    data2lcd          ; Send data byte in W to LCD
; =============================================================================
; For 16x2 LCD, don't move cursor address.Just continue for 9th character
; position
; =============================================================================
        movf    BCD_1,w           ; Put 100 Hz BCD digit into lower nibble of W
        andlw   0x0F              ; Mask for lower nibble only (0000YYYY)
        addlw   0x30              ; Add offset for ASCII char set (0030YYYY)
        call    data2lcd          ; Send data byte in W to LCD
;
        swapf   BCD_0,w           ; Swap 10 Hz BCD digit into lower nibble of W
        andlw   0x0F              ; Mask for lower nibble only (0000XXXX)
        addlw   0x30              ; Add offset for ASCII char set (0030XXXX)
        call    data2lcd          ; Send data byte in W to LCD
;
        movf    BCD_0,w           ; Put 1 Hz BCD digit into lower nibble of W
        andlw   0x0F              ; Mask for lower nibble only (0000YYYY)
        addlw   0x30              ; Add offset for ASCII char set (0030YYYY)
        call    data2lcd          ; Send byte in W to LCD
;
        movlw   'k'               ; Send a 'k'
        call    data2lcd          ;   to LCD
;
        movlw   'H'               ; Send an "H"
        call    data2lcd          ;   to LCD
;
        movlw   'z'               ; Send a 'z'
        call    data2lcd          ;   to LCD

;       movlw   ' '               ; Send a space
;       call    data2lcd          ;   to LCD
;
        return                    ;


;*****************************************************************************
;************************        calc_dds_word          **********************
;*****************************************************************************
; * Purpose:  Multiply the 32 bit number for oscillator frequency times the  *
; *           32 bit number for the displayed frequency.                     *
; *   Input:  The reference oscillator value in oscal_3 ... oscal_0 and the  *
; *           current frequency stored in daccc_3...daccc_0.                 *
; *           The reference oscillator value is treated as a fixed point     *
; *           real, with a 24 bit mantissa.                                  *
; *           osc_temp contains a copy of oscal                              *
; *  Output:  The result is stored in result_4 ... result_0.                 *
; *  Modification,12-08-2009,names                                           *
;*****************************************************************************

calc_dds_word
        clrf    result_0          ; Clear the result control word bytes
        clrf    result_1          ;
        clrf    result_2          ;
        clrf    result_3          ;
        clrf    result_4          ;
        movlw   0x20              ; Set count  to 32   (4 osc bytes of 8 bits)
        movwf   mult_count        ; Keep running count
        movf    oscal_0,w         ; Move the four osc bytes
        movwf   osc_temp_0        ; to temporary storage for this multiply
        movf    oscal_1,w         ; (Don't disturb original oscal bytes)
        movwf   osc_temp_1        ;
        movf    oscal_2,w         ; 
        movwf   osc_temp_2        ;
        movf    oscal_3,w         ;
        movwf   osc_temp_3        ;

mult_loop
        bcf     STATUS,C          ; Start with Carry clear
        btfss   osc_temp_0,0      ; Is bit 0 (Least Significant bit) set?
        goto    noAdd             ; No, don't need to add daccc term to total
        movf    daccc_0,w          ; Yes, get the daccc_0 term
        addwf   result_1,f        ;   and add it in to total
        btfss   STATUS,C          ; Does this addition result in a carry?
        goto    add7              ; No, continue with next daccc term
        incfsz  result_2,f        ; Yes, add one and check for another carry
        goto    add7              ; No, continue with next daccc term
        incfsz  result_3,f        ; Yes, add one and check for another carry
        goto    add7              ; No, continue with next daccc term
        incf    result_4,f        ; Yes, add one and continue

add7
        movf    daccc_1,w          ; Use the daccc_1 term
        addwf   result_2,f        ; Add daccc term to total in correct position
        btfss   STATUS,C          ; Does this addition result in a carry?
        goto    add8              ; No, continue with next daccc term
        incfsz  result_3,f        ; Yes, add one and check for another carry
        goto    add8              ; No, continue with next daccc term
        incf    result_4,f        ; Yes, add one and continue

add8
        movf    daccc_2,w          ; Use the daccc_2 term
        addwf   result_3,f        ; Add daccc term to total in correct position
        btfss   STATUS,C          ; Does this addition result in a carry?
        goto    add9              ; No, continue with next daccc term
        incf    result_4,f        ; Yes, add one and continue

add9
        movf    daccc_3,w          ; Use the daccc_3 term
        addwf   result_4,f        ; Add daccc term to total in correct position

noAdd
        rrf     result_4,f        ; Shift next multiplier bit into position
        rrf     result_3,f        ; Rotate bits to right from byte to byte
        rrf     result_2,f        ;
        rrf     result_1,f        ;
        rrf     result_0,f        ;
        rrf     osc_temp_3,f      ; Shift next multiplicand bit into position
        rrf     osc_temp_2,f      ; Rotate bits to right from byte to byte
        rrf     osc_temp_1,f      ;
        rrf     osc_temp_0,f      ;
        decfsz  mult_count,f      ; One more bit has been done.  Are we done?
        goto    mult_loop         ; No, go back to use this bit
        clrf    result_4          ; Yes, clear _4.  Answer is in bytes _3 .._0

        return                    ; Done.


;*****************************************************************************
;************************         par_load_dds          **********************
;*****************************************************************************
;	Update DDS chip with a new frequency word in parallel mode
;   F.Klinker,12-01-2010

par_load_dds:

;check that dds is awake
	bcf	DDS_RESET

;load first word W0
	movlw	B'00000000'	;phase 0 (bits7-3,power_down off (bit2),parall
				;input mode (bit1),REFCLK multiplier off (bit0)	
	movwf	PORTC		;put it in PORTC and
	bsf	DDS_WCLK	;move it into the DDS data register
	bcf	DDS_WCLK

;the next 4 bytes constitute the frequency word, starting with W1 as the 
;MS byte and so on.
;W1
	movf	result_3,w		;put result_3 (the MS byte) in W1
	movwf	PORTC			;put it in PORTC and
	bsf	DDS_WCLK		;move it into the DDS data register
	bcf	DDS_WCLK		

;W2
	movf	result_2,w		;put result_2 (the MS byte) in W2
	movwf	PORTC			;put it in PORTC and
	bsf	DDS_WCLK		;move it into the DDS data register
	bcf	DDS_WCLK	

;W3
	movf	result_1,w		;put result_1 (the MS byte) in W3
	movwf	PORTC			;put it in PORTC and
	bsf	DDS_WCLK		;move it into the DDS data register
	bcf	DDS_WCLK	

;W4
	movf	result_0,w		;put result_0 (the MS byte) in W4
	movwf	PORTC			;put it in PORTC and
	bsf	DDS_WCLK		;move it into the DDS data register
	bcf	DDS_WCLK	

;transfer the contents of the data register into the device
	bsf	DDS_FQUD
	bcf	DDS_FQUD			
	
	return

;*****************************************************************************
;************************           dblcpy              **********************
;*****************************************************************************
; dblcpy                                                                     *
; Copies a 4-byte (aka double length) variable into another 4-byte           *
; variable.                                                                  *
; Inputs: FSR already points to source variable, W points to                 *
;    destination variable                                                    *
; Output: none                                                               *
; Postconditions: corrupts count, tmp, tmp16, and FSR.                       *
;*****************************************************************************

dblcpy:
	movwf   tmp             ; Save dest pointer in tmp

	movlw   4
	movwf   count

cpyloop:
	movf    INDF, W         ; Get next byte
	movwf   tmp16          ; ..and save it
	incf    FSR, W
	movwf   tmp16+1           ; Save incremented source addr.

	movf    tmp, W
	movwf   FSR             ; Set up destination addr.
	movf    tmp16, W
	movwf   INDF            ; Copy byte to destination
	incf    FSR, W
	movwf   tmp             ; Save incremented dest addr.

	movf    tmp16+1, W
	movwf   FSR             ; Restore source addr to FSR

	decfsz  count, F
	goto    cpyloop         ; Repeat for other bytes

	retlw   0

;*****************************************************************************
;************************           dbladd              **********************
;*****************************************************************************
; Double length addition routine - adds a 32-bit number in dacca             *
; to the 32-bit number in daccc.                                             *
; Inputs: 32 bit values in dacca and daccc                                   *
; Output: daccc <- daccc + dacca                                             *
;*****************************************************************************

dbladd:
	movf    dacca_0, W
	addwf   daccc_0, F      ;add LSB
	btfss   _C
	goto    nocarry1

	incf    daccc_1, F      ;add in carry
	btfss   _Z
	goto    nocarry1

	incf    daccc_2, F      ;..and propagate on if necessary
	btfsc   _Z
	incf    daccc_3, F

nocarry1:
	movf    dacca_1, W
	addwf   daccc_1, F      ;...repeat for other bytes
	btfss   _C
	goto    nocarry2

	incf    daccc_2, F
	btfsc   _Z
	incf    daccc_3, F

nocarry2:
	movf    dacca_2, W
	addwf   daccc_2, F
	btfsc   _C
	incf    daccc_3, F

	movf    dacca_3, W
	addwf   daccc_3, F

	retlw   0

;*****************************************************************************
;************************           dblsub              **********************
;*****************************************************************************
; Double length subtract routine - subtracts a 32-bit number in dacca        *	
; from the 32-bit number in daccc. Only tested for the case where            *
; daccc > dacca.                                                             *
; Inputs: 32 bit values in dacca and daccc                                   *
; Output: daccc <- daccc - dacca                                             *
;*****************************************************************************

dblsub:
	movf    dacca_0, W
	subwf   daccc_0, F      ;subtract LSB
	btfsc   _C
	goto    noborrow1

	decf    daccc_1, F      ;subtract borrow
	incf    daccc_1, W
	btfss   _Z
	goto    noborrow1

	decf    daccc_2, F      ;..and propagate on if necessary
	incf    daccc_2, W
	btfsc   _Z
	decf    daccc_3, F

noborrow1:
	movf    dacca_1, W
	subwf   daccc_1, F      ;...repeat for other bytes
	btfsc   _C
	goto    noborrow2

	decf    daccc_2, F
	incf    daccc_2, W
	btfsc   _Z
	decf    daccc_3, F

noborrow2:
	movf    dacca_2, W
	subwf   daccc_2, F
	btfss   _C
	decf    daccc_3, F

	movf    dacca_3, W
	subwf   daccc_3, F
	retlw   0

;*****************************************************************************
;************************          readKey              **********************
;*****************************************************************************
; Checks the keypad for a key press. Assumes that the keyboard I/O           *
; lines have been configured as inputs and outputs as appropriate.           *
; NOTE: this routine doesn't block - it returns immediately, regardless      *
; of whether a key has been pressed.                                         *
; Note that at present this routine does not perform key debouncing,         *
; but this may change in future!                                             *
; Inputs: none                                                               *
; Output: If key pressed, Z flag is clear, and tmpk = key value (0 - 9,      *
;         HASH_KEY or STAR_KEY)                                              *
;         Else Z flag is set and tmpk is undefined.                          *
;*****************************************************************************

readKey:

;       Try to reduce RFI by normally only checking if *any* key has
;       been pressed, before bothering to scan for which one.

	clrf    tmpk             ; Initially assume no key pressed
	bcf	KEY_OUT1         ; Activate all keypad outputs
	bcf	KEY_OUT2    	 ; (Note: keyboard I/O is active low)
	bcf	KEY_OUT3
	bcf	KEY_OUT4
	call 	wait50us
	movlw   ~KEY_IN_MASK     ;..and look for active inputs
	iorwf   PORTD, w         ; (i.e. any which are *low*)
	xorlw   0FF
	btfsc   _Z	
            
	retlw   0               ; No keys pressed, so don't bother
               				; scanning for which one

;       Here when at least one key is being pressed - check which one.

	bcf		KEY_OUT1
	bsf		KEY_OUT2
	bsf		KEY_OUT3
	bsf		KEY_OUT4
	call	wait50us
	movlw   0
	movwf   tmpk            ; Prepare to scan keys 1 - 3 and A (=13)
	call    scanrow
	btfss   _Z
	goto    gotkey

	bsf	KEY_OUT1
	bcf	KEY_OUT2
	call 	wait50us
	movlw   .3
	movwf   tmpk            ; Scan keys 4 - 6 and B (=16)
	call    scanrow
	btfss   _Z
	goto    gotkey

	bsf	KEY_OUT2
	bcf	KEY_OUT3
	call	wait50us
	movlw   .6
	movwf   tmpk            ; Scan keys 7 - 9 and C (=19)
	call    scanrow
	btfss   _Z
	goto    gotkey

	bsf	KEY_OUT3
	bcf	KEY_OUT4
	call	wait50us
	movlw   .9
	movwf   tmpk            ; Scan keys 10 - 12 and D (=22)
	call    scanrow
	btfsc   _Z

	retlw   0

;       Here when a key has been pressed. (W + tmpk) gives the key number
;       in the range 1 to 12. However, we need to watch out for (and
;       adjust) a value of ZERO_KEY which has a key code that differs
;       from its numeric value.
;		(01-08-2009)
;		Also the A,B,C and D key have to be given successive numbers 
;		(13 to 16) to facilitate working with tables.


gotkey:
	addwf   tmpk, F
	movlw   ZERO_KEY
	xorwf   tmpk, W
	btfsc   _Z
	goto	zerok

	movlw	A_KEY
	xorwf	tmpk, W
	btfsc	_Z
	goto	Akey

	movlw	D'16'	
	xorwf	tmpk, W
	btfsc	_Z
	goto	Bkey

	movlw	D'19'	
	xorwf	tmpk, W
	btfsc	_Z
	goto	Ckey

	movlw	D'22'	
	xorwf	tmpk, W
	btfsc	_Z
	goto	Dkey

	bcf	_Z			; Ordinary numeric key

	retlw	1

zerok:
	clrf    tmpk             ; Convert code of ZERO_KEY to numeric 0
	bcf	_Z

	retlw   1

Akey:
	bcf	_Z			; tmpk = 13 for A

	retlw	1

Bkey:
	movlw	D'2'			; tmpk = 16
	subwf	tmpk, F			; tmpk = 14 for B
	bcf	_Z

	retlw	1

Ckey:
	movlw	D'4'			; tmpk = 19  
	subwf	tmpk, F			; tmpk = 15 for C
	bcf	_Z

	retlw	1

Dkey:
	movlw	D'6'			; tmpk = 22
	subwf	tmpk, F			; tmpk = 16 for D
	bcf	_Z

	retlw	1

;*****************************************************************************
;************************           scanrow             **********************
;*****************************************************************************
; Checks a single row of the keypad for a key press. Assumes that the        *
; keyboard I/O lines have been configured as inputs and outputs as           *
; appropriate, and the relevant row output has already been selected.        *
; Inputs: none                                                               *
; Output: If key pressed, Z flag is clear, and W = column of first           *
;         depressed key (1 - 3). Else Z flag is set and W = 0.               *
; Modification,29-07-2009: 4th column added for A,B,C and D key              *
;*****************************************************************************

scanrow:
;       Check each column input in turn
	bcf	_Z
	btfss   KEY_IN1         ; Note: key inputs are active low
	retlw   D'1'
	btfss   KEY_IN2
	retlw   D'2'
	btfss   KEY_IN3
	retlw   D'3'
	btfss   KEY_IN4
	retlw   D'13'
	bsf	_Z

	retlw   0

;******************************************************************************
;************************         mode_entry           ************************
;******************************************************************************

mode:
;first line of text

	call	lcd_cl
	movlw	'S'
	call	data2lcd
	movlw	'W'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'1'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'C'
	call	data2lcd
	movlw	'W'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'2'
	call	data2lcd

;second line of text

	movlw	0xC0
	call	cmd2lcd
	movlw	'S'
	call	data2lcd
	movlw	'I'
	call	data2lcd
	movlw	'N'
	call	data2lcd
	movlw	'G'
	call	data2lcd
	movlw	'L'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'-'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'H'
	call	data2lcd
	movlw	'O'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'3'
	call	data2lcd

mo_en1:
	call	readKey
	btfss	_Z
	goto 	keydown

	movlw	NO_KEY
	movwf	lastkey
	goto	mo_en1		;wait until next key press

keydown:
	movf	tmpk,W
	xorwf	lastkey,W	;is this key different from last time
	btfsc	_Z
	goto	mo_en1		;no, so ignore it, no auto-repeat here

;Here if a new/different key has been pressed

	call	wait100ms	;wait a while for key bounce to subside

	movf	tmpk,W		;and store key for comparison after
	movwf	lastkey		;debounce time

	call	readKey
	btfsc	_Z
	goto	mo_en1		;key press gone again - ignore it

;IF it is still the same key then process it

	movf	tmpk,W
	xorwf	lastkey,W	;is this key different from last time
	btfss	_Z
	goto	mo_en1		;no, so ignore it, no auto-repeat here

	movf	lastkey,W	;is it 1?
	sublw	0x01
	btfsc	_Z
	goto	mo_one		;yes it is 1
	movf	lastkey,W	;no, check if it is 2
	sublw	0x02
	btfsc	_Z
	goto	mo_two		;yes it is a 2
	movf	lastkey,W	;no, check if it is 3
	sublw	0x03
	btfsc	_Z
	goto	mo_three	;yes it is a 3 
	goto	mo_en1		;it is neither 1,2 nor 3 so go for 
				;a correct one

mo_one:
	call	lcd_cl
	movlw	'S'
	call	data2lcd
	movlw	'W'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd

;second line of text
	movlw	0xC0
	call	cmd2lcd
	movlw	'2'
	call	data2lcd
	movlw	'5'
	call	data2lcd
	movlw	'0'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	'S'
	call	data2lcd

	call	wait2s
	call	lcd_cl
	bcf	MODE_FLAG		;00=sweep	
	bcf	SSHOT_FLAG		;prevent single shot mode

	return

mo_two:
	call	lcd_cl
	movlw	'C'
	call	data2lcd
	movlw	'W'
	call	data2lcd

;second line of text
	movlw	0xC0
	call	cmd2lcd
	movlw	'F'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'1'
	call	data2lcd
	movlw	'k'
	call	data2lcd
	movlw	'H'
	call	data2lcd
	movlw	'z'
	call	data2lcd
	movlw	'('
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'F'
	call	data2lcd
	movlw	')'
	call	data2lcd

	call	wait2s
	call	lcd_cl
	bsf	MODE_FLAG		;10=step
	bcf	SSHOT_FLAG		;prevent single shot mode

	return

mo_three:
	call	lcd_cl
	movlw	'S'
	call	data2lcd
	movlw	'I'
	call	data2lcd
	movlw	'N'
	call	data2lcd
	movlw	'G'
	call	data2lcd
	movlw	'L'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'-'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'H'
	call	data2lcd
	movlw	'O'
	call	data2lcd
	movlw	'T'
	call	data2lcd

;second line of text
	movlw	0xC0
	call	cmd2lcd
	movlw	'2'
	call	data2lcd
	movlw	'5'
	call	data2lcd
	movlw	'0'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	'S'
	call	data2lcd

	call	wait2s
	call	lcd_cl
	bsf	SSHOT_FLAG		;01=single-shot
	bcf	MODE_FLAG		;enable sweep mode

	return


;******************************************************************************
;************************        fstart_entry          ************************
;******************************************************************************

fstart_entry:
	bcf	FSTART_FLAG		;new entry

;first line of text
	call	lcd_cl
	movlw	'F'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'A'
	call	data2lcd
	movlw	'R'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'#'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'N'
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	0xC0
	call	cmd2lcd


	clrf	fstart_0	;clear old fstart
	clrf	fstart_1			
	clrf	fstart_2
	clrf	fstart_3

	clrf	freq_0		;clear old freq
	clrf	freq_1			
	clrf	freq_2
	clrf	freq_3

fsta_en1:
	call	readKey
	btfss	_Z
	goto 	keydwn

	movlw	NO_KEY
	movwf	lastkey
	goto	fsta_en1	;wait until next key press

keydwn:
	movf	tmpk,W
	xorwf	lastkey,W	;is this key different from last time
	btfsc	_Z
	goto	fsta_en1	;no, so ignore it, no auto-repeat here

;Here if a new/different key has been pressed

	call	wait100ms	;wait a while for key bounce to subside
	movf	tmpk,W
	movwf	lastkey

	call	readKey
	btfsc	_Z
	goto	fsta_en1	;key press gone again - ignore it

;If it is still the same key then process it

	movf	tmpk,W
	xorwf	lastkey,W	;is this key different from last time
	btfss	_Z
	goto	fsta_en1	;no, so ignore it, no auto-repeat here

	movlw	HASH_KEY	;check for hash key to end entry
	xorwf	lastkey,W
	btfsc	_Z
	goto	fsta_end	;yes, end

	movlw	STAR_KEY	;check for non-numeric keys to ignore
	xorwf	lastkey,W
	btfsc	_Z
	goto	fsta_en1	;yes, ignore

	movlw	A_KEY		;check for non-numeric keys to ignore
	xorwf	lastkey,W
	btfsc	_Z
	goto	fsta_en1	;yes, ignore

	movlw	B_KEY		;check for non-numeric keys to ignore
	xorwf	lastkey,W
	btfsc	_Z
	goto	fsta_en1	;yes, ignore

	movlw	C_KEY		;check for non-numeric keys to ignore
	xorwf	lastkey,W
	btfsc	_Z
	goto	fsta_en1	;yes, ignore

	movlw	D_KEY		;check for non-numeric keys to ignore
	xorwf	lastkey,W
	btfsc	_Z
	goto	fsta_en1	;yes, ignore

	clrf	dacca_0		;start key processing,
	clrf	dacca_1		;newfreq = 10*oldfreq + keyvalue
	clrf	dacca_2
	clrf	dacca_3

	clrf	daccc_0
	clrf	daccc_1
	clrf	daccc_2
	clrf	daccc_3

	movlw	fstart_0	;put fstart in dacca for adding to itself
	movwf	FSR
	movlw	dacca_0	
	call	dblcpy		


	movlw	D'10'
	movwf	lpcnt

mploop:
	call	dbladd		;10*fstart loop, result in daccc
	decfsz	lpcnt,F
	goto	mploop

	clrf	dacca_0		;clear dacca
	clrf	dacca_1			
	clrf	dacca_2
	clrf	dacca_3

	movf	lastkey,W	;put keyvalue in dacca
	movwf	dacca_0
	call	dbladd		;add keyvalue and 10*fstart,result in daccc

	clrf	fstart_0	;clear old fstart
	clrf	fstart_1			
	clrf	fstart_2
	clrf	fstart_3

	clrf	freq_0		;clear old freq
	clrf	freq_1			
	clrf	freq_2
	clrf	freq_3

	movlw	daccc_0
	movwf	FSR
	movlw	fstart_0
	call	dblcpy		;put daccc in fstart

	movlw	daccc_0
	movwf	FSR
	movlw	freq_0
	call	dblcpy		;and put daccc in freq to display it

	call	bin2BCD		;now show it
	call	show_freq

	goto	fsta_en1	;and go for the next entry

fsta_end:
	bsf	FSTART_FLAG	;fstart has been set
	
	return

;******************************************************************************
;************************        fstep_entry           ************************
;******************************************************************************

fstep_entry:
	bcf	FSTEP_FLAG	;new entry

;check for mode,if mode=CW fstep is set at 1kHz (default),if not proceed
;as shown below

	btfsc	MODE_FLAG	;check for CW mode (MODE_FLAG=1)
	goto	default_step	;yes, it is

;first line of text
	call	lcd_cl
	movlw	'F'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'#'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'N'
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	0xC0
	call	cmd2lcd


	clrf	fstep_0		;clear old fstep
	clrf	fstep_1			
	clrf	fstep_2
	clrf	fstep_3

	clrf	freq_0		;clear old freq
	clrf	freq_1			
	clrf	freq_2
	clrf	freq_3

fste_en1:
	call	readKey
	btfss	_Z
	goto 	keydwn2

	movlw	NO_KEY
	movwf	lastkey
	goto	fste_en1	;wait until next key press

keydwn2:
	movf	tmpk,W
	xorwf	lastkey,W	;is this key different from last time
	btfsc	_Z
	goto	fste_en1	;no, so ignore it, no auto-repeat here

;Here if a new/different key has been pressed

	call	wait100ms	;wait a while for key bounce to subside
	movf	tmpk,W
	movwf	lastkey

	call	readKey
	btfsc	_Z
	goto	fste_en1	;key press gone again - ignore it

;If it is still the same key then process it

	movf	tmpk,W
	xorwf	lastkey,W	;is this key different from last time
	btfss	_Z
	goto	fste_en1	;no, so ignore it, no auto-repeat here
		
	movlw	HASH_KEY	;check for hash key to end entry
	xorwf	lastkey,W
	btfsc	_Z
	goto	fste_end	;yes, end

	movlw	STAR_KEY	;check for non-numeric keys to ignore
	xorwf	lastkey,W
	btfsc	_Z
	goto	fste_en1	;yes, ignore

	movlw	A_KEY		;check for non-numeric keys to ignore
	xorwf	lastkey,W
	btfsc	_Z
	goto	fste_en1	;yes, ignore

	movlw	B_KEY		;check for non-numeric keys to ignore
	xorwf	lastkey,W
	btfsc	_Z
	goto	fste_en1	;yes, ignore

	movlw	C_KEY		;check for non-numeric keys to ignore
	xorwf	lastkey,W
	btfsc	_Z
	goto	fste_en1	;yes, ignore

	movlw	D_KEY		;check for non-numeric keys to ignore
	xorwf	lastkey,W
	btfsc	_Z
	goto	fste_en1	;yes, ignore

	clrf	dacca_0		;start key processing,
	clrf	dacca_1		;newfreq = 10*oldfreq + keyvalue
	clrf	dacca_2
	clrf	dacca_3

	clrf	daccc_0
	clrf	daccc_1
	clrf	daccc_2
	clrf	daccc_3

	movlw	fstep_0		;put fstep in dacca for adding to itself
	movwf	FSR
	movlw	dacca_0	
	call	dblcpy		


	movlw	D'10'
	movwf	lpcnt

mploop2:
	call	dbladd		;10*fstep loop, result in daccc
	decfsz	lpcnt,F
	goto	mploop2

	clrf	dacca_0		;clear dacca
	clrf	dacca_1			
	clrf	dacca_2
	clrf	dacca_3

	movf	lastkey,W	;put keyvalue in dacca
	movwf	dacca_0
	call	dbladd		;add keyvalue and 10*fstart,result in daccc

	clrf	fstep_0		;clear old fstep
	clrf	fstep_1			
	clrf	fstep_2
	clrf	fstep_3

	clrf	freq_0		;clear old freq
	clrf	freq_1			
	clrf	freq_2
	clrf	freq_3

	movlw	daccc_0
	movwf	FSR
	movlw	fstep_0
	call	dblcpy		;put daccc in fstep

	movlw	daccc_0
	movwf	FSR
	movlw	freq_0
	call	dblcpy		;and put daccc in freq to display it

	call	bin2BCD		;now show it
	call	show_freq

	goto	fste_en1	;and go for the next entry

;here to set and display the default step of 1kHz in the CW mode
;1000 is 3E8 hex

default_step

;first line of text in CW mode
	call	lcd_cl
	movlw	'D'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'F'
	call	data2lcd
	movlw	'A'
	call	data2lcd
	movlw	'U'
	call	data2lcd
	movlw	'L'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'O'
	call	data2lcd
	movlw	'F'
	call	data2lcd
	movlw	0xC0
	call	cmd2lcd

;step_ind is not set yet because it is set to default in run_step
;step is 1000 Hz or 03E8 hex
	movlw	0xE8
	movwf	fstep_0
	movlw	0x03
	movwf	fstep_1
	clrf	fstep_2
	clrf	fstep_3

;copy fstep to freq and display it

	movlw	fstep_0
	movwf	FSR
	movlw	freq_0
	call	dblcpy		; put fstep in freq to display it

	call	bin2BCD		;now show it
	call	show_freq
	call	wait2s

fste_end:
	bsf	FSTEP_FLAG	;fstep has been set		
	return	

;******************************************************************************
;************************         test_entry           ************************
;******************************************************************************
;check if the flags for fstart and fstep have been set,if not give message and*
;return to mainloop.                                                          *
;if both set, show fstart and fstep on display each for 2 seconds             *
;then calculate the stopfrequency in 250 steps and display it on the bottom   *
;line.                                                                        *
;if ok key 1 and use buttons on display for stepping or sweeping.             *
;otherwise key 0 for mainloop and use B and/or C key to change fstart and/or  *
;fstep and try again.                                                         *
;******************************************************************************

test_entry:
	btfss	FSTART_FLAG	;test if fstart has been defined
	goto	msg1		;no,give warning and return

	clrf	fzero
	movf	fstart_0,F	;test for 0
	btfsc	_Z
	incf	fzero,F	
	movf	fstart_1,F	;test for 0
	btfsc	_Z
	incf	fzero,F	
	movf	fstart_2,F	;test for 0
	btfsc	_Z
	incf	fzero,F	
	movf	fstart_3,F	;test for 0
	btfsc	_Z
	incf	fzero,F	

	movf	fzero,W		;test for all bytes 0
	sublw	4
	btfsc	_Z
	goto	msg1 


	btfss	FSTEP_FLAG	;test if fstep has been defined	
	goto	msg2		;no,give warning and return		

	clrf	fzero
	movf	fstep_0,F	;test for 0
	btfsc	_Z
	incf	fzero,F	
	movf	fstep_1,F	;test for 0
	btfsc	_Z
	incf	fzero,F	
	movf	fstep_2,F	;test for 0
	btfsc	_Z
	incf	fzero,F	
	movf	fstep_3,F	;test for 0
	btfsc	_Z
	incf	fzero,F	

	movf	fzero,W		;test for all bytes 0
	sublw	4
	btfsc	_Z
	goto	msg2 


;here with fstart and fstep ok, so display them each for 2 seconds

	movlw	fstart_0
	movwf	FSR
	movlw	freq_0
	call	dblcpy		;put fstart in freq to display it

	call 	lcd_cl
	movlw	'F'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'A'
	call	data2lcd
	movlw	'R'
	call	data2lcd
	movlw	'T'
	call	data2lcd

	call 	bin2BCD
	call	show_freq
	call	wait2s


	movlw	fstep_0
	movwf	FSR
	movlw	freq_0
	call	dblcpy		;put fstep in freq to display it

	call 	lcd_cl
	movlw	'F'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd

	call 	bin2BCD
	call	show_freq
	call	wait2s

;check mode because for the step (CW) mode we don't need the fstop check

	btfsc	MODE_FLAG	;mode flag is 1 for step
	goto	fstop_ok

testloop:
	call 	prep_regs	;put fstart in daccc and fstep in dacca
;addition loop
	movf	nsteps,w	;set loop count
	movwf	lpcnt
addloop:
	call	dbladd
	bcf	MAX_FREQ_FLAG	;check if max freq hasn't been exceeded
	bcf	PCLATH,4	;select page 01 
	bsf	PCLATH,3	;to call check_fhigh (is on page 1) 
	call	check_fhigh	;
	btfsc	MAX_FREQ_FLAG
	goto	display_maxf	;yes,it has so take care
	decfsz	lpcnt,F		;no,it hasn't so continue
	goto	addloop	

;display stop frequency in daccc

	movlw	daccc_0
	movwf	FSR
	movlw	freq_0
	call	dblcpy		

	call	lcd_cl
	movlw	'F'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'O'
	call	data2lcd
	movlw	'P'
	call	data2lcd

	call 	bin2BCD
	call	show_freq
	call	wait2s
	call	wait2s

	goto 	fstop_ok	;fstop is below the limit

;indicate that fstop exceeds the maximum frequency.
display_maxf:
	movf	lpcnt,w		;determine actual value of lpcnt and
	subwf	nsteps,w	;number of steps to be made
	movwf	lpcnt_mod	;new loop count value instead of 250. 

	movlw	max_freq_0
	movwf	FSR
	movlw	freq_0
	call	dblcpy
	
	call	lcd_cl
	movlw	'F'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'O'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'X'
	call	data2lcd
	movlw	'C'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	':'
	call	data2lcd

	call 	bin2BCD
	call	show_freq
	call	wait2s

;Show how many steps will be made	

	call	lcd_cl
	movlw	'N'
	call	data2lcd
	movlw	'U'
	call	data2lcd
	movlw	'M'
	call	data2lcd
	movlw	'B'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'R'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'O'
	call	data2lcd
	movlw	'F'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	'S'
	call	data2lcd

	movf	lpcnt_mod,w
	call	byte2bcd

	movlw	0xC0
	call	cmd2lcd
	call	show_3digs
	call	wait2s		

;now make the choice to continue or to divert 
;to the mainloop to alter mode, fstart or fstep.

fstop_ok:
	call lcd_cl
	movlw	'O'
	call data2lcd
	movlw	'K'
	call data2lcd
	movlw	'?'
	call data2lcd
	movlw	' '
	call data2lcd
	movlw	'Y'
	call data2lcd
	movlw	'E'
	call data2lcd
	movlw	'S'
	call data2lcd
	movlw	'='
	call data2lcd
	movlw	'1'
	call data2lcd
	movlw	' '
	call data2lcd
	movlw	'N'
	call data2lcd
	movlw	'O'
	call data2lcd
	movlw	'='
	call data2lcd
	movlw	'0'
	call data2lcd

	movlw	0xC0		;start at 2hd line
	call	cmd2lcd

;Here it all starts or not

tst_en1:
	call	readKey
	btfss	_Z
	goto 	tst_kdwn
	movlw	NO_KEY
	movwf	lastkey
	goto	tst_en1		;wait until next key press

tst_kdwn:
	movf	tmpk,W
	xorwf	lastkey,W	;is this key different from last time
	btfsc	_Z
	goto	tst_en1		;no, so ignore it, no auto-repeat here

;Here if a new/different key has been pressed

	call	wait100ms	;wait a while for key bounce to subside

	movf	tmpk,W		;and store key for comparison after
	movwf	lastkey		;debounce time

	call	readKey
	btfsc	_Z
	goto	tst_en1		;key press gone again - ignore it

;If it is still the same key then process it

	movf	tmpk,W
	xorwf	lastkey,W	;is this key different from last time
	btfss	_Z
	goto	tst_en1		;no, so ignore it, no auto-repeat here

	movf	lastkey,F	;yes it is different, so is it 0?
	btfsc	_Z
	goto	tst_zero	;yes it is 0, not OK, so return to main

	movf	lastkey,W	;no, check if it is 1
	sublw	0x01
	btfss	_Z
	goto	tst_en1		;it is neither 1 nor 0 so go for a correct one

;Here the key entry is a 1 so we can continue with the sweeping, single shot
;or stepping

	btfsc	SSHOT_FLAG	;test for sshot (flag =1)
	goto	sshot_en	;yes it is
	btfsc	MODE_FLAG	;test for sweep (flag =0) or step (flag = 1)
	goto	step_en		;here in step mode

	call	run_sweep	;carry out sweeping 
	goto	mainloop

sshot_en:
	call	run_sshot	;carry out single shot operation
	goto	mainloop

step_en:
	call	run_step	;carry out stepping
	goto	mainloop

msg1:
	call	lcd_cl
	movlw	'N'
	call	data2lcd
	movlw	'O'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'F'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'A'
	call	data2lcd
	movlw	'R'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'!'
	call	data2lcd
	call	wait2s
	return

msg2:
	call	lcd_cl
	movlw	'N'
	call	data2lcd
	movlw	'O'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'F'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	'!'
	call	data2lcd
	call	wait2s

tst_zero:
	return



;******************************************************************************
;************************         run_sweep            ************************
;******************************************************************************
;routine to execute the selected mode

run_sweep:
	call	lcd_cl
	movlw	'S'		;first line of text
	call	data2lcd
	movlw	'W'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	' '
	call	data2lcd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;TEST;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	movf	speed_ind,w	;speed-ind shows % of maximum speed		
	call	byte2bcd	;show it
	call	show_3digs	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;set first time flag

	bsf	 FIRST_TIME			

;now test S1

test_s1:
	btfsc	S1_START	;S1 is 0 when activated
	goto	test_s1
	call	wait100ms	;debounce
	btfsc	S1_START
	goto	test_s1
		
;S1 activated
;change PORTA,5 from input (for S1_START) to output, for reset pulse

	bsf	STATUS,RP0
	bcf	TRISA,5		;PORTA,5 now output, rest unchanged
	bcf	STATUS,RP0

	bsf	PORTA,5		;ensure sweep reset (low) at start, 
	bcf	PORTA,5
	nop
	nop
	bsf	PORTA,5


;first time for sweep, change the display
new_sweep1:
;	call	newswp_display	;

new_sweep:			;sweep mode and step mode first time
	call	prep_regs	;prepare frequency registers 

;here the value of speed_ind can be displayed without interference to
;the sweep speed

	movf	speed_ind,w	;speed-ind shows % of maximum speed		
	call	byte2bcd	;show it
	call	show_3digs	


	bsf	FIRST_TIME	;set first time flag to prevent dbladd 
				;on first pass			
	movf	nsteps,w	;sweep mode or single shot mode
	btfsc	MAX_FREQ_FLAG	;has fstop exceeded fmax?
	movf	lpcnt_mod,w	;yes,it has so use less than nsteps
	movwf	lpcnt	

	call	init_dds	;dds is possible asleep so awake it

addloop2:			;sweep mode loop and step mode next step
	btfss	FIRST_TIME	;test for first time because no addition
				;is required to obtain fstart 
	call	dbladd		;daccc contains the new frequency

;here the DDS routines and perhaps wait routines for speed regulation

	call	calc_dds_word
	call	par_load_dds

;test here if marker generation and speed control is required

	bcf	MARKER_OUT	;mode is sweep or sshot,reset the 
	btfsc	S5_MARKER	;marker output pulse and test for marker
	goto	no_marker	;active = 0
	call  	marker_gen	;check if marker has to be generated
	goto	speed_reg

no_marker:
	btfsc	MARKER_FLAG	;test if marker has been on , if so
	call	newswp_display	;change to correct display

speed_reg:		
	call	speed_s2	;mode_flag = 0 (sweep),faster
	call	speed_s3	;slower

;test if required speed is maximum

	movf	del_fact,f	;test if del_fact is 0
	btfss	_Z		;if so no speed control is required
	call	wait_var	;del_fact unequal to 0 

;test S4 here for stop
test_s4: 
	btfsc	S4_STOP		;test S4, 0 when activated
	goto 	no_stop		;S4 not pressed
	bsf	STOP_FLAG	;S4 pressed but stop after completion of the
				;sweep
no_stop:
	bcf	FIRST_TIME	;		
	decfsz	lpcnt,F
	goto	addloop2	;sweep mode and sweeping
		
;here is the end of the sweep , show the marker frequency if required,
;arrange for a new sequence or go to main to change settings  

	btfsc	S5_MARKER	;test if marker is on (active = 0)
	goto	end_trace	;
	call  	bin2BCD		;prepare for display of marker frequency
	call 	show_freq	;and show it
	movlw	'M'		;MKR indication 
	call	data2lcd
	movlw	'K'
	call	data2lcd
	movlw	'R'
	call	data2lcd
	movlw	0x8B		;move cursor to speed position on display
	call	cmd2lcd		;position 11 on 1st line (cmd=120+pos dec) 

end_trace
	call	stop_dds	;silence dds

	bcf	PORTA,5		;reset sweep
	nop
	nop
	bsf	PORTA,5
			
	btfsc	STOP_FLAG	;test for a stop
	goto	run_end
	goto	new_sweep	;start new sweep

run_end:
	call	stop_dds	;silence dds

;change PORTA,5 from output to input (for S1_START) 

	bsf	STATUS,RP0
	bsf	TRISA,5		;PORTA,5 now input, others unchanged
	bcf	STATUS,RP0		
	
		return

;******************************************************************************
;************************          run_sshot           ************************
;******************************************************************************
;routine to execute the selected mode

run_sshot:

;ICH_FLAG may be set so clear it

	bcf	ICH_FLAG
	call	lcd_cl
	movlw	'S'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'H'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	' '
	call	data2lcd

;here the value of speed_ind can be displayed without interference to
;the sweep speed

	movf	speed_ind,w	;speed-ind shows % of maximum speed		
	call	byte2bcd	;show it
	call	show_3digs	
;	movlw	'%'
;	call	data2lcd

;set first time flag

	bsf	 FIRST_TIME			

;now test S1

sstest_s1:
	btfsc	S1_START	;test S1, S1 is 0 when activated
	goto	sstest_s4	;S1 not active, test S4 (stop)
	call	wait100ms	;S1 active, debounce
	btfsc	S1_START	;test again
	goto	sstest_s1	;not active, test S1 and S4 again
	goto	sshot_start	;S1 active, start sshot

sstest_s4:
	btfsc	S4_STOP		;test S4, S4 is 0 when activated
	goto	sstest_s2	;S4 not active, test speed_s2 
	call	wait100ms	;S4 active, debounce
	btfsc	S4_STOP		;test again
	goto	sstest_s1	;not active, test S1 and S4 again
	goto	ssrun_end	;S4 active, end sshot

sstest_s2:
	btfss	S2_FAST		;test S2, S2 is 0 when activated
	goto	next_s2		;S2 is active
	bcf	S2_FLAG		;S2 is not active clear the flag to prevent
	goto	sstest_s3	;key repeating and go to testing S3

next_s2:
	call	wait100ms	;S2 active, debounce
	btfss	S2_FAST		;test again, S2 is 0 when active
	goto	exec_s2		;still active, execute S2 command
	bcf	S2_FLAG		;not active anymore, clear S2_FLAG
	goto	sstest_s1	;and start testing S1,S2,S3 and S4 again

exec_s2:
	call	s2_entry	;faster (entry in speed_s2)
	btfsc	ICH_FLAG	;has speed been changed?
	goto	run_sshot	;yes, display it and wait for start or stop
	goto	sstest_s1	;no, test S1 and S4 again	

sstest_s3:
	btfss	S3_SLOW		;test S3, S3 is 0 when activated
	goto	next_s3		;S3 is active
	bcf	S3_FLAG		;S3 is not active clear the flag to prevent
	goto	sstest_s1	;key repeating and go to testing S1,etc.

next_s3:
	call	wait100ms	;S3 active, debounce
	btfss	S3_SLOW		;test again, S3 is 0 when active
	goto	exec_s3		;still active, execute S3 command
	bcf	S3_FLAG		;not active anymore, clear S3_FLAG
	goto	sstest_s1	;and start testing S1,S2,S3 and S4 again

exec_s3:
	call	s3_entry	;slower (entry in speed_s3)
	btfsc	ICH_FLAG	;has speed been changed?
	goto	run_sshot	;yes, display it and wait for start or stop
	goto	sstest_s1	;no, test S1 and S4 again	
		
;S1 activated, start

sshot_start:

;change PORTA,5 from input (for S1_START) to output, for reset pulse

	bsf	STATUS,RP0
	bcf	TRISA,5		;PORTA,5 now output, rest unchanged
	bcf	STATUS,RP0

	bsf	PORTA,5		;ensure sweep reset (low) at start, 
	bcf	PORTA,5
	nop
	nop
	bsf	PORTA,5

;indicate BUSY on second line of lcd

	movlw	0xC0
	call	cmd2lcd
	movlw	'B'
	call	data2lcd
	movlw	'U'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'Y'
	call	data2lcd

;test first time and mode 

	btfss	MODE_FLAG
	goto	ssnew_sweep	;sweep mode first time
	btfss	FIRST_TIME
	goto	ssaddloop2	;step mode not first time


ssnew_sweep:			;sweep mode and step mode first time
	call	prep_regs	;prepare frequency registers 

	bsf	FIRST_TIME	;set first time flag to prevent dbladd 
				;on first pass			
	movf	nsteps,w	;sweep mode or single shot mode
	btfsc	MAX_FREQ_FLAG	;has fstop exceeded fmax?
	movf	lpcnt_mod,w	;yes,it has so use less than nsteps
	movwf	lpcnt	

	call	init_dds	;dds is possible asleep so awake it

ssaddloop2:			;sweep mode loop and step mode next step
	btfss	FIRST_TIME	;test for first time because no addition
				;is required to obtain fstart 
	call	dbladd		;daccc contains the new frequency

;here the DDS routines and perhaps wait routines for speed regulation

	call	calc_dds_word
	call	par_load_dds

;test if required speed is maximum

	movf	del_fact,f	;test if del_fact is 0
	btfss	_Z		;if so no speed control is required
	call	wait_var	;del_fact unequal to 0 

	bcf	FIRST_TIME	;		
	decfsz	lpcnt,F
	goto	ssaddloop2	;check which way to go, depends on mode	

;here is the end of the sweep , arrange for a new sequence or go to main 
;to change settings in case of single shot operation

	call	stop_dds	;silence dds

	bcf	PORTA,5		;reset sweep
	nop
	nop
	bsf	PORTA,5

;change PORTA,5 from output to input (for S1_START) 

	bsf	STATUS,RP0
	bsf	TRISA,5		;PORTA,5 now input, others unchanged
	bcf	STATUS,RP0		

	btfsc	SSHOT_FLAG	;is 1 for single shot
	goto 	run_sshot	;entry for new shot
	nop

ssrun_end:
	call	stop_dds	;silence dds,it also resets the sweep

	return


;******************************************************************************
;************************           run_step           ************************
;******************************************************************************
;routine to execute the stepping (CW) mode
;F.Klinker,28-12-2009

run_step:
	call	lcd_cl
	movlw	'C'
	call	data2lcd
	movlw	'W'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	'='
	call	data2lcd

	movlw	D'5'		;setting of step_ind,not to 4,but to 5 (or 3)
	movwf	step_ind	;because dec_step (or inc_step) must be invoked
				;to get the proper step value on display

	bcf	PCLATH,4	;set page bits to 01 because check_fhigh
	bsf	PCLATH,3	;is on page 1 of the program memory
	call	dec_step	;step_ind is 5,moet dus zakken naar 4 voor 1k

	call	prep_regs	;prepare frequency registers 
	call	init_dds	;dds is possible asleep so awake it


disp_freq:
	movlw	daccc_0		;copy daccc to freq 
	movwf	FSR				
	movlw	freq_0
	call	dblcpy

	call 	bin2BCD
	call	show_freq	;display the frequency

;activate dds
	call	calc_dds_word
	call	par_load_dds

;check for a change in frequency or stepsize, but first for a stop

check_again:
	btfss	S4_STOP		;test S4, 0 when activated
	goto	strun_end	;S4 pressed

	call	read_enc	;encoder read check output for action

	btfsc	FREQ_UP_FLAG	;step up?
	goto	check_up_limit	;yes, check if limit (FMAX) is reached
	btfsc	FREQ_DWN_FLAG	;no, may be step down?
	goto	check_dwn_limit	;yes, check low frequency limit (FMIN)

;check here for new stepsize
;first S2 
	btfsc	S2_FAST		;test for S2 active (active=0)
	goto	test_upflag	;no,test if S2_FLAG is set
	call	wait100ms	;S2 active,debounce and
	btfss	S2_FAST		;test again
	bsf	S2_FLAG		;it's active,set upflag

now_s3:
	btfsc	S3_SLOW		;test for S3 active (active=0)
	goto	test_dwnflag	;no,test if S3_FLAG is set
	call	wait100ms	;S3 active,debounce and
	btfss	S3_SLOW		;test again
	bsf	S3_FLAG		;it's active,set upflag
	goto	check_again	;no change at all, go for new encoder 
;				;and switches check

;here if frequency has to be increased, first check high limit
check_up_limit:
	bcf	PCLATH,4	;set page bits to 01 because check_fhigh
	bsf	PCLATH,3	;is on page 1 of the program memory
	call	check_fhigh
	btfsc	MAX_FREQ_FLAG	;FMAX exceeded?
	goto	check_again	;yes, do nothing
	call	dbladd		;no, increase the frequency and process it
	goto	disp_freq

;here if the frequency has to be decreased, then check low limit
check_dwn_limit:
	call	dblsub		;decrease the frequency
	bcf	PCLATH,4	;set page bits to 01 because check_fhigh
	bsf	PCLATH,3	;is on page 1 of the program memory
	call	check_fhigh	;check if freq has decreased below 0 
	btfsc	MAX_FREQ_FLAG	
	call	dbladd		;yes, it has so correct it to the old value
	bcf	MAX_FREQ_FLAG	;reset flag, otherwise perhaps problems
	goto	disp_freq	;check if freq remains the same or decreases

;here the stepsize has to be increased perhaps
test_upflag:
	btfss	S2_FLAG	;is the flag set?
	goto	now_s3		;no,check s3, encoder and switches again
	bcf	PCLATH,4	;set page bits to 01 because inc_step
	bsf	PCLATH,3	;is on page 1 of the program memory
	call	inc_step	;yes,increase stepsize
	call	copy_step	;copy new step value in dacca
	bcf	S2_FLAG		;make system ready for new S2 command
	goto	check_again	;no,check encoder and switches again

;here the stepsize has to be decreased perhaps
test_dwnflag:
	btfss	S3_FLAG		;is the flag set?
	goto	check_again	;no,check encoder and switches again
	bcf	PCLATH,4	;set page bits to 01 because dec_step
	bsf	PCLATH,3	;is on page 1 of the program memory
	call	dec_step	;yes,decrease stepsize
	call	copy_step	;copy new step value in dacca
	bcf	S3_FLAG		;make system ready for new S3 command
	goto	check_again	;no,check encoder and switches again
		 
;here if S4 is used to stop	

strun_end:
	call	stop_dds	;silence dds

	return

;*****************************************************************************
;************************        newswp_display        ***********************
;*****************************************************************************
;F.Klinker,10-11-2009. 
;
newswp_display:       
	bcf	MARKER_FLAG	;clear marker flag to prevent repeated
				;calling of this routine after marker has 
				;been switched off                       
	call	lcd_cl
	movlw	'S'
	call	data2lcd
	movlw	'W'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'P'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	' '
	call	data2lcd

	return

;*****************************************************************************
;************************        marker_gen            ***********************
;*****************************************************************************
;F.Klinker,26-10-2009.                                                       *
;Generate marker pulse and display the frequency if lpcnt or lpcnt_mod equals* 
;the value of marker which can be set by the rotary encoder switch.          *                       ;
;*****************************************************************************
marker_gen:
	call	read_enc
	movf	lpcnt,w		;
	xorwf	marker,w	;is lpcnt equal to marker?
	btfss	_Z
	return			;no,do nothing and return

	bsf	MARKER_OUT	;yes, generate marker pulse,the bcf command is
				;just prior to the dds command in run
	movlw	daccc_0		;display the present frequency as the marker
	movwf	FSR
	movlw	freq_0
	call	dblcpy	

;	call 	bin2BCD
;	call	show_freq
		
	bsf	MARKER_FLAG	;indicator for displaytype on LCD

	return

;*****************************************************************************
;************************         show_3digs           ***********************
;*****************************************************************************
;F.Klinker,11-10-2009.                                                       *
;Display a 3 digit number on the LCD. A single byte can be converted into 3  *
;decimal digits using the byte2bcd routine.                                  *
;Input : Hundreds digit in hund,tens digit in tend and ones digit in oned.   *
;Output: The number displayed on the LCD.                                    *
;*****************************************************************************

show_3digs:

;Digit contains YYYYXXXX
;Mask with 0x0F to get 0000XXXX
;Add ASCII bias (0030XXXX)
;
        movf    hund,w            ; Hundreds digit first
        andlw   0x0F              ; Mask for lower nibble only (0000XXXX)
        addlw   0x30              ; Add offset for ASCII char set (0030XXXX)
        call    data2lcd          ; Send byte in W to LCD

;Do the same with the tens digit

        movf    tend,w            ; Now the tens digit
        andlw   0x0F              ; Mask for lower nibble only (0000XXXX)
        addlw   0x30              ; Add offset for ASCII char set (0030XXXX)
        call    data2lcd          ; Send byte in W to LCD

;and again with the ones digit 

        movf    oned,w            ; and the ones digit last
        andlw   0x0F              ; Mask for lower nibble only (0000YYYY)
        addlw   0x30              ; Add offset for ASCII char set (0030YYYY)
        call    data2lcd          ; Send byte in W to LCD

;move cursor to the left to hold display steady in the loop
;otherwise the display swamped by speed_ind values (07-12-2009)

	movlw	0x10
	call	cmd2lcd
	movlw	0x10
	call	cmd2lcd
	movlw	0x10
	call	cmd2lcd

	return 

;*****************************************************************************
;************************         byte2bcd             ***********************
;*****************************************************************************
;F.Klinker,11-10-2009.                                                       * 
;Decomposition of an 8-bits byte into three decimal digits.                  * 
;Input : byte in w.                                                          * 
;Output: hundreds digit in hund,tens digit in tend and ones digit in oned.   * 
;ATTENTION!!!!!              #define _C STATUS,0                             * 
;*****************************************************************************
byte2bcd:
	clrf	hund	
	clrf	tend
	movwf	oned

ghund:
	movlw	D'100'
	subwf	oned,w
	btfss	_C
	goto	restore		
	movwf	oned
	incf	hund,f
	goto	ghund

restore:
	addlw	D'100'
	movwf	oned

gtenth1:
	movwf	oned
	movlw	D'10'
	subwf	oned,w
	btfss	_C
	goto	last
	movwf	oned
	incf	tend,f
	goto	gtenth1

last:
	retlw	0
 

;*****************************************************************************
;****************************    prep_regs   *********************************
;*****************************************************************************
;prepare the frequency registers and put fstart in daccc and fstep in dacca.

prep_regs:
	clrf	dacca_0			
	clrf	dacca_1			
	clrf	dacca_2
	clrf	dacca_3

	clrf	daccc_0
	clrf	daccc_1
	clrf	daccc_2
	clrf	daccc_3

	movlw	fstart_0
	movwf	FSR
	movlw	daccc_0
	call	dblcpy	

copy_step:	
	movlw	fstep_0
	movwf	FSR
	movlw	dacca_0
	call	dblcpy		

	return

;*****************************************************************************
;****************************    speed_s2    *********************************
;*****************************************************************************
;sweep speed control by means of variable delay (01-09-2009)
;speed is increased

speed_s2:

;check the flag
	btfsc	S2_FLAG			
	goto 	s2_test		;flag set,test s2 for action
	btfss	S2_FAST		;flag clear,test s2 (0=active)
	bsf	S2_FLAG		;s2 active,set flag
				;s2 not active and flag clear
	return				

s2_test:
	btfss	S2_FAST		;test s2 (0=active)
	return			;s2 active and flag set do nothing
	bcf	S2_FLAG		;s2 not active but has been earlier
				;so clear flag and change del_fact 

s2_entry:			;this entry is for sshot
	movf	del_fact,f	;check if delay factor equals 0
	btfsc	_Z		;then no delay is required (speed is maximum)
				;_Z is set, meaning that del_fact = 0
	return	
					
	decf	speed_sel,f	;del_fact not 0 so decrease speed_sel
	call	select_speed	;and determine new value of del_fact
	bsf	ICH_FLAG	;indicate the change
	
	return



;*****************************************************************************
;****************************    speed_s3    *********************************
;*****************************************************************************
;sweep speed control by means of variable delay (01-09-2009)
;speed is decreased

speed_s3:

;check the flag
	btfsc	S3_FLAG			
	goto 	s3_test		;flag set,test s3 for action
	btfss	S3_SLOW		;flag clear,test s3 (0=active)
	bsf	S3_FLAG		;s3 active,set flag
				;s3 not active and flag clear
	return

s3_test:
	btfss	S3_SLOW		;test s3 (0=active)
	return			;s3 active and flag set do nothing
	bcf	S3_FLAG		;s3 not active but has been earlier
				;so clear flag and change del_fact

s3_entry			;this entry is for sshot 
	movf	del_fact,w	;check if del_fact is already at its maximum
	sublw	D'250'		;value of 99, if so it needs not to be 
	btfsc	_Z		;increased because speed is minimum

	return

	incf	speed_sel,f	;del_fact not at its maximum so increase 
	call	select_speed	;speed_sel and determine new value of del_fact
	bsf	ICH_FLAG	;indicate the change

	return

;*****************************************************************************
;*************************   wait_var TIMING LOOP    *************************
;*************************   minimum 1080CY @ 20MHz  *************************
;*****************************************************************************
; Delay = 1080 instruction cycles
; Clock frequency = 20 MHz
; Actual delay = 0.000216 seconds = 1080 cycles
; Error = 0 %

wait_var:
	movf	del_fact,w	;external delay control variable
	movwf	temp_del

start_800:			;1078 cycles
	movlw	0xD7
	movwf	dwv1
	movlw	0x01
	movwf	dwv2

Delay_4
	decfsz	dwv1, f
	goto	$+2
	decfsz	dwv2, f
	goto	Delay_4

				;2 cycles
	goto	$+1

	decfsz	temp_del,f
	goto	start_800

	retlw 0

		
;*****************************************************************************
;*************************   wait50us TIMING LOOP    *************************
;*************************        250CY @ 20MHz      *************************
;*****************************************************************************
; Delay = 250 instruction cycles
; Clock frequency = 20 MHz
; Actual delay = 5e-005 seconds = 250 cycles
; Error = 0 %
				;250 cycles
wait50us:
	movlw	0x51		;81
	movwf	d50u

Delay_0
	decfsz	d50u, f
	goto	Delay_0

	retlw	0 



;*****************************************************************************
;*************************    wait2ms TIMING LOOP    *************************
;*************************      10000CY @ 20MHz      *************************
;*****************************************************************************
; Delay = 0.002 seconds
; Clock frequency = 20 MHz
; Actual delay = 0.002 seconds = 10000 cycles
; Error = 0 %

				;9998 cycles
wait2ms:
	movlw	0xCF
	movwf	d12m
	movlw	0x08
	movwf	d22m

Delay_1
	decfsz	d12m, f
	goto	$+2
	decfsz	d22m, f
	goto	Delay_1

				;2 cycles
	goto	$+1

	retlw	0

;*****************************************************************************
;*************************    wait100ms TIMING LOOP  *************************
;*************************     500000CY @ 20MHz      *************************
;*****************************************************************************
; Delay = 0.1 seconds
; Clock frequency = 20 MHz
; Actual delay = 0.1 seconds = 500000 cycles
; Error = 0 %
				;499994 cycles
wait100ms:
	movlw	0x03
	movwf	d1100m
	movlw	0x18
	movwf	d2100m
	movlw	0x02
	movwf	d3100m

Delay_2
	decfsz	d1100m, f
	goto	$+2
	decfsz	d2100m, f
	goto	$+2
	decfsz	d3100m, f
	goto	Delay_2

				;6 cycles
	goto	$+1
	goto	$+1
	goto	$+1

	retlw	0

;*****************************************************************************
;*************************     wait2s TIMING LOOP    *************************
;*************************   20 callS TO wait100ms   *************************
;*****************************************************************************
wait2s:
	movlw	D'20'
	movwf	count
Delay_3:
	decfsz	count,F
	goto	$+2
	retlw	0	
	call	wait100ms	
	goto	Delay_3

	retlw	0

;*****************************************************************************
;*************************    start message on lcd   *************************
;*****************************************************************************
msg:
	call 	lcd_cl
;first line of message
	movlw	'='
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	'D'
	call	data2lcd
	movlw	'S'
	call	data2lcd
	movlw	'-'
	call	data2lcd
	movlw	'G'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'N'
	call	data2lcd
	movlw	'E'
	call	data2lcd
	movlw	'R'
	call	data2lcd
	movlw	'A'
	call	data2lcd
	movlw	'T'
	call	data2lcd
	movlw	'O'
	call	data2lcd
	movlw	'R'
	call	data2lcd
	movlw	'='
	call	data2lcd

;second line of message
	movlw	0xC0
	call	cmd2lcd	
	movlw	' '
	call	data2lcd
	movlw	' '
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	'1'
	call	data2lcd
	movlw	'H'
	call	data2lcd
	movlw	'z'
	call	data2lcd
	movlw	'-'
	call	data2lcd
	movlw	'3'
	call	data2lcd
	movlw	'5'
	call	data2lcd
	movlw	'M'
	call	data2lcd
	movlw	'H'
	call	data2lcd
	movlw	'z'
	call	data2lcd
	movlw	'='
	call	data2lcd
	movlw	0x0C		;hide cursor
	call	cmd2lcd

	call	wait2s
	call	wait2s
	call	wait2s

	call	lcd_cl
		
	return

;*****************************************************************************
;************************        init_all             ************************
;*****************************************************************************
;F.Klinker,28-12-2009.

init_all:
	call    init_PIC	;init PIC
	call    lcd_init4	;init lcd in 8 bit mode
	call    init_dds	;init dds
	call	stop_dds	;required to switch off RF ON led
	call    msg		;message on lcd	

	clrf	flags_0		;clear all flags
	clrf	flags_1

	clrf	freq_0		;clear frequency
	clrf	freq_1
	clrf	freq_2
	clrf	freq_3

	clrf	fstart_0	;clear startfrequency
	clrf	fstart_1
	clrf	fstart_2
	clrf	fstart_3

	clrf	BCD_0		;clear BCD
	clrf	BCD_1
	clrf	BCD_2
	clrf	BCD_3
	clrf	BCD_4 

	movlw	0xC0		; maximum frequency is 35000000 Hz or
	movwf	max_freq_0	; 0x02160EC0
	movlw	0x0E
	movwf	max_freq_1
	movlw	0x16
	movwf	max_freq_2
	movlw	0x02
	movwf	max_freq_3

;************************   DDS CALIBRATION FACTOR   ************************
;************************      FOR 80MHz CLOCK       ************************

	movlw	0x35		;DDS calibration factor = 2^32/(80*10^6)=
	movwf	oscal_0		;53.6870912 Now oscal_3 (MSB) = 53 = 0x35.
	movlw	0xE5		;The mantissa 0.6870912 is spread over the
	movwf	oscal_1		;remaining 24 bits. Thus 0.6870912*2^24=
	movlw	0xAF		;11527477 = 0xAFE535, which corresponds 
	movwf	oscal_2		;to oscal_2 to _0 resp.
	movlw	0x35		;Routine calc_dds_word takes care of the 	
	movwf	oscal_3		;multiplication

;****************************************************************************

	clrf	del_fact	;sweep speed is maximum at start

	movlw	D'4'		;encoder gives 4 pulses between detents
	movwf	enc_cntd	;required in read_enc
	movwf	enc_cnti	;

	clrf	speed_sel	;start at maximum sweep speed
	movlw	D'100'		;set speed indicator to maximum
	movwf	speed_ind

	movlw	D'250'		;default number of steps used for sweeping
	movwf	nsteps		;or stepping

	movlw	D'125'
	movwf	marker		;marker position at mid of display

	bcf	PCLATH,3	;ensure adress on page 0 is OK		
	return

;*****************************************************************************
;************************       check_fhigh           ************************
;*****************************************************************************
;  Purpose:  Check if freq exceeds the upper limit (35 MHz).                 *
;    Input:  The 32 bit values in <daccc_0:daccc_3>                          *
;   Output:  If freq is below the limit, nothing happens.  Otherwise, the    *
;            MAX_FREQ_FLAG is set.                                           *
;*****************************************************************************

check_fhigh:
	bcf	MAX_FREQ_FLAG	      ;Clear the flag

;       Check the most significant byte.

        movf    max_freq_3,w      ; Get high limit value
        subwf   daccc_3,w         ; Subtract the limit value
        btfss   _C 	          ; Are we at the limit for the byte?
        goto    exit1          	  ; No, below.  Checks are done.
	btfss	_Z		  ; Byte is greater than or equal to the
				  ; maximum value,so test for equality.	
	goto 	set_flag	  ; Here not equal so too large, set flag
				  ; and return. Otherwise, check next byte.	

;       Check the second most significant byte.

        movf    max_freq_2,w      ; Get high limit value
        subwf   daccc_2,w         ; Subtract the limit value
        btfss   _C 	          ; Are we at the limit for the byte?
        goto    exit1          	  ; No, below.  Checks are done.
	btfss	_Z		  ; Byte is greater than or equal to the
				  ; maximum value,so test for equality.	
	goto 	set_flag	  ; Here not equal so too large, set flag
				  ; and return. Otherwise, check next byte.	 

;       Check the third most significant byte.

        movf    max_freq_1,w      ; Get high limit value
        subwf   daccc_1,w         ; Subtract the limit value
        btfss   _C 	          ; Are we at the limit for the byte?
        goto    exit1          	  ; No, below.  Checks are done.
	btfss	_Z		  ; Byte is greater than or equal to the
				  ; maximum value,so test for equality.	
	goto 	set_flag	  ; Here not equal so too large, set flag
				  ; and return. Otherwise, check next byte.	
 
;       Check the least significant byte.

        movf    max_freq_0,w      ; Get high limit value
        subwf   daccc_0,w         ; Subtract the limit value
        btfss   _C 	          ; Are we at the limit for the byte?
        goto    exit1          	  ; No, below.  Checks are done.
	btfss	_Z		  ; Byte is greater than or equal to the
				  ; maximum value,so test for equality.	
	goto 	set_flag	  ; Here not equal so too large, set flag
				  ; and return. 	

set_flag:
	bsf	MAX_FREQ_FLAG		

exit1
	bcf	PCLATH,3	  ;ensure adress on page 0 is OK
	
        return     

;*****************************************************************************
;************************       inc_step           ***************************
;*****************************************************************************
;F.Klinker,19-06-2010.

inc_step:

	movf	step_ind,w		;test if step_ind equals 7	
	sublw	D'7'
	btfsc	_Z
	goto	exit2			;yes,step_ind=7, do nothing
	incf	step_ind,f		;no,increase step_ind and set new step
	call	set_step
		
exit2:
	bcf	PCLATH,4		;ensure adress on page 0 is OK	
	bcf	PCLATH,3		;ensure adress on page 0 is OK	
        return     


;*****************************************************************************
;************************       dec_step           ***************************
;*****************************************************************************
;F.Klinker,19-06-2010.

dec_step:

	movf	step_ind,w		;test if step_ind equals 1	
	sublw	D'1'
	btfsc	_Z
	goto	exit3			;yes,step_ind=1, do nothing
	decf	step_ind,f		;no,decrease step_ind and set new step
	call	set_step
		
exit3:
	bcf	PCLATH,4		;ensure adress on page 0 is OK	
	bcf	PCLATH,3		;ensure adress on page 0 is OK	
        return    

;*****************************************************************************
;************************       set_step           ***************************
;*****************************************************************************
;determination of step size depending on step_ind.
;F.Klinker,20-06-2010. 

set_step:

	movf	step_ind,w	;test if step_ind equals 7
	sublw	D'7'
	btfsc	_Z
	goto	set_1M		;yes,it is, set step to 1MHz

	movf	step_ind,w	;test if step_ind equals 6
	sublw	D'6'
	btfsc	_Z
	goto	set_100k	;yes,it is, set step to 100kHz

	movf	step_ind,w	;test if step_ind equals 5
	sublw	D'5'
	btfsc	_Z
	goto	set_10k		;yes,it is, set step to 10kHz

	movf	step_ind,w	;test if step_ind equals 4
	sublw	D'4'
	btfsc	_Z
	goto	set_1k		;yes,it is, set step to 1kHz

	movf	step_ind,w	;test if step_ind equals 3
	sublw	D'3'
	btfsc	_Z
	goto	set_100		;yes,it is, set step to 100Hz

	movf	step_ind,w	;test if step_ind equals 2
	sublw	D'2'
	btfsc	_Z
	goto	set_10		;yes,it is, set step to 10Hz

	movf	step_ind,w	;test if step_ind equals 1
	sublw	D'1'
	btfsc	_Z
	goto	set_1		;yes,it is, set step to 1Hz

set_1M:
;set step to 1 MHz (= 0x0F4240)
	movlw	0x40		;load fstep_0
	movwf	fstep_0
	movlw	0x42		;load fstep_1
	movwf	fstep_1
	movlw	0x0F		;load fstep_2
	movwf	fstep_2
	movlw	0x00		;load fstep_3
	movwf	fstep_3

;update lcd display
	movlw	0x8B		;move cursor to step position on display 
					
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	cmd2lcd		;position 11 on 1st line (cmd=120+pos dec) 
 	movlw	'1'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	'M'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
		
        return    

set_100k:
;set step to 100 kHz (= 0x0186A0)
	movlw	0xA0		;load fstep_0
	movwf	fstep_0
	movlw	0x86		;load fstep_1
	movwf	fstep_1
	movlw	0x01		;load fstep_2
	movwf	fstep_2
	movlw	0x00		;load fstep_3
	movwf	fstep_3

;update lcd display
	movlw	0x8B		;move cursor to step position on display
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	cmd2lcd		;position 11 on 1st line (cmd=120+pos dec) 
	movlw	'1'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	'0'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	'0'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	'k'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
		
        return    

set_10k:
;set step to 10 kHz (= 0x2710)
	movlw	0x10		;load fstep_0
	movwf	fstep_0
	movlw	0x27		;load fstep_1
	movwf	fstep_1
	movlw	0x00		;load fstep_2
	movwf	fstep_2
	movlw	0x00		;load fstep_3
	movwf	fstep_3

;update lcd display
	movlw	0x8B		;move cursor to step position on display
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	cmd2lcd		;position 11 on 1st line (cmd=120+pos dec)  
	movlw	'1'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	'0'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	'k'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
		
        return    

set_1k:
;set step to 1 kHz (= 0x03E8)
	movlw	0xE8		;load fstep_0
	movwf	fstep_0
	movlw	0x03		;load fstep_1
	movwf	fstep_1
	movlw	0x00		;load fstep_2
	movwf	fstep_2
	movlw	0x00		;load fstep_3
	movwf	fstep_3

;update lcd display
	movlw	0x8B		;move cursor to step position on display
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	cmd2lcd		;position 11 on 1st line (cmd=120+pos dec)
	movlw	'1'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	'k'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
		
        return    

set_100:
;set step to 100 Hz (= 0x64)
	movlw	0x64		;load fstep_0
	movwf	fstep_0
	movlw	0x00		;load fstep_1
	movwf	fstep_1
	movlw	0x00		;load fstep_2
	movwf	fstep_2
	movlw	0x00		;load fstep_3
	movwf	fstep_3

;update lcd display
	movlw	0x8B		;move cursor to step position on display
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	cmd2lcd		;position 11 on 1st line (cmd=120+pos dec) 
	movlw	'1'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	'0'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	'0'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
		
        return    

set_10:
;set step to 10 Hz (= 0x0A)
	movlw	0x0A		;load fstep_0
	movwf	fstep_0
	movlw	0x00		;load fstep_1
	movwf	fstep_1
	movlw	0x00		;load fstep_2
	movwf	fstep_2
	movlw	0x00		;load fstep_3
	movwf	fstep_3

;update lcd display
	movlw	0x8B		;move cursor to step position on display
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	cmd2lcd		;position 11 on 1st line (cmd=120+pos dec) 
	movlw	'1'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	'0'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
		
        return    

set_1:
;set step to 1Hz (= 0x01)
	movlw	0x01		;load fstep_0
	movwf	fstep_0
	movlw	0x00		;load fstep_1
	movwf	fstep_1
	movlw	0x00		;load fstep_2
	movwf	fstep_2
	movlw	0x00		;load fstep_3
	movwf	fstep_3

;update lcd display
	movlw	0x8B		;move cursor to step position on display
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	cmd2lcd		;position 11 on 1st line (cmd=120+pos dec) 
	movlw	'1'
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
	movlw	' '
	bcf	PCLATH,4	;ensure adress on page 0 is OK	
	bcf	PCLATH,3	;
	call	data2lcd
		
        return    

 end
