 TITLE  "Frequency Counter"   	  
 List P=PIC16F648a, R=DEC	
 INCLUDE "p16f648a.inc"

SCL		EQU 2					; Clock line setup
SDA		EQU 3					; Data line setup
BLANK	EQU 11
ESYM	EQU 10

; data segment in BANK 0
 CBLOCK 0x20           
 d, cnt, del:2, FSR_save  		; local variables 
 w_save, stat_save, pc_save		; ISR variables 
 dataIO							; I2C interface variable
 digits:4, digits2:4			; storage for digits to display on LCD
 freq:4 		 				; storage for the (binary) frequency value
 freqLen						; number of decimal digits in freq
 tmillions:3, millions:2		; constants needed for the BCD conversion
 hthousands:2, tthousands:2
 thousands:2
 first, order, point, mode		; freq aux. parameters
 ENDC					

; code segment
 PAGE
  __CONFIG _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC

 ORG 0
	goto 	main

 ORG 4							; ISR (execusion time 18*40 = 720usec)
	movwf	w_save				; save Wreg
	swapf	STATUS, w			; save stat reg without
	movwf	stat_save			; changing flags

	btfss	PIR1, TMR1IF		; is it TMR1 interrupt?
	 goto	ISR_end				; NO - back to the main code
	incf	freq+3, f			; increment the TMR1 overflow counter
	bcf		PIR1, TMR1IF		; clear TMR1 interrupt flag

ISR_end
	swapf	stat_save, w		; get original flags in STATUS
	movwf	STATUS
	swapf	w_save, f			; restore Wreg		
	swapf	w_save, w
	retfie

encode7seg						; setup for 7-seg digit codes
	andlw	0x0F				
	addwf	PCL, f				; bit 5 is the decimal point
  	retlw	b'11001111' 		; digit 0 
	retlw	b'11000000' 		; digit 1
	retlw	b'01011110'			; digit 2
	retlw	b'11011100'			; digit 3
	retlw	b'11010001'			; digit 4	
	retlw	b'10011101'			; digit 5
	retlw	b'10011111'			; digit 6
	retlw	b'11001000'			; digit 7
	retlw	b'11011111' 		; digit 8
	retlw	b'11011101'			; digit 9
	retlw	b'00011111'			; letter E
	retlw	b'00000000'			; blank
 	retlw	b'00000000'			; blank
	retlw	b'00000000'			; blank
	retlw	b'00000000'			; blank
	retlw	b'00000000'			; blank 

getPointIndex					; needed for displaying the decimal point
	addwf	PCL, f
	retlw	3					; for mode=0
	retlw	2
	retlw	1
	retlw	3
	retlw	2
	retlw	1	
	retlw	-1
	retlw	-1
	retlw	-1					; for mode=1
	retlw	-1
	retlw	3
	retlw	2
	retlw	1
	retlw	-1
	retlw	-1
	retlw	-1

getOrder						; display frequency exponent
	addwf	PCL, f				; E6 = MHz
	retlw	6					; E3 = KHz
	retlw	6					; E0 = Hz
	retlw	6
	retlw	3
	retlw	3
	retlw	0
	retlw	0
	retlw	0

main       		               	; main code
	bcf		STATUS, RP0			; activate BANK 0
	clrf	PORTA				; initialize PORT A
	clrf	PORTB				; initialize PORT B
	movlw	0x07
	movwf	CMCON				; comparators OFF
	
	bsf    	STATUS, RP0      	; change to BANK 1	
	movlw	b'00101100'
	movwf	TRISA ^ 0x80		; enable RA5 and RA<3:2> for input
	movlw	b'11110011'
	movwf	TRISB ^ 0x80		; enable output on RB<3:2>

	movlw	249
	movwf	PR2 ^ 0x80			; TMR2 period (250*4*16*0.01=160msec)
	bsf		PIE1 ^ 0x80, TMR1IE	; enable TMR1 interrupts

	bcf    	STATUS, RP0        	; back to BANK 0
	movlw	156
	movwf	CCPR1L				; PWM duty cycle (100msec)
	movlw	b'00011100'
	movwf	CCP1CON				; switch to PWM mode
	movlw	3
	movwf	T2CON				; TMR2 1:16 prescaler

	movlw	6
	movwf	T1CON				; setup TMR1 (external clock, no synch)
	clrf	TMR1L				; clear the TMR1 counter
	clrf	TMR1H
	clrf	freq+3				; clear the TMR1 overflow counter
	clrf	mode				; mode=0 if T=0.1sec and mode=1 if T=1sec
	bsf		INTCON, PEIE		; enable periferal interrupts
	bsf		INTCON, GIE			; enable interrupts system

	call 	delay1ms			; required for PCF8562
	call 	initialize			; setup PCF8562
	bsf		PORTB, 2			; enable 74LV161A counter
	bsf		T2CON, TMR2ON		; start PWM and also Freq count mode
	bsf		T1CON, TMR1ON
	nop							; short delay

