Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 14

;-------------------- Original Version ------------------------

;Frequency display and VFO stabiliser (c)1993 - 2002 E.Skelton.


;Version 4.0. 9 Dec. 2002
;Crystal freq. 4.000MHz
;I.F. offests. 7.79850 and 7.80150 for an I.F. of 7.8MHz
;--------------------------------------------------------------
;
;-------------------- Modified Version ------------------------
;Modified by YD1CHS on Jan. 2009
;Crystal freq. 4.000MHz
;I.F. Offsets. 9.99850 and 10.0015 for an I.F. of 10.0MHz
;Microcontroller Type is 16F84A (the original one is 16F84)
;--------------------------------------------------------------
;
; Changes: Modify the configuration word for the PIC16F84
; The last version was for the obsolete PIC16C84.
;
; Complete re-write of the IF offset code to fix a
; bug and to make it easier to modify for different
; VFO and IF frequencies. Search for label 'CONVERT'

LIST P=16F84A ;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 0x3FF1 ;XT, NO WDT, PWR-UP, NO CP

;*** use 0x3FF1 for the PIC16F84, 0x3FF9 for the PIC16C84

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
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
;******************************************************

;*********** MOVE TO SPECIFIK ADDRESS - MHz($0C) ******


; This function was added by YD1CHS on Feb 2009
;******************************************************
ADR_MHZ IORLW 0x8C ;COMMAND TO PLACE CURSOR at $0C
CALL STROBE ;Command for this is always $80
CALL MS2 ;higher than address
RETLW 0
;******************************************************
;***** MOVE TO SPECIFIK ADDRESS - FRQ($03) ************
; This function was added by YD1CHS on Feb 2009
;******************************************************
ADR_FRQ IORLW 0x83 ;COMMAND TO PLACE CURSOR at $04
CALL STROBE ;Command for this is always $80
CALL MS2 ;higher than address
RETLW 0
;******************************************************

;***** MOVE TO SPECIFIK ADDRESS - Error($48) **********


; This function was added by YD1CHS on Feb 2009
;******************************************************
ADR_ERR IORLW 0xCB ;COMMAND TO PLACE CURSOR at $4B
CALL STROBE ;Command for this is always $80
CALL MS2 ;higher than address
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 0xB7
MOVWF 0X01 ;PRESCALER /256, RB PULL UP DIS.
BCF 3,5 ;SWITCH TO F REGISTER PAGE 0
CLRF RA
CLRF RB

CALL LCDINIT ;INITIALIZE LCD MODULE

IORLW 0x86
CALL STROBE
CALL MS2

MOVLW 'V'
CALL DATS
MOVLW 'I'
CALL DATS
MOVLW 'V'
CALL DATS
MOVLW 'A'
CALL DATS

IORLW 0xC3
CALL STROBE
CALL MS2

MOVLW 'H'
CALL DATS
MOVLW 'O'
CALL DATS
MOVLW 'M'
CALL DATS
MOVLW 'E'
CALL DATS
MOVLW 'B'
CALL DATS
MOVLW 'R'
CALL DATS
MOVLW 'E'
CALL DATS
MOVLW 'W'
CALL DATS
MOVLW 'E'
CALL DATS
MOVLW 'R'
CALL DATS

MOVLW 0x14 ;Delay for 2 sec.


CALL DECI
CALL CLEAR

CALL HOME

MOVLW 'F'
CALL DATS
MOVLW '='
CALL DATS

CALL ADR_MHZ ;WRITE "Mhz" AT ADDRESS OF $0C -> Originally


using a 16x1 LCD, I use a 16x2 LCD
MOVLW ' '
CALL DATS
MOVLW 'M'
CALL DATS
MOVLW 'H'
CALL DATS
MOVLW 'z'
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 ;OK, NOW, WE HAVE H_BYTE:M_BYTE:L_BYTE
GOTO TST_FLG

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

; TESTING WHETHER VCO > IF OR VCO < IF ?

TST_FLG MOVLW 0XB0 ;STORE I.F. OFFSET IS 10.7 MHZ = 1053B0 HEX =
1070000 DEC
MOVWF COUNT1
MOVLW 0X53
MOVWF COUNT2
MOVLW 0X10
MOVWF COUNT3

MOVF L_BYTE,W ;SUB IF OFFSET WITH VCO FREQUENCY


SUBWF COUNT1,F ;COUNT1:COUNT2:COUNT3
;H_BYTE:M_BYTE:L_BYTE
;-------------------- -
;COUNT1:COUNT2:COUNT3
BTFSS STATUS,CARRY

