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).  I will try to describe the actions of all the code.  But, since there are over 1600 lines of code, the page will be "in-work" for quite some time.
Page Started Nov. 30, 2004 and is in progress.  Use your browser's "Refresh" for latest info.
Updated Dec. 23, 2004, add subroutine list
Updated June 13, 2005, change software to revision 103, added auto reset for DDS modification
Updated Aug 7, 2005, change software to revision 104, added spur test button to all PLL types
Updated Nov 19, 2005, change software to revision 105, added more features, optional 12 bit A to D process
Updated Nov 28, 2005, change software to revision 106, added more features to take advantage of a 12 bit A to D process

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 code is doing.
How to Operate and Calibrate the Spectrum Analyzer, this will take you to a different page
List of Main Blocks of the Code
List of Subroutines in the Code

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 code is explained 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.
PLL 2 will be used as an Integer-N PLL, even if it has Fractional-N capability.  PLL 2 is a direct loop synthesizer, that is, no op amp is needed.
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 or PLL 3.  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.
  PLL 3 is a direct loop synthesizer, that is, no op amp is needed.
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.  For software revision 105 and later, a 12 bit Analog to Digital process is supported.

Here is the Main Block List, and Code Flow 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 1600 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.

    These are the main routines of the software:
Establish Global Variables
Command PLL 3
Command PLL 2
Command PLL 1 Reference Divider
Create the Working Window
Grab Working Window Data
Create the Graph Window
Sweep from Start Frequency
Calculate Next Step for Sweep
Create PLL 1
Command PLL 1 N Divider
Command DDS
Settle Down Time
Read Log Data
Plot Log Data
Determine Next Operation
return to top