; 	call	testLCD
;	goto	$

loop	
	btfsc	PORTB, 1			; end of freq measurement cycle?
	 goto	$-1					; Not yet - wait

	bcf		T1CON, TMR1ON		; disable TMR1 for counting
	call	getFreq				; read the freq value from TMR1 and 74LV161A
	bcf		PORTB, 2			; clear 74LV161A and disable it for counting
	call	freq2BCD			; convert freq into BCD representation

	movf	freqLen, w
	addwf	freq, f				; now freq = 1 iff originally freq = 0
	movlw	5					; default freq counting interval is 0.1sec
	subwf	freqLen, w			; if freq value is less than 5 decimal digits
	decf	freq, f				;   (here Z=1 iff originally freq=0)
	movlw	5					; we measure the freq again in a 1sec interval
	andwf	STATUS, w			; and set mode=1			
	btfsc	STATUS, Z           ; here we check if both Z and C bits are 0
	 call	countLowFreq		; count freq in 1 sec interval

	call	displayFreq			; display freq on LCD

	clrf	TMR1L				; clear the freq counters
	clrf	TMR1H				; for the next cycle
	clrf	freq+3
	clrf	mode				; back to default mode=0 and 0.1sec counting

	btfss	PORTB, 1			; wait for a PWM pulse
	 goto	$-1					; (probably not needed)
	btfsc	PORTB, 1			; wait for the end of pulse
	 goto	$-1					
	
	bsf		PORTB, 2			; enable 74LV161A for counting			
	bsf		T1CON, TMR1ON		; enable TMR1 for counting
	btfss	PORTB, 1			; wait for a PWM pulse again
	 goto	$-1	

	goto	loop


; procedures
countLowFreq	
	incf	mode, f				; set mode=1 
	movlw	52					; settings for a 1sec delay
	movwf	del
	movlw	13
	movwf	del+1
	
	movlw	0xF0
	andwf	CCP1CON, f			; disable PWM at RB3
	bcf		INTCON, GIE			; disable interrupts 
	clrf	TMR1L				; clear the TMR1 counter
	clrf	TMR1H				
	bsf		T1CON, TMR1ON		; enable TMR1 for counting
	bsf		PORTB, 2			; stop clearing 74LV161A 
	bsf		PORTB, 3			; enable 74LV161A for counting	

	movlw	1					; this fragment takes 25000 instruction
	subwf	del, f				; cycles and provides a 1 sec delay 
	btfss	STATUS, C			; by running PIC at 100KHz
	 decf	del+1, f
	movf	del+1, w			; during this time interval the freq
	btfss	STATUS, Z			; count is taken by 74LV161A and TMR1;
	 goto	$-6					; TMR1 does not overflow, so freq+3 = 0
	nop							; end of a 1sec delay

	bcf		PORTB, 3			; disable 74LV161A for counting
	bcf		T1CON, TMR1ON		; disable TMR1 for counting
	
	call	getFreq				; read the freq value from TMR1 and 74LV161A
	clrf	freq+3
	bcf		PIR1, TMR1IF		; clear TMR1 interrupt flag
	bsf		INTCON, GIE			; enable interrupts
	bcf		PORTB, 2			; clear 74LV161A and disable it for counting
	movlw	0x0F
	iorwf	CCP1CON, f			; enable PWM at RB3
	call	freq2BCD			; convert freq into BCD representation	

	return

