Software for the
Modularized
Spectrum Analyzer
This
page is a Description of the Software Code that controls the
Spectrum
Analyzers.
I have
previously written
several Liberty Basic software routines to control the different
versions of the
Spectrum Analyzer. I have now combined them all, into one version
that
will operate any of my Spectrum Analyzer designs (SSAProto, SSABoard,
and MSA). On this page, I will try to describe
the the program. But, since there
are over 2000 lines of code, I will not describe the action of each
code line. If you want to know what a specific line of code does,
e-mail me. I will be happy to respond. wsprowls@yahoo.com
Page
Started Nov. 30,
2004 and is in progress. Use
your browser's "Refresh" for latest info.
Updated
Mar 15, 2006, change software to
revision 107, added a 16
bit A to D serial process
Updated
June 24, 2006, change software to
revision 108 and update this page.
If you came to this page from a Link, return by using your
browser's Back button, or click the following:
Go Back to the Modularized Spectrum
Analyzer Main Page
This is a fairly long
page. Use the following buttons to navigate to the sections of
interest:
What computer is needed to
operate the Spectrum Analyzers?
What software is needed?
How to download the Spectrum Analyzer
Software
Describe what the software is
doing.
How to Operate and Calibrate the Spectrum
Analyzer, this will take you to a different page
Computer Required to operate
the Spectrum Analyzer:
PC or Laptop Computer with LPT 1 standard parallel
port. Windows or OS/2.
Monitor can be any size, but must be set for a
minimum of 800 by 600 pixel resolution. More is fine.
I am using a Toshiba Satellite Laptop, 700 MHz
Celeron. return to top
Software Required to operate
the Spectrum Analyzer:
Liberty Basic 3.01 or more recent. I wrote the
program in this "Basic" code because I am not a software guru. I
was
famaliar only with HP Basic and Commodore Basic and this is very
similar. It is also very inexpensive. Go visit their web
site at www.libertybasic.com. They have a free version of Liberty
Basic 4.0, and although it is a trial version, it will operate the
Spectrum
Analyzer with this software.
If you can do the programming, you
can rewrite my code in some other software. If you look at the
code, a
description is annotated with the program lines. That should tell
you
what you want the program to do. The code is in text
format. Just copy and paste the code into your Liberty basic
.bas file, and it will run just fine. return to top
How to download the Spectrum
Analyzer Software?
Here is the
Liberty Basic Code spectrumanalyzer.bas
for
the
Modularized Spectrum Analyzer. This software code will also work
fine
for the SSA Prototype, SSA Board, and Modularized Spectrum
Analyzer. I am even changing previous
links
to use this software. I will continually update this software for
more
types of PLL's. The revision number will be on the first line of
code.
If I find an error or enhance the operating characteristics, I will
note
the revision as
102, 103, 104, etc. Any 10x version of software will work fine
with
the MSA, as designed. If I change the software to a revision that
will not work for the original MSA, SSAP, or
SSAB, I will not link to it on this page. I have no plans to do
that at the moment, but one day, I am
going to design a Control Board for USB interface that will require a
major revision.
If you are using Netscape, left clicking on the
above
link will open the code in a text format. To download the program
to your Liberty Basic folder, right click on the link and save as a
link target.
It you are using Explorer, clicking on the link will
open a request window for saving or opening. It will open as a
text document. It will save as a .bas file. Save it in your
Liberty Basic folder.
No matter how you save this code, keep the original
in a safe spot and copy it with a different name. Use the copied
version when opening and changing the global variables, for the first
time. If you happen to mess up, you will have the original
version to start over.
This software is quite lengthly, due to the
subroutines that handle
the various PLL types and other informational remarks. Any lines that begin with
apostrophe are remarks and are not compiled. You can shorten the code by
deleting the
subroutines and remarks that are not needed, but I don't advise that,
unless you
become quite familiar with the Liberty Basic. The program will not run
any faster with the subroutines and remarks deleted, however, it will
compile a little faster.
When the Spectrum Analyzer's Program is opened
in
Liberty Basic, the Liberty Basic Code Window will open. The
Global Variables must be established by changing some of the code lines
at the beginning of the code. The SA's Program is started
when the RUN button in the Liberty Basic Code Window is clicked.
Upon running, two windows will
open, covering up the Code Window. They are the Spectrum Analyzer
Graph Window and Spectrum Analyzer Working Window. return to top
Software Descriptions
This program is
described here, with the
following assumptions:
1. The 2nd LO frequency (PLL 2) is a fixed frequency, locked to the
Master Oscillator. PLL 2 can be deleted and
substituted with an SRD Multiplier or similar multiplier, locked to the
Master Oscillator. If used, the PLL 2
will be used as an Integer-N PLL, even if it has Fractional-N
capability.
2. All
Final Xtal Filters, used within the same program, must be within the
bandwidth of the 1st IF Filter. For example, if the Spectrum
Analyzer's 1st IF Filter is a Cavity Filter with a bandwidth of 2 MHz,
then the total spread of the Final Xtal Filters can be no greater than
2 MHz. ie, final filters are 10.0 MHz, 10.6 MHz, 10.7 MHz, 11.15
MHz. Total spread is 11.15 - 10.0 = 1.15 MHz
3. PLL's 1, 2, and 3 are built
with LMX 2325, 2326, 2350, 2353's or the ADF 2112. All PLL's can
be the same, or
a
combination, thereof.
4. The Master
Clock must
be an integer multiple of the Phase Frequency of PLL 2.
For the LMX series PLLs, the integer multiple must be 3 or greater.
5. Optional PLL 3, Tracking Generator can use either a
Fractional-N
or Integer-N PLL. Fractional-N would be preferred, since the TG
could
be programmed in smaller increments, to be more compatible with odd
frequency Final Xtal Filters.
6. PLL 1 could be set up as a Fractional-N PLL, but, I don't
recommend it, due to excessive spurs.
7. The Log Detector can be either an LM3356, AD3806 or
AD3807.
8. The Analog to Digital conversion can use 8 bit or 12 bit
parallel, or 16 bit serial process.
Here are descriptions of the Software. Click on any
one to jump to the Block's individual Description. To keep this
page from being overly long, I will not show every line of code in the
program. There are over 2000 lines of code. I suggest you
open a seperate window for, or print out, the code to view, while
looking at the code descriptions. Get the code here. You can open and read the
code with any text reader program, such as Notepad.
There are 3 Main Blocks to this
software program. The Global
Variables, Main Routines, and Sub-Routines. The Global Variables are used throughout the
program. The program flow follows the Main
Routines. The Sub-Routines are called upon by the Main
Routines.
Global Variables,
and their functions:
This
is the beginning of the program, and it is where the user must define
the Global Variables that
are specific to his Spectrum Analyzer. Some
of the
variables are defaults. That is, they are starting values for the
Spectrum Analyzer Program and will be changed by software action
while the SA Program is running. Other variables, once
established, will never be changed. Here is a description of how
and where the
global variables are used in the program.
nomainwin
This just tells the program not to open a main window. This
program will open two windows, later in the code.
masterclock = 64
This is the frequency of the Master Clock, in MHz. Enter the
EXACT frequency of your Master Clock, up to 6 decimal places. If
you don't know it's frequency, enter what you think it should be (like,
what it is marked). If it is adjustable, enter the frequency you
know it will be after it is calibrated. You will be able to
calibrate it later, during the MSA calibration procedure. The
program uses this
to calculate the actual (and correct) frequency of the
Local Oscillator 1, Local Oscillator 2, and the optional Tracking
Generator.
cf = 0
This is the center frequency default, all frequencies in MHz., used to
determine the frequency at the center of the sweep. It will
be shown and can be changed in the "Center Freq" Box of the Working
Window.
sw = .02
This is the default sweep width, in MHz. The SA will sweep from
one half sw
below CF to one half above the CF (center
frequency). It will
be shown and can be changed in the Working Window's, "Sweep
Width" Box.
wat = 0
This is a whole number that is used later in the code, to slow down the
sweep speed. This is so that
the hardware will have time to settle before data is taken. This
is a default, and will
be shown and can be changed in the Working Window, "Wait"
Box.
sps = 400
Steps per sweep, default. This is the number of steps in each
sweep. Used to determine where in
the sweep the program is. Value can be changed in "Steps/Sweep"
Box, of Working Window. This number can be any whole number
between 1
and 720.
mkr1 = 100
This is the default step number, where the marker 1 will place
information in the Graph Window. It will be shown, and can
be changed in the "Place
Markers at Steps" Boxs. It can be a whole number from 0 to the
value that is in "sps".
If a marker is not wanted, the value of
the "mkr" can be changed to
a number higher than "sps".
For
example, entering "450"
will not allow a marker to be displayed.
mkr2 = 200
Marker 2 step placement, default. Same as above
mkr3 = 300
Marker 3 step placement, default. Same as above
finalfreq1 = 10.7
Normally, this is the center frequency (in MHz) of Final Xtal Filter #
1. This will be the final I.F. frequency that enters the Log.
Detector. This variable is used to determine the correct LO1
freq, and the Tracking Generator Frequency. There are provisions,
in the software, for 4 final filters. Each one can be selected in
the "Select Final Filter:" boxes of the Working Window. In
certain cases, the operator may want to change this global variable to
"offset" the final I.F. Just remember, whatever frequency is
placed into this global variable, that is what the final I.F. frequency
is going to be, no matter what the Final Xtal Filter #
1 frequency is.
The Final Xtal Filter and the final
I.F. can be any
frequency, within reason. It should not be less than about 8
MHz.
This is due to the characteristics of the cavity filter used for I.F
1. It will not reject the generated image frequencies if a Final
I.F.
is too low. Higher final I.F. frequencies are limited only by the
bandwidth of the final I.F. amplifiers and the Log Detector. When
using the AD83xx series of Log Detectors, a final I.F. of 21 MHz or 45
MHz is perfectly acceptable. I chose 10.7 MHz because there are
many
inexpensive off-the-shelf Monolithic Crystal Filters in this frequency
range.
finalbw1 = 2.0
This is the band width (in KHz) of Final Xtal Filter # 1. This is
not used in
calculations, only placed into the "Final I.F. Freq" Box, along
with the Final Freq value.
sagain1 = 0
This is the total gain (in dB) of MSA with Final Filter #1
installed. Used to
calibrate Graph Window. On initial set-up, use a value of
"0".
During MSA calibration, this value will be changed to
reflect the actual gain of the MSA circuitry. For
example, if the MSA has a gain of 37 dB from the input of the MSA to
the input of the Log Detector, the value "37" will be entered here.
finalfreq2 = 10.7
'freq of Final Xtal Filter # 2
finalbw2 = 10.0
'BW (in KHz)of Final Xtal Filter # 2
sagain2 = 0
'total gain of MSA with Final Filter #2 installed
finalfreq3 = 10.7
'freq of Final Xtal Filter # 3
finalbw3 = 30
'BW (in KHz)of Final Xtal Filter # 3
sagain3 = 0
'total gain of MSA with Final Filter #3 installed
finalfreq4 = 10.7
'freq of Final Xtal Filter # 4
finalbw4 = 200
'BW (in KHz)of Final Xtal Filter # 4
sagain4 = 0
'total gain of MSA with Final Filter #4 installed
These
are the values of the other 3 filters. If only one filter
is used, then enter the same values as entered for Filter 1. If
using
the I.F. 1 cavity filter I have designed, all 4 filters must be within
2 MHz of each other. This is because the bandwidth of the cavity
filter is 2 MHz.
appxDDS = 10.7
This is the center frequency of the DDS xtal
filter and the nominal DDS output frequency (Ref. for
PLL1). The program uses this value as an approximation when
calculating LO 1
frequency.
ddsfilbw = .015
This is the bandwidth of the DDS output filter. This
value is only used as an error check, when commanding the
DDS.
The DDS filter is chosen for minimum bandwidth, to
minimize DDS
spurious. But, it must be wide enough to allow for full
"steering" of
the PLL 1. The minimum bandwidth that can be used is derived from
the
formula: PLL1phasefreq
= (VCO 1 minimum frequency) x ddsfilbw/appxDDS.
rewritten : ddsfilbw =
PLL1phasefreq
x appxDDS / (VCO 1 minimum frequency) or
ddsfilbw = .972 MHz x 10.7 MHz / 1000 MHz = .0104 MHz. A 15
KHz BW filter satisfies this requirement, for the Integer-N PLL 1.
If Fractional-N PLL 1 is used, the following formual is used:
ddsfilbw = (
PLL1phasefreq/16)
x appxDDS / (VCO 1 minimum frequency).
Using the Fractional example: ddsfilbw
= (3.57 MHz/16) x 10.7 MHz / 1000 MHz = .002387 MHz.
Therefore, a 2.5
KHz BW (or wider) filter would work nicely for the Fractional-N PLL.
PLL1 = 2326
Enter the suffix of the PLL chip you are using in this position: (LMX)
2325, 2326, 2350, 2353, (ADF) 4112. The
program will use "if" statements using these
values to determine which PLL subroutine to use for commanding.
PLL1phasefreq
= .972
This is the Phase Detector
Frequency (PDF) you have designed for PLL 1, in MHz. It is also
the
step size for PLL 1 and determines the value of it's Rcounter.
"PLL1phasefreq" must be less than the following formula: PLL1phasefreq
= (VCO 1 minimum frequency) x ddsfilbw/appxDDS. The determining
factor is the DDS output frequency and it's narrow band filter.
Assume that the lowest frequency of the LO 1 will be 1000 MHz, the DDS
output frequency is 10.7 MHz, and the DDS filter has a band
width of 15 KHz. Formula: PLL1phasefreq = 1000
x .015 / 10.7 = 1.401869 (MHz) The number, 1.4 would give the
best phase noise characteristics for PLL 1, however, the LMX 2326 would
be given illegal codes to it's "Bcounter". The highest phase
frequency allowed for the LMX2326, without illegal codes, is 1.05
MHz. If 1.05 was selected as the phase frequency, the LMX 2326
must divide the reference frequency by 10.19. Since the reference
divider within the LMX2326 must be a whole number value, the divider
will be 11, since 10 would give too high a phase frequency.
Therefore, 10.7/11 = .9727 (MHz). This is the number to put into
the global variable, PLL1phasefreq.
PLL1mode = 0
This variable is the usage of PLL1: "1" = Fractional-N
Mode,
"0" =
Integer-N
Mode. The previous instruction, for setting up the global
variable "PLL1phasefreq", assumed that PLL 1 is operating
as an Integer-N phase locked loop. All of the PLLs mentioned (2325,
2326, 2350, 2353,4112) will operate as an Integer-N. Two of these
chips, LMX 2350 and 2353, can also be used as Fractional-N. The
advantage of a Fractional-N PLL is, a higher PLL phase detector
frequency (PDF) can be used, which results in an improvement in PLL
phase noise. The disadvantage is, Fractional-N counters
create significant spurs.
If the builder desires the use of the LMX 2350 or 2353 as
Fractional-N, then enter a "1" into the variable "PLL1mode", and use
the following instructions for the "PLL1phasefreq" global variable:
PLL1phasefreq = 3.57
(when PLL 1 is used as
Fractional-N)
This is the formula to determine the VCO frequency when using a
Fractional-N PLL :
VCO freq = [(B x P) + A + F/16 ] x PDF where:
VCO freq will range from 1000 MHz to 2000 MHz
P is the preselector and will be 16 for maximum PDF
B is the numerical Bcounter and can be from
A is the numerical Acounter
F is the fractional counter (0 to 15)
PDF is the phase detector frequency, the number we will obtain to
enter into the variable, "PLL1mode"
The chip has an Acounter, Bcounter relationship that must be
followed: The
Bcounter must equal to, or greater than (Acounter + 2).
Since the preselector is 16, then the Acounter can be as high as
15. This means the Bcounter can not be less than 17.
By using the above formula, we can solve for PDF:
PDF = VCO freq/ [(B x P) + A + F/16 ],
PDF = 1000 MHz/ [(17 x 16) + 0 + 0/16 ] = 3.676 MHz.
If the Reference frequency is 10.7 MHz, the Rcounter is Ref/PDF =
10.7/3.676 = 2.91
Of course, the Rcounter must be next whole number, 3. The
PDF will then be: Ref/Rcounter = 10.7/3 = 3.57 MHz. This
is the number to put into
the global variable, PLL1phasefreq.
PLL1loop = 1
For non-inverting loop filter, enter "2"; for inverting op
amp, enter
"1". This commands
the phase detector output in the PLL chip to
either, invert or not invert. It is not used in the LMX 2325 IC.
PLL2 = 2326
Again, enter the PLL suffix: 2325,
2326, 2350, 2353, 4112, or, 0
when using a multiplier scheme for LO 2. If "0"
is used, the program will not send a command for PLL 2.
appxLO2 = 1024
This is the 2nd LO frequency, nominally, 1024 (in MHz). This is
a coarse frequency used to determine the PLL2
commands. Even if PLL 2 is replaced by a multiplier scheme, enter
the frequency of LO
2 (in MHz).
PLL2phasefreq
= 4
This is the Phase Detector
Frequency (PDF) you have designed for PLL 2, in MHz. It is also
the
step size for PLL 2 and determines the value of it's Rcounter.
You can
use 8 Mhz, for better phase noise, but make sure the Loop Filter is
designed for it. If VCO2/PLL2 is less than 1024 MHz, the 4 or 8
MHz
will result in illeagle commands to PLL 2.
PLL2loop = 2
This tells the software if PLL2 is configured with a loop
filter that is inverting or non inverting. The published
schematics
for PLL2 have non inverting loop filters, enter "2". If an inverting op amp
is used in the loop filter, enter "1".
It is acceptable to use a VCO2 that has a reverse tuning
characteristic. This is the code to change, if that is the case.
PLL3 = 2326
Again, enter the PLL suffix of the PLL chip you
are using in the Tracking Generator: 2325, 2326,
2350, 2353,4112, or enter 0 (zero) for no Tracking
Generator.
PLL3off
= 970
Output frequency (in MHz) of PLL3/VCO3 when the Tracking Generator is
turned "off".
Used to determine the
command word when
commanding the PLL3 "off". This is because the PLL3 is not
powered
down and the VCO3 will continually run. A frequency must be
chosen so
that PLL 3 will not cause interference to the MSA during normal
spectral analysis.
PLL3mode = 0
1 = Fractional Mode, 0 = Integer Mode. Used as part of
the command word when commanding the PLL3. If PLL3 chip can be
used as
a Fractional-N, it is advised to use it this way. It will allow a
higher phase detector frequency, providing better stability, with lower
step sizes.
PLL3phasefreq = .005
This is the Tracking Generator's PLL3 phase detector frequency (PDF),
which will determine the step size of LO3 (PLL3/VCO3). It is
advisable
to use the highest PDF possible. The software will calculate the
correct frequency to program PLL3 in this manner: PLL3 freq = LO2
freq
- Final I.F. Frequency. For example, if LO2 = 1024 MHz and Final
I.F. Frequency = 10.700 MHz, then PLL3 will be commanded to 1013.3
MHz. Therefore, a good PDF to use would be .1 MHz. If,
however, the
Final Xtal Filter has a center frequency of 11.15 MHz, the PLL3 would
be commanded to 1012.85 MHz. A PDF of 100 KHz would not be
acceptable,
because the step size is 100 KHz and could only step to 1012.80 or
1012.90 MHz. The PDF would have to be changed to 50 KHz (.05
MHz).
Another example: The Final Xtal Filter has a center
frequency of 9.955 MHz, the PLL3 would be commanded to 1014.045
MHz.
Here, the PDF would have to be .005 (MHz).
If a Fractional-N PLL is used, the PDF (the
variable,
"PLL3phasefreq") will be 16 times the step frequency. Therefore,
if
the step size required is .005 (MHz), the PDF will be .08 (MHz).
If the designer is using a Final Xtal
Filter
that is not a multiple integer of 5 KHz, there is a way to make the
PLL3 command to a frequency that creates a final I.F. that is
extremely close (if not right on) to the Final Xtal filter's
center
frequency. For example, a Final Xtal Filter is 9.954 MHz (CF)
with a
bandwidth of 2 KHz. We would like the PLL3 to create a frequency
of
1014.046 MHz. However, with a step size of 5 KHz, the closest
stepped
frequency would be 1014.045 MHz. This would create a final I.F.
of
9.955 MHz, which is 1 KHz away from the center frequency of the Xtal
Filter. The measurement will be 3 dB lower due to the signal
being on
the edge of the filter response.
There is no rule that a PLL's PDF must be some value
of "whole
number frequency". With some innovative calculations, we can
create a
PDF that will, in turn, create a frequency of 1014.046 MHz. The
frequency formula for an integer PLL is : VCO output
frequency = N x
Reference Clock / R, where N is the PLL's N counter, and R is the PLL's
reference clock divider. With a Reference Clock of 64 MHz and VCO
output frequency (wanted) of 1014.046 MHz, the N to R ratio is
1014.046/64 = 15.844469. Both N and R must be whole
numbers. With
some itterative calculations, it is found that N = 14446 and R =
913.
Substituting N and R into the frequency formula: VCO output
frequency = N x Reference Clock / R, 14446 x 64 MHz
/ 913 = 1014.046 MHz. The PDF = Reference
Clock/913 = .070098576 MHz. I did not sit around all day with a
calculator trying to find these numbers. I wrote a short
iterative
program in Liberty Basic to find them for me. You can grab it
here,
called, findpllpdf.bas. You
only need to know the Master Clock
frequency, and the frequency
of LO2.
PLL3loop = 2
This tells the software if PLL3 is configured with a loop
filter that is inverting or non inverting. The published
schematics
for PLL3 have non inverting loop filters, enter "2". If an inverting op amp
is used in the loop filter, enter "1".
It is acceptable to use a VCO3 that has a reverse tuning
characteristic. This is the code to change, if that is the case.
glitchtime = 5000
This is time added when the DDS or PLL changes drastically.
Later in the program, an if/then
statement uses this value and will slow down the program. This is so
that the PLLs and final Xtal Filter will have
time to settle before data is taken. This value is somewhat
arbitrary
and depends of the speed of the home computer being used. This
seems
to be a good number for my Celeron 700 MHz, but may have to be
increased for a faster computer. The actual time of the waiting
period
can be changed when the program is running by changing the value in the
Working Window's box, called, "Wait".
topref = 0
This is the default top reference line on scale, in dBm input to
the MSA. It is used to
create the Log Scale in the Graph Window. This value should not
be
greater than the maximum input to the MSA when the Log Detector begins
compression. For initial operation, and before calibration, enter
"0".
After calibration, this number will reflect the actual power input to
the MSA.
botref = -100
This is the default bottom reference line on scale, in dBm input to
MSA. This number cannot be greater than the value in the
variable,
"topref".
'[CalibrationFile]
'change following
variables for your Log Det/AtoD combination.
adconv = 8
There are 3 different Analog to Digital Converter designs that can be
used for the MSA. Enter "8"
for the original 8 bit, enter "12" for optional 12
bit ladder, or enter "16"
for the serial
AtoD.
maxpower = 0
This is, normally, the input power
level (in dBm) to the Log Detector when the Log Detector begins
compression. For the LM3356 design, it is approximately "0"
dBm. For
the AD83xx series Log Det, it is about + "10" dBm. But, it can be
anything and will be treated as the maximum input to the Log
Detector.
Be sure to enter the sign if negative, ie, "-3" dBm. Before
calibration, enter "0".
The following are nominal values to enter, before
calibration.
maxbits = 255 (or
4095 for
12 bit, or 65535 for 16 bit)
This is the bit value when
maxpower is applied to Log Det. During calibration, the A/D is
adjusted to create a value of maximum bits when the maxpower level is
applied to the Log Detector. For the 12 bit A/D the nominal value
is "4095" and for the 16
bit A/D it is "65535"
minus10bits = 239
(or 3741 for 12
bit, or 59850 for 16 bit)
This is the bit value when 10 dB less than maxpower
is applied to the Log Det.
minus20bits = 211
(or 3384 for 12
bit, or 54140 for 16 bit)
This is the bit value when 20 dB less than maxpower
is applied to the Log Det.
minus30bits = 183 (or
3024 for
12 bit, or 48380 for 16 bit)
This is the bit value when 30 dB less than maxpower
is applied to the Log Det.
minus40bits = 155 (or
2673 for
12 bit, or 42770 for 16 bit)
This is the bit value when 40 dB less than maxpower
is applied to the Log Det.
minus50bits = 123 (or
2323 for
12 bit, or 37170 for 16 bit)
This is the bit value when 50 dB less than maxpower
is applied to the Log Det.
minus60bits = 95 (or
1981 for
12 bit, or 31700 for 16 bit)
This is the bit value when 60 dB less than maxpower
is applied to the Log Det.
minus70bits = 63 (or
1631 for
12 bit, or 26100 for 16 bit)
This is the bit value when 70 dB less than maxpower
is applied to the Log Det.
minus80bits = 37 (or
1299 for
12 bit, or 20780
for 16 bit)
This is the bit value when 80 dB less than maxpower
is applied to the Log Det.
minus90bits = 24 (or
971 for
12 bit, or 15540 for 16 bit)
This is the bit value when 90 dB less than maxpower
is applied to the Log Det.
minus100bits = 23 (or
697 for
12 bit, or 11150 for 16 bit)
This is the bit value when 100 dB less than maxpower
is applied to the Log Det.
minus110bits = 23 (or
577 for
12 bit, or 9230 for 16 bit)
This is the bit value when 110 dB less than maxpower
is applied to the Log Det.
minus120bits = 23 (or
556 for
12 bit, or 8900 for 16 bit)
This is the bit value when 120 dB less than maxpower
is applied to the Log Det.
minus130bits = 23 (or
553 for
12 bit, or 8850 for 16 bit)
This is the bit value when 130 dB less than maxpower
is applied to the Log Det. Notice that the last 4 variables are
the
same or close to it. This is due my using the MC3356 Log Det,
which
has only 90 dB of dynamic range. The AD83xx series has over 100
dB of
range, and these values will increase during calibration.
'The following are nominal values you can start with, before
calibration.
'maxbits = 255
4095 65535 ver107
'minus10bits = 241 3741
59850 ver107
'minus20bits = 213 3384
54140 ver107
'minus30bits = 186 3024
48380 ver107
'minus40bits = 158 2673
42770 ver107
'minus50bits = 126 2323
37170 ver107
'minus60bits = 97
1981 31700 ver107
'minus70bits = 65
1631 26100 ver107
'minus80bits = 39
1299 20780 ver107
'minus90bits = 28
971 15540 ver107
'minus100bits = 23
697 11150 ver107
'minus110bits = 23
577 9230 ver107
'minus120bits = 23
556 8900 ver107
'minus130bits = 23
553 8850 ver107
port =
hexdec("&H378")
This is the LPT printer port data address
for many home computers. "Port" is used as a simplification when
commanding 8 Bits
to the LPT 1 printer port. This address, and the following
"status"
and "control", should work for almost all home computers. If it
does
not, the operator must determine the correct addresses to use for his
computer.
status =
hexdec("&H379")
This is the LPT printer port status address for
specific computer. "Status" is used as a
simplification when reading Bits on the
LPT 1 printer port.
control =
hexdec("&H37A")
This is the LPTprinter port command address for
specific
computer. "Control" is used as a simplification when
commanding 4 Bits to the LPT 1 printer port.
x = 720
This is the width of the horizontal Frequency Graph. It is 720
pixels in width(x). For larger monitors with a higher resolution
than
800 by 600, this value can be changed to the user's preference.
y = 300
This is the height of the vertical Amplitude Graph and is 300 pixels
high(y). Again, for larger monitors with a higher resolution
than 800 by 600, this value can be changed to the user's preference.
windowwide = 800
This is the total width of the Working and Graph Windows. They
are 800 pixels wide. Again, for larger
monitors with a higher resolution than 800 by 600, this value can be
changed to the user's preference.
maxscale = 255
This is the height of Log Amplitude Scale, in pixels, and must be less
than the value "y".
Again, for larger monitors with a higher
resolution than 800 by 600, this value can be changed to the user's
preference.
windowhigh = 180
This is the total height of the Working Window and is 180 pixels in
height. Again, for larger
monitors with a higher resolution than 800 by 600, this value can be
changed to the user's preference.
graphhigh = 415
This is the total height of the Graph Window and is 415 pixels in height.
Again, for larger monitors with a higher
resolution than 800 by 600, this value can be changed to the user's
preference.
This ends the portion of Global Variables, that are normally changed by
the user. The Variables from this point, on, are not to be
changed
without justification.
The following variables are specific to the Control
Board that I designed for the MSA and can be changed if necessary.
finalfreq = finalfreq1
'default, sweeping will
begin with data entered into the finalfreq1 Global
finalbw = finalbw1
'default, sweeping will begin with data entered into the
finalbw1 Global
sagain =
sagain1 'default,
sweeping will begin with data entered into the sagain1 Global
contclear =
11
'global
control bits to take all command lines low
cont1and2 =
3
'global
control bits to activate PLL1/PLL2(EnaP)J1 and J2, (Select Input)
cont3and4 =
15 'global
control bits
to activate PLL3/spare(EnaT)J3 and J4, (Init Printer)
contwclk =
9
'global control bits to take DDS wclk line high, (Auto Feed)
contfqud =
10
'global control bits to take DDS fqud line high, (Strobe)
contreset = 8
'global
control bits to take DDS wclk and fqud lines high, to reset the DDS, if
the DDS has had the modification.
lepllj1 =
4 'global port data to
send
LE on J1 (PLL 1), if cont1and2 is set
lepllj2 =
8 'global port data to
send
LE on J2 (PLL 2), if cont1and2 is set
lepllj3 = 16
'global port data to send LE on J3 (PLL 3), if cont3and4 is set
lepllj4 = 32
'global port data to send LE on J4 (spare), if cont3and4 is set (not
used)
out port,
0
'begin the program by sending the computer's 8 bit data lines low
out control, contreset:
'this will reset the DDS, if modified
out control, contclear
'begin the program by sending the computer's 4
command lines low
Main Routines,
and their functions:
[Command
PLL 3]
This commands the
Tracking Generator "OFF", actually to a specific frequency determined
by the Global Variable, "PLL3off". gosub
[SetUpPLL3] If there is no optional Tracking
Generator (global variable PLL3 = 0) there will be no PLL 3
command action.
[Command
PLL 2]
This section of
code will command PLL2 to create the LO 2 frequency that is set in the
global variable, "appxLO2".
This area is hardcoded for Integer-N commanding, even if using
Fractional-N type PLL's.
It will jump to the appropriate PLL subroutine [CommandxxxxR] and
ititialize and command the Rcounter portion of PLL 2. It will
return and then jump to the appropriate PLL
subroutine [CommandxxxxN] and
command the Ncounter portion of PLL 2. If the R or N counter is
out of range, an error message will be created and displayed when the
program is halted.
The subroutine knows which PLL to command, by using
the
variables Jcontrol = cont1and 2, and LEPLL = lepllj2. These were
globals established at the beginning of the program.
In all of my designs, I am using 1024 MHz as the 2
nd Local Oscillator (PLL 2). 1024 is a 16 th harmonic of the
Master Oscillator of 64 MHz, and makes for a good Step Recovery Diode
Multiplier scheme. If an SRD or other multiplier scheme replaces
the PLL 2 module, this section will skip over commanding PLL 2.
It will, however, calculate the exact frequency of LO 2 for later use
in the program.
[DeterminePLL1ReferenceDivider]
This section calculates the
initial reference divider
portion of PLL 1. It will then gosub
[CommandPLL1ReferenceDivider] where, it determines if PLL 1 is
Fractional or
Integer, the preselector value, and reference counter value. It
will then jump to the appropriate gosub
[CommandxxxxR] and
ititialize and command PLL 1. The subroutine knows which PLL to
command, by using the variables Jcontrol = cont1and 2, and LEPLL =
lepllj1. These were globals established at the beginning of the
program.
If the Rcounter is out of range, an error message
will be created and displayed when the program is halted.
[SetUpWorkingWindow]
This section
immediatly jumps to the subroutine [createWorkingWindow].
Here,
the Working Window is created with text, boxes, and buttons. The
global variables are inserted into the appropriate boxes. The
global variables "windowwide" and "windowhigh" create the size of the
Working Window. These were set for a monitor that has a
resolution of 800 by 600 pixels. If your monitor has higher
resolution, the window will not totally fill the width of the screen,
as they will on an 800x600 monitor.
It will place the Working Window on the monitor
screen, with the top left corner of the window at the monitor's pixel
location of x,1 and y,415. Monitor pixel locations begin at the
top left of the screen (x,1 and y,1). For an 800x600 monitor, the
top right pixel location is x,800 and y,1. Lower left is x,1 and
y,600. Lower right is x,800 and y,600.
[GrabWorkingWindowData]
This section
will go to the subroutine [calcWindowInfo]
and look at the values that are in the Working Window boxes to
create
variables that will be used in the rest of the program. This
section is a
pointer location. That is, any time the "RESTART" button is
clicked in the Working Window, the program will return to this location
to check to see if any of the variables have been changed by the
operator.
[SetUpGraphWindow]
This section
will jump to the subroutine [CreateGraph].
The Graph Window is
created using the global variables, windowwide and graphhigh.
Like the Working Window, these variables are for an 800x600 pixel
monitor screen.
The x-axis and titles are created using the
previously established global variables.
[Sweep
from Start Frequency]
This section is the
"reset" when the Spectrum Analyzer begins sweeping. It resets the
graph to the left side of the x-axis and the step number to "0".
Later in the program, when the spectrum analyzer is stepped to its last
step, it is pointed back to this section to "start over". The
number of steps can be anything from 2 to 720.
[CalculateNextStep]
This section will
calculate and determine several values that are used to step the
Spectrum Analyzer to its next step.
Firts, it will calculate the exact input frequency
that the SA will tune to: thisfreq = startfreq + (stepfreq * thisstep)
It then calculates the frequency that LO 1 (PLL3)
must be: LO1 = thisfreq + LO2 - finalfreq
It then calculates the approximate Phase Detector
Frequency (PDF) for PLL 1: appxphasef = appxDDS/rcounter1
It then calculates the approximate
N counter value for PLL 1: appxncounter = LO1/appxphasef
[CreatePLL1asFractional]
When PLL 1 is used as
a Fractional-N PLL, this section will
calculate the variables for
PLL 1.
The Ncounter and Fcounter is
calculated. Then, the DDS output frequency is calculated.
Since Fractional-N PLL's create some known spurs, a
calculation is made to determine if a potential spur is likely to be
created at this frequency: harnonicb = int(firstif/fractionalfreq)
If there is a likely spur, the F counter is changed by one count.
This changes the PDF of PLL 1 a small amount and the DDS output
frequency is
recalculated.
If the operator has pushed the Spur Test button, [Spurtest], the
F counter will be changed one count and the DDS will be recalculated
again: ddsoutput = actphasef * rcounter1
The data is ready to command the PLL 1 N counter section and the DDS.
[CreatePLL1asInteger]
If PLL 1 is
Integer,
the Ncounter is calculated. Then, the DDS output frequency is
calculated. The data is ready to command the
PLL 1 N counter section and DDS.
[CommandPLL1Ndivider]
First, it will reset the
extra wait statement: glitch = 0. If the data for PLL 1 has not
changed from the previous step, then it won't waste time recommanding
PLL
1.
If commanding PLL 1 is required, add some wait time
to the settling time routine: glitch=1
If PLL 1 is Fractional, change the preselector of
PLL 1 to 16.
It will select the correct PLL and then command the
appropriate N-counter
portion: if PLL1 = xxxx then gosub [CommandxxxxN].
It will return
with an error message if the N counter is out of range. Variables
are established for the next step to determine if the PLL 1 will need
recommanding: ncount = ncounter
[CommandDDS]
This section begins
be verifying that the DDS output frequency is within the bandwidth of
the DDS Xtal filter: if ddsoutput-appxDDS>xfilbw/2 then
beep:error$="DDSoutput too high for filter".
A determination is made if the DDS frequency is lower than the previous
step. If so, add some wait time to the settling time
routine: glitch=1
Then it will jump to the
subroutine [DDScommand] and command
the DDS.
[SettleDownTime]
This section is a
wait statement to slow down the computer while the Spectrum Analyzer
circuits are settling down. When PLL 1 becomes unlocked, due to
commanding the Ncounter, or, if the DDS changes a large amount, the PLL
1
loop filter will require several hundred microseconds for
reacquisition. This is where the glitch addition comes into
play. Also, time is required for the Log Detector to settle, due
to the bandwidth of the Final Xtal Filter" : for waittime = 0 to (wats
*
100) + (glitch*glitchtime), next waittime. Every home computer
has
a different speed, and the global variables "wats" and "glitchtime" can
be changed accordingly. We would like the Spectrum Analyzer to
sweep as fast as possible, but slow enough to guarantee correct Log
Detector information.
[ReadLogData]
This section
determines which A/D scheme is used and will
jump to the appropriate subroutine
[logData8Bit] , [logData12Bit]
, or [logData12Bit].
This is where the A to D
process takes place. It will return with an amplitude value
called, "bitsy", which will be used in the next routine.
[ConvertLogData]
The value "bitsy" is used in subroutine
[ConvertBitsToPower] , to calculate a power
level. This power level is then converted to pixels, in subroutine
[ConvertPowerToPixels] , to be used in the next section
for plotting. An array is created to store the data taken at this
sweep step so that it can be retrieved later.
[PlotLogData]
This section will
jump to the subroutine [PlotData].
This
is where the data is
plotted into the Graph Window.
[DetermineNextOperation]
If the "Show
Variables" window is open, it will be updated with the latest
information. The
program will then determine if the operator has halted the sweep.
If so, gosub [Halted].
If not halted,
the sweep will continue at [IncrementOneStep]
[IncrementOneStep]
A number is
added to this step number: thisstep =
thisstep + 1
If this new step number is higher than the maximum
steps in this sweep, then go back to [SweepFromStartFreq]
and sweep from the first step. If not, then go back to [CalculateNextStep] and continue
sweeping at the next step.
Sub-Routines,
and their functions:
[CommandPLL1ReferenceDivider]
This specifies the rcounter for PLL1 and
commands it in the appropriate subroutine [CommandxxxxR]
[logData8Bit]
This
is where the computer will command the D/A ladder network and pole the
comparator
until the correct Log Detector value is determined. It treats the A to D process as a
Successive Approximation
Determination. The final Log
Det
output variable, is called "bitsy" and has a value of 8 bits (0 to 255).
[logData12Bit]
This operates the same way as the
8 bit detection, but uses 12
bits instead of 8. The final Log
Det
output variable, is called "bitsy" and has a value of 12 bits (0 to
4095).
[logData16Bit]
This
is where the computer will access the serial AtoD converter and
retrieve the data. The software will two AtoD's at once.
However, only magnitude data is used in this software at this
time. The phase data is written for later expansion. The final Log
Det
output variable, is called "magdata" and has a value of 16 bits (0 to
65535).
[ConvertBitsToPower]
This converts the A/D bit value to power using the
cal table
[ConvertPowerToPixels]
This converts the power to pixels for display
[PlotData]
This
subroutine will plot one amplitude data point into the Graph Window at
coordinates x and y. Where x is the horizontal point which represents
the frequency step at which the data was taken and the y point is the
amplitude of Log Detector (in pixels)
[insertMarker]
This adds information to
the Graph at the Markers
[createWorkingWindow]
This
creates the Working Window and inserts the
default global variables
[calcWindowInfo]
This reads data in the Working Window boxes and creates new
variables
[LeftButDown]
This reads the horizontal pixels in the Graph when the Mouse
is "left clicked". The data in the array is read and printed into
the Working Window
[RightButDown]
This reads the horizontal pixels in the
Graph when the Mouse
is "right clicked". The data in the array is read and printed
into the Working Window
Cent :
[centerbutton]
This will take the contents of the "This Freq" box and
put it in the "Center Frequency" box and then wait for a "RESTART"
[CreateGraph]
This creates the Graph
Window and draws the X and Y graph
scale
[Reprintlines]
This reprints the reference graph lines for clarity
[DDScommand]
This commands the DDS in a parallel mode
[Command2325R] and [Command2325N]-this commands the specific
LMX 2325 R
and N counters
[Command2326R]
and [Command2326N]-this
commands the specific LMX 2326 R and N counters
[Command2350R]
and [Command2350N]-this
commands the specific LMX 2350 R and N counters
[Command2353R]
and [Command2353N]-this
commands the specific LMX 2353 R and N counters
[Command4112R]
and [Command4112N]-this
commands the specific ADF 4112 R and N counters
[Halted]
When the sweep has been halted,
the graph lines will be reprinted in the Graph Window. If an
error has taken place, the error will be printed into the Working
Window's Message Box. The statistics of the last sweep step will
be printed into their appropriate boxes of the Working Window.
The operation will now "wait" for the operator to change one or more of
the data parameters in the Working Window's red boxes and then click
one
of the BUTTONS in the Working Window.
The following are the
BUTTONS and
the [Subroutines] that will be
jumped to, when that buttton is clicked:
F1
: [button1]
This changes
the Final Xtal Filter parameters to the Global Variables for Filter 1,
then toggles D4 and Init lines on the LPT printer port. It then
waits for next button push.
F2 : [button2]
This
changes
the Final Xtal Filter parameters to the Global Variables for Filter 2,
then toggles D5 and Init lines on the LPT printer port. It then
waits for next button push.
F3 : [button3]
This
changes
the Final Xtal Filter parameters to the Global Variables for Filter 3,
then toggles D6 and Init lines on the LPT printer port. It then
waits for next button push.
F4 : [button4]
This
changes
the Final Xtal Filter parameters to the Global Variables for Filter 4,
then toggles D7 and Init lines on the LPT printer port. It then
waits for next button push.
RESTART : [Restart]
This will close the Graph Window and restart the sweep at [GrabWorkingWindowData]
REWRITE : [Rewrite]
Will
step
the frequency
by one
step each time
the button is clicked, and will plot a line trace in the Graph that
won't
be erased until the RESTART button is clicked.
REW.CONT : [Rewcont]
Will continue the sweep from the
stopped position, and will plot a line
trace in the Graph that won't be erased until the RESTART button is
clicked.
ONESTEP : [OneStep]
Will
step the frequency by one step each time the
button is clicked
CONTINUE : [Continue]
Will continue the sweep from the stopped
position
[ClearKeyBox]
This
will clear any information in the "Hit Any Key" box, so that sweeping
will be continuous.
[FocusKeyBox]
This will make the "Hit Any Key"
box, accept a keyboard press, without having to click on it.
Track Gen is OFF (or ON) : [Trkbutton]
This changes the data printed in the button, then turns the Tracking
Generator on (or off), then waits.
[SetUpPLL3]
This commands the Tracking Generator frequency
Spur Test is OFF (or ON) : [Spurtest]
This will cause the PDF
of PLL 1 to change, making any self generated spur to move on the
Graphed Plot.
Harmonic Window: [CreateHarmonicWindow]
This will open a small window inside the Graph Widow to display
probable spur generator frequencies. It will then Wait for an
action within that window.
[Image0][Image1][Image2][Image3][Image4][Image4][Image4]
Will inject
data from Harmonic Window into the center frequency box and
automatically Restart the sweep
[CloseHarmonicWindow]
Will close the Harmonic Window
Show
Variables :
[Showvar]
Will
create a small window containing the status of variables used within
this program. A nice troubleshooting tool.
[updatevar]
Will update the status within the "Variables" window.
[Closevarwin]
Will close the variables window.
[finished]
Will close all windows and end the running program.
June 24, 2006 (I will
continue the subroutine explanations as time
permits)
You can email me, Scotty Sprowls,
with questions or comments
at wsprowls@yahoo.com. I'm a retired Design
Engineer with plenty of time to answer you. Best Wishes, all!