;Frequency display and VFO stabiliser (c)1993 - 2000 E.Skelton. ;Crystal freq. 4.000MHz ;I.F. offsets. 8.99850 and 9.00150 for an I.F. of 9.0 MHz List P=16F628, F=INHX8M #Include ; REGISTER ADDRESSES CARRY EQU 0x00 STATUS EQU 0x03 Z EQU 0x02 PORTA EQU 0x05 PORTB EQU 0x06 RTCC EQU 0x01 PC EQU 0x02 FSR EQU 0x04 W EQU 0x00 F EQU 0x01 ; PORTA PIN ASSIGNMENTS PUFF EQU 0x00 HUFF EQU 0x01 ENA EQU 0x02 ; LCD ENABLE LINE RS EQU 0x03 ; LCD RS LINE ; PORTB PIN ASSIGNMENTS RESET EQU 0x01 ;COUNTER RESET UP_CNT EQU 0x02 ;CLOCK UP 1 (ALSO ACTS AS SECOND GATE) GATE EQU 0x03 ;COUNTER GATE UP_DWN EQU 0x04 SBS EQU 0x05 BUTTON EQU 0x06 ; USER DEFINED FLAG BITS HI_ERR EQU 0x05 LOK_FLG EQU 0x06 ;========================================================================== ; ; Configuration Bits ; ;========================================================================== _BODEN_ON EQU H'3FFF' _BODEN_OFF EQU H'3FBF' _CP_ALL EQU H'03FF' _CP_75 EQU H'17FF' _CP_50 EQU H'2BFF' _CP_OFF EQU H'3FFF' _PWRTE_OFF EQU H'3FFF' _PWRTE_ON EQU H'3FF7' _WDT_ON EQU H'3FFF' _WDT_OFF EQU H'3FFB' _LVP_ON EQU H'3FFF' _LVP_OFF EQU H'3F7F' _MCLRE_ON EQU H'3FFF' _MCLRE_OFF EQU H'3FDF' _ER_OSC_CLKOUT EQU H'3FFF' _ER_OSC_NOCLKOUT EQU H'3FFE' _INTRC_OSC_CLKOUT EQU H'3FFD' _INTRC_OSC_NOCLKOUT EQU H'3FFC' _EXTCLK_OSC EQU H'3FEF' _LP_OSC EQU H'3FEC' _XT_OSC EQU H'3FED' _HS_OSC EQU H'3FEE' ; CONFIG WORD __config (_CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _HS_OSC) ;========================================================================== ;********* USER DEF'S ********** CBLOCK 0x20 ; Start Data Block UDC ; LST_DIG ; ERR_LEV ; L ; M ; H ; COUNT ; TEMP ; COUNT1 ; COUNT2 ; COUNT3 ; COUNT4 ; CHR ; CNT1_L ; CNT1_M ; CNT1_H ; H_BYTE ; M_BYTE ; L_BYTE ; R0 ; R1 ; R2 ; R3 ; COUNT5 ; FLAGS ; ENDC ; End of Data Block ;========================================================================================== ; ; MACRO AREA ; ;========================================================================================== ; Bank Select Macros to simplify bank changes BANK0 MACRO bcf STATUS,RP0 ; Select Bank 0 bcf STATUS,RP1 ; ENDM BANK1 MACRO bsf STATUS,RP0 ; Select Bank 1 bcf STATUS,RP1 ; ENDM BANK2 MACRO bcf STATUS,RP0 ; Select Bank 2 bsf STATUS,RP1 ; ENDM BANK3 MACRO bsf STATUS,RP0 ; Select Bank 3 bsf STATUS,RP1 ; ENDM ;========================================================================================== ; ; RESET ENTRY ; ;========================================================================================== ORG 0x000 ; processor reset vector clrf PCLATH ; ensure page bits are cleared goto START ; go to beginning of program ;========================================================================================== ; ; SUB ROUTINES ; ;========================================================================================== ;******** 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 PORTA,RS ;REGISTER SELECT LOW BCF PORTA,ENA ;ENABLE LINE LOW MOVLW 0x03 MOVWF PORTB ;8 BIT MODE BSF PORTA,ENA ;ENA HIGH NOP ;MORE THAN 470 NS BCF PORTA,ENA ;ENA LOW CALL MS100 ;WAIT FOR DISPLAY TO CATCH UP MOVLW 0x03 MOVWF PORTB ;8 BIT MODE BSF PORTA,ENA ;ENA HIGH NOP ;MORE THAN 470 NS BCF PORTA,ENA ;ENA LOW CALL DELAY ;WAIT FOR DISPLAY TO CATCH UP MOVLW 0x03 MOVWF PORTB ;8 BIT MODE BSF PORTA,ENA ;ENA HIGH NOP ;MORE THAN 470 NS BCF PORTA,ENA ;ENA LOW CALL DELAY ;WAIT FOR DISPLAY TO CATCH UP MOVLW 0x02 MOVWF PORTB ;4 BIT MODE BSF PORTA,ENA ;ENA HIGH NOP ;MORE THAN 470 NS BCF PORTA,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 PORTA,RS ;SELECT COMMAND REGISTER GOTO CM DATS BSF PORTA,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 PORTB ;SEND DATA TO DISPLAY BSF PORTA,ENA ;ENA HIGH NOP BCF PORTA,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 PORTB ;SEND DATA TO DISPLAY BSF PORTA,ENA ;ENA HIGH NOP BCF PORTA,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 BANK1 ; SWITCH TO PAGE 1 MOVLW 0x10 MOVWF PORTA ;PORTA 0 TO 3 OUTPUTS, PORTA 4 INPUT MOVLW 0xF0 ;PORTB 4 TO 7 INPUTS MOVWF PORTB MOVLW 0xA7 MOVWF 0X01 ;PRESCALER /256, PORTB PULL UP DIS. BANK0 ;SWITCH TO F REGISTER PAGE 0 CLRF PORTA CLRF PORTB movlw 0x07 ; Turn OFF Comparators movwf CMCON BSF PORTA,HUFF ;HUFF LINE HIGH BCF PORTA,PUFF ;PUFF LINE LOW ;SETS OUTPUT AT ABOUT 2.5VDC BCF FLAGS,LOK_FLG ;LOOP IS NOT LOCKED CALL LCDINIT ;INITIALIZE LCD MODULE MOVLW 'W' CALL DATS MOVLW '6' CALL DATS MOVLW 'J' CALL DATS MOVLW 'F' CALL DATS MOVLW 'R' CALL DATS MOVLW ' ' CALL DATS MOVLW '2' CALL DATS MOVLW '0' CALL DATS MOVLW ' ' CALL DATS CALL LINE2 MOVLW 'S' CALL DATS MOVLW 'S' CALL DATS MOVLW 'B' CALL DATS MOVLW ' ' CALL DATS MOVLW 'X' CALL DATS MOVLW 'C' CALL DATS MOVLW 'V' CALL DATS MOVLW 'R' 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 PORTB ;CLOSE BOTH GATES, RESET LOW CLRF M_BYTE ;RESET LOW AND MID BYTE COUNT REGISTERS CLRF L_BYTE BSF PORTB,RESET ;RESET EXTERNAL COUNTER (393) NOP BCF PORTB,RESET CLRF RTCC ;RESET INTERNAL COUNT (INCLUDING PRESCALER) BSF PORTB,UP_CNT BSF PORTB,GATE ;OPEN GATE'S CALL MS100 ;100MS DELAY BCF PORTB,GATE ;CLOSE GATE(COUNT COMPLETE) BCF PORTB,UP_CNT MOVF RTCC,W ;GET HIGH BYTE MOVWF H_BYTE ;STORE HIGH BYTE BANK1 ;SWITCH TO F REGISTER PAGE 1 MOVLW 0x70 MOVWF PORTB ;MAKE PORTB,7 AN OUTPUT BANK0 ;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 PORTB,7 ;CLOCK INTERNAL PRESCALER UP 1 NOP BCF PORTB,7 INCF M_BYTE,1 GOTO CLK_AGN M_DONE BANK1 ;SWITCH TO F REGISTER PAGE 1 MOVLW 0xF0 MOVWF PORTB ;MAKE PORTB,7 AN INPUT AGAIN BANK0 ;SWITCH TO F REGISTER PAGE 0 NY BTFSS PORTB,7 GOTO UP_IT CLK1 BTFSC PORTB,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 PORTB,UP_CNT NOP BCF PORTB,UP_CNT GOTO CLK1 UP_IT INCF L_BYTE,1 BSF PORTB,UP_CNT NOP BCF PORTB,UP_CNT GOTO NY ;The IF addition/subtPORTAction begins here. CONVERT BTFSS PORTB,UP_DWN ;TEST UP_DWN INPUT GOTO SUB_IF BTFSC PORTB,SBS ;TEST USB/LSB INPUT GOTO ADD_HI MOVLW 0x0A ;Add IF 8.99850 ADDWF L_BYTE,F BTFSC STATUS,CARRY ;0DBB0A HEX = 899850 Dec. INCF M_BYTE,F MOVLW 0xBB ADDWF M_BYTE,F BTFSC STATUS,CARRY INCF H_BYTE,F MOVLW 0x0D ADDWF H_BYTE,F GOTO O_DONE ADD_HI MOVLW 0x36 ;Add IF 9.00150 ADDWF L_BYTE,F BTFSC STATUS,CARRY ;0DBC36 HEX = 900150 Dec. INCF M_BYTE,F MOVLW 0xBC ADDWF M_BYTE,F BTFSC STATUS,CARRY INCF H_BYTE,F MOVLW 0x0D ADDWF H_BYTE,F GOTO O_DONE ;The IF is subtPORTActed by adding the compliment of the IF. SUB_IF BTFSC PORTB,SBS ;TEST SIDEBAND SELECT SWITCH GOTO SUB_HI MOVLW 0xF6 ;SubtPORTAct IF by adding -IF ADDWF L_BYTE,F BTFSC STATUS,CARRY ;-899850 Dec = F244F6 HEX INCF M_BYTE,F MOVLW 0x44 ADDWF M_BYTE,F BTFSC STATUS,CARRY INCF H_BYTE,F MOVLW 0xF2 ADDWF H_BYTE,F GOTO O_DONE SUB_HI MOVLW 0xCA ;SubtPORTAct IF by adding -IF ADDWF L_BYTE,F BTFSC STATUS,CARRY ;-900150 Dec = F243CA HEX INCF M_BYTE,F MOVLW 0x43 ADDWF M_BYTE,F BTFSC STATUS,CARRY INCF H_BYTE,F MOVLW 0xF2 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 PORTB,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 PORTA,PUFF ;OUTPUT LOW PULSE TO INTEGPORTATOR MOVF CNT1_L,W ;GET ERROR LEVEL MOVWF ERR_LEV GOTO PULSE_T PULSE_H MOVLW '>' MOVWF TEMP BSF PORTA,HUFF ;OUTPUT HIGH PULSE TO INTEGPORTATOR 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 PORTB,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 ;EXTPORTA DELAY FOR BUTTON DEBOUNCE BCF PORTA,HUFF ;HUFF LOW , PUFF HIGH - BSF PORTA,PUFF ;LET OUTPUT FLOAT GOTO DUNIT ;SETUP COMPLETE ;******************************************************** ;****** UNLOCK LOOP ******* UNLOCK BCF FLAGS,LOK_FLG ;CLEAR LOCK FLAG (3,6) BSF PORTA,HUFF ;SET OUTPUT AT 2.5VDC BCF PORTA,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 ;EXTPORTA DELAY FOR BUTTON DEBOUNCE GOTO DONE ;************************** EXTPORTA CALL MS2 DECFSZ COUNT3,F GOTO EXTPORTA GOTO NO_MORE PULSE_T CALL MS2 ;DELAY FOR 2MS MOVF ERR_LEV,W MOVWF COUNT3 INCF COUNT3,F DECFSZ COUNT3,F GOTO EXTPORTA NO_MORE BCF PORTA,HUFF BSF PORTA,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