getFreq
	movf	PORTB, w			; get 74LV161A counted value
	movwf	freq
	rlf		freq, f
	bcf		freq, 4
	btfsc	STATUS, C
	 bsf	freq, 4
	movlw	0xF0				; clear the lower nibble
	andwf	freq, f
	movf	TMR1L, w			; get the TMR1 value in freq+2:freq+1
	movwf	freq+1				; freq+3 is set by the ISR
	movf	TMR1H, w
	movwf	freq+2				; at this point the freq counter is set up
	return

    ; code from here to freq2BCD is under development
	btfss	freq, 7				; software correction of the TMR1 value:
	 return						; it is only needed if not all bits 	
	movlw	b'11110000'			; of freq are set  
	subwf	freq, w				; in this case TMR1 has counted an extra pulse 
	btfsc	STATUS, Z			; so we need to subtract 1 from 
	 return						; (freq+3):(freq+1) to compensate this

correction
	movlw	1					; decrementing a 3-byte value	
	subwf	freq+1, f		
	clrw	
	clrf	d			
	btfss	STATUS, C
	 incfsz	d, w					
	  subwf	freq+2, f
	clrw
	btfss	STATUS, C
	 addlw	1
	subwf	freq+3, f			; end of software correction

	btfss	freq+3, 7			; the above correction was only needed
	 return						; if freq+3:freq+2:freq+1 is non-zero 
	clrf	freq+1				; in which case no correction is needed
	clrf	freq+2				; we fix it by clearing the values of
	clrf	freq+3				; freq+3:freq+2:freq+1
	return

freq2BCD
	clrf	freqLen				; number of decimal digits in freq
	call	getFirstDigit
	call	getSecondDigit
	call 	getThirdDigit	
	call	getFourthDigit

	bcf		STATUS, C			; shift freq 4 bits to the right
	rrf		freq+2, f			; at this point freq is at most 16-bit
	rrf		freq+1, f
	rrf		freq, f
	rrf		freq+2, f
	rrf		freq+1, f
	rrf		freq, f
	rrf		freq+2, f
	rrf		freq+1, f
	rrf		freq, f
	rrf		freq+2, f
	rrf		freq+1, f
	rrf		freq, f

	call	getFifthDigit
	call	getSixthDigit
	call	getLastDigits

	movlw	8
	subwf	freqLen, w			
	sublw	0					
	movwf	first				; index of freq's first digit
	movlw	6					; no rounding off is needed
	subwf	freqLen, w			; C=0 if freqLen < 6
	btfss	STATUS, C
	 goto	normalize

roundoff
	movlw	digits
	movwf	FSR
	movf	first, w
	addlw	5					; index of the rounding off digit
	addwf	FSR, f	
	movf	INDF, w				; w = rounding off digit
	sublw	4					; C=0 if digit >=5
	btfsc	STATUS, C
	 goto	normalize

	decf	FSR, f				; get to the 5-th freq digit
	incf	INDF, f				; round it off
	movlw	10
	subwf	INDF, w				; is it 10 after rounding off?
	btfss	STATUS, Z
	 goto	normalize			; NO - proceed
	clrf	INDF				; YES - clear the digit
	decf	FSR, f				; and round off the previous one

	incf	INDF, f				; round off the 4-th digit
	movlw	10
	subwf	INDF, w				; is it 10 after rounding off?
	btfss	STATUS, Z
	 goto	normalize			; NO - proceed
	clrf	INDF				; YES - clear the digit
	decf	FSR, f				; and round off the previous one

	incf	INDF, f				; round off the 3-rd digit
	movlw	10
	subwf	INDF, w				; is it 10 after rounding off?
	btfss	STATUS, Z
	 goto	normalize			; NO - proceed
	clrf	INDF				; YES - clear the digit
	decf	FSR, f				; and round off the previous one

	incf	INDF, f				; round off the 2-nd digit
	movlw	10
	subwf	INDF, w				; is it 10 after rounding off?
	btfss	STATUS, Z
	 goto	normalize			; NO - proceed
	clrf	INDF				; YES - clear the digit
	decf	FSR, f				; and round off the previous one

	incf	INDF, f				; round off the 1-st
	movlw	10
	subwf	INDF, w				; is it 10 after rounding off?
	btfss	STATUS, Z
	 goto	normalize			; NO - proceed
	clrf	INDF				; YES - clear the digit
	decf	FSR, f				; and round off the previous one
	incf	INDF, f				; the previous digit=0; this happens
	decf	first,f				; only for freq=999999, so the prev. exists

