; Bat frequency heterodyne counter
; 
; derived from a counter with 4 digits
; actually uses only 2 digits now
; redundant zero are kept
;
; last change: September 2, 1999
; Bertrik Sikken


CommonAnode	equ	1
CommonCathode	equ	2

DisplayType	equ	CommonCathode
DebugMode	equ	0			; set to 0 in final version !!!!


	if	DisplayType==CommonCathode
	messg	"Compiling for common cathode"
	else
	messg	"Compiling for common anode"
	endif

	if	DebugMode==1
	messg	"Warning: compiling for debugging !"
	endif


; !!!! make sure to change the following lines when
; !!!! using the PIC16F84 instead of PIC16C84

	list    p=16c84, r=DEC
	include p16c84.inc
	__fuses _WDT_OFF & _XT_OSC & _PWRTE_ON


; definition of hardware connections
#define pin_osc_in      PORTA,4
; RA0 = left digit common, RA1 = right digit common
#define	pin_dig_left	PORTA,0
#define	pin_dig_right	PORTA,1
; PORTB 1-7 is connected to segments a-g



; definition of variables
	cblock 12
	count
	temp1
	temp2
	dig1
	dig2
	muxcount
	int16_a
	int16_b
	int16_c_hi
	int16_c_lo
	int16_count
	templed7
	endc


init
	bsf     STATUS,RP0
; set tristate registers
	movlw   B'00000001'		; all outputs for PORTB bits 1-7
	movwf   PORTB
	movlw   B'11111'		; all inputs
	movwf   PORTA
; no prescaler, external, rising edge
	movlw   B'10101000'             
	movwf   TMR0
	bcf     STATUS,RP0

; program mainloop
main
	call    count_pulses
	call    convert_digits
	goto    main



;------------------------------------------
; led conversion lookup table


led7
; in:  number in W
; out: 7-seg code in W in format B'gfedcba0'
;	movwf   templed7
;	movlw   HIGH led7               ; protect against wrong page
;	movwf   PCLATH
;	movfw   templed7
	andlw   15
	addwf   PCL,f
; format B'abcdefg.'
	if	DisplayType==CommonCathode

	retlw   B'01111110'
	retlw   B'00001100'
	retlw   B'10110110'
	retlw   B'10011110'
	retlw   B'11001100'
	retlw   B'11011010'
	retlw   B'11111010'
	retlw   B'00001110'
	retlw   B'11111110'
	retlw   B'11011110'
	retlw	B'10000000'
	retlw	B'10000000'
	retlw	B'10000000'
	retlw	B'10000000'
	retlw	B'10000000'
	retlw	B'00000000'			; empty character

	else

	retlw	B'10000000'
	retlw	B'11110010'
	retlw	B'01001000'
	retlw	B'01100000'
	retlw	B'00110010'
	retlw	B'00100100'
	retlw	B'00000100'
	retlw	B'11110000'
	retlw	B'00000000'
	retlw	B'00100000'
	retlw	B'01111110'
	retlw	B'01111110'
	retlw	B'01111110'
	retlw	B'01111110'
	retlw	B'01111110'
	retlw	B'11111110'			; empty character

	endif	

led7end

	if	HIGH led7 != HIGH led7end
	error	"Warning: page overflow in table lookup!"
	endif



;------------------------------------------
; update digits
; each digit is lit for approx. 0.5 msec, so the total
; time spent is almost 1 msec

display
	if	DisplayType==CommonCathode
		bcf	pin_dig_left
	else
		bsf	pin_dig_left
	endif
	movfw	dig1
	call    led7
	movwf   PORTB
	bsf	STATUS,RP0
	bcf	pin_dig_left			; set pin as output
	bcf	STATUS,RP0
	call	delay500u


	if	DisplayType==CommonCathode
		bcf	pin_dig_right
	else
		bsf	pin_dig_right
	endif
	bsf	STATUS,RP0
	bsf	pin_dig_left			; pin = input
	bcf	pin_dig_right			; pin = output
	bcf	STATUS,RP0

	movfw	dig2
	call	led7
	movwf	PORTB
	call	delay500u

	bsf	STATUS,RP0
	bsf	pin_dig_right
	bcf	STATUS,RP0

	nop			; timing adjustment

	return


delay500u
; delay for approx. 0.5 msec
	movlw   159
	movwf   temp1
dis_loop3
	decfsz  temp1,f
	goto    dis_loop3
	return

;------------------------------------------

; divides 15-bit number in int16_c by 7-bit int16_b into int16_a
; the remainder goes into int16_c_hi
divide
	movlw   8
	movwf   int16_count
div_loop
	rlf     int16_c_lo,f
	rlf     int16_c_hi,f
	movfw   int16_b
	subwf   int16_c_hi,w
	btfsc   STATUS,C
	movwf   int16_c_hi
	rlf     int16_a,f
	decfsz  int16_count,f
	goto    div_loop
	return

;------------------------------------------
; the following routine converts the 16-bit value
; in count_c_lo and count_c_hi into 2 decimal digits
; dig1 is the most significant digit

convert_digits
; divide count by 10
	movfw   count
	movwf   int16_c_lo
	clrf	int16_c_hi
	movlw   10
	movwf   int16_b
	call    divide

	movfw	int16_a
	movwf	dig1
	movfw	int16_c_hi
	movwf	dig2
	return



;------------------------------------------
; count pulses in a 1 msec period, this
; corresponds to the frequency in multiples of 1 kHz


count_pulses

; wait for first edge down
	if	DebugMode==0

c2w1    btfss   pin_osc_in
	goto    c2w1
c2w2    btfsc   pin_osc_in
	goto    c2w2

	endif

; reset timer & prescaler : start count
	clrf    TMR0
; refresh display during counting ...
	call    display
; save count:
	movfw   TMR0
	movwf   count
	return

	END
