; FREQUENY COUNTER
; my clk is 12 mhz
; Maximum input frequency is clk / 24 or in my case 500khz.
; All sfr's used are saved. You, like me are probably using 
; them for something else like baud rate and a real-time clock.
; Input freq must be high for at least 2 machine states.
; my input conditioner uses a 7474 as last counter to make input square.
; accuracy is good to + or - 10 hz
; for my test, I used a 1.8432mhz clock into a 74191 and then the 7474.
;
$mod51
$nolist
$nosymbols
$include(mymon.inc)
$include(controls.inc)
$list
t0vec	equ	00bh
count	equ	not 10000		; clk / 12 / 100 - code
ready	bit	21h.0
oie	data	24h
otmod	data	25h
otl0	data	26h
oth0	data	27h
otl1	data	28h
oth1	data	29h
oip	data	2ah
opcon	data	2bh
otcon	data	2ch
freq	data	2dh
;	and	2eh
tenth	data	2fh

vec0hi	data	44h
vec0lo	data	45h

	org	tpa		; transient program area (cpm diehard)
start:	jmp	main
;
t0isr:	dec	a		; isr is 100hz / 10 = 10hz
	jnz	t0dun	
	clr	tr1		; stop counter 1
	mov	freq,th1
	mov	freq+1,tl1
	setb	ready
t0dun:	reti
	
main:	call	save_context
	mov	dptr,#t0isr	; timer 0 service routine
	mov	a,#t0vec
	call	setint
; timer 1 is a 16 bit counter 
; timer 0 is a 16 bit timer
	mov	tmod,#51h
	mov	tl0,#low count
	mov	th0,#high count		; 1/100 second
	clr	a
	mov	tl1,a		; clear counter
	mov	th1,a
	mov	freq,a		; clear frequency
	mov	freq+1,a
	mov	tenth,#10
	clr	ready
	clr	tf0
	clr	tf1
	setb	p3.4
	setb	p3.5
	setb	et0		; enable timer 0 int
	setb	tr1		; start counter 1
	setb	tr0		; start timer 0
	setb	ea
wait:	jnb	ready,wait	; wait until done
	clr	tr0		; stop timer 0
	call	restore_context
	call	crlf
	mov	dpl,freq+1
	mov	dph,freq
	push	radix
	push	radsiz
	mov	radix,#10
	mov	radsiz,#5
	call	prtaddr
	call	ilprt
	db	8,'0 hz',0	; backup and print an 0, always * 10
	call	crlf
	pop	radsiz
	pop	radix
	jmp	hot

restore_context:
	clr	ea
;
	mov	dptr,#t0vec		; reset timer 0 isr
	inc	dptr
	mov	a,vec0hi
	movx	@dptr,a
	inc	dptr		
	mov	a,vec0lo
	movx	@dptr,a
;
	mov	a,opcon
	mov	pcon,a			; restore power control reg
	mov	a,otl1
	mov	tl1,a
	mov	a,oth1
	mov	th1,a			; restore timer 1 counter
	mov	a,otl0
	mov	tl0,a
	mov	a,oth0
	mov	th0,a			; restore timer 0 counter
	mov	a,otmod
	mov	tmod,a			; reenable timers as they were
	mov	a,otcon
	mov	tcon,a			; restore timer control
	mov	a,oip
	mov	ip,a			; restore priority
	mov	a,oie
	mov	ie,a			; reenable ints as they were
	ret
;
save_context:
	mov	a,ie
	mov	oie,a		; save interrupt enable flags
	mov	ie,#0		; stop all interrupts
;
	mov	dptr,#t0vec	; save timer 0 isr
	inc	dptr
	movx	a,@dptr
	mov	vec0hi,a
	inc	dptr		
	movx	a,@dptr
	mov	vec0lo,a

	mov	a,tmod
	mov	otmod,a		; save timer mode reg
	mov	a,tcon
	mov	otcon,a		; save timer control reg
	mov	a,tl0
	mov	otl0,a
	mov	a,th0
	mov	oth0,a		; save timer 0 counter
	mov	a,tl1
	mov	otl1,a
	mov	a,th1
	mov	oth1,a		; save timer 1 counter
	mov	a,ip			
	mov	oip,a		; save priority reg
	mov	a,pcon
	mov	opcon,a		; save power control reg
	ret

	end
	