normalize							
	movf	first, w			; compute the order
	call	getOrder
	movwf	order

	movf	mode, w				; compute position of the decimal point
	btfss	STATUS, Z
	 movlw	8					; w = mode*8
	addwf	first, w
	call	getPointIndex		; get position from the table
	movwf	point
	return

displayFreq
	movlw	5					; freqLen = max(freqLen, 5)
	subwf	freqLen, w
	movlw	5
	btfsc	STATUS, C
	 movwf	freqLen

	call	start_I2C
	movlw	b'01110000'			; slave address
	movwf	dataIO
	call	write_I2C
	clrf	dataIO				; clear the address pointer
	call	write_I2C

	movf	order, w			; sending the order
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	movlw	ESYM				; sending the E symbol
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	movlw	BLANK				; separating space character
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	movf	freqLen, w			; sending freqLen digits to the LCD
	movwf	d
	movlw	digits
	addwf	first, w
	addwf	freqLen, w
	addlw	-1
	movwf	FSR_save			; FSR points to the last digit

digitsLoop
	movf	FSR_save, w			; restore the FSR
	movwf	FSR					; index of the first digit
	movf	INDF, w				; get digit
	call	encode7seg
	movwf	dataIO

	movf	d, w				; check if the decimal point
	subwf	point, w			; should be displayed
	btfsc	STATUS, Z
	 bsf	dataIO, 5			; ... and turn it on, if needed

	decf	FSR, w				; update the digits pointer
	movwf	FSR_save			; and save it
	movlw	0x85				; load FSR with the address of TRISB
	movwf	FSR
	call	write_I2C
	decfsz	d, f
	 goto	digitsLoop

	movf	freqLen, w
	sublw	4					; w = 4 - freqLen
	btfss	STATUS, C			; C=1 if freqLen < 5
	 goto	$+9

	addlw	1
	movwf	d					; add d spaces
	movlw	BLANK				; send the blanks to the LCD
	call	encode7seg
	movwf	dataIO
	call	write_I2C
	decfsz	d, f
	 goto	$-5

	call	stop_I2C
	return

getFirstDigit
	clrf	digits				
	movf	tmillions, w		; 24-bit subtract
	subwf	freq+1, f		
	movf	tmillions+1, w	
	btfss	STATUS, C
	 incfsz	tmillions+1, w		
	  subwf	freq+2, f
	movf	tmillions+2, w
	btfss	STATUS, C
	 incfsz	tmillions+2, w
	  subwf	freq+3, f			; subtraction is completed
	incf	digits, f			; update the counter
	btfsc 	STATUS, C
	 goto	getFirstDigit+1

	decf	digits, f			; restore the counter
	btfss	STATUS, Z
	 incf	freqLen, 1			; update the number of decimal digits

	movf	tmillions, w		; restore freq (add 10^7 to it)
	addwf	freq+1, f
	movf	tmillions+1, w
	btfsc	STATUS, C
	 incfsz	tmillions+1, w
	  addwf	freq+2, f
	movf	tmillions+2, w
	btfsc	STATUS, C
	 addlw	1					; here the correct C bit is not needed
	addwf	freq+3, f
	return	

getSecondDigit
	clrf	digits+1				
	movf	millions, w			; get the first byte
	subwf	freq+1, f			;
	movf	millions+1, w	
	btfss	STATUS, C
	 incfsz	millions+1, w	
	  subwf	freq+2, f
	clrw
	clrf	d					; the 3d byte of millions is 0
	btfss	STATUS, C
	 incfsz	d, w
	  subwf	freq+3, f			; subtraction is completed
	incf	digits+1, f			; update the counter
	btfsc 	STATUS, C
	 goto	getSecondDigit+1

	decf	digits+1, f			; restore the counter

	movf	digits+1, w			; update the freq length
	addwf	freqLen, w
	btfss	STATUS, Z
	 incf	freqLen, f

	movf	millions, w			; restore freq (add 10^6 to it)
	addwf	freq+1, f
	movf	millions+1, w
	btfsc	STATUS, C
	 incfsz	millions+1, w
	  addwf	freq+2, f
	clrw
	btfsc	STATUS, C
	 addlw	1					; here the correct C bit is not needed
	addwf	freq+3, f
	return		

