Piclist Weedfreq 8DIGIT.ASM
The Weeder Frequency Counter
Expanded by Brad Hernlem
3 byte count, 8 digits, 1Hz resolution below 16MHz
;******************************************************************************
; FREQUENCY COUNTER
; Model : WTCNT
; Author : Terry J. Weeder
; Date : November 18, 1993
; Version: 1.0
;
; WWW.WEEDTECH.COM
;
; Ported to 16f84 by
; Peter Cousens
; October 1998
;
; Further revised,
; expanded and modified by
; Brad Hernlem
; October 2000
;******************************************************************************
; This version is changed to use the full capability to count to 3 byte
; quantities (16,777,215) and disables the overflow at 10,000,000 originally
; in Cousens' code. Also, 8 digits are used instead of seven and the gate
; times are set to 1 second to allow 1 Hz resolution on all ranges.
; When the frequency exceeds 16,777,215 Hz the gate period is
; reduced to 0.1 second to keep the count within 3 bytes. When frequency is
; again less than 16,777,216 Hz the gate period reverts to 1 second.
; Please also note that the register addresses are now designated in a
; CBLOCK. This means that any changes to the CBLOCK MUST NOT affect the
; fixed addresses of the digs to digs+7 registers which SHOULD begin at
; 0C and increase from there. If these are changed, the FSR indirect
; addressing will be munged.
;
; Other changes:
;
; 1) the LCD control pins are reassigned to be compatible with Halicky's code
; 2) the display reads "0" when no pulses are inputted. Cousens' code included
; an rtcc toggle of unknown use which gave an output of "1" without input.
; 3) display shows message "Counting" during initial 1 second count delay.
;
; [Brad Hernlem]
;
; FCounter.ASM
;***************************************************************************
list P=PIC16F84A
INCLUDE <P16f84a.inc>
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
rtcc equ 1h
c equ 0h
z equ 2h
o equ 7h
rs equ 0h ;This bits were changed for compatibility
rw equ 1h ;with other counter
e equ 2h ;routines (e.g. Halicky)
;Cousens had the following hard designated. CBLOCK makes them float
;but BEWARE that digs is addressed by FSR and MUST NOT be changed from
;the first position of this block
CBLOCK h'0C'
digs:8 ;the display digits registers digs to digs+7
count1
count2
addcnt
gate
cnt1
cnt2
cnt3
calc1
calc2
calc3
sum1
sum2
sum3
rtcc2
temp1
temp2
temp3
cnt4
ENDC
;
org 0
goto start
;
int_del movlw 0x05 ;delay 5.000 ms (4 MHz clock)
movwf count1
d1 movlw 0xA5
movwf count2
d2 decfsz count2,f
goto d2
decfsz count1,f
goto d1
retlw 0x00
;
lcd_out movwf PORTB ;load data into PORTB
movlw b'00000000' ;define PORTB as output
tris PORTB
bsf PORTA,rs ;rs = data
bcf PORTA,rw ;r/w = write
bsf PORTA,e ;toggle enable
bcf PORTA,e
movlw b'11111111' ;define PORTB as input
tris PORTB
bcf PORTA,rs ;rs = instruction
bsf PORTA,rw ;r/w = read
bsf PORTA,e ;enable high
movf PORTB,w ;get address counter
movwf addcnt
bsf addcnt,7
bcf PORTA,e ;enable low
out1 bsf PORTA,e ;enable high
btfss PORTB,7 ;test busy flag
goto out2
bcf PORTA,e ;enable low
goto out1
out2 bcf PORTA,e ;enable low
goto shift
;
inst movwf PORTB ;load instruction into PORTB
movlw b'00000000' ;define PORTB as output
tris PORTB
bcf PORTA,rs ;rs = instruction
bcf PORTA,rw ;r/w = write
bsf PORTA,e ;toggle enable
bcf PORTA,e
movlw b'11111111' ;define PORTB as input
tris PORTB
bsf PORTA,rw ;r/w = read
inst1 bsf PORTA,e ;enable high
btfss PORTB,7 ;test busy flag
goto inst2
bcf PORTA,e ;enable low
goto inst1
inst2 bcf PORTA,e ;enable low
retlw 0x00
;
shift btfss addcnt,0 ;shift to opposite side of display?
retlw 0x00
btfss addcnt,1
retlw 0x00
btfss addcnt,2
retlw 0x00
btfss addcnt,3
retlw 0x00
movlw 0x39
addwf addcnt,f
bsf addcnt,7
movf addcnt,w
goto inst
;
sub bcf STATUS,o ;clear overflow bit
movf calc1,w ;subtract calc1 from cnt1
subwf cnt1,f
btfsc STATUS,c
goto sb1
movlw 0x01 ;borrow from cnt2 if overflow
subwf cnt2,f
btfsc STATUS,c
goto sb1
subwf cnt3,f ;borrow from cnt3 if cnt2 overflow
btfss STATUS,c
bsf STATUS,o ;set overflow bit if result is negative
sb1 movf calc2,w ;subtract calc2 from cnt2
subwf cnt2,f
btfsc STATUS,c
goto sb2
movlw 0x01 ;borrow from cnt3 if cnt2 overflow
subwf cnt3,f
btfss STATUS,c
bsf STATUS,o ;set overflow bit if result is negative
sb2 movf calc3,w ;subtract calc3 from cnt3
subwf cnt3,f
btfss STATUS,c
bsf STATUS,o ;set overflow bit if result is negative
retlw 0x00
;
add movf calc1,w ;add calc1 to cnt1
addwf cnt1,f
btfss STATUS,c
goto ad1
incfsz cnt2,f ;add to cnt2 if cnt1 overflow
goto ad1
incf cnt3,f ;add to cnt3 if cnt2 overflow
ad1 movf calc2,w ;add calc2 to cnt2
addwf cnt2,f
btfsc STATUS,c
incf cnt3,f ;add to cnt3 if cnt2 overflow
movf calc3,w ;add calc3 to cnt3
addwf cnt3,f
retlw 0x00
;
; The following has been modified to extract 8 digits
; and get 1 Hz accuracy up to the full 3 byte limit of 16,777,215
;
cnvt movlw 0x08 ;8 digits in display
movwf count1
movlw 0x0C ;set fsr for MSB in display
movwf FSR
movlw 0x2F ;one less that ASCII "0"
cnvt0 movwf INDF
incf FSR,f
decfsz count1,f
goto cnvt0
movlw 0x98 ;load "10,000,000" in calc1-3
movwf calc3
movlw 0x96
movwf calc2
movlw 0x80
movwf calc1
cnvt1 call sub ;subtract 10 million from count
incf digs,f ;increment 10,000,000s register
btfss STATUS,o ;check if overflow
goto cnvt1
call add ;add back last number
movlw 0x0F ;load "1,000,000" in calc1-3
movwf calc3
movlw 0x42
movwf calc2
movlw 0x40
movwf calc1
cnvt2 call sub ;subtract number from count
incf digs+1,f ;increment 1,000,000's register
btfss STATUS,o ;check if overflow
goto cnvt2
call add ;add back last number
movlw 0x01 ;load "100,000" in calc1-3
movwf calc3
movlw 0x86
movwf calc2
movlw 0xA0
movwf calc1
cnvt3 call sub ;subtract number from count
incf digs+2,f ;increment 100,000's register
btfss STATUS,o ;check if overflow
goto cnvt3
call add ;add back last number
clrf calc3 ;load "10,000" in calc1-3
movlw 0x27
movwf calc2
movlw 0x10
movwf calc1
cnvt4 call sub ;subtract number from count
incf digs+3,f ;increment 10,000's register
btfss STATUS,o ;check if overflow
goto cnvt4
call add ;add back last number
movlw 0x03 ;load "1,000" in calc1-3
movwf calc2
movlw 0xE8
movwf calc1
cnvt5 call sub ;subtract number from count
incf digs+4,f ;increment 1,000's register
btfss STATUS,o ;check if overflow
goto cnvt5
call add ;add back last number
clrf calc2 ;load "100" in calc1-3
movlw 0x64
movwf calc1
cnvt6 call sub ;subtract number from count
incf digs+5,f ;increment 100's register
btfss STATUS,o ;check if overflow
goto cnvt6
call add ;add back number
movlw 0x0A ;load "10" in calc1-3
movwf calc1
cnvt7 call sub ;subtract number from count
incf digs+6,f ;increment 10's register
btfss STATUS,o ;check if overflow
goto cnvt7
call add ;add back last number
movf cnt1,w ;put remainder in 1's register
addwf digs+7,f
incf digs+7,f
retlw 0x00
;
; Count period is 25*count2*count1 clocks
; for 4MHz crystal with count2=200, count1=20 gives 0.1 s gate period
; count1=200 gives 1 s gate period
;
count movlw b'00110111' ;rtcc = ext, 1/256
option
movlw b'00010000' ;define PORTA as output
tris PORTA
bcf PORTA,3
bcf PORTA,rs
clrf cnt3
clrf cnt4
clrf temp3
clrf rtcc
clrf rtcc2
; bsf PORTA,rs ;toggle rtcc pin
; bcf PORTA,rs ;[these two lines were in Cousens' code. purpose unkown]
movf gate,w ;get gate time
movwf count1
st1 bsf PORTA,3 ;start count
fr4 movlw 0xC8 ;1 count2 set to 200
movwf count2 ;2
goto fr6 ;4
fr5 nop ;24
nop ;25
nop ;01
nop ;02
nop ;03
nop ;04
fr6 movf rtcc,w ;5 test for rtcc rollover (12)
subwf rtcc2,f ;6
btfss STATUS,z ;7
goto fr7 ;9
nop ;9
goto fr8 ;11
fr7 btfsc STATUS,c ;10
incf cnt3,f ;11
fr8 movwf rtcc2 ;12
movf cnt3,w ;13 test for cnt3 rollover
subwf temp3,f ;14
btfss STATUS,z ;15
goto br1 ;17
nop ;17
goto br2 ;19
br1 btfsc STATUS,c ;18
incf cnt4,f ;19 increment cnt4 if cnt3 rollover
br2 movwf temp3 ;20
decfsz count2,f ;21
goto fr5 ;23
decfsz count1,f ;23+25(count2-1)
goto fr4 ;25
bcf PORTA,3 ;25*count2*count1 stop count
st2 movf rtcc,w ;get rtcc count
movwf cnt2
subwf rtcc2,f ;test for rtcc rollover
btfss STATUS,c
goto fr9
btfss STATUS,z
incf cnt3,f
fr9 clrf cnt1 ;set to get prescaler count
fr10 decf cnt1,f
bsf PORTA,rs ;toggle rtcc pin
bcf PORTA,rs
movf rtcc,w ;test if rtcc has changed
xorwf cnt2,w
btfsc STATUS,z
goto fr10
retlw 0x00
;
;******************************************************************************
; START
;******************************************************************************
;
start clrf PORTA ;instruction, write, enable low
movlw b'00010000'
tris PORTA
clrf PORTB
movlw b'00000000'
tris PORTB
call int_del
call int_del
call int_del
movlw 0x38 ;initialize display
movwf PORTB
bsf PORTA,e ;toggle enable
call int_del
bcf PORTA,e
bsf PORTA,e ;toggle enable
call int_del
bcf PORTA,e
bsf PORTA,e ;toggle enable
call int_del
bcf PORTA,e
movlw 0x38 ;function
call inst
movlw b'00001100' ;display on, cursor off
call inst
movlw b'00000001' ;clear display
call inst
movlw b'00000110' ;entry mode
call inst
; Intro message during initial count
movlw 0x20 ;space
call lcd_out
movlw 0x20 ;space
call lcd_out
movlw 0x20 ;space
call lcd_out
movlw 0x20 ;space
call lcd_out
movlw 0x43 ;C
call lcd_out
movlw 0x6F ;0
call lcd_out
movlw 0x75 ;u
call lcd_out
movlw 0x6E ;n
call lcd_out
movlw 0x74 ;t
call lcd_out
movlw 0x69 ;i
call lcd_out
movlw 0x6E ;n
call lcd_out
movlw 0x67 ;g
call lcd_out
;
mhz movlw 0xC8 ;1 sec gate
movwf gate
call count
clrw ;check whether cnt4 is zero
xorwf cnt4,w
btfss STATUS,z
goto shortg ;not zero - use shorter gate period
call cnvt ;convert binary to BCD
movlw 0x30 ;test if "0"
xorwf digs,w
btfss STATUS,z
goto mhz1
movlw 0x30 ;test if "0"
xorwf digs+1,w
btfsc STATUS,z
goto khz1
mhz1 movlw 0x81 ;set display address
call inst
movlw 0x02 ;output first 2 characters
movwf count1
movlw 0x0C ;MSD of freq, i.e. digs
movwf FSR
mhz2 movlw 0x30 ;test if "0"
xorwf INDF,w
btfss STATUS,z
goto mhz3
movlw 0x20 ;change preceeding "0's" to "space"
call lcd_out
incf FSR,f
decfsz count1,f
goto mhz2
goto mhz4
mhz3 movf INDF,w
call lcd_out
incf FSR,f
decfsz count1,f
goto mhz3
mhz4 movlw 0x2E ;"."
call lcd_out
movlw 0x06 ;output last 6 characters
movwf count1
mhz5 movf INDF,w
call lcd_out
incf FSR,f
decfsz count1,f
goto mhz5
movlw 0x20 ;"space"
call lcd_out
movlw 0x4D ;"M"
call lcd_out
movlw 0x48 ;"H"
call lcd_out
movlw 0x7A ;"z"
call lcd_out
movlw 0x20 ;"space"
call lcd_out
movlw 0x20 ;"space"
call lcd_out
goto mhz
;
khz movlw 0xC8 ;1 sec gate
movwf gate
call count
call cnvt ;convert binary to BCD
movlw 0x30 ;test if 0
xorwf digs,w
btfss STATUS,z
goto mhz1
movlw 0x32 ;test if < 2
subwf digs+1,w
btfsc STATUS,c
goto mhz1
movlw 0x30 ;test if "0"
xorwf digs+1,w
btfss STATUS,z
goto khz1
movlw 0x30 ;test if "0"
xorwf digs+2,w
btfss STATUS,z
goto khz1
movlw 0x30 ;test if "0"
xorwf digs+3,w
btfsc STATUS,z
goto hz0
khz1 movlw 0x81 ;set display address
call inst
movlw 0x05 ;output first 5 characters
movwf count1
movlw 0x0C ;MSD of freq, digs register
movwf FSR
khz2 movlw 0x30 ;test if "0"
xorwf INDF,w
btfss STATUS,z
goto khz3
movlw 0x20 ;change preceeding "0's" to "space"
call lcd_out
incf FSR,f
decfsz count1,f
goto khz2
goto khz4
khz3 movf INDF,w
call lcd_out
incf FSR,f
decfsz count1,f
goto khz3
khz4 movlw 0x2E ;"."
call lcd_out
movf INDF,w ;output last 3 characters
call lcd_out
incf FSR,f
movf INDF,w
call lcd_out
incf FSR,f
movf INDF,w
call lcd_out
movlw 0x20 ;"space"
call lcd_out
movlw 0x4B ;"K"
call lcd_out
movlw 0x48 ;"H"
call lcd_out
movlw 0x7A ;"z"
call lcd_out
movlw 0x20 ;"space"
call lcd_out
movlw 0x20 ;"space"
call lcd_out
goto khz
;
hz movlw 0xC8 ;1 sec gate
movwf gate
call count
call cnvt ;convert binary to BCD
movlw 0x30 ;test if "0"
xorwf digs,w
btfss STATUS,z
goto mhz1
movlw 0x32 ;test if < 2
subwf digs+1,w
btfsc STATUS,c
goto mhz1
movlw 0x30 ;test if "0"
xorwf digs+1,w
btfss STATUS,z
goto khz1
movlw 0x30 ;test if "0"
xorwf digs+2,w
btfss STATUS,z
goto khz1
movlw 0x30 ;test if "0"
xorwf digs+3,w
btfss STATUS,z
goto khz1
hz0 movlw 0x81 ;set display address
call inst
movlw 0x07 ;output first 7 characters
movwf count1
movlw 0x0C ;MSD of freq, digs register
movwf FSR
hz1 movlw 0x30 ;test if "0"
xorwf INDF,w
btfss STATUS,z
goto hz2
movlw 0x20 ;change preceeding "0's" to "space"
call lcd_out
incf FSR,f
decfsz count1,f
goto hz1
goto hz3
hz2 movf INDF,w
call lcd_out
incf FSR,f
decfsz count1,f
goto hz2
hz3 movf INDF,w
call lcd_out
movlw 0x20 ;"space"
call lcd_out
movlw 0x48 ;"H"
call lcd_out
movlw 0x7A ;"z"
call lcd_out
movlw 0x20 ;"space"
call lcd_out
movlw 0x20 ;"space"
call lcd_out
movlw 0x20 ;"space"
call lcd_out
movlw 0x20 ;"space"
call lcd_out
goto hz
;
shortg movlw 0x14 ;0.1 sec gate
movwf gate
call count
call tenx ;multiply count by ten
clrw ;check whether cnt4 is zero
xorwf cnt4,w
btfsc STATUS,z
goto mhz ;was zero - use longer gate period
call cnvt ;convert binary to BCD
movlw 0x30 ;test if "0"
xorwf digs,w
btfss STATUS,z
goto shg1
movlw 0x30 ;test if "0"
xorwf digs+1,w
btfsc STATUS,z
goto mhz
shg1 movlw 0x81 ;set display address
call inst
movlw 0x03 ;output first 3 characters
movwf count1
movlw 0x0C ;MSD of freq, i.e. digs
movwf FSR
shg2 movlw 0x30 ;test if "0"
xorwf INDF,w
btfss STATUS,z
goto shg3
movlw 0x20 ;change preceeding "0's" to "space"
call lcd_out
incf FSR,f
decfsz count1,f
goto shg2
goto shg4
shg3 movf INDF,w
call lcd_out
incf FSR,f
decfsz count1,f
goto shg3
shg4 movlw 0x2E ;"."
call lcd_out
movlw 0x05 ;output last 5 characters
movwf count1
shg5 movf INDF,w
call lcd_out
incf FSR,f
decfsz count1,f
goto shg5
movlw 0x20 ;"space"
call lcd_out
movlw 0x4D ;"M"
call lcd_out
movlw 0x48 ;"H"
call lcd_out
movlw 0x7A ;"z"
call lcd_out
movlw 0x20 ;"space"
call lcd_out
movlw 0x20 ;"space"
call lcd_out
goto shortg
;
; This subroutine multiplies the count in cnt1-3 by 10 (called from the 0.1 sec
; gate routine) and puts any overflow into cnt4. This is to check whether the frequency
; has gone back under 16,777,216 and whether the gate period should be increased to 1 sec.
;
tenx clrf cnt4 ;clear the overflow register and
movf cnt1,w ;fill calc1-3 with current cnt1-3 values
movwf calc1 ;it is assumed that cnt4 cannot be non-zero
movf cnt2,w ;when the gate period is only 0.1 sec
movwf calc2 ;
movf cnt3,w ;
movwf calc3 ;
bcf STATUS,c
rlf calc1,f ;multiply by 2 and carry through
rlf calc2,f
rlf calc3,f
btfsc STATUS,c
incf cnt4,f
movf calc1,w ;temporarily store the times 2 value
movwf temp1
movf calc2,w
movwf temp2
movf calc3,w
movwf temp3
bcf STATUS,c
rlf calc1,f ;multiply by 2 twice and check for carry each time
rlf calc2,f
rlf calc3,f
btfsc STATUS,c
incf cnt4,f
bcf STATUS,c
rlf calc1,f
rlf calc2,f
rlf calc3,f
btfsc STATUS,c
incf cnt4,f
movf temp1,w ;now add the x2 and x8 values for x10 total
addwf calc1,f
btfsc STATUS,c
incf calc2, f
btfsc STATUS,z
incf calc3,f
btfsc STATUS,z
incf cnt4,f
movf temp2,w
addwf calc2,f
btfsc STATUS,c
incf calc3,f
btfsc STATUS,z
incf cnt4,f
movf temp3,w
addwf calc3,f
btfsc STATUS,c
incf cnt4,f
return
;
end
file: /Techref/piclist/weedfreq/8digit.asm, 22KB, , updated: 2006/4/7 13:43, local time: 2024/11/19 06:07,
|
| ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/techref/piclist/weedfreq/8digit.asm"> piclist weedfreq 8digit</A> |
Did you find what you needed?
|