Subroutines, and their functions:
[CommandPLL1ReferenceDivider]-this specifies the rcounter for PLL1 and commands it
[logData8Bit]-this is actual Log Detector output's A to D conversion process for an 8 Bit A to D
[logData12Bit]
-this is actual Log Detector output's A to D conversion process for a 12 Bit A to D
[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 plots the data into the Graph Window
[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 the Working Window boxes and creates new variables
[LeftButDown]-this calculates data points in the Graph when the Mouse is "left clicked"
[RightButDown]-this calculates data points in the Graph when the Mouse is "right clicked"
[centerbutton]-this will take the contents of the "This Freq" box and put it in the "Center Frequency" box
[CreateGraph]-this creates the Graph Window and draws the X and Y graph scale
[Halted]-this stops the sweeping process
[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
[button1],[button2],[button3] and [button4]-this changes the Final Xtal Filter and changes global variables for further calculations
[Restart],[Rewrite],[Rewcont],[OneStep],[Continue]
and [ClearKeyBox]-continuations after Sweep is halted
[FocusKeyBox]-directs the program's attention to the "hitanykey" box for Halting
[Trkbutton]-this turns the Tracking Generator ON or OFF
[SetUpPLL3]-this commands the Tracking Generator frequency
[Spurtest]-this enables the spurcheck, but only if PLL 1 is used as a Fractional-N PLL
[CreateHarmonicWindow]-will create a window within the Graph Window, containing spur information
[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
[finished]-this closes the Working and Graph Windows, the Harmonic Window, and escapes the Running Program
return to top

Establish Global Variables
   
This is the beginning of the program and 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.  The other variables, once established, will never be changed.  Go to the  Operate  page if you want to see the reasoning for determining the values of the global variables.  Here, we will only describe how and where the global variables are used in the program.

    The global variable values, that are shown, are for a spectrum analyzer with these attributes:
PLL's are all LMX2326  (Integer-N).  Tracking Generator resolution is 5 KHz.
    nomainwin    'this just tells the program not to open a main window.
    masterclock = 64    'nominal frequency of the Master Clock (in MHz).  This is a "coarse" frequency
       used to determine the correct counter commands for the PLL's
    actualclock = 64    'actual output frequency of the Master Clock (in MHz).  This used to calculate the
       actual (and correct) frequency of the Local Oscillator 1.
    cf = 0              'center frequency default, all frequencies in MHz.  Used to determine the frequency
       at the center of the sweep.  Will be shown or changed in the "Center Freq" Box.
    sw = .02            'sweep width in MHz, default.  The SA will sweep from one half sw below CF
       to one half above the CF (cf, center frequency), shown or changed in the "Sweep Width" Box.
    wat = 0             'wait before data take, default.  Later in the program, an if/then statement will slow
         down the program so that the hardware will have time to settle before data is taken.
    sps = 400           'default steps per sweep.  This is the number of steps in each sweep. Used to deter-
            mine where in the sweep the program is.  Value can be changed in "Steps per Sweep" Box.
    mkr1 = 100          'marker 1 step placement, default.  Program will stop sweeping at each marker
       and write information to the Graph Window. 
Will be shown or changed in the "Place Markers at
         Steps" Box.

    mkr2 = 200          'marker 2 step placement, default
    mkr3 = 300          'marker 3 step placement, default
    finalfreq1 = 10.7   'freq of Final Xtal Filter # 1.  This is used to determine the correct I.F. frequency,
       which also determines the correct LO1 freq, and Track Gen Frequency
    finalbw1 = 2.0      'BW (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         'total gain of SA with Final Filter #1 installed.  Used to calibrate Graph Window.
    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 SA 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 SA 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 SA with Final Filter #4 installed
    appxLO2 = 1024      '2nd LO frequency,1024 MHz or greater, 4 MHz steps.   This is a coarse freq-
       uency used to determine the PLL2 commands.
    PLL1 = 2326         'enter PLL type, (LMX) 2325, 2326, 2350, 2353, (ADF)4112.  The program will
        use "if" statements using these values to determine which subroutine to use for PLL commanding.
    PLL2 = 2326         'enter PLL type, (LMX) 2325, 2326, 2350, 2353, 0 for SRD.  If "0" is used,
       the program will not command PLL 2.
    PLL3 = 2326         'enter PLL type, (LMX) 2325, 2326, 2350, 2353, 0 for no Tracking Generator
    PLL1phasefreq = .70009   'This is the maximum Phase Detector Frequency (PDF) for PLL 1.  This
       is a coarse number that determines the value of the Rcounter for PLL1
    PLL1mode = 0            '1 = Fractional Mode, 0 = Integer Mode.  Used as part of the command word
       when commanding the PLL1.
    PLL2phasefreq = 4       '2nd LO's PLL2 phase frequency is 4 MHz.
  Used to determine command
         word when commanding the PLL2.

    PLL3off = 970      'Output freq of PLL3/VCO3 when Trk Gen "off", v103.    Used to determine
         the command word when commanding the PLL3 "off".

    PLL3phasefreq = .005   'TrkGen LO's PLL3 phase frequency, which will determine command word
    PLL3mode = 0            '1 = Fractional Mode, 0 = Integer Mode
  Used as part of the command word
       when commanding the PLL3.

    appxDDS = 10.7      'this DDS output(Ref. for PLL1), and center freq. of DDS xtal filter.  Used as
       a coarse value when calculating LO 1 frequency.
    xfilbw = .0075      'this is the DDS xtal filter bandwidth, must be > .0045 (MHz).  This value is used
       as an error check when commanding the DDS.
    glitchtime = 5000   'this is time added when the DDS or PLL changes drastically.  
  Later in the
         program, an if/then statement will slow down the program so that the hardware will have time to
        settle before data is taken.

    topref = 0           'default top reference line on scale, in dBm input to SSA, used to create the Log Scale in the Graph Window
    botref = -100           'default bottom reference line on scale, in dBm input to SSA
    dabits = 8             'use "8" for original 8 bit, or "12" for 12 bit A to D network, this determines which of the following calibration tables is used when calculating the SSA power input
    '[8Bit]  'insert the proper values below, for an 8 bit A to D network, the default values below were taken in my MSA using the original A to D network, and an LM3356 as the Log Detector.  They are changed during the Calibration Procedure.
    maxpower = 0       'power level at the input to the Log Det at compression, in dBm
    maxbits = 255       'bit value from A to D converter when "maxpower" is applied to the Log Det.
    minus10bits = 241   '
bit value when "maxpower" - 10 dB is applied to the Log Det.
    minus20bits = 213   'bit value when "maxpower" - 20 dB is applied to the Log Det.
    minus30bits = 185   'etc
    minus40bits = 157
    minus50bits = 125 
    minus60bits = 97 
    minus70bits = 65 
    minus80bits = 39 
    minus90bits = 25 
    minus100bits = 23 
    minus110bits = 23
    minus120bits = 23
    minus130bits = 23
    if dabits = 8 then goto [end12bit] ' if so, skip the next table
    '[12Bit]  'insert the proper values below, for a 12 bit A to D network
, the default values below were taken in my MSA using the new A to D network, and an AD8306 as the Log Detector.  They are changed during the Calibration Procedure.
    maxpower = 10       'power level at the input to the Log Det at compression, in dBm
    maxbits = 4095       'bit value from A to D converter when "maxpower" is applied to the Log Det.
    minus10bits = 3712   'bit value when "maxpower" - 10 dB is applied to the Log Det.
    minus20bits = 3327    'bit value when "maxpower" - 20 dB is applied to the Log Det.
    minus30bits = 2985    'etc
    minus40bits = 2623
    minus50bits = 2296 
    minus60bits = 1951
    minus70bits = 1608 
    minus80bits = 1272
    minus90bits = 960   
    minus100bits = 684
    minus110bits = 568 
    minus120bits = 511 
    minus130bits = 511 
    [end12bit]

    port = hexdec("&H378")    'printer port data address for specific computer.  "Port" is used as a
       simplification when commanding 8 Bits to the LPT 1 printer port.
    status = hexdec("&H379")  '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") 'printer port command address for specific computer.  "Control" is used
        as a simplification when commanding 4 Bits to the LPT 1 printer port.

    x = 720             'graph horizontal is 720 pixels in width(x)
    y = 300             'graph vertical is 300 pixels in amplitude(y)
    windowwide = 800    'working and graph windows are 800 pixels wide
    maxscale = 255        'height of Log Scale, in pixels, must be less than y
    windowhigh = 180    'working window is 180 pixels in height
    graphhigh = 415     'graph window is 415 pixels in height.  All of these values are used to create the
       Working Window and Graph Window. 
These numbers (x through graphhigh) are set for a Laptop
        or 15 inch monitor.  They can be increased when using larger monitors with higher resolution.
    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. v103
    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, v103
    out control, contclear      'begin
the program by sending the computer's 4 command lines low
Return to the Index of Code Blocks

Command PLL 3
    This commands the Tracking Generator "OFF":  PLL3output = PLL3off:gosub [SetUpPLL3]:trkgen = 0   This sets TG's PLL3 to the value of "PLL3off", in MHz.  If there is no optional Tracking Generator (global variable PLL3 = 0) there will be no PLL 3 command action.
Return to the Index of Code Blocks

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.
 
Return to the Index of Code Blocks

Command PLL 1 Reference Divider
This section calculates the information required to initialize and command the reference divider portion of PLL 1.  It determines if PLL 1 is Fractional or Integer, the preselector value, and reference counter value.  It will then jump to the appropriate PLL subroutine [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.
 
Return to the Index of Code Blocks

Create the Working Window
    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.
 
Return to the Index of Code Blocks

Grab Working Window Data
    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 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.
  
Return to the Index of Code Blocks

Create the Graph Window
    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.
  
Return to the Index of Code Blocks

Sweep from Start Frequency
   This section is the "reset" when the Spectrum Analyzer is 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.
  
Return to the Index of Code Blocks

Calculate Next Step for Sweep
   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
   Return to the Index of Code Blocks

Create PLL 1
   This section will calculate the N counter ratio for PLL 1 and the actual frequency that the DDS must create to steer PLL 1.  First, it must determine if PLL 1 is being used as a Fractional-N or Integer-N PLL:  if PLL1mode = 0 then goto [CreatePLL1asInteger], that is, if PLL 1 is used as an Integer-PLL, then jump over to next section.
    If PLL 1 is used as a Fractional-N PLL, then the variables for PLL 1 are created.  Next, 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.
    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.
  
Return to the Index of Code Blocks

Command PLL 1 N Divider
    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 (ncount = ncounter) and (fcount = fraction) then goto [endCommandPLL1Ndivider]
    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
  
Return to the Index of Code Blocks

Command DDS
   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.  It will return and establish the variable:  lastddsoutput = ddsoutput
   Return to the Index of Code Blocks

Settle Down Time
   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.
    The Spectrum Analyzer input frequency, for this step, is placed in the Working Window's "This Freq" box:  print #main.thisfreqbox, thisfreq
   Return to the Index of Code Blocks

Read Log Data
   This section will jump to the subroutine [logData8Bit] if the original 8 bit A to D is used.  It will jump to subroutine [logData12Bit] if the new 12 bit A to D is used.  This is where the A to D process takes place.  It will return with a value in the variable "bitsy", to be used for calculating Power in the subroutine [ConvertBitsToPower] .  This power level is then used in the subroutine [ConvertPowerToPixels] to be used in the next section for plotting.

Plot Log Data
   This section will jump to the subroutine [PlotData].  This is where the data is plotted into the Graph Window.
      Return to the Index of Code Blocks

Determine Next Operation
   This is where the program will determine if the operator has halted the sweep and has changed the operating parameters in the Working Window.
print #main.hitkeybox, "!contents? stop$"
if len(stop$)>0 then gosub [Halted]    'look at Hit any key box.  If anything is entered, then go to the subroutine [Halted].
  This is a "halt".
    If not halted, it will continue to: [IncrementOneStep]
    If the sweep has been halted, the operator can change one or more of the data parameters in the Working Window's red boxes and then push one of the BUTTONS in the Working Window.  The following are the BUTTONS and the subroutines [blue] that will be pointed to when clicked:
F1 :  [button1] this changes the Final Xtal Filter parameters, then waits for next button push.
F2 :  [button2] these 4 buttons use the global variables extablished at the beginning of the code
F3 :  [button3] same
F4 :  [button4] same
Track Gen is OFF (or ON) :  [Trkbutton] this turns the Tracking Generator on (or off), then waits.
RESTART : goes to [Restart] and will restart the sweep from the beginning
ONESTEP : goes to [OneStep] and will step the frequency by one step each time the button is clicked
CONTINUE : goes to [Continue] and will continue the sweep from the stopped position
REWRITE : goes to [Rewrite] and will step the frequency by one step each time the button is clicked, but will plot a line trace in the Graph that won't be erased until the RESTART button is clicked.
REW.CONT : goes to [Rewcont] and will continue the sweep from the stopped position, but will plot a line trace in the Graph that won't be erased until the RESTART button is clicked.
Spur Test is OFF (or ON) : goes to [Spurtest] This button will appear only when PLL 1 is operated as a Fractional-N PLL.  This will cause the PDF of PLL 1 to change, making any self generated spur to move on the Plot.
Harmonic Window: goes to [CreateHarmonicWindow] and will open a small window inside the Graph Widow that displays probable spur generator frequencies.
  It will then Wait for an action within the window.
Cent : goes to [centerbutton] and inserts the present frequency step into the Center Freq Box.  It will then Wait for a restart
     Return to the Index of Code Blocks

Increment One Step
    thisstep = thisstep + 1
    if thisstep > steps then goto [SweepFromStartFreq] 'this checks to see if it is at the end of the sweep.  If this happens to be the last step in the sweep, the program will be pointed back to [SweepFromStartFreq].  If not, then:
    goto [CalculateNextStep]  If not at the sweep's end, it will continue sweeping at the next step at: [CalculateNextStep]

Subroutines
subroutine [logData8Bit] , this is a change in version 105 software.  It now treats the A to D process as a Successive Approximation Determination.
  This is where the computer will command the D/A ladder network and pole the comparator until the correct Log Detector value is determined.  The final Log Det output variable, is called "bitsy" and has a value of 8 bits (0 to 255).   The subroutine [logData12Bit] operates the same way but uses 12 bits instead of 8.
    out port, 128    The computer will command the D/A ladder network to half value (128/256). The D/A converts the bits to an analog voltage (aprox. 1.25 v) and sends it to the comparator.  The comparator compares this voltage to the Log Detector's output voltage.  If the D/A voltage is greater than the Log Det voltage, the comparator is HIGH.  if inp(status) > 127 then busy line (comparator output) is low.
    onetwentyeight = 128   this "sets" the value for "onetwentyeight"
    if inp(status) > 127 then onetwentyeight = 0  The computer reads the status lines. If this statement is true, it means the D/A voltage is greater than the Log Det voltage.  Therefore, change the value of "onetwentyeight" to 0, so that the next D/A command will be a lower voltage.
    out port, onetwentyeight + 64  
The computer will command the D/A ladder network to the next half value (64/256) and repeat the same type of comparison as the first step.  Each bit is commanded to the D/A ladder network until all 8 bits are calculated.
    sixtyfour = 64
    if inp(status) > 127 then sixtyfour = 0
    out port, onetwentyeight + sixtyfour+32
    thirtytwo = 32
    if inp(status) > 127 then thirtytwo = 0
    out port, onetwentyeight + sixtyfour+thirtytwo+16
    sixteen = 16
    if inp(status) > 127 then sixteen = 0
    out port, onetwentyeight + sixtyfour+thirtytwo+sixteen+8
    eight = 8
    if inp(status) > 127 then eight = 0
    out port, onetwentyeight + sixtyfour+thirtytwo+sixteen+eight+4
    four = 4
    if inp(status) > 127 then four = 0
    out port, onetwentyeight + sixtyfour+thirtytwo+sixteen+eight+four+2
    two = 2
    if inp(status) > 127 then two = 0
    out port, onetwentyeight + sixtyfour+thirtytwo+sixteen+eight+four+two+1
    one = 1
    if inp(status) > 127 then one = 0
    out port, 0    'return data to zero
    bitsy = onetwentyeight+sixtyfour+thirtytwo+sixteen+eight+four+two+one   The value of "bitsy" can be from 0 to 255.

    return   
click to return to the Read Log Data main section

    subroutine [PlotData]' This subroutine will plot one data point into the Graph Window
    thispointx = thisstep * x/steps  'establishes x data point on the x-axis of graph (0 to 720)
    print #handle, "color white"  'this tells the next line plot to be white
    if rewrite = 0 then print #handle, "line ";thispointx;" ";y;" ";thispointx;" ";y-275
        '
during normal sweep, this plots a white line from the bottom of the graph to the top, hiding (clearing) any previous sweep's data point
    print #handle, "color black" 'this tells the next data plot to be black
    if rewrite = 0 then print #handle, "line ";thispointx;" ";y;" ";thispointx;" ";(y-1)-thispointy
        'during normal sweep, this plots a line from the
bottom of the graph to the bit value of the Log Detector output.
    if rewrite = 1 then print #handle, "line ";thispointx;" ";(y-1)-thispointy;" ";lastpointx;" ";lastpointy
        '
during rewrite mode, plots the data as a dot, one pixel higher than normal sweep, and connecting that dot to the previous sweep's data point plot
    if thisstep = marker1 then gosub [insertMarker]'when the sweep gets to the step that was established as a marker, go to the subroutine and create the marker information. Return here after inserting marker
    if thisstep = marker2 then gosub [insertMarker]'and return here after inserting marker
    if thisstep = marker3 then gosub [insertMarker]'and return here after inserting marker
    lastpointx = thispointx     'remember this x data point for next step data take
    lastpointy = (y-1)-thispointy   '
remember this y data point for next step data take
    return  'return to [endPlotLogData]         click to return to the Plot Log Data main section


Nov 28, 2005  (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!