;Frequency display and VFO stabiliser (c)1993 - 2000 E.Skelton. ;Crystal freq. 4.000MHz ;I.F. offests. 7.79850 and 7.80150 for an I.F. of 7.8MHz LIST P=16F84 ;SET PIC TYPE FOR ASSEMBLER ; THE FOLLOWING LINE SETS THE CONFIGURATION WORD FUSES. I USE ; THE GPASM ASSEMBLER FOR LINUX. IT SHOULD ALSO WORK WITH MPASM. ; IF YOUR ASSEMBLER DOESN'T SUPPORT __CONFIG, DELETE THE NEXT ; LINE. __CONFIG 0x3FF9 ;XT, NO WDT, PWR-UP, NO CP HI_ERR EQU 0x05 LOK_FLG EQU 0x06 CARRY EQU 0x00 STATUS EQU 0x03 Z EQU 0x02 RA EQU 0x05 RB EQU 0x06 RTCC EQU 0x01 PC EQU 0x02 FSR EQU 0x04 W EQU 0x00 F EQU 0x01 PS0 EQU 0x00 PS1 EQU 0x01 PS2 EQU 0x02 PSA EQU 0x03 RTE EQU 0x04 RTS EQU 0x05 INTEDG EQU 0x06 RBPU EQU 0x07 ;********* USER DEF'S ********** GATE EQU 0x03 ;COUNTER GATE UP_CNT EQU 0x02 ;CLOCK UP 1 (ALSO ACTS AS SECOND GATE) RESET EQU 0x01 ;COUNTER RESET HUFF EQU 0x01 PUFF EQU 0x00 RS EQU 0x03 ENA EQU 0x02 UP_DWN EQU 0x04 SBS EQU 0x05 BUTTON EQU 0x06 UDC EQU 0x10 LST_DIG EQU 0x11 ERR_LEV EQU 0x12 L EQU 0x13 M EQU 0x14 H EQU 0x15 COUNT EQU 0x16 TEMP EQU 0x17 COUNT1 EQU 0x18 COUNT2 EQU 0x19 COUNT3 EQU 0x1A COUNT4 EQU 0x1B CHR EQU 0x1C CNT1_L EQU 0x1D CNT1_M EQU 0x1E CNT1_H EQU 0x1F H_BYTE EQU 0x20 M_BYTE EQU 0x21 L_BYTE EQU 0x23 R0 EQU 0x24 R1 EQU 0x25 R2 EQU 0x26 R3 EQU 0x27 COUNT5 EQU 0x28 FLAGS EQU 0x29 ORG 0x00 GOTO START ;******** DELAY LOOP ******** ;** WATCH OUT FOR CALL TO MS100 DECI MOVWF COUNT4 ;DELAY 100MS X CONTENTS (W) NXT6 CALL MS100 DECFSZ COUNT4,1 GOTO NXT6 RETLW 0 ;***************************** ;******** DELAY LOOP 100MS *********** MS100 MOVLW 0x2D ;100 MS DELAY LOOP MOVWF COUNT1 ;EXACT TIMING .1 SEC L1 MOVLW 0x0C ;INCLUDING CALL AND RETURN MOVWF COUNT2 ;4 MHZ XTAL L2 MOVLW 0X3C MOVWF COUNT3 L3 DECFSZ COUNT3,1 GOTO L3 DECFSZ COUNT2,1 GOTO L2 DECFSZ COUNT1,1 GOTO L1 MOVLW 0x96 MOVWF COUNT1 LP99 DECFSZ COUNT1,1 GOTO LP99 NOP NOP RETLW 0 ;**************************************** ;******** DELAY LOOP 200 MICRO SEC. ************* DELAY MOVLW 0x42 ;DELAY LOOP 200 MICROSEC MOVWF COUNT1 NXT5 DECFSZ COUNT1,1 GOTO NXT5 RETLW 0 ;************************************************* ;*********** DELAY LOOP 2MS *********************** MS2 MOVLW 0x0A ;DELAY 2MS MOVWF COUNT1 LP15 MOVLW 0x42 MOVWF COUNT2 LP16 DECFSZ COUNT2,1 GOTO LP16 DECFSZ COUNT1,1 GOTO LP15 RETLW 0 ;************************************************** ;******* CONVERT 24 BIT BIN TO PACKED BCD ********** B2_BCD BCF STATUS,CARRY MOVLW 0x18 MOVWF COUNT CLRF R0 CLRF R1 CLRF R2 CLRF R3 LOOP16 RLF L_BYTE,F RLF M_BYTE,F RLF H_BYTE,F RLF R0,F RLF R1,F RLF R2,F RLF R3,F DECFSZ COUNT,1 GOTO ADJDEC RETLW 0 ADJDEC MOVLW R3 MOVWF FSR CALL ADJBCD MOVLW R2 MOVWF FSR CALL ADJBCD MOVLW R1 MOVWF FSR CALL ADJBCD MOVLW R0 MOVWF FSR CALL ADJBCD GOTO LOOP16 ADJBCD MOVLW 0x03 ADDWF 0,W MOVWF TEMP BTFSC TEMP,3 MOVWF 0 MOVLW 0x30 ADDWF 0,W MOVWF TEMP BTFSC TEMP,7 MOVWF 0 RETLW 0 ;**************************************** ;*********** INITIALISE LCD MODULE 4 BIT MODE *********************** LCDINIT CALL MS100 ;WAIT FOR LCD MODULE HARDWARE RESET BCF RA,RS ;REGISTER SELECT LOW BCF RA,ENA ;ENABLE LINE LOW MOVLW 0x03 MOVWF RB ;8 BIT MODE BSF RA,ENA ;ENA HIGH NOP ;MORE THAN 470 NS BCF RA,ENA ;ENA LOW CALL MS100 ;WAIT FOR DISPLAY TO CATCH UP MOVLW 0x03 MOVWF RB ;8 BIT MODE BSF RA,ENA ;ENA HIGH NOP ;MORE THAN 470 NS BCF RA,ENA ;ENA LOW CALL DELAY ;WAIT FOR DISPLAY TO CATCH UP MOVLW 0x03 MOVWF RB ;8 BIT MODE BSF RA,ENA ;ENA HIGH NOP ;MORE THAN 470 NS BCF RA,ENA ;ENA LOW CALL DELAY ;WAIT FOR DISPLAY TO CATCH UP MOVLW 0x02 MOVWF RB ;4 BIT MODE BSF RA,ENA ;ENA HIGH NOP ;MORE THAN 470 NS BCF RA,ENA ;ENA LOW CALL DELAY ;WAIT FOR DISPLAY MOVLW 0x0C ;DISPLAY ON CALL STROBE CALL DELAY MOVLW 0x06 ;ENTRY MODE SET CALL STROBE CALL DELAY MOVLW 0x01 ;CLEAR DISPLAY CALL STROBE CALL MS2 RETLW 0 ;********************************************************** ;******* STROBE/DATS ****************** ; SENDS DATA TO LCD DISPLAY MODULE (4 BIT MODE) STROBE BCF RA,RS ;SELECT COMMAND REGISTER GOTO CM DATS BSF RA,RS ;SELECT DATA REGISTER CM MOVWF CHR ;STORE CHAR TO DISPLAY SWAPF CHR,0 ;SWAP UPPER AND LOWER NIBBLES (4 BIT MODE) ANDLW 0x0F ;MASK OFF UPPER 4 BITS MOVWF RB ;SEND DATA TO DISPLAY BSF RA,ENA ;ENA HIGH NOP BCF RA,ENA ;ENA LOW MOVLW 0x42 ;DELAY LOOP MOVWF COUNT1 DL3 DECFSZ COUNT1,1 GOTO DL3 MOVF CHR,0 ;GET CHAR AGAIN ANDLW 0x0F ;MASK OFF UPPER 4 BITS MOVWF RB ;SEND DATA TO DISPLAY BSF RA,ENA ;ENA HIGH NOP BCF RA,ENA ;ENA LOW MOVLW 0x42 ;DELAY LOOP MOVWF COUNT1 DL4 DECFSZ COUNT1,1 GOTO DL4 RETLW 0 ;******************************************************************** ;************ MOVE TO START OF LINE 2 ***************** LINE2 MOVLW 0xC0 ;ADDRESS FOR SECOND LINE OF DISPLAY CALL STROBE CALL DELAY RETLW 0 ;****************************************************** ;************ CLEAR DISPLAY *************************** CLEAR MOVLW 0x01 ;COMMAND TO CLEAR DISPLAY CALL STROBE CALL MS2 ;LONGER DELAY NEEDED WHEN CLEARING DISPLAY RETLW 0 ;****************************************************** ;*********** MOVE TO HOME ***************************** HOME MOVLW 0x02 ;COMMAND TO HOME DISPLAY CALL STROBE CALL MS2 RETLW 0 ;****************************************************** ;********* MAIN PROG ************ ;INITIALISE PORTS START BSF 3,5 ;SWITCH TO F REGISTER PAGE 1 MOVLW 0x10 MOVWF RA ;RA 0 TO 3 OUTPUTS, RA 4 INPUT MOVLW 0xF0 ;RB 4 TO 7 INPUTS MOVWF RB MOVLW 0xA7 MOVWF 0X01 ;PRESCALER /256, RB PULL UP DIS. BCF 3,5 ;SWITCH TO F REGISTER PAGE 0 CLRF RA CLRF RB BSF RA,HUFF ;HUFF LINE HIGH BCF RA,PUFF ;PUFF LINE LOW ;SETS OUTPUT AT ABOUT 2.5VDC BCF FLAGS,LOK_FLG ;LOOP IS NOT LOCKED CALL LCDINIT ;INITIALIZE LCD MODULE MOVLW 'P' CALL DATS MOVLW 'H' CALL DATS MOVLW 'P' CALL DATS MOVLW '1' CALL DATS MOVLW ' ' CALL DATS MOVLW 'E' CALL DATS MOVLW 'I' CALL DATS MOVLW '9' CALL DATS CALL LINE2 MOVLW 'G' CALL DATS MOVLW 'Q' CALL DATS MOVLW ' ' CALL DATS MOVLW 'V' CALL DATS MOVLW '3' CALL DATS MOVLW '.' CALL DATS MOVLW '8' CALL DATS MOVLW 0x28 ;Delay for 4 sec. CALL DECI CALL CLEAR CALL LINE2 ;WRITE "Mhz" AT START OF LINE 2 MOVLW ' ' CALL DATS MOVLW 'M' CALL DATS MOVLW 'H' CALL DATS MOVLW 'z' CALL DATS MOVLW ' ' CALL DATS MOVLW 0x04 MOVWF UDC ;UPDATE DISPLAY EVERY 4 COUNTS CNT_AGN CLRF RB ;CLOSE BOTH GATES, RESET LOW CLRF M_BYTE ;RESET LOW AND MID BYTE COUNT REGISTERS CLRF L_BYTE BSF RB,RESET ;RESET EXTERNAL COUNTER (393) NOP BCF RB,RESET CLRF RTCC ;RESET INTERNAL COUNT (INCLUDING PRESCALER) BSF RB,UP_CNT BSF RB,GATE ;OPEN GATE'S CALL MS100 ;100MS DELAY BCF RB,GATE ;CLOSE GATE(COUNT COMPLETE) BCF RB,UP_CNT MOVF RTCC,W ;GET HIGH BYTE MOVWF H_BYTE ;STORE HIGH BYTE BSF 3,5 ;SWITCH TO F REGISTER PAGE 1 MOVLW 0x70 MOVWF RB ;MAKE RB,7 AN OUTPUT BCF 3,5 ;SWITCH TO F REGISTER PAGE 0 MOVF H_BYTE,W MOVWF TEMP CLK_AGN MOVF TEMP,W XORWF RTCC,W BTFSC STATUS,Z GOTO UP_1 NOP NOP BCF STATUS,CARRY MOVLW 0xFF MOVWF TEMP MOVF M_BYTE,W SUBWF TEMP,W MOVWF M_BYTE GOTO M_DONE UP_1 BSF RB,7 ;CLOCK INTERNAL PRESCALER UP 1 NOP BCF RB,7 INCF M_BYTE,1 GOTO CLK_AGN M_DONE BSF 3,5 ;SWITCH TO F REGISTER PAGE 1 MOVLW 0xF0 MOVWF RB ;MAKE RB,7 AN INPUT AGAIN BCF 3,5 ;SWITCH TO F REGISTER PAGE 0 NY BTFSS RB,7 GOTO UP_IT CLK1 BTFSC RB,7 GOTO UP_MOR NOP NOP BCF STATUS,CARRY MOVLW 0xFF MOVWF TEMP MOVF L_BYTE,W SUBWF TEMP,W MOVWF L_BYTE INCF L_BYTE,F ;!!!!!!!!!!!!!! BTFSC STATUS,CARRY INCF M_BYTE,F GOTO CONVERT UP_MOR INCF L_BYTE,1 BSF RB,UP_CNT NOP BCF RB,UP_CNT GOTO CLK1 UP_IT INCF L_BYTE,1 BSF RB,UP_CNT NOP BCF RB,UP_CNT GOTO NY ;The IF addition/subtraction begins here. CONVERT BTFSS RB,UP_DWN ;TEST UP_DWN INPUT GOTO SUB_IF BTFSC RB,SBS ;TEST USB/LSB INPUT GOTO ADD_HI MOVLW 0x4A ;Add IF 7.79850MHz ADDWF L_BYTE,F BTFSC STATUS,CARRY ;0BE64A HEX = 779850 Dec. INCF M_BYTE,F MOVLW 0xE6 ADDWF M_BYTE,F BTFSC STATUS,CARRY INCF H_BYTE,F MOVLW 0x0B ADDWF H_BYTE,F GOTO O_DONE ADD_HI MOVLW 0x76 ;Add IF 7.80150MHz ADDWF L_BYTE,F BTFSC STATUS,CARRY ;0BE776 HEX = 780150 Dec. INCF M_BYTE,F MOVLW 0xE7 ADDWF M_BYTE,F BTFSC STATUS,CARRY INCF H_BYTE,F MOVLW 0x0B ADDWF H_BYTE,F GOTO O_DONE ;The IF is subtracted by adding the compliment of the IF. SUB_IF BTFSC RB,SBS ;TEST SIDEBAND SELECT SWITCH GOTO SUB_HI MOVLW 0xB6 ;Subtract IF by adding -IF ADDWF L_BYTE,F BTFSC STATUS,CARRY ;-779850 Dec = F419B6 HEX INCF M_BYTE,F MOVLW 0x19 ADDWF M_BYTE,F BTFSC STATUS,CARRY INCF H_BYTE,F MOVLW 0xF4 ADDWF H_BYTE,F GOTO O_DONE SUB_HI MOVLW 0x8A ;Subtract IF by adding -IF ADDWF L_BYTE,F BTFSC STATUS,CARRY ;-780150 Dec = F4188A HEX INCF M_BYTE,F MOVLW 0x18 ADDWF M_BYTE,F BTFSC STATUS,CARRY INCF H_BYTE,F MOVLW 0xF4 ADDWF H_BYTE,F O_DONE MOVF L_BYTE,W ;STORE CURRENT COUNT MOVWF CNT1_L MOVF M_BYTE,W MOVWF CNT1_M MOVF H_BYTE,W MOVWF CNT1_H BTFSS FLAGS,LOK_FLG GOTO LOK_TST BTFSS RB,BUTTON ;IS LOCK/UNLOCK BUTTON PRESSED GOTO UNLOCK ;YES, UNLOCK LOOP. DUNIT MOVF L,W SUBWF CNT1_L,F BTFSS STATUS,CARRY DECF CNT1_M,F MOVF M,W SUBWF CNT1_M,F BTFSS STATUS,CARRY DECF CNT1_H,F MOVF H,W SUBWF CNT1_H,F BTFSS STATUS,CARRY GOTO PULSE_H MOVLW '<' MOVWF TEMP BCF RA,PUFF ;OUTPUT LOW PULSE TO INTEGRATOR MOVF CNT1_L,W ;GET ERROR LEVEL MOVWF ERR_LEV GOTO PULSE_T PULSE_H MOVLW '>' MOVWF TEMP BSF RA,HUFF ;OUTPUT HIGH PULSE TO INTEGRATOR MOVF CNT1_L,W ;GET ERROR LEVEL MOVWF ERR_LEV ;REMEMBER ERR_LEV IS NOW A NEG. VALUE COMF ERR_LEV,F ;NEG ERR_LEV ; INCF ERR_LEV,F GOTO PULSE_T LOK_TST BTFSS RB,BUTTON GOTO SETUP GOTO DONE ;******* SET UP LOOP LOCK FREQ AND LOCK FLAG ********** SETUP BSF FLAGS,LOK_FLG ;SET LOCKED FLAG MOVF CNT1_L,W ;SAVE CURRENT COUNT TO BE - MOVWF L ;COMPARED TO LATER COUNTS MOVF CNT1_M,W MOVWF M MOVF CNT1_H,W MOVWF H CALL MS100 ;EXTRA DELAY FOR BUTTON DEBOUNCE BCF RA,HUFF ;HUFF LOW , PUFF HIGH - BSF RA,PUFF ;LET OUTPUT FLOAT GOTO DUNIT ;SETUP COMPLETE ;******************************************************** ;****** UNLOCK LOOP ******* UNLOCK BCF FLAGS,LOK_FLG ;CLEAR LOCK FLAG (3,6) BSF RA,HUFF ;SET OUTPUT AT 2.5VDC BCF RA,PUFF CALL LINE2 MOVLW ' ' CALL DATS MOVLW 'M' CALL DATS MOVLW 'h' CALL DATS MOVLW 'z' CALL DATS MOVLW ' ' CALL DATS MOVLW ' ' CALL DATS MOVLW ' ' CALL DATS CALL MS100 ;EXTRA DELAY FOR BUTTON DEBOUNCE GOTO DONE ;************************** EXTRA CALL MS2 DECFSZ COUNT3,F GOTO EXTRA GOTO NO_MORE PULSE_T CALL MS2 ;DELAY FOR 2MS MOVF ERR_LEV,W MOVWF COUNT3 INCF COUNT3,F DECFSZ COUNT3,F GOTO EXTRA NO_MORE BCF RA,HUFF BSF RA,PUFF ;FLOAT OUTPUT AGAIN CALL LINE2 MOVLW ' ' CALL DATS MOVF LST_DIG,W CALL DATS MOVLW ' ' CALL DATS MOVLW 'E' CALL DATS MOVLW 0x0A SUBWF ERR_LEV,W BTFSS STATUS,CARRY GOTO EC MOVLW 0x09 MOVWF ERR_LEV EC MOVLW 0x30 ;CONVERT ERROR LEVEL TO ASCII ADDWF ERR_LEV,W CALL DATS MOVLW ' ' CALL DATS MOVF TEMP,W CALL DATS MOVF ERR_LEV,F BTFSC STATUS,Z ;IS THE ERROR LEVEL = 0 ? GOTO FMW MOVLW 0x05 MOVWF COUNT5 GOTO DONE FMW DECFSZ COUNT5,F GOTO DONE INCF COUNT5,F GOTO CNT_AGN DONE DECFSZ UDC,F GOTO CNT_AGN ;DON'T UPDATE DISPLAY MOVLW 0x02 MOVWF UDC ;UPDATE DISPLAY EVERY 2 COUNTS CALL B2_BCD ;CONVERT COUNT TO BCD CALL HOME ;HOME DISPLAY MOVLW 0x30 MOVWF TEMP ;AMOUNT TO ADD TO CONVERT TO ASCII MOVF R3,0 ;GET FIRST BCD DIGIT ANDLW 0x0F ;MASK OFF OTHER PACKED BCD DIGIT BTFSS STATUS,Z ;IS IT A '0' ? GOTO NO_BLNK MOVLW 0x20 ;YES PRINT A BLANK SPACE CALL DATS GOTO NXT_DIG NO_BLNK ADDWF TEMP,W CALL DATS NXT_DIG SWAPF R2,0 ;GET NEXT DIGIT ANDLW 0x0F ;MASK OFF OTHER PACKED BCD DIGIT ADDWF TEMP,W CALL DATS ;DISPLAY IT MOVLW '.' CALL DATS MOVF R2,0 ;GET OTHER BCD DIGIT ANDLW 0x0F ;MASK OFF OTHER PACKED BCD DIGIT ADDWF TEMP,W CALL DATS SWAPF R1,0 ;GET NEXT DIGIT ANDLW 0x0F ;MASK OFF OTHER PACKED BCD DIGIT ADDWF TEMP,W CALL DATS ;DISPLAY IT MOVF R1,0 ;GET OTHER BCD DIGIT ANDLW 0x0F ADDWF TEMP,W CALL DATS SWAPF R0,0 ;GET NEXT DIGIT ANDLW 0x0F ;MASK OFF OTHER PACKED BCD DIGIT ADDWF TEMP,W CALL DATS ;DISPLAY IT MOVF R0,0 ;GET OTHER BCD DIGIT ANDLW 0x0F ADDWF TEMP,W MOVWF LST_DIG CALL HOME GOTO CNT_AGN ;ALL DONE , START AGAIN END