getThirdDigit
	clrf	digits+2				
	movf	hthousands, w		; get the first byte
	subwf	freq+1, f			
	movf	hthousands+1, w		
	btfss	STATUS, C
	 incfsz	hthousands+1, w					
	  subwf	freq+2, f			; subtraction is completed
	incf	digits+2, f			; update the counter
	btfsc 	STATUS, C
	 goto	getThirdDigit+1

	decf	digits+2, f			; restore the counter

	movf	digits+2, w			; update the freq length
	addwf	freqLen, w
	btfss	STATUS, Z
	 incf	freqLen, f

	movf	hthousands, w		; restore freq (add 10^5 to it)
	addwf	freq+1, f
	movf	hthousands+1, w
	btfsc	STATUS, C
	 addlw	1
	addwf	freq+2, f
	return		

getFourthDigit
	clrf	digits+3				
	movf	tthousands, w		; get the first byte
	subwf	freq+1, f		
	movf	tthousands+1, w	
	btfss	STATUS, C
	 incfsz	tthousands+1, w
	  subwf	freq+2, f			; subtraction is completed
	incf	digits+3, f			; update the counter
	btfsc 	STATUS, C
	 goto	getFourthDigit+1

	decf	digits+3, f			; restore the counter

	movf	digits+3, w			; update the freq length
	addwf	freqLen, w
	btfss	STATUS, Z
	 incf	freqLen, f

	movf	tthousands, w		; restore freq (add 10^4 to it)
	addwf	freq+1, f
	movf	tthousands+1, w
	btfsc	STATUS, C
	 addlw	1
	addwf	freq+2, f
	return		

getFifthDigit
	clrf	digits+4			; at this point freq is 16-bit				
	movf	thousands, w		; get the first byte
	subwf	freq, f		
	movf	thousands+1, w	
	btfss	STATUS, C
	 incfsz	thousands+1, w	
	  subwf	freq+1, f			; subtraction is completed
	incf	digits+4, f			; update the counter
	btfsc 	STATUS, C
	 goto	getFifthDigit+1

	decf	digits+4, f			; restore the counter

	movf	digits+4, w			; update the freq length
	addwf	freqLen, w
	btfss	STATUS, Z
	 incf	freqLen, f

	movf	thousands, w		; restore freq (add 10^3 to it)
	addwf	freq, f
	movf	thousands+1, w
	btfsc	STATUS, C
	 addlw	1
	addwf	freq+1, f
	return		

getSixthDigit
	clrf	digits+5			; at this point freq is 16-bit				
	movlw	100				
	subwf	freq, f		
	clrw
	clrf	d
	btfss	STATUS, C
	 incfsz	d, w			
	  subwf	freq+1, f			; subtraction is completed
	incf	digits+5, f			; update the counter
	btfsc 	STATUS, C
	 goto	getSixthDigit+1

	decf	digits+5, f			; restore the counter

	movf	digits+5, w			; update the freq length
	addwf	freqLen, w
	btfss	STATUS, Z
	 incf	freqLen, f

	movlw	100					; restore freq (add 100 to it)
	addwf	freq, f
	clrw
	btfsc	STATUS, C
	 addlw	1
	addwf	freq+1, f
	return		

getLastDigits
	clrf	digits+6			; at this point freq is 8-bit				
	movlw	10					; get the first byte
	subwf	freq, f				; C=0 if diff<0
	incf	digits+6, f			; update the counter
	btfsc 	STATUS, C
	 goto	getLastDigits+1

	decf	digits+6, f			; restore the counter

	movf	digits+6, w			; update the freq length
	addwf	freqLen, w
	btfss	STATUS, Z
	 incf	freqLen, f

	movlw	10					; restore freq (add 10 to it)
	addwf	freq, w
	movwf	freq
	movwf	digits+7			; set the last digit
	incf	freqLen, f			; update freq length
	return		