DECF COUNT2,F

MOVF M_BYTE,W
SUBWF COUNT2,F

BTFSS STATUS,CARRY

DECF COUNT3,F
MOVF H_BYTE,W
SUBWF COUNT3,F

BTFSS STATUS,CARRY
GOTO SET_FLG
BSF FLAGS,LOK_FLG ;VCO < IF, (VICE VERSA VCO > IF -->
FLAGS,LOK_FLG = 0)
GOTO CONVERT

SET_FLG BCF FLAGS,LOK_FLG ;VCO > IF, (VICE VERSA VCO < IF -->
FLAGS,LOK_FLG = 1)

; The IF offset code starts here. The frequency in 10's of HZ


; is stored as 24 bits in registers L_BYTE, M_BYTE and H_BYTE. The IF
; offset is stored in COUNT1, COUNT2 and COUNT3. Note that
; the COUNT1,2,3 registers are also used by other parts of the
; program.
;
; Read the latest version of gadget.txt from:
; http://homepage.eircom.net/~ei9gq/gadget.txt
;

CONVERT BTFSS FLAGS,LOK_FLG ;TEST WHETER VCO > IF ? OR VCO < IF ?


GOTO SUB_IF ;VCO > IF

CALL LINE2 ;VCO < IF, DISPLAY "VCO < IF"


MOVLW 'V'
CALL DATS
MOVLW 'C'
CALL DATS
MOVLW 'O'
CALL DATS
MOVLW '<'
CALL DATS
MOVLW 'I'
CALL DATS
MOVLW 'F'
CALL DATS
MOVLW ' '
CALL DATS

MOVLW 'L' ;DISPLAY "LSB"


CALL DATS
MOVLW 'S'
CALL DATS
MOVLW 'B'
CALL DATS

MOVLW 0XB0 ;STORE I.F. OFFSET.


MOVWF COUNT1 ;10.7 MHZ = 1053B0 HEX = 1070000 DEC
MOVLW 0X53
MOVWF COUNT2
MOVLW 0X10
MOVWF COUNT3

MOVF L_BYTE,W ;SUB I.F. OFFSET WITH VCO FREQUENCY


SUBWF COUNT1,W ;COUNT1:COUNT2:COUNT3
MOVWF L_BYTE ;H_BYTE:M_BYTE:L_BYTE
;-------------------- -
;H_BYTE:M_BYTE:L_BYTE

BTFSS STATUS,CARRY

DECF COUNT2,F

MOVF M_BYTE,W
SUBWF COUNT2,W
MOVWF M_BYTE

BTFSS STATUS,CARRY

DECF COUNT3,F

MOVF H_BYTE,W
SUBWF COUNT3,W
MOVWF H_BYTE

GOTO DONE

;VCO > IF --> The IF is subtracted by adding the (2's) compliment of the IF.

SUB_IF CALL LINE2


MOVLW 'V'
CALL DATS
MOVLW 'C'
CALL DATS
MOVLW 'O'
CALL DATS
MOVLW '>'
CALL DATS
MOVLW 'I'
CALL DATS
MOVLW 'F'
CALL DATS
MOVLW ' '
CALL DATS

MOVLW 'U' ;DISPLAY "USB"


CALL DATS
MOVLW 'S'
CALL DATS
MOVLW 'B'
CALL DATS

MOVLW 0X50 ;STORE I.F. OFFSET.


MOVWF COUNT1 ;-10.7 MHZ = EFAC50 HEX = -1070000 DEC
MOVLW 0XAC
MOVWF COUNT2
MOVLW 0XEF
MOVWF COUNT3

MOVF COUNT1,W ;ADD I.F.(2'S COMP) WITH VCO FREQUENCY


ADDWF L_BYTE,F
MOVF COUNT2,W
BTFSC STATUS,CARRY
INCFSZ COUNT2,W
ADDWF M_BYTE,F
MOVF COUNT3,W
BTFSC STATUS,CARRY
INCFSZ COUNT3,W
ADDWF H_BYTE,F

;------ CALCULATION COMPLETE, NOW DISPLAY FREQ -------

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 ADR_FRQ

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
MOVLW ' ' ;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

MOVLW '.'
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 DATS ;DISPLAY IT

;------ EVERIYTHING IS DONE, REPEAT FROM BEGINNING AGAIN -----

GOTO CNT_AGN ;ALL DONE , START AGAIN

END

You might also like