; Bat frequency heterodyne counter ; ; this version should remove redundant leading zeros ; ; last change: June 6, 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 connection #define pin_osc_gate PORTB,0 #define pin_osc_in PORTA,4 ; PORTB 1-7 is connected to segments a-g ; PORTA 0-3 is connected to LED commons (RA0 to leftmost digit, RA3 to rightmost) ; definition of variables cblock 12 count_hi count_lo temp1 temp2 dig1 dig2 dig3 dig4 muxcount mux_out hun_lsb dis_count int16_a int16_b int16_c_hi int16_c_lo int16_count templed7 endc init bsf STATUS,RP0 ; set tristate registers movlw 0 ; all outputs for PORTB movwf PORTB movlw B'10000' ; RA4 is input, rest of PORTA is output movwf PORTA ; set prescaler to 256, external, rising edge movlw B'10100111' 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. 2.5 msec, so the total ; time spent is almost 10 msec display if DisplayType==CommonCathode movlw B'11111110' else movlw B'00000001' endif movwf mux_out movlw dig1 ; address of leftmost digit movwf FSR movlw 4 movwf dis_count dis_loop1 movfw mux_out ; activate common pin of LED movwf PORTA if DisplayType==CommonCathode bsf STATUS,C ; shift in 1 else bcf STATUS,C ; shift in 0 endif rlf mux_out,f ; set next common pin movfw INDF call led7 movwf PORTB incf FSR,f ; set FSR to next digit ; delay for approx. 2.5 msec movlw 25 movwf temp2 dis_loop2 movlw 19 movwf temp1 dis_loop3 nop nop decfsz temp1,f goto dis_loop3 decfsz temp2,f goto dis_loop2 nop ; timing adjustment nop nop decfsz dis_count,f goto dis_loop1 movfw mux_out movwf PORTA nop nop 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 4 decimal digits ; dig1 is the most significant digit ; ; leading zeros are converted to a special character convert_digits ; divide count by 100 movfw count_lo movwf int16_c_lo movfw count_hi movwf int16_c_hi movlw 100 movwf int16_b call divide ; the remainder is used to find the 2 right digits movfw int16_c_hi movwf hun_lsb ; the ratio is used to find the 2 left digits movfw int16_a ; now divide by 10 to find individual digits 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 movfw hun_lsb movwf int16_c_lo clrf int16_c_hi call divide movfw int16_a movwf dig3 movfw int16_c_hi movwf dig4 ; remove leading zeros by converting them to a special character movlw dig1 movwf FSR movlw 2 movwf temp1 rz_loop1 movfw INDF btfss STATUS,Z goto rz_end movlw 15 ; empty character code movwf INDF incf FSR,f decfsz temp1,f goto rz_loop1 rz_end return ;------------------------------------------ ; count pulses in a 10 msec period, this ; corresponds to the frequency in multiples of 100 Hz count_pulses ; enable counting bsf STATUS,RP0 bsf pin_osc_gate bcf STATUS,RP0 ; 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 ; close gate: stop counting bcf pin_osc_gate bsf STATUS,RP0 bcf pin_osc_gate ; make gate 0 bcf STATUS,RP0 ; save count: ; the high 8 bits are in TMR0 movfw TMR0 movwf count_hi ; the low 8 bits are in the prescaler ; The contents of the prescaler can be read by stimulating ; the count input and determining when the prescaler overflows ; and causes TMR0 to change if DebugMode==0 clrf count_lo c2loop3 bsf pin_osc_gate ; stimulate input decf count_lo,f bcf pin_osc_gate movfw count_hi ; check if TMR0 has changed subwf TMR0,w btfsc STATUS,Z goto c2loop3 endif return END