testLCD
	clrf 	digits
	movlw	1
	movwf	digits+1
	movlw	2
	movwf	digits+2
	movlw	3
	movwf	digits+3
	movlw	4
	movwf	digits+4
	movlw	5
	movwf	digits+5
	movlw	6
	movwf	digits+6
	movlw	7
	movwf	digits+7

	clrf 	d
	call	start_I2C
	movlw	b'01110000'			; slave address
	movwf	dataIO
	call	write_I2C	

	clrf	dataIO				; reset the address pointer
	call	write_I2C

	movf	digits, w
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	movf	digits+1, w
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	movf	digits+2, w
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	movf	digits+3, w
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	movf	digits+4, w
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	movf	digits+5, w
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	movf	digits+6, w
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	movf	digits+7, w
	call	encode7seg
	movwf	dataIO
	call	write_I2C

	call	stop_I2C
	return	

initialize
	call 	start_I2C			; PCF8562 initialization
	movlw	b'01110000'			; slave address
	movwf	dataIO
	call	write_I2C	
	movlw	b'11001011'			; 1:3 drive mode w. 1/3 bias
	movwf	dataIO
	call	write_I2C
	clrf	dataIO				; reset the address pointer
	call	write_I2C
	clrw
	call	encode7seg			; display 0	
	movwf	dataIO
	call	write_I2C
	call	stop_I2C			; end of initialization

	movlw	b'01101000'			; constants used for BCD conversion
	movwf	tmillions
	movlw	b'10001001'
	movwf	tmillions+1
	movlw	9
	movwf	tmillions+2

	movlw	b'00100100'
	movwf	millions
	movlw	b'11110100'
	movwf	millions+1

	movlw	b'01101010'
	movwf	hthousands
	movlw	b'00011000'
	movwf	hthousands+1

	movlw	b'01110001'
	movwf	tthousands
	movlw	2
	movwf	tthousands+1

	movlw	b'11101000'
	movwf	thousands	
	movlw	3
	movwf	thousands+1
	return

start_I2C						; start setup for I2C interface
	movlw	0x85				; setup FSR to point to TRISA
	movwf	FSR
	movlw	b'11110011'
	andwf	PORTA, f
	bsf		INDF, SDA			; pull high SDA and SCL
	bsf		INDF, SCL
	goto	$+1					; delay slot
	bcf		INDF, SDA			; set data low
	nop							; wait for slave to detect it
	bcf		INDF, SCL			; set clock low
	return

stop_I2C						; stop setup for I2C interface
	movlw	b'11110011'
	andwf	PORTA, f
	bcf		INDF, SCL			; make sure that clock and data
	bcf		INDF, SDA			;  lines are low
	goto	$+1
	bsf		INDF, SCL			; release clock line
	goto	$+1
	bsf		INDF, SDA			; release data line
	return

write_I2C						; write byte to I2C line
	movlw	b'11110011'
	andwf	PORTA, f
	bcf		INDF, SCL			; make sure that clock is low
	movlw	8
	movwf	cnt					; bits counter

w_loop
	bcf		INDF, SDA			; start w. data bit low
	rlf		dataIO, f			; get the rightmost data bit
	btfsc	STATUS, C
	 bsf	INDF, SDA			; now the data bit is on the data bus
	bsf		INDF, SCL			; raise clock up
	bcf		INDF, SCL			; ... and low
	decfsz	cnt, f
	 goto	w_loop				; repeat this 8 times

	bsf		INDF, SDA			; get ACK from slave		
	nop							; let slave respond
	bsf		INDF, SCL			; clock up
	nop							; slave responds OK (hopefully)
	bcf		INDF, SCL			; clock down
	return

delay1ms
	movlw	5
	sublw	1					; this loop takes 200us*5 = 1ms
	sublw	0					; for PIC16F648a @ 100 kHz
	btfss	STATUS, Z
	 goto 	$-3
	return

setTestFreq
	movlw	b'10110000'
	movwf	freq
	movlw	b'00000000'
	movwf	freq+1
	movlw	b'00000000'
	movwf	freq+2
	movlw	b'00000000'
	movwf	freq+3
	return

 end
