'spectrumanalyzer.bas (or .tkn). 8-1-2009 'Created from version 114-7q 'Reason for change: For final release, Version 114 '------------Changes and additions ------------ '7q Create routine to measure client area of window using a small test window. ' In filter analysis window, add P+ marker only if analysis is turned on ' Separate checkbox captions into statictext so color comes out right. ' Fix marker clearing so info area is always updated. ' cause gGridString$ to be created even if gIsDynamic=0 '7p Fix bug when no preference file exists or file is bad ' Restore setting of initial margins, accidentally deleted in 7o ' For future compatibility, when data type is bad assign a default value. '7o. Place graph windows items based on actual client area, not estimate. ' Widen filter selection box ' Rename NumDiv$ in X and Y axis windows to NumHorDiv$ and NumVertDiv$ ' Change default mag cal so 0 dBm is half of max ADC bits '7n Provide [LeftButDouble] in x and y axis windows to avoid crash if user double clicks twice. ' Change Close method in var wind and data wind to subroutine, to avoid crash if user attempts ' to close them from within a subroutine window. ' Clear marker info area when doing Clear Marks ' Add Version to sweeep context. ' Fix error message when restoring contexts. ' Fix DetectChanges regarding change in data type ' Add vector transmission graph for S21 mag (ratio) ' Add SaneLimits to impose reasonable limits when changing data types without blindly carrying ' over prior values--e.g. keeping 0-360 range when changing from angle to capacitance. ' Fix typo in restoring S21GraphR0 from context. ' Add uGetParamText$ to retrieve parameters. ' Save/restore S21 Jig Attach and R0 for base and line cal contexts '7m Move generation of doSpecialRandom so it doesn't change until final point is plotted. ' Allow 1 step sweep. ' Change frequencies in X window dialog only if change is not miniscule, to avoid restart. ' Deleted stepfreq; that info is computed when needed. '7L Broaden test for difPhase=180 to include >179 and <-179. ' Change Track Gen Reflection to Track Gen Transmission ' Fix typos with minor effects ' Change some text lengths on Line Cal dialog. ' Fixes as to when to install which line cal. ' Print cal info in red if cal is downgraded ' Changed baseLineNumPoints to baseLineNumSteps in a couple of places '7k. Reset to SG when switching to SA mode. Set manual marker clicks to integral point. ' Fix [ConvertMagPhaseData] to request phase correction. ' Move call to calInitFirstUse to a point after config file has been loaded. ' Cause marker placement to update variables window properly. ' Disable use of right click in setting markers. ' Fix to path cal to handle inversion properly. ' Add a suppressPDMInversion flag to [ReadStep] ' Set phase correction to 180 and suppress useless inversions when PDM is stuck in crap zone during cal. ' Average 50 readings instead of 10 in calibration. ' Blank ADC and Phase when starting Measure. ' Fix to gCanUseExpeditedDraw when phase is off '7j. Print correct version in graph window title. Change default mag cal file to contain two points ' based on ADC type. Force restart when path is changed. Fix calc of stepfreq. ' Fix so Halt causes flush. ' Force restart when offset or sgout changes ' Implement transform of S21 to new impedance; Fix some text, changing S21->Transmission ' Change doSpecialGraph=5 to use 25 ohms in series with 1 nf. '7i. Fix TG Y-axis label. Fix config manager initial display of TG and VNA items. ' Freq cal fixes. Fix infinite recursion in uExtractTextItem. ' Remove stylebits from comboboxes that need to take immediate action when clicked. '7h. Fix labeling of shape factor in filter analysis. Enlarge Preset Phase... button. ' Add stylebits to comboboxes to prevent user typing. ' Fix to uExtractTextItem$. Change some graphBox$ references to graphHandle$. ' Adjust [ChangeMode] so all changes go through it. '7g. Scotty's fixes. Remove menu items for Reflection and Reference Lines--to be implemented in next release. ' Remove save/recall data buttons--to be implemented in next release '7f. Fixes to DetectChanges. Change Go Data and Go Config to use DetectChanges. ' Fixes to reference trace generation. Change gAdjustPhaseToDisplay so it can use ' uWorkArray, and returns but does not save adjusted phase. Added ReferenceDialog to specify reference lines. '7e. Implement routines to save/restore datatable info as a Data Context, in place of the previous ' routines to do that with the graph data. '7e. Add autoscale, graph data, S21 Jig info and S11 Bridge info to sweep context. That may or may not be ' the best context for them. TO DO--Need to change data context to be datatable(), not graph data. ' Add routines to calculate S11 and S21 for RLC combinations, which may also include a transmission line. ' These will be used for reference lines and in characterizing OSL standards. Added doSpecialGraph=5 to ' graph simulated response of RLC combinations. Changed reference trace generation to use new RLC combo specs, ' and to generate the lines from datatable(). Deleted debugSkipHardware. '7d. Changes involving the amount of data redrawn when Refreshing. When some changes were made, or when clicking ' Redraw, redrawing was done at an unnecessary depth. Fix Expand. Fix some angle interpolations. Allow multiplier ' characters in S21 Jig window for resistance. Misc. fixes. '7c. Created variable debugSkipHardware (non-global) which can be manually set to 1 at the beginning of the program ' to cause all hardware commands to be skipped in a normal sweep, to aid in debugging. That variable is tested ' in [ReadMagnitude], [ReadPhase], and in a couple of places in the main sweep loop. If this is set to 1 we know ' any crash is not being caused by NTPort problems. '7b. Add glitchtime to Variables Window. Minor fixes to calc of data to graph. Change doSpecialGraph=3 ' to generate slightly larger values that convert better to S21, Impedance, etc. Suppress S21 transform ' data unless S21DoTransform=1 as a result of user selection. '7a. Added CalcAutoScale to do axis auto scaling. Fixed bug in uTenPower for negative integral powers. ' Alterations to DetectChanges to handle changes in autoscaling. '6k. Require restart when TG/SG or SpurCheck is changed. ' Altered S21 Setup window. Transform to different connection deleted. Change graph data selection ' to occur in Y axis windows. Changed an instance of 1e20 to 1e7 to avoid LB/NTPort bug. Then created ' constMaxValue=1e7 to use for now in place of 1e7. When we are free of the NTPort bug, 1e15 would be better. '6j. Scotty's changes re window titles and mode names. Print mode in upper left of graph window. ' Fix Load Preferences Dialog window. Hide video filter items in Config Mgr. ' When initializing before loading Prefs.txt, set sweep width to ten times the ' Path 1 bandwidth. '6i. Added routines in utility module relating to impedance calculations and equivalent circuits. ' Added routine in graph module to generate a string containing draw commands for a user-specified ' reference trace. There is not yet a user interface to so specify, and the routine needs some ' more work to allow various types of reference lines. The idea is that perhaps 1 or 2 reference lines ' could be calculated on Restart and then drawn after the grid is drawn, and also when Refreshing. ' DetectChanges needs to be changed to regenerate the reference trace strings when certain things change. '6h. Fixed group delay calculation.Changed routines to do transforms. Created routines to do ' complex uMultiply, uDivide and uInvert. This avoids needing to solve equations to calculate ' the real and imaginary parts separately, which can create bugs, though it is maybe 50% ' more efficient to do them separately. Worked on S21 data transforms. '6g. Add methods to calculate impedance from reflection measurements, or from S21 via a test jig. ' Adds SeriesJigImpedance, ShuntJigImpedance, and S11ToImpedance, and related variables. '6f. Changed Data Window not to cause a halt, and changed some data titles ' TO DO Phase interpolation should not assume any fixed phase range; it should determine ' wrap-around from whether the angle changed more than 180 degrees. ' Added CalcGraphData to allow converting mag, phase into other data, such as linear mag, ' group delay and impedance. Added some related routines to allow user to select the data type ' to graph, which is stored in graphDataType$ and is used to determine dataTransform$, which in ' turn is used in [PlotDataToScreen] to determine what, if any, data to apply. ' TO DO--Need to include graphDataType$ in Sweep Context. '6e. Created refreshXXX flags to control what is redrawn in a Refresh. Created RememberState and DetectChanges ' and related globals (prefixed "prev") to detect changes from user action and from loading contexts, and to ' do any necessary redrawing and specify whether a restart is required. '6d. Cause all trace drawing commands (excluding erase) when in dynamic draw mode to be accumulated in ' gTrace1$() or gTrace2$(). Use those commands to do erasures on the next sweep. ' Created gGetMinMaxPointNum to get the first and last ' point numbers actually graphed. We used to use 1 to gNumPoints, but with reverse sweeps the first graphed ' point is gDynamicSteps+1 and we go down from there. Eliminated gEnableTraceAccum. '6c. Scotty's changes re timing when inverting the PDM, making use of video filter info. '6b. Print videoFilter$ in setup info. Revised accumulation of trace draw commands, which are now saved in ' an array of strings, one per point. This allows retaining all the prior sweep commands until they actually ' get replaced. In One Step, we can now Refresh rather than Redraw, getting much faster response. '6a. Tried creating grid bitmap to use when refreshing the graph, to eliminate the "blink" on refresh. ' The blink in the grid goes away, but the trace blinks more, due to the longer redraw time for the ' grid bitmap as compared to the prior method. The bitmap variable was retained, but the code was commented out. '5q. Added warning about log sweep with freq<=0. Modified Path and Freq cal routines to use the Interpolation ' module to create the initial tables of cubic coefficients. '5p. Added interpolation module. Modify InstallSelectedLineCal to use it. Add Video Filter selection ' items. videoFilter$ will contain Wide, Mid or Narrow. videoFilterCaps(1-3) will contain the ' capacitances (uf) for those filters, now initialized to 0.001, 0.1 and 1 uf. Config manager ' does not yet have boxes to specify the actual values. Fixed bug re axis.DivLab. '5o. Provide for saving/retrieving data, similar to save/go config. Similar buttons are used. The ' data is saved as a Data Context string in savedData$(), numbered 0 thru maxSavedData. Presently, ' the retrieved data is just put into the display for viewing. ' Merged Misc. Setup window into X-axis pref window, and moved invdeg and planeadj boxes to that window. ' After opening X-axis pref window, require restart only if absolutely necessary. '5n. Eliminated use of variable vna to indicate vna mode. Modes are now per 5L. Renamed line cal arrays to ' baseLineCal(), bandLineCal(), and lineCalArray(), the latter being the one used to actually ' apply line cal. Many fixes to OperatingCal-->Perform Cal. Fixes to restore point array contexts. ' Renamed some calibration variables. Many changes are not marked individually. Made Halt marker appear ' on each trace, not on x-axis. '5m. Change Halt Marker to wedge that points in the sweep direction. Eliminate erasure gap on redraw ' after OneStep. Create routines to save/load BaseLineCal file in MSA_Info\OperatingCal. Increased ' uWorkTitle$() to 6 lines to allow more embedded info. First 3 are actual title info, if any. ' Rename fullLineCal as bandLineCal ' Changed data, baseLineCal and bandLineCal contexts to put/retrieve sweep data in line 4 of title, ' and to retrieve date/time stamp data in line 3 of title. ' Resize arrays to 2001 points at start, because there are issues with loading large amounts of data ' stored from other sessions where the arrays may have been larger. TO DO: check this out. If the sweep context ' is restored first, then there should always be enough room. This is a problem only when loading freestanding ' data. ' '5L. Delete invdeg=1 as flag for PDM cal in progress. Use new variable doingPDMCal. Implement gMode$ ' to specify the operating mode in the graph module--SA, ScalarTrans, VectorTrans, Ref or TwoPort. ' These indicate the nature of the data. Also created msaMode$ containing the same info outside the ' graph module, though perhaps gGetMode$() is sufficient. The effects of msaMode$ are not fully implemented. ' Modify marker routines so a marker is only selected in the combo box when necessary. Unnecessary selections ' during scanning make it hard to manually select a marker during a scan. ' Renamed marker routines to start with prefix "m". '5k. Create menu item for PDM Inversion cal, and a dialog to do it. When cal is done, user can ' save the new value (in the program and in the config file), or can cancel, which restores the ' prior value. '5j. Split VNA Cal window into Cal and Ref windows, and revised their layouts. Added PDM cal ' to the VNA Cal window. '5i. Restore title when reading data context. Misc. fixes. In GoConfig, start by [FinishSweeping] ' if in mid-sweep. In GoConfig, we now restore Full Line Cal, so we now do InstallSelectedLineCal. ' We do not save or restore Base Line Cal as part of save/go config. Created routines to ' save/restore Marker contexts. Fixed bug in Config Manager regarding items previously deleted. ' Also save config file after loading it on startup, so it is saved in the current format. ' Expanded number of possible contexts to 30 to be sure we don't reach max. ' Made it possible to save Hardware Context as part of a larger context file, but not to restore ' it as part of such a file. ' Create menu item Save Debug File, that saves all contexts. '5h. Delete variable calfwd, which was replaced by calInProgress and specialOneSweep. Fixes regarding ' routines to save and restore contexts. Add routines to save/restore Base Line Cal context. ' Rename various Line Cal variables as Full Line Cal (e.g. fullLineStartFreq). '5g. Fix glitch regarding existing line cal being applied when doing subsequent line cals. '5f. Implemented the routines called by the previously created dialog. Created global specialOneSweep, ' so we can gosub [Restart] and perform a single sweep, then return to the caller. For calibration, ' it is then not necessary to enter data into cal arrays as the sweep is performed. The data can ' be taken from datatable() after the sweep is done. applyLineCalLevel must first ' be set to zero so as not to apply any cal during the sweep. Likewise, planeadj must be set to 0. '5e. Create [RunVNACal], a dialog to determine which calibrations to apply, and to run calibrations. ' Created global variables to keep track of sweep params at time of calibration, and whether calibration ' is currently valid. Line cal now runs through that dialog. Need to create Baseline cal, which is a general ' purpose line calibration to use when we don't have a current line cal at our current sweep params. ' Also: Move AdjustPhaseToDisplay to graph module ' Also: Create gSweepStart and gSweepEnd in graph module and use them as the bounds of the sweep '5d. Display phase in range specified by user using new [adjustPhaseToDisplay] '5c. In alternate sweeping, ProcessAndPrint the final step immediately, then reverse direction and ' start the next scan with the same point. Fix gInitErase bug. In alternate sweeping, resuming ' would start with point 2 of the reverse sweep '5b. -- '5a. Added alternateSweep to allow alternating sweep direction. Modified DisplayAxisXPreference to let ' user choose forward, backward or alternating. '4n. Draw final point of line by drawing line in reverse. Use "set" for single point histogram column. ' Made sweepDir, sweepStartStep and sweepEndStep non-global for speed. To do this, made UpdateGraphParams ' and InitGraphParams into gosub routines. Reduced erase lead length for small number of points. ' Made Y-axis preference changes active immediately. '4m. Various fixes for sweep direction and fixes to be sure the endpoints of lines ' get drawn. Move line calling [CalPDMinvdeg] to fix PDM cal. '4k. created sweepDir (+1 or -1), sweepStartStep and sweepEndStep to handle reverse sweeps. ' These are use to control the basic sweep loop. Roughly implemented reverse sweep '4j. More fixes to Setup-->Misc regarding SG and TG '4i. Properly initialize and remember items in Setup-->Misc window '4h. Misc. fixes. Some labeled 4g. Deleted sgpreset and directly used sgout instead. '4g. Rearrange GoConfig/SaveConfig to share a common box for the config number. Require Restart after ' GoConfig. '4f. Delete Working Window boxes for halt info. Eliminate instructions that print to boxes ' that no longer exist. Switch Show Variables from button to menu item. Move more items off ' working window. Create ShowButtonsOnGraph and HideButtonsOnGraph to show/hide buttons ' that lie on top of graph, so they can be hidden to copy the image. Draw the Halt marker smaller. ' Finish moving items off Working Window and delete the routines that created it. '4e. Delete DrawThreePointValues, which drew values under first, last and center points. Delete ' calls to DrawPointValue (maybe can delete the routine). Delete message box and create message ' area on graph window, using PrintMessage and new global message$. '4d. When user clicks to place a marker for a histogram, round to nearest point. Also add a Halt ' marker to show info on the point at which a scan halts, unless ended by HaltAtEnd. '4c. Move many of Working Window functions to a new Misc Setup Window. Move Special Tests button ' to a menu item. Add a new "Halt" marker, which automatically appears at the point of the halt ' so point info will be displayed. '4b. Fixes regarding cal module, so increasing max cal points works properly. '4a. Changed buttons for markers so no buttons have to be hidden. Deleted placement of R marker ' with right-click; now must select R marker and place it like any other marker. Right-click ' is reserved for some future action. '3h. Make config file a Hardware Context. Remove preference items ' from config manager. '3g. Added doSpecialRandom to provide a different random number each sweep for [doSpecialGraph]. ' Also changed Working Window title to Control Window, and version to 114. '3f. Changes to initialize variables in Step 3, then load the preferences file, then save it. This creates ' one if it does not exist, in \MSA_Info\MSA_Prefs, and creates that folder if necessary. '3e. Various changes to utilize uTextPointArray$(), an array of strings, as the intermediary when saving ' or restoring contexts. '3d. Changed freq cal so boxes are updated when Enter is invoked. Freq and Measured Power buttons are ' now disabled, so user cannot enter data directly, only via the sweep info. Created calManEnterError ' to enable [calManEnterAll] to abort if an error occurs. '3c. Changes regarding preference file. Created graphBox$ to hold the handle of the current graphics ' box, and changed many commands with global search/replace to use #graphBox$ rather than #handle.g. ' This helps to allow multiple graph boxes when implemented in conjunction with Contexts. '3b. Various changes to cause frequency cal to calculate correction factor as true power minus measured power. ' This was mostly fixing labels, but also true power had to be retrieved from the user boxes at every point. '3a. Create preference file using Contexts. Created SavePreferenceFile and [LoadPreferenceFile]. '2f. Work on Grid and Trace Contexts. Created OpenContextFile$(), SaveContextFile() and LoadContextFile$() ' to save/load multiple contexts to/from a file. '2e. Scotty's changes regarding Spur Test '2d. Made vna part of Sweep Context. Various cleanup to Sweep Contexts, [GoConfig] and [SaveConfig] '2c. Misc. cleanup found while working on context saving. Created SweepContext$, [RestoreSweepContext], ' RestoreSweepContext$ and PrivateRestoreSweepContext$ to save/retrieve sweep context info. These deal ' with variables outside the graph module, and call gSweepContext and gRestoreSweep context to handle the ' variables within the graph module. Also revised gSweepContext$, gRestoreSweepContext$ and made related changes. ' Changed [SaveConfig] and [GoConfig] to use the new routines. Need to make hor and vert divisions part of ' the sweep context rather than grid context. '2b. Eliminated use of doInitHardware and now re-initialize hardware on every [Restart]. '2a. Modified uArrayToFile, uArrayToString$, uArrayFromFile$ and uArrayFromString to develop a ' common method to save/retrieve array data to/from files or strings. Revised [SaveConfig] and [GoConfig] ' to use these. Revised context saving routines in graph module to use them, and also to divide the ' context data into logical parts. The latter is still a work in progress as to non-array data. The ' current context types are Grid (appearance of backgound and labels), Sweep (freq, mag and phase params ' to setup the sweep), Trace (style of the actual traces), Data (the current freq, mag, phase data points), ' and LineCal (the line cal data points). The idea is to be able to save one or more contexts in various ' combinations for different purposes. For example, the Grid, Sweep and Trace contexts can be saved together ' to make a preference file to use on startup. The Sweep and LineCal contexts together make up the current ' "configurations". The Data context can be saved alone to allow recall of a former trace, or it can be saved ' together with Grid, Sweep and Trace contexts to allow complete recreation of the original graph, ' which the user could then graphically modify. The latter could be an item under the Edit and Save menus, ' as an alternative to saving the image as a bitmap. ' Contexts begin with the line "StartContext Name", where name=Grid, Sweep, etc. They end with the line ' "EndContext". This allows any context file to be parsed into the separate contexts, each of which can be ' processed by the appropriate routine. As a result, a single routine would load context files regardless ' of the type of context(s) included. ' Contexts containing array data actually contain an exclamation point before StartContext and EndContext, ' so as to make them "comments" to a Touchstone file reader. Such array data contexts also contain a line with ' "!Points=NNN", where NNN=number of points, followed by a line with the Touchsone "#" options, followed by ' a line with "! MHz S21_Mag S21_Degrees, followed by a series of lines containing each containing a frequency ' and mag and/or phase, space delimited. At the very end is the EndContext line. '1f. Made changes to allow the graph module to keep track of the total sweep steps, in addition to the ' actual number of points currently graphed. '1e. Revised gSetMaxPoints so the number of possible points is never reduced, which ' could cause problems with reading saved large data. '1d. Defined path$ as global '1c. Deleted duplicate global def of vna, centfreq, sweepwidth, sgout, offset,topref, botref '1b. Changes noted as: SEWgraph2 '1a. Changes noted as: SEWgraph and SEWgraph1 '----------Notes to Myself. The following are things I want to do:-------------- 'If Calibration Manager Window is open and we close MSA, we 'need to go close Calibration Manager Window without saving anything. 'I thought we had already done this, check previous versions 'Add buttons to VNA WW. "Use MSA Reference Calibration", ' "Use Line Reference Calibration", "Use No Calibration" 'Change PDM wait time calculation 'During VNA sweep, if the phase bits jump more than xx%, add waittime and mearure again. 'Is it possible to to just reprint secreen in bitmap? At [Halt], delsegement everything, then save screen, then re-write screen 'Re-visit the power rush on DDS 'add a menu item "save Working and Graph Windows" as a text file, containing ALL data for future re-creation 'Possibly, split [CommandAllSlims] into [PreCommandAllSlims]and[CommandAllSlims].SLIM only. 'For Original Control Board, delete option for parallel DDS1. Use Serial, only. 'Change phase data to reflect the scale used in the Graph Window 'Control Sweep using Mouse. 'Interesting:The Text File created by the Menu has the options of "save, save as, open, etc" '-------------Sequence of Main Routine for Original or Slim MSA/TG/VNA--------------- 'Notes: The SLIM MSA (SLIM Control Board) can command all 6 modules at one time (PLO1,DDS1,PLO3,DDS3,PDM,FilterBank). ' However, the FilterBank is commanded independently. So is PLO2. ' The Original MSA (original Control Board) must command the modules independently. '1.Establish User Global variables from external msaconfig.txt '2.Establish hard Global variables '3.Create Working Window, for Spectrum Analyzer Mode, and insert the Default Global Variables '4.measure computer speed and update global, glitchtime '5.Command Filter Bank to Path one ' access the Path 1 Magnitude Calibration Table ' access the MagError vs Freq Calibration Table '6.if configured, initialize DDS3 by reseting to serial mode. Frequency is commanded to zero '7.if configured, initialize PLO3. No frequency command yet. '8.initialize and command PLO2 to proper frequency '9.Initialize PLO 1. No frequency command yet. '10.initialize DDS1 by reseting to serial mode. Frequency is commanded to zero '11.[GrabWorkingWindowData] get info from Working Window and update variables '12.[CreateGraphWindow], using Working Window data '13.Calculate the command information for first step through last step of the sweep and put in arrays '14.[StartSweep]'Begin sweeping from step 0 '15.[CommandThisStep](1.9ms). command relevant Control Board and modules '16.Determine sequence of operations after commanding the modules ' a. if in OneStep mode, then ' add extra settling time ' read data of thisstep. gosub [ReadStep] ' process data of thisstep. gosub [ProcessAndPrint] ' wait here, until the next button push ' b. if ThisStep is the first step after a halt, then ' add extra settling time ' read data of thisstep. gosub [ReadStep] ' goto [Scan] ' c. if ThisStep is not the first step after halt (middle of sweep), then ' process and print the Previous Step. gosub [ProcessAndPrintLastStep](3.8ms) ' [ProcessAndPrint](3.8ms) /1.9 ' [ConvertMagPhaseData](2.5ms) /.53 ' call calConvertMagPhase(1.2ms) ' freqerror=calConvertFreqError(thisfreq)(0.9ms) /.085 ' [CalcMagpowerPixel](0.4ms) ' [PlotDataToScreen](1.3ms) /1.3 ' read data of thisstep. gosub [ReadStep](1.9ms) ' goto [Scan] '17.[Scan] Check to see if a button has been pushed ' If a button was pushed (other than OneStep) goto [Halted] ' If not, continue to [IncrementOneStep] '18.[IncrementOneStep] ' add 1 to the value of thisstep ' if the new value of thisstep exceeds the number of steps in this sweep ' "Glue" the full sweep plot into memory ' go back to [StartSweep] ' if not, go back to [CommandThisStep] and continue sweeping '19.[Halted] ' process and print ThisStep. gosub [ProcessAndPrint] ' reprint Graph lines and text. gosub [PrintGraph] ' "Glue" Graph into memory ' wait for operator action. '--------Start of Code, Main Routine--------- '1.Establish User Global variables from external msaconfig.txt. all of the following are in msaconfig.txt '[EstablishUserVariables] '----Start of global variables set from a configuration file; some depend on construction of the 'spectrum analyzer; others are just convenient defaults that can be changed at runtime.--------- '[EstablishUserVariables] 'all of the following are "default" values and are dependent on the construction of your Spectrum Analyzer global masterclock 'Exact frequency of the Master Clock (in MHz). Example: 64.000056 or 63.999937 'You can start with default configuration and change after calibration. global centfreq 'Sweep center frequency, in MHz. For initial set-up use "0" global sweepwidth 'Sweep width in MHz. For initial set-up use 10 times the BW of Final Xtal Filter 'delver113-7c global wate 'value to "slow" the sweep speed for more accurate data. Use "0" as default. 'delver113-7c global glitchtime 'default=0, causing a self determination at startup. global adconv 'AtoD topology."8" for original 8 bit,"12" for optional 12 bit ladder,"16" for serial 16 bit AtoD, or "22" for serial 12 bit AtoD ver111-36e global topref 'Top magnitude reference line on graph scale, in dBm input to MSA. For initial set-up, use "0" global botref 'Bottom magnitude reference line on scale, in dBm input to MSA. For initial set-up, use "-100" global cb '0= old Control Board, 1= old Control Board with new harness, 2 = SLIM Control Board ver111-22 global dds1parser '0 if DDS 1 is in parallel mode, 1 if serial 'ver111-21."0" not allowed on SLIM Control Board ver111-29 global appxdds1 'nominal DDS1 output frequency (in MHz) that steers PLL 1; . Near 10.7. 'appxdds1 must be the center freq. of DDS1 xtal filter; exact value determined in calibration. global dds1filbw 'DDS1 xtal filter bandwidth (in MHz), at the 3 dB points). global PLL1 'PLL 1 model. Allowed values are 2325, 2326, 2350, 2353, or 4112 global PLL1phasefreq 'approx. Phase Detector Frequency (MHz) for PLL 1. Use .974 when DDS1 filter is 15 KHz wide 'PLL1phasefreq must be less than the following formula: 'PLL1phasefreq < (VCO 1 minimum frequency) x dds1filbw/appxdds1 global PLL1mode '0 = Integer Mode, 1 = Fractional Mode for PLL 1. 'I don't recommend Fractional Mode for PLL 1, although it will work (noiser) global PLL1phasepolarity '1 for non-inverting loop filter1; 0 inverting op amp; enter 0 for SLIM MSA global PLL2 'PLL 2 model. Allowed values are 2325, 2326, 2350, 2353, or 4112, or 0 for SRD multiplier global appxLO2 '2nd LO frequency (MHz). 1024 is nominal, Must be integer multiple of PLL2phasefreq global PLL2phasefreq 'PLL2 phase frequency (MHz). See appxLO2". 4 is nominal global PLL2phasepolarity 'for non-inverting loop filter, enter 1(SLIM MSA); for inverting op amp, enter 0 global TGtop 'Tracking Generator Topology:"0" for not installed, "1" for original Trk Gen, '"2" for New TG (DDS3/PLL3 combination) ver111-18 global PLL3 'PLL 3 model. Allowed values are 2325, 2326, 2350, 2353, or 4112, or 0 for no Trk Gen ' 2350 and 2353 can be used as fractional-N global appxdds3 'nominal DDS3 output frequency (in MHz) that steers PLL 1; Near 10.7. 'appxdds3 must be the center freq. of DDS3 xtal filter; exact value determined in calibration. 'Enter "0" if TGtop = 0(no TG) or 1. The original Trk Gen does not use a DDS3. ver111-17 global dds3filbw 'DDS3 xtal filter bandwidth (in MHz), at the 3 dB points). global PLL3phasepolarity '1 for non-inverting loop filter; 0 for inverting op amp; enter 0 for SLIM MSA global PLL3mode '0 = Integer Mode, 1 = Fractional Mode for PLL 1. 'Enter "1" only if PLL3 = 2350 or 2353. Enter "0" for new DDS3/PLL3 combination (SLIM MSA). global PLL3phasefreq 'TrkGen PLL3 phase frequency (MHz). If TG is DDS3/PLL3 combo, use same technique as PLL1phasefreq 'if Original TG (TGtop=1) then this must be a sub-multiple of both Master Clock and Final Xtal Filter Frequency 'global sgpreset 'delver114-4h global offset 'Enter "0" (Mhz). Default Tracking Generator frequency output, relative to MSA input. ver111-18 global maxpdmout 'bit count for Phase AtoD converter when Phase Det Module output is maximum. ver112-1a 'For SLIM-ADC-16 = 65535, SLIM-ADC-12 = 4095. For the Original Control Board and: '12 Bit Parallel AtoD = 4095, 16 Bit Serial AtoD = 65535, or 8 Bit Parallel AtoD = 255. These are adjustable during calibration global invdeg 'actual phase change when PDM is inverted. Nominally, 180. Enter actual value after calibration. global doingPDMCal '=1 when PDM cal in progress to determine invdeg ver114-5L global CalInvDeg 'set to value of invdeg determined by cal ver114-5L '--SEW End of variables initialized from configuration file '--SEW2 added the following global declarations to make these available to true subroutines 'del13-7c global steps 'whole number of steps per sweep. 1 thru 720 is acceptable. 400 is a good number. 'del13-7c global thisstep 'keeps track of current step number during a sweep global globalPort 'Used to pass new port value back from config routine w/o making port global. ver113.7c 'ver114-5k deleted globalGlitchtime, which was no longer used global globalSteps 'SEWgraph; Number of steps set by user. Set in calcWindoInfo. global version of steps. global varwindow, datawindow '=1 when indicated window is open 'ver114-7n 'SEWgraph added doSpecialGraph global doSpecialGraph '=0 for normal operation; for other values see [doSpecialGraph] global doSpecialRandom 'Random number generated at start of each sweep, for doSpecialGraph ver 114-3g 'del13-7c global port, status, control 'Parallel port addresses global finalfreq, finalbw 'freq and bandwidth of current final filter global hasVNA '=1 if the build includes VNA; otherwise 0 global calManWindHndl$ 'holds handle of open window for calibration manager, or blank if not running global configWindHndl$ 'Handle to our main window SEWcal3 moved to here from cal module 'configFilters is a list of final filters; second dimension 0=freq (MHz), 1=BW (KHz); 'zero entry of first dimension not used dim MSAFilters(40,1) global MSANumFilters 'Number of filters in list dim MSAFiltStrings$(40) 'Same info as MSAFilters(), but freq and bw are combined in a string; zero entry is used '------SEWgraph globals for graph params global firstScan 'Set to 1 for first scan after background grid for graph is drawn 'ver114-4e deleted global graphAppearance$ global graphMarLeft, graphMarRight, graphMarTop, graphMarBot global haltAtEnd 'Flag set to 1 to cause a halt at end of current sweep 'SEWgraph global hasMarkPeakPos, hasMarkPeakNeg, hasMarkL, hasMarkR, hasAnyMark 'Marker flags dim markerIDs$(9) 'IDs of markers, used to fill combo box. marker numbers run from 1 so ID of marker N is markerIDs$(N-1) global selMarkerID$ 'ID of marker selected by user global doGraphMarkers 'Set/cleared by user to show or hide markers on graph global doPeaksBounded '=1 to limit peak search between L and R markers; otherwise 0 global doLRRelativeTo$ 'marker ID of reference marker when L and R are relative to another marker; otherwise blank global doLRRelativeAmount 'db offset when L,R are relative to another marker; otherwise 0 global continueCode 'Checked after "scan" command; 0=continue; 1=halt via [Halted]; 2=immediate wait; 3=restart. global centerStep 'step number for center point of sweep, =int(steps/2) global axisPrefHandle$ 'handle variable for axis preference window; non-blank when window is open global graphBox$ 'handle variable containing handle for current graph box. ver 114-3c global displaySweepTime '=1 to display sweep time in message area 'ver114-4f global interpolateMarkerClicks '=1 to enable placing marker at exact click point; =0 to round to nearest step. ver114-7k 'ver114-4k variables allowing forward or reverse sweep 'The following 2 variables are not global, but are used in connection with reverse sweeps 'sweepDir '+1 for left-right sweep; -1 for right-left sweep 'sweepStartStep, sweepEndStep 'start and end steps for current sweep global alternateSweep '=1 to alternate forward and reverse sweeps; =0 if direction is set by sweepDir ver114-5a global refreshForceRefresh 'Set to 1 to force one-time refresh at end of scan, nothwithstanding value of refreshEachScan ver114-6e global refreshEachScan 'Set/cleared by user to control screen refresh. =1 means refresh each scan. 'ver114-6e added the following flags to control refreshing global refreshForceRefresh 'Forces refresh at end of scan even though refreshEachScan=0 'The following globals determine whether we redraw various components from scratch or by a faster method. global refreshGridDirty 'Forces grid (and labels, title) and setup info to redraw from scratch in RefreshGraphs global refreshTracesDirty 'Forces traces to be redrawn from raw Y1 and Y2 values in RefreshGraph global refreshMarkersDirty 'Forces recalc of marker positions based on their frequency global refreshAutoScale 'Do auto scaling on refresh; also implies refreshRedrawFromScratch ver114-7a global refreshRedrawFromScratch 'Forces complete redraw from scratch in RefreshGraph global doingInitialization 'Set to 1 during startup initialization of context variables; then to 0 ver114-3f global haltsweep 'Set to 1 when scan is running 'global vna ' =1 when we are in vna mode delver114-5n global phadisp, magdisp 'Type of phase and mag graphing. Made global for sub use. global isStickMode ' =1 when phadisp or magdisp are in a "stick" mode global doPhaseTrace, doMagTrace '=1 to graph the corresponding trace (calc from phasdisp, magdisp) ver114-6e global maxConfiguration 'Saved configurations can be numbered 0 through maxConfiguration, for total of maxConfiguration+1 global specialOneSweep '=1 when [Restart] is called to do one sweep and then return, rather than wait. ver 114-5f global msaMode$ '=SA, ScalarTrans, VectorTrans, Ref or TwoPort ver114-5L global autoScaleY1, autoScaleY2 '=1 to autoscale the axes 'ver114-6k added constants to aid in calculating graph data. The calculation is in two steps. First, we 'must calculate a complex number with the necessary info, and then extract or calc a real component to graph global Y1SourceConst, Y1ComponentConst 'data source constant and component constant to determine Y1 graph data global Y2SourceConst, Y2ComponentConst 'data source constant and component constant to determine Y2 graph data 'The following data source constants are used to specify the source data needed to calculate the Y1 or Y2 graph data global constRaw,constLinearMag,constS11,constRefco,constImpedance constRaw=0 'Original MSA data; dBm or db/angle constLinearMag=1 'Original data with mag made linear constS11=2 'S11; either original data or calc from S21 for two-terminal DUTs constRefco=3 'S11 with linear mag constImpedance=4 'Impedance (R,X) calc from S11 or S21(two-terminal DUTS) 'The following component constants are used to specify the data component needed to graph global constMagDBM,constMagWatts,constMagDB,constMagRatio,constMagV global constRho,constAngle,constTheta,constGD,constReact global constSerR,constSerC,constSerL,constParR,constParC,constParL constMagDBM=0 'Magnitude dBM constMagWatts=1 'Magnitude watts (linear) constMagDB=2 'Magnitude dB constMagRatio=3 'Magnitude ratio (linear) constMagV=4 'Magnitude volts (linear) constRho=5 'Rho for refco constAngle=6 'Angle constTheta=7 'Theta for refco constGD=8 'Group Delay constReact=9 'Series Reactance 'RLC components have values from 20-25 to make it easy to test for them as a group constSerR=20 'Series Resistance constSerC=21 'Equiv series capacitance constSerL=22 'Equiv series inductance constParR=23 'Equiv parallel resistance constParC=24 'Equiv parallel capacitance constParL=25 'Equiv parallel inductance 'SEWgraph; The following hold parameters used to perform filter analysis when requested by the user global doFilterAnalysis '=1 to perform filter analysis; 0 otherwise SEWgraph global x1DBDown, x2DBDown 'positive db values for x1 and x2 points SEWgraph global filterPeakMarkID$ 'Marker that indicates filter peak 'SEWgraph The following are used to manage a "working array" in the Utilities Module. This array is used for very 'temporary processing to deal with the fact that in LB you can't pass arrays as arguments. So some routines, 'such as saving/retrieving data points to/from strings or files, utilize this specific array. The user is 'responsible for transferring data in and out of this array. Data can't be left in the array for long, because 'another operation might utilize the array. dim uWorkArray(800,8) 'Initially 800 points with up to 9 (0...8) data items per point global uWorkMaxPoints, uWorkNumPoints 'max points and actual used points in uWorkArray global uWorkMaxPerPoint, uWorkNumPerPoint 'max and actual number of data items per entry of uWorkArray dim uWorkFormats$(8) 'Format strings for each data item, in form suitable for "using" function, 'or blank to cause str$() function to be used. global maxNumSteps 'Absolute max number of steps allowed for sweep or in arrays of points (num points=num steps+1) ver114-3e maxNumSteps=40000 'ver114-3e maxPointExtraLines=100 'max lines in a file or string with point data, not including the numeric point data itself ver 114-3e dim uWorkTitle$(6) 'Title info extracted when processing uTextPointArray$; 0 not used ver114-3e; ver114-5m increased to 6 dim uTextPointArray$(maxNumSteps+maxPointExtraLines+5) 'Array of points as string; used as short-term 'intermediary in saving/retrieving arrays of points ver114-3e dim contextTypes(30) 'Used in connection with save and retrieve context files 'indicating which contexts are involved ver114-3a 'Additional variables that need to be available to subroutines 'ver114-1c deleted duplicate global def of vna, centfreq, sweepwidth, sgout, offset global startfreq, endfreq, wate, planeadj 'ver114-7n deleted stepfreq global sgout 'ver114-4h sgout turned out not to be a duplicate global topphase, botphase 'SEWgraph deleted centphase, which was not being used global test 'SEWgraph Contents get printed to message box on halt global spurcheck '=1 to turn spur test on 'ver114-4f global gentrk, normrev 'ver114-4c global path$ 'Currently active filter path (1...); a number as a string in form "Path N" ver114-1d dim fileInfo$(1,1) 'array for use with Files() command ver114-3f global message$ 'Message to print in graph window global varwindow '=1 if variables window is open ver114-7k global suppressPDMInversion '=1 to suppress inversion in [ReadStep] ver114-7k global leftstep 'Used to hold a marker step number for [preupdatevar] ver114-7k 'Variables for saving/restoring context files via gosub routines, where these are used as parameters global restoreFileName$, restoreContext$, restoreIsValidation, restoreErr$ global videoFilter$ 'Selected video filter: Wide, Mid or Narrow 'ver114-5p dim videoFilterCaps(3) 'Capacitance(uf) for Wide(1), Mid(2) and Narrow(3) video filters 'ver114-5p 'Globals used to remember state info to allow detection of user changes; added by ver114-6e 'See RememberState and DetectChanges global prevMSAMode$ 'This is also set whenever the mode is changed by ChangeMode or the routines it calls global prevPath$ 'Filter path. ver114-7j global prevStartF, prevEndF global prevXIsLinear, prevY1IsLinear, prevY2IsLinear global prevSteps, prevSweepDir, prevAlternate global prevStartY1, prevEndY1 global prevStartY2, prevEndY2 global prevHorDiv, prevVertDiv global prevPhaDisp,prevMagDisp global prevGenTrk, prevSpurCheck 'ver114-6k global prevTGOff, prevSGFreq 'ver114-7j global prevPlaneAdj 'ver114-7f global prevY1SourceConst, prevY1ComponentConst, prevY2SourceConst, prevY2ComponentConst global prevAutoScaleY1, prevAutoScaleY2 'ver114-7a global prevDataChanged 'This must be set to 1 when data is loaded from a context global prevS21JigAttach$ '"Series" or "Shunt" to indicate the Transmission jig used ver114-6k global prevS21JigR0, prevS21GraphR0 'Source and load impedances of Transmission global prevS21DoTransform '=1 to transform S21 per jig when graphing global prevS11BridgeR0, prevS11GraphR0 'Bridge reference and graph reference for S11 'ver114-6k 'ver114-5e added these cal items. Full Line cal is a calibration of through response with the current sweep settings. 'Baseline cal is a cal of through response with a generic wideband sweep. 'desiredLineCalLevel is the user-specified level. applyLineCalLevel is the level we are actually applying global desiredLineCalLevel, applyLineCalLevel '2=bandLineCal (if exists); 1=BaseLineCal(if exists); 0=None 'Following are Full Line cal sweep params ver114-5e global bandLineStartFreq, bandLineEndFreq, bandLineNumSteps, bandLineLinear, bandLinePath$, bandLineTimeStamp$ global baseLineS21JigAttach$, bandLineS21JigAttach$ 'S21JigAttach$ for applicable cal 'ver114-7L global baseLineS21JigR0, bandLineS21JigR0 'S21 jig R0 for applicable cal ver114-7L 'Following are Base Line cal sweep params ver114-5e global baseLineStartFreq, baseLineEndFreq, baseLineNumSteps, baseLineLinear, baseLinePath$, baseLineTimeStamp$ 'Following are sweep params at which Base Line Cal was last installed ver114-5f global installedBaseLineStartFreq, installedBaseLineEndFreq, installedBaseLineNumSteps global installedBaseLineLinear 'ver114-7L deleted installedBaseLinePath$ 'Impedance can be measured via S21 in a test jig, or via S11 in a reflection bridge 'We need to know the reference impedance (a resistance) of each, and for the jig 'we need to know if the DUT is in series, or shunted to ground 'ver114-6g added these global S21JigAttach$ '"Series" or "Shunt" to indicate the Transmission jig used ver114-6k global S21JigR0, S21GraphR0 'Source and load impedances of Transmission global S21DoTransform '=1 to transform S21 per jig when graphing global S11BridgeR0, S11GraphR0 'Bridge reference and graph reference for S11 'ver114-6k 'ver114-7f added these dialog variables global DialogCancelled, DialogRLCConnect$ 'Used to pass values to/from some dialogs global DialogRValue, DialogLValue, DialogCValue 'Used to pass values to/from some dialogs global DialogR0Value, DialogDelayValue 'Used to pass values to/from some dialogs global referenceLineSpec$, referenceLineType 'Spec and type of reference line ver114-7f 'type: 0=none; 1=use data when ref was selected; 2=use RLC in spec global referenceTrace 'which ref lines to do 0=none; 1=Y1, 2=Y2; 3=both ver114-7f global referenceSourceNumPoints 'Number of valid points in referenceSource() dim referenceSource(800,2) 'freq, db and angle of source data for reference lines ver114-7f dim referenceTransform(800,2) 'Actual graph data for reference lines ver114-7f global referenceColor1$, referenceWidth1,referenceColor2$, referenceWidth2 'Reference Trace color and width 'calInProgress 'variable set to 1 before starting a cal sweep, then to 0 when done 'ver114-6b moved the following dim statements here 'SEWgraph; the following arrays may be expanded in ResizeArrays to accomodate more steps 'SEWgraph Pixel values are no longer kept in these arrays, so references to thispointx, thispointmag, thispointphase, 'oldmagpixwl and oldphapixel should be ignored. Eventually, the arrays could be compacted to eliminate those unused slots. global constMaxValue constMaxValue=1e7 'Max value for RLC components and certain calculations.1e15 is preferable, but crashes LB with NTPort. ver114-6k maxConfiguration=20 'SEWgraph dim datatable(800,3) 'data from most current sweep, (0)thisstep,(1)thisfreq,(2)processed magpower,(3)processed phase dim magarray(800,3) 'magni pixels for each step#: (0)thispointx, (1)oldmagpixel,(2)thispointmag(3)magdata dim phaarray(800,4) '(0)pdmcmd; phase pixels for each step#:(1)oldphapixel,(2)thispointphase,(3)phadata,(4)pdmread ver111-39d dim lineCalArray(800,2) 'calibration data for each step#: (0)notused,(1)magpower during cal,(2)phaseofpdm during cal dim bandLineCal(800,2) 'Bandsweep line calibration data; transferred to lineCalArray when needed ver 114-5f dim baseLineCal(800,2) 'Baseline line calibration data; transferred to lineCalArray when needed ver 114-5f dim PLL1array(800,48) '(0-23)N23thruN0,(24-39)notused,(40)pdf1,(43)LO1freq,(45)ncounter,(46)Fcounter,(47)Acounter,(48)Bcounter. ver111-30a dim PLL3array(800,48) '(0-23)N23thruN0,(24-39)notused,(40)pdf3,(43)LO3freq,(45)ncounter,(46)Fcounter,(47)Acounter,(48)Bcounter. ver111-30a dim DDS1array(800,46) '(0-39)sw0-sw39,(40-44)w0-w4,(45)base,(46)actualdds1output dim DDS3array(800,46) '(0-39)sw0-sw39,(40-44)w0-w4,(45)base,(46)actualdds3output dim freqCorrection(800) 'freq correction factors for frequency of each step in current sweep 'ver114-2d combined config arrays into one, and deleted configarray dim savedConfig$(maxConfiguration,3) 'saved info for configurations ver114-2d; renamed ver114-3e 'second dimen: 0=sweep context; 1=data context; 2=band line cal context; 3=band OSL context dim cmdallarray(800,39) '(0-15)DDS1+DDS3, (16-39)PLL1+DDS1+PLL3+DDS3 '---------------END OF VARIABLES DECLARATIONS------- nomainwin interpolateMarkerClicks=0 'Note user has no way to change this ver114-7k steps = 400 globalSteps=400 'SEWgraph call gSetNumDynamicSteps steps 'ver114-1f graphBox$="" 'ver114-7h markerIDs$(0)="1" : markerIDs$(1)="2" : markerIDs$(2)="3" : markerIDs$(3)="4" 'SEWgraph markerIDs$(4)="5" : markerIDs$(5)="6" : markerIDs$(6)="L" : markerIDs$(7)="R" 'SEWgraph markerIDs$(8)="P+" : markerIDs$(9)="P-" 'SEWgraph '-------Initialize Modules--------- call uInitFirstUse 'Initialize Utilities Module call configInitFirstUse 'Initialize Configuration Module '----------------Load Configuration File--------- if configFileExists()=0 then dum=configRunManager(1) 'Lets user enter configuration data, and saves to file '1 signals we are running on startup so no cancellation is allowed else errStr$=configLoadData$() 'Initializes the configuration globals from the configuration file if errStr$<>"" then 'errStr$ is blank if no error occurred; otherwise it describes the error notice "Configuration File Error; "+errStr$;"; Default values used" call configInitializeDefaults 'Load default values because of file error else call configSaveFile 'Save config file in current format ver114-5i end if end if 'Convert Configuration Globals into Locals port=globalPort 'SEW5 add ver113-7c glitchtime=0 'SEW5 add ver113-7c; ver114-5k deleted globalGlitchtime status=port+1 'SEW5 add ver113-7c control=port+2 'SEW5 add ver113-7c call SetCenterSpanFreq centfreq, sweepwidth 'SEWgraph Set related variables from these two, which were part of config file 'The following was moved here by ver114-7k so that hasVNA is set first call calInitFirstUse 201, 1001, hasVNA 'Initialize Mag/Freq Calibration Module--201 max mag cal points; 1001 max freq cal points ver114-4b 'ResizeArrays needs TGtop, so we do it after loading config file call ResizeArrays 2001 'Make all arrays big enough for 2001 points; also loads BaseLineCal file 'ver114-5m '---------Load path and freq calibration info------ call calInstallFile 0 'Loads frequency calibration file; creates one if necessary for i=MSANumFilters to 1 step -1 'For each filter, create the file if necessary and load it 'Each one loaded replaces the data from the previous one. We are just 'trying to be sure they exist and are OK. 'We do this in reverse order to path 1 will be the last one and stays in place 'This also sets finalfreq and finalbw call calInstallFile i next i path$="Path 1" 'Note physical selection of filter 1 is done in step 5 below for i=1 to MSANumFilters 'For each filter, combine freq and bw into nicely aligned string. Used to load #main.FiltList 'cngver113-7c MSAFiltStrings$(i-1)=configFormatFilter$(MSAFilters(i,0), MSAFilters(i,1)) MSAFiltStrings$(i-1)="P"+str$(i)+" "+configFormatFilter$(MSAFilters(i,0), MSAFilters(i,1)) 'ver113-7c next i '---------Create OperatingCal Folder------------- if TGtop>0 then isErr=CreateOperatingCalFolder() 'Create OperatingCal folder if it does not exist if isErr then notice "Unable to create OperatingCal folder." end if '--Normally, nothing below this line will ever need changing----- '2.Establish hard Global variables 'the following lines of code are operations and will not be changed by the user unless 'a different type of Control Board is used. contclear = 11 'global to take all LPT control lines low STRB = 10 'global to take LPT-pin 1 high. (Strobe line,STRB)(was fqud) ver111-22 AUTO = 9 'global to take LPT-pin 14 high. (Auto Feed line,AUTO)(was wclk) ver111-22 INIT = 15 'global to take LPT-pin 16 high. (Init Printer line,INIT)(was enat) ver111-22 SELT = 3 'global to take LPT-pin 17 high. (Select In line,SELT)(was enap) ver111-22 INITSELT = 7 'global to take both LPT-pins 16 & 17 high. (INIT,SELT)(was enapt) ver111-22 STRBAUTO = 8 'global to take both LPT-pins 1 & 14 high. (FQUD,WCLK)(was wclkfqud) ver111-22 if cb=0 then le1=4:le2=8:le3=16:fqud1=STRB:fqud3=2 'ver111-31b if cb=1 then le1=1:le2=1:le3=4:fqud1=2:fqud3=8 'ver111-31b if cb=2 then le1=1:le2=16:le3=4:fqud1=2:fqud3=8 'ver111-31b if adconv = 8 then pdmlowlim = 51 : pdmhighlim = 205 'establish boundries for 8 bit parallel A to D ver111-36f if adconv = 12 then pdmlowlim = 819 : pdmhighlim = 3277 'establish boundries for 12 bit parallel A to D ver111-36f if adconv = 16 then pdmlowlim = 13107 : pdmhighlim = 52429 'establish boundries for 16 bit serial A to D ver111-36f if adconv = 22 then pdmlowlim = 819 : pdmhighlim = 3277 'establish boundries for 12 bit serial A to D ver111-37a '3.Initialize for whatever mode we will start up in 'Some of these initializations may be changed when the preferences file 'is loaded in [LoadContextFile] doingInitialization=1 'ver114-3f message$="" 'ver114-7g phadisp=0 : magdisp=1 'ver114-6f planeadj=0 'ver114-4i gentrk=0 : normrev=0 : sweepDir=1 'ver 114-4k refreshEachScan=1 'ver114-3f call SelectVideoFilter "Wide" 'ver114-5p 'ver114-3f moved the call to gInitFirstUse here from [CreateGraphWindow] graphMarLeft=70 : graphMarRight=180 : graphMarTop=55 : graphMarBot=140 'Graph margins from edge of graphicbox ver114-7n restored this initialGraphWindowHeight=600 : initialGraphWindowWidth=800 gosub [FindClientOffsets] 'set clientWidthOffset and clientHeightOffset from test window ver114-7q 'initial client height and width offsets are guessed at; they are calculated accurately when 'a graph window has been opened. 'clientHeightOffset=46 'client area is this much shorter than window height ver114-7o 'clientWidthOffset=6 'ver114-7o graphBoxHeight=initialGraphWindowHeight-clientHeightOffset-44 'ver114-7o graphBoxWidth=initialGraphWindowWidth-clientWidthOffset 'ver114-7o call gInitFirstUse "#handle.g", graphBoxWidth, graphBoxHeight, graphMarLeft, graphMarRight, _ graphMarTop, graphMarBot 'SEWgraph Initialize graphing module gosub [InitGraphParams] 'SEWgraph 'Initialize parameters to set up the graphing module ver114-3f moved prevMSAMode$="" : msaMode$="SA" 'ver114-7f gosub [ChangeMode] 'create Graph Window in mode of msaMode$ desiredLineCalLevel=0 'Desire no cal ver114-6b applyLineCalLevel=0 bandLineNumSteps=-1 'Indicate cal does not exist ver114-5f; baseLine cal was handled above ver114-5m call ClearCalarray gMaxNumPoints()-1 'Clear existing line cal data ver 114-5L 'Defaults are now in place. Read the preferences file and save it. If there is no preference file 'this has the effect of creating one with the default values. If there is one, saving it updates a 'possibly old preferences file to the current format. 'ver114-3f added instructions to load and save preference file restoreFileName$=DefaultDir$+"\MSA_Info\MSA_Prefs\Prefs.txt" 'tells [LoadContextFile] what to load gosub [LoadContextFile] 'Loads Preference file if restoreErr$<>"" then 'ver114-7p modified this 'Error. If error was that file does not exist at all, that is OK; we'll create one fileHndl$=OpenContextFile$(restoreFileName$,"IN") if fileHndl$<>"" then 'A file exists and it is bad close #fileHndl$ notice "Error in Preference File: ";restoreErr$ 'ver114-7n end if end if 'If we are still in SA mode, then the graph window has not been created a second time, 'so some controls may be misplaced because the original guess of clientHeightOffset was wrong call SavePreferenceFile restoreFileName$ 'Save Preference file in current format 'ver114-6f moved the call to InitGraphParams after the prefs have been loaded call mClearMarkers 'SEWgraph 'Clear all graph markers 'ver114-3c moved some lines from step 3 into InitGraphParams '4.measure computer speed and update global, glitchtime 'Determine speed of computer 'ver111-37c if glitchtime = 0 then gosub [AutoGlitchtime] 'ver111-37c 'return with glitchtime, number approximates 1 millisecond of computer processing speed with Liberty Basic 'this is a "coarse" calculation. 'ver114-4f moved printing of glitchtime to a later point '5.Command Filter Bank to Path one [InitializeHardware] 'Label added by SEWgraph1 out port, 0 'begin with all data lines low if cb = 2 then out control, 4 'latch "0" into all SLIM Control Board Buffers'ver113-2b out control, contclear 'begin with all control lines low 'the following are meaningless values to guarantee first time commanding. Used in subroutine, [DetermineModule] lastdds1output = appxdds1:lastdds3output = appxdds3:lastpdmstate = 2 'ver111-28 lastncounter1 = 0 : lastncounter3 = 0 'to guarantee Original MSA will command PLL's after init. ver114-6c 'Initialize Final Filter path to Path 1 (1 of 4). This is an optional hardware addition to the MSA 'ver111-29: no final filter bank module has been released. 'However, assume these are the command schemes for the filters: '4 bank, using A0 and A1, and a latch line A2. To be used with original Control Board or SLIM Control Board '4 bank, using A0 and A1, with no latch line. To be used with SLIM Control Board, only. 'The SLIM Control Board can support an 8 bank, using A0,A1,A2 as control, with no latching capability 'delver113-6c A1=0 : A0=0 : path$ = "Path 1" 'default Filter Bank to path 1. ver113-6a 'delver113-6c gosub [CommandFilter]'ver111-29 'delver113-6c gosub [CalTablePath1] 'ver111-39a 'SEW added next two lines, which implement the above comments and also replace 'the call to button1, which is gone. 'A1=0 : A0=0 : path$ = "Path 1" 'default Filter Bank to path 1. ver113-7 delVer114-2c to keep current filter gosub [CommandFilter]'ver113-7 'SEW deleted comment about Path 1 cal variables being in calpwrX... Those are gone 'InitializeTrkGen, if installed '6.if configured, initialize DDS3 by reseting to serial mode. Frequency is commanded to zero if TGtop = 0 then goto [endInitializeTrkGen]' there is no Tracking Generator ver111-22 'Initialize DDS 3 if cb = 0 and TGtop = 2 then Jcontrol = INIT:swclk = 32:sfqud = 2:gosub [ResetDDS3ser] 'ver111-7 '[ResetDDS3ser]needs:port,control,Jcontrol,swclk,sfqud,contclear ; resets DDS3 into Serial mode if cb = 2 then gosub [ResetDDS3serSLIM] 'ver111-29 '7.if configured, initialize PLO3. No frequency command yet. 'Initialize PLL 3. 'CreatePLL3R,CommandPLL3R appxpdf=PLL3phasefreq 'ver111-4 if TGtop = 1 then reference=masterclock 'ver111-4 if TGtop = 2 then reference=appxdds3 'ver111-4 gosub [CreateRcounter]'needs:reference,appxpdf ; creates:rcounter 'ver111-14 rcounter3=rcounter : pdf3=pdf 'ver111-7 'CommandPLL3R and Init Buffers datavalue = 8:levalue = 4 'PLL3 data and le bit values ver111-28 gosub [CommandPLL3R]'needs:PLL3mode,PLL3phasepolarity,INIT,PLL3 ; Initializes and commands PLL3 R Buffer(s) 'ver111-7 [endInitializeTrkGen] '8.initialize and command PLO2 to proper frequency 'CreatePLL2R appxpdf=PLL2phasefreq 'ver111-4 reference=masterclock 'ver111-4 gosub [CreateRcounter]'needed:reference,appxpdf ; creates:rcounter,pdf 'ver111-14 rcounter2 = rcounter 'ver111-7 pdf2 = pdf 'actual phase detector frequency of PLL 2 'ver111-7 'CommandPLL2R and Init Buffers datavalue = 16: levalue = 16 'PLL2 data and le bit values ver111-28 gosub [CommandPLL2R]'needs:PLL2phasepolarity,SELT,PLL2 ; Initializes and commands PLL2 R Buffer(s) 'CreatePLL2N appxVCO = appxLO2 : reference = masterclock gosub [CreateIntegerNcounter]'needs:appxVCO,reference,rcounter ; creates:ncounter,fcounter(0) ncounter2 = ncounter:fcounter2 = fcounter gosub [CreatePLL2N]'needs:ncounter,fcounter,PLL2 ; returns with Bcounter,Acounter, and N Bits N0-N23 Bcounter2=Bcounter: Acounter2=Acounter LO2=((Bcounter*preselector)+Acounter+(fcounter/16))*pdf2 'actual LO2 frequency 'CommandPLL2N Jcontrol = SELT : LEPLL = 8 datavalue = 16: levalue = 16 'PLL2 data and le bit values ver111-28 gosub [CommandPLL]'needs:N23-N0,control,Jcontrol,port,contclear,LEPLL ; commands N23-N0,old ControlBoard ver111-5 '9.Initialize PLO 1. No frequency command yet. '[InitializePLL1]'set PLL1 to proper Rcount and initialize ' appxpdf=PLL1phasefreq 'ver111-4 ' reference=appxdds1 'ver111-4 ' gosub [CreateRcounter]'needed:reference,appxpdf ; creates:rcounter,pdf 'ver111-4 ' rcounter1 = rcounter 'ver111-4 'Create rcounter1 ver114-2e rcounter1=int(appxdds1/PLL1phasefreq) 'ver114-2e if (appxdds1/PLL1phasefreq) - rcounter1 >= 0.5 then rcounter1 = rcounter1 + 1 'rounds off rcounter ver114-2e if spurcheck=1 and PLL1mode=0 then rcounter1 = rcounter1 +1 'only do this for IntegerN PLL ver114-2e 'CommandPLL1R and Init Buffers datavalue = 2: levalue = 1 'PLL1 data and le bit values ver111-28 gosub [CommandPLL1R]'needs:rcounter1,PLL1mode,PLL1phasepolarity,SELT,PLL1 ; Initializes and commands PLL1 R Buffer(s) '10.initialize DDS1 by reseting. Frequency is commanded to zero 'It should power up in parallel mode, but could power up in a bogus condition. if cb = 0 and dds1parser = 0 then gosub [ResetDDS1par]'(Orig Control)'needs:control,STRBAUTO,contclear ; resets DDS1 on J5, parallel ver111-21 if cb = 0 and dds1parser = 1 then gosub [ResetDDS1ser]'(Orig Control)'needed:control,AUTO,STRB,contclear ; resets DDS1 on J5, into serial mode ver111-21 if cb = 2 then gosub [ResetDDS1serSLIM]'reset serial DDS1 without disturbing Filter Bank or PDM 'ver111-29 'SEWgraph Renamed GrabWorkingWindowData, which was and is just a label for the initialization 'for a series of scans based on current window parameters. '[BeginScanSeries] is currently accessed by goto and ends with a wait. It ends at [EndSweepSeries]. 'It can easily be changed to a subroutine '11.[BeginScanSeries] get info from windows and update variables [BeginScanSeries] 'Start a new series of scans 'doInitHardware=0 'Turn off hardware initialization flag 'delVer114-2b 'gosub [calcWindowInfo] delver114-4d since the Working Window is gone 'If calibrating then signal to halt at the end of the sweep; otherwise clear haltAtEnd if specialOneSweep then haltAtEnd=1 else haltAtEnd=0 'ver114-5f 'SEWgraph Creation of graph window moved to step 3 as a one-time initialization 'Step 12 is now initialization of that new window, or of the window as left from the 'previous scan. '12.[InitializeGraphModule] suppressPDMInversion=0 'ver114-7k gosub [UpdateGraphParams] 'SEWgraph Update graph module for any changes made by the user firstScan=1 'Signal that the next scan is the first after Restart 'ver114-5f moved some items to UpdateGraphParams call gInitDynamicDraw 'ver114-6e deleted parameters call ImplementPhaMagDisp if calInProgress=0 then call InstallSelectedLineCal 'ver114-5f Note x values must be calculated first (in [UpdateGraphParams]) ; modVer114-5g xLin=gGetXIsLinear() 'Returns 1 if sweep is linear if xLin=1 then centerStep=int(steps/2) else centerStep=-1 'center step number, for labeling; don't label if log sweep 'SEWgraph end initialization call gSetTitleLine 3, date$("mm/dd/yy"); "; ";time$() 'SEWgraph Put date and time in line 3 of title if gGetXIsLinear() then call gSetTitleLine 4, "Linear Sweep ";path$ _ else call gSetTitleLine 4, "Log Sweep ";path$ 'Save linear/log and path info ver114-5m call gDrawGrid 'SEWgraph; Clear graphics area and draw the background grid and labels call DrawSetupInfo 'SEWgraph Draw info describing the sweep setup #graphBox$, "flush" 'Make the setup info sticks useExpeditedDraw=gCanUseExpeditedDraw() 'SEWgraph; For normal SA use, [gDrawSingleTrace] will be used. 'ver114-7g deleted printing of glitchtime doingInitialization=0 'We are done with initialization on startup 'ver114-4g moved if calInProgress=1 then 'ver114-5g message$="Calibration in progress." : call PrintMessage 'ver114-4g else message$="" : call PrintMessage 'ver114-4f end if '13.Calculate the command information for first step through last step of the sweep and put in arrays gosub [CalculateAllStepsForLO1Synth] 'ver111-18 if TGtop > 0 then gosub [CalculateAllStepsForLO3Synth] 'ver111-18 gosub [CreateCmdAllArray] 'ver111-31b call CalcFreqCorrection 'Calculate power correction at each frequency SEWgraph1 continueCode=0 'SEWgraph Set to other values by subroutines to cause halt, wait or restart '14.[StartSweep]'Begin sweeping from step 0 'SEW StartSweep begins the outer loop that repeats the entire scan process until halted. 'SEW The scan loop continues until a user action which aborts the scan, or in the case of 'SEW OneStep it continues only for a single point. scanResumed=0 'used to indicate whether we start with a new scan(0) or resume where we left off(1)SEW 'ver114-6e Normally, refresh will occur at end of scan only if halted or refreshEachScan=1, 'and will be done by expedited methods. But if the user makes certain changes, the following 'variables are used to force more extensive redrawing. call mDeleteMarker "Halt" 'ver114-4h moved the -4d version suppressSweepTime=1 'to suppress it for the first scan ver114-4h [StartSweep]'enters from above, or [IncrementOneStep]or[FocusKeyBox]([OneStep][Continue]) if scanResumed=1 then 'Perform same increment as [IncrementOneStep] if we are resuming 'For a resumed scan, a halt occurred after the previous step and that step was fully processed. 'haltsweep will equal 0. If alternateSweep=0 and the halt occurred at the end of a sweep, we need to 'repeat the last point as the first point of the new sweep. call mDeleteMarker "Halt" 'ver114-4h moved the -4d version if thisstep = sweepStartStep and syncsweep = 1 then gosub [SyncSweep] 'ver112-2b; ver114-4k 'ver114-5a modified the following if alternateSweep=0 or haltWasAtEnd=0 then 'ver114-5c Go to next step unless we need to repeat this one if sweepDir=1 then if thisstepsweepEndStep then thisstep = thisstep - 1 else thisstep=sweepStartStep end if end if else 'ver114-5c No longer need to retest scanResumed thisstep=sweepStartStep 'ver114-4k end if scanResumed=0 'Reset flag if displaySweepTime then 'ver114-4f currTime=Time$("ms") message$= "Sweep Time=";using("####.##", (currTime-startTime)/1000);" sec." if suppressSweepTime=0 then call PrintMessage 'ver114-4h suppressSweepTime=0 'Only suppress on first scan 'ver114-4h startTime=currTime 'SEWgraph timer for testing end if '15.[CommandThisStep]. command relevant Control Board and modules 'SEW CommandThisStep begins the inner loop that moves from step to step to complete a single 'SEW scan.This branch label is accessed only from the end of the loop. [CommandThisStep]'needs:thisstep ; commands PLL1,DDS1,PLL3,DDS3,PDM 'ver111-7 'a. first, check to see if any or all the 5 module commands are necessary [DetermineModule] 'b. calculate how much delay is needed for each module[DetermineModule], but use only the largest one[WaitStatement]. 'c. send individual data, clocks, and latch commands that are necessary for[CommandOrigCB] 'or for SLIM, use [CommandAllSlims] for commanding concurrently 'ver111-31c gosub [DetermineModule] 'determine which, if any, module needs commanding. ver111-27 cmdneeded = glitchp1 + glitchd1 + glitchp3 + glitchd3 + glitchpdm 'ver111-38a if cmdneeded > 0 and cb = 0 then gosub [CommandOrigCB]'old Control (150 usec, 0 SW) 'ver111-28ver111-38a 'if cb = 1 then gosub [CommandRevB]'old Control looking like SLIM 'not created yet if cmdneeded > 0 and cb = 2 then gosub [CommandAllSlims]'ver111-38a '16.Determine sequence of operations after commanding the modules 'ver114-4m moved the following line to here 'if invdeg = 1 then gosub [CalPDMinvdeg] : wait 'delver114-5L if onestep = 1 then 'in the One Step mode glitchhlt = 10 'add extra settling time gosub [ReadStep] 'read this step gosub [ProcessAndPrint] 'process and print this step call DisplayButtonsForHalted 'ver114-4f replaced call to [UpdateBoxes] call mAddMarker "Halt", thisstep+1, "1" 'ver114-4d 'If marker is shown on graph, we need to redraw the whole graph 'Otherwise just redraw the marker info if doGraphMarkers then call RefreshGraph 0 else call mDrawMarkerInfo 'No erasure gap in redraw ver114-5m if thisstep=sweepEndStep then 'Note reversal is after graph is redrawn if alternateSweep then gosub [ReverseSweepDirection] 'ver114-4m; ver114-5e haltWasAtEnd=1 'ver114-5c else haltWasAtEnd=0 'ver114-5c end if wait 'wait here for next button push ver113-6d end if if haltsweep = 0 then 'in first step after a Halt haltsweep = 1 'change flag to say we are not in first step after a Halt, for future steps glitchhlt = 10 'add extra settling time gosub [ReadStep] 'read this step 'ver113-6d else 'if neither, then in middle of sweep. process and print the previous step, then read this step gosub [ProcessAndPrintLastStep] gosub [ReadStep]'read this step 'ver113-6d end if '17.[Scan] Check to see if a button has been pushed 'SEWgraph Note that on any user action, if haltsweep=1 the action must have been detected 'during the following "scan". But if haltsweep=0 the action occurred during a wait state. 'Exception: Window resizing is detected when it happens, not during "scan". [Scan] 'ver113-6d scan 'check for any button push and go there. ver111-26 'otherwise, continue sweeping. [PostScan] 'SEWgraph. Label is used to return here after a button action handled by a [xyz] routine. When 'all have been converted to true subroutines, just an exit sub will do the job 'and we won't need this label. 'SEWgraph Note: after a button handler in the form of a true subroutine, control will exit sub back 'to this point. We do not want a "wait" to occur in such a subroutine, because that will suspend 'control in a non-global namespace, and the user will be unable to take actions that require access 'to [xyz] routines. To cause a halt, wait or restart in such a subroutine, the subroutine should set 'the global variable continueCode to 1, 2 or 3. if continueCode<>0 then 'SEWgraph created this if... block; =0 means continue normally if continueCode=1 then continueCode=0 : goto [Halted] '=1 means halt immediately if continueCode=2 then continueCode=0 : haltsweep=0 : wait '=2 means wait immediately continueCode=0 : haltsweep=0 : goto [Restart] 'Anything else means restart end if '18.[IncrementOneStep] 'SEW IncrementOneStep is the end of both the inner loop over points and the outer loop 'SEW over scans. goto [CommandThisStep] continues the inner loop with the next point. 'SEW goto[StartSweep] continues the outer loop with the next scan. 'SEW [IncrementOneStep] is commented out to be clear it is not used for any goto. '[IncrementOneStep] if thisstep = sweepEndStep and syncsweep = 1 then gosub [SyncSweep] 'ver112-2b 'ver114-4k 'ver114-5a modified the following if sweepDir=1 then 'ver114-4k added this block to handle possible reverse sweeps if thisstepsweepEndStep then thisstep = thisstep - 1 :goto [CommandThisStep] 'ver114-4k end if 'SEWgraph If we are here, we have just read the final step of a sweep if haltAtEnd=0 then 'Alternate sweep directions if required. When we switch direction, thisstep 'was the final point of one sweep and becomes the first point of the next. 'We process and print it immediately as the last point of this sweep; then reverse 'direction and start with the same point. To avoid re-processing it at the next step we 'set haltsweep=0. if alternateSweep then 'ver114-5c gosub [ProcessAndPrint] gosub [ReverseSweepDirection] haltsweep=0 end if goto [StartSweep] 'SEWgraph Repeat loop over scans if halt flag not set end if if haltAtEnd=0 then 'Alternate sweep directions if required; added by ver114-5a 'When we switch direction, thisstep was the final point of 'one sweep and is now the first point of the next. We move to the next 'step of the new sweep. Note that for sweeps after the first, the first point 'read for each sweep is actually the second point in the sweep. In our procedure 'of processing the prior step after commanding a new step, we will process the last 'step of the prior sweep as though it is the first of the new sweep, which it is. if alternateSweep then 'ver114-5a gosub [ReverseSweepDirection] : thisstep=sweepStartStep+sweepDir else thisstep=sweepStartStep end if goto [StartSweep] 'SEWgraph Repeat loop over scans if halt flag not set end if 'SEWgraph We fall out of this loop only when haltAtEnd=1 and we reach thisstep=sweepEndStep '[EndSweepSeries] 'SEWgraph renamed and made this a comment, to show label is not accessed. 'This label marks the end of the scan loops '19.[Halted] [Halted] 'SEWgraph moved guts of this to FinishSweeping, which can also be called from elsewhere if desired. gosub [FinishSweeping]'get raw data, process, print to the computer monitor ver111-22 if specialOneSweep then specialOneSweep=0 : return 'ver114-5f [Restart] was called by gosub; we return to caller. wait 'wait for operator action 'SEWgraph created FinishSweeping; 'ver114-6e split the non-graphing cleanup into [CleanupSweep] [FinishSweeping] 'SEWgraph0 Do cleanup to end sweeping but return for further actions 'This is a modified version of the former [Halted], without the wait at the end gosub [ProcessAndPrint]'get raw data, process, print to the computer monitor ver111-22 if haltAtEnd=0 then call mAddMarker "Halt", thisstep+1, "1" 'Add Halt marker ver114-4d haltsweep=0 'do now so RefreshGraph will "flush" ver114-7j if isStickMode=0 then refreshGridDirty=1: call RefreshGraph 1 'SEWgraph; redraw and show erasure gap; don't do if stick mode ver114-7d if specialOneSweep and thisstep <> sweepEndStep then beep: message$="Sweep Aborted" : call PrintMessage 'ver114-4f 'ver114-4k ver114-5f else if calInProgress then beep: message$="Calibration Complete" : call PrintMessage 'ver114-5h end if 'test is used for troubleshooting. Coder can insert 'test = (any variable) anywhere in the code, and it will get displayed in the Messages Box during Halt. if test<>0 then message$=str$(test) : call PrintMessage 'ver114-4e 'Alternate sweep directions if required; added by ver114-5a if thisstep=sweepEndStep then if alternateSweep then gosub [ReverseSweepDirection] 'ver114-5a goto [CleanupAfterSweep] 'ver114-6e added [CleanupAfterSweep] [CleanupAfterSweep] 'Do cleanup after a sweep to be sure flags are set/reset properly 'Called by [FinishSweeping]. Can also be called by other routines to immediately 'terminate a sweep when they will be Restarting so they don't care about finishing the plotting. call DisplayButtonsForHalted 'ver114-4f replaced call to [UpdateBoxes] if thisstep=sweepEndStep then haltWasAtEnd=1 else haltWasAtEnd=0 'ver114-5c haltAtEnd=0 'SEWgraph In case we got here from auto halt at end of sweep calInProgress=0 'ver114-5h haltsweep = 0 'this says the sweep has been halted, so don't print the first command of the next sweep step 'ver111-20 return 'ver114-5a added [ReverseSweepDirection] [ReverseSweepDirection] 'Reverse direction of sweep 'This is called after sweepEndStep has been fully processed, but only if alternateSweep=1 if sweepDir=1 then sweepDir=-1 sweepStartStep=steps : sweepEndStep=0 else sweepDir=1 sweepStartStep=0 : sweepEndStep=steps end if call gSetSweepDir sweepDir 'Notify graph module of new direction return '----SubRoutines------ [FindClientOffsets] 'set clientWidthOffset and clientHeightOffset from test window ver114-7q 'Open a small test window so we can find the client area to determine how much 'smaller it is than the full window size. WindowWidth = 150 : WindowHeight = 150 UpperLeftX = 1 : UpperLeftY = 1 menu #handle, "File", "Save Image", [SaveImage] 'We need a menu to get the size right open "Test" for window as #handle 'Now that we have a window, find the actual client area--ver114-7o hWind = hWnd(#handle) 'Windows handle of graph window STRUCT Rect, leftX as long, upperY as long, rightX as long, lowerY as long 'To hold the returned data calldll #user32,"GetClientRect", hWind as ulong, Rect as struct, r as long 'Fill Rect with size info 'The offsets will be the size difference between the full window and the client area clientWidthOffset = 150-(Rect.rightX.struct-Rect.leftX.struct) clientHeightOffset = 150-(Rect.lowerY.struct-Rect.upperY.struct) close #handle 'We don't need the test window anymore return 'SEWgraph added ResizeGraphHandler [ResizeGraphHandler] 'Called when graph window resizes #handle, "hide" 'hide window to minimize system redraws ver114-1p #graphBox$ "home" #graphBox$ "posxy CenterX CenterY" clientHeight = CenterY * 2-1 clientWidth = CenterX * 2-1 'Note: On resizing, all non-buttons seem to end up a few pixels higher than the original spec, 'so the Y locations are adjusted accordingly via markTop 'Note WindowHeight when window is created is entire height; on resizing, it is the client area only markTop=clientHeight+15 : markSelLeft=5 'ver114-7q markEditLeft=markSelLeft+55 markMiscLeft=markEditLeft+185 configLeft=markMiscLeft+80 #handle, "refresh" #handle.Cover, "!show" 'Cover the crap that can appear from resizing #handle.Cover, "!hide" 'Uncover and the crap is gone #handle, "show" 'show window ver114-1p 'The graphicbox auto resizes but we have to update the graph module 'to let it know the new size call gUpdateGraphObject graphBox$, clientWidth, clientHeight, _ graphMarLeft, graphMarRight, graphMarTop, graphMarBot call gCalcGraphParams 'Calculate new scaling call gGenerateXValues gPointCount() 'recreate x values; keep same number of points call gRecalcPix 0 '0 signals not to recalc x pixel coords. 'If a sweep is in progress, we don't want to redraw from here, because that can cause a crash. 'So we just clear the graph and signal to wait for the user to redraw. This crash may have to 'do with the fact that we don't know where we are in the sweep process when resizing is invoked, 'because it is not synchronous with the scan command. Or it may simply have something to do with 'the fact that no button has yet been pushed on the graph window, which somehow affects the 'LB resizing process. The crash still sometimes occurs, so it is best to halt before resizing. if haltsweep=1 then #graphBox$, "cls" notice "Warning: Halt before resizing to avoid LB bug." else refreshRedrawFromScratch=1 'To redraw from scratch ver114-7q call RedrawGraph 0 'Redraw at new size end if call RequireRestart wait 'ver114-6e added ImplementPhaMagDisp sub ImplementPhaMagDisp 'calculate the various items from phadisp and magdisp if phadisp=2 or magdisp=2 or magdisp=4 then isStickMode=1 else isStickMode=0 if phadisp<>0 then doPhaseTrace=1 else doPhaseTrace=0 'phadisp=0 if phase is off if magdisp<>0 then doMagTrace=1 else doMagTrace=0 call gActivateGraphs doPhaseTrace,doMagTrace 'Turn graphs on if magdisp>2 then call gSetDoHist 1 else call gSetDoHist 0 'Set histogram or normal trace call gGetTraceWidth t1Width, t2Width 'ver114-4n Erase eraseLead points ahead of drawing. The more steps, the larger eraseLead if globalSteps<=50 then 'ver114-4n reduced eraseLead eraseLead=1 else eraseLead=2+int(steps/400) if (t1Width>2 or t2Width>2) and globalSteps>200 then eraseLead=eraseLead+1 end if if magdisp<>1 and magdisp<>3 then doErase2=0 else doErase2=1 'ver114-2f if phadisp<>1 then doErase1=0 else doErase1=1 'ver114-2f call gSetErasure doErase1, doErase2, eraseLead end sub 'SEWgraph added UpdateGraphParams; ver114-4n made it a gosub to allow use of non-globals [UpdateGraphParams] 'Set up graphs for drawing, but don't draw anything if alternateSweep then sweepDir=1 : call gSetSweepDir 1 'Start out forward if alternating ver114-5a sweepDir=gGetSweepDir() 'ver114-4k if sweepDir=1 then 'ver114-4k added this if... block 'Forward direction sweepStartStep=0 : sweepEndStep=steps else 'Reverse direction sweepStartStep=steps : sweepEndStep=0 end if if phadisp<>0 then doPhaseTrace=1 else doPhaseTrace=0 'phadisp=0 if phase is off if magdisp<>0 then doMagTrace=1 else doMagTrace=0 'isStickMode=1 if we have a trace in stick mode, meaning we can't refresh at the end of the scan if phadisp=2 or magdisp=2 or magdisp=4 then isStickMode=1 else isStickMode=0 'Trace 1 is phase, if used. Trace 2 is dbm or db on right axis. call gActivateGraphs doPhaseTrace,doMagTrace 'Turn graphs on if magdisp>2 then call gSetDoHist 1 else call gSetDoHist 0 'Set histogram or normal trace 'For linear sweep we display frequency in MHz; for log we do 1, 1 K, 1 M, or 1 G if gGetXIsLinear() then 'ver114-6d modified this block to use startfreq/endfreq for log sweeps call gInitGraphRange centfreq-sweepwidth/2,centfreq+sweepwidth/2, _ botphase, topphase, botref, topref 'min and max values for x, y1 and y2; calls gCalcGraphParams else call gInitGraphRange startfreq, endfreq, _ botphase, topphase, botref, topref 'min and max values for x, y1 and y2; calls gCalcGraphParams end if 'ver114-5f moved the following here from step 12 call gGenerateXValues 0 'Precalculate x values for steps+1 points; reset number of points to 0; ver114-1f deleted parameter call UpdateGraphDataFormat return sub UpdateGraphDataFormat 'Update graph module for the type of data we are graphing, and set data source and component call gSetGridStyles "EndsAndCenter", "All", "All" 'For linear sweep we display frequency in MHz; for log we do 1, 1 K, 1 M, or 1 G if gGetXIsLinear() then 'ver114-6d modified this block to use startfreq/endfreq for log sweeps xForm$= "4,6,9//suffix= M" else xForm$= "3,4,5//UseMultiplier//Scale=1000000" end if select Y1ComponentConst case constAngle if Y1SourceConst=constS11 then y1AxisLabel$="S11 Phase(Deg)" : y1Label$="S11 Deg" else y1AxisLabel$="S21 Phase(Deg)" : y1Label$="S21 Deg" end if y1IsPhase=1 y1Form$="####.##" 'ver114-7g case constTheta y1AxisLabel$="Theta" : y1Label$="Theta" y1IsPhase=1 y1Form$="####.##" 'ver114-7g case constGD 'calc group delay y1AxisLabel$="Grp Delay (sec)" : y1Label$="G.D." y1Form$="3,2,4//UseMultiplier//DoCompact" case constReact y1AxisLabel$="Reactance" : y1Label$="React" y1Form$="3,2,4//UseMultiplier//DoCompact" case constSerC, constParC if Y1ComponentConst=constSerC then y1AxisLabel$="Capacitance" _ else y1AxisLabel$="Par. Cap." 'ver114-7b y1Label$="Cap" y1Form$="3,2,4//UseMultiplier//DoCompact" case constSerL, constParL if Y1ComponentConst=constSerL then y1AxisLabel$="Inductance" _ else y1AxisLabel$="Par. Ind." 'ver114-7b y1Label$="Induct" y1Form$="3,2,4//UseMultiplier//DoCompact" case else 'error. make it angle just to be able to continue ver114-7n Y1ComponentConst=constAngle if Y1SourceConst=constS11 then y1AxisLabel$="S11 Phase(Deg)" : y1Label$="S11 Deg" else y1AxisLabel$="S21 Phase(Deg)" : y1Label$="S21 Deg" end if y1IsPhase=1 y1Form$="####.##" 'ver114-7g end select select Y2ComponentConst case constMagDBM y2AxisLabel$="Magnitude (dBm)" : y2Label$="dBm" y2Form$="####.##" case constMagWatts y2AxisLabel$="Magnitude (Watts)" : y2Label$="Watts" y2Form$="3,2,4//UseMultiplier//DoCompact" case constMagDB 'Only done for S21 and S11 if Y2SourceConst=constS11 then y2AxisLabel$="S11 Mag(dB)" : y2Label$="S11 dB" else if msaMode$="ScalarTrans" then 'ver114-7i y2AxisLabel$="Transmission (dB)" : y2Label$="dB" else y2AxisLabel$="S21 Mag(dB)" : y2Label$="S21 dB" end if end if y2Form$="####.##" case constMagRatio 'Only done for refco and TG mode transmission if Y2SourceConst=constRefco then y2AxisLabel$="Rho" : y2Label$="Rho" else y2AxisLabel$="Mag (Ratio)" : y2Label$="Ratio" y2Form$="3,2,4//UseMultiplier//DoCompact" end if case constMagV y2AxisLabel$="Mag (Volts)" : y2Label$="Volts" y2Form$="3,2,4//UseMultiplier//DoCompact" case constRho y2AxisLabel$="Rho" : y2Label$="Rho" y2Form$="#.###" case constSerR, constParR if Y2ComponentConst=constSerR then y2AxisLabel$="Resistance" _ else y2AxisLabel$="Par. Resist." 'ver114-7b y2Label$="Resist" y2Form$="3,2,4//UseMultiplier//DoCompact" case else 'error. make it dBm just to be able to continue ver114-7n Y2ComponentConst=dBm 'ver114-7p y2AxisLabel$="Magnitude (dBm)" : y2Label$="dBm" y2Form$="####.##" end select call gSetIsPhase y1IsPhase, y2IsPhase call gSetAxisFormats xForm$, y1Form$, y2Form$ call gSetAxisLabels "", y1AxisLabel$, y2AxisLabel$ 'No label for freq call gSetDataLabels y1Label$, y2Label$ end sub 'SEWgraph added InitGraphParams; ver114-4n made it a gosub to allow use of non-globals [InitGraphParams] 'Initial setup for graphs 'This is called one time early on, or to re-initialize default values 'The following intialize a lot of variables that the user may subsequently override call SetPhaseRange -180,180 'ver114-4d call SetPowerRange -100,0 'ver114-4d autoScaleY1=0 : autoScaleY2=0 'ver114-7a wate=0 : offset=0 : sgout=10 'ver114-3c ver114-4h gentrk=0 : normrev=0 phadisp=0 : magdisp=1 'ver 114-4k msaMode$="SA" 'ver114-5L S21DoTransform=0 S21JigAttach$="Series" 'ver114-7n S21JigR0=50 : S21GraphR0=50 S11BridgeR0=50 : S11GraphR0=50 Y1SourceConst=constRaw :Y2SourceConst=constRaw 'init for SA data ver114-6k Y1ComponentConst=constAngle :Y2ComponentConst=constMagDBM 'init for SA data ver114-7n call UpdateGraphDataFormat 'Updates from graphDataType$ planeadj=0 'ver 114-4k call gSetMode msaMode$ call SetCenterSpanFreq 0, finalbw/100 'ver114-6j call gSetNumDivisions 10,10 'Number of Hor and Vert divisions call gSetTraceWidth 1, 1 'Set width of both graph traces call gUsePresetColors "DARK" 'SEWgraph Activate the appearance ver114-3c call gSetIsLinear 1, 1,1 'SEWgraph default is linear sweep ver114-3c call gSetNumDynamicSteps globalSteps 'ver114-4k alternateSweep=0: sweepDir=1 'ver 114-5a call gSetSweepDir 1 'ver114-4k specialOneSweep=0 'No special sweep in progress doGraphMarkers=1 refreshEachScan=1 referenceTrace=0 referenceColor1$="250 250 0" : referenceColor2$="0 255 0" referenceWidth1=1 : referenceWidth2=1 gosub [UpdateGraphParams] return 'ver114-4f deleted [UpdateBoxes] because no boxes are left [ReadStep]'and put raw data bits into arrays. made subroutine and moved 'ver113-6d gosub [WaitStatement]'needs:wate,glitch variables,glitchtime ;slows program before reading data 'ver111-20b magdata = 0 'reset this variable before reading data doingPhase=msaMode$<>"SA" and msaMode$<>"ScalarTrans" 'ver114-7k if doingPhase or varwindow = 1 then gosub [ReadPhase] 'ver112-1b ver114-5n ver114-7k 'and return with phadata(in bits). Also installed into pharray(thisstep,3). ' If serial AtoD, magdata is returned, but not installed in any array 'the phadata could be in dead zone, but in SA mode, we don't care. 'if in VNA Mode and PDM is in automatic, check for phasedata (bits) for limits if doingPhase and setpdm = 0 and suppressPDMInversion=0 and _ (phadata < pdmlowlim or phadata > pdmhighlim) then gosub [InvertPDmodule] 'ver112-2b ver114-7k 'if magdata is collected during [ReadPhase], skip Read Magnitude ver111-22 if magdata = 0 then gosub [ReadMagnitude]'and return with raw magdata bits 'ver111-22 magarray(thisstep,3) = magdata 'put raw data into array ver111-19 return [ProcessAndPrintLastStep] rememberstep = thisstep 'remember where we were when entering this routine 'ver111-19 'since we are processing and printing the previous step, use raw data in array(thisstep - sweepDir,data) if thisstep=sweepStartStep then 'Added by ver114-4m thisstep=sweepEndStep 'back up one and wrap around else thisstep=thisstep-sweepDir 'Back up one step; no wraparound to worry about end if gosub [ProcessAndPrint]'get raw data, process, print to the computer monitor ver111-22 thisstep = rememberstep 'ver111-19 return [WaitStatement]'needed:wate,glitch()(p1,d1,p3,d3,pdm,hlt),glitchtime ; this slows the program 'ver111-27 glitch = max(max(max(glitchp1, glitchd1),max(glitchp3, glitchd3)), max(glitchpdm, glitchhlt)) 'ver111-27 'glitchp1=PLL1:glitchd1=DDS1:glitchp3=PLL3:glitchd3=DDS3:glitchpdm=PDM(10):glitchhlt=halted(10) waittime = (wate + glitch)*glitchtime 'ver111-27 'in my Toshiba, a waittime count of 80 gives a delay of approx, 1 millisecond 'therefore, each increment of any "glitchXX" or "wate" (Wait Box) should add 1 ms of delay before a "read" timecounter = 0 'ver111-27 [TimeLoop] 'ver111-27 if timecounter < waittime then timecounter = timecounter + 1:goto [TimeLoop] 'ver111-27 glitchp1=0:glitchd1=0:glitchp3=0:glitchd3=0:glitchpdm=0:glitchhlt=0 'reset glitch variables back to 0 'ver111-27 return 'to [ReadStep]or[InvertPDmodule]or[CalPDMinvdeg] [AutoGlitchtime] 'ver111-37c glitchtime = 100000 whatiswate = wate wate = 1 a = time$("ms") 'time of day, in milliseconds. This uses the computer's internal clock gosub [WaitStatement] b = time$("ms") glitchtime = glitchtime/(b-a) 'glitchtime is the value required for a 1 ms wait time wate = whatiswate 'change wate back to it's original global value return [ReadMagnitude]'needed: port,status ; creates: magdata (and phadata for serial A/D's) if adconv = 8 then gosub [Read8Bitmag] 'and return here with magdata if adconv = 12 then gosub [Read12Bitmag] 'and return here with magdata if adconv = 16 then gosub [ReadAD16Status]:gosub [Process16Mag] 'combined ver111-34a 'and return here with just magdata 'ver111-33b if adconv = 22 then gosub [ReadAD22Status]:gosub [Process22Mag] 'ver111-37a 'and return here with just magdata 'ver111-37a return 'to [ReadStep] [ReadPhase]'needed: port,status ; creates: phadata (and magdata for serial A/D's) if adconv = 8 then gosub [Read8Bitpha] 'and return here with phadata if adconv = 12 then gosub [Read12Bitpha] 'and return here with phadata if adconv = 16 then gosub [ReadAD16Status]:gosub [Process16MagPha] 'combined ver111-34a if adconv = 22 then gosub [ReadAD22Status]:gosub [Process22MagPha] 'ver111-37a if doSpecialGraph>0 then phadata=maxpdmout/4 + thisstep*30 'SEWgraph Force to a value not requiring constant inversion 'and return here with phadata (and magdata, if serial AtoD) 'ver111-33b 'if calibrating the PDM inversion, don't put raw data into arrays, used only in [CalPDMinvdeg] if doingPDMCal = 1 then return 'to [CalPDMinvdeg] 'ver111-29 ver114-5L phaarray(thisstep,3) = phadata 'put raw data into array 'ver112-2a phaarray(thisstep,4) = phaarray(thisstep,0) 'PDM state at which this data is taken. ver112-2a 'it is only used in Variables Windows to show state of PDM when data was collected. return 'to [ReadStep] 'ver114-6c revised [InvertPDmodule] [InvertPDmodule]'this will change the state of the PDM for this step and future steps 'ver111-28 'entered from [ReadStep], where it was determined that phadata was in, or close to "dead zone" 'this subroutine will re-command PDM, and return to [ReadStep] and read the phase again, 'but not test for dead zone again, just assumes data to be viable 'determine what the pdmstate was when entering, and "flip" it if phaarray(thisstep,0) = 0 then newpdmstate = 1 'ver112-2a if phaarray(thisstep,0) = 1 then newpdmstate = 0 'ver112-2a 'change the pdm state for thisstep to the newpdmstate phaarray(thisstep,0) = newpdmstate 'now, go and command the PDM to the new state (Command PDM only!) gosub [CommandPDMonly] 'command just the PDM ver111-28 'this has just created a large glitch in the PDM output, so while it is settling down, 'change future PDM commands for all subsequent steps to end of sweep. for i = thisstep to sweepEndStep step sweepDir 'ver114-5a phaarray(i,0) = newpdmstate 'inverts pdmcmd for thisstep and subsequent steps to end of sweep. ver111-28 next i 'add appropriate wait time before reading the phase again gosub [VideoGlitchPDM]'calculates glitchpdm, depending on Video Selection gosub [WaitStatement] 'and use the new glitchpdm value 'now, go and read Phase, again. Use its "return" to return to [ReadStep] goto [ReadPhase] 're-read the phase and return to [ReadStep] 'when back in [ReadStep], it will not test for dead zone again. Assumes valid Phase. 'ver114-6c added [VideoGlitchPDM] [VideoGlitchPDM]'entered from [InvertPDmodule],[PDM] if videoFilter$ = "Wide" then glitchpdm = glitchpdm + 10 ' or maybe just glitchpdm=10, etc if videoFilter$ = "Mid" then glitchpdm = glitchpdm + 100 if videoFilter$ = "Narrow" then glitchpdm = glitchpdm + 1000 return 'to [InvertPDmodule]or[PDM] [CalPDMinvdeg] 'to find the amount of phase shift when the PDM state is inverted 'invdeg is a calibration value used in [ConvertPhadata], (phase of inverted PDM) - (invdeg) = real phase of PDM. ver113-7b 'the VNA must be in "0" sweepwidth, freq close to the transition point. rememberpdmstate = phaarray(thisstep,0) 'ver112-2e #handle.Restart, "Cal PDM" 'ver114-4c deleted print to #main.restart beep phaarray(thisstep,0) = 0 'command PDM to Normal 'ver111-29 gosub [CommandPDMonly] 'ver111-29 glitchpdm = 5000 'should equate to 5 seconds of delay 'ver111-29 gosub [WaitStatement] 'ver111-29 gosub [ReadPhase]'return here with phadata 'ver111-29 'the 16 bit serial has just been "hit" with a conv (D7)in Commanding the Orig PDM. OK to hit it again? Yes. 'expect phadata to be either 80% or 20% of maxpdmout phase0 = 360*phadata/maxpdmout 'convert to degrees phaarray(thisstep,0) = 1 'command PDM to Inverted 'ver111-29 gosub [CommandPDMonly] 'ver111-29 glitchpdm = 5000 'should equate to 5 seconds of delay 'ver111-29 gosub [WaitStatement] 'ver111-29 gosub [ReadPhase]'return here with phadata 'ver111-29 'expect phadata to be either 20% or 80% of maxpdmout phase1 = 360*phadata/maxpdmout 'convert to degrees CalInvDeg = phase1 - phase0 'ver114-5L if CalInvDeg < 0 then CalInvDeg = CalInvDeg + 360 CalInvDeg = val(using("####.##",CalInvDeg)) 'PDM's phase shift when inverted, in .01 degree resolution call DisplayButtonsForHalted 'SEW8 replaced print #main.restart, "Restart" message$=phase0;" ";phase1 : call PrintMessage 'ver114-4e beep 'ver111-36d 'put PDM into the state at which it entered this subroutine phaarray(thisstep,0) = rememberpdmstate 'ver112-2e gosub [CommandPDMonly] 'ver112-2e return 'ver114-5k changed wait to return [Read8Bitmag]'needed: port,status ; creates: magdata 'This will 8 bit parallel on Original or Slim Control Board. ver111-29 ' if inp(status) < 128 then wait (status bit 7) line is high (D/A 127 then wait line is low (magnitude voltage 63 then ack line is high (phase voltage>ladder) 'the data will always be 1 bit less than crossover region phadata = 0 if cb = 2 then out control, AUTO 'enable P3 on SLIM Control Board. ver111-29 out port, phadata + 128 'set D/A MSB to "1", creates 2.5v out of D/A ladder magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 128 out port, phadata + 64 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 64 out port, phadata + 32 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 32 out port, phadata + 16 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 16 out port, phadata + 8 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 8 out port, phadata + 4 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 4 out port, phadata + 2 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 2 out port, phadata + 1 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 1 out port, 0 'return data to zero if cb = 2 then out control, contclear 'disable P3 on SLIM Control Board. ver111-29 return 'return, with phadata [Read12Bitmag]'needed: port,status ; creates: magdata 'This will read 12 bit parallel, WAIT line, on Original or Slim Control Board. ver111-29 ' if inp(status) < 128 then wait line (status bit 7)is high (D/A 127 then wait line is low (magnitude voltage 63 then ack line is high (phase voltage>ladder) ' if inp(status) < 64 then ack line is low (phase voltage 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 2048: word = word + 8 out port,word +4 +16 +32 ' put 4 into MSB latch, D/A = 1024 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 1024: word = word + 4 out port,word +2 +16 +32 ' put 2 into MSB latch, D/A = 512 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 512: word = word + 2 out port,word +1 +16 +32 ' put 1 into MSB latch, D/A = 256 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 256: word = word + 1 out port,word +16 +32 ' put appxm. into MSB latch, D/A = appx out port,word +16 +32 +64 ' latch MSB with appx word = 0 out port,8 +16 +64 ' put 8 into middle latch, D/A = 128 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 128: word = word + 8 out port,word +4 +16 +64 ' put 4 into middle latch, D/A = 64 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 64: word = word + 4 out port,word +2 +16 +64 ' put 2 into middle latch, D/A = 32 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 32: word = word + 2 out port,word +1 +16 +64 ' put 1 into middle latch, D/A = 16 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 16: word = word + 1 out port,word +16 +64 ' put appxm. into middle latch, D/A = appx out port,word +16 +32 +64 ' latch middle with appx word = 0 out port,8 +32 +64 ' put 8 into LSB latch, D/A = 8 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 8: word = word + 8 out port,word +4 +32 +64 ' put 4 into LSB latch, D/A = 4 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 4: word = word + 4 out port,word +2 +32 +64 ' put 2 into LSB latch, D/A = 2 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 2: word = word + 2 out port,word +1 +32 +64 ' put 1 into LSB latch, D/A = 1 magpha = inp(status) if magpha > 127 then magpha = magpha - 128 if magpha > 63 then phadata = phadata + 1 out port, 0 'return data to zero if cb = 2 then out control, contclear 'disable P3 on SLIM Control Board. ver111-29 return ' return with phadata [ReadAD16Status]'needed: port,status ; creates: 16 status port words (stat15-stat0)mag,(and, pha if two A/D's installed) 'ver111-33a 'written for Analog Devices, AD7685, but other 16 bit serial AtoD's will probably work with this code 'reads 16 bit serial using Original or Slim Control Board. ver111-33c 'good for 16 Bit Original AtoD Module or SLIM-ADC-16 'MAG is WAIT, PHASE is ACK, SCLK is BD6, CVNis BD7. if cb = 2 then out control, AUTO 'enable P3 on SLIM Control Board. ver111-29 out port, 128 'take CVN high out port, 64 'CVN low, SCLK=1 'bit 15 is valid stat15 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'bit 14 is valid out port, 64 'CVN low, SCLK=1 stat14 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat13 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat12 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat11 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat10 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat9 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat8 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat7 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat6 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat5 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat4 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat3 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat2 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat1 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'bit 0 is valid 'a/d outputs would go high z on 16th SCLK trailing edge.Only 15 have been sent. stat0 = inp(status) 'read data, statX is 8 bit word if cb = 2 then out control, contclear 'disable P3 on SLIM Control Board. ver111-29 'we now have raw a/d status words in stat15-stat0 return 'to [ReadMagnitude]or[ReadPhase]with status words [Process16MagPha]'ver111-33a 'process the stat15-0 for both magnitude and phase.Determines magdata bit (D7) and phadata bit (D6) in each word magdata = 0 phadata = 0 if stat15>127 then stat15=stat15-128:magdata = magdata + 32768 'WAIT is low, MAG is high if stat15<64 then phadata = phadata + 32768 'ACK is low, PHASE is high if stat14>127 then stat14=stat14-128:magdata = magdata + 16384 if stat14<64 then phadata = phadata + 16384 if stat13>127 then stat13=stat13-128:magdata = magdata + 8192 if stat13<64 then phadata = phadata + 8192 if stat12>127 then stat12=stat12-128:magdata = magdata + 4096 if stat12<64 then phadata = phadata + 4096 if stat11>127 then stat11=stat11-128:magdata = magdata + 2048 if stat11<64 then phadata = phadata + 2048 if stat10>127 then stat10=stat10-128:magdata = magdata + 1024 if stat10<64 then phadata = phadata + 1024 if stat9>127 then stat9=stat9-128:magdata = magdata + 512 if stat9<64 then phadata = phadata + 512 if stat8>127 then stat8=stat8-128:magdata = magdata + 256 if stat8<64 then phadata = phadata + 256 if stat7>127 then stat7=stat7-128:magdata = magdata + 128 if stat7<64 then phadata = phadata + 128 if stat6>127 then stat6=stat6-128:magdata = magdata + 64 if stat6<64 then phadata = phadata + 64 if stat5>127 then stat5=stat5-128:magdata = magdata + 32 if stat5<64 then phadata = phadata + 32 if stat4>127 then stat4=stat4-128:magdata = magdata + 16 if stat4<64 then phadata = phadata + 16 if stat3>127 then stat3=stat3-128:magdata = magdata + 8 if stat3<64 then phadata = phadata + 8 if stat2>127 then stat2=stat2-128:magdata = magdata + 4 if stat2<64 then phadata = phadata + 4 if stat1>127 then stat1=stat1-128:magdata = magdata + 2 if stat1<64 then phadata = phadata + 2 if stat0>127 then stat0=stat0-128:magdata = magdata + 1 if stat0<64 then phadata = phadata + 1 return 'to [ReadPhase] with magdata and phadata [Process16Mag]'ver111-33a 'process the stat15-0 for magnitude only. Determines magdata bit (D7) in each word magdata = 0 if stat15>127 then magdata = magdata + 32768 'WAIT is low, MAG is high if stat14>127 then magdata = magdata + 16384 'WAIT is low, MAG is high if stat13>127 then magdata = magdata + 8192 'WAIT is low, MAG is high if stat12>127 then magdata = magdata + 4096 'WAIT is low, MAG is high if stat11>127 then magdata = magdata + 2048 'WAIT is low, MAG is high if stat10>127 then magdata = magdata + 1024 'WAIT is low, MAG is high if stat9>127 then magdata = magdata + 512 'WAIT is low, MAG is high if stat8>127 then magdata = magdata + 256 'WAIT is low, MAG is high if stat7>127 then magdata = magdata + 128 'WAIT is low, MAG is high if stat6>127 then magdata = magdata + 64 'WAIT is low, MAG is high if stat5>127 then magdata = magdata + 32 'WAIT is low, MAG is high if stat4>127 then magdata = magdata + 16 'WAIT is low, MAG is high if stat3>127 then magdata = magdata + 8 'WAIT is low, MAG is high if stat2>127 then magdata = magdata + 4 'WAIT is low, MAG is high if stat1>127 then magdata = magdata + 2 'WAIT is low, MAG is high if stat0>127 then magdata = magdata + 1 'WAIT is low, MAG is high return 'to [ReadMagnitude]with magdata [ReadAD22Status]'needed: port,status ; creates: 12 status port words (stat11-stat0)mag,(and, pha if two A/D's installed) 'ver111-37a 'written for Linear Technology, LTC1860, but other 12 bit serial AtoD's will probably work with this code 'reads 12 bit serial using Original or Slim Control Board. ver111-33c 'good for serial, 12 Bit Original AtoD Module or SLIM-ADC-12 'MAG is WAIT, PHASE is ACK, SCLK is BD6, CVN is BD7. if cb = 2 then out control, AUTO 'enable P3 if SLIM Control Board. ver112-2d 'delver112-2d out control, AUTO 'enable P3 on SLIM Control Board out port, 128 'take CVN high out port, 64 'CVN low, SCLK=1 'serial data out is not valid yet, still Hi-Z out port, 0 'CVN low, SCLK=0 Bit 11 is valid. fix error ver111-39c out port, 64 'CVN low, SCLK=1 fix error ver111-39c stat11 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat10 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat9 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat8 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat7 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat6 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat5 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat4 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat3 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat2 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'next bit is valid out port, 64 'CVN low, SCLK=1 stat1 = inp(status) 'read data, statX is 8 bit word out port, 0 'CVN low, SCLK=0 'bit 0 is valid out port, 64 'CVN low, SCLK=1 'not necessary for LTC1860 stat0 = inp(status) 'read data, statX is 8 bit word out port, 0 'SCLK=0 'LTC1860 would go to zero on the 13th SCLK trailing edge. Only 12 have been sent. if cb = 2 then out control, contclear 'disable P3 if SLIM Control Board. ver112-2d 'we have raw a/d status words in stat11-stat0 return 'to [ReadMagnitude]or[ReadPhase]with status words [Process22MagPha]'ver111-37a 'process the stat11-0 for both magnitude and phase.Determines magdata bit (D7) and phadata bit (D6) in each word magdata = 0 phadata = 0 if stat11>127 then stat11=stat11-128:magdata = magdata + 2048 'WAIT is low, MAG is high if stat11<64 then phadata = phadata + 2048 'ACK is low, PHASE is high if stat10>127 then stat10=stat10-128:magdata = magdata + 1024 if stat10<64 then phadata = phadata + 1024 if stat9>127 then stat9=stat9-128:magdata = magdata + 512 if stat9<64 then phadata = phadata + 512 if stat8>127 then stat8=stat8-128:magdata = magdata + 256 if stat8<64 then phadata = phadata + 256 if stat7>127 then stat7=stat7-128:magdata = magdata + 128 if stat7<64 then phadata = phadata + 128 if stat6>127 then stat6=stat6-128:magdata = magdata + 64 if stat6<64 then phadata = phadata + 64 if stat5>127 then stat5=stat5-128:magdata = magdata + 32 if stat5<64 then phadata = phadata + 32 if stat4>127 then stat4=stat4-128:magdata = magdata + 16 if stat4<64 then phadata = phadata + 16 if stat3>127 then stat3=stat3-128:magdata = magdata + 8 if stat3<64 then phadata = phadata + 8 if stat2>127 then stat2=stat2-128:magdata = magdata + 4 if stat2<64 then phadata = phadata + 4 if stat1>127 then stat1=stat1-128:magdata = magdata + 2 if stat1<64 then phadata = phadata + 2 if stat0>127 then stat0=stat0-128:magdata = magdata + 1 if stat0<64 then phadata = phadata + 1 return 'to [ReadPhase] with magdata and phadata [Process22Mag]'ver111-37a 'process the stat11-0 for magnitude only. Determines magdata bit (D7) in each word magdata = 0 if stat11>127 then magdata = magdata + 2048 'WAIT is low, MAG is high if stat10>127 then magdata = magdata + 1024 'WAIT is low, MAG is high if stat9>127 then magdata = magdata + 512 'WAIT is low, MAG is high if stat8>127 then magdata = magdata + 256 'WAIT is low, MAG is high if stat7>127 then magdata = magdata + 128 'WAIT is low, MAG is high if stat6>127 then magdata = magdata + 64 'WAIT is low, MAG is high if stat5>127 then magdata = magdata + 32 'WAIT is low, MAG is high if stat4>127 then magdata = magdata + 16 'WAIT is low, MAG is high if stat3>127 then magdata = magdata + 8 'WAIT is low, MAG is high if stat2>127 then magdata = magdata + 4 'WAIT is low, MAG is high if stat1>127 then magdata = magdata + 2 'WAIT is low, MAG is high if stat0>127 then magdata = magdata + 1 'WAIT is low, MAG is high return 'to [ReadMagnitude]with magdata [ProcessAndPrint]'process and print "thisstep" 'ver111-22 'SEW3 changed the next few lines to have phase degrees adjusted for phase-change-over-signal-level 'The calculation of the phase adjustment, difPhase, is made in ConvertMagPhaseData (formerly ConvertMagData). 'That correction is then added to phase in ConvertPhadata.Note that ConvertPhadata must now be 'called after ConvertMagPhaseData so difPhase is valid when ConvertPhadata is executed. gosub [ConvertMagPhaseData] 'convert magdata (bits read) to magpower (dBm) and thispointmag (pixels) if msaMode$<>"SA" then gosub [ConvertPhadata]'convert phadata (bits read) to phase (degrees) and thispointphase (pixels) 'ver111-19 gosub [PlotDataToScreen] return 'from [ProcessAndPrint] 'SEWgraph1 added CalcFreqCorrection sub CalcFreqCorrection 'Calculate power correction factors for each frequency step. for s=0 to globalSteps thisFreq=gGetPointXVal(s+1) 'Point number is one more than step num freqCorrection(s)=calConvertFreqError(thisFreq) 'Put power correction into the array next s end sub 'SEW2 added difPhase to the following comment [ConvertPhadata]'needed: phadata,PDM polarity,difPhase ; creates "phaseofpdm" and "thispointphase", the pixel value 'retrieve phadata from array 'convert phadata to phase, round off to .01 deg 'compensate phase using "invdeg" (if PDM was inverted during the phase reading) 'compensate phase using "difPhase", Phase Error Correction Factor' 'as determined in Path Calibration, (variation of phase readings over signal level) 'if in line cal, write phase to lineCalArray 'if normal sweep, process phase by removing line calibration phase 'add or subtract Reference Plane Extension 'convert phase to +360 to 0 degree format and round off to .01 degree 'convert phase to +180 to -180 format 'convert phase to pixels, depending on scale SEWgraph--pixel calculation deleted if doSpecialGraph=0 then 'ver114-7e '[DoSpecialGraph] sets phase directly 'grab raw phase data bits from array phadata = phaarray(thisstep,3) 'ver111-19 'convert phadata to absolute phase lead, referenced to 0 degrees. maxpdmout/4 = 90 degrees lead,maxpdmout/2 = 180 degrees lead phase = val(using("####.##",(360*phadata/maxpdmout))) 'converts phadata bits to absolute phase and round off to .01 degrees 'the absolute phase will normally be between limits of +288 and +72 degrees, 'however, it can be between 360 and 0 degrees if the PDM is "forced" into a set state (setpdm=1) 'ver114-5q allowed the calculations to proceed without worrying about the bounds in which 'phase lies, normalizing it to -180 to 180 at the end. 'if PDM was inverted, subtract the inverted phase change (norm to inv adds "invdeg" deg) phase = phase - (invdeg * phaarray(thisstep,0)) 'ver111-36g 'now, the absolute phase can be between +360 and appx -180 deg end if phase=phase-difPhase 'SEW3: subtract correction for change of phase over signal level. 'calculate phase with calibration table factored in 'ver114-5f Apply lineCalArray only if LineCal or BaseLineCal is active if applyLineCalLevel>0 then phase = phase - lineCalArray(thisstep,2) '[RefPlaneExt] add or subtract reference plane adjustment 'ver113-1b 'convert the planeadj(nsec) to rotational delay(freq vs time) 'rotations = [planeadjustment/(1/f)] 'f is in MHz rotate = .001 * planeadj * datatable(thisstep,1) 'decimal number of rotations, 1.234 'drop whole number of rotations and change to degrees (0 to 360), round off to .01 degrees adddegrees = val(using("####.##",(360*(rotate - int(rotate))))) '+360 to 0 degrees phase = phase + adddegrees 'The phase correction is set to 180 degrees when the phase reading during initial calibration 'is suspect. In that case, we override all the foregoing and set the final phase to 0. if difPhase>179 or difPhase<-179 then phase=0 'ver114-7k ver114-7L 'convert to standard +180 -180 format while phase >180 : phase = phase - 360 : wend 'ver114-5d fixed typo while phase <=-180 : phase = phase + 360 : wend 'write the processed phase into the memory array, +180 to -180 deg datatable(thisstep,3) = phase 'put current phase measurement into the array, line value= thisstep 'Note that phase may have to be adjusted during graphing to fit the bounds of the display return '--SEW Replaced [ConvertMagData] and [ConvertFreq] with following combined routine, 'to utilize the calibration module to interpolate the necessary correction factors 'to convert the raw ADC reading into dbm, and then to correct that number for variations 'over frequency. Phase correction is also calculated so the routine name was changed. 'That phase correction is difPhase and is subtracted from phase in ConvertPhadata 'SCOTTY: The phase correction for signal level has to be calculated here, because it 'is a function of magnitude ADC reading and so can be interpolated at the same time 'as that ADC reading is converted to mag power. This messes up the terminology a bit 'because we now have ConvertPhadata and ConvertMagPhaseData. But it works. [ConvertMagPhaseData]'convert magnitude data bits to MSA input power(in dBm) and to pixels. ver111-39a 'needed: magarray,calibration table 'this converts magdata to MSA input power, using 'a Magnitude Error Correction Factor, (determined in Frequency Calibration) 'If in VNA mode, it also finds the phase correction for the power level indicated 'by magdata, and put it into difPhase, to be subtracted from phase later. 'SEWgraph put special graphing into new [DoSpecialGraph] if doSpecialGraph=0 then 'Normal scan. Apply the calibration magdata = magarray(thisstep,3) 'Apply mag calibration to get power and phase correction if msaMode$<>"SA" and msaMode$<>"ScalarTrans" then doPhaseCor=1 else doPhaseCor=0 'ver114-7k call calConvertMagPhase magdata, doPhaseCor, power, difPhase 'ver114-5n thisfreq = datatable(thisstep,1) freqerror=freqCorrection(thisstep) 'find freq cal adjustment SEWgraph1 else gosub [DoSpecialGraph] end if goto [CalcMagpowerPixel] '--SEW End of new routine to make calibration adjustments [CalcMagpowerPixel] power = power + freqerror if convdatapwr = 1 then gosub [ConvertDataToPower] 'ver112-2b 'round off MSA input power to .01 dBm, magpower, no matter which AtoD is used magpower = val(using("####.##",power)) 'ver114-5f Apply lineCalArray only if LineCal or BaseLineCal is active if msaMode$<>"SA" then if applyLineCalLevel>0 then magpower = magpower - lineCalArray(thisstep,1) 'ver114-5n datatable(thisstep,2) = magpower 'put current power measurement into the array, line value= thisstep 'SEWgraph deleted the following, as we no longer need to calculate thispointmag in pixels ' [ConvertPowerToPixels]'needed:magpower,topref,botref ; creates thispointmag (pixels) ' if magpower > topref then thispointmag = maxscale 'normally, maxscale=255 ' if magpower <= topref and magpower >= botref then thispointmag = maxscale*(magpower-botref)/(topref-botref) ' if magpower < botref then thispointmag = 0 'thispointmag is in pixels, from 0 to maxscale return 'to [ProcessAndPrint] return 'SEWgraph added DoSpecialGraph [DoSpecialGraph] difPhase=0 : freqerror=0 'ver114-7e if doSpecialGraph=1 then 'Graph mag calibration table. Find the min and max ADC values 'and make magdata run linearly from the minimum to the maximum. 'Any non-linearities in the graph then reflect the calibration 'We do nothing with phase call calGetMagPoint 1,minADC, calMag, calPhase 'ignore calMag and calPhase call calGetMagPoint calNumMagPoints(),maxADC, calMag, calPhase testSlope=(maxADC-minADC)/steps magdata=minADC+testSlope*thisstep 'Apply mag calibration to get power, but forget phase correction call calConvertMagPhase magdata, 0, power, dum 'skip freq cal return end if if doSpecialGraph=2 then 'Force power to 0 dbm and then find the frequency compensation. 'The resulting graph will show the shape of the frequency compensation 'curve. power=0 thisfreq = datatable(thisstep,1) freqerror=freqCorrection(thisstep) 'find freq cal adjustment SEWgraph1 return end if if doSpecialGraph=3 then 'Generate random values for magdata superimposed on a sine wave centered midway in ADC call calGetMagPoint 1,minADC, calMag, calPhase 'ignore calMag and calPhase call calGetMagPoint calNumMagPoints(),maxADC, calMag, calPhase magdata=3*(1+RND(1)/20)*(maxADC)/4 + 3000*sin(10*datatable(thisstep,1)) 'ver114-7b 'Note: without being connected to MSA, which is when DoSpecialGraph is useful, 'phase will bounce between 0 and 180 and thus will show some graph action. call calConvertMagPhase magdata, 1, power, difPhase 'ver114-5n thisfreq = datatable(thisstep,1) freqerror=freqCorrection(thisstep) 'find freq cal adjustment SEWgraph1 phase=180-10*datatable(thisstep,1) ' phadata =maxpdmout-1000*datatable(thisstep,1) 'For special graph 3, force to a linear function ver114-7b ' while phadata=1000 then 'ver114-4k 'Discard at least every 1000 points to avoid a slowdown. oneThousandthThisStep=thisstep/1000 if int(oneThousandthThisStep)=oneThousandthThisStep then #graphBox$, "discard" end if 'ver114-4e deleted drawing of point values at start, center and end if thisstep=sweepEndStep then 'just processed final point of a sweep 'ver114-4k 'If autoscale is on for either axis then calculate the scale and redraw from raw values 'We only do this for the first scan. ver114-7a added this autoscale material if firstScan and (autoScaleY2 or (autoScaleY1 and msaMode$<>"SA" and msaMode$<>"ScalarTrans")) then if haltAtEnd=1 then 'Halt will redraw, so we just autoscale here call PerformAutoScale 'Recalculates scaling in graph module else refreshForceRefresh=1 : refreshAutoScale=1 'ver114-7a end if end if if refreshForceRefresh or refreshEachScan then 'force full refresh unless we are in stick mode; and don't redraw if haltAtEnd=1 because 'a redraw will occur when we halt. if isStickMode=0 and haltAtEnd=0 then call RefreshGraph 1 else if hasAnyMark=1 then call mDrawMarkerInfo 'Update marker info at end of every scan no matter what 'If no auto refresh, draw markers on first scan only, and only if user wants them drawn if firstScan=1 and doGraphMarkers=1 then 'In case frequency axis has changed, we want to update the marker point numbers 'to maintain their prior frequencies, if possible. call gDetermineMarkerPointNumbers if doGraphMarkers=1 then call gDrawMarkers 'Draw markers if we are supposed to end if #graphBox$, "discard" 'Get rid of marker draw commands in memory end if firstScan=0 'scan has ended; next point is not in first scan since restart doSpecialRandom=RND(1) 'Random number for doSpecialGraph ver114-7m end if if varwindow = 1 then gosub [updatevar] 'moved here from [ProcessAndPrint] ver111-34a return 'ver114-6k added GetDataAsRefco sub GetDataAsRefco db, ang, byref rho, byref theta 'Get data db, ang as reflection coefficient 'Note that S21 or S11 at this point have been converted to use the GraphR0, not BridgeR0 ver114-7j if msaMode$="Reflection" then 'ver114-7j modified to recognize that S11 is already in S11GraphR0 rho=20*uSafeLog10(db) 'mag made linear theta=ang 'phase, as is else 'ver114-7p deleted an error test 'Convert to impedance based on jig attachment and then to S11db if S21JigAttach$="Series" then call uSeriesJigImpedance S21JigR0, db, ang, impR, impX 'calc impedance : R, X else call uShuntJigImpedance S21JigR0, db, ang, impR, impX 'calc impedance : R, X end if 'Note we use S21GraphR0 to calculate reflection, because we are deriving 'it from S21. TO DO May want to change this when reflection mode is implemented. call uImpedanceToRefco S21GraphR0, impR, impX, rho, theta end if end sub 'ver114-6k added GetDataAsImpedance sub GetDataAsImpedance db, ang, byref impR, byref impX 'Get data db, ang as impedance 'Note that S21 or S11 at this point have been converted to use the GraphR0, not BridgeR0 ver114-7j if msaMode$="Reflection" then call uS11DBToImpedance S11GraphR0, db, ang, impR, impX 'calc impedance : R, X modver114-7j else 'ver114-7n deleted an error test 'Convert S21 to impedance based on jig connection if S21JigAttach$="Series" then call uSeriesJigImpedance S21GraphR0, db, ang, impR, impX 'calc impedance : R, X else call uShuntJigImpedance S21GraphR0, db, ang, impR, impX 'calc impedance : R, X end if end if end sub 'ver114-6f added CalcGraphData; substantially modified by ver114-6k sub CalcGraphData currStep, byref y1, byref y2, useWorkArray 'Calculate y1,y2 per user request 'If useWorkArray=1 then the data source is uWorkArray(); otherwise it is datatable() 'Power is in uWorkArray(currStep+1,1), phase in uWorkArray(currStep+1,2) 'Power is in datatable(currStep,2), phase in datatable(currStep,3) Y2IsParComponent=0 'Set to 1 if Y2 data source is parallel components y1=0:y2=0 if useWorkArray then trueFreq=1000000*uWorkArray(currStep+1,0) db=uWorkArray(currStep+1,1) ang=uWorkArray(currStep+1,2) else trueFreq=1000000*datatable(currStep,1) db=datatable(currStep,2) ang=datatable(currStep,3) end if 'If S21 or S11 is to be transformed to new reference impedance, do it now, so all further 'processing will use S21GraphR0 or S11GraphR0 if msaMode$="VectorTrans" then 'ver114-7j added entire if ...else block if S21DoTransform and S21JigR0<>S21GraphR0 then 'Transform raw S21 to required reference impedance for two terminal devices if S21JigAttach$="Series" then call uSeriesJigImpedance S21JigR0, db, ang, resDUT, reactDUT 'get DUT impedance call uSeriesImpedanceToS21DB S21GraphR0, resDUT, reactDUT, db, ang 'convert back to S21 with new R0 else call uShuntJigImpedance S21JigR0, db, ang, resDUT, reactDUT 'get DUT impedance call uShuntImpedanceToS21DB S21GraphR0, resDUT, reactDUT, db, ang 'convert back to S21 with new R0 end if end if else if msaMode$="Reflection" then if S11BrigeR0<>S11GraphR0 then 'Transform to graph reference impedance call uS11DBToImpedance S11BridgeR0, db, ang, impR, impX 'calc impedance : R, X call uImpedanceToRefco S11GraphR0, impR, impX, rho, ang 'calc S11 db=20*uSafeLog10(rho) 'put S11 in db form ver114-7L fixed typo end if end if end if select Y2SourceConst case constRaw Y2SourceR=db 'mag, as is Y2SourceI=ang 'phase, as is case constLinearMag Y2SourceR=uTenPower(db/10) 'Power ratio=10^(db/10) Y2SourceI=ang 'phase, as is case constS11 'Need S11 call GetDataAsRefco db, ang, Y2SourceR, Y2SourceI Y2SourceR=20*uSafeLog10(Y2SourceR) case constRefco 'Need Reflection coefficient call GetDataAsRefco db, ang, Y2SourceR, Y2SourceI case constImpedance 'Need Impedance call GetDataAsImpedance db, ang, Y2SourceR, Y2SourceI end select 'Y2SourceR and Y2SourceI now have the necessary source data. Note that they are designated R and I, 'but may not actually be real and imaginary parts. select Y2ComponentConst case constMagDBM 'Y2 source data will be raw dbm y2=Y2SourceR case constMagWatts 'Y2 source data will be linear power (mw) y2=Y2SourceR/1000 case constMagDB 'Y2 source data will be raw db y2=Y2SourceR case constMagRatio 'Y2 source data will be linear mag ratio y2=Y2SourceR case constMagV 'Y2 source data will be linear power (mw) if Y2SourceR<=0 then y2=0 else y2=sqr(Y2SourceR/20) 'square root of 50* mw/1000 case constRho 'Y2 source data will be Refco y2=Y2SourceR case constSerR 'Y2 source data will be impedance y2=Y2SourceR case constParR 'Y2 source data will be impedance Y2IsParComponent=1 'So Y1 can possibly use same data 'Y2 source data will be impedance call uEquivParallelRLC trueFreq, Y2SourceR, Y2SourceI, parR, parL, parC y2=parR 'ver114-7b case else y2=Y2SourceR 'Error, but assign a value just to continue ver114-7p end select if msaMode$<>"SA" and msaMode$<>"ScalarTrans" then 'Y1 axis data ver114-7f select Y1SourceConst case constRaw Y1SourceR=db 'mag, as is Y1SourceI=ang 'phase, as is case constLinearMag Y1SourceR=uTenPower(db/10) 'Power ratio=10^(db/10) Y1SourceI=ang 'phase, as is case constS11 'Need S11 if magdisp>0 and Y2SourceConst=constS11 then Y1SourceR=Y2SourceR : Y1SourceI=Y2SourceI 'Same source data as Y2 else call GetDataAsRefco db, ang, Y1SourceR, Y1SourceI Y1SourceR=20*uSafeLog10(Y1SourceR) end if case constRefco 'Need Reflection coefficient if magdisp>0 and Y2SourceConst=constRefco then Y1SourceR=Y2SourceR : Y1SourceI=Y2SourceI 'Same source data as Y2 else call GetDataAsRefco db, ang, Y1SourceR, Y1SourceI end if case constImpedance 'Need Impedance if magdisp>0 and Y2SourceConst=constImpedance then Y1SourceR=Y2SourceR : Y1SourceI=Y2SourceI 'Same source data as Y2 else call GetDataAsImpedance db, ang, Y1SourceR, Y1SourceI end if end select 'Y1SourceR and Y1SourceI now have the necessary source data. Note that they are designated R and I, 'but may not actually be real and imaginary parts. select Y1ComponentConst case constAngle 'Source data is raw y1=Y1SourceI case constTheta 'Source data is Refco y1=Y1SourceI case constGD 'calc group delay if startfreq=endfreq then message$= "Can't calculate Group Delay with zero sweep width." : call PrintMessage y1=-1 else call gGetSweepStartAndEndPointNum pStart, pEnd dir=gGetSweepDir() '1 or -1 if currStep=pStart-1 then y1=-1 'Need two points; only have one at first point else if useWorkArray then y1=(uWorkArray(currStep+1,2)-uWorkArray(currStep+1-dir,2))/360 _ else y1=(datatable(currStep,3)-datatable(currStep-dir,3))/360 'delta phase in cycles ver114=4h if y1>0.5 then y1=y1-1 else if y1<-0.5 then y1=y1+1 'Deal with wraparound ver114-6k if useWorkArray then deltaF=1000000*(uWorkArray(currStep+1,0)-uWorkArray(currStep+1-dir,0)) _ else deltaF=1000000*(datatable(currStep,1)-datatable(currStep-dir,1)) 'delta freq, cycles per second y1=0-y1/deltaF 'negative of delta phase over delta freq end if end if case constReact y1=Y1SourceI case constSerC call uEquivSeriesLC trueFreq, Y1SourceR, Y1SourceI, serL, serC y1=serC case constSerL call uEquivSeriesLC trueFreq, Y1SourceR, Y1SourceI, serL, serC y1=serL case constParC if Y2IsParComponent then y1=parC 'already calculated above as part of Y2 calc else call uEquivParallelRLC trueFreq, Y1SourceR, Y1SourceI, parR, parL, parC y1=parC end if case constParL if Y2IsParComponent then y1=parL 'already calculated above as part of Y2 calc else call uEquivParallelRLC trueFreq, Y1SourceR, Y1SourceI, parR, parL, parC y1=parL end if case else y1=Y1SourceI 'Error, but assign a value just to continue ver114-7p end select end if end sub 'ver114-7f added CreateReferenceSource sub CreateReferenceSource 'Return reference trace ver114-7e 'Create referenceSource() data in accordance with referenceLineType and referenceSpec$ 'refType describes the reference type: ' referenceLineType=0 No Reference lines ' referenceLineType=1 Use existing datatable() data ' referenceLineType=2 Calculate trace for RLC combo specified in spec$, per uParseRLC 'This routine is specific to the test setup. In the case of RLC combos, it can calculate impedance at a freq, and 'then determine the S21 that the impedance would generate in the S21 fixture, or it can generate S11 data 'based on the current ref impedance. if referenceLineType=0 then referenceSourceNumPoints=0 : exit sub if referenceLineType=2 then '2=RLC call uSetMaxWorkPoints gNumDynamicSteps()+1,3 uWorkNumPoints=gNumDynamicSteps()+1 for i=0 to uWorkNumPoints : uWorkArray(i+1,0)=datatable(i,1) : next i 'set up for uRLCComboResponse 'Calc response in whatever S11 or S21 setup the user has chosen if msaMode$="Reflection" then doSpecialR0=S21BridgeR0 : doSpecialJig$="S11" else doSpecialR0=S21JigR0 if S21JigAttach$="Series" then doSpecialJig$="S21Series" else doSpecialJig$="S21Shunt" end if isErr= uRLCComboResponse(referenceLineSpec$, doSpecialR0, doSpecialJig$) if isErr then notice "Invalid RLC reference specification" : exit sub 'uWorkArray now contains the db, degrees response for each frequency 'Transfer to referenceSource() referenceSourceNumPoints=uWorkNumPoints for i=1 to uWorkNumPoints referenceSource(i, 0)=uWorkArray(i, 0) 'freq referenceSource(i, 1)=uWorkArray(i, 1) 'db referenceSource(i, 2)=uWorkArray(i, 2) 'ang next i else 'referenceLineType=1; use current data referenceSourceNumPoints=gNumDynamicSteps()+1 for i=1 to uWorkNumPoints referenceSource(i, 0)=datatable(i-1, 1) 'freq referenceSource(i, 1)=datatable(i-1, 2) 'db referenceSource(i, 2)=datatable(i-1, 3) 'ang next i end if end sub 'ver114-7f added CreateReferenceTransform sub CreateReferenceTransform 'Transform referenceSource() data into actual graph data; put it into referenceTransform call uSetMaxWorkPoints referenceSourceNumPoints,3 uWorkNumPoints=referenceSourceNumPoints for i=1 to uWorkNumPoints uWorkArray(i, 0)=referenceSource(i, 0) 'freq uWorkArray(i, 1)=referenceSource(i, 1) 'db uWorkArray(i, 2)=referenceSource(i, 2) 'ang next i for i=1 to uWorkNumPoints 'Calc graph data from info just put into uWorkArray call CalcGraphData i-1, thispointy1, thispointy2, 1 'step num is one less than point num referenceTransform(i, 0)=referenceSource(i, 0) referenceTransform(i, 1)=thispointy1 referenceTransform(i, 2)=thispointy2 next i end sub 'ver114-7f added CreateReferenceTraces$ function CreateReferenceTraces$(tCol$, tSize,traceNum) 'Return reference trace ver114-7e 'The trace is created from the data in referenceTransform(). 'referenceTrace indicates which traces we want if (traceNum and referenceTrace)=0 then CreateReferenceTraces$="down" : exit function call uSetMaxWorkPoints referenceSourceNumPoints,3 uWorkNumPoints=referenceSourceNumPoints for i=1 to uWorkNumPoints uWorkArray(i, 0)=referenceTransform(i, 0) 'freq uWorkArray(i, 1)=referenceTransform(i, 1) 'ang uWorkArray(i, 2)=referenceTransform(i, 2) 'db next i CreateReferenceTraces$="color ";tCol$;";size ";tSize;";"; _ PrivateCreateReferenceTrace$(traceNum, 1, gNumDynamicSteps()+1) end function 'ver114-6i added CreateReferenceTrace; modver114-7f function PrivateCreateReferenceTrace$(traceNum, startPoint, endPoint) 'Return reference line for RLC combo 'We generate values from startPoint to endPoint for a reference trace, using data in uWorkArray() 'traceNum=1 for Y1 and 2 for Y2. 'color and size prefix not included span=endPoint-startPoint if span=0 then PrivateCreateReferenceTrace$="down" : exit function 'down is a NOP in order to have a valid command if span>20 then 'If large number of points, divide in half and then put the two halves together mid=startPoint+int(span/2) PrivateCreateReferenceTrace$=PrivateCreateReferenceTrace$(traceNum, startPoint, mid)+ _ PrivateCreateReferenceTrace$(traceNum, mid+1, endPoint) exit function end if call gGetIsPhase y1IsPhase, y2IsPhase if startPoint<>1 then 'If not very first point of trace, the starting point is the point before startPoint if traceNum=1 then if y1IsPhase then lastY=gAdjustPhaseToDisplay(1, startPoint-1, 1) else lastY=uWorkArray(startPoint-1, 1) call gConvertYToPix lastY, 0 else if y2IsPhase then lastY=gAdjustPhaseToDisplay(2, startPoint-1, 1) else lastY=uWorkArray(startPoint-1, 2) call gConvertYToPix 0,lastY end if lastX=gGetPointXPix(startPoint-1) 'Ref has same x pixel as main graph end if for currPoint=startPoint to endPoint 'create segment from prior point to this point, for both y1 and y2 as appropriate if traceNum=1 then if y1IsPhase then y=gAdjustPhaseToDisplay(1, currPoint, 1) else y=uWorkArray(currPoint, 1) call gConvertYToPix y, 0 else if y2IsPhase then y=gAdjustPhaseToDisplay(2, currPoint, 1) else y=uWorkArray(currPoint, 2) call gConvertYToPix 0,y end if x=gGetPointXPix(currPoint) 'Ref has same x pixel as main graph if currPoint=1 then t$="set ";x;" ";y 'just set the point else t$=t$;";"; "line ";lastX; " ";lastY;" ";x;" ";y end if lastX=x : lastY=y next currPoint 'Result is what we have put together so far, plus the final line drawn backward to 'be sure final point is fully drawn PrivateCreateReferenceTrace$=t$;";line ";x;" ";y;" ";lastX; " ";lastY end function [CreateRcounter]'needed:reference,appxpdf ; creates:rcounter,pdf 'ver111-4 rcounter = int(reference/appxpdf) 'ver111-4 if (reference/appxpdf) - rcounter >= .5 then rcounter = rcounter + 1 'rounds off rcounter 'ver111-4 pdf = reference/rcounter 'ver111-4 return 'to (Initialize PLL 3),[InitializePLL2],or[InitializePLL1]with rcounter,pdf 'ver111-4 [CommandPLL1R]'needed:rcounter1,PLL1mode,PLL1phasepolarity,SELT,PLL1 rcounter = rcounter1 preselector = 32 : if PLL1mode = 1 then preselector = 16 phasepolarity = PLL1phasepolarity 'inverting op amp is 0, non-inverting loop is 1 fractional = PLL1mode '0 for Integer-N; 1 for Fractional-N Jcontrol = SELT 'for PLL 1, on Control Board J1, the value is "3" LEPLL = 4 'for PLL 1, on Control Board J1, the value is "4" PLL = PLL1 gosub [CommandRBuffer]'needs:rcounter,preselector,phasepolarity,fractional,Jcontrol,LEPLL,PLL if len(errora$)>0 then error$ = "PLL 1, " + errora$ message$=error$ : call PrintMessage 'ver114-4e wait end if return [CommandPLL2R]'needed:reference,appxpdf,PLL2phasepolarity,SELT,PLL2 preselector = 32 phasepolarity = PLL2phasepolarity 'inverting op amp is 0, non-inverting loop is 1 fractional = 0 '0 for Integer-N; PLL 2 should not be fractional due to increased noise Jcontrol = SELT 'for PLL 2, on Control Board J2, the value is "3" LEPLL = 8 'for PLL 2, on Control Board J2, the value is "8" PLL = PLL2 gosub [CommandRBuffer]'needs:rcounter,preselector,phasepolarity,fractional,Jcontrol,LEPLL,PLL if len(errora$)>0 then error$ = "PLL 2, " + errora$ message$=error$ : call PrintMessage 'ver114-4e wait end if return 'to 'CommandPLL2R and Init Buffers [CommandPLL3R]'needed:PLL3mode,PLL3phasepolarity,INIT,PLL3 preselector = 32 : if PLL3mode = 1 then preselector = 16 phasepolarity = PLL3phasepolarity 'inverting op amp is 0, non-inverting loop is 1 fractional = PLL3mode '0 for Integer-N; 1 for Fractional-N Jcontrol = INIT 'for Tracking Gen PLL, on Control Board J3, the value is "15" LEPLL = 16 'for Tracking Gen PLL, on Control Board J3, the value is "16" PLL = PLL3 gosub [CommandRBuffer]'needs:rcounter,preselector,phasepolarity,fractional,Jcontrol,LEPLL,PLL if len(errora$)>0 then error$ = "PLL 3, " + errora$ message$=error$ : call PrintMessage 'ver114-4e wait end if return 'to 'CommandPLL3R and Init Buffers [CommandRBuffer]'needed:rcounter,preselector,phasepolarity,fractional,Jcontrol,LEPLL,PLL if PLL = 2325 then gosub [Command2325R]'needs:rcounter,preselector,Jcontrol,port,LEPLL,contclear ; commands LMX2325 rcounter and registers if PLL = 2326 then gosub [Command2326R]'needs:rcounter,phasepolarity,Jcontrol,port,LEPLL,contclear ; commands LMX2326 rcounter and registers if PLL = 2350 then gosub [Command2350R]'needs:rcounter,phasepolarity,Jcontrol,port,LEPLL,contclear,fractional ; commands LMX2350 rcounter if PLL = 2353 then gosub [Command2353R]'needs:rcounter,phasepolarity,Jcontrol,port,LEPLL,contclear,fractional ; commands LMX2353 rcounter if PLL = 4112 then gosub [Command4112R]'needs:rcounter,preselector,phasepolarity,Jcontrol,port,LEPLL,contclear ; commands AD4112 rcounter return [CreateIntegerNcounter]'needed:appxVCO,reference,rcounter ; creates:ncount,ncounter,fcounter(0),pdf ncount = appxVCO/(reference/rcounter) 'approximates the Ncounter for PLL ncounter = int(ncount) 'approximates the ncounter for PLL if ncount - ncounter >= .5 then ncounter = ncounter + 1 'rounds off ncounter fcounter = 0 pdf = appxVCO/ncounter 'actual phase freq of PLL return 'to 'CreatePLL2N,'[CalculateThisStepPLL1],or '[CalculateThisStepPLL3] with ncount, ncounter and fcounter(=0) [CreateFractionalNcounter]'needed:appxVCO,reference,rcounter ; creates:ncount,ncounter,fcounter,pdf ncount = appxVCO/(reference/rcounter) 'approximates the Ncounter for PLL ncounter = int(ncount) 'actual value for PLL Ncounter fcount = ncount - ncounter fcounter = int(fcount*16) 'ver111 if (fcount*16) - fcounter >= .5 then fcounter = fcounter + 1 'rounds off fcounter ver111 if fcounter = 16 then ncounter = ncounter + 1:fcounter = 0 pdf = appxVCO/(ncounter + (fcounter/16)) 'actual phase freq for PLL 'ver111-10 return 'with ncount,ncounter,fcounter,pdf [AutoSpur]'needed:LO1,LO2,finalfreq,appxdds1,dds1output,rcounter1,finalbw,fcounter,ncounter,spurcheck;changes pdf,dds1output '[AutoSpur] is a continuation of [CreateFractionalNcounter], used only in MSA when PLL 1 is Fractional spur = 0 'reset spur, and determine if there is potential for a spur firstif = LO2 - finalfreq fractionalfreq = dds1output/(rcounter1*16) harnonicb = int(firstif/fractionalfreq) if (firstif/fractionalfreq)-harnonicb >=.5 then harnonicb = harnonicb + 1 'rev108 harnonica = harnonicb - 1 harnonicc = harnonicb + 1 firstiflow = LO2 - (finalfreq + finalbw/1000) firstifhigh = LO2 - (finalfreq - finalbw/1000) if harnonica*fractionalfreq > firstiflow and harnonica*fractionalfreq < firstifhigh then spur = 1 if harnonicb*fractionalfreq > firstiflow and harnonicb*fractionalfreq < firstifhigh then spur = 1 if harnonicc*fractionalfreq > firstiflow and harnonicc*fractionalfreq < firstifhigh then spur = 1 if spur = 1 and (dds1outputappxdds1) then fcounter = fcounter + 1 if fcounter = 16 then ncounter = ncounter + 1:fcounter = 0 'rev108 if fcounter <0 then ncounter = ncounter - 1:fcounter = 15 'rev108 pdf = LO1/(ncounter + (fcounter/16)) dds1output = pdf * rcounter1 'actual output of DDS1(input Ref to PLL1) return 'with possibly new ncounter,fcounter,pdf,dds1output [ManSpur]'needed:spurcheck,dds1output,appxdds1,fcounter,ncounter '[ManSpur] is a continuation of [CreateFractionalNcounter], used only in MSA when PLL 1 is Fractional if spurcheck = 1 and (dds1outputappxdds1) then fcounter = fcounter + 1 'causes -shift in pdf1 if fcounter = 16 then ncounter = ncounter + 1:fcounter = 0 'rev108 if fcounter < 0 then ncounter = ncounter - 1:fcounter = 15 'rev108 pdf = LO1/(ncounter + (fcounter/16)) dds1output = pdf * rcounter1 'actual output of DDS1(input Ref to PLL1) return 'with possibly new:ncounter,fcounter,pdf,dds1output [CreatePLL1N]'needed:ncounter,fcounter,PLL1mode,PLL1 preselector = 32 : if PLL1mode = 1 then preselector = 16 PLL = PLL1 gosub [CreateNBuffer]'needs:ncounter,fcounter,PLL,preselector;creates:Bcounter,Acounter, and N Bits N0-Nx if len(errora$)>0 then error$ = "PLL 1, " + errora$ message$=error$ : call PrintMessage 'ver114-4e wait end if Bcounter1=Bcounter: Acounter1=Acounter return 'returns with Bcounter1,Acounter1,N0thruNx [CreatePLL2N]'needed:ncounter,fcounter,PLL2 preselector = 32 PLL = PLL2 gosub [CreateNBuffer]'needs:ncounter,fcounter,PLL,preselector;creates:Bcounter,Acounter, and N Bits N0-Nx if len(errora$)>0 then error$ = "PLL 2, " + errora$ message$=error$ : call PrintMessage 'ver114-4e wait end if return 'to 'CreatePLL2N [CreatePLL3N]'needed:ncounter,fcounter,PLL3mode,PLL3 ver111-14 preselector = 32 : if PLL3mode = 1 then preselector = 16 PLL = PLL3 gosub [CreateNBuffer]'needs:ncounter,fcounter,PLL,preselector;creates:Bcounter,Acounter, and N Bits N0-Nx if len(errora$)>0 then error$ = "PLL 3, " + errora$ message$=error$ : call PrintMessage 'ver114-4e wait end if Bcounter3=Bcounter: Acounter3=Acounter return 'returns with Bcounter3,Acounter3,N0thruNx [CreateNBuffer]'needed:PLL,ncounter,fcounter,preselector if PLL = 2325 then gosub [Create2325N]'needs:ncounter,preselector; creates LMX2325 N Buffer ver111 if PLL = 2326 then gosub [Create2326N]'needs:ncounter ; creates LMX2326 N Buffer ver111 if PLL = 2350 then gosub [Create2350N]'needs:ncounter,preselector,fcounter; creates LMX2350 RFN Buffer ver111 if PLL = 2353 then gosub [Create2353N]'needs: ncounter,preselector,fcounter; creates LMX2353 N Buffer ver111 if PLL = 4112 then gosub [Create4112N]'needs:ncounter,preselector; creates AD4112 N Buffer ver111 return 'with Bcounter,Acounter, and N Bits N0-N23 [Command2325R]'needed:rcounter,preselector,control,Jcontrol,port,LEPLL,contclear ; commands LMX2325 rcounter and registers if rcounter <3 then beep:errora$ = "2325 Rcounter is < 3":return 'with errora$ ver111-37c if rcounter >16383 then beep:errora$ = "2325 Rcounter is > 16383":return 'with errora$ ver111-37c N0 = 1 'address bit, 0 sets the N Buffer, 1 is for R Buffer rc1 = int(rcounter/2):N1 = rcounter - 2*rc1 'binary conversion from decimal rc2 = int(rc1/2):N2 = rc1 - 2*rc2 rc3 = int(rc2/2):N3 = rc2 - 2*rc3 rc4 = int(rc3/2):N4 = rc3 - 2*rc4 rc5 = int(rc4/2):N5 = rc4 - 2*rc5 rc6 = int(rc5/2):N6 = rc5 - 2*rc6 rc7 = int(rc6/2):N7 = rc6 - 2*rc7 rc8 = int(rc7/2):N8 = rc7 - 2*rc8 rc9 = int(rc8/2):N9 = rc8 - 2*rc9 rc10 = int(rc9/2):N10 = rc9 - 2*rc10 rc11 = int(rc10/2):N11 = rc10 - 2*rc11 rc12 = int(rc11/2):N12 = rc11 - 2*rc12 rc13 = int(rc12/2):N13 = rc12 - 2*rc13 rc14 = int(rc13/2):N14 = rc13 - 2*rc14 N15 = 1: if preselector = 64 then N15 = 0 'sets preselector divide ratio, 1=32, 0=64 gosub [CommandPLL]'needs:N23-N0,control,Jcontrol,port,contclear,LEPLL ; commands N23-N0,old ControlBoard ver111 return [Create2325N]'needed:ncounter,preselector; creates LMX2325 n buffer Bcounter = int(ncounter/preselector) Acounter = ncounter- (Bcounter * preselector) if Bcounter<3 then beep:errora$ = "2325 Bcounter < 3":return 'with errora$ ver111-37c if Bcounter>2047 then beep:errora$ = "2325 Bcounter > 2047":return 'with errora$ ver111-37c if Bcounter16383 then beep:errora$="2326 R counter >16383":return 'with errora$ ver111-37c N0 = 0 'R address bit 0, must be 0 N1 = 0 'R address vit 1, must be 0 ra0 = int(rcounter/2):N2 = rcounter- 2*ra0 'LSB ra1 = int(ra0/2):N3 = ra0- 2*ra1 ra2 = int(ra1/2):N4 = ra1- 2*ra2 ra3 = int(ra2/2):N5 = ra2- 2*ra3 ra4 = int(ra3/2):N6 = ra3- 2*ra4 ra5 = int(ra4/2):N7 = ra4- 2*ra5 ra6 = int(ra5/2):N8 = ra5- 2*ra6 ra7 = int(ra6/2):N9 = ra6- 2*ra7 ra8 = int(ra7/2):N10 = ra7- 2*ra8 ra9 = int(ra8/2):N11 = ra8- 2*ra9 ra10 = int(ra9/2):N12 = ra9- 2*ra10 ra11 = int(ra10/2):N13 = ra10- 2*ra11 ra12 = int(ra11/2):N14 = ra11- 2*ra12 ra13 = int(ra12/2):N15 = ra12- 2*ra13 'MSB N16 = 0 'Test Bit N17 = 0 'Test Bit N18 = 0 'Test Bit N19 = 0 'Test Bit N20 = 0 'Lock Detector Mode, 0=3 refcycles, 1=5 cycles '[Command2326Rbuffer]'need Jcontrol,LEPLL,contclear gosub [CommandPLL]'needs:N23-N0,control,Jcontrol,port,contclear,LEPLL ; commands N23-N0,old ControlBoard ver111 return [Create2326N]'needed:ncounter ; creates LMX2326 n buffer ver111 Bcounter = int(ncounter/32) Acounter = int(ncounter-(Bcounter*32)) if Bcounter < 3 then beep:errora$="2326 Bcounter <3":return 'with errora$ ver111-37c if Bcounter > 8191 then beep:errora$="2326 Bcounter >8191":return 'with errora$ ver111-37c if Bcounter < Acounter then beep:errora$="2326 Bcounter 32767 then beep:errora$="2350 Rcounter >32767":return 'with errora$ ver111-37c N0=0 '2350 RF_R register, 2 bits, must be 0 N1=1 '2350 RF_R register, 2 bits, must be 1 rfra2 = int(rcounter/2):N2 = rcounter- 2*rfra2 rfra3 = int(rfra2/2):N3 = rfra2- 2*rfra3 rfra4 = int(rfra3/2):N4 = rfra3- 2*rfra4 rfra5 = int(rfra4/2):N5 = rfra4- 2*rfra5 rfra6 = int(rfra5/2):N6 = rfra5- 2*rfra6 rfra7 = int(rfra6/2):N7 = rfra6- 2*rfra7 rfra8 = int(rfra7/2):N8 = rfra7- 2*rfra8 rfra9 = int(rfra8/2):N9 = rfra8- 2*rfra9 rfra10 = int(rfra9/2):N10 = rfra9- 2*rfra10 rfra11 = int(rfra10/2):N11 = rfra10- 2*rfra11 rfra12 = int(rfra11/2):N12 = rfra11- 2*rfra12 rfra13 = int(rfra12/2):N13 = rfra12- 2*rfra13 rfra14 = int(rfra13/2):N14 = rfra13- 2*rfra14 rfra15 = int(rfra14/2):N15 = rfra14- 2*rfra15 rfra16 = int(rfra15/2):N16 = rfra15- 2*rfra16 N17 = phasepolarity 'RF phase polarity, 1=positive action, 0=inverted action N18=1 'LSB of RF charge pump sel, 4 Bits, 16 levels, 100ua/level N19=1 'total current = (100ua * bit value)+100ua N20=1 '100ua to 1600ua: ie, 800ua = 0111, 1600ua = 1111 N21=1 'MSB of RF charge pump sel, 4 Bits 100ua/bit N22=0 'V2 enable voltage doubler =1 0=norm Vcc N23 = fractional 'DLL mode, delay line cal, 0=slow 1=fast,fractional mode '[CommandRFRbuffer2350] gosub [CommandPLL]'needs:N23-N0,control,Jcontrol,port,contclear,LEPLL ; commands N23-N0,old ControlBoard ver111 return [Create2350N]'needed: ncounter,preselector,fcounter; creates LMX2350 RFN Buffer Bcounter = int(ncounter/preselector) Acounter = int(ncounter-(Bcounter*preselector)) if Bcounter < 3 then beep:errora$="2350 Bcounter <3":return 'with errora$ ver111-37c if Bcounter > 1023 then beep:errora$="2350 Bcounter >1023":return 'with errora$ ver111-37c if Bcounter < Acounter + 2 then beep:errora$="2350 Bcounter32767 then beep:errora$ = "2353 Rcounter is > 32767":return 'with errora$ ver111-37c N0 = 0 'R address bit 0 N1 = 1 'R address bit 1 ra0 = int(rcounter/2):N2 = rcounter- 2*ra0 'LSB R buffer ra1 = int(ra0/2):N3 = ra0- 2*ra1:ra2 = int(ra1/2):N4 = ra1- 2*ra2 ra3 = int(ra2/2):N5 = ra2- 2*ra3:ra4 = int(ra3/2):N6 = ra3- 2*ra4 ra5 = int(ra4/2):N7 = ra4- 2*ra5:ra6 = int(ra5/2):N8 = ra5- 2*ra6 ra7 = int(ra6/2):N9 = ra6- 2*ra7:ra8 = int(ra7/2):N10 = ra7- 2*ra8 ra9 = int(ra8/2):N11 = ra8- 2*ra9:ra10 = int(ra9/2):N12 = ra9- 2*ra10 ra11 = int(ra10/2):N13 = ra10- 2*ra11:ra12 = int(ra11/2):N14 = ra11- 2*ra12 ra13 = int(ra12/2):N15 = ra12- 2*ra13:ra14 = int(ra13/2):N16 = ra13- 2*ra14 'MSB R buffer N17 = phasepolarity 'phase detector polarity 1=normal,0=reverse for opamp N18 = 1 'LSB of Charge pump control, 100ua x1 +100ua N19 = 1 'Charge pump control, 100ua x2 +100ua N20 = 1 'Charge pump control, 100ua x4 +100ua N21 = 1 'MSB of Charge pump control, 100ua x8 +100ua N22 = 0 'Charge Pump Voltage Doubler Enabled when 1 N23 = fractional 'Delay Line Loop Cal mode, set to 1 for fractional N '[Cmd2353Rbuffer] gosub [CommandPLL]'needs:N23-N0,control,Jcontrol,port,contclear,LEPLL ; commands N23-N0,old ControlBoard ver111 return [Create2353N]'needed: ncounter,preselector,fcounter; creates LMX2353 N Buffer Bcounter = int(ncounter/preselector) Acounter = int(ncounter-(Bcounter*preselector)) if Bcounter < 3 then beep:errora$ = "2353 Bcounter is < 3":return 'with errora$ ver111-37c if Bcounter > 1023 then beep:errora$ = "2353 Bcounter is > 1023":return 'with errora$ ver111-37c if Bcounter < Acounter + 2 then beep:errora$ = "2353 Bcounter < Acounter+2":return 'with errora$ ver111-37c N0 = 1 'n address bit 0 N1 = 1 'n address bit 1 f0 = int(fcounter/2):N2 = fcounter - 2*f0 'fcounter bit 0 f1 = int(f0/2):N3 = f0 - 2*f1 'fcounter bit 1 f2 = int(f1/2):N4 = f1 - 2*f2 'fcounter bit 2 f3 = int(f2/2):N5 = f2 - 2*f3 'fcounter bit 3 (0 to 15) na0 = int(Acounter/2):N6 = Acounter- 2*na0 'Acounter bit 0 LSB na1 = int(na0/2):N7 = na0 - 2*na1 na2 = int(na1/2):N8 = na1 - 2*na2 na3 = int(na2/2):N9 = na2 - 2*na3 na4 = int(na3/2):N10 = na3 - 2*na4 'Acounter bit 4 MSB nb0 = int(Bcounter/2):N11 = Bcounter- 2*nb0 'Bcounter bit 0 LSB nb1 = int(nb0/2):N12 = nb0 - 2*nb1 nb2 = int(nb1/2):N13 = nb1 - 2*nb2 nb3 = int(nb2/2):N14 = nb2 - 2*nb3 nb4 = int(nb3/2):N15 = nb3 - 2*nb4 nb5 = int(nb4/2):N16 = nb4 - 2*nb5 nb6 = int(nb5/2):N17 = nb5 - 2*nb6 nb7 = int(nb6/2):N18 = nb6 - 2*nb7 nb8 = int(nb7/2):N19 = nb7 - 2*nb8 nb9 = int(nb8/2):N20 = nb8 - 2*nb9 'Bcounter bit 9 MSB N21 = 0 :if preselector = 32 then N21 = 1 '0=16/17 1=32/33 N22 = 0 'power down if 1 N23 = 0 'counter reset if 1 return [Command4112R]'needed: rcounter,preselector,phasepolarity,control,Jcontrol,port,LEPLL,contclear ; commands AD4112 rcounter '[Create4112InitBuffer]'needed:preselector,phasepolarity N23=1 'N24,23 prescaler: 0=8, 1=16, 2=32, 3=64 N22=0 'preselector defaulted to 32 if preselector =8 then N23=0:N22=0 if preselector =16 then N23=0:N22=1 if preselector =64 then N23=1:N22=1 N21=0 'Power Down Mode, 0=async, 1=sync use 0 N20=1 'N22,21,20 Phase Current for Set 2 N19=1 'current= min current + min current*bit value N18=1 'use bit value of 7 and 4.7 Kohm for 5.0 ma N17=1 'N18,17,16 Phase Current for Set 1 N16=1 'current= min current + min current*bit value N15=1 'use bit value of 7 and 4.7 Kohm for 5.0 ma N14=0 'N15,14,13,12 Fastlock Timer cycles N13=0 '4 Bits, Cycles= 3 cycles + 4*bit value N12=0 'Fastlock Time out value, use 0 N11=0 'use 4 bit value = 0 N10=0 '0=Fastlock Mode 1 (command), 1=Mode 2 (automatic) N9=0 '1=Fastlock enabled, 0 =Fastlock Disabled N8=0 '1=Tristate the phase det output, use 0 N7 = phasepolarity 'Phase det polarity, 1=pos 0=neg N6=0 'FoLD control(pin14 output), 0= tristate, 1= Digital Lock Detect N5=0 '2= N Divider out, 3= High output, 4= R Divider output N4=0 '5= Open drain lock detect, 6= Serial Data output, 7= Low output N3=0 'PD1, Power Down, 0=normal operation, 1=select power down mode N2=0 '1= Counter Reset Enable, allows reset of R,N counters,use 0 N1=1 'F1 address bit 1, must be 1 N0=1 'F1 address bit 0, must be 1 '[Command4112InitBuffer] gosub [CommandPLL]'needs:N23-N0,control,Jcontrol,port,contclear,LEPLL ; commands N23-N0,old ControlBoard ver111 '[Create4112Rbuffer]'needs:rcounter if rcounter >16383 then beep:errora$="4112 R counter >16383":return 'with errora$ ver111-37c N0 = 0 'R address bit 0, must be 0 N1 = 0 'R address vit 1, must be 0 ra0 = int(rcounter/2):N2 = rcounter- 2*ra0 'LSB R0 ra1 = int(ra0/2):N3 = ra0- 2*ra1 ra2 = int(ra1/2):N4 = ra1- 2*ra2 ra3 = int(ra2/2):N5 = ra2- 2*ra3 ra4 = int(ra3/2):N6 = ra3- 2*ra4 ra5 = int(ra4/2):N7 = ra4- 2*ra5 ra6 = int(ra5/2):N8 = ra5- 2*ra6 ra7 = int(ra6/2):N9 = ra6- 2*ra7 ra8 = int(ra7/2):N10 = ra7- 2*ra8 ra9 = int(ra8/2):N11 = ra8- 2*ra9 ra10 = int(ra9/2):N12 = ra9- 2*ra10 ra11 = int(ra10/2):N13 = ra10- 2*ra11 ra12 = int(ra11/2):N14 = ra11- 2*ra12 ra13 = int(ra12/2):N15 = ra12- 2*ra13 'MSB N16 = 0 'N17,16 Antibacklash width N17 = 0 '0=3ns, 1=1.5ns, 2=6ns, 3=3ns N18 = 0 'Test Bit, use 0 N19 = 0 'Test Bit, use 0 N20 = 0 'Lock Detector Mode, 0=3 refcycles, 1=5 cycles N21 = 0 'resyncronization enable 0=normal, 1=resync prescaler N22 = 1 '0=resync with nondelayed rf input, 1=resync with delayed rf N23 = 0 'reserved, use 0 '[Command4112Rbuffer] gosub [CommandPLL]'needs:N23-N0,control,Jcontrol,port,contclear,LEPLL ; commands N23-N0,old ControlBoard ver111 return '[endCommand4112R] [Create4112N]'needed: ncounter,preselector; creates AD4112 N Buffer Bcounter = int(ncounter/preselector) Acounter = int(ncounter-(Bcounter*preselector)) if Bcounter < 3 then beep:errora$="4112 N counter <3":return 'with errora$ ver111-37c if Bcounter > 8191 then beep:errora$="4112 N counter >8191":return 'with errora$ ver111-37c if Bcounter < Acounter then beep:errora$="4112 B counter= ddsclock/2 then beep:message$="Error, ddsoutput > .5 ddsclock" : call PrintMessage :goto [Halted] 'ver114-4e end if base = int(fullbase) 'rounded down to whole number if fullbase - base >= .5 then base = base + 1 'rounded to nearest whole number 'now, the actual ddsoutput can be determined by: ddsoutput = base*ddsclock/2^32 'Create Parallel Words 'needed:base w0= 0 'a "1" here will activate the x4 internal multiplier, but not recommended w1= int(base/2^24) 'w1 thru w4 converts decimal base code to 4 words, each are 8 bit binary w2= int((base-(w1*2^24))/2^16) w3= int((base-(w1*2^24)-(w2*2^16))/2^8) w4= int(base-(w1*2^24)-(w2*2^16)-(w3*2^8)) 'Create Serial Bits'needed:base ; creates serial word bits; sw0 thru sw39 b0 = int(base/2):sw0 = base - 2*b0 'LSB, Freq-b0. sw is serial word bit b1 = int(b0/2):sw1 = b0 - 2*b1:b2 = int(b1/2):sw2 = b1 - 2*b2 b3 = int(b2/2):sw3 = b2 - 2*b3:b4 = int(b3/2):sw4 = b3 - 2*b4 b5 = int(b4/2):sw5 = b4 - 2*b5:b6 = int(b5/2):sw6 = b5 - 2*b6 b7 = int(b6/2):sw7 = b6 - 2*b7:b8 = int(b7/2):sw8 = b7 - 2*b8 b9 = int(b8/2):sw9 = b8 - 2*b9:b10 = int(b9/2):sw10 = b9 - 2*b10 b11 = int(b10/2):sw11 = b10 - 2*b11:b12 = int(b11/2):sw12 = b11 - 2*b12 b13 = int(b12/2):sw13 = b12 - 2*b13:b14 = int(b13/2):sw14 = b13 - 2*b14 b15 = int(b14/2):sw15 = b14 - 2*b15:b16 = int(b15/2):sw16 = b15 - 2*b16 b17 = int(b16/2):sw17 = b16 - 2*b17:b18 = int(b17/2):sw18 = b17 - 2*b18 b19 = int(b18/2):sw19 = b18 - 2*b19:b20 = int(b19/2):sw20 = b19 - 2*b20 b21 = int(b20/2):sw21 = b20 - 2*b21:b22 = int(b21/2):sw22 = b21 - 2*b22 b23 = int(b22/2):sw23 = b22 - 2*b23:b24 = int(b23/2):sw24 = b23 - 2*b24 b25 = int(b24/2):sw25 = b24 - 2*b25:b26 = int(b25/2):sw26 = b25 - 2*b26 b27 = int(b26/2):sw27 = b26 - 2*b27:b28 = int(b27/2):sw28 = b27 - 2*b28 b29 = int(b28/2):sw29 = b28 - 2*b29:b30 = int(b29/2):sw30 = b29 - 2*b30 b31 = int(b30/2):sw31 = b30 - 2*b31 'MSB, Freq-b31 sw32 = 0 'x4 multiplier, 1=enable, but not recommended sw33 = 0 'control bit sw34 = 0 'power down bit sw35 = 0 'phase data sw36 = 0 'phase data sw37 = 0 'phase data sw38 = 0 'phase data sw39 = 0 'phase data return '[endCreateBaseForDDSarray] [ResetDDS1par]'needed:control,STRBAUTO,contclear ; resets DDS1 on J5(OrigControlBd), into parallel mode out control, STRBAUTO 'wclk and fqud lines high, causing DDS "Reset" line to go high out control, contclear 'wclk and fqud lines low (all control lines low) return [ResetDDS1ser]'OrigControlBoard.needed:AUTO,STRB,STRBAUTO ; set DDS1(J5)to serial mode. ver113-2c 'DDS (AD9850/9851) can be hard wired. pin2=D2=0, pin3=D1=1,pin4=D0=1, D3-D7 are don't care. 'this will reset DDS into parallel, involk serial mode, then command zero output out port, 3 'data=0000 0011, if the DDS is not already hard wired '(reset DDS1 to parallel)Data,WCLK up,WCLK up and FQUD up,WCLK up and FQUD down,WCLK down out control, AUTO 'WCLK up, FQUD=0 out control, STRBAUTO 'WCLK=1 and FQUD up out control, AUTO 'WCLK=1, FQUD down out control, contclear 'WCLK down, FQUD=0 '(end reset DDS1 to parallel) '(involk serial mode DDS1)WCLK up, WCLK down, FQUD up, FQUD down out control, AUTO:out control, contclear 'WCLK up, WCLK down out control, STRB:out control, contclear 'FQUD up, FQUD down 'even if the DDS1, D0-D2 is not hard wired, it will be in Serial Mode '(end involk serial mode DDS1) '(command DDS1 to flush registers)D7=0,WCLK up,WCLK down,(repeat39more),FQUD up,FQUD down out port, 0 'D7=0 for thisloop = 0 to 39 out control, AUTO:out control, contclear 'D7=0,WCLK up,WCLK down next thisloop out control, STRB:out control, contclear 'FQUD up, FQUD down '(end command DDS1 flush)DDS will output a DC signal return [ResetDDS3ser]'OrigControlBoard.needed:AUTO,STRB,STRBAUTO ; set DDS3(J4)to serial mode. ver113-2c 'DDS3 (AD9850/9851) must be hard wired. pin2=D2=0, pin3=D1=1,pin4=D0=1, D3-D7 are don't care. out control, Jcontrol 'enable Control Board J connector '(reset DDS3 to parallel)WCLK up and FQUD up,WCLK down and FQUD down out port, 34 'WCLK up and FQUD up. DDS register pointer will reset '(end reset DDS1 to parallel) out port, sfqud:out port, 0 ' DDSpin8, FQUD up, FQUD down. DDS register pointer will reset out port, swclk:out port, 0 ' DDSpin9, WCLK up, DDS WCLK down out port, sfqud:out port, 0 ' DDSpin8, FQUD up, FQUD down. DDS will go to 0 Hz. out control, contclear 'disable Control Board J connector return [ResetDDS1serSLIM]'reset serial DDS1 without disturbing Filter Bank or PDM. ver113-2c 'must have DDS (AD9850/9851) hard wired. pin2=D2=0, pin3=D1=1,pin4=D0=1, D3-D7 are don't care. 'this will reset DDS into parallel, involk serial mode, then command to 0 Hz. pdmcmd = phaarray(thisstep,0) 'ver111-39d '(reset DDS1 to parallel)WCLK up,WCLK up and FQUD up,WCLK up and FQUD down,WCLK down out port, filtbank + 1 'apply last known filter path and WCLK=D0=1 to buffer out control, SELT 'DDSpin9, WCLK up to DDS out control, contclear 'disable buffer,leaving filtbank, and WCLK=high to DDS out port, pdmcmd*64 + 2 'apply last known pdmcmd and FQUD=D3=1 to buffer out control, INIT 'DDSpin8, FQUD up,DDS resets to parallel,register pointer will reset out port, pdmcmd*64 'DDSpin8, FQUD down out control, contclear 'disable buffer, leaving last known PDM state latched out port, filtbank 'apply last known filter path and WCLK=D0=0 to buffer out control, SELT 'DDSpin9, WCLK down out control, contclear 'disable buffer,leaving filtbank '(end reset DDS1 to parallel) '(involk serial mode DDS1)WCLK up, WCLK down, FQUD up, FQUD down out port, filtbank + 1 'apply last known filter path and WCLK=D0=1 to buffer out control, SELT 'DDSpin9, WCLK up to DDS out port, filtbank 'apply last known filter path and WCLK=D0=0 to DDS out control, contclear 'disable buffer,leaving filtbank out port, pdmcmd*64 + 2 'apply last known pdmcmd and FQUD=D3=1 to buffer out control, INIT 'DDSpin8, FQUD up,DDS resets to parallel,register pointer will reset out port, pdmcmd*64 'DDSpin8, FQUD down out control, contclear 'disable buffer, leaving last known PDM state latched '(end involk serial mode DDS1) '(flush and command DDS1)D7,WCLK up,WCLK down,(repeat39more),FQUD up,FQUD down 'present data to buffer,latch buffer,disable buffer,present data+clk to buffer,latch buffer,disable buffer a=filtbank for thisloop = 0 to 39 out port, a:out control, SELT:out control, contclear: out port, a+1:out control, SELT:out control, contclear next thisloop out port, a:out control, SELT:out control, contclear 'leaving filtbank latched out port, pdmcmd*64 + 2 'apply last known pdmcmd and FQUD=D3=1 to buffer out control, INIT 'DDSpin8, FQUD up,DDS resets to parallel,register pointer will reset out port, pdmcmd*64 'DDSpin8, FQUD down out control, contclear 'disable buffer, leaving last known PDM state latched '(end flush command DDS1) return 'to '[InitializeDDS1] [ResetDDS3serSLIM]'reset serial DDS3 without disturbing Filter Bank or PDM. ver113-2c 'must have DDS (AD9850/9851) hard wired. pin2=D2=0, pin3=D1=1,pin4=D0=1, D3-D7 are don't care. 'this will reset DDS into parallel, involk serial mode, then command to 0 Hz. pdmcmd = phaarray(thisstep,0) 'ver111-39d '(reset DDS3 to parallel)WCLK up,WCLK up and FQUD up,WCLK up and FQUD down,WCLK down out port, filtbank + 1 'apply last known filter path and WCLK=D0=1 to buffer out control, SELT 'DDSpin9, WCLK up to DDS out control, contclear 'disable buffer,leaving filtbank, and WCLK=high to DDS out port, pdmcmd*64 + 8 'apply last known pdmcmd and FQUD=D3=1 to buffer out control, INIT 'DDSpin8, FQUD up,DDS resets to parallel,register pointer will reset out port, pdmcmd*64 'DDSpin8, FQUD down out control, contclear 'disable buffer, leaving last known PDM state latched out port, filtbank 'apply last known filter path and WCLK=D0=0 to buffer out control, SELT 'DDSpin9, WCLK down out control, contclear 'disable buffer,leaving filtbank '(end reset DDS3 to parallel) '(involk serial mode DDS3)WCLK up, WCLK down, FQUD up, FQUD down out port, filtbank + 1 'apply last known filter path and WCLK=D0=1 to buffer out control, SELT 'DDSpin9, WCLK up to DDS out port, filtbank 'apply last known filter path and WCLK=D0=0 to DDS out control, contclear 'disable buffer,leaving filtbank out port, pdmcmd*64 + 8 'apply last known pdmcmd and FQUD=D3=1 to buffer out control, INIT 'DDSpin8, FQUD up,DDS resets to parallel,register pointer will reset out port, pdmcmd*64 'DDSpin8, FQUD down out control, contclear 'disable buffer, leaving last known PDM state latched '(end involk serial mode DDS3) '(flush and command DDS3)D7,WCLK up,WCLK down,(repeat39more),FQUD up,FQUD down 'present data to buffer,latch buffer,disable buffer,present data+clk to buffer,latch buffer,disable buffer a=filtbank for thisloop = 0 to 39 out port, a:out control, SELT:out control, contclear: out port, a+1:out control, SELT:out control, contclear next thisloop out port, a:out control, SELT:out control, contclear 'leaving filtbank latched out port, pdmcmd*64 + 8 'apply last known pdmcmd and FQUD=D3=1 to buffer out control, INIT 'DDSpin8, FQUD up,DDS resets to parallel,register pointer will reset out port, pdmcmd*64 'DDSpin8, FQUD down out control, contclear 'disable buffer, leaving last known PDM state latched '(end flush command DDS3) return 'to '(InitializeDDS 3) 'SEWgraph rewrote RequireRestart sub RequireRestart 'Disable OneStep and Continue so user can only proceed by Restart if doingInitialization then exit sub 'Buttons don't exist yet ver114-3f haltsweep=0 call DisplayButtonsForHalted #handle.OneStep, "!disable" #handle.Continue, "!disable" end sub 'SEWgraph rewrote DisplayButtonsForRunning sub DisplayButtonsForRunning 'Display buttons for sweep in progress if doingInitialization then exit sub 'Buttons don't exist yet ver114-3f #handle.OneStep, "!enable" #handle.Continue, "!enable" print #handle.Restart, "Running" 'ver114-4c deleted print to #main.restart 'OneStep becomes HaltAtEnd when scan is in progress #handle.OneStep, "Halt At End" 'SEWgraph 'Continue becomes Halt when scan is in progress #handle.Continue, "Halt" 'SEWgraph #handle.Redraw, "!hide" 'SEWgraph hide during scan end sub 'SEWgraph rewrote DisplayButtonsForHalted sub DisplayButtonsForHalted 'Display buttons for sweep halted, to enable resuming or restarting if doingInitialization then exit sub 'Buttons don't exist yet ver114-3f #handle.OneStep, "!enable" #handle.Continue, "!enable" print #handle.Restart, "Restart" 'ver114-4c deleted print to #main.restart 'OneStep becomes HaltAtEnd when scan is in progress #handle.OneStep, "One Step" 'SEWgraph 'Continue becomes Halt when scan is in progress #handle.Continue, "Continue" 'SEWgraph #handle.Redraw, "!show" 'SEWgraph hide during scan end sub 'ver114-5j added [menuVNARef] [menuVNARef] if haltsweep=1 then gosub [FinishSweeping] WindowWidth = 150 : WindowHeight = 150 UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = DisplayHeight-WindowHeight-100 BackgroundColor$="darkblue" ForegroundColor$="white" TextboxColor$="blue" ComboboxColor$="blue" VNAinfoLeft=15 : VNAapplyTop=10 if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then statictext #VNAref.Apply, "Reference Transmission Measurements To:",VNAinfoLeft,VNAapplyTop+10,120, 35 else statictext #VNAref.Apply, "Reference Reflection Measurements To:",VNAinfoLeft,VNAapplyTop+10,120, 35 end if 'ver114-7q separated the captions from the checkboxes so the text color comes out right checkbox #VNAref.Line, "", [VNAapplyLineOn], [VNAapplyLineOff], VNAinfoLeft+5,VNAapplyTop+45, 25, 15 statictext #VNAref, "Band Sweep Cal", VNAinfoLeft+25,VNAapplyTop+45, 130, 15 checkbox #VNAref.BaseLine, "", [VNAapplyBaseLineOn], [VNAapplyBaseLineOff], VNAinfoLeft+5,VNAapplyTop+65, 25, 15 statictext #VNAref, "Baseline Cal", VNAinfoLeft+25,VNAapplyTop+65, 130, 15 checkbox #VNAref.None, "", [VNAapplyNoneOn], [VNAapplyNoneOff], VNAinfoLeft+5,VNAapplyTop+85, 25, 15 statictext #VNAref, "No Reference", VNAinfoLeft+25,VNAapplyTop+85, 120, 15 open "Ref" for dialog_modal as #VNAref 'ver114-7q print #VNAref, "trapclose [VNARefFinished]" 'goto [finished] if xit is clicked saveDesiredLineCalLevel=desiredLineCalLevel 'ver114-5L if desiredLineCalLevel=0 then #VNAref.None, "set" : wait if desiredLineCalLevel=2 then #VNAref.Line, "set" : wait #VNAref.BaseLine, "set" wait 'ver114-5j added [VNARefFinished] [VNARefFinished] #VNAref.None, "value? calLevel$" if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then if calLevel$="set" then desiredLineCalLevel=0 else #VNAref.BaseLine, "value? calLevel$" if calLevel$="set" then desiredLineCalLevel=1 else desiredLineCalLevel=2 end if 'Implement selected calibration if anything changed if saveDesiredLineCalLevel<>desiredLineCalLevel then 'ver114-5L created if... applyLineCalLevel=0 'Pretend nothing is now installed installedBaseLineNumSteps=-1 'ver114-7L corrected variable name call RequireRestart end if else 'TO DO Must implement Reflection end if close #VNAref wait 'ver114-5e added the following methods to make the Line, BaseLine, and None checkboxes act like 'radio buttons. Actual radio buttons on dialogs have bugs. 'ver114-5j made these part of the Reference dialog [VNAapplyLineOn] #VNAref.BaseLine, "reset" : #VNAref.None, "reset" :wait [VNAapplyLineOff] #VNAref.Line, "set" : wait [VNAapplyBaseLineOn] #VNAref.Line, "reset" : #VNAref.None, "reset" : wait [VNAapplyBaseLineOff] #VNAref.BaseLine, "set" : wait [VNAapplyNoneOn] #VNAref.BaseLine, "reset" : #VNAref.Line, "reset" : wait [VNAapplyNoneOff] #VNAref.None, "set" : wait 'ver114-5k added [menuCalPDM] [menuCalPDM] if haltsweep=1 then gosub [FinishSweeping] WindowWidth = 475 : WindowHeight = 325 UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = 75 'ver114-7i BackgroundColor$="darkblue" ForegroundColor$="white" TextboxColor$="blue" ComboboxColor$="blue" s$="The actual phase shift caused by PDM inversion will differ from the theoretical" s$=s$;" 180 degrees. A one-time calibration is required to determine the actual phase shift." s$=s$;" This value will be used internally, and you will not directly need to know or use the value." s$=s$;" To perform this calibration you first need to do the following, which will require that" s$=s$;" you close this window and return to the Graph Window:" statictext #PDMcal.t1, s$,15,15,400, 100 statictext #PDMcal.t2, "*Set Video Filter to NARROW bandwidth.",25,112,400, 16 statictext #PDMcal.t3, "*Connect Tracking Generator output to MSA input with 1-2 foot cable.",25,129,400, 16 statictext #PDMcal.t4, "*In menu Operating Cal->Transmission, set Transmission Reference to No Reference.",25,146,450, 16 'ver114-5L'ver114-5n statictext #PDMcal.t5, "*Sweeping 0-200 MHz, find a frequency with a phase shift near 90 or 270 deg.",25,163,450, 16 statictext #PDMcal.t6, "*Center the sweep at that frequency, with zero sweep width.",25,180,400, 16 statictext #PDMcal.t7, "*Return to this window and click the PDM Inversion Cal button.",25,197,400, 16 button #PDMcal.PDM, "PDM Inversion Cal",[DoPDMCal], UL, 150, 220, 100,20 statictext #PDMcal.PDMval, "Current Inversion=xxx deg.",140,240,150, 15 button #PDMcal.Done, "Save New Value and Quit",[PDMCalFinished], UL, 60, 265, 140,20 button #PDMcal.Cancel, "Cancel",[PDMCalCancel], UL, 250, 265, 75,20 open "PDM Calibration" for dialog_modal as #PDMcal 'ver114-3g print #PDMcal, "trapclose [PDMCalWait]" #PDMcal.t1, "!font Times_New_Roman size 10" #PDMcal.t2, "!font Times_New_Roman size 9" #PDMcal.t3, "!font Times_New_Roman size 9" #PDMcal.t4, "!font Times_New_Roman size 9" #PDMcal.t5, "!font Times_New_Roman size 9" #PDMcal.t6, "!font Times_New_Roman size 9" #PDMcal.t7, "!font Times_New_Roman size 9" #PDMcal.PDMval, "Current Inversion=";invdeg;" deg." doingPDMCal=0 'ver114-5L deleted use of saveinvdeg CalInvDeg=360 'Will change if cal is done ver114-5L wait 'ver114-5k added [PDMCalWait] [PDMCalWait] wait 'ver114-5k added [PDMCalCancel] [PDMCalCancel] close #PDMcal wait 'ver114-5k added [PDMCalFinished] [PDMCalFinished] if doingPDMCal=1 then wait 'Don't allow quit in middle of cal if CalInvDeg<>360 then invdeg=CalInvDeg 'ver114-5L use calibrated value if cal was done globalPort=port call configSaveFile close #PDMcal wait 'ver114-5j added [DoPDMCal]; Modified by ver114-5k [DoPDMCal] 'Run PDM calibration and display resulting invdeg if doingPDMCal=1 then goto [PostScan] 'continue on; don't stop ver114-5L doingPDMCal=1 'ver114-5L #PDMcal.PDMval, "Current Inversion= " #PDMcal.Done, "!disable" : #PDMcal.Cancel, "!disable" #PDMcal.PDM, "Be Patient" gosub [CalPDMinvdeg] #PDMcal.Done, "!enable" : #PDMcal.Cancel, "!enable" #PDMcal.PDMval, "Current Inversion= "; CalInvDeg ;" deg." 'Calibration result ver114-5L #PDMcal.PDM, "PDM Inversion Cal" doingPDMCal=0 'ver114-5L wait 'ver114-5e added [RunVNACal] [RunVNACal] if haltsweep=1 then gosub [FinishSweeping] WindowWidth = 550 : WindowHeight = 300 UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = DisplayHeight-WindowHeight-50 BackgroundColor$="darkblue" ForegroundColor$="white" TextboxColor$="blue" ComboboxColor$="blue" statictext #VNAcal.Path1, "The MSA is currently in Path X.",110,15,350, 18 statictext #VNAcal.Path2, "MSA calibrations are not saved separately for different paths. If the current path is not the one",25,35,520, 18 statictext #VNAcal.Path3, "for which the calibration will be used, close this window and change the path selection.",25,52,520, 18 statictext #VNAcal.Video, "VIDEO FILTER should be set to NARROW bandwidth for maximum smoothing.",25,75,520, 18 VNAbtnLeft=25 : VNAbtnTop=80 s$="Band Sweep calibration is run at the same frequency points at which it will be used." s$=s$;" It is most accurate if performed shortly before use, and is not saved to a file." statictext #VNAcal.BandInst, s$,VNAbtnLeft+25,VNAbtnTop+37,450, 35 checkbox #VNAcal.selBand, "", [setBand], [resetBand], VNAbtnLeft, VNAbtnTop+40, 25, 25 checkbox #VNAcal.selBase, "", [resetBand], [setBand], VNAbtnLeft, VNAbtnTop+70, 25, 25 'ver114-7L changed some text lengths. if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then s$="Baseline Calibration is a broadband sweep useable as a coarse reference, even if its frequency points" s$=s$;" don't match the current sweep. It is saved to a file for use in subsequent sessions." statictext #VNAcal.BaseInst, s$,VNAbtnLeft+25,VNAbtnTop+70,450, 40 statictext #VNAcal.connect, "TG output must have THROUGH connection to MSA input.",25,95,520, 18 else s$="Baseline Calibration is a broadband sweep useable as a coarse reference, even if its frequency points" s$=s$;"don't match the current sweep parameters. OSL Baseline Calibration is saved internally but is not saved to a file." statictext #VNAcal.BaseInst, s$,VNAbtnLeft+25,VNAbtnTop+70,400, 40 statictext #VNAcal.connect, "TG output and MSA input must be connected to bridge, and proper cal standards attached.",45,95,450, 18 end if statictext #VNAcal.LastCal, "xx",VNAbtnLeft,VNAbtnTop+125,475, 18 button #VNAcal.Perform, "Do Band Sweep",[PerformCal], UL, VNAbtnLeft+10, VNAbtnTop+150, 120,20 'ver114-5f button #VNAcal.Clear, "Clear Band Sweep",[ClearCal], UL, VNAbtnLeft+175, VNAbtnTop+150, 120,20 'ver114-5f button #VNAcal.Done, "Done",[VNACalFinished], UL, VNAbtnLeft+400, VNAbtnTop+145, 75,30 open "Perform Calibrations" for dialog_modal as #VNAcal 'ver114-3g print #VNAcal, "trapclose [VNACalFinished]" 'goto [finished] if xit is clicked #VNAcal.Path1, "!font Times_New_Roman size 10" #VNAcal.Path2, "!font Times_New_Roman size 10" #VNAcal.Path3, "!font Times_New_Roman size 10" #VNAcal.Video, "!font Times_New_Roman size 10" #VNAcal.connect, "!font Times_New_Roman size 10" #VNAcal.Path1, "The MSA is currently in "; path$ 'ver114-5p calInProgress=0 BaseLineCalDone=0 : BandSweepCalDone=0 'ver114-5L BaseOSLCalDone=0 : BandOSLCalDone=0 goto [setBand] [VNACalFinished] if calInProgress=1 then goto [PostScan] 'Don't allow quit in middle of cal 'If we did a cal, make it the desired one and force restart to implement if BaseLineCalDone=1 or BandSweepCalDone=1 then 'ver114-5L created if... if BaseLineCalDone then desiredLineCal=1 'desire BaseLine ver114-5L if BandSweepCalDone then desiredLineCal=2 'desire BandSweep; overrides BaseLine ver114-5L applyLineCalLevel=0 'Pretend nothing is now installed, so new cal gets installed on Restart installedBaseLineNumSteps=-1 'ver114-7L corrected name call RequireRestart 'To activate desired cal; graph is messed up anyway ver114-5L end if close #VNAcal 'ver114-5n moved this outside the if... block wait [setBand] #VNAcal.selBand, "set" : #VNAcal.selBase, "reset" #VNAcal.Perform, "Perform Band Sweep" #VNAcal.Clear, "Clear Band Sweep" #VNAcal.LastCal, CalInfo$(bandLinePath$, bandLineTimeStamp$, bandLineLinear, _ bandLineNumSteps, bandLineStartFreq, bandLineEndFreq) wait [resetBand] #VNAcal.selBand, "reset" : #VNAcal.selBase, "set" #VNAcal.Perform, "Perform Baseline" #VNAcal.Clear, "Clear Baseline" #VNAcal.LastCal, CalInfo$(baseLinePath$, baseLineTimeStamp$, baseLineLinear, _ baseLineNumSteps, baseLineStartFreq, baseLineEndFreq) wait function CalInfo$(cPath$, dateStamp$, cLinear, nSteps, fStart, fEnd) 'Return line cal info in a string if nSteps<0 then CalInfo$="Calibration is cleared." : exit function if cLinear then lin$="linear" else lin$="log" CalInfo$="Last performed ";dateStamp$;" in ";cPath$;" with ";lin$;" sweep, ";nSteps;" steps from ";fStart;" to ";fEnd;" MHz." end function 'ver114-5f added BandLineCalIsCurrent() function BandLineCalIsCurrent() 'Returns 1 if full line cal data was taken at current sweep settings 'Current means the full line cal exists and matches current sweep params call gGetXAxisRange xMin, xMax if globalSteps=bandLineNumSteps and gGetXIsLinear()=bandLineLinear and _ xMin=bandLineStartFreq and xMax=bandLineEndFreq then _ BandLineCalIsCurrent=1 else BandLineCalIsCurrent=0 'ver114-7L end function 'ver114-7L added BaseLineCalIsCurrent function BaseLineCalIsCurrent() 'Returns 1 if OSL band cal has valid data even if different sweep params 'Current does not mean it is actually installed if baseLineNumSteps>0 and path$=baseLinePath$ and baseLineS21JigAttach$=S21JigAttach$ and _ baseLineS21JigR0=S21JigR0 then isCurr=1 else isCurr=0 if isCurr then BaseLineCalIsCurrent=1 else BaseLineCalIsCurrent=0 : installedBaseLineNumSteps=-1 'Indicate not validly installed ver114-7n end if end function function BaseLineCalIsInstalled() 'Returns 1 if base line cal is already installed at current sweep params 'Current means the full line cal exists and was last installed with sweep params matching the current params if BaseLineCalIsCurrent()=0 then BaseLineCalIsInstalled=0 : exit function 'Don't have current base cal ver114-7L call gGetXAxisRange xMin, xMax if globalSteps=installedBaseLineNumSteps and gGetXIsLinear()=installedBaseLineLinear and _ xMin=installedBaseLineStartFreq and xMax=installedBaseLineEndFreq then _ BaseLineCalIsInstalled=1 else BaseLineCalIsInstalled=0 'ver114-7L end function 'ver114-5f added InstallSelectedLineCal sub InstallSelectedLineCal 'Apply full line cal or baseLine cal per applyLineCalLevel 'We put the necessary data into lineCalArray, and set actualLineCalLevel to 0(None), 1 (BaseLine) 'or 2 (Full LineCal) to indicate the level of line cal actually installed. 'If applyLineCalLevel=2 and LineCal is current, install it if desiredLineCalLevel=2 then isCurr=BandLineCalIsCurrent() if applyLineCalLevel=2 and isCurr then exit sub 'ver114-7L if isCurr then applyLineCalLevel=2 else applyLineCalLevel=1 else applyLineCalLevel=1 end if if applyLineCalLevel=2 then installedBaseLineNumSteps=-1 'Indicate that base line cal is not installed ver114-7L fixed typo for i=0 to globalSteps 'retrieve data lineCalArray(i,1)=bandLineCal(i,1) 'mag lineCalArray(i,2)=bandLineCal(i,2) 'Phase next i exit sub end if 'We get here if applyLineCalLevel<2 or we did not have a current LineCal, so use BaseLineCal if desiredLineCalLevel>0 then if BaseLineCalIsCurrent() then applyLineCalLevel=1 else applyLineCalLevel=0 'ver114-7L else applyLineCalLevel=0 end if if applyLineCalLevel=1 then 'We want and have BaseLine cal, so install it if BaseLineCalIsInstalled() then exit sub 'Already installed with these sweep params 'ver114-5p changed interpolation to use the new Interpolation Module if msaMode$="SA" or msaMode$="ScalarTrans" then doPhase=0 :doParams=1 'do mag only else doPhase=1 :doParams=3 'Do both mag and phase end if call intSetMaxNumPoints baseLineNumSteps 'Be sure we have room ver114-5q call intClearSrc : call intClearDest for i=0 to baseLineNumSteps 'copy cal table to intSrc call intAddSrcEntry baseLineCal(i,0),baseLineCal(i,1),gNormalizePhase(baseLineCal(i,2)) next i for i=1 to globalSteps+1 call intAddDestFreq gGetPointXVal(i) 'Install frequencies in intDest next i call intSrcToDest doPhase, 0, doParams, 1 'Do the actual interpolation into intDest() for i=0 to globalSteps 'put the data where we want it call intGetDest i+1,f, m, p lineCalArray(i,0)=f lineCalArray(i,1)=int(100*m+0.5)/100 'mag rounded to two decimals p=gNormalizePhase(int(100*p+0.5)/100) 'phase rounded to two decimals -180 to 180 lineCalArray(i,2)=p next i 'Save the sweep params under which we installed base line cal installedBaseLineStartFreq=startfreq installedBaseLineEndFreq=endfreq installedBaseLineNumSteps=globalSteps installedBaseLineLinear=gGetXIsLinear() 'installedBaseLinePath$=path$ delver114-7L exit sub end if 'end of applying baseLine cal 'Here we want no type of line cal, so clear lineCalArray call ClearCalarray globalSteps end sub 'ver114-5f added ClearCalarray sub ClearCalarray nSteps 'Clear array containing current line cal data for i=0 to nSteps : lineCalArray(i,0)=0 : lineCalArray(i,1)=0 : lineCalArray(i,2)=0 : next i installedBaseLineNumSteps=-1 applyLineCalLevel=0 'Signal that none is installed end sub 'ver114-5j added SetCalButtonStatus sub SetCalButtonStatus stat$ 'Enable or disable all calibration buttons 'stat$ should be "!enable" or "!disable" #VNAcal.Perform, stat$ #VNAcal.Clear, stat$ #VNAcal.Done, stat$ end sub 'ver114-5j added [CalAborted] [CalAborted] 'Common routine for aborting calibration gosub [FinishSweeping] 'Finish nicely 'ver114-7d #VNAcal.selBase, "value? doBase$" if doBase$="set" then #VNAcal.Perform, "Perform Baseline" else #VNAcal.Perform, "Perform Band Sweep" 'ver114-1L fixed typo specialOneSweep=0 calInProgress=0 'ver114-5L sweepDir=saveSweepDir : alternateSweep=saveAlternate planeadj=savePlaneAdj : wate=saveWate call SetCalButtonStatus "!enable" 'ver114-6k return [PerformCal] if msaMode$="Reflection" then wait 'TO DO--must implement else #VNAcal.selBase, "value? doBase$" if doBase$="set" then goto [BaseLineCal] else goto [BandLineCal] end if wait [ClearCal] if msaMode$="Reflection" then wait 'TO DO--must implement else #VNAcal.selBase, "value? doBase$" if doBase$="set" then 'Clear baseline and delete the file baseLineNumSteps=-1 Kill DefaultDir$;"\MSA_Info\OperatingCal\BaseLineCal.txt" goto [resetBand] 'to display info else 'Clear band sweep bandLineNumSteps=-1 goto [setBand] 'to display info end if end if wait 'ver114-5f addedd [LineCal] [BandLineCal] 'Run Line Calibration if calInProgress then gosub [CalAborted] : wait call SetCalButtonStatus "!disable" #VNAcal.Perform, "!enable" : #VNAcal.Perform, "Abort Cal" calInProgress=1 haltsweep=0 'So Restart will actually restart. ver114-4f specialOneSweep=1 saveAlternate=alternateSweep : saveSweepDir=sweepDir : savePlaneAdj=planeadj : saveWate=wate alternateSweep=0 : sweepDir=1 : wate=100 planeadj=0 'So phase will not be affected applyLineCalLevel=0 'ver114-5g gosub [Restart] 'Perform one sweep and fill datatable(,) specialOneSweep=0 sweepDir=saveSweepDir : alternateSweep=saveAlternate planeadj=savePlaneAdj : wate=saveWate 'Cal data is now in datatable for i=0 to steps 'retrieve data bandLineCal(i,0)=datatable(i,1) 'frequency bandLineCal(i,1)=datatable(i,2) 'mag bandLineCal(i,2)=datatable(i,3) 'Phase next i 'Save the conditions under which the cal was done bandLineStartFreq=startfreq bandLineEndFreq=endfreq bandLineNumSteps=steps bandLineLinear=gGetXIsLinear() bandLineS21JigAttach$=S21JigAttach$ 'ver114-7L bandLineS21JigR0=S21JigR0 'ver114-7L bandLinePath$=path$ bandLineTimeStamp$=date$("mm/dd/yy"); "; ";time$() calInProgress=0 #VNAcal.Perform, "Perform Band Sweep" call SetCalButtonStatus "!enable" desiredLineCalLevel=2 'opt for using band cal since we just did it ver114-6b BandSweepCalDone=1 'ver114-5L goto [setBand] 'To display info 'ver114-5f addedd [BaseLineCal] [BaseLineCal] 'Run BaseLine Calibration if calInProgress then gosub [CalAborted] : wait call SetCalButtonStatus "!disable" #VNAcal.Perform, "!enable" : #VNAcal.Perform, "Abort Cal" calInProgress=1 haltsweep=0 'So Restart will actually restart. ver114-4f specialOneSweep=1 saveAlternate=alternateSweep : saveSweepDir=sweepDir : savePlaneAdj=planeadj : saveWate=wate wate=100 planeadj=0 'So phase will not be affected applyLineCalLevel=0 'ver114-5g gosub [Restart] 'Perform one sweep and fill datatable(,) specialOneSweep=0 sweepDir=saveSweepDir : alternateSweep=saveAlternate planeadj=savePlaneAdj : wate=saveWate 'Cal data is now in datatable for i=0 to steps 'retrieve data baseLineCal(i,0)=datatable(i,1) 'frequency baseLineCal(i,1)=datatable(i,2) 'mag baseLineCal(i,2)=datatable(i,3) 'Phase next i 'Save the conditions under which the cal was done baseLineStartFreq=startfreq baseLineEndFreq=endfreq baseLineNumSteps=steps baseLineLinear=gGetXIsLinear() baseLineS21JigAttach$=S21JigAttach$ 'ver114-7L baseLineS21JigR0=S21JigR0 'ver114-7L baseLinePath$=path$ baseLineTimeStamp$=date$("mm/dd/yy"); "; ";time$() calInProgress=0 #VNAcal.Perform, "Perform Baseline" call SetCalButtonStatus "!enable" call SaveBaseLineCalFile 'Save the new cal data as a file ver114-5m desiredLineCalLevel=1 'opt for using baseline cal ver114-6b BaseLineCalDone=1 'ver114-5L goto [resetBand] 'To display info 'ver114-5m added CreateOperatingCalFolder function CreateOperatingCalFolder() 'Creates MSA_Info\OperatingCal folder if it does not already exist 'Return 1 if error 'First see if we have the folder MSA_Info\OperatingCal CreateOperatingCalFolder=0 'assume no error files DefaultDir$;"\MSA_Info", "", fileInfo$() 'get directory list numFolders=val(fileInfo$(0,1)) for i=1 to numFolders 'search list for OperatingCal if fileInfo$(i,1)="OperatingCal" then exit function next i 'Create folder if necessary if 0<>mkDir("MSA_Info\OperatingCal") then CreateOperatingCalFolder=1 : notice "Cannot create OperatingCal." end function 'ver114-5m added CreateOperatingCalFolder sub SaveBaseLineCalFile if CreateOperatingCalFolder()=1 then notice "Cannot save BaseLine Cal file." : exit sub open DefaultDir$;"\MSA_Info\OperatingCal\BaseLineCal.txt" for output as #baseLineOut call BaseLineCalContextToFile "#baseLineOut" close #baseLineOut end sub 'ver114-5m added OpenBaseLineCalFile$ function OpenBaseLineCalFile$() 'Open baseline calibration file; return its handle 'If file does not exist, return "". fName$=DefaultDir$;"\MSA_Info\OperatingCal\BaseLineCal.txt" On Error goto [noFile] open fName$ for input as #baselineFile OpenBaseLineCalFile$="#baselineFile" exit function [noFile] OpenBaseLineCalFile$="" 'ver114-2f end function 'ver114-5m added LoadBaseLineCalFile function LoadBaseLineCalFile() 'Return 1 if error (file does not exist) fHndl$=OpenBaseLineCalFile$() if fHndl$="" then LoadBaseLineCalFile=1 : baseLineNumSteps=-1 : exit function nPoints=GetBaseLineCalContextFromFile(fHndl$) if nPoints<=0 then LoadBaseLineCalFile=1 : baseLineNumSteps=-1 'error else LoadBaseLineCalFile=0 end if close #fHndl$ end function 'Ver114-2b deleted [menuInit] 'SEW3 added menuRunConfig and menuRunCal 'SEW9 rewrote the following menuRunConfig. ver113-7d [menuRunConfig]'Graph Window Menu,Setup,Configuration Manager was selected 'the following 4 lines of code were the SEW3 new code: ' if haltsweep=1 then goto [Halted]'sew6 ver113-7c ' cancelled=configRunManager(0) '0 signals we are not running on startup so cancellation is allowed ' if cancelled then goto [Halted] 'Cancelled; halt scan and wait ' goto [finished] 'Must restart if config was changed 'the following 10 lines of code are for the new SEW9, ver113-7d: savePath$=path$ 'ver114-4c cancelled=configRunManager(0) '0 signals we are not running on startup so cancellation is allowed if cancelled then 'Cancelled; restore filter setting; Halt or wait path$=savePath$ 'ver114-4c gosub [SelectFilter] if haltsweep=1 then goto [Halted] 'Finish last point of sweep that was in progress. wait end if goto [finished] 'Must restart if config was changed 'end of now for SEW9, ver113-7d 'changedver113-7cSEW6[menuRunCal] [menuRunCal]'Menu item for config manager was selected 'SEW6 rewrote routine.ver113-7c savePath$=path$ 'ver114-4c 'calRunManager will return with filter path 1 installed. call RequireRestart 'SEW8 Let the user proceed only by Restarting gosub [calManRunManager] path$=savePath$ 'ver114-4c 'restores prior filter gosub [SelectFilter] wait [CreateGraphWindow]'changed ver113-4b 'SEWgraph rewrote entire [CreateGraphWindow] BackgroundColor$="black" ForegroundColor$="white" WindowWidth = initialGraphWindowWidth WindowHeight = initialGraphWindowHeight UpperLeftX = 1 'the Graph window upper left corner is 1 pixel right.. UpperLeftY = 1 '...and 1 pixel down from the upper left of the screen TextboxColor$="blue" ComboboxColor$="blue" '--SEW and SEW3Added the File and Edit menu items to save or copy the graph image 'and open ConfigMan, CalMan menu #handle, "File", "Save Image", [SaveImage], "Load Prefs", [menuLoadPreferenceFile], _ "Save Prefs", menuSavePreferenceFile, "Save Debug File", [SaveAllContextsFile] menu #handle, "Edit", "Copy Image",[CopyImage] 'SEW 'ver114-5o changed name of Cal and Config manager entries if hasVNA and msaMode$<>"SA" then 'ver114-6h menu #handle, "Options", "Markers", mMenuMarkerOptions, _ "Sweep", [menuFreqAxisPreference], "Show Variables", [Showvar], _ "Transmission Setup", DisplayS21Jig 'ver114-7g menu #handle, "Setup", "Hardware Config Manager", [menuRunConfig], _ "Initial Cal Manager", [menuRunCal], _ "Special Tests", [SpecialTests], "PDM Calibration", [menuCalPDM] 'ver114-7g else menu #handle, "Options", "Markers", mMenuMarkerOptions, _ "Sweep", [menuFreqAxisPreference], "Show Variables", [Showvar] 'ver114-7g menu #handle, "Setup", "Hardware Config Manager", [menuRunConfig], _ "Initial Cal Manager", [menuRunCal], _ "Special Tests", [SpecialTests] end if menu #handle, "Data", "Magnitude input to MSA",[MagnitudeMSAinput],"Magnitude AtoD Bits",[MagBitsAtoD],_ "Magnitude Calibration Table",[MagCalTable],"Phase Data, Processed",[PhaProcessed],_ "Phase AtoD Bits",[PhaBitsAtoD],"Phase Calibration Table",[PhaCalTable],"S21 Parameters",[MagPhaS21] 'ver113-5a menu #handle, "Analysis", "Filter",SetFilterAnalysis 'SEWgraph if msaMode$<>"SA" then menu #handle, "Operating Cal", "Perform Cal", [RunVNACal], _ "Reference To",[menuVNARef] 'ver114-5n; ver114-5o if TGtop>0 then 'No need for mode selection if SA is the only possible mode ver114-5n if hasVNA then 'ver114-6j changed modes menu #handle, "Mode", "Spectrum Analyzer", [RestartSAmode], _ "VNA Transmission", [RestartTransmissionMode] 'ver114-7g removed Reflection Mode else menu #handle, "Mode", "Spectrum Analyzer", [RestartSAmode], "TG Transmission", [RestartTransmissionMode] end if end if 'GraphicBox for graphing 'ver114-3f window and graph box dimensions are now set in step 3. graphBoxHeight=initialGraphWindowHeight-clientHeightOffset-41 'ver114-7q graphBoxWidth=initialGraphWindowWidth-clientWidthOffset 'ver114-7o graphicbox #handle.g, 0,0,graphBoxWidth,graphBoxHeight 'Marker Selection buttons markTop=graphBoxHeight+12 'This isn't the top of anything in particular, just a reference point ver114-7q markSelLeft=5 statictext #handle.selMarkLab "Marker", markSelLeft+3, markTop-12, 40, 14 selMarkIDs$(0)="None" : for i=0 to 9 : selMarkIDs$(i+1)=markerIDs$(i) : next i 'Stylebits #handle.selMark, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h del114_7i so box generates click event combobox #handle.selMark, selMarkIDs$(), mUserMarkSelect, markSelLeft, markTop+2, 50, 180 'Marker Editing Items ver114-4a changed marker edit buttons so none need to be hidden markEditLeft=markSelLeft+55 'button #handle.markEdit, "Edit",btnMarkEdit, LL, markEditLeft, -22, 35,18 button #handle.markDelete, "Delete",mBtnMarkDelete, LL, markEditLeft, -4, 65,18 'stylebits #handle.markClear, _BS_MULTILINE, 0, 0, 0 'Prints label over two lines button #handle.markClear, "Clear Marks",mBtnMarkClear, LL, markEditLeft, -22, 65,18 button #handle.markDec, "-",[btnDecPoint], LL, markEditLeft+70, -7, 14,13 'ver114-7q button #handle.markInc, "+",[btnIncPoint], LL, markEditLeft+130, -7, 14,13 'ver114-7q statictext #handle.FreqLab, "MHz", markEditLeft+100, markTop-6, 28,13 textbox #handle.markFreq, markEditLeft+70, markTop+7, 75,20 button #handle.markEnterFreq, "Enter",mEnterMarker, LL, markEditLeft+146, -25, 35,15 'Misc Marker buttons markMiscLeft=markEditLeft+185 button #handle.ExpandLR, "Expand L-R", [menuExpandSweep],LL, markMiscLeft, -4,65,18 'ver114-7d button #handle.mMarkToCenter, "Mark->Cent", mMarkToCenter,LL, markMiscLeft, -22,65,18 'ver114-7b deleted buttons for IncDecRef 'Configuration items ver114-4f Moved here from working window 'ver114-7g rearranged config buttons and deleted data buttons configLeft=markMiscLeft+80 textbox #handle.configNum, configLeft, markTop+8, 26, 19 'config number button #handle.saveconf, "STO Config", [SaveConfig], LL, configLeft+27, -5, 65, 18 'ver113-1a button #handle.goconf, "RCL Config", [GoConfig], LL, configLeft+27, -23, 65, 18 'ver113-1a 'stylebits #handle.godata, _BS_MULTILINE, 0, 0, 0 'delver114-7g 'button #handle.godata, "RCL Data", [GoData], LL, configLeft+67, -3, 35, 38 'ver113-1a 'delver114-7g 'Sweep Control Buttons button #handle.Redraw, "Redraw",btnRedraw, LR, 105,13,70,19 'OneStep becomes HaltAtEnd when scan is in progress button #handle.OneStep, "HaltAtEnd",[OneStep], LR, 105,-6,70,19 'Continue becomes Halt when scan is in progress button #handle.Continue, "Halt",[Continue], LR, 35,13,60,19 'Restart toggles between Restart and Running button #handle.Restart, "Running",[Restart], LR, 35,-6,60,19 'Button to bring control window to front 'ver114-4f deleted button to move to control window 'There is a bug in LB causing some ephemeral images to appear when resizing a window, 'but they can be eliminated by covering and then uncovering them. The following button 'is used in [ResizeGraphHandler] for that purpose. It only appears for an instant, so the handler is irrelevant. button #handle.Cover, "", nilHandler,LL, 0,40,1000,80 'SEWgraph modeTitle$="VNA Mode" 'ver114-6j if msaMode$="SA" then modeTitle$="Spectrum Analyzer Mode" 'ver114-6j if msaMode$="ScalarTrans" then modeTitle$="Tracking Generator Mode" 'ver114-6j if graphBox$<>"" then close #handle 'Close existing window before opening new one ver114-7h open "MSA Graph Window for ";modeTitle$;"--version 114" for window as #handle 'ver114-7i graphBox$="#handle.g" 'Used to draw in the graphics box 'ver114-7h 'if vna = 1 then open "Graph Window for MSA/VNA, Vector Network Analyzer Mode - version 113" for graphics_nsb as #handle 'print #handle.g, "when leftButtonDown [LeftButDown]" 'delver114-6d print #handle.g, "when rightButtonDown [RightButDown]" print #handle.g, "when leftButtonDouble [LeftButDouble]" print #handle, "trapclose [finished]" 'goto [finished] if xit is clicked 'Note that full initialization of graph parameters 'is done at the commencement of a scan series. 'ver114-3f moved initialization of graph module to step 3 #handle.g, "autoresize" #handle, "resizehandler [ResizeGraphHandler]" #handle.Cover, "!hide" 'Used only during resizing #handle.OneStep, "!font Arial 9 bold" 'SEWgraph #handle.Continue, "!font Arial 9 bold" 'SEWgraph #handle.Redraw, "!font Arial 9 bold" 'SEWgraph #handle.Restart, "!font Arial 9 bold" 'SEWgraph #handle.Redraw, "!hide" 'We start out running so hide this 'Tell graph module what size we are, and calculate scaling ver114-6f call gUpdateGraphObject graphBox$, graphBoxWidth, graphBoxHeight, _ graphMarLeft, graphMarRight, graphMarTop, graphMarBot call gCalcGraphParams 'Calculate new scaling 'ver114-7q moved measurement of client area elsewhere return 'ver114-4c deleted SwitchToControls and SwitchToGraph 'SEWgraph added mMarkToCenter sub mMarkToCenter btn$ 'Recenter around marker frequency if selMarkerID$="" then notice "No marker is selected." exit sub 'No marker selected so nothing to do end if 'Get frequency from from marker number from marker ID newCenterFreq=gMarkerCurrXVal(mMarkerNum(selMarkerID$)) newCenterFreq=int(1000000*newCenterFreq+0.5)/1000000 'Round to nearest Hz. call SetCenterSpanFreq newCenterFreq, sweepwidth 'Set new center with old span; also updates startfreq and endfreq if haltsweep=1 then continueCode=3 'Forces restart if in midsweep. else call RequireRestart end if end sub 'ver114-7d added [menuExpandSweep] [menuExpandSweep] call Expand if haltsweep then continueCode=3 : goto [PostScan] else goto [Restart] end if 'SEWgraph added Expand sub Expand 'Expand L to R markers to be the bounds of the sweep. Called from [menuExpandSweep] if hasMarkL=0 and hasMarkR=0 then exit sub 'No L or R; nothing to do. if hasMarkL=1 then newLowerFreq=gMarkerCurrXVal(mMarkerNum("L")) 'Get L frequency else newLowerFreq=startfreq end if if hasMarkR=1 then newUpperFreq=gMarkerCurrXVal(mMarkerNum("R")) 'Get R frequency else call gGetPointVal globalSteps+1, newUpperFreq, dum1, dum2 'Use final frequency ver114-7d end if 'Note that when the first scan is completed, the marker point numbers will be 'redetermined from their current frequencies, so L and R will be moved to the 'edges of the scan. call SetStartStopFreq newLowerFreq, newUpperFreq 'Enter new frequencies in globals end sub 'SEWgraph deleted [PrintPhaReferences]; axis labels are now printed in gDrawGrid print #handle, "color red" 'the Phase text, on left, will be red print #handle, "place 2 40" print #handle, "\";topphase;" Deg." print #handle, "place 2 320" print #handle, "\";botphase;" Deg." return 'ver114-4f deleted [createCommonWorkingWindow],[WorkingWindowforMSA],[WorkingWindowforVNA] 'ver114-4c deleted setRefresh and resetRefresh 'SEWgraph Added btnRedraw sub btnRedraw btn$ 'Redraw button was pushed 'haltsweep=1 if scan is in progress, so we set flag to halt sweeping on return from the "scan" 'command that enabled this button to be handled. if haltsweep=1 then continueCode=1 : exit sub 'Signal to halt after "scan" command call mDeleteMarker "Halt" 'Delete Halt marker ver114-4c refreshGridDirty=1 : call RefreshGraph 0 'ver114-7d end sub 'SEWgraph Added RedrawGraph sub RedrawGraph restoreErase 'Redraw all layers of the graph 'Redraw entire graph from scratch, using the point values previously accumulated. refreshRedrawFromScratch=1 call RefreshGraph restoreErase end sub 'ver114-6e added RememberState sub RememberState 'Record state before loading a context, to allow detection of certain changes 'We want to record enough to determine whether we have to restart, do a full redraw or just 'refresh and redraw setup info. 'Some of these changes can be made during a scan without an immediate redraw, but when loading 'a context we will force a halt. 'Change to msaMode$ may reqire a new graph window prevMSAMode$=msaMode$ 'Changes to these will require a complete Restart call gGetXAxisRange prevStartF, prevEndF call gGetIsLinear prevXIsLinear, prevY1IsLinear, prevY2IsLinear prevSteps=globalSteps prevSweepDir=gGetSweepDir() : prevAlternate=alternateSweep prevGenTrk=gentrk : prevSpurCheck=spurcheck 'ver114-6k prevTGOff=offset : prevSGFreq=sgout 'ver114-7j prevPath$=path$ 'ver114-7j 'Changes to these will require calling gCalcGraphParams and then a full Redraw call gGetYAxisRange 1, prevStartY1, prevEndY1 call gGetYAxisRange 2, prevStartY2, prevEndY2 call gGetNumDivisions prevHorDiv, prevVertDiv 'Changes to graph data type will require a replotting to get the proper transform, 'and redrawing from scratch to get axis labeling correct. prevY1SourceConst=Y1SourceConst : prevY1ComponentConst=Y1ComponentConst prevY2SourceConst=Y2SourceConst : prevY2ComponentConst=Y2ComponentConst 'If in a mode where these are relevant, changes to the following are treated 'the same as a change to the data source. 'ver114-7e added these prevS21JigAttach$=S21JigAttach$ prevS21JigR0=S21JigR0 : prevS21GraphR0=S21GraphR0 prevS21DoTransform=S21DoTransform prevS11BridgeR0=S11BridgeR0 : prevS11GraphR0=S11GraphR0 'Changes to these require a full Redraw from existing Y values 'Note this refers to magtable data, not graph data prevDataChanged=0 'If changed, this has to be set elsewhere 'Changes to these may require redraw from scratch or just normal refresh prevPhaDisp=phadisp : prevMagDisp=magdisp 'If auto scale gets turned on, we will signal to do autoscale at end of sweep, 'or do it immediately if we are halted. prevAutoScaleY1=autoScaleY1 : prevAutoScaleY2=autoScaleY2 'Changing planeadj could require immediate recalc of existing data, but we don't prevPlaneAdj=planeadj 'ver114-7f 'If none of the above are changed, we will do a RefreshGraph with refreshGridDirty=1 'Items that reach here include: 'Marker Options, Graph Appearance, trace width and trace color ' video filter, SigGen freq, TG offset, spur test, wait time and plane extension end sub 'ver114-7f added [DetectFullChanges] [DetectFullChanges] 'Take appropriate redraw/restart action in response to certain changes 'This is a gosub routine so it can access [ChangeMode]. This needs to be called only if msaMode$ may have changed; 'otherwise call DetectChanges directly. doRestart=0 if prevMSAMode$<>msaMode$ then gosub [ChangeMode]: doRestart=1 call DetectChanges doRestart return 'ver114-6e added DetectChanges; modver114-7f to move mode change detection to gosub routine sub DetectChanges doRestart 'Take appropriate redraw/restart action in response to certain changes 'We want to record enough to determine whether we have to restart, do a full redraw or just 'refresh and redraw setup info. If doRestart=1, we will specify a restart no matter what. 'Some of these changes can be made during a scan without an immediate redraw, but when loading 'a context we will force a halt. 'We set continueCode to specify the user action required: 0=continue; 2=wait; 3=restart continueCode=0 'Assume we can continue when we are done here doCalcAndRedraw=0 doTransform=0 dataTypeChanged=0 'ver114-7n 'Changes to graph data type will require recalculating grid labels with new format, 'recalculating the transform and then 'redrawing from scratch to get axis labeling correct. if prevY1SourceConst<>Y1SourceConst or prevY1ComponentConst<>Y1ComponentConst _ or prevY2SourceConst<>Y2SourceConst or prevY2ComponentConst<>Y2ComponentConst _ then doCalcAndRedraw=1 : dataTypeChanged=1 :doTransform=1 'ver114-7n 'Changes to these will require a complete Restart call gGetXAxisRange currStartF, currEndF call gGetIsLinear currXIsLinear, currY1IsLinear, currY2IsLinear if currStartF<>prevStartF or currEndF<>prevEndF or prevSteps<>globalSteps then doRestart=1 if currXIsLinear<>prevXIsLinear or currY1IsLinear<>prevY1IsLinear _ or currY2IsLinear<>prevY2IsLinear then doRestart=1 if prevGenTrk<>gentrk or prevSpurCheck<>spurcheck then doRestart=1 'ver114-6k if prevTGOff<>offset or prevSGFreq<>sgout then doRestart=1 'ver114-7j if doRestart then 'If we are using fixed data as the reference source and any of the above changed, 'we can no longer use it. if referenceLineType=1 then referenceLineType=0 : referenceTrace=0 : call gClearAllReferences 'ver114-7f end if if prevSweepDir<>gGetSweepDir() or prevAlternate<>alternateSweep then doRestart=1 if prevPath$<>path$ then doRestart=1 'ver114-7j if doRestart then 'If the data changed, we should redraw it before we exit. We assume the frequency 'points of the data are consistent with any changes to the graph module frequency points. 'If the data did not change, we may not be able to redraw it with the new sweep parameters so 'we don't try. continueCode=3 if prevDataChanged=0 then exit sub call gGenerateXValues gPointCount() 'Make sure x values correspond to sweep parameters 'For RLC reference, recalculate reference data if referenceLineType=2 then call CreateReferenceSource : call CreateReferenceTransform 'ver114-7f doCalcAndRedraw=1 doTransform=1 end if 'Changes to these will require calling gCalcGraphParams and then a full Redraw from existing Y values call gGetYAxisRange 1, currStartY1, currEndY1 call gGetYAxisRange 2, currStartY2, currEndY2 call gGetNumDivisions currHorDiv, currVertDiv if currStartY1<>prevStartY1 or currEndY1<>prevEndY1 then doCalcAndRedraw=1 if currStartY2<>prevStartY2 or currEndY2<>prevEndY2 then doCalcAndRedraw=1 if currHorDiv<>prevHorDiv or currVertDiv<>prevVertDiv then doCalcAndRedraw=1 if doCalcAndRedraw then 'ver115-1b if dataTypeChanged then call UpdateGraphDataFormat 'To get new data format call gCalcGraphParams end if doRedraw=doCalcAndRedraw if (prevAutoScaleY1=0 and autoScaleY1=1) or (prevAutoScaleY2=0 and autoScaleY2=1) then _ autoScaleTurnedOn=1 else autoScaleTurnedOn=0 'ver114-7a if autoScaleY1=1 or autoScaleY2=1 then autoScaleIsOn=1 else autoScaleIsOn=0 'ver114-7a 'If in a mode where these are relevant, changes to the following are treated 'the same as a change to the data source. 'ver114-7e added these if msaMode$="VectorTrans" then if prevS21JigAttach$<>S21JigAttach$ then doTransform=1 if prevS21JigR0<>S21JigR0 or prevS21GraphR0<>S21GraphR0 then doTransform=1 if prevS21DoTransform<>S21DoTransform then doTransform=1 end if if msaMode$="Reflection" and (prevS11BridgeR0<>S11BridgeR0 or prevS11GraphR0<>S11GraphR0) then doTransform=1 'If data changes, recalc x pixel values and require a restart, though proceeding will destroy the new data if prevDataChanged then continueCode=3 : doTransform=1 if doTransform then call UpdateGraphDataFormat 'Update data formatting; may also affect data transform call RecalcYValues if autoScaleIsOn then call PerformAutoScale 'autoscale with the new data 'ver114-7a autoScaleTurnedOn=0 'Since we just did autoscale ver114-7e end if call CreateReferenceTransform doRedraw=1 'Signal to do complete redraw from scratch end if 'If auto scale has been turned on, we signal to do the autoscaling at the end of the sweep or on redraw if autoScaleTurnedOn then refreshAutoScale=1 'ver114-7a if doRedraw then call RedrawGraph 0: exit sub 'Changing trace style requires recreating the traces and refreshing if it has just 'been turned on (since we have no accumulated trace draw commands) or if it 'was and remains on but the style changed (between histo/normal or erase/stick). if prevPhaDisp<>phadisp and (phadisp<>0 or prevPhaDisp=0) then doRefreshTraces=1 'ver114-7d if prevMagDisp<>magdisp and (magdisp<>0 or prevMagDisp=0) then doRefreshTraces=1 'ver114-7d if doRefreshTraces then refreshTracesDirty=1 : refreshGridDirty=1 : call RefreshGraph 0 : exit sub 'ver114-7d 'Everything else we redraw everything except the traces from scratch; traces 'will be drawn from gTrace1$() and gTrace2$() 'Marker Options, Graph Appearance, trace width and trace color will be in this category refreshGridDirty=1 'We don't redraw if in stick mode, because the "stuck" traces will be erased. if haltsweep=1 then doErasure=1 else doErasure=0 'Do erasure gap if still sweeping if isStickMode=0 then call RefreshGraph doErasure end sub 'ver114-6h added RecalcYValues sub RecalcYValues 'Recalculate Y values for existing graph points, and change in the graph module call gGetMinMaxPointNum pMin, pMax for i=pMin to pMax call CalcGraphData i-1, y1, y2, 0 'i-1 to get step number from point number ver114-6h call gChangePoints i, y1, y2 'Change point values in graph module next i end sub 'SEWgraph Added RefreshGraph sub RefreshGraph restoreErase 'Quick redraw of graph area 'This uses saved information from the most recent gDrawGrid (called in RedrawGraph) 'to quickly redraw the graph area and about 20 pixels around it to effectively erase 'the traces and markers, and also uses such saved info to quickly redraw the traces. 'We then redraw the markers at their current locations. The marker info box is also 'updated; the first step in that update is to draw a filled box with a border, which 'erases everything underneath. We don't flush, so if the window gets covered the markers 'and traces will disappear. We discard to clear some memory. 'This may be called as a result of some user action in the middle of scanning. To avoid 'interference with the dynamic scan process, we Pause dynamic scanning and then resume it. 'In a language faster than Liberty Basic we could just use RedrawGraph to redraw from scratch. 'The following globals determine whether we redraw various components from scratch or by a faster method. 'global refreshGridDirty 'Forces grid (and labels, title) and setup info and references to redraw from scratch in RefreshGraphs 'global refreshTracesDirty 'Forces traces and references to be redrawn from raw Y1 and Y2 values in RefreshGraph 'global refreshMarkersDirty 'Forces marker relocation based on frequency 'global refreshAutoScale 'Forces autoscaling of axes; implies refreshRedrawFromScratch 'global refreshRedrawFromScratch 'Forces complete redraw from scratch in RefreshGraph if refreshAutoScale then 'ver114-7a call PerformAutoScale 'Recalculates scaling in graph module refreshRedrawFromScratch=1 end if recreateReferences=0 if refreshRedrawFromScratch or refreshGridDirty then call gDrawGrid call DrawSetupInfo recreateReferences=1 else call gRefreshGrid end if if referenceLineType<>0 then 'ver114-7f if recreateReferences or refreshTracesDirty=1 then call CreateReferenceTransform call gClearAllReferences if referenceTrace>1 then call gAddReference 1,CreateReferenceTraces$(referenceColor2$,referenceWidth2,2) 'Do Y2 reference if (referenceTrace=1 or referenceTrace=3) and msaMode$<>"SA" and msaMode$<>"ScalarTrans" then _ call gAddReference 2,CreateReferenceTraces$(referenceColor1$,referenceWidth1,1) end if call gDrawReferences end if call gPauseDynamicScan 'Keeps the trace redraws from accumulating if refreshTracesDirty=1 or refreshRedrawFromScratch then call gRecreateTraces 1 'Recreate and draw trace draw commands 'ver114-6e 'ver114-7e else call gRefreshTraces 'Draw from accumulated trace draw commands 'ver114-6e end if if restoreErase then call gRestoreErasure call gResumeDynamicScan 'Discard draw commands if scan is still in progress; otherwise we flush a bit later if haltsweep=1 then #graphBox$, "discard" 'In case frequency axis has changed, we want to update the marker point numbers 'to maintain their prior frequencies, if possible. We do this on every Refresh or Redraw 'through the end of the first scan. if refreshMarkersDirty or refreshRedrawFromScratch then call gDetermineMarkerPointNumbers call gUpdateMarkerXVal 'Save frequency values for markers call mDrawMarkerInfo 'Draw marker info after relocating any floating markers if doGraphMarkers then call gDrawMarkers 'Discard draw commands if scan is still in progress; otherwise flush if haltsweep=1 then #graphBox$, "discard" else #graphBox$, "flush" 'ver114-6e Clear refresh flags, since we just redrew refreshForceRefresh=0 refreshGridDirty=0 refreshTracesDirty=0 refreshMarkersDirty=0 refreshAutoScale=0 'ver114-7b refreshRedrawFromScratch=0 end sub 'ver114-7a added PerformAutoScale sub PerformAutoScale 'do autoscaling of axes as required, but no redraw if autoScaleY1 and msaMode$<>"SA" and msaMode$<>"ScalarTrans" then doAutoY1=1 else doAutoY1=0 'If autoscale is on then calculate the scale and redraw from raw values if doAutoY1 then call CalcAutoScale 1, newMin, newMax : call SetPhaseRange newMin, newMax if autoScaleY2 then call CalcAutoScale 2, newMin, newMax : call SetPowerRange newMin, newMax call gCalcGraphParams 'Recalculates scaling in graph module end sub 'SEWgraph Added mUpdateMarkerLocations sub mUpdateMarkerLocations 'Find point numbers for peak markers and for L and R if relative to the peaks 'We are called from mDrawMarkerInfo, which also has the ability to move markers. saveSel$=selMarkerID$ 'We want to save and restore the current selected marker if hasMarkPeakPos or hasMarkPeakNeg then 'Locate peaks if doPeaksBounded=1 then if hasMarkL=0 then pStart=1 else pStart=gMarkerPointNum(mMarkerNum("L")) if hasMarkR=0 then pEnd=gPointCount() else pEnd=gMarkerPointNum(mMarkerNum("R")) else pStart=1 : pEnd=gPointCount() 'Signals to search all points end if call gFindPeaks 2,pStart, pEnd, minNum, maxNum, minY, maxY if hasMarkPeakPos then call gUpdateMarkerPointNum mMarkerNum("P+"),maxNum if hasMarkPeakNeg then call gUpdateMarkerPointNum mMarkerNum("P-"),minNum end if if doLRRelativeTo$<>"" then 'Locate LR relative to another marker markNum=mMarkerNum(doLRRelativeTo$) if markNum<1 then notice "Invalid Marker Number" 'For debugging pNum=gMarkerPointNum(markNum) if pNum>0 then 'Only proceed if the marker exists call gFindDBOffset pNum, doLRRelativeAmount, leftPoint, rightPoint if leftPoint>=1 then call mAddMarker "L", leftPoint, "2" if rightPoint<=gPointCount() then call mAddMarker "R", rightPoint, "2" end if end if if doFilterAnalysis then peakPoint=gMarkerPointNum(mMarkerNum(filterPeakMarkID$)) 'Get point number of marker that is the peak reference if peakPoint<0 then doFilterAnalysis=0 'Our peak marker has been deleted, so terminate the analysis end if 'If we are placing markers as part of filter analysis, we do it now. if doFilterAnalysis then peakPoint=gMarkerPointNum(mMarkerNum(filterPeakMarkID$)) 'Get point number of marker that is the peak reference if peakPoint<0 then doFilterAnalysis=0 'Our peak marker has been deleted, so terminate the analysis end if if doFilterAnalysis then 'Locate the points required for filter analysis. It is possible the points 'don't exist on the graph, in which case their point numbers will end up as -1. call gSetPeakAnalysis x1DBDown, x2DBDown, ripHighFreq, ripLowFreq 'For now we do auto determination of ripple search limits in gPeakAnalysis call gPeakAnalysis peakPoint, 1, 1 'Find points down 3db, x1DBDown and x2DBDown, and ripple min and max call gGetPeakAnalysisPoints db3LowPoint, db3HighPoint, x1LowPoint, x1HighPoint, x2LowPoint, x2HighPoint 'Place markers 2,3,4 and 5 as needed on the x1 and x2 points. Note that mAddMarker for 'an existing marker just relocates it. if x1DBDown<>0 then _ call mAddMarker "2", x1LowPoint, "2" : call mAddMarker "3", x1HighPoint, "2" 'SEWgraph2 if x2DBDown<>0 then _ call mAddMarker "4", x2LowPoint, "2" : call mAddMarker "5", x2HighPoint, "2" 'SEWgraph2 end if selMarkerID$=saveSel$ 'ver114-5L deleted call to mDisplaySelectedMarker end sub 'SEWgraph Added DrawSetupInfo sub DrawSetupInfo 'Draw info about MSA setup at right side of graph box call gGetGraphicsSize InfoX, dum 'Get width InfoX=InfoX-100 : InfoY=graphMarTop+10 call gGetInfoColors textColor$, backColor$ #graphBox$, "font Tahoma 8 bold;color ";textColor$;";backcolor ";backColor$ if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then 'ver114-5n if msaMode$="ScalarTrans" then call gPrintText "Track Gen Transmission", InfoX-10,16 _ else call gPrintText "VNA Transmission", InfoX-10,16 'ver114-6j ver114-7L if applyLineCalLevel0 then call gPrintText "Spect. Analyzer", InfoX-10,16 'ver114-6j call gPrintText "RBW=";str$(finalbw)+"KHz",InfoX, InfoY : InfoY=InfoY+18 call gPrintText "Video=";videoFilter$,InfoX, InfoY : InfoY=InfoY+18 'ver114-6b call gPrintText "Wait=";str$(wate)+" ms", InfoX, InfoY : InfoY=InfoY+18 'Print number of steps call gPrintText "Steps=";str$(globalSteps), InfoX, InfoY : InfoY=InfoY+18 if gGetXIsLinear() then 'Print stepfreq as Hz, KHz, etc. with up to 3 whole places, max 4 decimals 'and max 5 total significant digits. We don't do this for log sweeps because 'the freq/step is not constant stepfreq=(endfreq-startfreq)/globalSteps 'stepfreq is only calculated for printing ver114-7n stepSize$=uFormatted$(1000000*stepfreq,"3,4,5//UseMultiplier//suffix=Hz") call gPrintText uCompact$(stepSize$);"/Step", InfoX, InfoY : InfoY=InfoY+18 'Print Freq/div. also done only for linear sweep call gGetNumDivisions nHorDiv, nVertDiv stepSize$=uFormatted$(1000000*sweepwidth/nHorDiv,"3,4,5//UseMultiplier//suffix=Hz") call gPrintText uCompact$(stepSize$);"/Div", InfoX, InfoY : InfoY=InfoY+18 end if if msaMode$<>"SA" and msaMode$<>"ScalarTrans" then call gPrintText "Exten=";str$(planeadj)+" ns", InfoX, InfoY : InfoY=InfoY+18 'ver114-5f if msaMode$="VectorTrans" then 'ver114-7j call gPrintText "Z0=";S21GraphR0, InfoX, InfoY : InfoY=InfoY+18 else call gPrintText "Z0=";S11GraphR0, InfoX, InfoY : InfoY=InfoY+18 end if end if end sub 'SEWgraph Added mMarkerNum function mMarkerNum(markID$) 'Return ordinal marker number for this marker ID$ 'This value corresponds to the entry in the list of markers (1...) '-1 for invalid ID$. This is used to convert meaningful ID's into 'arbitrary storage locations. When marker info is printed, it is 'printed in the same order as the ordinal marker numbers. This is the only place 'that ID's are tied to specific ordinals, to make it easy to change. select case markID$ case "Halt" 'ver114-4c added Halt and renumbered mMarkerNum=1 case "L" mMarkerNum=2 case "R" mMarkerNum=3 case "P+" mMarkerNum=4 case "P-" mMarkerNum=5 case "1" mMarkerNum=6 case "2" mMarkerNum=7 case "3" mMarkerNum=8 case "4" mMarkerNum=9 case "5" mMarkerNum=10 case "6" mMarkerNum=11 case else mMarkerNum=-1 end select end function 'SEWgraph Added mDeleteMarker sub mDeleteMarker markID$ markNum=mMarkerNum(markID$) : if markNum<1 then notice "Invalid Marker Number" : exit sub call gUpdateMarkerPointNum markNum,-1 'Update the flags indicating whether we have the special markers select case markID$ case "L" hasMarkL=0 case "R" hasMarkR=0 case "P+" hasMarkPeakPos=0 case "P-" hasMarkPeakNeg=0 case "1", "2","3","4","5", "6", "Halt" 'ver114-4c 'valid markers but nothing special to do case else exit sub 'Not valid marker ID end select if gValidMarkerCount>0 then hasAnyMark=1 else hasAnyMark=0 if markID$=selMarkerID$ then call mMarkSelect "" 'ver114-5L end if end sub 'SEWgraph Added mAddMarker sub mAddMarker markID$, pointNum, trace$ 'Add specified marker at specified point markTrace$=trace$ markStyle$="LabeledWedge" markNum=mMarkerNum(markID$) if markNum<1 then notice "Invalid Marker Number" : exit sub end if if pointNum<0 then call mDeleteMarker markID$ : exit sub 'Adding with point num <0 is deleting select case markID$ case "L" hasMarkL=1 case "R" hasMarkR=1 case "P+" hasMarkPeakPos=1 markTrace$="2" 'Always do peak markers on trace 2 (mag) case "P-" hasMarkPeakNeg=1 markTrace$="2" markStyle$="LabeledInvertedWedge" case "Halt" 'ver114-4c markTrace$="Xaxis" 'ver114-6d markStyle$="HaltPointer" 'ver114-5m case "1", "2","3","4","5", "6" 'valid markers but nothing special to do case else exit sub 'not valid marker end select hasAnyMark=1 'Indicate that we have at least one marker call gSetMarkerNum markNum, pointNum, markID$, markTrace$, markStyle$ 'Note we do not change the selected marker here end sub 'SEWgraph Added mClearMarkers sub mClearMarkers hasMarkL=0 : hasMarkR=0 : hasMarkPeakPos=0 : hasMarkPeakNeg=0 : hasAnyMark=0 call gClearMarkers call gDrawMarkerInfo 'to clear info area ver114-7n call mMarkSelect "" 'ver114-5L end sub 'SEWgraph Added mDrawMarkerInfo sub mDrawMarkerInfo 'Draw marker info at bottom of graph call gGetGraphicsSize graphwide, graphigh call mUpdateMarkerLocations 'Determines locations of peak markers and L,R if they are relative to the peaks 'We will draw marker info in a rectangular area below the labels of the x axis. 'This is the frequency, mag and phase (if applicable) call gDrawMarkerInfo 'Set InfoX and InfoY where additional info can be printed. InfoX=gGetMarkerInfoRight()+5 InfoY=gGetMarkerInfoTop() if selMarkerID$<>"" then call mDisplaySelectedMarker 'info may have changed 'We may have to print some additional info from an analysis if doFilterAnalysis then peakPoint=gMarkerPointNum(mMarkerNum(filterPeakMarkID$)) 'Get point number of marker that is the peak reference 'Note we know peakPoint is a valid point because mUpdateMarkerLocations set doFilterAnalysis=0 if it was not. peakFreq=gGetPointXVal(peakPoint) 'Frequency of peak 'gPeakAnalysis has found the points that are down the required number of db. It is possible the points 'don't exist on the graph, in which case their point numbers will end up as -1. call gGetPeakAnalysisPoints db3LowPoint, db3HighPoint, x1LowPoint, x1HighPoint, x2LowPoint, x2HighPoint call gGetPeakAnalysisRipple ripLowFreq, ripHighFreq, ripMinVal, ripMaxVal 'Get frequencies at each of the points db3HighFreq=gGetPointXVal(db3HighPoint) db3LowFreq=gGetPointXVal(db3LowPoint) x1HighFreq=gGetPointXVal(x1HighPoint) x1LowFreq=gGetPointXVal(x1LowPoint) x2HighFreq=gGetPointXVal(x2HighPoint) x2LowFreq=gGetPointXVal(x2LowPoint) db3BW=db3HighFreq-db3LowFreq 'If any of the required db values does not have both its points, we set a flag to zero. if db3LowPoint>0 and db3HighPoint>0 then hasDB3=1 else hasDB3=0 if x1LowPoint>0 and x1HighPoint>0 then hasX1=1 else hasX1=0 if x2LowPoint>0 and x2HighPoint>0 then hasX2=1 else hasX2=0 call gGetInfoColors textColor$, backColor$ #graphBox$, "color ";textColor$ 'Set drawing color #graphBox$, "font Tahoma 8 bold"; 'Set drawing font #graphBox$, "backcolor ";backColor$ 'Set background color #graphBox$, "size 1" 'We draw a filled box to get an outline and to clear any existing data boxHt= 5 + 7*13 'Assume 7 lines of height 13 each boxWidth=150 #graphBox$, "place ";InfoX;" "; InfoY 'locate pen at upper left #graphBox$, "boxfilled "; InfoX+boxWidth; " "; InfoY+boxHt 'This is lower right corner InfoX=InfoX+7 InfoY=InfoY+15 'Set to bottom of first line (matches marker heading) 'Now print the filter information on screen if x1DBDown<>3 and x2DBDown<>3 and hasDB3 then 'If neither x1 nor x2 is 3 db down, then print the 3db bandwidth if we have it bw$=uFormatted$(db3BW*1000000,"3,3,4//UseMultiplier//suffix=Hz") call gPrintText "BW(3db)=";bw$, InfoX, InfoY :InfoY=InfoY+13 'e.g. BW(3db)=123 KHz end if if hasX1 then x1BW=x1HighFreq-x1LowFreq bw$=uFormatted$(x1BW*1000000,"3,3,4//UseMultiplier//suffix=Hz") call gPrintText "BW(";str$(x1DBDown);"db)=";bw$, InfoX, InfoY :InfoY=InfoY+13 'e.g. BW(3db)=123 KHz end if if hasX2<>0 then x2BW=x2HighFreq-x2LowFreq bw$=uFormatted$(x2BW*1000000,"3,3,4//UseMultiplier//suffix=Hz") call gPrintText "BW("; str$(x2DBDown);"db)=";bw$, InfoX, InfoY :InfoY=InfoY+13 'e.g. BW(3db)=123 KHz end if 'Print Q if we have the necessary data if hasDB3 and db3BW>0 then Q$=Trim$(using("#####.#", peakFreq/db3BW)) call gPrintText "Q=";Q$, InfoX, InfoY :InfoY=InfoY+13 'e.g. Q=345.1 end if if hasX1 and hasX2 and x1BW>0 then 'Print shape factor if we have needed data shape$=Trim$(using("###.##", x2BW/x1BW)) call gPrintText "SF(";x2DBDown; "db/";x1DBDown;"db)=";shape$, InfoX, InfoY :InfoY=InfoY+13 'e.g. Shape=2.6 ver114-7h end if if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then 'ver114-5n IL=gGetPointYVal(peakPoint,2) : if IL<0 then IL=0-IL 'Note TO DO: we could also do this if in TG mode IL$=Trim$(using("###.##", IL)) 'Insertion loss, which we only do if in transmission call gPrintText "IL=";IL$, InfoX, InfoY : InfoY=InfoY+13 end if 'Print ripple. Ideally we would print the ripple search bounds, but we don't have room 'Maybe we should delete insertion loss, because it is apparent from the peak value if hasDB3 then rip$=Trim$(using("####.##", ripMaxVal-ripMinVal)) call gPrintText "Ripple=";rip$;" db", InfoX, InfoY : InfoY=InfoY+13 InfoX=InfoX+boxWidth 'End by setting InfoX to the far right of what we just drew end if end if end sub 'ver114-4e added PrintMessage sub PrintMessage 'Print message above top of marker info area 'The message is in message$ y=gGetMarkerInfoTop()-5 x=30 call gGetInfoColors textColor$, backColor$ #graphBox$, "font Tahoma 8 bold;color ";textColor$;";backcolor ";backColor$ call gPrintText space$(150), x, y if message$<>"" then call gPrintText "MESSAGE: ";Left$(message$,100), x, y 'ver114-5c Don't print if blank end sub 'ver114-4d added SetPhaseRange sub SetPhaseRange bot, top 'Set range of phase axis call gSetYAxisRange 1, bot, top botphase=bot topphase=top end sub 'ver114-4d added SetPowerRange sub SetPowerRange bot, top 'Set range of mag/power axis call gSetYAxisRange 2, bot, top botref=bot topref=top end sub 'ver114-5o added [SaveData] modver114-7f [GoData] 'Retrieve saved data and sweep context from save configuration if haltsweep = 1 then gosub [FinishSweeping] print #handle.configNum, "!contents? config$"; 'Entered Configuration number, 0-99 config = val(config$) 'if invalid make it "0" if config <1 then config = 0:print #handle.configNum,0 'if number is more than maxConfiguration, make it maxConfiguration if config >maxConfiguration then config = maxConfiguration:print #handle.configNum,maxConfiguration beep 'ver114-2c, ver114-2d changed the following lines to and retrieve from the string restoreContext$=savedConfig$(config,0) if restoreContext$ = "" then message$="Config is empty, choose another" : call PrintMessage :haltsweep=0:wait 'ver114-4e end if call RememberState restoreIsValidation=0 'ver114-2c gosub [RestoreSweepContext] 'Actual restoration ver114-2c if restoreErr$<>"" then notice "Error Restoring Sweep Context:";chr(13);restoreErr$ : haltsweep=0:wait 'ver114-2c dataStart=1 nPoints=RestoreDataContext(savedConfig$(config, 1),dataStart, 1) 'Actual restoration of data and title if nPoints<=0 then notice "Error Restoring Data" else message$="Data Restored" : call PrintMessage gosub [DetectFullChanges] message$="Data Restored" : call PrintMessage 'ver114-5i if continueCode=3 then call RequireRestart wait [SaveConfig] 'ver113-1a modver114-7f 'install the present set-up configurations into an array 'The Nth config is a collection of contexts saved in savedConfig$(N,i), where i is: 0=sweep context; 1=data context; ' 2=band line cal context; 3=band OSL context print #handle.configNum, "!contents? config$"; 'Entered Configuration number config = val(config$) 'if invalid, make it "0" if config <1 then config = 0:print #handle.configNum,0 'if number is more than maxConfiguration, make it maxConfiguration if config >maxConfiguration then config = maxConfiguration:print #handle.configNum,maxConfiguration savedConfig$(config, 0)=SweepContext$() savedConfig$(config, 1)=DataContext$() if msaMode$="VectorTrans" then savedConfig$(config,2)=BandLineCalContext$() else savedConfig$(config,2)="" 'TO DO--OSL message$="Configuration is stored" : call PrintMessage 'ver114-4e if haltsweep=1 then goto [PostScan] 'If midsweep, keep going ver114-2d wait 'ver114-2c moved several context-related routines to put all in same place [GoConfig] 'ver113-1a modver114-7f 'Load saved config with cal table (if VectorTrans mode) but without MSA data 'use number in box and retrieve variables. saveHaltSweep=haltsweep if haltsweep=1 then gosub [FinishSweeping] 'ver114-5i Finish cleanly with current settings print #handle.configNum, "!contents? config$"; 'Entered Configuration number, 0-99 config = val(config$) 'if invalid make it "0" if config <1 then config = 0:print #handle.configNum,0 'if number is more than maxConfiguration, make it maxConfiguration if config >maxConfiguration then config = maxConfiguration:print #handle.configNum,maxConfiguration beep 'ver114-2c, ver114-2d changed the following lines to and retrieve from the string restoreContext$=savedConfig$(config,0) if restoreContext$ = "" then message$="Config is empty, choose another" : call PrintMessage :haltsweep=0:wait 'ver114-4e end if call RememberState restoreIsValidation=0 'ver114-2c gosub [RestoreSweepContext] 'Actual restoration ver114-2c if restoreErr$<>"" then notice "Error Restoring Sweep Context:";chr(13);restoreErr$ : haltsweep=0:wait 'ver114-2c 'call gCalcGraphParams 'delVer114-2d Now done in gRestoreSweepContext (and again on Restart) 'Get the cal data from the saved string; ver114-2c changed if msaMode$="VectorTrans" then lineCalStart=1 'ver114-3e nPoints=RestoreBandLineCalContext(savedConfig$(config,1),lineCalStart) 'ver114-3e if nPoints<0 then notice "Error Retrieving Line Cal Points:" : haltsweep=0:wait 'ver114-2c, ver114-2d, ver114-3e, ver114-5h 'We have restored Full Line Cal; we must now install it 'Note that we don't restore Base Line Cal. We assume the user didn't change it, or if he did 'that he would want to keep the current one. desiredLineCalLevel=2 : call InstallSelectedLineCal 'ver114-5i end if gosub [DetectFullChanges] message$="Config selected, use [Restart]" : call PrintMessage 'ver114-5i if saveHaltSweep=1 then goto [PostScan] 'Continue on, per continueCode else if continueCode=3 then call RequireRestart 'ver114-5i end if 'assume filter path, PDM inversion box, does not need changing 'do these things: 'close variables window if open 'close special tests if open, including data window 'install config data into Working Window but, do not auto "Restart" wait '-------------Explanation of Contexts------------- ver114-2d 'A context file or string contains a series of lines (separated by chr$(13) in strings) containing 'information on one or more types of contexts. Data for a given type begins with the line ' "StartContext Name", where Name is the name of the context type. It ends with the end of the 'file or string, or with the line "EndContext". Routines that restore individual types do not necessarily expect 'the file or string to begin with the StartContext xxx line, which should have been processed by the caller. ' 'Some variables are stored both inside the graphing module and, under a different name, outside it. 'In those cases, only one version needs to be saved, but both versions need to be restored. '--------------------------------------- 'ver114-2c added SweepContext$ function SweepContext$() 'Return sweep context as string 'successive lines are separated by chr$(13) newLine$=chr$(13) aSpace$=" " 'First include variables used outside the graph module s1$= "Version=A" 'This item was added in ver114-7n s1$= s1$;newLine$;"msaMode=";msaMode$ 'ver114-6f ver114-7p s1$= s1$;newLine$;"SpecialGraph=";doSpecialGraph s1$= s1$;newLine$;"Wait=";wate s1$= s1$;newLine$;"PlaneAdj=";planeadj s1$= s1$;newLine$;"Path=";Word$(path$,2) 'path$ is in form "Path N" s1$= s1$;newLine$;"SGPreset=";sgout 'ver114-4h s1$= s1$;newLine$;"Offset=";offset s1$= s1$;newLine$;"IsTG=";gentrk 'ver114-4i s1$= s1$;newLine$;"NormRev=";normrev 'ver114-4k s1$= s1$;newLine$;"VideoFilter=";videoFilter$ 'ver114-5p s1$= s1$;newLine$;"GraphData=";Y1SourceConst; aSpace$; Y1ComponentConst;aSpace$; _ Y2SourceConst; aSpace$; Y2ComponentConst 'ver114-7e s1$= s1$;newLine$;"Autoscale=";autoScaleY1; aSpace$; autoScaleY2 'ver114-7e s1$= s1$;newLine$;"S21Jig=";S21JigAttach$;aSpace$; S21JigR0;aSpace$;S21GraphR0; aSpace$; S21DoTransform 'ver114-7e s1$= s1$;newLine$;"S11Bridge=";S11BridgeR0; aSpace$; S11GraphR0 'ver114-7e SweepContext$=s1$;newLine$;gSweepContext$() 'Add items from graph module end function 'ver114-2c added [RestoreSweepContext]; ver114-6f merged it with PrivateRestoreSweepContext [RestoreSweepContext] 'public routine to restore sweep context 'There are a couple of things we can't do within a true subroutine, so we use this routine as a wrapper 'Because this gosub routine cannot accept arguments, the following values (non-global) must be preset: ' restoreContext$ is the string containing the context ' restoreIsValidation=1 to do just validation run (i.e. don't change data); 0 otherwise 'If there is an error, and error message is placed in restoreErr$; otherwise it is made blank 'Get next line and increment startPos to start of the following line startPos=1 tLine$=uGetLine$(restoreContext$, startPos) oldStartPos=startPos while tLine$<>"" origLine$=tLine$ 'ver114-7n if Upper$(Left$(tLine$,10))="ENDCONTEXT" then exit while isErr=0 equalPos=instr(tLine$,"=") 'equal sign marks end of tag if equalPos=0 then isErr=1 : exit while else tag$=Upper$(Left$(tLine$, equalPos-1)) 'tag is stuff before equal sign tLine$=Trim$(Mid$(tLine$, equalPos+1)) 'contents is stuff after equal sign end if v1=val(tLine$) 'Most of our data is numeric values select case tag$ 'Each tag represents one or several data items. These are retrieved one at a time, 'and as each is retrieved it is deleted from tLine$. Numeric items are delimited 'by spaces, tabs or commas. Text items are delimited by the double character 'contained in sep$, because they may contain spaces or commas. If this is just 'a validation run, we do not enter any of the retrieved data into our variables. 'ver114-2d cleaned up and added VNA case "VERSION" 'Do nothing on this ver114-7p case "MSAMODE" 'if restoreIsValidation=0 and tLine$<>msaMode$ then changeModeTo$=tLine$ : gosub [ChangeMode] 'ver114-6f if restoreIsValidation=0 then msaMode$=tLine$ case "SPECIALGRAPH" if restoreIsValidation=0 then doSpecialGraph=v1 case "WAIT" if restoreIsValidation=0 then wate=v1 case "PLANEADJ" if restoreIsValidation=0 then planeadj=v1 case "PATH" isErr=(v1<=0 or v1>MSANumFilters) if isErr=0 and restoreIsValidation=0 then path$="Path ";v1 case "SGPRESET" if restoreIsValidation=0 then sgout=v1 'ver114-4h case "OFFSET" if restoreIsValidation=0 then offset=v1 case "ISTG" 'ver114-4i if restoreIsValidation=0 then gentrk=v1 case "NORMREV" 'ver114-4i if restoreIsValidation=0 then normrev=v1 case "VIDEOFILTER" 'ver114-5p if restoreIsValidation=0 then videoFilter$=tLine$ case "GRAPHDATA" if restoreIsValidation=0 then Y1SourceConst=val(Word$(tLine$,1)) : Y1ComponentConst=val(Word$(tLine$,2)) Y2SourceConst=val(Word$(tLine$,3)) : Y2ComponentConst=val(Word$(tLine$,4)) end if case "AUTOSCALE" 'ver114-7e if restoreIsValidation=0 then v1=val(Word$(tLine$,1)) : v2=val(Word$(tLine$,2)) if (v1<>0 and v1<>1) or (v2<>0 and v2<>1) then isErr=1 if isErr=0 then autoScaleY1=v1 : autoScaleY2=v2 end if case "S21JIG" 'ver114-7e if restoreIsValidation=0 then w$=Word$(tLine$,1) if w$<>"Series" and w$<>"Shunt" then isErr=1 if isErr=0 then S21JigAttach$=w$ v1=val(Word$(tLine$,2)) : v2=val(Word$(tLine$,3)): v3=val(Word$(tLine$,4)) if v1<=0 or v2<=0 or (v3<>0 and v3<>1)then isErr=1 if isErr=0 then S21JigR0=v1 : S21GraphR0=v2 : S21DoTransform=v3 'ver114-7n end if case "S11BRIDGE" 'ver114-7e 'DO nothing; reflection mode is disabled. 'ver114-7n case else 'Unrecognized tag. Must belong to the graph module, so we end here startPos=oldStartPos 'reset to beginning of this line exit while end select if isErr then restoreErr$="Sweep Context Error in: "; origLine$: return 'ver114-7n 'Get next line and increment startPos to start of the following line oldStartPos=startPos tLine$=uGetLine$(restoreContext$, startPos) wend 'If no error so far, process the data for the graph module restoreErr$=gRestoreSweepContext$(restoreContext$, startPos, isValidation) if restoreErr$<>"" or isValidation=1 then return 'done if error or if this is just validation run 'Now set variables that are calculated from the data just retrieved. call gGetYAxisRange 2, botref, topref 'mag range ver114-4d reversed mag and phase call gGetYAxisRange 1, botphase, topphase 'phase range globalSteps=gNumDynamicSteps() 'number of steps call gGetXAxisRange xMin, xMax call SetStartStopFreq xMin, xMax 'sets centfreq, sweepwidth 'stepfreq=(xMax-xMin)/globalSteps 'del ver114-7j steps=globalSteps sweepDir=gGetSweepDir() 'ver114-4n gosub [SelectFilter] 'selects filter for path$ ver114-4c return 'ver114-2f added TraceContext$ function TraceContext$() 'Return trace context as string 'successive lines are separated by chr$(13) newLine$=chr$(13) 'First include variables used outside the graph module s1$= "RefreshEachScan=";refreshEachScan s1$= s1$;newLine$;"TraceModes=";phadisp;",";magdisp TraceContext$=s1$;newLine$;gTraceContext$() 'Add items from graph module end function 'ver114-2f added RestoreTraceContext$ function RestoreTraceContext$(s$, byref startPos, isValidation) 'Restore sweep context 'Returns error message if error; otherwise 0. Ignores data prior to startPos. 'startPos is updated to one past the last line we process (normally EndContext or end of string) 'if isValidation=1, we merely check for errors 'sep$ is a possibly multi-character separator to delimit text items on one line 'successive lines are separated by chr$(13) newLine$=chr$(13) aSpace$=" " sep$=";;" 'Used to separate text items nonTextDelims$=" ," + chr$(9) 'space, comma and tab are delimiters 'Get next line and increment startPos to start of the following line oldStartPos=startPos tLine$=uGetLine$(s$, startPos) oldStartPos=startPos while tLine$<>"" origLine$=tLine$ 'ver114-7n if Upper$(Left$(tLine$,10))="ENDCONTEXT" then exit while isErr=0 equalPos=instr(tLine$,"=") 'equal sign marks end of tag if equalPos=0 then isErr=1 : exit while else tag$=Upper$(Left$(tLine$, equalPos-1)) 'tag is stuff before equal sign tLine$=Trim$(Mid$(tLine$, equalPos+1)) 'contents is stuff after equal sign end if select case tag$ case "REFRESHEACHSCAN" if isValidation=0 then refreshEachScan=val(tLine$) case "TRACEMODES" isErr=uExtractNumericItems(2, tLine$, nonTextDelims$, v1, v2, v3) if isValidation=0 and isErr=0 then phadisp=v1 : magdisp=v2 case else 'Unrecognized tag. Must belong to the graph module, so we end here startPos=oldStartPos 'reset to beginning of this line exit while end select if isErr then RestoreTraceContext$="Trace Context Error in: "; origLine$: exit function 'ver114-7n 'Get next line and increment startPos to start of the following line oldStartPos=startPos tLine$=uGetLine$(s$, startPos) wend 'If no error so far, process the data for the graph module errMsg$=gRestoreTraceContext$(s$, startPos, isValidation) RestoreTraceContext$=errMsg$ end function 'ver114-2f added RestoreGridContext$; modified by ver114-3a and ver114-4e function RestoreGridContext$(s$, byref startPos, isValidation) 'Restore sweep context 'Returns error message if error; otherwise 0. Ignores data prior to startPos. 'startPos is updated to one past the last line we process (normally EndContext or end of string) 'if isValidation=1, we merely check for errors call gGetGraphicsSize oldWidth, oldHeight errMsg$=gRestoreGridContext$(s$, startPos, isValidation) RestoreGridContext$=errMsg$ if errMsg$<>"" or isValidation=1 then exit function call gGetMargins graphMarLeft, graphMarRight, graphMarTop, graphMarBot 'Get graph margins 'We may need to resize the graph window to match the dimensions just retrieved 'For now, we restore the previous size with the possibly new margins call gUpdateGraphObject graphBox$, oldWidth, oldHeight, graphMarLeft, graphMarRight, graphMarTop, graphMarBot end function 'ver114-3e added LineCalContextAsTextArray$() function BandLineCalContextAsTextArray() 'Put line cal points into uTextPointArray$, with header info 'return number of lines placed into uTextPointArray$ 'First line begins with ! and is line 1 of the title: !Log Sweep Path N. "Log" may instead by "Linear"; N=path number 'First 3 lines are title, each preceded by ! 'Next line is sweep info 'Next is Touchstone options line 'Next is comment data headings 'Then comes each point as its own string if bandLineLinear then sweep$="!Linear Sweep; " else sweep$="!Log Sweep; " uTextPointArray$(1)="! BandSweep Line Calibration Data" uTextPointArray$(2)="!" uTextPointArray$(3)="!";bandLineTimeStamp$ 'Save sweep info: log/linear ; path info (in form Path N); Jig attachment and R0 uTextPointArray$(4)=sweep$;bandLinePath$;"; S21Jig=";bandLineS21JigAttach$; "; S21JigR0="; bandLineS21JigR0 'ver114-7n uTextPointArray$(5)="# MHz S DB R 50" 'Freq in MHz, data in DB/angle format uTextPointArray$(6)="! MHz S21_DB S21_Degrees" aSpace$=" " for i=0 to globalSteps 'save freq, mag and phase uTextPointArray$(i+7)=bandLineCal(i,0);aSpace$;bandLineCal(i,1);aSpace$;bandLineCal(i,2) 'ver114-5f next i BandLineCalContextAsTextArray=globalSteps+7 'Number of lines end function 'ver114-2a added LineCalContext$(); ver114-3e modified it function BandLineCalContext$() 'Return data points as string, with title in first 3 lines 'We do not include StartContext or EndContext lines nLines=BandLineCalContextAsTextArray() 'Assemble strings into uTextPointArray$ BandLineCalContext$=uTextArrayToString$(1,nLines) 'Assemble array of strings into one string end function 'ver114-2a added LineCalContextToFile; ver114-3e modified it sub BandLineCalContextToFile fHndl$ 'save line cal points to file 'We do not include StartContext or EndContext lines 'fHndl$ is the handle of an already open file. We output our data 'but do not close the file. nLines=BandLineCalContextAsTextArray() 'Assemble strings into uTextPointArray$ for i=1 to nLines print #fHndl$, uTextPointArray$(i) next i end sub 'ver114-5f added BaseLineCalContextAsTextArray() function BaseLineCalContextAsTextArray() 'Put line cal points into uTextPointArray$, with header info 'return number of lines placed into uTextPointArray$ 'First line begins with ! and is line 1 of the title: !Log Sweep Path N. "Log" may instead by "Linear"; N=path number 'First 3 lines are title, each preceded by ! 'Next line is sweep info 'Next is Touchstone options line 'Next is comment data headings 'Then comes each point as its own string if baseLineLinear then sweep$="!Linear Sweep; " else sweep$="!Log Sweep; " uTextPointArray$(1)="! BaseLine Calibration Data" uTextPointArray$(2)="!" uTextPointArray$(3)="!";baseLineTimeStamp$ 'Save sweep info: log/linear ; path info (in form Path N); Jig attachment and R0 uTextPointArray$(4)=sweep$;baseLinePath$;"; S21Jig=";baseLineS21JigAttach$; "; S21JigR0="; baseLineS21JigR0 'ver114-7n uTextPointArray$(5)="# MHz S DB R 50" 'Freq in MHz, data in DB/angle format uTextPointArray$(6)="! MHz S21_DB S21_Degrees" aSpace$=" " for i=0 to globalSteps 'save freq, mag and phase uTextPointArray$(i+7)=baseLineCal(i,0);aSpace$;baseLineCal(i,1);aSpace$;baseLineCal(i,2) next i BaseLineCalContextAsTextArray=globalSteps+7 'Number of lines end function 'ver114-5f added BaseLineCalContext$() function BaseLineCalContext$() 'Return data points as string, with title in first 3 lines 'We do not include StartContext or EndContext lines nLines=BaseLineCalContextAsTextArray() 'Assemble strings into uTextPointArray$ BaseLineCalContext$=uTextArrayToString$(1,nLines) 'Assemble array of strings into one string end function 'ver114-5f added BaseLineCalContextToFile sub BaseLineCalContextToFile fHndl$ 'save line cal points to file 'We do not include StartContext or EndContext lines 'fHndl$ is the handle of an already open file. We output our data 'but do not close the file. nLines=BaseLineCalContextAsTextArray() 'Assemble strings into uTextPointArray$ for i=1 to nLines print #fHndl$, uTextPointArray$(i) next i end sub 'ver114-2a added RestoreLineCalContext$; ver114-3e modified ;'ver114-5h modified this routine function RestoreBandLineCalContext(byref s$, byref startPos) 'Restore line cal points. Return number of points 'We return number of points read, or -1 for file error 'We ignore data prior to startPos. We update startPos to the start of the next line after the line 'with "!EndContext"; or if no such line then one past end of string isErr=uArrayFromString(s$, 1, startPos, 3) 'Get data into uWorkArray; 3 data per line (freq+mag+phase) if isErr then RestoreBandLineCalContext=0 : errCode=1 : exit function 'Now transfer retrieved data from uWorkArray() to lineCalArray(). errCode=0 for i=1 to uWorkNumPoints bandLineCal(i-1,0)=uWorkArray(i, 0) 'freq bandLineCal(i-1,1)=uWorkArray(i, 1) : bandLineCal(i-1,2)=uWorkArray(i, 2) 'Mag and phase next i RestoreBandLineCalContext=uWorkNumPoints 'Now derive the sweep parameters from the array and the title ver114-5h bandLineNumSteps=uWorkNumPoints-1 bandLineStartFreq=bandLineCal(0,0) : bandLineEndFreq=bandLineCal(bandLineNumSteps,0) bandLineTimeStamp$=uWorkTitle$(3) 'uArrayFromString put date/time stamp here sweep$=uWorkTitle$(4) 'uArrayFromString put sweep info here if instr(sweep$,"Linear")>0 then bandLineLinear=1 else bandLineLinear=0 'ver114-7n added the retrieval of the following sweep info 'Get remaining sweep info from sweep$. Each item has a keyword and ends with a semi-colon or end of line bandPathNum$=uGetParamText$(sweep$, "Path ", ";") 'Gets text after "Path " to semicolon or end if bandPathNum$="" then bandLinePath$="Path 1" else bandLinePath$="Path ";bandPathNum$ bandLineS21JigAttach$=uGetParamText$(sweep$, "S21Jig=", ";") 'Gets text after S21Jig= to semicolon or end if bandLineS21JigAttach$="" then bandLineS21JigAttach$="Series" bandLineS21JigR0=val(uGetParamText$(sweep$, "S21JigR0=", ";")) 'Gets text after S21Jig= to semicolon or end if bandLineS21JigR0=0 then bandLineS21JigR0=50 end function 'ver114-2a added GetLineCalContextFromFile; ver114-3e modified; 'ver114-5h modified this routine function GetBandLineCalContextFromFile(fHndl$) 'get points from file; return number of points 'We return number of points read, or -1 for file error 'fHndl$ is the handle of an already open file. We read our data 'but do not close the file. The last line we read will be "!EndContext" isErr=uArrayFromFile(fHndl$,3) 'Get data, 3 per line if isErr then GetBandLineCalContextFromFile=-1 : baseLineNumSteps=-1 : exit function 'Move the data from uWorkArray to gGraphVal for i=1 to uWorkNumPoints bandLineCal(i-1,0)=uWorkArray(i, 0) 'freq bandLineCal(i-1,1)=uWorkArray(i, 1) : bandLineCal(i-1,2)=uWorkArray(i, 2) 'Mag and phase next i GetBandLineCalContextFromFile=uWorkNumPoints 'Now derive the sweep parameters from the array and the title ver114-5h bandLineNumSteps=uWorkNumPoints-1 bandLineStartFreq=bandLineCal(0,0) : bandLineEndFreq=bandLineCal(bandLineNumSteps,0) bandLineTimeStamp$=uWorkTitle$(3) 'uArrayFromFile put date/time stamp here sweep$=uWorkTitle$(4) 'uArrayFromFile put sweep info here if instr(sweep$,"Linear")>0 then bandLineLinear=1 else bandLineLinear=0 'ver114-7n added the retrieval of the following sweep info 'Get remaining sweep info from sweep$. Each item has a keyword and ends with a semi-colon or end of line bandPathNum$=uGetParamText$(sweep$, "Path ", ";") 'Gets text after "Path " to semicolon or end if bandPathNum$="" then bandLinePath$="Path 1" else bandLinePath$="Path ";bandPathNum$ bandLineS21JigAttach$=uGetParamText$(sweep$, "S21Jig=", ";") 'Gets text after S21Jig= to semicolon or end if bandLineS21JigAttach$="" then bandLineS21JigAttach$="Series" bandLineS21JigR0=val(uGetParamText$(sweep$, "S21JigR0=", ";")) 'Gets text after S21Jig= to semicolon or end if bandLineS21JigR0=0 then bandLineS21JigR0=50 end function '114-5h added RestoreBaseLineCalContext 'ver114-5h modified this routine function RestoreBaseLineCalContext(byref s$, byref startPos) 'Restore line cal points. Return number of points 'We return number of points read, or -1 for file error 'We ignore data prior to startPos. We update startPos to the start of the next line after the line 'with "!EndContext"; or if no such line then one past end of string isErr=uArrayFromString(s$, 1, startPos, 3) 'Get data into uWorkArray; 3 data per line (freq+mag+phase) if isErr then RestoreBaseLineCalContext=-1 : exit function 'Now transfer retrieved data from uWorkArray() to lineCalArray(). 'Make sure baseLineCal is big enough. Note that it can be bigger than data arrays, 'since it is used only by interpolating into a possibly smaller array. if uWorkNumPoints>gMaxNumPoints then redim baseLineCal(uWorkNumPoints+20, 2) 'ver114-5m for i=1 to uWorkNumPoints baseLineCal(i-1,0)=uWorkArray(i, 0) 'Freq baseLineCal(i-1,1)=uWorkArray(i, 1) : baseLineCal(i-1,2)=uWorkArray(i, 2) 'Mag and phase next i RestoreBaseLineCalContext=uWorkNumPoints 'Now derive the sweep parameters from the array and the title ver114-5h baseLineNumSteps=uWorkNumPoints-1 baseLineStartFreq=baseLineCal(0,0) : baseLineEndFreq=baseLineCal(baseLineNumSteps,0) baseLineTimeStamp$=uWorkTitle$(3) 'uArrayFromString put date/time stamp here sweep$=uWorkTitle$(4) 'uArrayFromString put sweep info here if instr(sweep$,"Linear")>0 then baseLineLinear=1 else baseLineLinear=0 'ver114-7n added the retrieval of the following sweep info 'Get remaining sweep info from sweep$. Each item has a keyword and ends with a semi-colon or end of line basePathNum$=uGetParamText$(sweep$, "Path ", ";") 'Gets text after "Path " to semicolon or end if basePathNum$="" then baseLinePath$="Path 1" else baseLinePath$="Path ";basePathNum$ baseLineS21JigAttach$=uGetParamText$(sweep$, "S21Jig=", ";") 'Gets text after S21Jig= to semicolon or end if baseLineS21JigAttach$="" then baseLineS21JigAttach$="Series" baseLineS21JigR0=val(uGetParamText$(sweep$, "S21JigR0=", ";")) 'Gets text after S21Jig= to semicolon or end if baseLineS21JigR0=0 then baseLineS21JigR0=50 end function '114-5h added GetBaseLineCalContextFromFile 'ver114-5h modified this routine function GetBaseLineCalContextFromFile(fHndl$) 'get points from file; return number of points 'We return number of points read, or -1 for file error 'fHndl$ is the handle of an already open file. We read our data 'but do not close the file. The last line we read will be "!EndContext" isErr=uArrayFromFile(fHndl$,3) 'Get data, 3 per line if isErr then GetBaseLineCalContextFromFile=-1 : baseLineNumSteps=-1 : exit function 'Move the data from uWorkArray to gGraphVal for i=1 to uWorkNumPoints baseLineCal(i-1,0)=uWorkArray(i, 0) 'Freq baseLineCal(i-1,1)=uWorkArray(i, 1) : baseLineCal(i-1,2)=uWorkArray(i, 2) 'Mag and phase next i GetBaseLineCalContextFromFile=uWorkNumPoints 'Now derive the sweep parameters from the array and the title ver114-5h baseLineNumSteps=uWorkNumPoints-1 baseLineStartFreq=baseLineCal(0,0) : baseLineEndFreq=baseLineCal(baseLineNumSteps,0) baseLineTimeStamp$=uWorkTitle$(3) 'uArrayFromFile put date/time stamp here sweep$=uWorkTitle$(4) 'uArrayFromFile put sweep info here if instr(sweep$,"Linear")>0 then baseLineLinear=1 else baseLineLinear=0 'ver114-7n added the retrieval of the following sweep info 'Get remaining sweep info from sweep$. Each item has a keyword and ends with a semi-colon or end of line basePathNum$=uGetParamText$(sweep$, "Path ", ";") 'Gets text after "Path " to semicolon or end if basePathNum$="" then baseLinePath$="Path 1" else baseLinePath$="Path ";basePathNum$ baseLineS21JigAttach$=uGetParamText$(sweep$, "S21Jig=", ";") 'Gets text after S21Jig= to semicolon or end if baseLineS21JigAttach$="" then baseLineS21JigAttach$="Series" baseLineS21JigR0=val(uGetParamText$(sweep$, "S21JigR0=", ";")) 'Gets text after S21Jig= to semicolon or end if baseLineS21JigR0=0 then baseLineS21JigR0=50 end function 'ver114-7f added DataContextAsTextArray$() function DataContextAsTextArray() 'Put data points into uTextPointArray$, with header info 'return number of lines placed into uTextPointArray$ 'First 3 lines are title, each preceded by ! 'Next line is sweep info 'Next is Touchstone options line 'Next is comment data headings 'Then comes each point as its own string uTextPointArray$(1)="!";gGetTitleLine$(1) uTextPointArray$(2)="!";gGetTitleLine$(2) uTextPointArray$(3)="!";gGetTitleLine$(3) uTextPointArray$(4)="!";gGetTitleLine$(4) 'This line has sweep info set by user; not printed as part of title ver114-5m uTextPointArray$(5)="# MHz S DB R 50" 'Freq in MHz, data in DB/angle format uTextPointArray$(6)="! MHz S21_DB S21_Degrees" 'We save frequency plus two data per point even if we only have one trace. aSpace$=" " call gGetMinMaxPointNum pMin, pMax 'ver114-6d minStep=pMin-1 : maxStep=pMax-1 for i=minStep to maxStep 'ver114-6d y1=datatable(i,3) y2=datatable(i,2) uTextPointArray$(i+7)=datatable(i,1);aSpace$;y2;aSpace$;y1 'Save freq, Y2, Y1 next i DataContextAsTextArray=maxStep+7 end function 'ver114-7f added DataContext$() function DataContext$() 'Return data points as string, with title in first 3 lines 'We do not include !StartContext or !EndContext lines nLines=DataContextAsTextArray() 'Assemble strings into uTextPointArray$ DataContext$=uTextArrayToString$(1,nLines) 'Assemble array of strings into one string end function 'ver114-7f added DataContextToFile() sub DataContextToFile fHndl$ 'save data points to file 'We do not include StartContext or EndContext lines 'fHndl$ is the handle of an already open file. We output our data 'but do not close the file. nLines=DataContextAsTextArray() 'Assemble strings into uTextPointArray$ for i=1 to nLines print #fHndl$, uTextPointArray$(i) next i end sub 'ver114-7f added RestoreDataContext$ function RestoreDataContext(byref s$, byref startPos, doTitle) 'Restore data points from s$ 'Return number of points; -1 if error 'Restore data; restore title only if doTitle=1 'We ignore data prior to startPos. We update startPos to the start of the next line after 'the point data, per uArrayFromString isErr=uArrayFromString(s$, 1, startPos, 3) 'Get data into uWorkArray; 3 data per line (freq+mag+phase) if isErr then RestoreDataContext=-1 : exit function 'Now transfer retrieved data from uWorkArray() to gGraphVal(). 'TO DO--This resizing does not help other arrays, and to resize them we would need to erase them. 'If we don't have room, we should notify the user that he needs to do a sweep with more points. if uWorkNumPoints>gMaxNumPoints() then call ResizeArrays uWorkNumPoints for i=1 to uWorkNumPoints datatable(i-1,1)=uWorkArray(i, 0) 'Frequency datatable(i-1,2)=uWorkArray(i, 1) : datatable(i-1,1)=uWorkArray(i, 2) 'Mag (Y2) first, then phase next i if doTitle then for i=1 to 4 call gSetTitleLine i, uWorkTitle$(i) 'Save title, which uArrayFromString retrieved ver114-5i next i end if 'Note title line 4 has info on linear/log. We don't change to match, so on a Restart we will 'not conform. But that should be taken care of in restoring the sweep context. Likewise with path info. RestoreDataContext=uWorkNumPoints prevDataChanged=1 call gSetNumDynamicSteps uWorkNumPoints-1 globalSteps=uWorkNumPoints-1 end function 'ver114-7f added GetDataContextFromFile function GetDataContextFromFile(fHndl$, doTitle) 'get points from file; return number of points or -1 if error 'Restore data; restore title only if doTitle=1 'fHndl$ is the handle of an already open file. We read our data 'but do not close the file. The last line we read will be "!EndContext" isErr=uArrayFromFile(fHndl$,3) 'Get data, 3 per line if isErr then GetDataContextFromFile=-1 : exit function 'Move the data from uWorkArray to gGraphVal if uWorkNumPoints>gMaxNumPoints() then call ResizeArrays uWorkNumPoints 'Make sure we have enough room for i=1 to uWorkNumPoints datatable(i-1,1)=uWorkArray(i, 0) 'Frequency datatable(i-1,2)=uWorkArray(i, 1) : datatable(i-1,1)=uWorkArray(i, 2) 'Mag (Y2) first, then phase next i if doTitle then for i=1 to 4 call gSetTitleLine i, uWorkTitle$(i) 'Save title, which uArrayFromString retrieved ver114-5i next i end if 'Note title line 4 has info on linear/log. We don't change to match, so on a Restart we will 'not conform. But that should be taken care of in restoring the sweep context. Likewise with path info. GetDataContextFromFile=uWorkNumPoints prevDataChanged=1 call gSetNumDynamicSteps uWorkNumPoints-1 globalSteps=uWorkNumPoints-1 end function 'ver114-5i added mMarkerContext$ function mMarkerContext$() 'Return marker context as string 'successive lines are separated by chr$(13) newLine$=chr$(13) s$=" " 'space to separate items j$="" s1$="" for i=0 to 9 id$=markerIDs$(i) :markNum=mMarkerNum(id$) call gGetMarkerByNum markNum, pointNum, id$, trace$, style$ if pointNum>0 then s1$=s1$;j$;"Marker=" + id$;s$; pointNum; s$; trace$ 'Marker id, point number and trace j$=newLine$ end if next s1$= s1$;j$;"Selected=";selMarkerID$ j$=newLine$ s1$= s1$;newLine$;"DoGraph=";doGraphMarkers s1$= s1$;newLine$;"LROptions=";doPeaksBounded;s$;doLRRelativeTo$;s$;doLRRelativeAmount s1$= s1$;newLine$;"FiltAnalysis=";doFilterAnalysis;s$;x1DBDown;s$;x2DBDown mMarkerContext$=s1$ end function 'ver114-5i added mRestoreMarkerContext$ function mRestoreMarkerContext$(s$, byref startPos, isValidation) 'Restore marker info from context string 'Returns error message if error; otherwise 0. Ignores data prior to startPos. 'startPos is updated to one past the last line we process (normally EndContext or end of string) 'if isValidation=1, we merely check for errors 'sep$ is a possibly multi-character separator to delimit text items on one line 'successive lines are separated by chr$(13) newLine$=chr$(13) nonTextDelims$=" ," + chr$(9) 'space, comma and tab are delimiters 'Get next line and increment startPos to start of the following line oldStartPos=startPos tLine$=uGetLine$(s$, startPos) 'Get line of data oldStartPos=startPos while tLine$<>"" origLine$=tLine$ 'ver114-7n if Upper$(Left$(tLine$,10))="ENDCONTEXT" then exit while isErr=0 equalPos=instr(tLine$,"=") 'equal sign marks end of tag if equalPos=0 then isErr=1 : exit while else tag$=Upper$(Left$(tLine$, equalPos-1)) 'tag is stuff before equal sign tLine$=Trim$(Mid$(tLine$, equalPos+1)) 'contents is stuff after equal sign end if select case tag$ case "MARKER" if isValidation=0 then _ call mAddMarker Word$(tLine$,2),val(Word$(tLine$,1)),Word$(tLine$,3) 'id, point num, trace case "SELECTED" if isValidation=0 then selMarkerID$=tLine$ case "DOGRAPH" if isValidation=0 then doGraphMarkers=val(tLine$) case "LROPTIONS" if isValidation=0 then doPeaksBounded=val(Word$(tLine$,1)) doLRRelativeTo$=Word$(tLine$,2) doLRRelativeAmount=val(Word$(tLine$,3)) end if case "FILTANALYSIS" if isValidation=0 then doFilterAnalysis=val(Word$(tLine$,1)) x1DBDown=val(Word$(tLine$,2)) x2DBDown=val(Word$(tLine$,3)) end if case else 'Unrecognized tag. Must belong to the graph module, so we end here startPos=oldStartPos 'reset to beginning of this line exit while end select if isErr then mRestoreMarkerContext$="Marker Context Error in: "; origLine$: exit function 'ver114-7n 'Get next line and increment startPos to start of the following line oldStartPos=startPos tLine$=uGetLine$(s$, startPos) wend mRestoreMarkerContext$="" call mMarkSelect selMarkerID$ 'To display info ver114-5L end function 'ver114-2f added LoadContextFile$; modified by ver114-3a and -3f; mod by ver114-5i [LoadContextFile] 'Load contexts from file restoreFileName$; set restoreErr$ to error message or "" 'restoreFileName$ contains complete path and file name 'The file may contain several contexts, each starting with StartContext Name or !StartContext Name 'and ending with EndContext. Grid context should be before Sweep context. 'The entries of contextTypes will be set to 1 if the corresponding context was read: 'See Case statement for contextTypes values if haltsweep=1 then gosub [FinishSweeping] 'Finish current sweep cleanly ver114-6e fHndl$=OpenContextFile$(restoreFileName$,"In") if fHndl$="" then restoreErr$="Context file failed to open: ";restoreFileName$ : return for i=0 to 30 : contextTypes(i)=0 : next i 'Clear contextTypes call RememberState 'ver114-6e while EOF(#fHndl$)=0 'Find next "StartContext" while EOF(#fHndl$)=0 Line Input #fHndl$, tLine$ tLine$=Upper$(Trim$(tLine$)) tagPos=instr(tLine$, "STARTCONTEXT") if tagPos>0 then contextName$=Trim$(Mid$(tLine$, tagPos+12)) 'text after tag is context name exit while end if wend select contextName$ case "HARDWARE" errMsg$="Can't restore Hardware Context" case "GRID", "TRACE", "SWEEP" 'These are read into a string and then processed restoreContext$="" 'Assemble context into string, without StartContext and EndContext lines joint$="" while EOF(#fHndl$)=0 Line Input #fHndl$, s1$ if Upper$(Trim$(s1$))="ENDCONTEXT" then exit while restoreContext$=restoreContext$;joint$;s1$ joint$=chr$(13) wend 'Process with proper routine select contextName$ case "GRID" contextTypes(1)=1 errMsg$=RestoreGridContext$(restoreContext$,1,0) 'Actual restoration case "TRACE" errMsg$=RestoreTraceContext$(restoreContext$,1,0) contextTypes(2)=1 case "SWEEP" contextTypes(3)=1 restoreIsValidation=0 gosub [RestoreSweepContext] 'Actual restoration errMsg$=restoreErr$ case "MARKER" contextTypes(4)=1 restoreIsValidation=0 gosub [RestoreMarkerContext] 'Actual restoration errMsg$=restoreErr$ end select if errMsg$<>"" then restoreErr$=errMsg$ : goto [errExit] case "BANDLINECAL" 'Process directly from file contextTypes(5)=1 nPoints=GetBandLineCalContextFromFile("#contextFile") if nPoints<0 then restoreErr$="Error retrieving Full Line Cal points" : goto [errExit] 'ver114-5h case "BASELINECAL" 'Process directly from file contextTypes(6)=1 nPoints=GetBandLineCalContextFromFile("#contextFile") if nPoints<0 then restoreErr$="Error retrieving Base Line Cal points" : goto [errExit] 'ver114-5h case "DATA" 'Process directly from file contextTypes(7)=1 prevDataChanged=1 'signal to DetectChanges that data changed nPoints=GetDataContextFromFile("#contextFile",1) '1 means include title ver114-5i if nPoints<0 then restoreErr$="Error Retrieving Data Points" : goto [errExit] case else restoreErr$="Unknown Context: ";contextName$ : goto [errExit] 'Unknown context name end select wend 'Reach here when entire file has been processed restoreErr$="" [subExit] gosub [DetectFullChanges] 'redraw, etc. if necessary if continueCode=3 and doingInitialization=0 then call RequireRestart close #fHndl$ return [errExit] continueCode=3 goto [subExit] return 'from [LoadContextFile] 'ver114-2f added OpenContextFile$ function OpenContextFile$(fName$, inout$) 'Open specified file. Return handle or "" 'fName$ contains complete path and file name On Error goto [noFile] inout$=Upper$(Trim$(inout$)) if inout$="IN" then open fName$ for input as #contextFile else open fName$ for output as #contextFile OpenContextFile$="#contextFile" exit function [noFile] OpenContextFile$="" end function 'ver114-2f added SaveContextFile; modified by ver114-3a; mod by ver114-5i function SaveContextFile$(fName$) 'Save specified Contexts to file; return error message or "" 'fName$ contains complete path and file name 'The entries of contextTypes will be set to 1 if the corresponding context is to be saved: fHndl$=OpenContextFile$(fName$,"Out") if fHndl$="" then SaveContextFile$="Context file failed to open: ";fName$ : exit function newLine$=chr$(13) if contextTypes(0)=1 then print #fHndl$, "StartContext Hardware";newLine$;configHardwareContext$();newLine$;"EndContext" if contextTypes(1)=1 then print #fHndl$, "StartContext Grid";newLine$;gGridContext$();newLine$;"EndContext" if contextTypes(2)=1 then print #fHndl$, "StartContext Trace";newLine$;TraceContext$();newLine$;"EndContext" if contextTypes(3)=1 then print #fHndl$, "StartContext Sweep";newLine$;SweepContext$();newLine$;"EndContext" if contextTypes(4)=1 then print #fHndl$, "StartContext Marker";newLine$;mMarkerContext$();newLine$;"EndContext" if contextTypes(5)=1 then print #fHndl$, "!StartContext BandLineCal" call BandLineCalContextToFile fHndl$ print #fHndl$, "!EndContext" end if if contextTypes(6)=1 then print #fHndl$, "!StartContext BaseLineCal" call BaseLineCalContextToFile fHndl$ print #fHndl$, "!EndContext" end if if contextTypes(7)=1 then print #fHndl$, "!StartContext Data" call DataContextToFile fHndl$ print #fHndl$, "!EndContext" end if close #fHndl$ SaveContextFile$="" end function 'ver114-3f added menuSavePreferenceFile sub menuSavePreferenceFile 'Save current preferences file to user-specified location. filedialog "Save As...", DefaultDir$+"\MSA_Info\MSA_Prefs\Prefs.txt", fileName$ if fileName$<>"" then call SavePreferenceFile fileName$ end sub 'ver114-3a added SavePreferenceFile; ver114-3f modified sub SavePreferenceFile fName$ 'Save current preferences file to fName$ 'Find out whether we have the MSA_Prefs folder; if not, create it files DefaultDir$+"\MSA_Info", "", fileInfo$() numFolders=val(fileInfo$(0,1)) haveFolder=0 for i=1 to numFolders if fileInfo$(i,1)="MSA_Prefs" then haveFolder=1: exit for next i if haveFolder=0 then 'Create MSA_Prefs folder if 0<>mkDir(DefaultDir$+"\MSA_Info\MSA_Prefs") then notice "Cannot create preference file." end if for i=0 to 30 : contextTypes(i)=0: next i contextTypes(1)=1 'Grid contextTypes(2)=1 'Trace contextTypes(3)=1 'Sweep errMsg$=SaveContextFile$(fName$) if errMsg$<>"" then notice "Unable to save preferences." end sub 'ver1124-5i added SaveAllContextsFile [SaveAllContextsFile] 'Save all contexts as a file; this is a menu item if haltsweep=1 then gosub [FinishSweeping] filedialog "Save", DefaultDir$+"\MSA_Info\Debug.txt", fName$ if fName$<>"" then for i=0 to 30 : contextTypes(i)=1 : next i 'Turn on all contexts errMsg$=SaveContextFile$(fName$) if errMsg$<>"" then notice errMsg$ end if wait 'ver114-3f added new [menuLoadPreferenceFile] [menuLoadPreferenceFile] 'Save current preferences file to user-specified location. filedialog "Open", DefaultDir$+"\MSA_Info\MSA_Prefs\Prefs.txt", restoreFileName$ 'ver114-6j if restoreFileName$<>"" then goto [LoadPreferenceFile] wait 'ver114-3f changed [menuLoadPreferenceFile] to [LoadPreferenceFile] [LoadPreferenceFile] 'Load preference file in restoreFileName$; set restoreErr$ with any error message 'ver114-3f if haltsweep=1 then goto [FinishSweeping] gosub [LoadContextFile] if restoreErr$<>"" then notice "Error loading preference file: ";restoreErr$ if continueCode=3 then call RequireRestart wait 'ver114-5n added [ChangeMode] [ChangeMode] 'Change mode to msaMode$; current mode is prevMSAMode$ select msaMode$ 'ver114-7f deleted changeModeTo$ case "ScalarTrans", "VectorTrans" gosub [GoTransmissionMode] case "Reflection" gosub [GoReflectionMode] case "TwoPort" 'TO DO wait case else gosub [GoSAmode] end select 'The following were centralized here by ver114-7h call gSetMode msaMode$ 'ver114-5L call ClearCalarray gMaxNumPoints()-1 'ver114-5f call mClearMarkers call gClearAllReferences haltsweep=0 'SEWgraph So Restart will actually restart return 'SEWgraph deleted [ChangeMagDisplayMSA],[ChangeMagDisplayVNA] and '[ChangePhaDisplayVNA], which are now handled in the Y-axis preference window [RestartSAmode] 'Restart in MSA mode added by ver114-5f; mod114-5n msaMode$="SA" 'ver114-7h gosub [ChangeMode] 'ver114-7h magdisp = 1 'ver114-6f phadisp = 0 'ver114-6f goto [Restart] [GoSAmode] 'Switch to MSA mode and return; mod114-5n 'if the Special Tests Window is open, close it. if special=1 then returnflag=1:gosub [CloseSpecial]:returnflag=0 'ver112-2f msaMode$="SA" : prevMSAMode$="SA" 'ver114-7f deleted changeModeTo$ autoScaleY1=0 'ver114-7a gentrk = 0 : sgout=10 'SG mode at 10 MHz ver114-7k Y1SourceConst=constRaw : Y2SourceConst=constRaw 'init for SA data ver114-6k Y1ComponentConst=constAngle :Y2ComponentConst=constMagDBM 'init for SA data ver114-6k gosub [CreateGraphWindow] 'ver114-5n 'Must always create new window changing to SA mode spurcheck = 0 'this assures Spur Test is OFF. ver114-2e return 'ver114-5f [RestartTransmissionMode] 'Restart in Transmission mode added by ver114-5f; mod114-5n if hasVNA then msaMode$="VectorTrans" else msaMode$="ScalarTrans" 'ver114-7h gosub [ChangeMode] 'ver114-7h magdisp = 1 'ver114-4c if hasVNA then phadisp = 1 'ver114-4c else phadisp=0 goto [Restart] [GoTransmissionMode] 'Switch to Transmission mode and return; mod114-5n 'if the Special Tests Window is open, close it. if special=1 then returnflag=1:gosub [CloseSpecial]:returnflag=0 'ver112-2f 'if spurcheck = 1 and PLL1mode = 0 then rcounter1=rcounter1-1:gosub [CommandPLL1R]:spurcheck = 0 'delver114-2e spurcheck = 0 'this assures Spur Test is OFF. ver114-2e gentrk = 1:normrev = 0:offset = 0 'turn on tracking generator, normal, zero offset 'ver111-17 if prevMSAMode$="SA" then doNewGraphWindow=1 'If changing from SA mode, must recreate Graph window 'ver114-5n Y1SourceConst=constRaw : Y2SourceConst=constRaw 'init for natural data ver114-6k Y1ComponentConst=constAngle :Y2ComponentConst=constMagDB 'init for natural data ver114-6k if hasVNA then msaMode$="VectorTrans" else msaMode$="ScalarTrans" 'ver114-5L autoScaleY1=0 'ver114-7a doNewGraphWindow=1 'ver114-7k end if prevMSAMode$=msaMode$ if doNewGraphWindow then gosub [CreateGraphWindow] 'ver114-7h return 'ver114-5f 'added by ver114-5n [RestartReflectionMode] 'Restart in Reflection mode added by ver114-5f; mod114-5n msaMode$="Reflection" 'ver114-7h gosub [ChangeMode] 'ver114-7h magdisp = 1 : phadisp = 1 'ver114-6f goto [Restart] 'added by ver114-5n [GoReflectionMode] 'Switch to Reflection mode and return; mod114-5n 'if the Special Tests Window is open, close it. if special=1 then returnflag=1:gosub [CloseSpecial]:returnflag=0 'ver112-2f 'if spurcheck = 1 and PLL1mode = 0 then rcounter1=rcounter1-1:gosub [CommandPLL1R]:spurcheck = 0 'delver114-2e spurcheck = 0 'this assures Spur Test is OFF. ver114-2e gentrk = 1:normrev = 0:offset = 0 'turn on tracking generator, normal, zero offset 'ver111-17 if prevMSAMode$="SA" then doNewGraphWindow=1 'If changing from SA mode, must recreate Graph window 'ver114-5n msaMode$="Reflection" : prevMSAMode$="Reflection" Y1SourceConst=constRaw : Y2SourceConst=constRaw 'init for natural data ver114-6k Y1ComponentConst=constAngle :Y2ComponentConst=constMagDB 'init for natural data ver114-6k if doNewGraphWindow then gosub [CreateGraphWindow] 'ver114-7h return 'ver114-5f 'SEWgraph Added ResizeArrays sub ResizeArrays nPoints 'Resize the arrays to hold at least nPoints points maxPoints=max(nPoints+10, 801) if gMaxNumPoints()0 then dum=CreateOperatingCalFolder() 'Create OperatingCal folder if it does not exist dum=LoadBaseLineCalFile() 'Load BaseLine file if it exists; if not we don't care bandLineNumSteps=-1 'Indicate no data; we just erased it call InstallSelectedLineCal 'To restore line cal data end if 'Note we don't have to resize configarray or configLineCalPoints$(); a flexible number of points 'is handled by simply having the strings in configLineCalPoints$ be different lengths. end sub 'ver114-4d deleted [calcWindowInfo] 'SEWgraph added LeftButDouble [LeftButDouble] 'Left button was double-clicked at MouseX, MouseY 'If the double click was on the grid line values for a Y axis, then open 'a preference window for that axis. If on the title, open a window to edit the title. 'Otherwise do nothing and return if gPixIsInGrid(MouseX, MouseY)=1 then goto [MarkerClick] 'ver114-6d ver114-7k call gGetGridCorner "LL", axis1Right, axis1Bot 'Lower left corner of grid call gGetGridCorner "LR", axis2Left, axis2Bot 'Lower right corner of grid axis1Left=graphMarLeft-50 : axisTop=graphMarTop-5 axis2Right=axis2Left+45 if MouseX>axis1Right-5 and MouseXaxis1Bot and MouseYaxis2Right+5 and MouseY>axis2Top and MouseY"SA" and msaMode$<>"ScalarTrans" and MouseX>=axis1Left and _ MouseX<=axis1Right and MouseY<=axis1Bot+5 and MouseY>=axisTop-5 then 'Double-click was on grid values for Y1 while in a phase mode call DisplayAxisYPreference 1 : yAxisChange=1 end if if MouseX>=axis2Left and MouseX<=axis2Right and MouseY<=axis2Bot+5 and MouseY>=axisTop-5 then 'Double-click was on grid values for Y2 call DisplayAxisYPreference 2 : yAxisChange=1 end if 'ver114-6d revised the redrawing procedure when the Y axis changes if yAxisChange then 'ver114-5c Moved this here from DisplayYAxisPreference useExpeditedDraw=gCanUseExpeditedDraw() if haltsweep=1 then if continueCode=3 then haltsweep=0 : goto [Restart] else goto [PostScan] 'Keep sweeping end if else if continueCode=3 then call RequireRestart end if end if if MouseYaxis1Right and MouseX0 then 'Click was not left or right of graphed points if selMarkerID$="" then newMarkID$="L" else newMarkID$=selMarkerID$ if gGetDoHist() or interpolateMarkerClicks=0 then clickedPointNum=int(clickedPointNum+0.5) 'Round to integral point ver114-7k call mAddMarker newMarkID$,clickedPointNum, str$(clickedTraceNum) call mMarkSelect newMarkID$ 'Select the marker we added ver114-5L call RefreshGraph 0 'ver114-7d leftstep=int(clickedPointNum)-1 'Make leftstep a step number, not point number, for [preupdatevar] if varwindow = 1 then gosub [preupdatevar] 'ver111-36h will update variables window as Mouse is clicked end if 'If a sweep is in progress return to the instruction after the scan command. if haltsweep=1 then goto [PostScan] 'SEWgraph0 wait 'ver114-7a added CalcAutoScale sub CalcAutoScale axisNum, byref axisMin, byref axisMax 'Calculate min and max for autoscaling axis axisNum if axisNum=1 then componConst=Y1ComponentConst else componConst=Y2ComponentConst call gGetMinMaxPointNum pMin, pMax if componConst=constGD then 'For group delay, the first point is invalid so don't include it if gGetSweepDir()=1 then pMin=pMin+1 else pMax=pMax-1 end if 'Find min and max values between points pMin and pMax call gFindPeaks axisNum, pMin, pMax, dum1, dum2, axisMin, axisMax select componConst case constMagDBM, constMagDB 'Round db/dbm to multiple of 5 axisMin=uRoundDownToMultiple(axisMin-0.5, 5) axisMax=uRoundUpToMultiple(axisMax+0.5, 5) case constAngle, constTheta 'Round angles to multiple of 15 axisMin=uRoundDownToMultiple(axisMin-5, 15) : if axisMin<-180 then axisMin=-180 'ver114-7g axisMax=uRoundUpToMultiple(axisMax+5, 15) : if axisMax>180 then axisMax=180 if axisMax-axisMin>120 then axisMin=-180 : axisMax=180 'Expand to full range 'ver114-7g case constSerR, constParR 'Round resistances to multiple of 25 if axisMax>1000000 then axisMax=1000 'Don't scale to screwy values, such as divide by zero might produce axisMin=uRoundDownToMultiple(axisMin-5, 25) axisMax=uRoundUpToMultiple(axisMax+5, 25) if axisMin<0 then axisMin=0 'No resistance below 0 case constReact 'Round reactances to multiple of 25 if axisMax>1000000 then axisMax=1000 'Don't scale to screwy values, such as divide by zero might produce tentMin=uRoundDownToMultiple(axisMin-5, 25) if tentMin<0 and axisMin>0 then tentMin=0 'Don't make axis<0 if axisMin>0 axisMin=tentMin tentMax=uRoundUpToMultiple(axisMax+5, 25) if tentMax>0 and axisMax<0 then tentMax=0 'Don't make axis>0 if axisMax<0 axisMax=tentMax case constMagWatts, constMagRatio, constMagV, constRho 'Fractional values that won't exceed 1 or be negative if axisMax>1 then axisMax=1 axisMin=uRoundDownToPower(axisMin, 10) axisMax=uRoundUpToPower(axisMax, 10) if axisMin>0 then if axisMax/axisMin>=100 then axisMin=0 case constSerC, constSerL, constParC, constParL 'Capacitance and Inductance if axisMin<0 then axisMin=axisMin*1.1 else axisMin=axisMin*0.9 if axisMax>0 then axisMax=axisMax*1.1 else axisMax=axisMax*0.9 axisMin=uRoundDownToPower(axisMin, 10) axisMax=uRoundUpToPower(axisMax, 10) if axisMax>1 then axisMax=1 : if axisMin<-1 then axisMin=-1 'If the range does not cross the axis and is two decades, pin one end to zero if axisMin*axisMax>0 then 'ver114-7b if axisMax/axisMin>=100 or axisMin/axisMax>=100 then if axisMax<0 then axisMax=0 else axisMin=0 end if end if case else 'constGD and anything we missed 'These items can have a broad range of values, positive and negative if axisMax>1000000 then axisMax=1 'Don't scale to screwy values, such as divide by zero might produce if axisMin<0 then axisMin=axisMin*1.1 else axisMin=axisMin*0.9 if axisMax>0 then axisMax=axisMax*1.1 else axisMax=axisMax*0.9 axisMin=uRoundDownToPower(axisMin, 10) axisMax=uRoundUpToPower(axisMax, 10) end select end sub 'ver114-7n added SaneLimits sub SaneLimits componConst, byref axisMin, byref axisMax 'Determine sane min and max for data 'If the axis limits are unreasonable, we find better limits 'componConst specifies what type of value we are dealing with. E.g. constTheta. 'axisMin and axisMax are the original limits; we change if necessary. 'This is called when the user changes the type of value graphed, to avoid carryover of goofy values. 'If the user specifies goofy values without changing the data type, we go with his specs. absMin=abs(axisMin) : absMax=abs(axisMax) select componConst case constMagDBM, constMagDB 'Round db/dbm to multiple of 5 if absMin<0.001 then axisMin=0 if absMax<0.001 then axisMax=0 'No tiny values if axisMin<-120 then axisMin=-120 if axisMax<-100 then axisMax=-100 if axisMin>0 then axisMin=0 if axisMax>10 then axisMax=10 if axisMin>=axisMax then axisMin=axisMax-1 'No reverse or zero span case constAngle, constTheta 'Round angles to multiple of 15 if absMin<0.001 then axisMin=0 if absMax<0.001 then axisMax=0 'No tiny values if axisMin<-360 then axisMin=-360 if axisMax>360 then axisMax=360 if axisMin>=axisMax or abs(axisMax-axisMin)<10 then axisMin=-180 : axisMax=180 'Expand to full range 'ver114-8c case constSerR, constParR 'Round resistances to multiple of 25 if axisMin<0.001 then axisMin=0 if axisMax<0.001 then axisMax=0 'No tiny values if axisMin>constMaxValue then axisMin=0 if axisMax>constMaxValue then axisMax=1000 if axisMin>=axisMax then axisMin=0 : axisMax=100 case constReact 'Round reactances to multiple of 25 if absMin<0.001 then axisMin=0 if absMax<0.001 then axisMax=0 'No tiny values if axisMin>constMaxValue then axisMin=0 if axisMax>constMaxValue then axisMin=1000 if axisMin<0-constMaxValue then axisMin=0 if axisMax<0-constMaxValue then axisMax=100 if axisMin>=axisMax then axisMin=-100 : axisMax=100 case constMagWatts, constMagRatio, constMagV, constRho 'Fractional values that won't exceed 1 or be negative if axisMin>1 then axisMin=0 if axisMax>1 then axisMax=1 if axisMin<0 then axisMin=0 if axisMax<0 then axisMax=1 if axisMin>0 then if axisMax/axisMin>=100 then axisMin=0 if axisMin>=axisMax then axisMin=0 : axisMax=1 case constSerC, constSerL, constParC, constParL 'Capacitance and Inductance if absMin<0 then axisMin=0 if absMax<0 then axisMax=1e-6 if absMin>0.001 then axisMin=0 if absMax>0.001 then axisMax=1e-5 if axisMin>=axisMax then axisMin=0 : axisMax=1e-5 case else 'constGD and anything we missed 'don't mess with these end select end sub 'ver114-7f added ReferenceDialog sub ReferenceDialog WindowWidth = 400 : WindowHeight = 350 UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = DisplayHeight-WindowHeight-70 BackgroundColor$="darkblue" ForegroundColor$="white" TextboxColor$="blue" ComboboxColor$="blue" staticText #refDialog.A1, "You may create reference lines from the current data (provided there", 10,10,400,19 staticText #refDialog.A2, "is a full sweep of data), or by simulating an RLC circuit.", 10,30,400,19 'These checkboxes operate as radio buttons 'ver114-7q separated the captions from the checkboxes so the text color comes out right checkbox #refDialog.Clear, "", [refClearOn], [refClearReset], 20, 50, 25, 19 statictext #refDialog, "No Reference Lines",45, 50, 105, 19 checkbox #refDialog.UseData, "", [refUseDataOn], [refUseDataReset], 20, 70, 25, 19 statictext #refDialog, "Use Current Data", 45, 70, 105, 19 checkbox #refDialog.UseRLC, "", [refRLCOn], [refRLCOn], 20, 90, 25, 19 statictext #refDialog, "Use RLC Circuit", 45, 90, 105, 19 staticText #refDialog.RLCInfo, "R=; L=; C=; Trans Line: R0=; Delay= ns", 30,110,400,19 traceLeft=60 : traceTop=140 'ver114-7q separated the captions from the checkboxes so the text color comes out right checkbox #refDialog.t1, "", [t1On], [t1Off],traceLeft+20,traceTop+80, 175, 15 statictext #refDialog, "Do Trace for Left Axis", traceLeft+45,traceTop+80, 175, 15 checkbox #refDialog.t2, "", [t2On], [t2Off],traceLeft+20,traceTop, 175, 15 statictext #refDialog, "Do Trace for Right Axis", traceLeft+45,traceTop, 175, 15 'Trace Color staticText #refDialog.colorLabel1, "Color", traceLeft+5,traceTop+100,75,15 graphicbox #refDialog.color1, traceLeft, traceTop+115, 40, 20 'Trace Color staticText #refDialog.colorLabel2, "Color", traceLeft+5,traceTop+20,75,15 graphicbox #refDialog.color2, traceLeft, traceTop+35, 40, 20 'Trace Color 'Trace width TraceWidths$(0)="1" : TraceWidths$(1)="2" : TraceWidths$(2)="3" staticText #refDialog.widthLabel1 "Width", traceLeft+85,traceTop+100,70,15 Stylebits #refDialog.width1, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h combobox #refDialog.width1, TraceWidths$(), [refDoNothing],traceLeft+80, traceTop+115, 50, 70 'Trace Width staticText #refDialog.widthLabel2 "Width", traceLeft+85,traceTop+20,70,15 Stylebits #refDialog.width2, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h combobox #refDialog.width2, TraceWidths$(), [refDoNothing],traceLeft+80, traceTop+35, 50, 70 'Trace Width 'OK and Cancel buttons button #refDialog.OK, "OK", [refDialogFinished],UL, 300, 240,50,25 button #refDialog.Cancel, "Cancel", [refCancel],UL, 300, 275,50,25 open "Reference Line Specification" for dialog_modal as #refDialog 'Open Reference dialog #refDialog, "trapclose [refDialogFinished]" #refDialog.color1, "when leftButtonDown [PickColor1]" #refDialog.color2, "when leftButtonDown [PickColor2]" #refDialog.A1, "!font Times_New_Roman size 10" #refDialog.A2, "!font Times_New_Roman size 10" form$="3,3,4//UseMultiplier" t1Color$=referenceColor1$ : t2Color$=referenceColor2$ #refDialog.width1, "selectindex ";referenceWidth1 #refDialog.width2, "selectindex ";referenceWidth2 #refDialog.color1, "cls; fill ";t1Color$; ";flush" #refDialog.color2, "cls; fill ";t2Color$; ";flush" if referenceLineType=0 then referenceTrace=0 if msaMode$="SA" then #refDialog.UseRLC, "hide" 'Can't do RLC in SA mode if msaMode$="SA" or msaMode$="ScalarTrans" then 'With no phase, only right axis is available #refDialog.t1, "hide" if referenceTrace>1 then referenceTrace=2 else referenceTrace=0 end if if referenceTrace>1 then #refDialog.t2, "set" else #refDialog.t2, "reset" #refDialog.width2, "hide" : #refDialog.color2, "hide" #refDialog.widthLabel2, "!hide" : #refDialog.colorLabel2, "!hide" end if if referenceTrace=1 or referenceTrace=3 then #refDialog.t1, "set" else #refDialog.t1, "reset" #refDialog.width1, "hide" : #refDialog.color1, "hide" #refDialog.widthLabel1, "!hide" : #refDialog.colorLabel1, "!hide" end if if referenceLineType=1 then #refDialog.UseData, "set" : goto [refUseDataOn] if referenceLineType=2 then #refDialog.UseRLC, "set" : spec$=referenceLineSpec$ : goto [refRLCOn] #refDialog.Clear, "set" : goto [refClearOn] wait 'never gets here [refCancel] close #refDialog exit sub [t1On] #refDialog.width1, "show" : #refDialog.color1, "show" #refDialog.widthLabel1, "!show" : #refDialog.colorLabel1, "!show" #refDialog.color1, "fill ";t1Color$; ";flush" wait [t1Off] #refDialog.width1, "hide" : #refDialog.color1, "hide" #refDialog.widthLabel1, "!hide" : #refDialog.colorLabel1, "!hide" wait [t2On] #refDialog.width2, "show" : #refDialog.color2, "show" #refDialog.widthLabel2, "!show" : #refDialog.colorLabel2, "!show" #refDialog.color2, "cls; fill ";t2Color$; ";flush" wait [t2Off] #refDialog.width2, "hide" : #refDialog.color2, "hide" #refDialog.widthLabel2, "!hide" : #refDialog.colorLabel2, "!hide" wait [refClearOn] #refDialog.UseData, "reset" #refDialog.UseRLC, "reset" #refDialog.RLCInfo, "!hide" #refDialog.t1, "hide" gosub [HideTrace1] #refDialog.t2, "hide" gosub [HideTrace2] wait [refClearReset] #refDialog.Clear, "set" 'Prevents reset wait [refUseDataOn] #refDialog.Clear, "reset" #refDialog.UseRLC, "reset" #refDialog.RLCInfo, "!hide" gosub [ShowEligibleTraces] wait [refUseDataReset] #refDialog.UseData, "set" 'Prevents reset wait [refRLCOn] 'RLC turned on or re-clicked when already on #refDialog.UseData, "reset" #refDialog.Clear, "reset" #refDialog.UseRLC, "set" 'So we can never turn off by clicking #refDialog.RLCInfo, "!hide" gosub [ShowEligibleTraces] 'Get current RLC spec; if invalid do defaults parseErr=uParseRLC(spec$, DialogRLCConnect$, DialogRValue, DialogLValue, _ DialogCValue, DialogR0Value, DialogDelayValue) if parseErr then spec$="S,R0,L0,C";constMaxValue;",Z50,D0" DialogRLCConnect$="S" : DialogRValue=0 : DialogLValue=0 : _ DialogCValue=constMaxValue : DialogR0Value=50 : DialogDelayValue=0 end if call RLCDialog if DialogCancelled then wait 'Get the new values; display them form$="3,3,4//UseMultiplier" R$=uFormatted$(DialogRValue, form$) L$=uFormatted$(DialogLValue, form$) C$=uFormatted$(DialogCValue, form$) R0$=uFormatted$(DialogR0Value, form$) Delay$=uFormatted$(DialogDelayValue, form$) if DialogRLCConnect$="S" then con$="Series" else con$="Parallel" #refDialog.RLCInfo, con$;" R=";R$;" L=";L$; "h C=";C$; "f R0=";R0$; " Delay=";Delay$;"s" #refDialog.RLCInfo, "!show" 'Create the RLC spec string spec$=DialogRLCConnect$;",R";uCompact$(R$);",L";uCompact$(L$); ",C";uCompact$(C$); ",Z";uCompact$(R0$); ",D";uCompact$(Delay$) wait [refRLCOff] #refDialog.RLCInfo, "!hide" wait [PickColor1] ColorDialog t1Color$, newColor$ if newColor$<>"" then t1Color$=newColor$ #refDialog.color1, "fill "; t1Color$;";flush" 'Fill box with new trace color end if wait [PickColor2] ColorDialog t2Color$, newColor$ if newColor$<>"" then t2Color$=newColor$ #refDialog.color2, "fill "; t2Color$;";flush" 'Fill box with new trace color end if wait [HideTrace1] #refDialog.width1, "hide" : #refDialog.color1, "hide" #refDialog.widthLabel1, "!hide" : #refDialog.colorLabel1, "!hide" return [ShowTrace1] #refDialog.width1, "show" : #refDialog.color1, "show" #refDialog.widthLabel1, "!show" : #refDialog.colorLabel1, "!show" return [HideTrace2] #refDialog.width2, "hide" : #refDialog.color2, "hide" #refDialog.widthLabel2, "!hide" : #refDialog.colorLabel2, "!hide" return [ShowTrace2] #refDialog.width2, "show" : #refDialog.color2, "show" #refDialog.widthLabel2, "!show" : #refDialog.colorLabel2, "!show" return [ShowEligibleTraces] if msaMode$<>"SA" and msaMode$<>"ScalarTrans" then #refDialog.t1, "show" #refDialog.t1, "value? s$" if s$="set" then gosub [ShowTrace1] end if #refDialog.t2, "show" #refDialog.t2, "set" gosub [ShowTrace2] return [refDialogFinished] referenceTrace=0 #refDialog.t1, "value? s$" if s$="set" then referenceTrace=referenceTrace+1 referenceColor1$=t1Color$ #refDialog.width1, "selectionindex? i" if i<1 then i=1 referenceWidth1=i end if #refDialog.t2, "value? s$" if s$="set" then referenceTrace=referenceTrace+2 referenceColor2$=t2Color$ #refDialog.width2, "selectionindex? i" if i<1 then i=1 referenceWidth2=i end if if referenceTrace>0 and s$="set" then 'If no trace selected, don't do ref 'Use current data as reference referenceLineType=1 : referenceLineSpec$="" else #refDialog.UseRLC, "value? s$" if referenceTrace>0 and s$="set" then 'Use RLC as reference referenceLineType=2 : referenceLineSpec$=spec$ else 'No reference lines referenceLineType=0 : referenceLineSpec$="" : referenceTrace=0 call gClearAllReferences refreshGridDirty=1 call RefreshGraph 0 close #refDialog exit sub end if end if call CreateReferenceSource close #refDialog refreshGridDirty=1 call RefreshGraph 0 end sub 'ver114-7f added RLCDialog sub RLCDialog WindowWidth = 400 : WindowHeight = 300 UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = DisplayHeight-WindowHeight-60 BackgroundColor$="darkblue" ForegroundColor$="white" TextboxColor$="blue" ComboboxColor$="blue" staticText #RLCDialog.A1, "Specify a parallel or serial combination of R, L and C. The", 10,10,350,19 staticText #RLCDialog.A2, "combination is connected to the test circuit via a transmission line", 10,30,350,19 staticText #RLCDialog.A3, "with the specified characteristic impedance and one-way time delay.", 10,50,375,19 staticText #RLCDialog.A4, "Specify zero delay for a direct connection.", 10,70,350,19 RLCTop=100 'ver114-7q separated the captions from the checkboxes so the text color comes out right checkbox #RLCDialog.Parallel, "", [RLCParOn], [RLCParReset], 10, RLCTop, 25, 19 staticText #RLCDialog, "Parallel", 35, RLCTop, 45, 19 checkbox #RLCDialog.Series, "", [RLCSerOn], [RLCSerReset], 80, RLCTop, 25, 19 staticText #RLCDialog, "Series", 105, RLCTop, 45, 19 checkbox #RLCDialog.selR, "", [RLCROn], [RLCROff], 20, RLCTop+20, 25, 19 staticText #RLCDialog, "Resistance (ohms)", 45, RLCTop+20, 93, 19 checkbox #RLCDialog.selL, "", [RLCLOn], [RLCLOff], 20, RLCTop+45, 25, 19 staticText #RLCDialog, "Inductance (henries)", 45, RLCTop+45, 93, 19 checkbox #RLCDialog.selC, "", [RLCCOn], [RLCCOff], 20, RLCTop+70, 25, 19 staticText #RLCDialog, "Capacitance (farads)", 45, RLCTop+70, 93, 19 textbox #RLCDialog.R, 145, RLCTop+20, 50, 19 textbox #RLCDialog.L, 145, RLCTop+45, 50, 19 textbox #RLCDialog.C, 145, RLCTop+70, 50, 19 staticText #RLCDialog.A5, "Transmission Line Connection", 25,RLCTop+100,150,19 staticText #RLCDialog.A6, "R0=", 15,RLCTop+120,25,19 staticText #RLCDialog.A7, "Delay=", 87,RLCTop+120,35,19 textbox #RLCDialog.R0, 42, RLCTop+120, 35, 19 textbox #RLCDialog.Delay, 125, RLCTop+120, 50, 19 staticText #RLCDialog.A8, "ns", 180,RLCTop+120,30,19 'OK and Cancel buttons button #RLCDialog.OK, "OK", [RLCDialogFinished],UL, 240, 225,50,25 button #RLCDialog.Cancel, "Cancel", [RLCCancel],UL, 320, 225,50,25 open "RLC Specification" for dialog_modal as #RLCDialog 'Open preference dialog #RLCDialog, "trapclose [RLCDialogFinished]" #RLCDialog.A1, "!font Times_New_Roman size 10" #RLCDialog.A2, "!font Times_New_Roman size 10" #RLCDialog.A3, "!font Times_New_Roman size 10" #RLCDialog.A4, "!font Times_New_Roman size 10" DialogCancelled=0 'Display existing values form$="3,3,4//UseMultiplier" R$=uFormatted$(DialogRValue, form$) L$=uFormatted$(DialogLValue, form$) C$=uFormatted$(DialogCValue, form$) R0$=uFormatted$(DialogR0Value, form$) Delay$=using("###.###",DialogDelayValue*1e9) 'Stored in seconds; displayed in ns #RLCDialog.R, R$ #RLCDialog.L, L$ #RLCDialog.C, C$ #RLCDialog.R0, R0$ #RLCDialog.Delay, Delay$ #RLCDialog.selR, "set" : #RLCDialog.selL, "set" : #RLCDialog.selC, "set" 'Always show a resistance; show L and C only if they are meaningful if DialogRLCConnect$="S" then #RLCDialog.Series, "set" #RLCDialog.Parallel, "reset" if DialogLValue=0 then #RLCDialog.selL, "reset" : #RLCDialog.L, "!hide" if DialogCValue>=constMaxValue then #RLCDialog.selC, "reset" : #RLCDialog.C, "!hide" else #RLCDialog.Parallel, "set" #RLCDialog.Series, "reset" if DialogLValue>=constMaxValue then #RLCDialog.selL, "reset" : #RLCDialog.L, "!hide" if DialogCValue=0 then #RLCDialog.selC, "reset" : #RLCDialog.C, "!hide" end if wait [RLCCancel] DialogCancelled=1 close #RLCDialog exit sub [RLCParOn] #RLCDialog.Parallel, "set" #RLCDialog.Series, "reset" wait [RLCParReset] #RLCDialog.Parallel, "set" 'Prevents reset wait [RLCSerOn] #RLCDialog.Series, "set" #RLCDialog.Parallel, "reset" wait [RLCSerReset] #RLCDialog.Series, "set" 'Prevents reset wait [RLCROn] #RLCDialog.R, "!show" wait [RLCROff] #RLCDialog.R, "!hide" wait [RLCLOn] #RLCDialog.L, "!show" wait [RLCLOff] #RLCDialog.L, "!hide" wait [RLCCOn] #RLCDialog.C, "!show" wait [RLCCOff] #RLCDialog.C, "!hide" wait [RLCDialogFinished] #RLCDialog.Parallel, "value? s$" if s$="reset" then DialogRLCConnect$="S" else DialogRLCConnect$="P" #RLCDialog.selR, "value? s$" if s$="reset" then 'if no R, use 0 for series and large value for parallel if DialogRLCConnect$="P" then DialogRValue=constMaxValue else DialogRValue=0 else #RLCDialog.R, "!contents? s$" DialogRValue=uValWithMult(s$) : if DialogRValue<0 then DialogRValue=0 end if #RLCDialog.selL, "value? s$" if s$="reset" then 'if no L, use 0 for series and large value for parallel if DialogRLCConnect$="P" then DialogLValue=constMaxValue else DialogLValue=0 else #RLCDialog.L, "!contents? s$" DialogLValue=uValWithMult(s$) : if DialogLValue<0 then DialogLValue=0 end if #RLCDialog.selC, "value? s$" if s$="reset" then 'if no C, use large value for series and 0 for parallel if DialogRLCConnect$="P" then DialogCValue=0 else DialogCValue=constMaxValue else #RLCDialog.C, "!contents? s$" DialogCValue=uValWithMult(s$) : if DialogCValue<0 then DialogCValue=0 end if #RLCDialog.R0, "!contents? s$" DialogR0Value=uValWithMult(s$) : if DialogR0Value<=0 then DialogR0Value=50 #RLCDialog.Delay, "!contents? s$" DialogDelayValue=val(uCompact$(s$))/1e9 'stored in seconds; displayed in ns close #RLCDialog end sub 'SEWgraph added DisplayAxisYPreference sub DisplayAxisYPreference axisNum 'Display dialog to select Y axis preferences if axisPrefHandle$<>"" then close #axisPrefHandle$ 'If pref window already open; close it WindowWidth = 550 : WindowHeight = 275 UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = DisplayHeight-WindowHeight-70 BackgroundColor$="darkblue" ForegroundColor$="white" TextboxColor$="blue" ComboboxColor$="blue" 'Ver114-6k rearranged and added graph data selection and autoscale. 'Top and bottom widths staticText #axis, "Top Ref", 120,10,50,15 textbox #axis.topref, 120, 25, 50,20 'Top Ref staticText #axis, "Bot Ref", 120,50,50,15 textbox #axis.botref, 120, 65, 50,20 'Bot Ref 'ver114-7q separated the captions from the checkboxes so the text color comes out right checkbox #axis.auto, "",[axisAutoscaleOn], [axisYDoNothing],120, 100, 25,15 'Auto Scale staticText #axis, "Auto Scale",140, 100, 60,15 'Auto Scale 'Trace Color staticText #axis, "Trace Color", 10,10,70,15 graphicbox #axis.color, 10, 25, 50, 20 'Trace Color 'Trace width staticText #axis "Trace Width", 10,50,70,15 TraceWidths$(0)="1" : TraceWidths$(1)="2" : TraceWidths$(2)="3" Stylebits #axis.width, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h combobox #axis.width, TraceWidths$(), [axisYDoNothing],10, 65, 50, 70 'Trace Width 'Trace style (Norm Erase,...) staticText #axis "Trace Style", 15,95,70,15 if axisNum=1 then if phadisp > 2 then phadisp = 0 TraceStyles$(0)="Off" : TraceStyles$(1)="Erase" : TraceStyles$(2)="Stick" TraceStyles$(4)="" : TraceStyles$(5)="" else if msaMode$="SA" or msaMode$="ScalarTrans" then TraceStyles$(0)="Off" : TraceStyles$(1)="Norm Erase" : TraceStyles$(2)="Norm Stick" TraceStyles$(4)="Histo Erase" : TraceStyles$(5)="Histo Stick" else TraceStyles$(0)="Off" : TraceStyles$(1)="Erase" : TraceStyles$(2)="Stick" TraceStyles$(4)="" : TraceStyles$(5)="" end if end if Stylebits #axis.style, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h combobox #axis.style, TraceStyles$(), [axisYDoNothing],10, 110, 80, 120 'Trace Style 'Number of vertical divisions staticText #axis "Number of Divisions", 10,140,140,15 staticText #axis "(Affects both Y axes)", 10,155,140,15 NumVertDiv$(0)="4" : NumVertDiv$(1)="5" : NumVertDiv$(2)="6" 'ver114-7o changed to NumVertDiv$ NumVertDiv$(3)="8" : NumVertDiv$(4)="10" : NumVertDiv$(5)="12" combobox #axis.NDiv, NumVertDiv$(), [axisYDoNothing],25, 170, 60, 120 'Number of vert divisions 'OK and Cancel buttons button #axis.OK, "OK", [axisYFinished],UL, 220, 175,50,25 button #axis.Cancel, "Cancel", [axisYCancel],UL, 300, 175,50,25 axisDataLeft=220 : axisDataTop=25 dim axisGraphData$(20) : dim axisSourceConst(20) : dim axisComponentConst(20) for i=0 to 20 : axisGraphData$(i)="" : next i if msaMode$="SA" then origSource=Y2SourceConst : origCompon=Y2ComponentConst 'ver114-7n axisGraphData$(0)="Magnitude (dBm)" : axisSourceConst(0)=constRaw : axisComponentConst(0)=constMagDBM axisGraphData$(1)="Magnitude (Watts)" : axisSourceConst(1)=constLinearMag : axisComponentConst(1)=constMagWatts axisGraphData$(2)="Magnitude (Volts)" : axisSourceConst(2)=constLinearMag : axisComponentConst(2)=constMagV end if if msaMode$="ScalarTrans" then origSource=Y2SourceConst : origCompon=Y2ComponentConst 'ver114-7n axisGraphData$(0)="Magnitude (dB)": axisSourceConst(0)=constRaw : axisComponentConst(0)=constMagDB axisGraphData$(1)="Magnitude (Ratio)" : axisSourceConst(1)=constLinearMag : axisComponentConst(1)=constMagRatio end if if msaMode$="VectorTrans" then if axisNum=1 then origSource=Y1SourceConst : origCompon=Y1ComponentConst 'ver114-7n axisGraphData$(0)="S21 Phase Angle" : axisSourceConst(0)=constRaw : axisComponentConst(0)=constAngle axisGraphData$(1)="S21 Group Delay" : axisSourceConst(1)=constRaw : axisComponentConst(1)=constGD if S21DoTransform then 'ver114-7b 'This graph data is possible only for the proper types of devices axisGraphData$(2)="S11 Phase Angle" : axisSourceConst(2)=constS11 : axisComponentConst(2)=constAngle axisGraphData$(3)="Reflect Coeff: Theta" : axisSourceConst(3)=constRefco : axisComponentConst(3)=constTheta axisGraphData$(4)="Impedance: Reactance" : axisSourceConst(4)=constImpedance : axisComponentConst(4)=constReact axisGraphData$(5)="Equiv Series Capacitance" : axisSourceConst(5)=constImpedance : axisComponentConst(5)=constSerC axisGraphData$(6)="Equiv Series Inductance" : axisSourceConst(6)=constImpedance : axisComponentConst(6)=constSerL axisGraphData$(7)="Equiv Parallel Capacitance" : axisSourceConst(7)=constImpedance : axisComponentConst(7)=constParC axisGraphData$(8)="Equiv Parallel Inductance" : axisSourceConst(8)=constImpedance : axisComponentConst(8)=constParL end if else origSource=Y2SourceConst : origCompon=Y2ComponentConst 'ver114-7n axisGraphData$(0)="S21 Magnitude (dB)" : axisSourceConst(0)=constRaw : axisComponentConst(0)=constMagDB axisGraphData$(1)="Magnitude (Ratio)" : axisSourceConst(1)=constLinearMag : axisComponentConst(1)=constMagRatio 'ver114-7n added this and renumbered the remainder if S21DoTransform then 'ver114-7b axisGraphData$(2)="S11 Magnitude (dB)" : axisSourceConst(2)=constS11 : axisComponentConst(2)=constMagDB axisGraphData$(3)="Reflect Coeff: Rho" : axisSourceConst(3)=constRefco : axisComponentConst(3)=constRho axisGraphData$(4)="Impedance: Resistance" : axisSourceConst(4)=constImpedance : axisComponentConst(4)=constSerR axisGraphData$(5)="Equiv Parallel Resistance" : axisSourceConst(5)=constImpedance : axisComponentConst(5)=constParR end if end if if S21DoTransform then 'ver114-7b staticText #axis.S21Instruct0, "Per Options->Transmission Setup:",axisDataLeft, axisDataTop+60, 300,15 'modver114-7j s$="S21 is graphed with a reference impedance of ";S21R0;" ohms," staticText #axis.S21Instruct1, s$,axisDataLeft, axisDataTop+75, 300,15 staticText #axis.S21Instruct2, "and graphing S21 as anything other than S21 data",axisDataLeft, axisDataTop+90, 300,15 staticText #axis.S21Instruct3, "assumes a two-terminal DUT connected in ";S21JigAttach$,axisDataLeft, axisDataTop+105, 300,15 s$="with source and load impedances of ";S21JigR0;" ohms." staticText #axis.S21Instruct4, s$,axisDataLeft, axisDataTop+120, 300,15 end if end if if msaMode$="Reflection" then if axisNum=1 then origSource=Y1SourceConst : origCompon=Y1ComponentConst 'ver114-7n axisGraphData$(0)="S11 Phase Angle" : axisSourceConst(0)=constRaw : axisComponentConst(0)=constAngle axisGraphData$(1)="Reflect Coeff: Theta" : axisSourceConst(1)=constRefco : axisComponentConst(1)=constTheta axisGraphData$(2)="Impedance: Reactance" : axisSourceConst(2)=constImpedance : axisComponentConst(2)=constReact axisGraphData$(3)="Equiv Series Capacitance" : axisSourceConst(3)=constImpedance : axisComponentConst(3)=constSerC axisGraphData$(4)="Equiv Series Inductance" : axisSourceConst(4)=constImpedance : axisComponentConst(4)=constSerL axisGraphData$(5)="Equiv Parallel Capacitance" : axisSourceConst(5)=constImpedance : axisComponentConst(5)=constParC axisGraphData$(6)="Equiv Parallel Inductance" : axisSourceConst(6)=constImpedance : axisComponentConst(6)=constParL else origSource=Y2SourceConst : origCompon=Y2ComponentConst 'ver114-7n xisGraphData$(0)="S11 Magnitude (dB)" : axisSourceConst(0)=constS11 : axisComponentConst(0)=constMagDB axisGraphData$(1)="Reflect Coeff: Rho" : axisSourceConst(1)=constRefco : axisComponentConst(1)=constRho axisGraphData$(2)="Impedance: Resistance" : axisSourceConst(2)=constImpedance : axisComponentConst(2)=constSerR axisGraphData$(3)="Equiv Parallel Resistance" : axisSourceConst(3)=constImpedance : axisComponentConst(3)=constParR end if staticText #axis.S21Instruct0, "Per Options->S11 Setup:",axisDataLeft, axisDataTop+60, 300,15 s$="S11 is measured on a bridge with reference impedance of ";S11BridgeR0 s$=s$;" ohms and graphed with reference impedance of ";S11GraphR0;" ohms." staticText #axis.S11Instruct1, s$,axisDataLeft, axisDataTop+75, 310,30 'ver114-7b end if staticText #axis.Instruct1, "Graph Data",axisDataLeft, axisDataTop, 270,15 Stylebits #axis.GraphData, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h comboBox #axis.GraphData, axisGraphData$(),[axisYDoNothing], axisDataLeft, axisDataTop+15, 175, 160 open "Axis Y";axisNum for dialog_modal as #axis 'Open preference dialog axisPrefHandle$="#axis" #axis, "trapclose [axisYFinished]" call gGetAxisFormats xForm$, y1Form$, y2Form$ #axis.color, "when leftButtonDown [PickColor]" 'Get some existing values call gGetTraceWidth w1, w2 'Trace widths call gGetTraceColors c1$, c2$ 'Trace colors if axisNum=1 then yForm$=y1Form$ tWidth=w1 tColor$=c1$ if autoScaleY1 then #axis.auto, "set" else #axis.auto, "reset" 'ver114-7a else yForm$=y2Form$ tWidth=w2 tColor$=c2$ if autoScaleY2 then #axis.auto, "set" else #axis.auto, "reset" 'ver114-7a end if 'Fill in preference choices with current values call gGetYAxisRange axisNum, yMin, yMax 'Previously specified min and max topref$= uFormatted$(yMax, yForm$): botref$=uFormatted$(yMin, yForm$) 'ver114-7n print #axis.topref, topref$ 'ver114-7n print #axis.botref, botref$ 'ver114-7n origTopRef=uValWithMult(topref$) : origBotRef=uValWithMult(botref$) 'ver114-7n #axis.color, "fill "; tColor$;";flush" 'Fill box with current trace color #axis.width, "select ";tWidth #axis.width, "setfocus" 'So selection is visually active call gGetNumDivisions nHorDiv, nVertDiv #axis.NDiv, "!";nVertDiv #axis.NDiv, "setfocus" 'So selection is visually active 'select initial trace style based on magdisp or phadisp. Note those variables run from 0 but 'combobox selection indices run from 1; hence the +1 if axisNum=1 then #axis.style, "selectindex ";phadisp+1 _ else #axis.style, "selectindex ";magdisp+1 #axis.style, "setfocus" 'Visually activate 'Select current graph data sel=0 if msaMode$="SA" then if Y2ComponentConst=constMagDBM then sel=1 if Y2ComponentConst=constMagWatts then sel=2 if Y2ComponentConst=constMagV then sel=3 end if if msaMode$="ScalarTrans" then if Y2ComponentConst=constMagDB then sel=1 if Y2ComponentConst=constMagRatio then sel=2 end if if msaMode$="VectorTrans" then if axisNum=1 then if Y1SourceConst=constRaw and Y1ComponentConst=constAngle then sel=1 if Y1ComponentConst=constGD then sel=2 if Y1SourceConst=constS11 and Y1ComponentConst=constAngle then sel=3 if Y1ComponentConst=constTheta then sel=4 if Y1ComponentConst=constReact then sel=5 if Y1ComponentConst=constSerC then sel=6 if Y1ComponentConst=constSerL then sel=7 if Y1ComponentConst=constParC then sel=8 if Y1ComponentConst=constParL then sel=9 else if Y2SourceConst=constRaw and Y2ComponentConst=constMagDB then sel=1 if Y2ComponentConst=constMagRatio then sel=2 'ver114-7n added this and renumbered the remainder if Y2SourceConst=constS11 and Y2ComponentConst=constMagDB then sel=3 if Y2ComponentConst=constRho then sel=4 if Y2ComponentConst=constSerR then sel=5 if Y2ComponentConst=constParR then sel=6 end if end if if msaMode$="Reflection" then if axisNum=1 then if Y1ComponentConst=constAngle then sel=1 if Y1ComponentConst=constTheta then sel=2 if Y1ComponentConst=constReact then sel=3 if Y1ComponentConst=constSerC then sel=4 if Y1ComponentConst=constSerL then sel=5 if Y1ComponentConst=constParC then sel=6 if Y1ComponentConst=constParL then sel=7 else if Y2ComponentConst=constMagDB then sel=1 if Y2ComponentConst=constRho then sel=2 if Y2ComponentConst=constSerR then sel=3 if Y2ComponentConst=constParR then sel=4 end if end if 'sel now has the index (1...) to use to select the current data type #axis.GraphData, "selectindex ";sel #axis.GraphData, "setfocus" #axis.color, "setfocus" 'to get focus off combo box, so scroll wheel doesn't affect it call RememberState 'Remember variables so we can detect changes wait 'Wait for user to make choices 'User gets here by double-click. If he double clicks again before we are open, we may end up 'with the double-click event. We need to provide this method so as not to crash. ver114-1n [LeftButDouble] wait [axisYDoNothing] 'embedded in DisplayYAxisPreference wait 'ver114-7a added [axisAutoscaleOn] [axisAutoscaleOn] 'autoscaling turned on call CalcAutoScale axisNum, axisMin, axisMax #axis.topref, axisMax : #axis.botref, axisMin wait [PickColor] 'embedded in DisplayYAxisPreference ColorDialog tColor$, newColor$ if newColor$<>"" then tColor$=newColor$ #axis.color, "fill "; tColor$;";flush" 'Fill box with new trace color end if wait [axisYCancel] 'User has cancelled; 'embedded in DisplayYAxisPreference close #axis axisPrefHandle$="" exit sub [axisYFinished] 'Window is being closed; record choices; 'embedded in DisplayAxisYPreference 'Get the source const and component const for the selected graph #axis.GraphData, "selectionindex? sel" newSource=axisSourceConst(sel-1) : newCompon=axisComponentConst(sel-1) 'ver114-7n if axisNum=1 then Y1SourceConst=newSource :Y1ComponentConst=newCompon 'ver114-7n else Y2SourceConst=newSource :Y2ComponentConst=newCompon 'ver114-7n end if #axis.topref "!contents? newTop$" #axis.botref "!contents? newBot$" #axis.width, "selection? newWidth$" 'uCompact deletes blanks, which can mess up negative numbers newTop=uValWithMult(newTop$) : newBot=uValWithMult(newBot$) : newWidth=val(uCompact$(newWidth$)) if newWidth<1 then newWidth=1 else if newWidth>3 then newWidth=3 if newTopnewSource or origCompon<>newCompon) 'ver114-7n topSame=(newTop=origTopRef) : botSame=(newBot=origBotRef) 'ver114-7n if dataChanged and topSame and botSame then _ call SaneLimits newCompon, newBot, newTop 'ver114-7n 'ver114-6f added a check for zero range. if newBot=newTop then newBot=yMin : newTop=yMax : notice "Axis range cannot be zero. Previous values retained." call gGetTextColors xCol$, y1Col$, y2Col$,gridCol$ #axis.auto, "value? auto$" if axisNum=1 then w1=newWidth c1$=tColor$ : y1Col$=tColor$ 'Set trace and grid labels to same color call SetPhaseRange newBot, newTop 'May not actually be phase ver114-7n if auto$="set" then autoScaleY1=1 else autoScaleY1=0 'ver114-7a else w2=newWidth c2$=tColor$ : y2Col$=tColor$ 'Set trace and grid labels to same color call SetPowerRange newBot, newTop 'May not actually be power ver114-7n if auto$="set" then autoScaleY2=1 else autoScaleY2=0 'ver114-7a end if call gSetTraceColors c1$, c2$ call gSetTraceWidth w1, w2 call gSetTextColors xCol$, y1Col$, y2Col$,gridCol$ #axis.NDiv, "contents? nDiv$" nVertDiv=val(nDiv$) : if nVertDiv<1 then nVertDiv=1 else if nVertDiv>12 then nVertDiv=12 call gSetNumDivisions nHorDiv, nVertDiv 'ver114-7n deleted call gCalcGraphParams; DetectChanges will handle that #axis.style, "selectionIndex? axisStyle" if axisStyle<1 then axisStyle=1 if axisNum=1 then 'Set phadisp or magdisp from contents of axis style box phadisp=axisStyle-1 else magdisp=axisStyle-1 end if call ImplementPhaMagDisp 'ver114-6e close #axis axisPrefHandle$="" call DetectChanges 0 'Redraw as required and/or signal to restart via continueCode end sub 'end DisplayAxisYPreference 'ver114-5o added [menuFreqAxisPreference] as wrapper to be invoked by menu; 'ends in wait instead of return [menuFreqAxisPreference] gosub [FreqAxisPreference] wait 'SEWgraph added [FreqAxisPreference] [FreqAxisPreference] 'Call routine to display frequency axis preference window. We do this in two stages because 'the subroutine cannot access steps directly (it is not global, for speed reasons). 'ver114-5o modified to require restart only when absolutely necessary 'ver114-6e revised needRestart=DisplayAxisXPreference() steps=globalSteps 'transfer to non-global sweepDir=gGetSweepDir() 'transfer to non-global gosub [SelectFilter] if needRestart=1 then if haltsweep=1 then haltsweep=0 'so Restart actually restarts goto [Restart] else call RequireRestart end if else 'Return to what we were doing continueCode=0 'signal to keep going if haltsweep=1 then goto [PostScan] end if wait 'SEWgraph added DisplayAxisXPreference 'ver114-5o merged misc. setup dialog into this one function DisplayAxisXPreference() 'Display dialog to select axis preferences 'Returns 1 if a restart is needed--only if frequency points or direction changed if axisPrefHandle$<>"" then close #axisPrefHandle$ 'If pref window already open; close it WindowWidth = 800 : WindowHeight = 220 UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = DisplayHeight-WindowHeight-70 BackgroundColor$="darkblue" ForegroundColor$="white" TextboxColor$="blue" ComboboxColor$="blue" statictext #axis.modeLab, "Data Mode", 15, 10, 90, 15 specialGraphs$(0)="0(Normal Operation)" specialGraphs$(1)="1(Graph Mag Cal)" specialGraphs$(2)="2(Graph Freq Cal)" specialGraphs$(3)="3(Graph Noisy Sine)" specialGraphs$(4)="4(Graph 1MHz Peak)" specialGraphs$(5)="5(RLC)" Stylebits #axis.OpMode, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h combobox #axis.OpMode, specialGraphs$(), [axisSetupNOP], 5, 25, 130, 130 'Operating Mode ver114-7h statictext #axis.filter, "Select Final Filter Path:", 5, 55, 130, 12 Stylebits #axis.FiltList, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h combobox #axis.FiltList, MSAFiltStrings$(), [axisSetupNOP],5,68,140,100 'Filter list ver114-7o 'ver114-5p added Video Filter statictext #axis.vidLab, "Video Filter BW", 15,100,80,15 videoFilts$(0)="Wide" videoFilts$(1)="Mid" videoFilts$(2)="Narrow" Stylebits #axis.VideoFilt, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h combobox #axis.VideoFilt, videoFilts$(), [axisSetupNOP], 5, 115, 100, 100 'Video Filter ver114-5p statictext #axis, "Graph Appearance",5,140,130,15 Appearances$(0)="DARK" : Appearances$(1)="LIGHT" : Appearances$(2)="SEPIA" 'Stylebits #axis.Appearance, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h del114_7i so box generates click event combobox #axis.Appearance, Appearances$(), [axisSetupSelectAppearance], 5, 155, 100,100 'Appearance List 'ver114-7q separated the captions from the checkboxes so the text color comes out right checkbox #axis.Refresh, "", [axisSetupNOP], [axisSetupNOP], 150, 15, 25, 15 statictext #axis, "Refresh Screen Each Scan", 170, 15, 140, 15 checkbox #axis.SweepTime, "", [axisSetupNOP], [axisSetupNOP], 150, 35, 25, 15 'ver114-4f statictext #axis, "Display Sweep Time", 170, 35, 140, 15 'ver114-5j moved invdeg and planeadj items to different dialog 'ver114-4i moved spurbox items and normReverse button to apply only for SA mode. if msaMode$="SA" or msaMode$="ScalarTransmission" then 'No vna; do SigGen/TrackGen buttons if we have TG 'ver114-7q separated the captions from the checkboxes so the text color comes out right checkbox #axis.spurbox, "",[axisSetupNOP], [axisSetupNOP], 325, 15, 20, 15 'ver114-4f statictext #axis, "Spur Test", 345, 15, 85, 15 'ver114-4j deleted some initializations, to leave current variables as is 'ver114-4j change preset button to normReverse, temporarily labeled Normal; only created for SA mode with TGtop=2 'ver114-7o moved the sig gen items to left if TGtop = 2 then button #axis.normReverse, "Normal", [NormRevbutton], UL, 280, 75, 48, 20 'ver111-18 button #axis.sigenbutton, "Signal Generator", [SignalGeneratorbutton], UL, 170, 75, 100, 20 'ver111-17 statictext #axis.enterfreqtxt, "Enter Freq", 170, 102, 65, 15 'ver111-26 textbox #axis.freqoffbox, 235, 100, 72, 20 'create box for Sig Gen freq or Trk Gen offset freq'ver111-17 statictext #axis.freqenter, "MHz", 310, 102, 24, 15 'ver111-17 else 'modes with phase statictext #axis.pdminvert, "PDM Inversion (deg)", 320,15,105,15 textbox #axis.invdegbox, 335, 30, 50, 20 statictext #axis.planeadj, "Plane Extension (ns)", 315, 60, 105, 15 'ver114-7g textbox #axis.planeadjbox, 335, 75, 50, 20 'create "plane extension" box end if sweepParamLeft=450 : sweepParamTop=30 'Center/Span frequencies and Start/Stop frequencies, with radio buttons to select one pair groupbox #axis.ParamGroup, "", sweepParamLeft-2, sweepParamTop-23, 310, 56 checkbox #axis.btnCentSpan, "", [setCentSpan], [setStartStop], sweepParamLeft+2,sweepParamTop, 14, 12 statictext #axis.CentLab, "Cent", sweepParamLeft+18, sweepParamTop-12, 27,15 statictext #axis.SpanLab, "Span", sweepParamLeft+18, sweepParamTop+11, 27,15 statictext #axis.MHzLabA, "MHz", sweepParamLeft+125, sweepParamTop-12, 25,15 statictext #axis.MHzLabB, "MHz", sweepParamLeft+125, sweepParamTop+12, 25,15 textbox #axis.SweepCent, sweepParamLeft+46, sweepParamTop-12, 75,19 textbox #axis.SweepSpan, sweepParamLeft+46, sweepParamTop+9, 75,19 checkbox #axis.btnStartStop, "", [setStartStop], [setCentSpan], sweepParamLeft+160,sweepParamTop, 14, 12 statictext #axis.StartLab, "Start", sweepParamLeft+175, sweepParamTop-12, 25,15 statictext #axis.StopLab, "Stop", sweepParamLeft+175, sweepParamTop+11, 25,15 statictext #axis.MHzLabC, "MHz", sweepParamLeft+278, sweepParamTop-12, 25,15 statictext #axis.MHzLabD, "MHz", sweepParamLeft+278, sweepParamTop+12, 25,15 textbox #axis.SweepStart, sweepParamLeft+201, sweepParamTop-12, 75,19 textbox #axis.SweepStop, sweepParamLeft+201, sweepParamTop+8, 75,19 'Steps per sweep statictext #axis.StepsLab, "Steps/Sweep", sweepParamLeft-10, sweepParamTop+40, 68,15 textbox #axis.SweepSteps, sweepParamLeft, sweepParamTop+55, 40,19 'Wait time moved here by ver114-4d statictext #axis.WaitLab, "Wait (ms)", sweepParamLeft-3, sweepParamTop+80, 45,13 textbox #axis.SweepWait, sweepParamLeft, sweepParamTop+93, 40,19 'Number of horizontal divisions staticText #axis.DivLab1 "Number of", sweepParamLeft+80,sweepParamTop+50,60,15 staticText #axis.DivLab2 "Divisions", sweepParamLeft+80,sweepParamTop+64,60,15 NumHorDiv$(0)="4" : NumHorDiv$(1)="6" : NumHorDiv$(2)="8" 'ver114-7o changed to NumHorDiv$ NumHorDiv$(3)="10" : NumHorDiv$(4)="12" combobox #axis.NDiv, NumHorDiv$(), [axisXDoNothing],sweepParamLeft+80, sweepParamTop+78, 50, 120 'Groupbox with "radio" buttons for linear/log groupbox #axis.group, "Sweep", sweepParamLeft+160, sweepParamTop+40, 165, 60 'ver114-7q separated the captions from the checkboxes so the text color comes out right checkbox #axis.linear, "", [axisXSelLinear],[axisXSelLog],sweepParamLeft+215, sweepParamTop +55, 20, 15 staticText #axis, "Linear",sweepParamLeft+230, sweepParamTop +55, 40, 15 checkbox #axis.log, "", [axisXSelLog],[axisXSelLinear],sweepParamLeft+275, sweepParamTop +55, 20, 15 staticText #axis, "Log", sweepParamLeft+290, sweepParamTop +55, 30, 15 'ver114-4k added reverse checkbox #axis.LR, "", [axisLRon],[axisLRoff],sweepParamLeft+165, sweepParamTop +80, 20, 15 staticText #axis, "L-R",sweepParamLeft+180, sweepParamTop +80, 20, 15 checkbox #axis.RL, "", [axisRLon],[axisRLoff],sweepParamLeft+210, sweepParamTop +80, 20, 15 staticText #axis, "R-L", sweepParamLeft+225, sweepParamTop +80, 20, 15 checkbox #axis.Alternate, "", [axisALTon],[axisALToff],sweepParamLeft+255, sweepParamTop +80, 20, 15 staticText #axis, "Alternate", sweepParamLeft+270, sweepParamTop +80, 50, 15 'OK and Cancel buttons button #axis.OK, "OK", [axisXFinished],UL, 150, 155,70,30 button #axis.Cancel, "Cancel", [axisXCancel],UL, 300, 155,70,30 'Open preference dialog open "Sweep Parameters" for dialog_modal as #axis axisPrefHandle$="#axis" #axis, "trapclose [axisXFinished]" 'Fill in preference choices with current values if alternateSweep then 'ver114-5a added alternateSweep #axis.Alternate, "set" else if gGetSweepDir()=1 then #axis.LR, "set" else #axis.RL, "set" end if linearF=gGetXIsLinear() 'Get freq linearity if linearF=1 then #axis.linear, "set" #axis.btnCentSpan, "set" 'Start in center/span mode gosub [enableCentSpan] else #axis.log, "set" #axis.btnStartStop, "set" 'Start in start/stop mode #axis.DivLab1, "!hide" : #axis.DivLab2, "!hide" 'Can't choose number of divisions for log sweep #axis.NDiv, "hide" gosub [enableStartStop] end if xForm$="####.######" print #axis.SweepCent, uFormatted$(centfreq, xForm$) print #axis.SweepSpan, uFormatted$(sweepwidth, xForm$) print #axis.SweepStart, uFormatted$(startfreq, xForm$) print #axis.SweepStop, uFormatted$(endfreq, xForm$) print #axis.SweepSteps, globalSteps print #axis.SweepWait, "";wate 'Wait time ver114-4d call gGetNumDivisions nHorDiv, nVertDiv #axis.NDiv, "!";nHorDiv #axis.NDiv, "setfocus" 'So selection is visually active #axis.SweepCent, "!setfocus" filtIndex=val(Word$(path$, 2))-1 'Index is one less than filter number, moved ver113-7a #axis.FiltList, "select ";MSAFiltStrings$(filtIndex) 'SEW2 Select filter for path$ #axis.FiltList, "setfocus" #axis.OpMode, "selectindex ";doSpecialGraph+1 #axis.OpMode, "setfocus" #axis.VideoFilt, "select "; videoFilter$ 'ver114-5p #axis.VideoFilt, "setfocus" 'ver114-5p #axis.Appearance, "select ";gGetLastPresetColors$() 'ver114-4d #axis.Appearance, "setfocus" 'Makes sure selection is visually activated if refreshEachScan then #axis.Refresh, "set" else #axis.Refresh, "reset" if displaySweepTime then #axis.SweepTime, "set" else #axis.SweepTime, "reset" 'ver114-4f #axis.OK, "!setfocus" changeAppearance=0 call RememberState 'Remember various variables so we can see if they change if msaMode$="SA" or msaMode$="ScalarTrans" then 'ver114-5n if TGtop = 2 then 'ver114-4j print proper label; button only exists for SA mode with TGtop=2 if normrev = 1 then print #axis.normReverse, "Reverse" end if if gentrk = 1 then print #axis.sigenbutton, "Tracking Generator" 'ver114-4i if TGtop = 2 then print #axis.freqoffbox, "";sgout 'ver114-4h if TGtop = 1 then print #axis.freqoffbox, "";offset if spurcheck=1 then #axis.spurbox, "set" else #axis.spurbox, "reset" 'ver114-4j To get buttons set up properly, reverse state of gentrk and 'then call [SignalGeneratorbutton] to reverse it back and print proper info. Then wait. if gentrk=1 then gentrk=0 else gentrk=1 'ver114-5n moved goto [SignalGeneratorbutton] 'ver114-5n moved else 'modes with phase #axis.invdegbox, invdeg #axis.planeadjbox, planeadj end if wait 'Wait for user to make choices 'User gets here by double-click. If he double clicks again before we are open, we may end up 'with the double-click event. We need to provide this method so as not to crash. ver114-1n [LeftButDouble] wait [axisXDoNothing] 'embedded in DisplayAxisXPreference wait [axisLRon] #axis.RL, "reset" #axis.Alternate, "reset" wait [axisLRoff] #axis.LR, "set" wait [axisRLon] #axis.LR, "reset" #axis.Alternate, "reset" wait [axisRLoff] #axis.RL, "set" wait [axisALTon] #axis.RL, "reset" #axis.LR, "reset" wait [axisALToff] #axis.Alternate, "set" wait [axisXSelLinear] #axis.DivLab1, "!show" : #axis.DivLab2, "!show" #axis.NDiv, "show" #axis.NDiv, "select 10" 'Start with 10 divisions when switching from log to linear ver114-2c #axis.log, "reset" wait [axisXSelLog] #axis.DivLab1, "!hide" : #axis.DivLab2, "!hide" 'Can't choose number of divisions for log sweep ver114-5p #axis.NDiv, "hide" #axis.linear, "reset" #axis.btnStartStop, "value? ssVal$" if ssVal$="reset" then #axis.btnStartStop, "set" : goto [setStartStop] 'Log should be in start/stop mode wait [setCentSpan] 'Select Center/Span mode; use Start/Stop to fill in Center/Span 'embedded in DisplayAxisXPreference #axis.btnStartStop, "reset" #axis.SweepStart, "!contents? currStart$" #axis.SweepStop, "!contents? currStop$" currStart=val(uCompact$(currStart$)) : currStop=val(uCompact$(currStop$)) print #axis.SweepCent, using("####.######",(currStart+currStop)/2) 'Enter center print #axis.SweepSpan, using("####.######",currStop-currStart) 'Enter span gosub [enableCentSpan] wait [enableCentSpan] #axis.SweepCent, "!enable" : #axis.SweepSpan, "!enable" #axis.SweepStart, "!disable" : #axis.SweepStop, "!disable" return [setStartStop] 'Select Start/Stop mode; use Center/Span to fill in Start/Stop 'embedded in DisplayAxisXPreference #axis.btnCentSpan, "reset" #axis.SweepCent, "!contents? currCent$" #axis.SweepSpan, "!contents? currSpan$" currCent=val(uCompact$(currCent$)) : currSpan=val(uCompact$(currSpan$)) print #axis.SweepStart, using("####.######",currCent-currSpan/2) 'Enter start print #axis.SweepStop, using("####.######",currCent+currSpan/2) 'Enter stop gosub [enableStartStop] wait [enableStartStop] #axis.SweepCent, "!disable" : #axis.SweepSpan, "!disable" #axis.SweepStart, "!enable" : #axis.SweepStop, "!enable" return [axisXCancel] 'User has cancelled; 'embedded in DisplayAxisXPreference close #axis axisPrefHandle$="" DisplayAxisXPreference=0 'signals no restart needed exit function [axisSetupNOP] wait [axisSetupSelectAppearance] 'Select graph appearance. Invoked by user click on combo box 'Note that unless the user changes the appearance, we do not activate the selection upon 'exit. This is because it will override previously selected trace colors. changeAppearance=1 wait [SignalGeneratorbutton]'selects either "Signal Generator" or "Tracking Generator" 'ver111-17 'this button does not exist in old TG topology. Only in new TG topology. if gentrk = 0 then 'ver114-4j gathered this if... block print #axis.sigenbutton, "Tracking Generator" if TGtop=2 then 'ver114-4j created this if... block print #axis.normReverse, "!show" 'ver114-4j if normrev=0 then print #axis.normReverse, "Normal" _ else print #axis.normReverse, "Reverse" 'ver114-4j end if print #axis.enterfreqtxt, "Enter Offset" 'ver111-26 print #axis.freqoffbox, "";offset gentrk = 1 else print #axis.sigenbutton, "Signal Generator" if TGtop=2 then print #axis.normReverse, "!hide" 'ver114-4j print #axis.enterfreqtxt, "Enter Freq" 'ver111-26 print #axis.freqoffbox, "";sgout 'ver114-4h gentrk = 0 end if wait [NormRevbutton]'when in Tracking Mode, selects either Normal or Reverse tracking 'ver111-17 'this button does not exist in old TG topology. Only in new TG topology. if normrev = 0 then print #axis.normReverse, "Reverse":normrev = 1:wait if normrev = 1 then print #axis.normReverse, "Normal":normrev = 0:wait [axisXFinished] 'Window is being closed; record choices; 'embedded in DisplayAxisXPreference #axis.Alternate, "value? s$" 'ver114-5a if s$="set" then alternateSweep=1 else alternateSweep=0 'ver114-5a 'ver114-5a added this if... block if alternateSweep then dir=1 'if alternating, start with forward else #axis.LR, "value? s$" if s$="set" then dir=1 else dir=-1 'set forward or reverse end if call gSetSweepDir dir 'save in graph module; caller must transfer it to sweepDir 'ver114-4n #axis.btnCentSpan, "value? CS$" if CS$="set" then 'Use Center/Span to determine centfreq, sweepwidth, startfreq and endfreq #axis.SweepCent, "!contents? currCent$" #axis.SweepSpan, "!contents? currSpan$" 'uCompact deletes spaces, which can mess up negative numbers temp1= val(uCompact$(currCent$)): temp2=val(uCompact$(currSpan$)) 'ver114-7m 'Enter new freq, but only if there is a material change. Otherwise, 'tiny differences between using center/span and start/stop will trigger a restart. ver114-7m if abs(temp1-centfreq)>1e-12 or abs(temp2-sweepwidth)>1e-12 then _ call SetCenterSpanFreq temp1, temp2 'new center and span else 'Use Start/Stop to determine centfreq, sweepwidth, startfreq and endfreq #axis.SweepStart, "!contents? currStart$" #axis.SweepStop, "!contents? currStop$" 'uCompact deletes spaces, which can mess up negative numbers temp1= val(uCompact$(currStart$)): temp2=val(uCompact$(currStop$)) 'ver114-7m 'Enter new freq, but only if there is a material change. ver114-7m if abs(temp1-startfreq)>1e-12 or abs(temp2-endfreq)>1e-12 then _ call SetStartStopFreq temp1, temp2 'new center and span end if #axis.SweepSteps, "!contents? steps$" 'Get user specified number of steps globalSteps=val(steps$) if globalSteps<>prevSteps then 'SEWgraph2 Note we set globalSteps here; steps is set from globalSteps 'after we exit back to [FreqAxisPreference] if globalSteps<1 then globalSteps=1 else if globalSteps>maxNumSteps then globalSteps=maxNumSteps 'ver114-7m 'Note we are called by [FreqAxisPreference], which will transfer globalSteps to steps. 'Resize arrays if necessary for all steps and a few to spare if globalSteps>=gMaxNumPoints() then call ResizeArrays globalSteps+10 'ver114-2a call gSetNumDynamicSteps globalSteps 'Tell graph module ver114-1f end if print #axis.SweepWait, "!contents? wate$"; 'Wait box wate = val(wate$) if wate<0 then wate=0 'Set sweep to log or linear. We do this after first setting the new range, since log sweep 'gets automatically changed to linear if the span is too small. #axis.linear, "value? lin$" if lin$="set" then linearF=1 else linearF=0 if linearF=0 then if startfreq<=0 then linearF=1 : notice "Changed to linear sweep because starting frequency <=0" 'ver114-5q else span=uSafeLog10(endfreq/startfreq) if span <0.7 then linearF=1 : notice "Changed to linear sweep because span is small." 'ver114-6e if span>9 then call SetStartStopFreq endfreq/1000000000, endfreq notice "Log span cannot exceed 9 decades; start freq changed." 'ver114-6e end if end if end if call gSetXIsLinear linearF 'Set freq linearity #axis.NDiv, "contents? nDiv$" 'Get user specified number of divisions nHorDiv=val(nDiv$) : if nHorDiv<2 then nHorDiv=2 else if nHorDiv>12 then nHorDiv=12 nHorDiv=2*int(nHorDiv/2) 'Make the number even 'Set new number of hor divisions, with old number of vert div call gSetNumDivisions nHorDiv,nVertDiv #axis.OpMode, "selectionindex? doSpecialGraph" if doSpecialGraph<1 then doSpecialGraph=0 else doSpecialGraph=doSpecialGraph-1 'e.g. selection 1 is doSpecialGraph=0 #axis.Refresh, "value? doRefresh$" if doRefresh$="set" then refreshEachScan=1 else refreshEachScan=0 #axis.SweepTime, "value? doSweepTime$" 'ver114-4f if doSweepTime$="set" then displaySweepTime=1 else displaySweepTime=0 if changeAppearance then #axis.Appearance, "contents? graphAppearance$" call gUsePresetColors graphAppearance$ 'Set color scheme #axis.OK, "!setfocus" 'Take focus off combo box to protect from scroll wheel end if #axis.FiltList, "selectionindex? filtIndex" 'Filter N is at index N in list if filtIndex=0 then 'filtIndex can be 0 if user typed something in the combo box filtIndex=1 #axis.FiltList, "select ";MSAFiltStrings$(0) 'Select default #axis.FiltList, "setfocus" 'SEW2 Needed to activate the highlight end if path$="Path "+str$(filtIndex) 'Name of filter path; Path 1, ver113-7c 'Filter will actually be selected by the caller #axis.VideoFilt, "contents? videoFilter$" 'get selected video filter ver114-5p 'ver114-2c added uCompact$() to several of these lines to handle neg number with space after the minus sign 'ver114-4i rearrange the following into an if...else block if msaMode$="SA" or msaMode$="ScalarTrans" then 'ver114-5n #axis.spurbox, "value? doSpur$" 'ver114-4f if doSpur$="set" then spurcheck=1 else spurcheck=0 if TGtop > 0 then print #axis.freqoffbox, "!contents? freqoff$"; 'Sig Gen Freq or TG offset box data ver111-18 if gentrk = 0 then sgout = val(uCompact$(freqoff$)) 'ver111-18 if TGtop > 0 and gentrk = 1 then offset = val(uCompact$(freqoff$)) 'ver111-18 else 'modes with phase print #axis.invdegbox, "!contents? invdeg$"; invdeg = val(uCompact$(invdeg$)) 'ver114-4i deleted calc of centphase, which is never used print #axis.planeadjbox, "!contents? planeadj$" 'SEW plane extension-->planeadj planeadj=val(uCompact$(planeadj$)) end if close #axis axisPrefHandle$="" call DetectChanges 0 'Do necessary redrawing and set continueCode ver114-6e if continueCode=3 then 'ver114-6e DisplayAxisXPreference=1 else continueCode=0 DisplayAxisXPreference=0 end if end function 'end of DisplayAxisXPreference 'ver114-6h added DisplayS21Jig sub DisplayS21Jig 'Display dialog with S21 Jig info 'We display info about the actual jig and about the desired transform WindowWidth = 680 : WindowHeight = 325 UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = DisplayHeight-WindowHeight-150 BackgroundColor$="darkblue" ForegroundColor$="white" TextboxColor$="blue" ComboboxColor$="blue" statictext #jig.head, "Transmission Measurement Setup", 160, 5, 300, 20 'modver114-7j s$="Measurement of transmission magnitude and phase (S21) may be done by directly cabling the TG output" s$=s$; " to the MSA input, or attenuators may be inserted on each side of the DUT to improve the impedance" s$=s$; " seen by the DUT. Such attenuators may also present the TG/MSA with 50 ohms and the DUT with another impedance." s$=s$; " It is necessary here to specify the impedance seen by the DUT in the test setup." statictext #jig.Inst1, s$, 15, 25, 650, 60 s$="In the special case of a two-terminal DUT, the DUT acts as an impedance whose value can be calculated from the measured" s$=s$; " S21, allowing S21 to be graphed as impedance. To do so, you must specify whether the DUT is attached in series or" s$=s$; " shunted to ground. You may also specify that in the graphing of S21 the data should be transformed" s$=s$; " to a different source/load resistance. This transformation of the S21 reference impedance is only" s$=s$; " possible for two-terminal devices." 'ver114-7g changed final 3 lines statictext #jig.Inst2, s$, 15, 95, 650, 80 'Checkboxes and Resistance text box boxTop=205 statictext #jig, "Actual Test Setup", 80,boxTop-25, 100, 15 statictext #jig, "Source and Load Resistance Presented to DUT", 23,boxTop-5, 250, 15 textbox #jig.R0A, 90, boxTop+10, 30,20 statictext #jig, "Connection of Two-Terminal DUTs", 25,boxTop+35, 190, 15 'ver114-7q separated the captions from the checkboxes so the text color comes out right checkbox #jig.SeriesA, "", [jigSeriesA],[jigShuntA], 50, boxTop+55, 20, 15 statictext #jig, "Series", 70, boxTop+55, 40, 15 checkbox #jig.ShuntA, "", [jigShuntA],[jigSeriesA], 120, boxTop+55, 20, 15 statictext #jig, "Shunt", 140, boxTop+55, 55, 15 checkbox #jig.Transform, "", [jigTransformOn],[jigTransformOff], 300, boxTop-25, 20, 15 statictext #jig, "Assume DUT is Two-Terminal Device When Graphing S21", 320, boxTop-25, 290, 15 statictext #jig.B1, "Transform S21 to This Reference Resistance", 345,boxTop-7, 250, 15 textbox #jig.R0B, 390, boxTop+10, 30,20 'OK and cancel buttons button #jig.OK, "OK", [jigFinished],UL, 350, boxTop+55,60,25 button #jig.Cancel, "Cancel", [jigCancel],UL, 430, boxTop+55,60,25 'Open preference dialog open "Transmission Measurement Setup" for dialog_modal as #jig 'ver114-7g #jig, "trapclose [jigFinished]" #jig.head, "!font Arial bold size 10" #jig.Inst1, "!font Times_New_Roman size 10" #jig.Inst2, "!font Times_New_Roman size 10" if S21JigAttach$="Series" then #jig.SeriesA, "set" : #jig.ShuntA, "reset" else #jig.ShuntA, "set" : #jig.SeriesA, "reset" end if #jig.R0A, S21JigR0 #jig.R0B, S21GraphR0 if S21DoTransform=1 then goto [jigTransformOn] else goto [jigTransformOff] [jigCancel] close #jig exit sub [jigSeriesA] #jig.SeriesA, "set" : #jig.ShuntA, "reset" wait [jigShuntA] #jig.ShuntA, "set" : #jig.SeriesA, "reset" wait [jigSeriesB] #jig.SeriesB, "set" : #jig.ShuntB, "reset" wait [jigShuntB] #jig.ShuntB, "set" : #jig.SeriesB, "reset" wait [jigTransformOn] #jig.Transform, "set" #jig.B1, "!show" #jig.R0B, "!show" wait [jigTransformOff] #jig.Transform, "reset" #jig.B1, "!hide" #jig.R0B, "!hide" wait [jigFinished] #jig.SeriesA, "value? attachVal$" if attachVal$="set" then S21JigAttach$="Series" else S21JigAttach$="Shunt" #jig.Transform, "value? transformVal$" if transformVal$="set" then S21DoTransform=1 else S21DoTransform=0 #jig.R0A, "!contents? R0$" 'ver114-7d modified the following few lines to use uValWithMult S21JigR0=uValWithMult(R0$) : if S21JigR0<=0 then S21JigR0=50 : notice "Invalid Test Source/Load. 50 ohms used." if S21DoTransform then 'ver114-7j #jig.R0B, "!contents? R0$" S21GraphR0=uValWithMult(R0$) : if S21GraphR0<=0 then S21GraphR0=50 : notice "Invalid Reference Resistance. 50 ohms used." else S21GraphR0=S21JigR0 end if close #jig call UpdateGraphDataFormat call RecalcYValues call RedrawGraph 1 'Redraw with transform applied. 'We will continue if we were sweeping or wait if we were waiting. end sub 'SEWgraph added SetCenterSpanFreq sub SetCenterSpanFreq cent, span 'Use Center/Span to determine centfreq, sweepwidth, startfreq, endfreq 'A centralized routine is used so all these related variables can be kept in sync. centfreq=cent sweepwidth=span if sweepwidth<0 then sweepwidth=0-sweepwidth startfreq=val(using("####.######",centfreq-sweepwidth/2)) 'ver114-5n endfreq=val(using("####.######",centfreq+sweepwidth/2)) 'ver114-5n 'ver114-7n deleted calc of stepfreq call gSetXAxisRange startfreq, endfreq 'ver114-6d end sub 'SEWgraph added SetStartStopFreq sub SetStartStopFreq startF, stopF 'Use Start/Stop to determine centfreq, sweepwidth, startfreq, endfreq and stepfreq 'A centralized routine is used so all these related variables can be kept in sync. startfreq=startF endfreq=stopF if startfreq>endfreq then dum=startfreq : startfreq=endfreq : endfreq=dum 'Swap to get in right order centfreq=val(using("####.######",(startfreq+endfreq)/2)) 'ver114-5n sweepwidth=endfreq-startfreq 'ver114-7n deleted calc of stepfreq call gSetXAxisRange startfreq, endfreq 'ver114-6d end sub 'SEWgraph added DisplayTitleWindow sub DisplayTitleWindow 'Display dialog to change title WindowWidth = 280 : WindowHeight = 220 UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = DisplayHeight-WindowHeight-70 BackgroundColor$="darkblue" TextboxColor$="blue" ComboboxColor$="blue" statictext #title.Instruct, "Enter up to 3 lines of title information.", 40,20,200, 15 statictext #title.Instruct, "(Line 3 gets overridden with date/time at Restart.)", 20,35,260, 15 textbox #title.t1, 10,50,250, 20 textbox #title.t2, 10,75,250, 20 textbox #title.t3, 10,100,250, 20 button #title.OK, "OK", [titleFinished],UL, 50, 150,50,25 button #title.Cancel, "Cancel", [titleCancel],UL, 160, 150,50,25 open "Title" for dialog_modal as #title 'Open title dialog #title, "trapclose [titleFinished]" 'Display existing title info and wait for user to change it call gGetTitleLine 1, t1$ : call gGetTitleLine 2, t2$ : call gGetTitleLine 3, t3$ print #title.t1, t1$ print #title.t2, t2$ print #title.t3, t3$ wait [titleCancel] 'embedded in DisplayTitleWindow close #title exit sub [titleFinished] 'embedded in DisplayTitleWindow #title.t1, "!contents? t1$" #title.t2, "!contents? t2$" #title.t3, "!contents? t3$" call gSetTitleLine 1, t1$ : call gSetTitleLine 2, t2$ : call gSetTitleLine 3, t3$ 'Refresh the graph,but in stick mode this will eliminate 'the stuck traces, so just reprint the title ver114-7d revised this procedure refreshGridDirty=1 'So next refresh will reprint the title if isStickMode=0 then call RefreshGraph 0 'Refresh in case traces got covered else call gPrintTitle 1 '1 signals to clear old info first end if close #title end sub 'SEWgraph added MarkOptions; ver114-4a renamed sub mMenuMarkerOptions 'Button handler to set marker options WindowHeight=275 : WindowWidth=200 BackgroundColor$="darkblue" ForegroundColor$="white" UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = DisplayHeight-WindowHeight-50 'ver114-7q separated the captions from the checkboxes and radio buttons so the text color comes out right checkbox #mark.Show, "", [markNil], [markNil],10,10,20,20 statictext #mark, "Show Markers On Graph",30,13,140,20 groupbox #mark.LR, "L,R Markers",5,40,160,140 radiobutton #mark.Indep, "", [markNil], [markNil],10,70,20,20 statictext #mark, "L,R Independent", 30,73,140,20 radiobutton #mark.Bounded, "", [markNil], [markNil],10,95,20,20 statictext #mark, "P+, P- bounded by L,R", 30,98,140,20 radiobutton #mark.Down3, "", [markNil], [markNil],10,120,20,20 statictext #mark, "L,R -3db re P+", 30,123,140,20 radiobutton #mark.Up3, "", [markNil], [markNil],10,145,20,20 statictext #mark, "L,R 3db re P-", 30,148,140,20 button #mark.OK "OK",[markFinished], UL, 20, 200, 50, 25 button #mark.Cancel "Cancel",[markBtnCancel], UL, 100, 200, 50, 25 open "Marker Options" for Dialog_modal as #mark #mark, "trapclose [markFinished]" #mark.Indep, "set" 'may change in next few lines if doGraphMarkers then #mark.Show, "set" else #mark.Show, "reset" if doPeaksBounded then #mark.Bounded, "set" if doLRRelativeTo$="P+" then #mark.Down3, "set" if doLRRelativeTo$="P-" then #mark.Up3, "set" wait [markNil] wait [markBtnCancel] close #mark exit sub [markFinished] #mark.Show, "value? box$" if box$="set" then doGraphMarkers=1 else doGraphMarkers=0 #mark.Bounded, "value? box$" if box$="set" then doPeaksBounded=1 else doPeaksBounded=0 doLRRelativeTo$="" : doLRRelativeAmount=0 #mark.Down3, "value? box$" if box$="set" then doLRRelativeTo$="P+" : doLRRelativeAmount=-3 #mark.Up3, "value? box$" if box$="set" then doLRRelativeTo$="P-" : doLRRelativeAmount=3 'Auto locating of markers prevents other automatic uses of the markers if doLRRelativeTo$<>"" then doFilterAnalysis=0 close #mark if haltsweep=0 then call RefreshGraph 0 'if not sweeping redraw graph ver114-7d end sub 'ver114-4a removed routines relating to hiding/showing marker edit buttons 'SEWgraph added mUpdateMarkerEditButtons sub mUpdateMarkerEditButtons 'Enable/disable buttons based on selected marker 'Disable if marker does not exist or for peak markers, which cannot be manually located if selMarkerID$="" then 'ver114-4a added this if... block noMarker=1 else pointNum=gMarkerPointNum(mMarkerNum(selMarkerID$)) if pointNum<0 then noMarker=1 else noMarker=0 end if if selMarkerID$="P+" or selMarkerID$="P-" then notManual=1 else notManual=0 'ver114-4a if noMarker or notManual then 'ver114-4a #handle.markInc, "!disable" #handle.markDec, "!disable" #handle.markFreq, "!disable" #handle.markEnterFreq, "!disable" if noMarker then #handle.markDelete, "!disable" else #handle.markDelete, "!enable" else #handle.markInc, "!enable" #handle.markDec, "!enable" #handle.markFreq, "!enable" #handle.markEnterFreq, "!enable" #handle.markDelete, "!enable" end if end sub 'SEWgraph added mUserMarkSelect sub mUserMarkSelect btn$ 'Marker was selected in combobox. #handle.selMark, "selection? selMarkerID$" if selMarkerID$="None" then selMarkerID$="" 'Show marker editing info; ver114-4a revised call mUpdateMarkerEditButtons 'Enable/disable proper buttons call mDisplaySelectedMarker 'Display numberic info end sub 'ver114-5L added mMarkSelect sub mMarkSelect markID$ 'Program selection specified marker in combo box if markID$="" then s$="None" else s$=markID$ #handle.selMark, "select ";s$ #handle.selMark, "setfocus" #handle.Restart, "!setfocus" call mUserMarkSelect "" 'Take same action as though user selected the marker end sub 'SEWgraph added mBtnMarkClear sub mBtnMarkClear btn$ 'Button to clear all markers was clicked call mClearMarkers 'call HideMarkerEdit 'delver114-4a if doGraphMarkers=1 then call RefreshGraph 0 'ver114-7q end sub 'SEWgraph added mBtnMarkEdit sub mBtnMarkEdit btn$ 'Button to edit selected marker was clicked 'call ShowMarkerEdit 'delver114-4a call mUpdateMarkerEditButtons end sub 'SEWgraph added mBtnMarkDelete sub mBtnMarkDelete btn$ 'Button to delete selected marker was clicked call mDeleteMarker selMarkerID$ 'call HideMarkerEdit 'delver114-4a if doGraphMarkers=1 then call RefreshGraph 0 else call mDrawMarkerInfo 'ver114-7d end sub [btnIncPoint] 'added by ver114-7k if haltsweep=1 then gosub [FinishSweeping] call IncDecPoint "markInc" if varwindow = 1 then gosub [preupdatevar] 'will update variables window. wait [btnDecPoint] 'added by ver114-7k if haltsweep=1 then gosub [FinishSweeping] call IncDecPoint "markDec" if varwindow = 1 then gosub [preupdatevar] 'will update variables window. wait 'SEWgraph added IncDecPoint sub IncDecPoint btn$ 'Button to increment or decrement frequency was clicked 'Change frequency, and redraw 'to update pointer on screen. But if markers are hidden, just refresh the marker info. if selMarkerID$="" then exit sub 'No marker selected, so can't modify ver114-4a pos=instr(btn$, ".") btn$=Mid$(btn$,pos+1) 'Drop the handle and the period #handle.markFreq, "!contents? markFreq$" markFreq=val(markFreq$) markPoint=gPointNumOfX(markFreq) if btn$="markDec" then 'Decrease markPoint to an integral value. If its fractional part is less than 0.001, it will become 'the integer next lower than its integral part; otherwise it becomes its integral part. markPoint=int(markPoint-0.001) 'ver114-7k else 'Increment 'Increase markPoint to an integral value. If its fractional part is more than 0.999, it will become 'the integer two larger than its integral part; otherwise it becomes one greater than its integral part. markPoint=int(markPoint+1.001) 'ver114-7k end if if markPoint<1 then markPoint=1 else if markPoint>gPointCount() then markPoint=gPointCount() markFreq=gGetPointXVal(markPoint) print #handle.markFreq, using("####.######", markFreq) 'Enter new frequency into box call gUpdateMarkerPointNum mMarkerNum(selMarkerID$), markPoint if doGraphMarkers=1 then call RefreshGraph 0 else call mDrawMarkerInfo 'ver114-7d leftstep=markPoint-1 'Make leftstep a step number, not point number, for [preupdatevar] ver114-7k end sub 'ver114-7b deleted IncDecRef 'SEWgraph added mEnterMarker; ver114-4a revised to delete the "Done" button sub mEnterMarker btn$ 'Marker Enter button was clicked 'Enter new marker info based on the frequency. If the point num was changed, 'the frequency was updated, but the user may have changed the frequency so 'the point number may be outdated. #handle.markFreq, "!contents? markFreq$" markFreq=val(markFreq$) markPoint=gPointNumOfX(markFreq) 'Find point number matching this frequency. if markPoint <1 then markPoint=1 maxPoint=gPointCount() 'ver114-4a if markPoint>maxPoint then markPoint=maxPoint markFreq=gGetPointXVal(markPoint) print #handle.markFreq, using("####.######", markFreq) 'Enter frequency into box, in case we changed it call gUpdateMarkerPointNum mMarkerNum(selMarkerID$), markPoint if doGraphMarkers=1 then call RefreshGraph 0 else call mDrawMarkerInfo 'ver114-7d end sub 'SEWgraph added mDisplaySelectedMarker sub mDisplaySelectedMarker 'Update label, point number and freq for selected marker 'ver114-5L deleted actual selection of marker in combobox, which is usually not necessary if selMarkerID$="" then #handle.markFreq, "" : exit sub 'No marker to update ver114-4a markPoint=gMarkerPointNum(mMarkerNum(selMarkerID$)) if markPoint<0 then #handle.markFreq, "" : exit sub 'No marker to update ver114-4a markFreq=gGetPointXVal(markPoint) #handle.markFreq, using("####.######",markFreq) end sub 'ver114-5p added SelectVideoFilter sub SelectVideoFilter filt$ 'Select Narrow, Mid or Wide video filter 'For now we just record the user's selection. When we have switching 'ability we will actually switch the filter videoFilter$=filt$ end sub 'ver114-4c deleted [UserSelectFilter] and modified [SelectFilter] [SelectFilter] 'Select filter indicated by path$, which is in form "Path N" filtIndex=val(Word$(path$,2)) 'ver114-4c path number is second word if filtIndex<=0 or filtIndex>MSANumFilters then filtIndex=1 : notice "Invalid filter selection." call calInstallFile filtIndex 'Loads file and sets finalfreq and finalbw if filtIndex<=2 then A1=0 else A1=1 'Set filter address if filtIndex=1 or filtIndex=3 then A0=0 else A0=1 gosub [CommandFilter] 'ver111-29 'Physically select filter return '--SEW2--End of filter selection change [CommandFilter] 'ver111-29 if cb = 0 then filtbank = A1*8 + A0*4 : gosub [CommandFilterOrigCB] if cb = 2 then filtbank = A1*64 + A0*32 : gosub [CommandFilterSlimCB] return 'to [SelectFilter]'ver113-7a [CommandFilterOrigCB]'command 1 of 4 and latch it ver111-29 out port, filtbank 'presents A0 and A1 to control buffer out control, INIT 'presents A0 and A1 to Filter Bank out port, filtbank + 1 'latches A0 and A1 into Filter Bank using latch signal out port, filtbank 'leaves A0 and A1 on Filter Bank, removing latch signal out control, contclear 'removes A0 and A1 from Filter Bank out port, 0 'removes A0 and A1 from control buffer return 'to [CommandFilter] [CommandFilterSlimCB] 'ver111-29 out port, filtbank 'presents A0 and A1 to control buffer out control, SELT 'presents A0 and A1 to Filter Bank out port, filtbank + 128 'latches A0 and A1 into Filter Bank using latch signal out port, filtbank 'leaves A0 and A1 on Filter Bank, removing latch signal out control, contclear 'removes A0 and A1 from Filter Bank out port, 0 'removes A0 and A1 from control buffer return 'to [CommandFilter] 'SEWgraph added HaltAtEnd [HaltAtEnd] 'Halt At End button pushed. 'This is actually the OneStep button during a scan, so we get here from [OneStep] 'The only way to get here is for the user to click Halt At End during a sweep, which will be 'detected on the "scan" command in the sweep loop. We just set a flag and return to the point 'after the scan command. haltAtEnd=1 'Set flag to cause halt at end of this sweep. goto [PostScan] 'SEWgraph changed [OneStep] 'SEWgraph The OneStep button shows HaltAtEnd during a scan if haltsweep = 1 then goto [HaltAtEnd] 'SEWgraph 'If the graph has been redrawn without erasure, we need to erase that part, because 'the normal one-point draw only erases a single segment, several points ahead. onestep = 1 'ver111-26 goto [FocusKeyBox] [Continue] 'SEWgraph The Continue button shows Halt during a scan if haltsweep = 1 then goto [Halted] 'ver111-26 onestep = 0 'ver111-26 [FocusKeyBox] call DisplayButtonsForRunning 'SEW8 consolidated various button commands call gRestoreErasure 'ver114-6d message$="" : call PrintMessage 'ver114-4f scanResumed=1 goto [StartSweep] 'ver114-6f deleted [PrepareToRestart] [Restart] if haltsweep = 1 then goto [Halted] 'ver111-26 'SEWgraph changed from closing window to clearing graphics with cls, which also releases 'all flushed segments from memory. The cls will occur when the background grid is printed 'close #handle 'close out graph window when restarting 'When a window is closed, all graphics drawing operations are deleted from memory gosub [UpdateGraphParams] 'ver114-6f onestep = 0 'ver111-26 call DisplayButtonsForRunning 'SEW8 replaced print #main.restart, "Running" 'SEWgraph1 Start new sweep series. 'Ver114-2b Reinitialize hardware every time goto [InitializeHardware] 'Ver114-2b 'ver114-4f deleted [ClearBoxes] because boxes are gone 'ver114-4f deleted [Spurtest]--it is in setup window [Showvar] 'modified by ver114-4f to avoid halting sweep and to operate from menu if varwindow=1 then close #varwin:varwindow = 0 'close existing window 'ver114-4f WindowWidth = 200 WindowHeight = 450 'ver111-26 UpperLeftX = DisplayWidth-WindowWidth-10 'ver114-4f UpperLeftY = 10 'ver114-4f BackgroundColor$ = "darkblue" ForegroundColor$ = "white" statictext #varwin.variable1, "this step = ";thisstep, 5, 5, 180, 15 'ver111-35 statictext #varwin.variable2, "dds1output = ";DDS1array(thisstep,46);" MHz", 5, 20, 180, 15 statictext #varwin.variable3, "LO 1 = ";PLL1array(thisstep,43);" MHz", 5, 35, 180, 15 statictext #varwin.variable4, "pdf1 = ";PLL1array(thisstep,40);" MHz", 5, 50, 180, 15 statictext #varwin.variable5, "ncounter1 = ";PLL1array(thisstep,45), 5, 65, 180, 15 statictext #varwin.variable6, "Bcounter1 = ";PLL1array(thisstep,48), 5, 80, 180, 15 statictext #varwin.variable7, "Acounter1 = ";PLL1array(thisstep,47), 5, 95, 180, 15 statictext #varwin.variable8, "fcounter1 = ";PLL1array(thisstep,46), 5, 110, 180, 15 statictext #varwin.variable9, "rcounter1 = ";rcounter1, 5, 125, 180, 15 statictext #varwin.variable10, "LO2 = ";LO2;" MHz", 5, 140, 180, 15 statictext #varwin.variable11, "pdf2 = ";pdf2;" MHz", 5, 155, 180, 15 statictext #varwin.variable12, "ncounter2 = ";ncounter2, 5, 170, 180, 15 statictext #varwin.variable13, "Bcounter2 = ";Bcounter2, 5, 185, 180, 15 statictext #varwin.variable14, "Acounter2 = ";Acounter2, 5, 200, 180, 15 statictext #varwin.variable15, "rcounter2 = ";rcounter2, 5, 215, 180, 15 statictext #varwin.variable16, "LO3 = ";PLL3array(thisstep,43);" MHz", 5, 230, 180, 15 statictext #varwin.variable17, "pdf3 = ";PLL3array(thisstep,40);" MHz", 5, 245, 180, 15 statictext #varwin.variable18, "ncounter3 = ";PLL3array(thisstep,45), 5, 260, 180, 15 statictext #varwin.variable19, "Bcounter3 = ";PLL3array(thisstep,48), 5, 275, 180, 15 statictext #varwin.variable20, "Acounter3 = ";PLL3array(thisstep,47), 5, 290, 180, 15 statictext #varwin.variable21, "fcounter3 = ";PLL3array(thisstep,46), 5, 305, 180, 15 statictext #varwin.variable22, "rcounter3 = ";rcounter3, 5, 320, 180, 15 statictext #varwin.variable23, "dds3output = ";DDS3array(thisstep,46), 5, 335, 180, 15 statictext #varwin.variable24, "Magdata = ";magarray(thisstep,3);" magpower= ";datatable(thisstep,2), 5, 350, 195, 15 'raw magdata bits, MSA input power(massaged) 'ver111-39b statictext #varwin.variable25, "Phadata = ";phaarray(thisstep,3);" PDM = ";phaarray(thisstep,4), 5, 365, 180, 15 'ver111-39d statictext #varwin.variable26, "Real Final I.F. = ";LO2 - (PLL1array(thisstep,45)*DDS1array(thisstep,46)/rcounter1) + datatable(thisstep,1), 5, 380, 180, 15 'ver112-2b 'real final IF = LO2-(LO1-thisfreq) statictext #varwin.variable27, "glitchtime = ";glitchtime, 5, 395, 180, 15 'ver114-7b open "Variables Window" for dialog as #varwin:varwindow = 1 print #varwin, "trapclose Closevarwin" 'goto [Closevarwin] if xit is clicked ver114-7n changed to subroutine if haltsweep=1 then goto [PostScan] wait [updatevar] print #varwin.variable1, "this step = ";thisstep 'ver111-35 print #varwin.variable2, "dds1output = ";DDS1array(thisstep,46);" MHz" print #varwin.variable3, "LO 1 = ";PLL1array(thisstep,43);" MHz" print #varwin.variable4, "pdf1 = ";PLL1array(thisstep,40);" MHz" print #varwin.variable5, "ncounter1 = ";PLL1array(thisstep,45) print #varwin.variable6, "Bcounter1 = ";PLL1array(thisstep,48) print #varwin.variable7, "Acounter1 = ";PLL1array(thisstep,47) print #varwin.variable8, "fcounter1 = ";PLL1array(thisstep,46) print #varwin.variable9, "rcounter1 = ";rcounter1 print #varwin.variable10, "LO2 = ";LO2;" MHz" print #varwin.variable11, "pdf2 = ";pdf2;" MHz" print #varwin.variable12, "ncounter2 = ";ncounter2 print #varwin.variable13, "Bcounter2 = ";Bcounter2 print #varwin.variable14, "Acounter2 = ";Acounter2 print #varwin.variable15, "rcounter2 = ";rcounter2 print #varwin.variable16, "LO3 = ";PLL3array(thisstep,43);" MHz" print #varwin.variable17, "pdf3 = ";PLL3array(thisstep,40);" MHz" print #varwin.variable18, "ncounter3 = ";PLL3array(thisstep,45) print #varwin.variable19, "Bcounter3 = ";PLL3array(thisstep,48) print #varwin.variable20, "Acounter3 = ";PLL3array(thisstep,47) print #varwin.variable21, "fcounter3 = ";PLL3array(thisstep,46) print #varwin.variable22, "rcounter3 = ";rcounter3 print #varwin.variable23, "dds3output = ";DDS3array(thisstep,46) print #varwin.variable24, "Magdata = ";magarray(thisstep,3);" magpower= ";datatable(thisstep,2)'raw magdata bits, MSA input power(massaged) 'ver111-39b print #varwin.variable25, "Phadata = ";phaarray(thisstep,3);" PDM = ";phaarray(thisstep,4) 'ver111-39d print #varwin.variable26, "Real Final I.F. = ";LO2 - (PLL1array(thisstep,45)*DDS1array(thisstep,46)/rcounter1) + datatable(thisstep,1) 'ver112-2b print #varwin.variable27, "glitchtime = ";glitchtime 'ver114-7b return sub Closevarwin hndl$ 'ver114-7n changed to subroutine close #varwin:varwindow = 0 'close out variables window end sub 'ver114-5h deleted [Calfwd] [CalculateAllStepsForLO1Synth] haltstep = thisstep 'remember where we were in the sweep when halted for thisstep = 0 to steps 'SEWgraph deleted the following calc of pixels, since we have already calculated them and don't need them in magarray() 'magarray(thisstep,0) = thisstep * x/steps 'establishes "thispointx" (on x-axis of graph) (0 to 720)ver111-25 'SEWgraph Frequencies have been pre-calculated in the graphing module via gGenerateXValues thisfreq=gGetPointXVal(thisstep+1) 'Point number is 1 greater than step number SEWgraph 'thisfreq = startfreq + (stepfreq * thisstep) 'calculates input freq. at this new step 'SEWgraph deleted LO1 = thisfreq + LO2 - finalfreq 'calculates the actual LO1 frequency:thisfreq,LO2,finalfreq are actuals datatable(thisstep,0) = thisstep 'put current step number into the array, row value= thisstep 'moved ver111-18 datatable(thisstep,1) = thisfreq 'put current frequency into the array, row value= thisstep 'moved ver111-18 '[CalculateThisStepPLL1] appxVCO=LO1 : reference=appxdds1 : rcounter=rcounter1 if PLL1mode = 0 then gosub [CreateIntegerNcounter]'needed:appxVCO,reference,rcounter ; creates:ncount,ncounter,fcounter(0) 'returns with ncount,ncounter,fcounter(0),pdf if PLL1mode = 1 then gosub [CreateFractionalNcounter]'needed:appxVCO,reference,rcounter ; creates:ncount,ncounter,fcounter,pdf 'returns with ncount,ncounter,fcounter,pdf dds1output = pdf * rcounter 'actual output of DDS1(input Ref to PLL1) if PLL1mode = 1 then gosub [AutoSpur]'needed:LO2,finalfreq,dds1output,rcounter1,finalbw,appxdds1,fcounter,ncounter ver111-8 '[AutoSpur] is a continuation of [CreateFractionalNcounter], used only in MSA when PLL 1 is Fractional 'returns with possibly new: ncounter,fcounter,pdf,dds1output if PLL1mode = 1 then gosub [ManSpur]'ver111-10 '[ManSpur] is a continuation of [CreateFractionalNcounter], used only in MSA when PLL 1 is Fractional 'if Spur Test Button On, will return with new ncounter,fcounter,pdf,dds1output gosub [CreatePLL1N]'needs:ncounter,fcounter,PLL1mode,PLL1 ; creates PLL NBuffer N0-Nx gosub [FillPLL1array]'need:N0-Nx,pdf,dds1output,LO1,ncount,ncounter,Fcounter,Acounter,Bcounter;creates samePLL1 '[endCalculateThisStepPLL1] '[CalculateThisStepDDS1]'need:dds1output,masterclock,appxdds1,dds1filbw ddsoutput = dds1output : ddsclock = masterclock if dds1output-appxdds1>dds1filbw/2 then 'ver114-4e beep:error$="DDS1output too high for filter" message$=error$ : call PrintMessage 'ver114-4e wait end if if appxdds1-dds1output>dds1filbw/2 then 'ver114-4e beep:error$="DDS1output too low for filter" message$=error$ : call PrintMessage :wait 'ver114-4e end if gosub [CreateBaseForDDSarray]'needed:ddsoutput,ddsclock ; creates: base,sw0thrusw39,w0thruw4 gosub [FillDDS1array]'need thisstep,sw0-sw39,w0-w4,base,ddsclock '[endCalculateThisStepDDS1] next thisstep thisstep = haltstep 'return to the step in the sweep, where we halted, if needed return '[endCalculateAllStepsForLO1Synth] [CalculateAllStepsForLO3Synth]'for hybrid, and orig (fixed freq) TG 'if TGtop = 0 then skip all this (return), actually we should not have even entered this subroutine. haltstep = thisstep 'remember where we were in the sweep when halted for thisstep = 0 to steps 'ver111-17 'SEWgraph Frequencies have been pre-calculated in the graphing module via gGenerateXValues thisfreq=gGetPointXVal(thisstep+1) 'Point number is 1 greater than step number SEWgraph 'thisfreq = startfreq + (stepfreq * thisstep) 'calculates input freq. at this new step 'SEWgraph deleted if TGtop = 1 then LO3 = LO2 - finalfreq - offset 'for orig, fixed freq TG ver111-15a 'or LO3 = LO1 - thisfreq - offset if TGtop = 2 and gentrk = 1 and normrev = 0 then LO3 = LO2 + thisfreq + offset 'for new TG, Trk Gen mode, normal ver111-18 if TGtop = 2 and gentrk = 1 and normrev = 1 then 'SEWgraph Frequencies have been pre-calculated in the graphing module via gGenerateXValues 'We can just retrieve them in reverse order. 'TO DO--Scotty; I am not 100% sure this does exactly what the deleted line did revfreq=gGetPointXVal(steps-thisstep+1) 'Point number is 1 greater than step number SEWgraph LO3 = LO2 + revfreq + offset end if 'SEWgraph deleted the following which was replaced by the if... block above 'if TGtop = 2 and gentrk = 1 and normrev = 1 then LO3 = LO2 + (centfreq - (stepfreq * (thisstep - (steps/2))) + offset) if TGtop = 2 and gentrk = 0 then LO3 = LO2 + sgout 'for new TG, Sig Gen mode ver111-18 '[CalculateThisStepPLL3] appxVCO=LO3 : reference=appxdds3 : rcounter=rcounter3 if appxdds3 = 0 then reference=masterclock 'for orig, fixed freq TG with no DDS3 steering. ver111-17 if PLL3mode = 0 then gosub [CreateIntegerNcounter]'needed:appxVCO,reference,rcounter ; creates:ncount,ncounter,fcounter(0) 'returns with ncount,ncounter,fcounter(0),pdf if PLL3mode = 1 then gosub [CreateFractionalNcounter]'needed:appxVCO,reference,rcounter ; creates:ncount,ncounter,fcounter,pdf 'returns with ncount,ncounter,fcounter,pdf dds3output = pdf * rcounter 'actual output of DDS3(input Ref to PLL3) gosub [CreatePLL3N]'needs:ncounter,fcounter,PLL3mode,PLL3 ; creates PLL NBuffer N0-Nx gosub [FillPLL3array]'need thisstep,N0thruN23,pdf3(40),dds3output(41),samePLL3(42)see dim PLL3array for slot info 'ver111-14 '[endCalculateThisStepPLL3] '[CalculateThisStepDDS3]'need:dds3output,masterclock,appxdds3,dds3filbw if appxdds3 = 0 then goto [endCalculateThisStepDDS3] 'there is no DDS, skip this section ver111-17 ddsoutput = dds3output : ddsclock = masterclock if dds3output-appxdds3>dds3filbw/2 then 'ver114-4e beep:error$="DDS3 output too high for filter" message$=error$ : call PrintMessage :wait end if if appxdds3-dds3output>dds3filbw/2 then 'ver114-4e beep:error$="DDS3output too low for filter" message$=error$ : call PrintMessage :wait end if gosub [CreateBaseForDDSarray]'needed:ddsoutput,ddsclock ; creates: base,sw0thrusw39,w0thruw4 gosub [FillDDS3array]'need thisstep,sw0-sw39,w0-w4,base,ddsclock ver111-15 [endCalculateThisStepDDS3] 'del.ver112-2b phaarray(thisstep,0) = 0 'this will set all pdmstates, to 0 'ver112-1a phaarray(thisstep,0) = 0 'this will set all pdmstates, to 0 'undeleted, ver113-7e next thisstep thisstep = haltstep 'return to the step in the sweep, where we halted, if needed lastpdmstate = 2 'this will guarantee that the PDM will get commanded 'ver112-1a return '[endCalculateAllStepsForLO3Synth] [FillPLL1array]'need thisstep,N0thruN23,pdf1(40),dds1output(41),samePLL1(42)see dim PLL1array for slot info 'ver111-1 'reversed sequence for N23 to be first. ver111-31a PLL1array(thisstep,23) = N0:PLL1array(thisstep,22) = N1 PLL1array(thisstep,21) = N2:PLL1array(thisstep,20) = N3 PLL1array(thisstep,19) = N4:PLL1array(thisstep,18) = N5 PLL1array(thisstep,17) = N6:PLL1array(thisstep,16) = N7 PLL1array(thisstep,15) = N8:PLL1array(thisstep,14) = N9 PLL1array(thisstep,13) = N10:PLL1array(thisstep,12) = N11 PLL1array(thisstep,11) = N12:PLL1array(thisstep,10) = N13 PLL1array(thisstep,9) = N14:PLL1array(thisstep,8) = N15 PLL1array(thisstep,7) = N16:PLL1array(thisstep,6) = N17 PLL1array(thisstep,5) = N18:PLL1array(thisstep,4) = N19 PLL1array(thisstep,3) = N20:PLL1array(thisstep,2) = N21 PLL1array(thisstep,1) = N22:PLL1array(thisstep,0) = N23 PLL1array(thisstep,40) = pdf PLL1array(thisstep,43) = LO1 PLL1array(thisstep,45) = ncounter PLL1array(thisstep,46) = fcounter PLL1array(thisstep,47) = Acounter PLL1array(thisstep,48) = Bcounter return [FillPLL3array]'need thisstep,N0thruN23,pdf3(40),dds3output(41),samePLL3(42)see dim PLL3array for slot info 'ver111-14 'reversed sequence for N23 to be first. ver111-31a PLL3array(thisstep,23) = N0:PLL3array(thisstep,22) = N1 PLL3array(thisstep,21) = N2:PLL3array(thisstep,20) = N3 PLL3array(thisstep,19) = N4:PLL3array(thisstep,18) = N5 PLL3array(thisstep,17) = N6:PLL3array(thisstep,16) = N7 PLL3array(thisstep,15) = N8:PLL3array(thisstep,14) = N9 PLL3array(thisstep,13) = N10:PLL3array(thisstep,12) = N11 PLL3array(thisstep,11) = N12:PLL3array(thisstep,10) = N13 PLL3array(thisstep,9) = N14:PLL3array(thisstep,8) = N15 PLL3array(thisstep,7) = N16:PLL3array(thisstep,6) = N17 PLL3array(thisstep,5) = N18:PLL3array(thisstep,4) = N19 PLL3array(thisstep,3) = N20:PLL3array(thisstep,2) = N21 PLL3array(thisstep,1) = N22:PLL3array(thisstep,0) = N23 PLL3array(thisstep,40) = pdf PLL3array(thisstep,43) = LO3 PLL3array(thisstep,45) = ncounter PLL3array(thisstep,46) = fcounter PLL3array(thisstep,47) = Acounter PLL3array(thisstep,48) = Bcounter return [FillDDS1array]'need thisstep,sw0-sw39,w0-w4,base,ddsclock 'ver111-12 DDS1array(thisstep,0) = sw0:DDS1array(thisstep,1) = sw1 DDS1array(thisstep,2) = sw2:DDS1array(thisstep,3) = sw3 DDS1array(thisstep,4) = sw4:DDS1array(thisstep,5) = sw5 DDS1array(thisstep,6) = sw6:DDS1array(thisstep,7) = sw7 DDS1array(thisstep,8) = sw8:DDS1array(thisstep,9) = sw9 DDS1array(thisstep,10) = sw10:DDS1array(thisstep,11) = sw11 DDS1array(thisstep,12) = sw12:DDS1array(thisstep,13) = sw13 DDS1array(thisstep,14) = sw14:DDS1array(thisstep,15) = sw15 DDS1array(thisstep,16) = sw16:DDS1array(thisstep,17) = sw17 DDS1array(thisstep,18) = sw18:DDS1array(thisstep,19) = sw19 DDS1array(thisstep,20) = sw20:DDS1array(thisstep,21) = sw21 DDS1array(thisstep,22) = sw22:DDS1array(thisstep,23) = sw23 DDS1array(thisstep,24) = sw24:DDS1array(thisstep,25) = sw25 DDS1array(thisstep,26) = sw26:DDS1array(thisstep,27) = sw27 DDS1array(thisstep,28) = sw28:DDS1array(thisstep,29) = sw29 DDS1array(thisstep,30) = sw30:DDS1array(thisstep,31) = sw31 DDS1array(thisstep,32) = sw32:DDS1array(thisstep,33) = sw33 DDS1array(thisstep,34) = sw34:DDS1array(thisstep,35) = sw35 DDS1array(thisstep,36) = sw36:DDS1array(thisstep,37) = sw37 DDS1array(thisstep,38) = sw38:DDS1array(thisstep,39) = sw39 DDS1array(thisstep,40) = w0 DDS1array(thisstep,41) = w1 DDS1array(thisstep,42) = w2 DDS1array(thisstep,43) = w3 DDS1array(thisstep,44) = w4 DDS1array(thisstep,45) = base 'base is decimal command DDS1array(thisstep,46) = base*ddsclock/2^32 'actual dds 1 output freq return [FillDDS3array]'need thisstep,sw0-sw39,w0-w4,base,ddsclock 'ver111-15 DDS3array(thisstep,0) = sw0:DDS3array(thisstep,1) = sw1 DDS3array(thisstep,2) = sw2:DDS3array(thisstep,3) = sw3 DDS3array(thisstep,4) = sw4:DDS3array(thisstep,5) = sw5 DDS3array(thisstep,6) = sw6:DDS3array(thisstep,7) = sw7 DDS3array(thisstep,8) = sw8:DDS3array(thisstep,9) = sw9 DDS3array(thisstep,10) = sw10:DDS3array(thisstep,11) = sw11 DDS3array(thisstep,12) = sw12:DDS3array(thisstep,13) = sw13 DDS3array(thisstep,14) = sw14:DDS3array(thisstep,15) = sw15 DDS3array(thisstep,16) = sw16:DDS3array(thisstep,17) = sw17 DDS3array(thisstep,18) = sw18:DDS3array(thisstep,19) = sw19 DDS3array(thisstep,20) = sw20:DDS3array(thisstep,21) = sw21 DDS3array(thisstep,22) = sw22:DDS3array(thisstep,23) = sw23 DDS3array(thisstep,24) = sw24:DDS3array(thisstep,25) = sw25 DDS3array(thisstep,26) = sw26:DDS3array(thisstep,27) = sw27 DDS3array(thisstep,28) = sw28:DDS3array(thisstep,29) = sw29 DDS3array(thisstep,30) = sw30:DDS3array(thisstep,31) = sw31 DDS3array(thisstep,32) = sw32 'x4 multiplier DDS3array(thisstep,33) = sw33 'control bit DDS3array(thisstep,34) = sw34 'power down bit DDS3array(thisstep,35) = sw35 '35-39 are Phase DDS3array(thisstep,36) = sw36:DDS3array(thisstep,37) = sw37 DDS3array(thisstep,38) = sw38:DDS3array(thisstep,39) = sw39 DDS3array(thisstep,40) = w0 'word 0, 8 bits, mult, control and phase DDS3array(thisstep,41) = w1 'word 1, 8 bits DDS3array(thisstep,42) = w2 'word 2, 8 bits DDS3array(thisstep,43) = w3 'word 3, 8 bits DDS3array(thisstep,44) = w4 'word 4, 8 bits DDS3array(thisstep,45) = base 'base is decimal command DDS3array(thisstep,46) = base*ddsclock/2^32 'actual dds 3 output freq return [CreateCmdAllArray] 'for SLIM CB only 'ver-31b 'a DDS serial command, will begin with LSB (W0), thru MSB (W31), ending with Phase bit 4 (W39) 'a PLL serial command, will begin with MSB (N23), thru LSB (N0, the address bit) rememberthisstep = thisstep 'remember where we were when entering this subroutine for thisstep = 0 to steps for clmn = 0 to 15 cmdallarray(thisstep,clmn) = DDS1array(thisstep,clmn)*4 + DDS3array(thisstep,clmn)*16 next clmn for clmn = 16 to 39 cmdallarray(thisstep,clmn) = PLL1array(thisstep,clmn-16)*2 + DDS1array(thisstep,clmn)*4 + PLL3array(thisstep,clmn-16)*8 + DDS3array(thisstep,clmn)*16 next clmn next thisstep thisstep = rememberthisstep return [CommandPLL]' comes here during PLL R Initializations and PLL 2 N command ver111-28 if cb = 0 then gosub [CommandPLLorig] 'ver111-28 if cb = 2 then gosub [CommandPLLslim] 'ver111-28 return 'to [InitializePLL2]or[CommandXPllRbuffer] [CommandPLLorig]'needs:N23-N0,control,Jcontrol,port,contclear,LEPLL ; commands N23-N0,old ControlBoard ver111-28 'used during initialization of PLL1, PLL2, and PLL3. PDM will get set to "0". 'when PLL1 or PLL2 then Jcontrol=SELT. when PLL3 the Jcontrol=INIT out control, Jcontrol 'enable Control Board J connector out port, N23:out port, N23 + 2 out port, N22:out port, N22 + 2:out port, N21:out port, N21 + 2 out port, N20:out port, N20 + 2:out port, N19:out port, N19 + 2 out port, N18:out port, N18 + 2:out port, N17:out port, N17 + 2 out port, N16:out port, N16 + 2:out port, N15:out port, N15 + 2 out port, N14:out port, N14 + 2:out port, N13:out port, N13 + 2 out port, N12:out port, N12 + 2:out port, N11:out port, N11 + 2 out port, N10:out port, N10 + 2:out port, N9:out port, N9 + 2 out port, N8:out port, N8 + 2:out port, N7:out port, N7 + 2 out port, N6:out port, N6 + 2:out port, N5:out port, N5 + 2 out port, N4:out port, N4 + 2:out port, N3:out port, N3 + 2 out port, N2:out port, N2 + 2:out port, N1:out port, N1 + 2 out port, N0:out port, N0 + 2:out port, LEPLL:out port, 0 'Latch buffer out control, contclear 'Disable the Control Board J connector return 'to [CommandPLL] [CommandPLLslim]'needs:datavalue,levalue,N23-N0,control,Jcontrol,port,contclear,LEPLL ; commands N23-N0,SLIM ControlBoard ver111-28 'used during initialization of PLL1, PLL2, and PLL3. PDM will get set to "0" during Initializations 'selt word = 1 common clock, 4 datas, plus 3 (filtbank). entering this sub, selt word should = filtbank only 'init word = 5 latch lines plus 2 pdm commands. entering this sub, init word should = pdmcmd + pdmclk only.ver111-39d 'two steps to do: command data and clock without disturbing Filter Bank, then send LE without disturbing PDM 'step 1. Command the PLL without changing the filter bank. 'For PLL1,datavalue=2, for PLL2,datavalue=16, for PLL3,datavalue=8 'following code lines changed in ver113-3c a=filtbank + N23*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N22*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N21*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N20*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N19*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N18*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N17*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N16*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N15*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N14*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N13*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N12*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N11*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N10*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N9*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N8*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N7*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N6*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N5*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N4*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N3*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N2*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N1*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear a=filtbank + N0*datavalue:out port, a:out control, SELT:out control, contclear:out port, a+1:out control, SELT:out control, contclear out port, filtbank:out control, SELT:out control, contclear 'leaving lines latched to filter bank out port, 0 'step 2. Command the PLL without changing the PDM pdmcommand = phaarray(thisstep,0)*64 'do not disturb PDM state, this may be used during Spur Test out port, pdmcommand + levalue 'levalues: PLL1=1, PLL2=16, PLL3=4 out control, INIT out port, pdmcommand out control, contclear 'leaving lines latched, and unchanged, to PDM out port, 0 return 'to [CommandPLL] [DetermineModule] 'ver111-28 'All "glitchXX's" are "0" when entering this subroutine. Either from "fresh RUN" or [WaitStatement] 'if a module is not present, or if it doesn't need commanding, return with it's "glitchXX = 0" '[DDS1] dds1output = DDS1array(thisstep,46) 'ver111-16 if dds1output = lastdds1output then goto [PLL1] 'dds 1 is same, don't waste time commanding 'ver111-28 glitchd1 = 1 'ver111-36h lastdds1output = dds1output [PLL1] ncounter1=PLL1array(thisstep,45):fcounter1=PLL1array(thisstep,46) 'ver111-16 if ncounter1=lastncounter1 and fcounter1=lastfcounter1 then goto [PLL3] 'don't waste time commanding 'ver111-28 glitchp1 = 1 'add 1 msec delay. ver111-28 lastncounter1=ncounter1:lastfcounter1=fcounter1 'ver111-16 [PLL3] if TGtop = 0 then return 'there is no PLL 3, no DDS 3,and no PDM for VNA ncounter3=PLL3array(thisstep,45):fcounter3=PLL3array(thisstep,46) if ncounter3=lastncounter3 and fcounter3=lastfcounter3 then goto [DDS3] 'don't waste time commanding 'ver111-28 glitchp3 = 1 'add 1 msec delay. ver111-28 lastncounter3=ncounter3:lastfcounter3=fcounter3 [DDS3] if appxdds3 = 0 then goto [PDM] 'if 0, there is no DDS3, but, there can be VNA ver111-28 dds3output = DDS3array(thisstep,46) if dds3output = lastdds3output then goto [PDM] 'dds 3 is same, don't waste time commanding 'ver111-29 glitchd3 = 1 'ver111-36h lastdds3output = dds3output [PDM] if msaMode$="SA" or msaMode$="ScalarTrans" then return ' not in VNA mode, skip the PDM 'ver111h ver 114-5n pdmcmd = phaarray(thisstep,0) 'ver111-39d if pdmcmd = lastpdmstate then return 'don't waste time commanding gosub [VideoGlitchPDM] 'ver114-6c 'lastpdmstate = pdmcmd 'delver114-6c we won't update "lastpdmstate" until it is actually commanded return 'to [CommandThisStep] [CommandOrigCB]' correct modules have been determined in [DetermineModule] 'Command necessary modules, independently, from Original Control Board if glitchd1 > 0 then gosub [CommandDDS1OrigCB] if glitchp1 > 0 then gosub [CommandPLL1OrigCB] if glitchd3 > 0 and TGtop > 0 then gosub [CommandDDS3OrigCB] if glitchp3 > 0 and TGtop > 0 then gosub [CommandPLL3OrigCB] if glitchpdm > 0 and msaMode$<>"SA" and msaMode$<>"ScalarTrans" then gosub [CommandPDMOrigCB] 'ver114-5n return 'to [CommandThisStep] [CommandDDS1OrigCB] 'needed:DDS1array 'ver111-21 if dds1parser = 1 then goto [CommandDDS1OrigCBserial] 'ver111-21 '(CommandDDS1OrigCBparallel)'needed:DDS1array(w0-w4),port,control,AUTO,STRB,contclear ; commands DDS1 on J5, parallel. ver111-21 'note, a DDS commanded parallel, will begin with Control Word (W0), then MSB Word (W1), ending with LSB Word (W4) 'set word 0 'set 8 bit word, W0 (0), phase info out port,DDS1array(thisstep,40) ' a "1" here would activate the x4 internal multiplier, but not recommended out control, AUTO 'wclk line goes high out control, contclear 'wclk line goes low 'set word 1 out port,DDS1array(thisstep,41) 'set 8 bit word, W1, MSB freq out control,AUTO:out control, contclear 'set word 2 out port,DDS1array(thisstep,42) 'W2 out control,AUTO:out control, contclear 'set word 3 out port,DDS1array(thisstep,43) 'W3 out control,AUTO:out control, contclear 'set word 4 out port,DDS1array(thisstep,44) 'set 8 bit word, W4, LSB freq out control,AUTO:out control, contclear out port, 0 'return the output port data lines to 0 'send fqud out control, STRB 'set fqud to 1, freq changes now out control, contclear 'set fqud to 0 and all others to 0 return 'to [CommandOrigCB] [CommandDDS1OrigCBserial]'needed:DDS1array(sw0-sw39),control,AUTO,STRB,contclear ; commands DDS1 on J5, serially ver111-21 'note: once the DDS1 has been reset into serial mode, the D0 thru D6 data lines are "don't care". 'note, a DDS serial command, will begin with LSB (W0), thru MSB (W31), ending with Phase bit 4 (W39) for clmn = 0 to 39 'ver111-21 out port, DDS1array(thisstep,clmn)*128 'apply data bit to DDS1pin25, D7 data line out control, AUTO:out control, contclear 'retain data bit while wclk up, then down next clmn 'next bit in 40 bit serial data transfer out port, 0 out control, STRB:out control, contclear 'fqud up, fqud down return 'to [CommandOrigCB] '[endCommandDDS1OldRevA] [CommandPLL1OrigCB]'needed:PLL1array(N23-N0),SELT,lastncounter1,lastfcounter1 'ver111-21 'ver111-28a makes the SELT buffer "see" the pdm state before commanding PLL1, to prevent orig PDM from changing states. Jcontrol = SELT : LEPLL = 4 'ver111-21 'Command PLL1,oldControl using N23-N0,control,Jcontrol,port,contclear,LEPLL ver111-21 'note, a PLL will serially command beginning with N23 and end with N0 (address bit) pdmcmd = phaarray(thisstep,0) 'ver111-39d out port, pdmcmd*128 'ver111-28a out control, Jcontrol 'enable Control Board J connector for clmn = 0 to 23 'reversed order 'ver111-31a out port, pdmcmd*128 + PLL1array(thisstep,clmn):out port, pdmcmd*128 + PLL1array(thisstep,clmn) + 2 'ver111-21 'ver111-28a next clmn 'ver111-21 out port, pdmcmd*128 + LEPLL:out port, pdmcmd*128 'Latch buffer 'ver111-28a out control, contclear 'Disable the Control Board J connector out port, 0 'ver111-28a lastpdmstate=phaarray(thisstep,0) 'ver114-6c return 'to [CommandOrigCB] [CommandDDS3OrigCB]'needed:DDS3array,lastdds3output,INIT 'ver111-18 Jcontrol = INIT:swclk = 32:sfqud = 2 'for Orig Control Bd,J4,DDS3 ver111-16 'Command DDS3,serially,oldControl using sw0-sw39,swclk,sfqud,control,Jcontrol,port,contclear,LEPLL ver111-21 'note, a DDS commanded serially, will begin with LSB, continue to MSB, and end with Control Word MSB Phase Bit 'present filter bank data while commanding DDS3, so as not to change filter bank ver111-29 out port, filtbank 'ver111-29 out control, Jcontrol 'enable Control Board J connector for clmn = 0 to 39 'ver111-21 out port, filtbank + DDS3array(thisstep,clmn) 'apply data bit to DDS, and also filter lines 'ver111-29 out port, filtbank + DDS3array(thisstep,clmn) + swclk 'apply data bit and wclk 'ver111-29 next clmn out port, filtbank:out port, filtbank + sfqud:out port, filtbank 'last sw down and swclk down, sfqud up, sfqud down 'ver111-29 out control, contclear 'disable J connector out port, 0 'ver111-29 return 'to [CommandOrigCB] [CommandPLL3OrigCB]'needed:PLL3array(N23-N0),INIT,lastncounter3,lastfcounter3 ver111-18 Jcontrol = INIT : LEPLL = 16 'ver111-21 'Command PLL3,Orig Control using N23-N0,control,Jcontrol,port,contclear,LEPLL ver111-21 'note, a PLL will serially command beginning with N23 and end with N0 (address bit) 'present filter bank data while commanding PLL3, so as not to change filter bank ver111-29 out port, filtbank 'ver111-29 out control, Jcontrol 'enable Control Board J connector for clmn = 0 to 23 'reversed order 'ver111-31a out port, filtbank + PLL3array(thisstep,clmn) 'ver111-29 out port, filtbank + PLL3array(thisstep,clmn) + 2 'ver111-21 'ver111-29 next clmn 'ver111-21 out port, filtbank + LEPLL:out port, filtbank 'Latch buffer 'ver111-29 out control, contclear 'Disable the Control Board J connector out port, 0 'ver111-29 return 'to [CommandOrigCB] [CommandPDMonly] 'ver111-28 if cb = 0 then goto [CommandPDMOrigCB] 'ver111-28 if cb = 2 then goto [CommandPDMSlimCB] 'ver111-28 return 'to [InvertPDmodule] [CommandPDMOrigCB]'Set original PDM phase for last known mode, since a PLL1 or PLL2 command will reset the PDM to Norm. out port, phaarray(thisstep,0)*128: out control, SELT: out control, contclear: out port, 0 'pdmcmd is determined in [InvertPDmodule] 'ver111-20 lastpdmstate=phaarray(thisstep,0) 'ver114-6c return 'to [CommandOrigCB]or[CommandPDMonly] [CommandPDMSlimCB]'also sending a "latch signal", used by orig PDM module out port, phaarray(thisstep,0)*64 out control, INIT out port, phaarray(thisstep,0)*64 + 32 out port, phaarray(thisstep,0)*64 out control, contclear out port, 0 lastpdmstate=phaarray(thisstep,0) 'ver114-6c return 'to [CommandPDMonly] 'delver113-3b[CommandPLL1SlimCB]'independently.(not used) 'delver113-3b[CommandPLL3SlimCB]'independently.(not used) 'delver113-4a[CommandDDS1SlimCB]'independently.(not used) 'delver113-4a[CommandDDS3SlimCB]'independently.(not used) [CommandAllSlims]'for SLIM Control and SLIM modules. Old PDM and old Filt Bank can be used 'ver111-31c '(send data and clocks without changing Filter Bank) '0-15 is DDS1bit*4 + DDS3bit*16, data = 0 to PLL 1 and PLL 3. see[CreateCmdAllArray]. 'present new Data with no clock,latch high,latch low,present new data with clock,latch high,latch low. ver113-2a 'repeat for each bit. (40 data bits and 40 clocks for each module, even if they don't need that many) 'this format guarantees that the common clock will not transition with a data transition, preventing crosstalk in LPT cable. ver111-32c for clmn = 0 to 39 'ver113-3c a= cmdallarray(thisstep,clmn)+ filtbank out port, a : out control, SELT:out control, contclear 'a is the data, without clock out port, a+1:out control, SELT:out control, contclear 'a+1 is data, plus clock next clmn out port, filtbank 'remove data, leaving filtbank data to filter bank. out control, SELT:out control, contclear 'disable buffer. filtbank signals will be latched to filter bank assembly 'send LE's to PLL1, PLL3, FQUD's to DDS1, DDS3, and command PDM 'begin by setting up init word=LE's and Fquds + PDM state for thisstep pdmcmd = phaarray(thisstep,0)*64 'ver111-39d out port, le1 + fqud1 + le3 + fqud3 + pdmcmd 'present data to buffer input'ver111-39d out control, INIT: out control, contclear 'latch the buffer, moving the signals to the 5 modules'ver113-2a out port, pdmcmd + 32 'remove LEs and Fquds, leaving PDM data, but add a latch signal P2D5 for old PDM if used.'ver111-39d out control, INIT: out control, contclear 'sends latch signal to old PDM'ver113-2a out port, pdmcmd 'remove the added latch signal to PDM, leaving just the PDM's static data'ver111-39d out control, INIT: out control, contclear 'ver113-2a out port, 0 'bring all Data lines low. PDM data remains static lastpdmstate=phaarray(thisstep,0) 'ver114-6c return 'to [CommandThisStep] [finished]'this is the end of the software, close any open window if special = 1 then close #special 'close out Special Tests window. ver113-5a if varwindow = 1 then close #varwin 'close out variable window if datawindow = 1 then close #datawin 'close out data window. ver113-5a if calManWindHndl$<>"" then close #calManWindHndl$ 'close window for calibration manager, SEWcal3 ver113-7g if configWindHndl$<>"" then close #configWindHndl$ 'close window for configuration manager, SEWcal3 ver113-7g if axisPrefHandle$<>"" then close #axisPrefHandle 'SEWgraph Close axis preference window; it's a modal dialog so this should not happen 'close #main 'close out working window delver114-4f close #handle 'close out graph window end '------------ ' The following are error messages and are not compiled: '"PLL 1" '"PLL 2" '"PLL 3" ' and: ' "2325 Rcounter is < 3" ' "2325 Rcounter is > 16383" ' "2325 Bcounter < 3" ' "2325 Bcounter > 2047" ' "2325 Bcounter16383" ' "2326 Bcounter <3" ' "2326 Bcounter >8191" ' "2326 Bcounter32767" ' "2350 Bcounter <3" ' "2350 Bcounter >1023" ' "2350 Bcounter 32767" ' "2353 Bcounter is < 3" ' "2353 Bcounter is > 1023" ' "2353 Bcounter < Acounter+2" ' "4112 R counter >16383" ' "4112 N counter <3" ' "4112 N counter >8191" ' "4112 B counter .5 ddsclock" 'ver112-2c '-------------------------------- [SpecialTests]'ver111-36b if haltsweep=1 then gosub [CleanupAfterSweep] 'ver114-4f if special=1 then goto [CloseSpecial] WindowWidth = 200 WindowHeight = 300 UpperLeftX = DisplayWidth-WindowWidth-20 'ver114-4f UpperLeftY = 5 'ver114-4f BackgroundColor$ = "darkblue" ForegroundColor$ = "white" TextboxColor$ = "red" 'the following textboxes will be red ver113-7e button #special.DDS1, "Command DDS 1", [CommandDDS1], UL, 5, 5, 100, 20 textbox #special.dds1out, 105, 5, 75, 20 'create DDS 1 frequency output box statictext #special.dds1txt, "with DDS Clock at ", 5, 30, 100, 15 textbox #special.masclkf, 105, 30, 75, 20 'create master clock frequency box button #special.DDS3, "Command DDS 3", [CommandDDS3], UL, 5, 55, 100, 20 'ver111-38a textbox #special.dds3out, 105, 55, 75, 20 'create DDS 1 frequency output box 'delver113-3a button #special.testglitch, "Test Glitchtime var", [TestGlitchtime], UL, 5, 80, 100, 20 'ver111-36c 'delver113-3a textbox #special.glitchbox, 105, 80, 75, 20 'create glitchbox 'ver111-36c button #special.dds3track, "DDS 3 Track", [DDS3Track], UL, 5, 105, 75, 20 'ver111-39d statictext #special.dds3trktxt, "0-32", 80, 107, 25, 15 'ver112-2c button #special.dds1track, "DDS 1 Sweep", [DDS1Sweep], UL, 115, 105, 75, 20 'ver112-2c button #special.pdminv, "Change PDM", [ChangePDM], UL, 5, 130, 90, 20 'ver112-2a if msaMode$<>"SA" and msaMode$<>"ScalarTrans" then button #special.insert, "Sync Test PDM", [SyncTestPDM], UL, 5, 155, 90, 20 'ver112-2f button #special.prevnalin, "Preset Phase Linearity", [PresetVNAlin], UL, 5, 180, 150, 20 'ver112-2f ver114-5n ver114-7h end if open "Special Tests Window" for dialog as #special:special = 1 print #special.dds1out, "";DDS1array(thisstep,46) 'insert DDS1 output frequency at thisstep 'ver112-2d print #special.masclkf, "";masterclock 'insert masterclock frequency print #special.dds3out, "";DDS3array(thisstep,46) 'insert DDS3 output frequency at thisstep 'ver112-2d 'delver113-3a print #special.glitchbox, "";glitchtime 'insert last glitchtime into glitchbox 'ver112-2d print #special, "trapclose [CloseSpecial]" 'goto [CloseSpecial] if xit is clicked wait [CloseSpecial]'ver111-36b syncsweep = 0 'ver112-2b setpdm = 0 'makes sure the PDM returns to automatic operation ver112-2a convdatapwr = 0 'ver112-2b vnalintest = 0 'ver112-2f test = 0 'ver112-2g close #special:special = 0 'close out Special Tests window if returnflag = 1 then return 'ver112-2f wait [OpenDataWindow]'ver113-5a if haltsweep = 1 then gosub [FinishSweeping] 'ver114-6f 'if the "Array Data Window" is already open, close it. if datawindow = 1 then close #datawin:datawindow = 0 'create window called, Data Window, to display all data for each step WindowWidth = 200 'ver114-6f WindowHeight = 300 UpperLeftX = DisplayWidth-WindowWidth-20 'ver114-6f UpperLeftY = 20 'ver114-6f BackgroundColor$ = "white" ForegroundColor$ = "black" open "Data Window" for text as #datawin:datawindow = 1 'delver113-5b print #datawin, "trapclose [CloseDataWindow]" 'goto [CloseDataWindow] if xit is clicked return sub CloseDataWindow hndl$ 'ver114-7n changed to sub. Note this is never used anyway close #datawin:datawindow = 0 end sub [MagnitudeMSAinput]'ver113-5a gosub [OpenDataWindow] enterthisstep = thisstep print #datawin,"MHz dBm" 'ver114-6f for thisstep = 0 to steps print #datawin, datatable(thisstep,1);" "; datatable(thisstep,2) 'Magnitude input to MSA next thisstep thisstep = enterthisstep wait [MagBitsAtoD]'ver113-5a gosub [OpenDataWindow] enterthisstep = thisstep print #datawin,"MHz Mag Bits" 'ver114-6f for thisstep = 0 to steps print #datawin, datatable(thisstep,1);" "; magarray(thisstep,3) 'Magnitude AtoD, in Bits next thisstep thisstep = enterthisstep wait [MagCalTable]'ver113-5a gosub [OpenDataWindow] enterthisstep = thisstep print #datawin,"MHz Mag Cal Correction" 'ver114-6f for thisstep = 0 to steps print #datawin, datatable(thisstep,1);" "; lineCalArray(thisstep,2) 'Magnitude, Calibration Table next thisstep thisstep = enterthisstep wait [PhaProcessed]'ver113-5a gosub [OpenDataWindow] enterthisstep = thisstep print #datawin,"MHz Phase (deg)" 'ver114-6f for thisstep = 0 to steps print #datawin, datatable(thisstep,1);" "; datatable(thisstep,3) 'Phase, processed next thisstep thisstep = enterthisstep wait [PhaBitsAtoD]'ver113-5a gosub [OpenDataWindow] enterthisstep = thisstep print #datawin,"MHz Phase Bits" 'ver114-6f for thisstep = 0 to steps print #datawin, datatable(thisstep,1);" "; phaarray(thisstep,3) 'Phase A/D. Bits next thisstep thisstep = enterthisstep wait [PhaCalTable]'ver113-5a gosub [OpenDataWindow] enterthisstep = thisstep print #datawin,"MHz Phase Cal Correction" 'ver114-6f for thisstep = 0 to steps print #datawin, datatable(thisstep,1);" "; lineCalArray(thisstep,2) 'Phase Claibration Table next thisstep thisstep = enterthisstep wait [MagPhaS21]'ver113-5b gosub [OpenDataWindow] xclm$="!" print #datawin,"!insert xclm$ +" print #datawin,"S21 Data for Transmission" 'ver114-5n print #datawin,"!select 1 2" print #datawin,"!insert xclm$ +" print #datawin, "Data taken: ";date$("mm/dd/yyyy");" ";time$() print #datawin,"!select 1 3" print #datawin,"!insert xclm$ +" print #datawin, "Touchstone Format, space delimited" print #datawin, "# MHZ S DB R 50" 'changed MV to DB, ver113-6a print #datawin,"!select 1 5" print #datawin,"!insert xclm$ +" print #datawin, "Freq Mag Ang" enterthisstep = thisstep for thisstep = 0 to steps print #datawin, datatable(thisstep,1);" ";datatable(thisstep,2);" ";datatable(thisstep,3) 'S21 Parameters: Frequency, Magnitude, and Phase Angle next thisstep thisstep = enterthisstep wait [CommandDDS1]'ver111-36b. ver113-4a 'this will recalculate DDS1, using the values in the Command DDS 1 Box, and "with DDS Clock at" Box. 'it will insert the new DDS 1 frequency into the command arrays for all steps, leaving others alone 'it will initiate a re-command at thisstep (where the sweep was halted) 'if Original Control Board is used, only the DDS 1 is re-commanded. ver113-4a 'if SLIM Control Board is used, all 4 modules will be re-commanded. ver113-4a 'using One Step or Continue will retain the new DDS1 frequency. 'PLO1 will be non-functional until [Restart] button is clicked. PLL1 will break lock and "slam" to extreme. '[Restart] will reset arrays and begin sweeping at step 0. Special Tests Window will not be updated. 'Signal Generator or Tracking Generator output will not be effected. 'caution, do not enter a frequency that is higher than 1/2 the masterclock frequency (ddsclock) print #special.dds1out, "!contents? dds1out$"; 'grab contents of Command DDS 1 Box ddsoutput = val(dds1out$) 'intended output frequency of DDS 1 print #special.masclkf, "!contents? msclk$"; 'grab contents of "with DDS Clock at" box msclk = val(msclk$) 'if "with DDS Clock at" box was not changed, this is the real MasterClock frequency ddsclock = msclk 'caution: if ddsoutput >= to .5 ddsclock, the program will error out gosub [CreateBaseForDDSarray]'needed:ddsoutput,ddsclock ; creates: base,sw0thrusw39,w0thruw4 remember = thisstep 'remember where we were when entering this subroutine for thisstep = 0 to steps 'ver112-2a gosub [FillDDS1array]'need thisstep,sw0-sw39,w0-w4,base,ddsclock next thisstep 'ver112-2a thisstep = remember 'ver112-2a gosub [CreateCmdAllArray] 'ver112-2a if cb = 0 then gosub [CommandDDS1OrigCB]'will command DDS 1, only 'delver113-4a if cb = 2 then gosub [CommandDDS1SlimCB]'will command DDS 1, only if cb = 2 then gosub [CommandAllSlims]'will command all 4 modules. ver113-4a wait [CommandDDS3]'ver111-38a 'this will recalculate DDS3, using the values in the Command DDS 3 Box, and "with DDS Clock at" Box. 'it will insert the new DDS 3 frequency into the command arrays for all steps, leaving others alone 'it will initiate a re-command at thisstep (where the sweep was halted) 'only the DDS 3 is re-commanded 'using One Step or Continue will retain the new DDS3 frequency. 'PLO3 will be non-functional until [Restart] button is clicked. PLL3 will break lock and "slam" to extreme. '[Restart] will reset arrays and begin sweeping at step 0. Special Tests Window will not be updated. 'Signal Generator or Tracking Generator output will be non functional. 'Spectrum Analyzer function is not effected 'caution, do not enter a frequency that is higher than 1/2 the masterclock frequency (ddsclock) print #special.dds3out, "!contents? dds3out$"; 'grab contents of Command DDS 3 Box ddsoutput = val(dds3out$) 'intended output frequency of DDS 3 print #special.masclkf, "!contents? msclk$"; 'grab contents of "with DDS Clock at" box msclk = val(msclk$) 'if "with DDS Clock at" box was not changed, this is the real MasterClock frequency ddsclock = msclk 'caution: if ddsoutput >= to .5 ddsclock, the program will error out gosub [CreateBaseForDDSarray]'needed:ddsoutput,ddsclock ; creates: base,sw0thrusw39,w0thruw4 remember = thisstep 'remember where we were when entering this subroutine for thisstep = 0 to steps gosub [FillDDS3array]'need thisstep,sw0-sw39,w0-w4,base,ddsclock next thisstep thisstep = remember gosub [CreateCmdAllArray] if cb = 0 then gosub [CommandDDS3OrigCB]'will command DDS 3, only 'delver113-4a if cb = 2 then gosub [CommandDDS3SlimCB]'will command DDS 3, only if cb = 2 then gosub [CommandAllSlims]'will command all 4 modules. ver113-4a wait [DDS3Track]'ver111-39d 'This uses DDS3 as a Tracking Generator, but is limited to 0 to 32 MHz, when MasterClock is 64 MHz 'DDS3 spare output is rich in harmonics and aliases. 'Tracks the values in Working Window, Center Frequency and Sweep Width (already in the command arrays) 'The Spectrum Analyzer function is not effected. 'PLO3, Normal Tracking Generator, and Phase portion of VNA will be non-functional 'Operation: 'In Working Window, enter Center Frequency to be within 0 to 32 (MHz), or less than 1/2 the MasterClock 'In Working Window, enter Sweep Width (in MHz). But, do not allow sweep to go below 0 or abov 1/2 MasterClock 'Click [Restart], then halt. 'In Special Tests Window, click [DDS 3 Track]. DDS 3 will, immediately, re-command to new frequency. 'Click [Continue]. Sweep will resume, but with DDS 3 tracking the Spectrum Analalyzer '[One Step] and [Continue] and halting operates normally until [Restart] button is pressed. '[Restart] will reset arrays, and leave the DDS 3 Track Mode. ie, normal sweeping. ddsclock = masterclock remember = thisstep for thisstep = 0 to steps ddsoutput = datatable(thisstep,1) 'caution: if ddsoutput >= to .5 ddsclock, the program will error out gosub [CreateBaseForDDSarray]'needed:ddsoutput,ddsclock ; creates: base,sw0thrusw39,w0thruw4 gosub [FillDDS3array]'need thisstep,sw0-sw39,w0-w4,base,ddsclock next thisstep thisstep = remember gosub [CreateCmdAllArray] if cb = 0 then gosub [CommandDDS3OrigCB]'will command DDS 3, only 'delver113-4a if cb = 2 then gosub [CommandDDS3SlimCB]'will command DDS 3, only if cb = 2 then gosub [CommandAllSlims]'will command all 4 modules. ver113-4a wait [DDS1Sweep]'ver112-2c 'This forces the DDS 1 to the values in Working Window: Center Frequency and Sweep Width (already in the command arrays) 'DDS1 spare output is rich in harmonics and aliases. 'PLO1, and thus, the Spectrum Analyzer will be non-functional in this mode. 'Signal Generator or Tracking Generator output will not be effected. 'Operation: 'In Working Window, enter Center Frequency to be within 0 to 32 (MHz), or less than 1/2 the MasterClock 'In Working Window, enter Sweep Width (in MHz). But, do not allow sweep to go below 0 or abov 1/2 MasterClock 'Click [Restart], then halt. 'In Special Tests Window, click [DDS 1 Sweep]. DDS 1 will, immediately, re-command to new frequency. 'Click [Continue]. Sweep will resume, but with DDS 1 sweeping. '[One Step] and [Continue] and halting operates normally until [Restart] button is pressed. '[Restart] will reset arrays, and will leave the DDS 1 Sweep Mode. ie, normal sweeping. ddsclock = masterclock remember = thisstep for thisstep = 0 to steps ddsoutput = datatable(thisstep,1) 'caution: if ddsoutput >= to .5 ddsclock, the program will error out gosub [CreateBaseForDDSarray]'needed:ddsoutput,ddsclock ; creates: base,sw0thrusw39,w0thruw4 gosub [FillDDS1array]'need thisstep,sw0-sw39,w0-w4,base,ddsclock next thisstep thisstep = remember gosub [CreateCmdAllArray] if cb = 0 then gosub [CommandDDS1OrigCB]'will command DDS 1, only 'delver113-4a if cb = 2 then gosub [CommandDDS1SlimCB]'will command DDS 1, only if cb = 2 then gosub [CommandAllSlims]'will command all 4 modules. ver113-4a wait 'delver113-3a [TestGlitchtime]'this subroutine is deleted for ver113 [ChangePDM]'ver112-2a 'enters from Special Tests Window Button setpdm = setpdm + 1 if setpdm > 2 then setpdm = 0 if setpdm = 0 then print #special.pdminv, "PDM is Auto" if setpdm = 1 then print #special.pdminv, "PDM in Normal":gosub [PdmNorm] if setpdm = 2 then print #special.pdminv, "PDM in Inverted":gosub [PdmInv] wait [PdmNorm]'this commands the pdm to Normal, for all steps rememberthisstep = thisstep for thisstep = 0 to steps phaarray(thisstep,0) = 0 next thisstep thisstep = rememberthisstep gosub [CommandPDMonly] return [PdmInv]'this commands the pdm to Invert, for all steps rememberthisstep = thisstep for thisstep = 0 to steps phaarray(thisstep,0) = 1 next thisstep thisstep = rememberthisstep gosub [CommandPDMonly] return [SyncTestPDM] 'ver112-2b 'enters from Special Tests Window Button, only if in VNA Mode 'this will set up defaults and begin sweeping to measure phase steps 'when CF=0 and SW=0, the PDM will measure "rolling" phase of two different frequencies, 'although the difference is less than 1 Hz.PDM is fixed at Norm(0) syncsweep = 1 'ver112-2b convdatapwr = 1 'ver112-2b 'SEWgraph updated the following to deal with changes in text boxes call SetCenterSpanFreq 0,0 'SEWgraph zero width, zero center wate=3 'SEWgraph 3ms wait time ver114-4d call SetPhaseRange 0,360 'SEWgraph Phase range 0 to 360 ver114-4d call SetPowerRange -5, 5 'SEWgraph Mag range -5 to 5 ver114-4d call gSetXIsLinear 1 'SEWgraph Be sure sweep is linear call gCalcGraphParams 'SEWgraph Calculate scaling, etc. with new parameters setpdm = 1 : print #special.pdminv, "PDM in Normal":gosub [PdmNorm] haltsweep=0 'So Restart actually restarts 'ver114-6e goto [Restart] wait [SyncSweep]'comes here at end of sweep if syncsweep = 1 'ver112-2b 'it will not continue sweeping until the phase data is between 80 and 90% of maxpdmout 'hopefully, it will "trigger" a sweep at 81% gosub [ReadPhase] scan 'this is a fail safe. Click any button to get out of this loop. ver113-6e if phadata > .8*maxpdmout and phadata < .9*maxpdmout then return goto [SyncSweep] [ConvertDataToPower] 'ver112-2b 'this routine is a traffic director when the blue Magnitude trace is used for other data. 'enters from [CalcMagpowerPixel] if convdatapwr = 1 if syncsweep = 1 then goto [ConvertSync] goto [ConvertPDMlin] [ConvertSync] 'ver112-2b 'this will take the phase difference of the previous step's and this step's phase 'and convert it to power, for display 'enters from [ConvertDataToPower] if syncsweep = 1 if thisstep = 0 then return 'the last step in the sweep - step 0 is bogus data 'grab raw phase bits from previous sweep and create deltabits deltabits = phaarray(thisstep-sweepDir,3) - phaarray(thisstep,3) 'ver114-4m 'convert deltabits to delta phase deltaphase = 360 * deltabits/maxpdmout power = deltaphase return [PresetVNAlin] 'ver112-2b print #special.prevnalin, "Test Transmission Linearity" 'change the button name if vnalintest = 1 then goto [VNAlinTest] vnalintest = 1 'SEWgraph created the following loop to clear lineCalArray, rather than redimensioning call ClearCalarray gMaxNumPoints()-1 'ver114-5f 'SEWgraph updated the following to deal with changes in text boxes call SetCenterSpanFreq 500,1000 'SEWgraph; 500 MHz center, 1000 MHz span wate=22 'ver114-4d; 22 ms wait time call SetPhaseRange-180,180 'SEWgraph Phase range -180 to 180 ver114-4d 'afix the PDM to "Normal" (0). It will remain fixed as long as the Special Tests Window is open. setpdm = 1 : print #special.pdminv, "PDM in Normal":gosub [PdmNorm] 'set up magnitude limits, prolly +/- 5 degrees(db) call SetPowerRange -5, 5 'SEWgraph Y2 from -5 to 5. This is actually degrees, not power ver114-4d call gSetXIsLinear 1 'SEWgraph be sure sweep is linear call gCalcGraphParams 'SEWgraph Calculate scaling, etc. with restored parameters haltsweep=0 'So Restart actually restarts 'ver114-6e goto [Restart] 'the sweep will begin, and display several sawtooths, the number depending on the length 'of the cable between the TG output and the MSA input. 'There will be extreme glitches near the center of each sawtooth, indicating the 'zero degree crossovers. This is due to the PDM being fixed at "Normal" [VNAlinTest]'for testing PDM Linearity 'ver112-2b 'make sure pdm is fixed at norm or invert before entering. Accomplished by previously clicking [PresetVNAlin] Button. 'before entering this routine, make sure the sweep is displaying one full segment that ' is greater than 360 degrees and less than 720 degrees. 'before entering this routine, pick a step point to be the zero phase error refpoint. It has: 'step #, frequency, and phase. It must be within the 0 degree crossover boundries. 'we use it as a reference zero degrees error. Use the Mouse's left click to select the step. 'then, click the Special Tests Window [Test VNA Linearity] Button. 'a very long line, between TG out and MSA in, will reduce the error created by Mixer 4, AM to PM conversion convdatapwr = 1 'used in [CalcMagpowerPixel] to skip processing Mag Data 'determine the "real" slope factor for this band segment, in degrees per MHz 'retrieve raw phase data bits. Bits0, Bits400 'ver112-2g phabits0 = phaarray(0,3) 'ver112-2g phabits400 = phaarray(steps,3) 'ver112-2g 'if phabits0 is less than or equal to phabits400, add 360 degrees(in bits) to phabits0 'ver112-2g 'maxpdmout is the bit value of 360 degrees, for any AtoD Module if phabits0 <= phabits400 then phabits0 = phabits0 + maxpdmout 'ver112-2g 'add maxpdmout (65535 bits) to phabits0 and take difference 'ver112-2g 'delta bits = maxpdmout + phabits0 - phabits400 'ver112-2g 'change to phase: 360 * (delta bits/maxpdmout) 'ver112-2g delpha = 360*((maxpdmout + phabits0 - phabits400)/maxpdmout) 'ver112-2g 'freq at step 0 - freq at last step = delta freq (551.8 - 829 = -277.2) delfreq = datatable(0,1) - datatable(steps,1) 'SEWgraph The following line avoids a crash with zero span if delfreq=0 then notice "Sweep must be preset to show 360-720 degrees." :wait 'SEWgraph 'realslopefactor (in deg per MHz) = delta phase / delta freq = (393.7 / -277.2) = -1.42 d/m realslopefactor = delpha/delfreq '(in -degrees/MHz) refstep = leftstep 'the processed phase for refstep is in datatable(refstep,3),always for previous sweep refstepphase = datatable(refstep,3) 'the frequency of refstep is in datatable(refstep,1),always for previous sweep refstepfreq = datatable(refstep,1) 'print the slope factor in the Message Box next time sweep is halted test=realslopefactor 'this will be cleared when leaving Spec Test Window. ver112-2g haltsweep=0 'So Restart actually restarts 'ver114-6e goto [Restart] [ConvertPDMlin] 'ver112-2b 'enters here from [CalcMagpowerPixel]. We are processing the previous step but it 'is still called "thisstep" 'the blue line will show how far off the real slope is from a theoritical slope, in degrees 'the processed phase for thisstep is in datatable(thisstep,3) 'the frequency of thisstep is in datatable(thisstep,1) 'this step will have a theoritical phase equal to: ' theoryphase = thisstep freq - refstep freq times realslopefactor + refstep phase theoryphase = ((datatable(thisstep,1)- refstepfreq) * realslopefactor) + refstepphase 'in wide band sweeps, theoryphase can get greater than 360 degrees 'ver112-2g 'therefore, change theoryphase to decimal number compared to 360 degrees 'ver112-2g theoryphase = theoryphase/360 'example theoryphase = 1.324 or -1.226 'ver112-2g 'cast out whole number and use decimal equivalent 'ver112-2g theoryphase = theoryphase - int(theoryphase) 'theoryphase = .324 or -.226 'ver112-2g 'reconvert back to phase 'ver112-2g theoryphase = 360*theoryphase 'ver112-2g if theoryphase < -180 then theoryphase = theoryphase + 360 if theoryphase > 180 then theoryphase = theoryphase - 360 'at this line, I could make power = theoryphase and display blue over red error 'the error will be equal to: phaseerror = thisstep phase - theoryphase phaseerror = datatable(thisstep,3) - theoryphase if phaseerror < -180 then phaseerror = phaseerror + 360 if phaseerror > 180 then phaseerror = phaseerror - 360 'using the blue magpower line as phase error, the processed magpower becomes phaseerror power = phaseerror return '--SEW Added the following routines to save/copy the graph image 'These routines are invoked through the File and Edit menus 'Scotty: I created additional variables here, all of which begin with captial X 'to avoid any conflicts with your variables. '=====================Start Routines to Save/Copy Image=========================== 'SEWgraph revised SaveImage [SaveImage] 'Save graph image to file if haltsweep=1 then notice "Sweep will halt at end. Then re-click Save Image." haltAtEnd=1 'Set flag to cause halt at end of this sweep. goto [PostScan] end if if isStickMode=0 then refreshGridDirty=1 : call RefreshGraph 0 'Redraw without erasure mark; but not if we are in stick mode ver114-7d bmpName$=FullGraphBmp$() 'get bmp name ver114-5q hBitmap=hbmp(bmpName$)'get bmp handle ver114-5q filedialog "Save As...", "*.bmp", graphFileName$ 'will have buttons that say SAVE and CANCEL if graphFileName$<>"" then open graphFileName$ for output as #outFile bmpsave "graphbmp", graphFileName$ close #outFile end if unloadbmp bmpName$ : bmpName$="" 'ver114-5q wait 'ver114-5q added FullGraphBmp$() function FullGraphBmp$() 'return name of bitmap for entire graph--grid and surrounding info 'Get Image size by finding center positions and doubling them call HideButtonsOnGraph 'ver114-4f #graphBox$, "home" #graphBox$, "posxy CenterX CenterY" clientWidth = CenterX * 2-1 clientHeight = CenterY * 2-1 print #graphBox$, "getbmp graphbmp 0 0 ";clientWidth;" ";clientHeight call ShowButtonsOnGraph 'ver114-4f FullGraphBmp$="graphbmp" end function 'SEWgraph revised CopyImage [CopyImage] 'Copy graph image to clipboard if haltsweep=1 then notice "Sweep will halt at end. Then re-click Copy Image." haltAtEnd=1 'Set flag to cause halt at end of this sweep. goto [PostScan] end if if isStickMode=0 then refreshGridDirty=1 : call RefreshGraph 0 'Redraw without erasure mark; but not if we are in stick mode ver114-7d bmpName$=FullGraphBmp$() 'get bmp name 'ver114-5q hBitmap=hbmp(bmpName$)'get bmp handle 'ver114-5q 'open clipboard: calldll #user32, "OpenClipboard",h as long, result as long calldll #user32, "EmptyClipboard", ret as long 'put bmp data on clipboard: calldll #user32, "SetClipboardData",_CF_BITMAP as long,_ hBitmap as long, rethandle as long calldll #user32, "CloseClipboard", r as boolean unloadbmp bmpName$ : bmpName$="" 'ver114-5q wait '@==================End of Save/Copy Image================ 'ver114-4f added HideButtonsOnGraph sub HideButtonsOnGraph 'Hide buttons on the graph box so image can be copied 'ver114-7b deleted the scale arrow buttons so there is nothing at the moment to hide end sub 'ver114-4f added HideButtonsOnGraph sub ShowButtonsOnGraph 'Show buttons that lie on the graph box 'ver114-7b deleted the scale arrow buttons so there is nothing at the moment to hide end sub sub SetFilterAnalysis 'Display dialog for filter analysis and set parameters 'This assumes that Trace 2 displays a peak with a marker at the peak. The user 'specifies the marker ID and two db levels: db1 and db2. For example, db1=-3 and 'db2=-40. We locate the frequencies where the response is down by those amounts, 'marking them with markers if requested. We calculate insertion loss, 'bandwidth at both db levels, Q, and shape factor. 'We can also calculate unloaded Q--i.e. the Q when not loaded 'by the VNA, if the user specifies the loads. WindowWidth = 325 : WindowHeight = 200 UpperLeftX = INT((DisplayWidth-WindowWidth)/2) UpperLeftY = DisplayHeight-WindowHeight-125 BackgroundColor$="darkblue" ForegroundColor$="white" TextboxColor$="blue" ComboboxColor$="blue" 'checkbox to activate or deactivate filter analysis 'ver114-7q separated the captions from the checkboxes so the text color comes out right checkbox #filt.doFilt, "", [filtNOP], [filtNOP],10, 10, 20, 15 'ver114-7d statictext #filt, "Analyze filter spectrum for bandwidth, Q and shape factor.",30, 10, 300, 15 'ver114-7d statictext #filt.Instruct1, "Reference Marker is considered the peak.", 25, 25, 250, 15 statictext #filt.Instruct2, "X1DB and X2DB are the points to evaluate.", 25, 40, 250, 15 textTop=65 statictext #filt.peakLab, "Ref Marker", 10, textTop, 70, 15 'SEWgraph2 Allowed reference markers are 1, L, R and P+. 'But markers other than P+ are allowed only if they have been placed if gMarkerPointNum(mMarkerNum("1"))<0 then markIDs$(0)="" else markIDs$(i)="1" if hasMarkL then markIDs$(1)="L" else markIDs$(1)="" if hasMarkR then markIDs$(2)="R" else markIDs$(2)="" markIDs$(3)="P+" Stylebits #filt.peakMark, _CBS_DROPDOWNLIST, 0, 0, 0 'ver114-7h combobox #filt.peakMark, markIDs$(), [filtNOP],10,textTop+15,60, 90 'combo box to select reference marker statictext #filt.db1Lab, "X1DB Down", 100, textTop, 60, 15 textbox #filt.db1, 110, textTop+15, 40, 20 'textbox for x1 point statictext #filt.db2Lab, "X2DB Down", 190, textTop, 60, 15 textbox #filt.db2, 200, textTop+15, 40, 20 'textbox for x2 point button #filt.OK, "OK", [filtFinished], UL, 70, 120, 50, 25 'OK button #filt.Cancel, "Cancel", [filtCancel], UL, 175, 120, 50, 25 'Cancel 'Open dialog open "Filter Analysis" for dialog_modal as #filt #filt, "trapclose [filtCancel]" if doFilterAnalysis=0 then 'If we start out w/o analysis, set some defaults but still set #filt.doFilt filterPeakMarkID$="P+" x1DBDown=3 : x2DBDown=0 end if #filt.doFilt, "set" 'Assume we will be doing the analysis print #filt.db1, str$(x1DBDown) 'Display existing values for db points print #filt.db2, str$(x2DBDown) if filterPeakMarkID$="" then filterPeakMarkID$="P+" #filt.peakMark, "select ";filterPeakMarkID$ 'Select the current or default reference marker #filt.peakMark, "setfocus" #filt.db1, "!setfocus" wait 'If the user double clicks on the menu when invoking this routine, the second click can be 'interpreted by LB as a click on the graph, so it will call [LeftButDown]. But it doesn't do 'so until it gets into this routine, at which point the real [LeftButDown] is hidden. So 'we provide one here that just exits. [LeftButDown] goto [Cancel] [filtNOP] wait [filtCancel] close #filt exit sub [filtFinished] 'Window is closing or OK was clicked 'Note that if #filt.doFilt is reset, indicating no filter analysis, we exit immediately and never get 'to here. Therefore, we know here that we want to do filter analysis #filt.doFilt, "value? doFilt$" 'ver114-7d if doFilt$="set" then doFilterAnalysis=1 else doFilterAnalysis=0 'ver114-7d 'Filter analysis will use many markers, so we can't have other automatic uses of the markers if doFilterAnalysis=1 then doLRRelativeTo$="" 'turn off auto locating of L and R 'ver114-7d #filt.peakMark, "selection? filterPeakMarkID$" 'selected marker ID for marker at peak if filterPeakMarkID$="" then doFilterAnalysis=0 : close #filt : exit sub 'invalid marker-user typed into combobox 'Get the db values for the x1 and x2 analysis points; force them positive #filt.db1, "!contents? c$" : x1DBDown=val(uCompact$(c$)) : if x1DBDown<0 then x1DBDown=0-x1DBDown #filt.db2, "!contents? c$" : x2DBDown=val(uCompact$(c$)) : if x2DBDown<0 then x2DBDown=0-x2DBDown 'If P+ is the reference marker, we add it if necessary. Other reference markers must already 'exist, because we wouldn't know where to add them if doFilterAnalysis=1 and filterPeakMarkID$="P+" and gMarkerPointNum(mMarkerNum("P+"))<0 then 'ver114-7q saveSel$=selMarkerID$ 'We want to save and restore the current selected marker call mAddMarker "P+", peakPoint, "2" 'place P+ marker on trace 2 call mMarkSelect saveSel$ 'ver114-5L end if close #filt 'If halted, redraw with markers; otherwise wait to end. ver114-7d if haltsweep=0 then call RefreshGraph 0 end sub ' 'ver114-5p added Interpolation Module; ver114-5q moved it to preced config module '====================START INTERPOLATION ROUTINES========================== 'The interpolation module handles linear and cubic interpolation, and deals with the fact 'that LB does not allow arrays as arguments. Three arrays are created: intSrc() contains the 'original data, which we assume for the moment is freq, mag and phase, in ascending order of freq. 'intDest() contains only frequency, and needs its mag and phase determined by interpolation. If 'cubic interpolation is used, the user calls intCreateCubicCoeffTable which fills the third array, 'intSrcCoeff(), with the eight coefficients (4 for mag, 4 for phase) that are needed to apply cubic 'interpolation. 'The user fills intSrc and intDest, calls intCreateCubicCoeffTable if necessary, and then calls 'intSrcToDest, which performs the interpolation. The user then copies the data (rounding as desired) 'from intDest() to the array where the data really belongs. The data in these arrays should not be 'relied on long-term, because another routine may make use of them. 'Angles must be in the range -180 to 180 degrees to interpolate properly. Returned angles may be 'outside that range and must be normalized as desired. 'Variables for interpolation routines dim intSrc(1000, 2), intDest(1000,2) 'Data for InterpolateTableToTable (freq, real, imag) dim intSrcCoeff(1000,7) 'Cubic coefficents (A,B,C,D) for interpolating real and imag parts from intSrc() global intSrcPoints, intDestPoints, intMaxPoints '------------------Data access routines-------------------- 'Even though our data is global, the user should access data only through these routines sub intSetMaxNumPoints maxPoints intMaxPoints=max(intMaxPoints, maxPoints+5) redim intSrc(intMaxPoints,2) : redim intDest(intMaxPoints,2) redim intSrcCoeff(intMaxPoints,7) end sub sub intReset 'Reset arrays and variables intMaxPoints=1000 for i=0 to intMaxPoints intSrc(i,0)=0:intSrc(i,1)=0:intSrc(i,2)=0 intDest(i,0)=0:intDest(i,1)=0:intDest(i,2)=0 next i intSrcPoints=0 intDestPoints=0 end sub sub intClearSrc 'Set source table to zero entries intSrcPoints=0 end sub sub intClearDest 'Set destination table to zero entries intDestPoints=0 end sub sub intAddSrcEntry f, r, im 'Add entry to end of source table 'f=frequency, r=real part, im=imaginary part intSrcPoints=intSrcPoints+1 intSrc(intSrcPoints,0)=f intSrc(intSrcPoints,1)=r intSrc(intSrcPoints,2)=im end sub sub intAddDestFreq f 'Add new frequency to end of destination table intDestPoints=intDestPoints+1 intDest(intDestPoints,0)=f end sub sub intGetSrc num, byRef f, byRef r, byRef im 'Get values for source entry number num (1...) 'f=frequency, r=real part, im=imaginary part f=intSrc(num,0) r=intSrc(num,1) im=intSrc(num,2) end sub function intSrcFreq(num) 'Get frequency for source entry number num (1...) intSrcFreq=intSrc(num,0) end function sub intGetDest num, byRef f, byRef r, byRef im 'Get values for dest entry number num (1...) 'f=frequency, r=real part, im=imaginary part f=intDest(num,0) r=intDest(num,1) im=intDest(num,2) end sub function intDestFreq(num) 'Get frequency for dest entry number num (1...) intDestFreq=intDest(num,0) end function function intMaxEntries() 'Get maximum number of entries intMaxEntries=intMaxPoints end function function intSrcEntries() 'Get number of steps in source table intSrcEntries=intSrcPoints end function function intDestEntries() 'Get number of steps in destination table intDestEntries=intDestPoints end function '------------------End Data access routines-------------------- '------------------Start Interpolation routines-------------------- function intLinearInterpolateDegrees(fract, v1, v2) 'linearly interpolate between phase v1 and v2 based on fract 'fract is a proportion (0...1) representing how far from v1 to v2 we want to go. The complication with 'phase is that it wraps around at 180 or 360 degrees. If abs(v2-v1)>180, we will assume that such wrap-around occurred. 'This works when the real phase shift from point to point is normally small. dif=v2-v1 : if dif<0 then absDif=0-dif else absDif=dif if absDif<=180 then intLinearInterpolateDegrees=v1+fract*dif else 'Apparent shift is more than 180 degrees, which means wrap occurred between v1 and v2. 'We shift v1 360 degrees towards v2 which reduces the magnitude of dif by 360. if dif>0 then dif=dif-360 else dif=dif+360 intLinearInterpolateDegrees=v1+fract*dif 'At this point, interp may be outside the bounds of the scaling of v1 and v2. The user must 'adjust the result end if end function sub intLinearInterpolation freq, isPolar, f1,R1,I1,f2,R2,I2,byref p1, byref p2 ' linearly interpolate between points 1 and 2 (each a frequency with complex value) ' freq=frequency for which value is to be determined ' This function will return the interpolated value for the real and imaginary parts ' in p1 and p2, respectively 'Interpolated angles may end up outside the original bounds of the angles, if wrap-around occurred, 'so the user should put them back in bounds. They will be at most 360 degress out-out-bounds. fSpan=f2-f1 'If we are interpolating between identical entries, just use data from the first if fSpan=0 then p1=R1:p2=I1:exit sub ratio=(freq-f1)/fSpan 'Interpolation ratio p1=R1+ratio*(R2-R1) dif=I2-I1 if isPolar=1 then 'We are interpolating polar data, so what we are labeling as the imaginary part 'is really the angle in degrees. if dif<0 then absDif=0-dif else absDif=dif if absDif<=180 then p2=I1+ratio*dif else 'Apparent shift is more than 180 degrees, which means wrap occurred between v1 and v2. 'We shift v1 360 degrees towards v2 which reduces the magnitude of dif by 360. if dif>0 then dif=dif-360 else dif=dif+360 p2=I1+ratio*dif 'At this point, p2 may be outside the bounds of the scaling of v1 and v2. The user must 'adjust the result end if else p2=I1+ratio*dif end if end sub sub intCreateCubicCoeffTable doPart1, doPart2, isAngle, favorFlat 'Create table of cubic coefficients intSrc() in intCubicCoeff 'We separately calculate for the specified parts of srcInt. If isAngle=1 then part2 is an angle. 'We pass favorFlat on to intCalcCubicCoeff, except if part2 is an angle we pass on favorFlat=1 for that part. 'Each entry of the cubic coefficient table will have 4 numbers. 0-3 are the A,B,C,D 'coefficients for interpolating the frequency power correction, which is a scalar. 'Angles must be in the range -180<=angle<=180 for i=1 to intSrcPoints if doPart1=0 then A=0 : B=0 : C=0 : D=0 else partNum=1 : partIsAngle=0 call intCalcCubicCoeff i,partNum,partIsAngle,favorFlat,A,B,C,D end if intSrcCoeff(i,0)=A :intSrcCoeff(i,1)=B intSrcCoeff(i,2)=C :intSrcCoeff(i,3)=D 'For an angle, specify to "favor flat", because 'we expect the phase not to approach vertical if doPart2=0 then A=0 : B=0 : C=0 : D=0 else partNum=2 : partIsAngle=isAngle if isAngle then doFlat=1 else doFlat=favorFlat call intCalcCubicCoeff i,partNum,partIsAngle,doFlat,A,B,C,D end if intSrcCoeff(i,4)=A :intSrcCoeff(i,5)=B intSrcCoeff(i,6)=C :intSrcCoeff(i,7)=D next i end sub sub intCalcCubicCoeff pointNum, partNum, isAngle, favorFlat,byref A,byref B,byref C,byref D 'Calculate the cubic interpolation coefficients to apply to a point 'lying between (possibly including) points pointNum-1 and pointNum of intSrc(). 'partNum=1 to process real part and =2 to process imag part. 'If isAngle=1 then we are interpolating an angle, otherwise not. 'The coefficients will approximate y values in the interval from pointNum-1 to pointNum 'as a cubic equation, such that it passes through the endpoints with the desired slope. 'To determine the desired slope, we use the points to the left and right of the interval. 'This gives us four points, 0-3, of which pointNum is number 2. The interval in which data 'will be interpolated with these coefficients is from point 1 to point 2. We determine what ' slopes we want at the endpoints and then fit a cubic equation to the interval. In ' general, at each point we want the curve on each side to have a common slope equal ' to some sort of average of the interval slopes on each side. We do a straight ' arithmetic average, except that if favorFlat=1 then we average the inverses of the ' slopes and invert that average. The latter tends to make the averaged slope flatter, ' which is useful to avoid overshoot/undershoot. ' Assume the cubic function ' y=A + B(x-x2) + C(x-x2)^2 + D(x-x2)^3 ' passes through points (x1, y1) and (x2, y2), with f12 then x0=intSrc(pointNum-2,0) : y0=intSrc(pointNum-2,partNum) if pointNum180 then 'large difference between points 2 and 3 if dif23>0 then dif23=dif23-360 else dif23=dif23+360 'reduce magnitude of difference by 360 end if end if if absDif12>180 then 'large difference between points 1 and 2 if dif12>0 then dif12=dif12-360 else dif12=dif12+360 'reduce magnitude of difference by 360 end if if pointNum>2 then 'true if we have point 0 if dif01<0 then absDif01=0-dif01 else absDif01=dif01 if absDif01>180 then 'large difference between points 0 and 1 if dif01>0 then dif01=dif01-360 else dif01=dif01+360 'reduce magnitude of difference by 360 end if end if end if '(4) Find m1, the desired slope of the cubic at point 1 if pointNum>2 then if x0=x1 then inSlope=0 'should not happen else inSlope=dif01/(x1-x0) 'slope from point 0 to point 1 end if else inSlope=dif12/(x2-x1) 'slope from point 1 to point 2 end if outSlope=dif12/(x2-x1) 'slope from point 1 to point 2 prod=inSlope*outSlope if prod <=0 then 'if slope on either side is zero, or is positive on one side 'and negative on the other, we want a zero slope m1= 0 else 'Calculate an average slope for point 1 based on connecting lines 'We average the inverses of the slopes, then invert m1= 2*prod/(inSlope+outSlope) end if '(5) Find m2, the desired slope of the cubic at point 2 inSlope=outSlope 'slope from point 1 to point 2 if pointNum= targData. 'if ceil=-1, we will look up that position with binary search. Arrays must be in 'ascending order of x values (usually frequency). 'We use cubic interpolation using the cubic coefficients which must have been 'precalculated in intSrcCoeff() if ceil=-1 then ceil=intBinarySearch(targData) 'search intSrc() to get ceil 'ceil now is the first entry >= magdata, except that if no entry meets that test, 'ceil will be one past the end. v1=0 :v2=0 if ceil>intSrcPoints then 'Off top end;use values for final intSrc() entry v1=intSrc(intSrcPoints,1) v2=intSrc(intSrcPoints,2) exit sub end if if ceil=1 then 'Off bottom end;use mag and phase correction for smallest ADC entry v1=intSrc(1,1) v2=intSrc(1,2) exit sub end if 'Evaluate cubic at x=targData dif=targData-intSrc(ceil,0) A=intSrcCoeff(ceil,0) : B=intSrcCoeff(ceil,1) C=intSrcCoeff(ceil,2) : D=intSrcCoeff(ceil,3) v1 = A+dif*(B+dif*(C+dif*D)) if wantV2=1 then A=intSrcCoeff(ceil,4) : B=intSrcCoeff(ceil,5) C=intSrcCoeff(ceil,6) : D=intSrcCoeff(ceil,7) v2 = A+dif*(B+dif*(C+dif*D)) 'TO DO--caller must put phase in proper range end if end sub function intBinarySearch(searchVal) 'Perform search of intSrc() to find the lowest entry whose lookup value is >=searchVal 'If dataType=0 then the lookup is for ADC value in calMagTable; otherwise it is for freq in in calFreqTable 'If searchVal is beyond the highest entry, we will return intSrcPoints+1 top=intSrcPoints bot=1 span=top-bot+1 while span>4 'Do preliminary search to narrow the search area halfSpan=int(span/2) mid=bot+halfSpan thisVal=intSrc(mid,0) if thisVal=searchVal then intBinarySearch=mid : exit function 'exact hit if thisVal= entry bot-1 but <= entry top, and we have a span of less than 4 'Start with bot entry and find first entry >= searchVal ceil=bot thisVal=intSrc(ceil,0) if thisVal>=searchVal then intBinarySearch=ceil : exit function ceil=ceil+1 : if ceil>intSrcPoints then intBinarySearch=ceil : exit function thisVal=intSrc(ceil,0) if thisVal>=searchVal then intBinarySearch=ceil : exit function ceil=ceil+1 : if ceil>intSrcPoints then intBinarySearch=ceil : exit function thisVal=intSrc(ceil,0) if thisVal>=searchVal then intBinarySearch=ceil : exit function intBinarySearch=ceil+1 'searchVal is off the top of the table end function sub intSrcToDest isPolar, interpMode, params, favorFlat 'Creates a table of frequency vs. complex numbers by interpolating from another table. 'isPolar=1 if data is in polar form; otherwise 0 'interpMode=0 for linear interpolation; interpMode=1 for cubic interpolation 'params=1 means process real part only; params=2 means imag only; params=3 means both parts 'This is used to create the tables used for calibration. We may have measured data for the 'calibration standards, which may not be at the specific frequencies needed. We may also have 'already calculated the OSL coefficients, but not at the current frequency steps. This is 'used to convert such data into data at the exact frequencies of the current scan. 'Since LB does not allow arrays as arguments, this has to be done with two fixed arrays. 'The original array is intSrc(step, data); the final is intDest(step, data), 'where step is the index for the entry number (0 is not used) and data is the index for 'the table data, which consists of frequency (0), real (1) and imaginary (2). (The actual 'labels "step" and "data" are not used.) 'intDest must be pre-filled with the desired frequencies, and intDestSteps must contain 'the number of frequency entries in intDest. 'intSrcSteps must contain the number of entries in intSrc. 'Everything is written in terms of the data being real and imaginary, but it could instead 'be magnitude and angle. Different results are obtained using the different formats; the 'difference is small if the changes in the data from step to step are small, as they normally 'should be. The complication of interpolating in polar format is that the angle wraps around 'at +/- 180 degrees. If interpolating half way between -178 and +178, we don't want to get 0. 'Therefore, if isPolar=1, if the angle difference between two successive points exceeds 180, we 'assume a wrap-around occurred. 'For cubic interpolation, CalcCubicSlopes must be called whenever intSrc data is changed. 'Any angles we actually interpolate will be put into in the range -180srcF1 then exit for currDestPoint=i intDest(i,1)=intSrc(1,1) 'Directly transfer value from first entry intDest(i,2)=intSrc(1,2) next i if currDestPoint=intDestPoints then wait 'We have processed all points in intDest() currDestPoint=currDestPoint+1 'The next intDest() point to process 'As long as we are within the bounds of intSrc, 'interpolate to get the cal data for each step frequency. ceil=1 'This will become the step number of the first intSrc() freq 'greater than or equal to the then current intDest() frequency. for i=currDestPoint to intDestPoints destF=intDest(i,0) 'current step frequency 'Move through intSrc() until we hit a frequency >= this intDest() frequency. while destF>intSrc(ceil,0) ceil=ceil+1 'move to next point in intSrc() if ceil>intSrcPoints then exit while 'ran off end of source table wend if ceil>intSrcPoints then exit for 'ran off end 'Here ceil is the first baseLine step with a frequency>= our target step freq. 'So we interpolate between points ceil-1 and ceil. srcF1=intSrc(ceil-1,0) 'low entry in src table : freq, mag and phase srcMag1=intSrc(ceil-1,1) srcPhase1=intSrc(ceil-1,2) srcF2=intSrc(ceil,0) 'high entry in src table : freq, mag and phase srcMag2=intSrc(ceil,1) srcPhase2=intSrc(ceil,2) 'Do the interpolation 'TO DO--Be sure phase range is correct if interpMode=0 then call intLinearInterpolation destF, isPolar, srcF1, srcMag1, srcPhase1, srcF2, srcMag2, srcPhase2,v1, v2 else wantV2=1 call intCubicInterpolation destF, ceil, wantV2, v1, v2 'find v1, v2 by cubic interpolation end if currDestPoint=i 'Record that we have this step taken care of intDest(i,1)=v1 'Enter results in intDest; x value is already there if isPolar then if v2>180 then v2=v2-360 else if v2<=-180 then v2=v2+360 'put into range -180