'spectrumanalyzer.bas, version G, 7-26-2010 'Created from version 115-9e 'Reason for change: '------------Changes and additions ------------ '115-9e ' Change Revision to G ' When resizing window, don't require restart if sweep is not in progress. ' Fix display of Initial Cal Manager in non-VNA modes 'Note: 115-9d was released as Revision F '115-9d ' Add routines for front-end adjustments of SA readings. ' Fix saving of reflection Test Setups to include R0 '115-9c ' Change Revision to F. ' Adjust Zoom in crystal analysis. ' Change crystal Cm to fF and Lm to mH 'Note: 115-9b was released as Revision E. '115-9b ' Change Revision to E. ' Add uFileOrFolderExists to determine file/folder existence. Not yet used anywhere. ' Fix typo regarding call to ActualSignalFrequency() ' Fix calBinarySearch when search value is beyond the top end of the table ' delete old subroutines [ReadAD16Status][ReadAD22Status] ' replace with new [ReadAD16Status][Read16wOrigCB][Read16wSlimCB][ReadAD22Status][Read22wOrigCB][Read22wSlimCB] 'Note 115-9a was released as Revision D. '115-9a ' Fix max 2000 steps for multiscan ' Add ability to change title in multiscan ' Multiscan: put red box in upper right of current window. ' Don't allow multiscan in SA mode when tracking generator is on (SA with TG mode). '115-8d ' Add Skip and Close All menus to multiscan ' Make multi-scan windows the same size as the main window. ' Various improvements to multi-scanning ' When restart is needed after changing sweep params, do [PartialRestart] rather than RequireRestart. ' When opening sweep params or Y-axis windows, halt if sweep is in progress. ' Delete unused global for centerstep '115-8c ' Fix caption when loading preferences ' Revise method of loading preferences ' Create suppressHardwareInitOnRestart so hardware initialization can be skipped on Restart or PartialRestart, ' to speed it up in certain circumstances, such as when loading data files. ' Provide for preference data as a header when saving or loading data files. ' Add multiscan module '115-8b ' Change to Revision D ' Add group delay function ' Fix uRoundDownToPower for negative numbers ' Make ideal Open have 35 fF fringe capacitance. ' Fix loading of debug files so S21DataArray and ReflectArray get filled. 'Note: 115-8a was released as Revision C '115-8a ' Make delay in OSL standards decrease the reflection angle, not increase it. '115-7a ' Set msaRevision$ to C. ' Allow reference lines to exist even when no trace is actually selected. ' Enable smith chart to draw small circles at each point ' Eliminate accumulation of trace draw commands for Smith chart; they weren't used anyway ' Tweak procedure for saving images ' Print R0 and length in RLC dialog window without using the "m" suffix ' Fixes to reference lines. Among other things, they could come out on the wrong axes. ' Change preset OSL standards to keep them in files ' In calculating refco of cal standards, use ReflectArray for the frequency 'Note: 115-6d was released as version 115, Rev B. '115-6d ' When displaying marker info for the selected marker, also show reference values for that marker as a message '115-6c ' Add suppressHardware flag to suppress all port operations, to make it easier to run without hardware. ' Check for ntport and zntport on startup to see whether to set suppressHardware '115-6b ' Draw reference line on Smith chart. ' Replace the buggy filedialog with API calls to open and save files. '115-6a ' Add File menu item to save data ' Change header info for Data Window Graph Data, S11 and S21 to use Title. '115-5g ' Add Rescan button to Crystal Analysis. '115-5f ' Fix revision number ' Impose max Q of 100000 in RLC dialog. Change transmission mode RLC instructions. ' Fix resistance display in reflection RLC to display correct point. ' Fix Generate S21 so dB appears on primary axis. ' Add ability to load data files. 'Note: 115-5e was released as Version 115, Rev A. '115-5e ' Fix ComponentGetValue to access S21DataArray properly--Same fix as 115-5c1 ' In Component Meter, print huge Q values as 300+ '115-5d ' Impose 0.001 ohm minimum magnitude for series/parallel resistance/reactance ' Fix data window phase display ' In ProcessOSLCal, don't apply shunt connector delay when doing full OSL ' Add routines to convert S11 to S21, in shunt or series fixture. ' Fix: Reflection RLC was printing series R even for parallel RLC ' Add function Generate S21 in Reflection mode to simulate S21 values from current impedances ' Add routines to hide/show menus ' When changing modes, simply hide/show appropriate menu items, rather than closing and ' recreating the entire window. Also, don't always clear markers and references. ' In reflection RLC analysis, show results with Rp, Lp, Cp, etc. instead of just R, L, C. ' Enable References menu item for debugging purposes. ' Create uBringWindowToFront so Smith Chart can be brought to front to copy bitmap. ' When showing reference lines, print "Ref" above axis in same color as the line. For ' fixed value reference, also print that value. 'NOTE: 115-5c was privately labeled version 115, Rev 0.2 '115-5c ' Divide crystal analysis and transmission mode RLC analysis into two separate routines. ' Create mechanism for zooming to Fs in crystal analysis, converting the existing band cal ' to a base cal, and restoring when done. Also use it for Component Meter to save/restore ' previous sweep settings. ' In crystal analysis, when phase is available, use zero phase or reactance to identify Fs ' more precisely, which is helpful for relatively coarse scans. ' Fix bug that crashed crystal analysis help window. ' Hide connector delay when opening Reflection cal window unless Shunt is selected. '115-5b ' Fix display of magpower in Variables window by widening the field. ' Fixes to Component Meter for reflection mode. ' Enable Component Meter in reflection mode. ' Change color of calibration and Reference To windows to gray; blue sometimes affect an underlying window. ' Change [PerformOSLCal] so it returns rather than waits. ' 'NOTE: 115-5a was privately labeled version 115, Rev 0.1 '115-5a ' Change RLC spec so series resistance will be made zero if L or C is specified but R is not. ' Fix to parallel RLC when no R is specified. ' Don't force S21JigAttach$ to "Series" when doing doSpecialGraph=5 ' When changing modes by menu, start Transmission with Series fixture and Reflection with bridge. ' Eliminate reference to #VNAcal.Delay in [BandLineCal] by storing the delay value in lineCalThroughDelay ' Change revision number to 0.1 'NOTE: 115-4k is the released version 115, Rev0 '115-4k ' Modify RLC Spec help window. ' Change spacing of setup info to compact it. ' Undo forcing reflection jig to Bridge when plane extension is attempted ' Reduce size of area cleared when refreshing grid to avoid impacting labels. ' Add revision number to Graph Window '115-4j ' Change color of RLC Spec dialog ' Ignore S21JigShuntDelay in uRLCComboResponse ' For series RLC spec, if no resistor specified, use large value. ' Fixes to interaction of calibration and simulated data. ' Provide notice when plane extension can't be done because of fixture type. ' For doSpecialGraph data, force jig to bridge in reflection and series in transmsission mode. ' If divide by zero error in calculating OSL, nullify the calibration '115-4i ' In Custom OSL, start out with most recently used values. ' Eliminate wait in intSrcToDest. '115-4h ' Add Graph Data to Data menu in all modes. '115-4g ' Fix to delay in Through connection for Line Cal. ' Add SA+TG to Build Level 3 (VNA) ' Fix SA graph on startup when primary axis is changed. ' Allow spur test in all modes '115-4f ' Fix insertion loss in Filter Analysis ' Separate spur test checkbox from its text ' Fix to allow entry to Reflection mode ' Create SA+TG mode. Eliminate SG/TG button. The new mode still uses msaMode$="SA", but also has gentrk=1. '115-4e ' In Component Meter, print values in Red if outside range of best accuracy. ' For doSpecialGraph<>0, when calibrating force mag and phase to zero. ' For series fixture with RLC simulation; ignore RLC if a coax is specified. ' Rename uInvert, uSqrt, uDivide and uMultiply to cxInvert, cxSqrt, cxDivide and cxMultiply ' Create format option SuppressMilli to avoid the "m" suffix; primarily for resistances/impedances ' Change most "3,2,4" formats to "3,3,4" to allow third decimal place if only one whole digit ' Stick modes got deleted on Restart; fixed by adding call to ImplementDisplayModes ' In Filter Analysis, changed db to dB. ' Fixes to SNA mode. '115-4d ' delete Change PDM button in SA mode ' changes to avoid math overflow ' Save magnitude to 5 decimal places ' Modify RLC dialog so in transmission mode, coax is always available but termination applies only ' to shunt fixture. ' Add routines to calculate S21 of lossy transmission lines, for use with series fixture. ' Fix typo relating to angle interpolation on graph Y2 value ' Rearrange Data Windows '115-4c ' In SA mode for doSpecialGraph=5, graph the fundamental and harmonics of a square wave. ' Change Analysis menu to Functions; change some names to append "Analysis" ' Change Component Measure window to Component Meter ' Save mag data to 5 decimals--needed for calculated S11 values of pure capacitance/inductance '115-4b ' Add new entries to coax table ' Fix bad variable name in LossyImpedToParallelLC ' Tweaks to RLC analysis and RLC dialog. ' Mods and additions to coax analysis modules. ' Save preference items for RLC spec. ' Create Coax Analysis ' Print warning message if step size exceeds RBW in SA mode. '115-4a ' Make the guts of crystal anlysis into subroutine; make crystalCancel a label within it. ' Add menu item for RLC analysis, using the crystal analysis routines as the core, with ' some modifications. ' Change Frequency Mode to Frequency Band in sweep parameters window. ' Add white ForegroundColor$ to Title window. ' Fix to doSpecialGraph=5; Fix to uRLCComboResponse ' Add a new RLC analysis to Reflection mode, that uses reactance and its slope. ' Add data types and calculations for admittance mag and angle, conductance and susceptance, but don't let user choose graphs for them. ' Fix startup so preference file is created if there is none. ' Add auxGraphData() and related items to hold graph data generated by analysis routines, such as Q analysis ' Add routines to do Q analysis. ' Change all references to pi to use uPi() ' Add routines to read files with coax data ' Add module for complex math functions ' Change minimum wait time in calibrations to 110 ms. ' Hide Fixture Type items when doing full OSL calibration. ' Changes and fixes to uRLCComboResponse and RLCDialog ' Consolidate some data window items into one window ' Rename TG Transmission mode as SNA Transmission mode '115-3f ' Add dummy parameter to sub crystalCancel. ' Fix marker info on Smith Chart when at an integral point. ' Fix OSL cal so if Done is pushed when no cal is done, the buttons aren't all disabled. ' Fix calls to [crystalCancel]. should be call crystalCancel dum$ ' Add R0 to crystal window. Also shunt/series, but that is temorarily hidden. ' Add doLRAbsolute to indicate that L and R markers are placed around another marker at absolute ' values, not relative values. This is for marking bandstop -3 dB points, which are actually at -3 dB, ' but located around P- marker. Note user has no way to set this flag; it is internal ' Disable reference line menu item for now. '115-3e ' When quitting Measure Components, set applyCalLevel=0 to nullify the calibration ' Adust inductor measurement ranges ' Check for negative L or C as a sign of self-resonance. ' Changes to Component Measure Help '115-3d ' In Component Measuring, make use of phase info if available, especially to separate series resistance out ' of inductor inductance. Without that, the loss in inductors makes inductor measurement fairly inaccurate. ' Fill in frequency ranges for measuring inductors, based on tests with the series fixture. '115-3c ' For Dark and Light presets, make trace colors depend on primary axis. ' Create [PartialReset] to implement changes but return before taking data. '115-3b ' cleanup regarding magdisp and phadisp ' Enable right axis graph for SA and ScalarTrans modes. Allow "none" for each axis. ' Fix formatting of numbers that come out to 1000 x, where x is a multiplier character ' Define a primary axis, to be listed first for marker info and to allow histograms, and to have mag when mode is changed. ' Change gFindDBOffset,gPeakAnalysis, crystal analysis and component measuring to be able to use either trace ' Clear markers at start of crystal analysis and component measuring ' Change phaDisp to Y1DisplayMode and magdisp to Y2DisplayMode; change related terms. Done by global search/replace ' Change variables using "ComponentConst" in their names to use "DataType" instead, by global search/replace '115-3a ' 'TO DO--track down failure to redraw axis in auto scale ' Disable buttons on OSL cal when finishing, so they don't get clicked before dialog closes. ' Remove some DEBUG commands. ' 'TO DO??--Should save both band and base contexts in test setups, separated by !End Context ' When loading, set desiredCalLevel to 2 if there is band cal ' Change smith chart interpolation of displayed data to match regular graph ' Fix to interpolation of graph value angles to keep original value if it can't be put in the graph bounds. ' Rearrange axisYDisplayPreference so certain actions are taken immediately when the graph type changes, ' and the axis range is reprinted in the proper format. ' Change SaneLimits to StartingLimits, to apply to Y axis range when graph type is changed. Generally start ' with standard values. ' Fix FilterDataType to use constNoGraph instead of 0. '115-2d ' Fix display of impedance on Smith chart ' Round marker clicks to integral step only in SA mode. ' Add smithDrawConductance and smithDrawReactance. Not used yet. ' Print message when OSL cal is aborted ' Set desiredCalLevel to 2 when OSL is done. ' Fix mysterious OSL bug. When [OSLDone] returned, it sometimes did not return to the place ' that called it. Somehow the stack must get corrupted. [PerformOSL] now does everything that needs ' to be done, so no return is needed and it can just wait. ' Add chr$(10) as terminator in uGetLine$() ' Add file extension before calling uConfirmSave, not after ' Modify plane extension and R0 transform for reflection. ReflectArray now contains extra slots for ' S11 prior to the final adjustment for plane extension and R0 transform, to make recalculation easier. ' Add date/time stamp to installed cal ' Add graphs for percent reflected power and component Q ' Fixes to OSL base cal ' Align data columns in data window ' Don't switch to base cal when saving band cal as base cal. '115-2c ' Clarify Appearances dialog. ' Add a high order digit to angle displays ' Add graph type for None ' Fix Appearances Dialog ' Print frequency range in Smith chart title ' Add R0 in sweep params for reflection ' Fix Smith chart redraw procedure. ' '115-2b ' Add button to recalc graph for changed planeadj in sweep param window. '115-2a ' Add custom color schemes. ' When saving images, go to same folder last used ' Fixes to Reference Lines '115-1i ' Replace Wait timing loop with uSleep function, when waittime exceeds 14 ms. ' Deleted box drawn around outside of marker info. ' In Test Setups, make list respond to single click. ' In Transmission Mode, add graphs for raw power and phase. ' When changing modes other than by menu command, don't initialize variables; they are set by contexts ' Delete setting of prevMSAMode$ when changing modes '115-1h ' Fix typo OSLApplyCalLevel-->applyCalLevel ' Fix marker info display in Smith chart. ' Set font in xtal list window '115-1g ' Revise procedure for saving configurations. Now done as test setups ' Combine Reflection Setup into OSL calibration window ' Suppress display of video filter setting '115-1f ' Work on component measurements module ' Add confirm save to preferences ' When saving, add proper extension if the user has not included one. ' Copied save/load Debug info from 114-7r. ' Change Shunt connector delay adjustment to use S21JigShuntDelay ' Add graphs for impedance mag and angle. '115-1e ' Change base/band cal. All cals when done are band cal. For Line Cal, the user then has the option to save it as ' base cal. ' Add Crystal Analysis. ' Revise Transmission setup. Add Reflection setup. ' Print multiplier char in log sweep next to the frequency w/o a blank. ' Change divide in determination of multipliers for large values. ' Create S21DataArray to hold transmission data, including actual signal frequency for VectorTrans and ScalarTrans modes. ' Add frequency, and impedance mag/angle to ReflectArray ' Fix halting of sweep on save/load prefs. ' Delete items and procedures relating to transform of R0 for transmission mode. ' Change dialog and explanation for reflection setup. ' Complete saving of band OSL as base ' Enhancements to Smith Chart ' Have user confirm saves when saving images to existing file names. '115-1d ' Fix typo applyCal->applyCalLevel ' If phase doesn't fit within display bounds, put in between -180 and 180. ' Change cal procedures so wate time is increased to OSLBaseNumSteps but never decreased. ' Save user's choice of center/span or start/stop as startup value next time dialog is opened. ' Add routine to highlite text box and to Sleep. ' Fix call to gInitGraphRange so it always uses rounded startfreq and endfreq. ' In ResizeArrays, reload cal only if arrays are actually changed. '115-1c ' make globals for initial window height and width and current graph box height and width ' Adjust location of dialogs, which are placed relative to the parent window origin, not the screen origin ' Reduce some checkbox widths; fix linear/log selection ' Require restart when various PLL and DDS errors occur. Initialize errora$ to blank on restart. ' Add FreqMode for 1G, 2G and 3G modes. Graph module contains actual frequency, datatable(x, 1) contains ' the frequency the hardware "thinks" it is tuning to, which is called the equivalent 1G frequency. ' For mode 3G, set LO3=target freq - LO2. 'NOTE 115-1b contained all bug fixes to initial release of Version 114. '115-1b Broaden test for difPhase=180 to include >179 and <-179. ' Enable Reflection Mode ' Add smith chart module ' Change Track Gen Reflection to Track Gen Transmission ' Fix a couple of typos ' Eliminate reflection-related graphs from transmission mode; they are only in reflection mode ' datatable now contains (1)for transmission modes, S21 referenced to S21JigR0; (2)for reflection ' mode, S11 referenced to S11BridgeR0. ' Limit base Line and OSL cal to 2000 steps, so we never have to resize their arrays. ' 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 ' Change desiredLineCalLevel and applyLineCalLevel to desiredCalLevel and applyCalLevel; they apply ' equally to line cal and OSL cal. ' 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. ' 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. ' Change constMaxValue to 1e12, since we don't have to worry about NTPort anymore. ' Create SaneLimits to avoid crazy carryover ranges when data type is changed. ' TO DO--Need to save/restore S21 Jig Attach and R0for base and line cal contexts ' Fix DetectChanges regarding change in data type ' Add uGetParamText$ to retrieve parameters. ' Save/restore S21 Jig Attach and R0 for base and line cal contexts ' Place graph windows items based on actual client area, not estimate. ' Add FilterDataType to be sure data types loaded from contexts are valid ' 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 ' Fix bug when no preference file exists or file is bad ' 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/radiobutton 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 '115-1a. Initialize message$ to blank. Fix labeling of shape factor in filter analysis. ' 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. ' 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. ' 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. ' 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 '8d. Add insertion loss, return loss, and SWR graphs. '8c. Misc bug fixes. (also made in 114-7g, beginning a new branch) '8b. Created referenceDoMath and related variables and implemented reference line math. '8a. Change line cal to allow specifying the delay of the through connection and to remove that ' delay from the final cal data. For reference line, add option not to update to current data. '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 global msaVersion$, msaRevision$ 'Version and revision numbers of this release ver115-5f msaVersion$="115" msaRevision$="G" 'ver115-9e '-------------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 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 'ver115-1b '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 global doSpecialRLCSpec$ 'RLC spec for doSpecialGraph global doSpecialCoaxName$ 'Name of coax last used in RLC spec ver115-4b global finalfreq, finalbw 'freq and bandwidth of current final filter global LO2 'actual LO2 frequency ver115-1c global hasVNA '=1 if the build includes VNA; otherwise 0 global hGraphWindow 'Windows handle to the graph window; set when created ver115-5d global hGraphMenuBar 'Windows handle to menu bar in graph window; set when created ver115-5d global hFileMenu, hOptionsMenu,hDataMenu,hFunctionsMenu,hOperatingCalMenu, hMultiscanMenu 'Windows handles to some graph window submenus ver115-5d global menuOperatingCalShowing '=1 when the operating cal menu is shown; otherwise 0 'zero-based index of menu positions in menu bar global menuOptionsPosition, menuDataPosition, menuFunctionsPosition, menuOperatingCalPosition, menuMultiscanPosition 'IDs of various listed menu items that may need to be hidden/shown in certain modes global menuDataS21ID, menuDataLineCalID, menuDataS11ID, menuDataS11DerivedID 'ver115-5d global menuDataLineCalRefID, menuDataLineCalOSLID 'ver115-5d global menuOptionsSmithID 'ver115-5d global menuFunctionsFilterID, menuFunctionsCrystalID, menuFunctionsMeterID, menuFunctionsRLCID 'ver115-5d global menuFunctionsCoaxID,menuFunctionsGenerateS21ID, menuFunctionsGroupDelayID 'ver115-8b 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 global componentWindHndl$ 'Handle to component measurement window global crystalListHndl$ 'Handle to crystal list windows; blank if not open 'ver115-5c deleted crystalWindHndl$ global crystalWindHndl$ 'Handle to crystal window global crystalLastUsedID 'Last ID of crystal added to crystal list global imageSaveLastFolder$ 'Folder in which last graph image was saved, regular or Smith chart ver115-2a dim Appearances$(10) 'Names of Appearances dim customPresetNames$(5) 'User names for custom color presets (1-5) ver115-2a '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 basicGraphWindowWidth 'Different modes may start with different widths; this is the normal width ver115-1c global initialGraphWindowHeight, initialGraphWindowWidth 'Height width at which graph window is originally created 'ver115-1c global currGraphBoxHeight, currGraphBoxWidth 'Actual current height, width, adjusted when resizing 'ver115-1c global clientHeightOffset, clientWidthOffset 'Difference between window size and client area size; set from test window 'ver115-1c global smithLastWindowHeight, smithLastWindowWidth 'Determines size of smith chart; initialized and later adjusted when resizing 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 doLRAbsolute '=1 when LR are placed around another marker, but at an absolute db level ver115-3f global continueCode 'Checked after "scan" command; 0=continue; 1=halt via [Halted]; 2=immediate wait; 3=restart. 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. ver115-1a 'ver114-4k variables allowing forward or reverse sweep 'The following 3 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 componStopAtEnd '=1 to stop component Measure and end of measure sweep. ver115-1f global RefRLCLastNumPoints,RefRLCLastConnect$ 'For continuity calling ReflectionRLC global analyzeQLastNumPoints 'For continuity in AnalyzeQ global GDLastNumPoints 'Number of points last used for group delay analysis global refreshEachScan 'Set/cleared by user to control screen refresh. =1 means refresh each scan. global refreshForceRefresh 'Forces refresh at end of scan even though refreshEachScan=0 global refreshOnHalt 'normally =1 to redraw when we halt. Set to 0 internally for some purposes. '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 'Y1DisplayMode, Y2DisplayMode: 0=off 1=NormErase 2=NormStick 3=HistoErase 4=HistoStick global Y1DisplayMode, Y2DisplayMode 'Type of phase and mag graphing. Made global for sub use. global isStickMode ' =1 when Y1DisplayMode or Y2DisplayMode are in a "stick" mode global specialOneSweep '=1 when [Restart] is called to do one sweep and then return, rather than wait. ver 114-5f global returnBeforeFirstStep '=1 to initialize on Restart and return to caller before taking any data ver115-1d global msaMode$ '=SA, ScalarTrans, VectorTrans, Ref or TwoPort ver114-5L global menuMode$ 'msaMode$ to which the graph window menus currently conform global autoScaleY1, autoScaleY2 '=1 to autoscale the axes global restartTimeStamp$ 'Date/time of last restart global primaryAxisNum '1 or 2, to indicate primary Y axis (e.g. where mag dBm defaults to) ver115-3b 'ver115-1b revised all the graphing constants global Y1DataType 'data component constant to determine Y1 graph data global Y2DataType 'data component constant to determine Y2 graph data 'The following component constants are used to specify the data component needed to graph global constGraphS11DB, constGraphS11Ang, constTheta global constMagDBM,constMagWatts,constMagDB,constMagRatio,constMagV global constRho,constAngle,constRawAngle,constGD,constSerReact,constParReact 'ver115-1b global constSerR,constSerC,constSerL,constParR,constParC,constParL global constSWR, constReturnLoss, constInsertionLoss 'ver114-8d global constImpedMag, constImpedAng 'ver115-1d global constReflectPower, constComponentQ 'ver115-2d global constAdmitMag, constAdmitAng, constConductance, constSusceptance 'ver115-4a global constAux0, constAux1, constAux2, constAux3, constAux4, constAux5 'for auxGraphData(,) ver115-4a global constNoGraph 'ver115-2c used to suppress data 'The following identify slots in ReflectArray() but are not used for graphing. They hold 'S11 prior to the final adjustment for plane extension and graph R0, and are saved to make 'it easier to recalculate S11 when those values change. global constIntermedS11DB, constIntermedS11Ang 'ver115-2d 'The following constant values are used to specify graph data, 'and assigned in such a way that the first ones can be 'used as the index into ReflectArray(), which holds a bunch of pre-calculated values for reflection mode. 'Note if these are changed, FilterDataType may have to be changed. 'ver115-1b altered these 'We start with 1, because entry 0 of ReflectArray is frequency constGraphS11DB=1 'S11 db re S11GraphR0 constGraphS11Ang=2 'S11 angle re S11GraphR0 constRho=3 'S11 data with mag made linear constImpedMag=4 'impedance magnitude (linear, not db) constImpedAng=5 'impedance angle constSerR=6 'Series Resistance constSerReact =7 'Series Reactance constParR=8 'Equiv parallel resistance constParReact=9 'Equiv parallel reactance constSerC=10 'Equiv series capacitance constSerL=11 'Equiv series inductance constParC=12 'Equiv parallel capacitance constParL=13 'Equiv parallel inductance constSWR=14 'SWR constIntermedS11DB=15 'Not a graph item ver115-2d constIntermedS11Ang=16 'Not a graph item ver115-2d 'The above are in ReflectArray(); the below are either not reflection related 'or are other names for reflection data, or negatives of that data. constMagDBM=17 'Magnitude dBM for SA mode constMagWatts=18 'Magnitude watts (linear) for SA mode constMagV=19 'Magnitude volts (linear) for SA mode constMagDB=20 'Magnitude dB for S21 constMagRatio=21 'Magnitude ratio (linear) for S21 constAngle=22 'Angle for S21 constTheta=23 'Theta for reflection constGD=24 'Group Delay for S21 constReturnLoss=25 'Return Loss for reflection ver114-8d constInsertionLoss=26 'Insertion Loss for S21 ver114-8d constReflectPower=27 'Percent reflected power ver115-2d constComponentQ=28 'component Q (not resonance Q) ver115-2d constAdmitMag=29 'ver115-4a constAdmitAng=30 constConductance=31 constSusceptance=32 constRawAngle=33 'Transmission angle without cal adjustment 'constAuxN represent the data in auxGraphData(step, N). They must be consecutively numbered. ver115-4a constAux0=34 constAux1=35 constAux2=36 constAux3=37 constAux4=38 constAux5=39 constNoGraph=40 'Don't graph and don't label the axis dim ReflectArray(800,16) 'Actual signal freq (0),GraphS11DB(1), GraphS11Ang(2),linearMag(3), 'Impedance Mag(4), Impedance Angle(5),Rs(6), Xs(7), Rp(8), ' Xp(9), Cs(10), Ls(11), Cp(12), Lp(13), SWR(14), 'intermedDB(), intermedAng(15) (intermed= w/o R0 transform or plane ext) 'ver115-2d dim uWorkReflectData(16) 'Same data as ReflectArray, but for only one entry 'ver115-1b 'ver115-2d dim S21DataArray(800,2) 'Frequency (actual input freq) (0), mag(1) and phase(2) for VectorTrans and ScalarTrans modes. Freq valid in all modes. dim auxGraphData(800, 5) 'Used to hold specially calculated data, such as from Q analysis, which can be retrieved and graphed. 'auxGraphDataInfo$ Info for UpdateGraphDataFormat for auxGraphData. ver115-4a '(,0) is graph Name, (,1) is formatting string, (,2) is axis label, (,3) is marker label dim auxGraphDataFormatInfo$(5,3) 'auxGraphDataInfo is numeric info about each item in auxGraphData. (,0) is 1 if the data is an angle '(,1) and (,2) are the axis min and max to use as defaults for graphing. dim auxGraphDataInfo(5,2) 'ver115-4a '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 'Constants to specify context types in contextTypes() global constHardware, constGrid, constTrace, constSweep, constMarker, constBand, constBase, constGraphData, constDatatable constHardware=0 : constGrid=1 : constTrace=2 : constSweep=3 : constMarker=4 : constBand=5 constBase=6 : constGraphData=7 : constDatatable=8 'Each entry of calMagCoeffTable() will have 8 numbers. 0-3 are the A,B,C,D 'coefficients for interpolating the real part; 4-7 are for the imag part. dim calMagCoeffTable(100,7) 'SEWcal Cubic coefficients for interpolating in calMagTable moved here by ver115-1d 'calFreqCoeffTable has the A,B,C,D coefficients for interpolating in the calFreqTable() dim calFreqCoeffTable(800,3) 'SEWcal Cubic interpolation coefficients for calFreqTable() moved here by ver115-1d '---Variables relating to touchstone data files--- ver115-5f global touchFreq$, touchForm$, touchRef 'Touchstone format specs global touchFreqMult 'Frequency multiplier corresponding to touchFreq$. E.g. 1e6 for MHZ. global touchBadLine 'Line number of Touchstone file error; zero if no error global dataLoadLastFolder$ 'Folder from which parameter data was last loaded global touchMaxData 'Max data lines in our touchstone files touchMaxData=3000 global touchSParamType$ 'Type of params in sParam: "Reflection" or "Transmission" dim touchComments$(10) 'Up to 10 lines of comments from parameter file. Zero entry not used global touchCommentCount 'Number of comment lines in touchComments$ '---End variables for data files---- '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 'ver115-1b deleted stepfreq global FreqMode '1, 2 or 3, indicating modes 1G, 2G and 3G ver115-1c global sgout 'signal generator output freq when in plain SA mode 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 '=1 when TG is being used (depends on mode); 0 if SG is used or build does not have TG hardware global normrev '=0 if TG is normal, =1 if TG is in reverse. global offset 'TG offset frequency moved ver115-5f 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 ver115-1a global suppressPDMInversion '=1 to suppress inversion in [ReadStep] ver115-1a global leftstep 'Used to hold a marker step number for [preupdatevar] ver115-1a global userFreqPref '0 if user last used Center/Span method; 1 if user last used Start/Stop ver115-1d 'Variables for saving/restoring context files via gosub routines, where these are used as parameters global restoreFileName$, restoreFileHndl$, restoreContext$, restoreIsValidation, restoreErr$,restoreLastLineNum 'ver115-8c 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$ 'msaMode$ global prevPath$ 'Filter path. ver115-1a global prevFreqMode 'frequency mode ver115-1c global prevStartF, prevEndF global prevXIsLinear, prevY1IsLinear, prevY2IsLinear global prevSteps, prevSweepDir, prevAlternate global prevStartY1, prevEndY1 global prevStartY2, prevEndY2 global prevHorDiv, prevVertDiv global prevY1Disp,prevY2Disp global prevGenTrk, prevSpurCheck 'ver114-6k global prevTGOff, prevSGFreq 'ver115-1a global prevPlaneAdj 'ver114-7f global prevY1DataType, prevY2DataType 'ver115-1b deleted source constants 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 'Source and load impedances of Transmission global prevS21JigShuntDelay 'Delay of shunt fixture connector global prevS11BridgeR0, prevS11GraphR0 'Bridge reference and graph reference for S11 'ver114-6k global prevS11JigType$ 'Jig previously used for reflection mode ver115-1b 'Functions may need to redo the sweep with new parameters. The following are used to save/restore the 'pre-existing parameters, using SaveAndChangeSweepParameters and [RestoreSweepParameters] ver115-5c global functSaveAlternate,functSaveSweepDir,functSavePlaneAdj,functSaveWate global functSaveSteps, functSaveStartFreq, functSaveEndFreq global functSaveAutoY1, functSaveAutoY2 global functSaveY1Mode, functSaveY1Mode global functSaveY1DataType, functSaveY2DataType global functSaveXIsLinear, functSaveY1IsLinear, functSaveY2IsLinear global functSaveNumHorDiv, functSaveNumVertDiv global functSaveDesiredCalLevel '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. 'desiredCalLevel is the user-specified level. applyCalLevel is the level we are actually applying global desiredCalLevel, applyCalLevel '2=band Cal (if exists); 1=Base Cal(if exists); 0=None 'We keep track of the parameters for the last cal. Number of steps is set to -1 to indicate no valid cal 'Following are Full Line cal sweep params ver114-5e global bandLineStartFreq, bandLineEndFreq, bandLineNumSteps, bandLineLinear, bandLinePath$, bandLineTimeStamp$ 'Following are Base Line cal sweep params ver114-5e global baseLineStartFreq, baseLineEndFreq, baseLineNumSteps, baseLineLinear, baseLinePath$, baseLineTimeStamp$ global baseLineS21JigAttach$, bandLineS21JigAttach$ 'S21JigAttach$ for applicable cal 'ver115-1B global baseLineS21JigR0, bandLineS21JigR0 'S21 jig R0 for applicable cal ver115-1b global installedBandLineTimeStamp$ 'Time stamp of the band cal that was installed; not when it was installed ver115-2d 'Following are sweep params at which Base Line Cal was last installed ver114-5f global installedBaseLineStartFreq, installedBaseLineEndFreq, installedBaseLineNumSteps global installedBaseLineLinear global installedBaseLineTimeStamp$ 'Time stamp of the base cal that was installed; not when it was installed ver115-2d dim lineCalArray(800,2) 'calibration data for each step#: (0)freq (tuning),(1)magpower during cal,(2)phaseofpdm during cal dim bandLineCal(800,2) 'Bandsweep line calibration data; transferred to lineCalArray when needed ver 114-5f 'Note baseLineCal is fixed sized dim baseLineCal(2000,2) 'Baseline line calibration data; transferred to lineCalArray when needed ver 114-5f '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. The S21 jig is actually used only in reflection mode. 'ver114-6g added these global S21JigAttach$ '"Series" or "Shunt" to indicate the Transmission jig used ver114-6k global S21JigR0 'Source and load impedances of Transmission global S21JigShuntDelay 'One-way delay of connector from shunt fixture through line to the DU, in ns. ver115-1e global S11BridgeR0, S11GraphR0 'Bridge reference and graph reference for S11 'ver114-6k global S11JigType$ '="Trans" if S21Jig is being used for reflection mode; "Reflect" if reflection bridge is used ver115-1b global lineCalThroughDelay 'Delay (ns) of line cal through connection. Used for continuity between lineCal dialog sessions 'and to inform [BandLineCal]. need not be saved as a preference item. '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 DialogQLValue, DialogQCValue 'ver115-4b global DialogCoaxSpecs$, DialogCoaxName$ 'Used to pass values to/from some dialogs ver115-4a 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; 3=use fixed value ver115-5d global referenceTrace 'which ref lines, based on bits: 1 bit=do trace 1; 2 bit=do trace 2; 4 bit=do Smith trace 'ver115-6b global referenceSourceNumPoints 'Number of valid points in referenceSource() dim referenceSource(801,2) 'freq(0), db(1) and angle() of source data for reference lines. First entry is 1 dim referenceTransform(801,2) 'Actual graph data for reference lines Entries are by point number, 1... (not step num) global referenceColor1$, referenceWidth1,referenceColor2$, referenceWidth2 'Reference Trace color and width global referenceColorSmith$, referenceWidthSmith 'color/width for smith chart reference line 'The reference line may be graphed or combined with the scan data. 'The math transform is in the form A*Ref + B*Data, A and B generally being 1 or -1 'Math is done if referenceDoMath=1 or 2; otherwise reference is just graphed. 'If referenceDoMath=1 then math is done on the dBm values that would be graphed with the default graphs. 'referenceDoMath=1 is allowed only for SA mode; too complicated and not very useful for VNA modes, which use calibration instead. 'If referenceDoMath=2 then math is done on the current graph values (e.g. capacitance) global referenceDoMath, referenceOpA, referenceOpB 'ver114-7b dim setupList$(15) 'List of current test setups; used in test setup dialog only '-----OSL cal variables----- 'ver115-1b added the following OSL items global OSLdoneO, OSLdoneS, OSLdoneL 'For communicating with [PerformOSLCal] 'These items are the currently active data for reflection dim OSLa(800,1), OSLb(800,1),OSLc(800,1) 'OSL coefficients a, b, c, at same frequencies as datatable() ver115-1b global OSLApplyFull '=1 if we have OSL coefficients '(In addition, the applicable reference is installed as the current line cal) 'These items are used only during the OSL calibration procedure to calculate coefficients. dim OSLstdOpen(800,1) 'Actual refco of open standard at each step, rho and theta dim OSLstdLoad(800,1) 'Actual refco of load standard at each step, rho and theta. As of ver115-1b this is not used dim OSLstdShort(800,1) 'Actual refco of short standard at each step, rho and theta dim OSLcalOpen(800,1) 'Measured (during cal) open at each step, rho and theta dim OSLcalLoad(800,1) 'Measured (during cal) load at each step, rho and theta dim OSLcalShort(800,1) 'Measured (during cal) short at each step, rho and theta global OSLLastSelectedCalSet 'Standard cal set selected last time dialog was open global OSLOpenCap, OSLOpenDelay 'Capacitance (F) and one-way delay (sec) of Open standard, from last dialog global OSLShortRes, OSLShortInd, OSLShortDelay 'Resistance(ohms), inductance (H) and one-way delay (sec) of Short standard, from last dialog global OSLLoadRes, OSLLoadLC, OSLLoadDelay 'Resistance (ohms) and L or C, and delay of load. ver115-7a global OSLLoadHasCap '=1 if load has capacitance; else 0. Used to interpret OSLLoadLC ver115-7a 'The following hold OSL standard values for moving to and from files ver115-7a added these global OSLfileOpenCap, OSLfileOpenDelay global OSLfileShortRes, OSLfileShortInd, OSLfileShortDelay global OSLfileLoadRes, OSLfileLoadLC, OSLfileLoadDelay global OSLfileLoadHasCap global OSLfileCalSetName$ dim OSLCalSetNames$(10) 'List of OSL cal sets; zero entry is used. Entries correspond to OSLCalSetFileNames ver115-7a dim OSLCalSetFileNames$(10) 'List of OSL cal sets; zero entry is used. redim'd as necessary ver115-7a global OSLCalSetNumber 'Number of entries in list of cal set names and file names ver115-7a 'These items are the result of calibration and allow either base or band cal to be installed 'The OSLBasex arrays are fixed size; the others are expanded as necessary dim OSLBaseA(2000,1), OSLBaseB(2000,1), OSLBaseC(2000,1) 'Base coefficients; used to fill OSLx() dim OSLBandA(800,1), OSLBandB(800,1), OSLBandC(800,1) 'Band coefficients (matches current frequencies) dim OSLBaseRef(2000,2), OSLBandRef(800,2) 'freq(0), db(1) and angle (2, degrees) for OSL ref data to plug into lineCalArray global OSLBaseApplyFull, OSLBandApplyFull '=1 if OSL coefficients are to be used 'We keep track of the parameters for the last cal. Number of steps is set to -1 to indicate no valid cal global OSLError '=1 if math error occurred in calculating OSL coeff; used to nullify the cal ver115-4j global OSLBaseStartFreq, OSLBaseEndFreq, OSLBaseNumSteps, OSLBaseLinear, OSLBasePath$ 'Params for last base OSL calibration global OSLBandStartFreq, OSLBandEndFreq, OSLBandNumSteps, OSLBandLinear, OSLBandPath$ 'Params for last band OSL calibration global OSLBandS11JigType$, OSLBaseS11JigType$ 'Jig type--"Reflect" or "Trans"-- for last cal global OSLBaseS21JigAttach$, OSLBandS21JigAttach$ 'S21 jig for last OSL cal; relevant only if jig type is "Trans" global OSLBaseS11BridgeR0, OSLBandS11BridgeR0 'Bridge R0 for last OSL cal; relevant only if jig type is "Reflect" global OSLBaseS21JigR0, OSLBandS21JigR0 'S21 jig R0 for last OSL cal; relevant only if jig type is "Trans" global OSLBaseTimeStamp$ 'Time stamp for last base open, load, short cal. global OSLBandTimeStamp$ 'Time stamp for last band open, load, short cal. global installedOSLBandTimeStamp$ 'Time stamp of the installed band cal; not when it was installed ver115-2d 'Following are sweep params at which base OSL cal coefficients were last installed global installedOSLBaseStartFreq, installedOSLBaseEndFreq, installedOSLBaseNumSteps global installedOSLBaseLinear global installedOSLBaseTimeStamp$ 'Time stamp of the installed base cal; not when it was installed ver115-2d '-------End OSL cal variables-------' global maxCoaxEntries, numCoaxEntries 'Maximum and actual number of entries in coax data arrays maxCoaxEntries=100 dim coaxNames$(maxCoaxEntries) 'Coax names; 0 entry not used dim coaxData(maxCoaxEntries, 4) 'Coax data: R0(,1), VF(,2), K1(,3), K2(,4) dim RLCDialogCoaxTypes$(maxCoaxEntries+10) 'For RLC specification dialog ver115-4a global 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=1e12 'Max value for RLC components and certain calculations. ver115-1b 'Data is put into datatable() point by point as it is gathered. Its frequency is the 0-1 GHz "equivalent 1G frequency". 'In VectorTrans and ScalarTrans modes, the data is also saved to S21DataArray() with the actual sweep frequency, and if reflection mode convert to S11 and save to ReflectArray() dim datatable(800,3) 'data from most current sweep, (0)thisstep,(1)thisfreq(hardware freq),(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 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; added to raw data 'frontEndCalData is the raw data, freq and dBm, for the current front end. It is interpolated to frontEndCorrection 'on Restart to match the current scan points. It is resized if necessary when a front end file is loaded 'first index is 1-based. For second index: 0=freq; 1=dBm ver115-9d 'The data is the value to be subtracted from the raw power readings. Subtraction is used so a front end file 'can be created by a transmission measurement of the front end, after calibrating with a through connection. dim frontEndCalData(800,1) dim frontEndCorrection(800) 'correction for front end in use for each step in current sweep; subtracted from raw data global frontEndCalNumPoints 'Number of valid points in frontEndCalData global frontEndActiveFilePath$ 'Path name for active front end file. Only relevant in SA modes.ver115-9c global frontEndLastFolder$ 'path to Last folder from which front end was loaded 'ver114-2d combined config arrays into one, and deleted configarray dim cmdallarray(800,39) '(0-15)DDS1+DDS3, (16-39)PLL1+DDS1+PLL3+DDS3 global suppressHardware '=1 to suppress hardware operations, otherwise 0 'ver115-6c global suppressHardwareInitOnRestart '=1 to skip hardware re-initialization to speed up Restart. global wantHardwareInitOnPartialRestart '=1 to do hardware init on [PartialRestart], which we normally don't do '-------Items for multi-scanning----------- ver115-8c 'In SA mode only, it is possible to rotate through several different scan settings; this 'is called multi-scanning. One sweep is completed with one setting, then we move to the next. 'When one is completed, its graphic is displayed in its own window. 'The settings are saved, as is the datatable info. The datatable info for a scan can be reloaded 'into the main window when scanning is stopped. 'Multiscan entries are numbered from 1 through multiscanMaxNum 'Entry zero is info for the main graph. global multiscanCurrNum 'Current entry number global multiscanMaxNum 'Maximum entry number global multiscanIsOpen '=1 when multiscan windows are open, even if scan not in progress. global multiscanInProgress '=1 when actually scanning in multiscan mode global multiscanHaltAtEnd 'set to non-zero during multiscan to cause halt at end, value depends on window selected global multiscanSaveRefreshEachScan 'Saves for restoration when quitting multiscan multiscanMaxNum=4 'This is fixed 'This array holds the context strings for the multiscan entries 'Blank for grid context means this entry is not to be used 'Zero entry of first index not used dim multiscanContexts$(multiscanMaxNum, 3) 'second index= grid(0), trace(1), sweep(2), marker(3) 'multiscanDBM holds the magnitude in dBm for each multiscan entry. Main graph is entry 0. '2000 steps are allowed for each entry, so the second index for entry N 'runs from 2001*N to 2001*(N+1)-1 'multiscanRefData holds reference data arranged similarly dim multiscanTitles$(multiscanMaxNum, 4) 'Four title lines for each multiscan entry ver115-9a dim multiscanDBM((multiscanMaxNum+1)*2001) 'Reference data is always to be added/subtracted with graph data, based on the math type dim multiscanRefData((multiscanMaxNum+1)*2001) 'The only reference type allowed in multiscans is reference math with data: the reference 'data and current data are added or subtracted based on two values OpA and OpB, which are each '1 or -1 (see referenceDoMath), but are zero if reference is not to be used. 'OpA for entry N is at 2*N. OpB is at 2*N+1. dim multiscanRefOps((multiscanMaxNum+1)*2) dim multiscanGraphHandles$(multiscanMaxNum) 'LB handles to the graphics box for each multiscan; blank if inactive dim multiscanWindowHandlesLB$(multiscanMaxNum) 'LB handles to windows for each multiscan; blank if inactive dim multiscanWindowHandlesWind(multiscanMaxNum) 'Windows handles to windows for each multiscan global multiscanMainWidth, multiscanMainHeight 'Dimensions of main graph box when multiscan was started global multiscanWindowsPosition, multiscanSettingsPosition 'positions of multiscan windows that need to be hidden/shown global multiscanControlPosition multiscanControlPosition=0 multiscanWindowsPosition=1 'Windows menu is number 1, indexed from 0 multiscanSettingsPosition=2 'Settings menu is number 2, indexed from 0 dim multiscanMenuBarHandles(multiscanMaxNum) 'Windows handles to menu bar for each scan dim multiscanWindowsMenuHandles(multiscanMaxNum) 'Windows handles to "Windows" menu for each scan dim multiscanSettingsMenuHandles(multiscanMaxNum) 'Windows handles to "Settings" menu for each scan dim multiscanControlMenuHandles(multiscanMaxNum) 'Windows handles to "Control" menu for each scan dim multiscanSkip(multiscanMaxNum) '=1 to skip this graph when scanning '-------End Items for multi-scanning----------- '---------------END OF VARIABLES DECLARATIONS------- nomainwin 'Suppress parallel port if we don't have the DLLs if uVerifyDLL("ntport") then suppressHardware=0 else suppressHardware=1 interpolateMarkerClicks=0 'Note user has no way to change this ver115-1a steps = 400 globalSteps=400 'SEWgraph call gSetNumDynamicSteps steps 'ver114-1f graphBox$="" 'ver115-1a 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 call calInitFirstUse 201, 1001, hasVNA 'Initialize Mag/Freq Calibration Module--201 max mag cal points; 1001 max freq cal points ver114-4b ' S21JigR0=12.5 ' call uCrystalParameters 20.015627, 20.07, -1.97, 20.016655, 20.018711, Rm, Cm, Lm, Cp ' print Rm; " ";Lm; " ";Cm; " ";Cp 'DEBUGGING '----------------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 'Will quit program when finished 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 ver115-1a 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 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 '-----Load or create coax data file----- call LoadCoaxDataFile 'ver115-4a '--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 [LoadPreferenceFile] doingInitialization=1 'ver114-3f suppressHardwareInitOnRestart=0 'Normally we do hardware initialization on each restart. refreshOnHalt=1 'We normally redraw the graph when we halt. multiscanIsOpen=0 multiscanInProgress=0 message$="" 'ver115-1a msaMode$="SA" 'ver115-3b planeadj=0 'ver114-4i gentrk=0 : normrev=0 : sweepDir=1 'ver 114-4k refreshEachScan=1 'ver114-3f call SelectVideoFilter "Wide" 'ver114-5p returnBeforeFirstStep=0 'ver115-1d specialOneSweep=0 'ver115-1d crystalLastUsedID=0 imageSaveLastFolder$=DefaultDir$ 'Folder in which image was last saved ver115-2a touchLastFolder$=DefaultDir$ 'Folder from which param data was last loaded ver115-5f doSpecialRLCSpec$="RLC[P, R1000,C1n,L1u]" 'default for doSpecialGraph of simulated RLC RefRLCLastNumPoints=0 RefRLCLastConnect$="" 'For continuity calling ReflectionRLC analyzeQLastNumPoints=0 'For continuity in AnalyzeQ GDLastNumPoints=0 'Number of points last used for group delay analysis frontEndCalNumPoints=0 'No front end adjustment frontEndActiveFilePath$="" frontEndLastFolder$=DefaultDir$ 'ver114-3f moved the call to gInitFirstUse here from [CreateGraphWindow] initialGraphWindowHeight=600 : basicGraphWindowWidth=800 'Reflection will be narrower ver115-1b initialGraphWindowWidth=basicGraphWindowWidth 'for SA mode ver115-1c gosub [FindClientOffsets] 'set clientWidthOffset and clientHeightOffset from test window ver115-1b smithLastWindowHeight=430 : smithLastWindowWidth=400 'ver115-5d currGraphBoxHeight=initialGraphWindowHeight-clientHeightOffset-44 'ver115-1b 'ver115-1c currGraphBoxWidth=initialGraphWindowWidth-clientWidthOffset 'ver115-1b 'ver115-1c graphMarLeft=70 : graphMarRight=180 : graphMarTop=55 : graphMarBot=140 'SEWgraph Graph margins from edge of graphicbox call gInitFirstUse "#handle.g", currGraphBoxWidth, currGraphBoxHeight, graphMarLeft, graphMarRight, _ 'ver115-1c graphMarTop, graphMarBot 'SEWgraph Initialize graphing module gosub [InitGraphParams] 'SEWgraph 'Initialize parameters to set up the graphing module ver114-3f moved gosub [ChangeMode] 'create Graph Window in mode of msaMode$ desiredCalLevel=0 'Desire no cal ver114-6b applyCalLevel=0 bandLineNumSteps=-1 'Indicate cal does not exist ver114-5f; baseLine cal was handled above ver114-5m OSLBandNumSteps=-1 'ver115-1b OSLBaseNumSteps=-1 'ver115-1b call ClearCalArray gMaxNumPoints()-1 'Clear existing line cal data ver115-1b OSLLastSelectedCalSet=0 'Indicates there was no prior selection ver115-7a OSLOpenDelay=0 : OSLOpenCap=0 'ver115-1b OSLShortDelay=0 : OSLShortL=0 : OSLShortR=0 'ver115-1b OSLS11JigType$="Reflect" 'ver115-1b '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 [LoadPreferenceFile] what to load gosub [LoadPreferenceFile] 'ver115-8c if restoreErr$<>"" then 'ver115-1b '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 else restoreErr$="" 'Clear error if problem was file does not exist. ver115-3c end if end if 'Resave preferences only if no serious error if restoreErr$="" then call SavePreferenceFile restoreFileName$ 'Save Preference file in current format ver115-4a if gGetXIsLinear() then userFreqPref=0 else userFreqPref=1 'Start with Center/Span for linear, Start/Stop for log 'ver115-1d 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] if suppressHardware=0 then 'ver115-6c 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 end if '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 error$="" : errora$="" 'ver115-1c 'Initialize Final Filter path to Path 1 (1 of 4). This is an optional hardware addition to the MSA '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 gosub [CommandFilter] 'Command per A0, A1, A2. Does nothing if suppressHardware=1. ver115-6c 'InitializeTrkGen, if installed '6.if configured, initialize DDS3 by reseting to serial mode. Frequency is commanded to zero if suppressHardware then goto [SkipHardwareInitialization] 'In case there is no hardware ver115-6c 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] 'skips to here if no TG '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 'ver115-1c LO2 is now global '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 resetting. 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 [SkipHardwareInitialization] 'Skips to here if there is no hardware (suppressHardware=1) ver115-6c cb=cb 'to avoid two labels in a row '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 '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 'ver115-1a 'ver115-8d moved test for specialOneSweep to step 14 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 if calInProgress=0 then 'Note x values must be calculated first (in [UpdateGraphParams]) ; modVer115-1c if msaMode$="Reflection" then call InstallSelectedOSLCal else if msaMode$<>"SA" then call InstallSelectedLineCal 'ver115-8c end if end if call gInitDynamicDraw 'Set up for first scan of dynamic draw/erase/redraw... call ImplementDisplayModes 'Done in [UpdateGraphParams] but gInitDynamicDraw overrode it 'ver115-4e 'In multiscan, we don't want to update the time stamp on every redraw, which sometimes happens without scanning. if multiscanIsOpen=0 or multiscanInProgress=1 then 'ver115-9a restartTimeStamp$=date$("mm/dd/yy"); "; ";time$() 'ver115-2c call gSetTitleLine 3, restartTimeStamp$ '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 end if 'For multiscan, the redraw of the background is done prior to scanning via [PartialRestart], and on refresh if multiscanInProgress=0 then 'Redraw background stuff on first scan of a series. ver115-8d 'ver115-8d deleted calc of centerstep, which is no longer used call gDrawGrid 'SEWgraph; Clear graphics area and draw the background grid and labels call DrawSetupInfo 'SEWgraph Draw info describing the sweep setup if smithGraphHndl$()<>"" then 'ver115-1b draw smith chart if we have one ver115-1e call smithRedrawChart 'Draw blank chart ver115-2c end if if referenceLineType<>0 then 'Draw reference lines ver114-8a if referenceLineType>1 then call CreateReferenceSource 'RLC or fixed value call CreateReferenceTransform 'Generate actual reference graph data call gClearAllReferences if referenceDoMath=0 then 'don't draw ref if we are using ref for math if (referenceTrace and 2) then call gAddReference 1,CreateReferenceTraces$(referenceColor2$,referenceWidth2,2) 'Do Y2 reference if (referenceTrace and 1) then _ call gAddReference 2,CreateReferenceTraces$(referenceColor1$,referenceWidth1,1) 'Do Y1 reference call gDrawReferences refHeadingColor1$=referenceColor1$ : refHeadingColor2$=referenceColor2$ 'ver115-5d else call gGetTraceColors refHeadingColor1$, refHeadingColor2$ 'Use trace colors for "REF" if math is used end if call PrintReferenceHeading 'Print above axis to indicate which line matches which axis 'ver115-5d end if #graphBox$, "flush" 'Make the setup info stick end if useExpeditedDraw=gCanUseExpeditedDraw() 'SEWgraph; For normal SA use, [gDrawSingleTrace] will be used. 'ver115-1a 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 if msaMode$="SA" and gentrk=0 and multiscanInProgress=0 then 'ver115-4f if (endfreq-startfreq)/steps >finalbw/1000 then 'compare as MHz message$= "Frequency step size exceeds RBW; signals may be missed." call PrintMessage end if end if '13.Calculate the command information for first step through last step of the sweep and put in arrays if suppressHardware then 'ver115-6c 'These are taken from the routines we are skipping for i=0 to steps thisfreq=gGetPointXVal(i+1) 'Point number is 1 greater than step number SEWgraph if FreqMode<>1 then thisfreq=Equiv1GFreq(thisfreq) 'Convert from display freq to equivalent 1G frequency datatable(i,0) = thisstep 'put current step number into the array, row value= thisstep 'moved ver111-18 datatable(i,1) = thisfreq phaarray(i,0) = 0 'pdm state next i else 'Do these only if we are using the hardware 'ver115-6c gosub [CalculateAllStepsForLO1Synth] 'ver111-18 if TGtop > 0 then gosub [CalculateAllStepsForLO3Synth] 'ver111-18 gosub [CreateCmdAllArray] 'ver111-31b end if call CalcFreqCorrection 'Calculate power correction at each frequency SEWgraph1 if msaMode$="SA" and frontEndActiveFilePath$<>"" then call frontEndInterpolateToScan 'Calculate corrections for front end ver115-9d continueCode=0 'SEWgraph Set to other values by subroutines to cause halt, wait or restart '14.[StartSweep]'Begin sweeping from step 0 'StartSweep begins the outer loop that repeats the entire scan process until halted. 'The scan loop continues until a user action which aborts the scan, or in the case of 'OneStep it continues only for a single point. If specialOneSweep=1 or HaltAtEnd=1, it 'automatically stops at the end of a single sweep. 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 'if we just want to go through the initialization procedure we set returnBeforeFirstStep 'and invoke [Restart] with a gosub; here we return to the caller if returnBeforeFirstStep then 'ver115-2a thisstep=sweepStartStep returnBeforeFirstStep=0 gosub [CleanupAfterSweep] return 'ver115-1d end if [StartSweep]'enters from above, or [IncrementOneStep]or[FocusKeyBox]([OneStep][Continue]) if specialOneSweep then haltAtEnd=1 else haltAtEnd=0 'ver115-8d moved this here 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 if suppressHardware=0 then 'ver115-6c 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 end if '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 'Sweep process was called by gosub; we return to caller. end if 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]'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" ver115-1a if isStickMode=0 then if refreshOnHalt then 'ver115-8c refreshGridDirty=1: call RefreshGraph 1 'SEWgraph; redraw and show erasure gap; don't do if stick mode ver114-7d else 'We sometimes don't want to waste time redrawing, such as when we are loading a data file, 'but we at least need to flush to make the graphics stick. #graphBox$, "flush" end if end if if specialOneSweep and thisstep <> sweepEndStep then beep: message$="Sweep Aborted" 'ver115-4b else if calInProgress then beep: message$="Calibration Complete" 'ver115-4b 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) if message$<>"" then call PrintMessage 'ver115-4b '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 ver115-1b '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 avoid multiple system redraws ver115-1b #graphBox$ "home" #graphBox$ "posxy CenterX CenterY" currGraphBoxWidth = CenterX * 2-1 'ver115-1c currGraphBoxHeight = CenterY * 2-1 'ver115-1c '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=currGraphBoxHeight+15 : markSelLeft=5 'ver115-1b 'ver115-1c 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 ver115-1b 'The graphicbox auto resizes but we have to update the graph module 'to let it know the new size call gUpdateGraphObject graphBox$, currGraphBoxWidth, currGraphBoxHeight, _ 'ver115-1c graphMarLeft, graphMarRight, graphMarTop, graphMarBot call gCalcGraphParams 'Calculate new scaling call gGenerateXValues gPointCount() 'recreate x values and x pixel locations; keep same number of points call gRecalcPix 0 '0 signals not to recalc x pixel coords, which we just di in gGenerateXValues. '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." call RequireRestart 'ver115-9e Otherwise old graph still appears, in wrong place. else refreshRedrawFromScratch=1 'To redraw from scratch ver115-1b call RedrawGraph 0 'Redraw at new size end if 'call RequireRestart 'ver115-9e Not sure why we should require restart wait 'ver114-6e added ImplementDisplayModes sub ImplementDisplayModes 'calculate the various items from Y1DisplayMode and Y2DisplayMode 'Y1DisplayMode, Y2DisplayMode: 0=off 1=NormErase 2=NormStick 3=HistoErase 4=HistoStick 'ver115-2c added checks for constNoGraph if (Y1DataType<>constNoGraph and (Y1DisplayMode=2 or Y1DisplayMode=4)) or _ (Y2DataType<>constNoGraph and (Y2DisplayMode=2 or Y2DisplayMode=4)) then isStickMode=1 else isStickMode=0 call gSetDoAxis Y1DataType<>constNoGraph, Y2DataType<>constNoGraph 'Turn graph data on or off ver115-3b 'Note that gActivateGraphs won't activate a graph if we just set its data existence to zero ver115-3b call gActivateGraphs Y1DisplayMode<>0,Y2DisplayMode<>0 'Turn actual graphing on or off ver115-3b if (Y1DataType<>constNoGraph and Y1DisplayMode>2) or (Y2DataType<>constNoGraph and Y2DisplayMode>2) then _ call gSetDoHist 1 else call gSetDoHist 0 'Set histogram or normal trace ver115-3b 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 ((Y1DataType<>constNoGraph and t1Width>2) or _ (Y2DataType<>constNoGraph and t2Width>2)) _ and globalSteps>200 then eraseLead=eraseLead+1 end if if Y2DisplayMode<>1 and Y2DisplayMode<>3 then doErase2=0 else doErase2=1 'ver114-2f if Y1DisplayMode<>1 and Y1DisplayMode<>3 then doErase1=0 else doErase1=1 'ver115-3b 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 'ver115-3b deleted settings related to Y2DisplayMode and Y1DisplayMode. They were overridden in ImplementMagPhaDisp, 'which is called by UpdateGraphDataFormat 'ver115-1d deleted the separate call for linear mode. startfreq and endfreq are now valid in all modes. call gInitGraphRange startfreq, endfreq, _ botphase, topphase, botref, topref 'min and max values for x, y1 and y2; calls gCalcGraphParams '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 'ver115-1b revised UpdateGraphDataFormat 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//DoCompact//Scale=1000000" 'ver115-1e end if 'ver115-2c caused the full procedure to be executed for both dataNum. SA and ScalarTrans 'now have constNoGraph for Y1DataType. Also eliminated default setting of yForm$ 'ver115-3a moved the select block to DetermineGraphDataFormat so others can use it for dataNum=1 to 2 if dataNum=1 then componConst=Y1DataType else componConst=Y2DataType if componConst=constNoGraph then doData=0 'Indicates whether there is a graph ver115-2c yAxisLabel$="None" : yLabel$="None" yForm$="####.##" 'Something valid, in case it gets mistakenly used if dataNum=1 then y1AxisLabel$="None" : y1Label$="None" y1Form$="####.##" 'Something valid, in case it gets mistakenly used else y2AxisLabel$="None" : y2Label$="None" y2Form$="####.##" 'Something valid, in case it gets mistakenly used end if else doData=1 if dataNum=1 then call DetermineGraphDataFormat componConst, y1AxisLabel$,y1Label$, y1IsPhase,y1Form$ else call DetermineGraphDataFormat componConst, y2AxisLabel$,y2Label$, y2IsPhase,y2Form$ end if end if if dataNum=1 then doY1=doData else doY2=doData next dataNum call gSetIsPhase y1IsPhase, y2IsPhase 'Tell graph module whether data is phase call gSetAxisFormats xForm$, y1Form$, y2Form$ 'Formats for displaying the data values call gSetAxisLabels "", y1AxisLabel$, y2AxisLabel$ 'Labels for the axes; No label for freq call gSetDataLabels y1Label$, y2Label$ 'Shorter labels for marker info call gSetDoAxis doY1, doY2 'Tell graph module whether we have graphs ver115-2c call ImplementDisplayModes 'give effect to Y2DisplayMode and Y1DisplayMode; may have been affected by doY1, doY2 ver115-2c end sub 'ver115-3a created DetermineGraphDataFormat by moving it from within UpdateGraphFormat sub DetermineGraphDataFormat componConst, byref yAxisLabel$, byref yLabel$,byref yIsPhase,byref yForm$ 'Return format info 'componConst indicates the data type. We return 'yAxisLabel$ The label to use at the top of the Y axis 'yLabel$ A typically shorter label for the marker info table 'yIsPhase$ =1 if the value represents phase. This indicates whether we have wraparound issues. 'yForm$ A formatting string to send to uFormatted$() to format the data ' yIsPhase=0 'Default, since most are not phase select case componConst case constGraphS11DB yAxisLabel$="S11 Mag(dB)" : yLabel$="S11 dB" yForm$="####.###" 'ver115-5d case constRawAngle 'Used for transmission mode only 'added by ver115-1i yAxisLabel$="Raw Phase(Deg)" : yLabel$="Raw Deg" yIsPhase=1 yForm$="#####.##" 'ver115-5d case constAngle,constGraphS11Ang,constTheta,constImpedAng if componConst=constAngle then yAxisLabel$="S21 Phase(Deg)" : yLabel$="S21 Deg" if componConst=constTheta then yAxisLabel$="Theta" : yLabel$="Theta" if componConst=constGraphS11Ang then yAxisLabel$="S11 Phase(Deg)" : yLabel$="S11 Deg" if componConst=constImpedAng then yAxisLabel$="Imped. (Deg)" : yLabel$="Z Deg" yIsPhase=1 yForm$="#####.##" 'ver115-5d case constGD 'calc group delay yAxisLabel$="Grp Delay (sec)" : yLabel$="G.D." yForm$="3,2,4//UseMultiplier//DoCompact" case constSerReact yAxisLabel$="Ser. React." : yLabel$="Xs" yForm$="3,3,4//UseMultiplier//SuppressMilli//DoCompact" 'ver115-4e case constParReact yAxisLabel$="Par. React." : yLabel$="Xp" yForm$="3,3,4//UseMultiplier//SuppressMilli//DoCompact" 'ver115-4e case constImpedMag yAxisLabel$="Imped. (ohms)" : yLabel$="Z Ohms" yForm$="3,3,4//UseMultiplier//SuppressMilli//DoCompact" 'ver115-4e case constSerR yAxisLabel$="Ser. Resist" yLabel$="Rs" yForm$="3,3,4//UseMultiplier//SuppressMilli//DoCompact" 'ver115-4e case constParR yAxisLabel$="Par. Resist." yLabel$="Rp" yForm$="3,3,4//UseMultiplier//SuppressMilli//DoCompact" 'ver115-4e case constSerC yAxisLabel$="Ser. Cap." yLabel$="Cs" yForm$="3,3,4//UseMultiplier//DoCompact" case constParC yAxisLabel$="Par. Cap." yLabel$="Cp" yForm$="3,3,4//UseMultiplier//DoCompact" case constSerL yAxisLabel$="Ser. Ind." yLabel$="Ls" yForm$="3,3,4//UseMultiplier//DoCompact" case constParL yAxisLabel$="Par. Ind." yLabel$="Lp" yForm$="3,3,4//UseMultiplier//DoCompact" case constMagDBM if msaMode$="SA" then yAxisLabel$="Magnitude (dBm)" : yLabel$="dBm" else yAxisLabel$="Power (dBm)" : yLabel$="dBm" 'ver115-1i end if yForm$="####.###" 'ver115-5d case constMagWatts yAxisLabel$="Magnitude (Watts)" : yLabel$="Watts" yForm$="3,3,4//UseMultiplier//DoCompact" case constMagDB 'Only done for Transmission if msaMode$="ScalarTrans" then 'ver115-1a yAxisLabel$="Transmission (dB)" : yLabel$="dB" else yAxisLabel$="S21 Mag(dB)" : yLabel$="S21 dB" end if yForm$="####.###" 'ver115-1e case constMagRatio 'Only done for TG mode transmission if msaMode$="ScalarTrans" then 'ver115-4f yAxisLabel$="Trans (Ratio)" : yLabel$="Ratio" else yAxisLabel$="Mag (Ratio)" : yLabel$="Ratio" end if yForm$="3,3,4//UseMultiplier//SuppressMilli//DoCompact" 'ver115-4e case constMagV yAxisLabel$="Mag (Volts)" : yLabel$="Volts" yForm$="3,3,4//UseMultiplier//DoCompact" case constRho yAxisLabel$="Rho" : yLabel$="Rho" yForm$="#.###" case constReturnLoss 'ver114-8d yAxisLabel$="Return Loss(dB)" : yLabel$="RL" yForm$="###.###" 'ver115-1e case constInsertionLoss 'ver114-8d yAxisLabel$="Insertion Loss(dB)" : yLabel$="IL" yForm$="###.###" 'ver115-1e case constReflectPower 'ver115-2d yAxisLabel$="Reflect Pow(%)" : yLabel$="Ref%" yForm$="###.##" case constComponentQ 'ver115-2d yAxisLabel$="Component Q" : yLabel$="Q" yForm$="#####.#" case constSWR 'ver114-8d yAxisLabel$="VSWR" : yLabel$="VSWR" yForm$="####.##" case constAdmitMag 'ver115-4a yAxisLabel$="Admit. (S)" : yLabel$="Y" yForm$="3,3,4//UseMultiplier//DoCompact" case constAdmitAng 'ver115-4a yAxisLabel$="Raw Phase(Deg)" : yLabel$="Admit Deg" yIsPhase=1 yForm$="#####.##" case constConductance 'ver115-4a yAxisLabel$="Conduct. (S)" : yLabel$="Conduct" yForm$="3,3,4//UseMultiplier//DoCompact" case constSusceptance 'ver115-4a yAxisLabel$="Suscep. (S)" : yLabel$="Suscep" yForm$="3,3,4//UseMultiplier//DoCompact" case constNoGraph 'ver115-2c yAxisLabel$="None" : yLabel$="None" yForm$="####.##" 'Something valid, in case it gets mistakenly used case constAux0, constAux1, constAux2, constAux3, constAux4, constAux5 auxNum=componConst-constAux0 'e.g. constAux4 produces 4 yAxisLabel$=auxGraphDataFormatInfo$(auxNum,2) : yLabel$=auxGraphDataFormatInfo$(auxNum,3) yForm$=auxGraphDataFormatInfo$(auxNum,1) case else yForm$="###.##" yAxisLabel$="Invalid" : yLabel$="Invalid" end select 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 wate=0 : offset=0 : sgout=10 'ver114-3c ver114-4h gentrk=0 : normrev=0 msaMode$="SA" 'ver114-5L call SetDefaultGraphData 'ver115-3b S21JigAttach$="Series" 'ver115-1b S21JigR0=50 : S21JigShuntDelay=0 S11BridgeR0=50 : S11GraphR0=50 S11JigType$="Reflect" 'ver115-1b call UpdateGraphDataFormat 'Updates from graphDataType$ planeadj=0 'ver 114-4k FreqMode=1 'start in 1G mode ver115-1c 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 referenceWidthSmith=1 : referenceColorSmith$=referenceColor2$ 'ver115-6b lineCalThroughDelay=0 for i=1 to 5 'clear custom names ver115-2a customPresetNames$(i)="Empty" next i call FillAppearancesArray 'ver115-2a primaryAxisNum=2 'Primary Y axis. Eg. on restart in SA mode, mag dBm goes here ver115-3b call gSetPrimaryAxis primaryAxisNum 'ver115-3c 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" 'ver115-1a if doingPhase or varwindow = 1 then gosub [ReadPhase] 'ver112-1b ver114-5n ver115-1a '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 ver115-1a '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 'number of ms we need to wait 'ver115-1i '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" if waittime>0 then 'ver115-1i added the use of the system sleep function if doingInitialization or waittime<15 then 'For short wait times we use our own timing loop 'Also for initialization, when we are measuring glitchtime waittime=waittime*glitchtime timecounter = 0 'ver111-27 [TimeLoop] 'ver111-27 if timecounter < waittime then timecounter = timecounter + 1:goto [TimeLoop] 'ver111-27 else 'It is preferable to use the system Sleep function, but it seems to impose a minimum 'of 10-15 ms. In addition, it seems to increment in steps of 10-15 ms. So it is only suitable for 'long wait times call uSleep waittime end if end if glitchp1=0:glitchd1=0:glitchp3=0:glitchd3=0:glitchpdm=0:glitchhlt=0 'reset glitch variables back to 0 'ver111-27 return [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 suppressHardware then magdata=0 : return 'ver115-6c 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 suppressHardware then 'ver115-6c phadata=0 else 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 end if 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 suppressHardware then return 'ver115-6c 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. if suppressHardware then 'ver115-6c message$=180;" ";phase1 : call PrintMessage 'ver114-4e return end if 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]'For reading the 16 bit serial AtoD. Changed 4-27-10 ver115-9b 'This routine modified to help reject noise glitching caused by newer, faster, cheaply made computers. 'needed: port, control, 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, CVN is BD7. if cb = 2 then goto[Read16wSlimCB]' if SLIM Contol Board, jump over [Read16wOrigCB] [Read16wOrigCB] 'Using the Original Control Board. added by ver115-9b out port, 128 'take CVN high. Begins data capture inside AtoD out port, 128:out port, 128 'keep CVN high for 3 port commands to assure full AtoD conversion out port, 64 'CVN low and SCLK=1 'bit 15 is valid stat15 = inp(status) 'read data, statX is an 8 bit word for the Status Port out port, 0:out port, 64 'Status bit 14 is now valid stat14 = inp(status) out port, 0:out port, 64 'Status bit 13 is now valid stat13 = inp(status) out port, 0:out port, 64 'Status bit 12 is now valid stat12 = inp(status) out port, 0:out port, 64 'Status bit 11 is now valid stat11 = inp(status) out port, 0:out port, 64 'Status bit 10 is now valid stat10 = inp(status) out port, 0:out port, 64 'Status bit 9 is now valid stat9 = inp(status) out port, 0:out port, 64 'Status bit 8 is now valid stat8 = inp(status) out port, 0:out port, 64 'Status bit 7 is now valid stat7 = inp(status) out port, 0:out port, 64 'Status bit 6 is now valid stat6 = inp(status) out port, 0:out port, 64 'Status bit 5 is now valid stat5 = inp(status) out port, 0:out port, 64 'Status bit 4 is now valid stat4 = inp(status) out port, 0:out port, 64 'Status bit 3 is now valid stat3 = inp(status) out port, 0:out port, 64 'Status bit 2 is now valid stat2 = inp(status) out port, 0:out port, 64 'Status bit 1 is now valid stat1 = inp(status) out port, 0 'Status bit 0 is now valid stat0 = inp(status) 'we now have raw a/d status words in stat15-stat0 return 'to [ReadMagnitude]or[ReadPhase]with status words [Read16wSlimCB] 'Using the SLIM Control Board. added by ver115-9b out port, 128:out control, AUTO:out control, contclear 'take CVN high. Begins data conversion inside AtoD, 'and is completed within 2.2 usec. out control, contclear 'keep CVN high for 3 port commands to assure full AtoD conversion out port, 64:out control, AUTO:out control, contclear 'CVN low and SCLK=1 'Status bit 15 'of the serial data is valid and can be read at any time. stat15 = inp(status) 'read data, statX is an 8 bit word for the Status Port out port, 0:out control, AUTO:out control, contclear 'SCLK=0 'bit 14 is valid, 'data (SDO) is incremented on the falling edge of SCLK out port, 64:out control, AUTO:out control, contclear 'SCLK=1 stat14 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 13 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat13 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 12 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat12 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 11 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat11 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 10 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat10 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 9 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat9 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 8 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat8 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 7 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat7 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 6 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat6 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 5 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat5 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 4 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat4 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 3 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat3 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 2 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat2 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 1 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat1 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 0 is valid 'a/d outputs would go high z on 16th SCLK trailing edge, but only 15 have been sent. stat0 = inp(status) 'read data, statX is 8 bit word 'U3 and P3 on SLIM Control Board is disabled. '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]'For reading the 12 bit serial AtoD. Changed 4-27-10 ver115-9b 'This routine modified to help reject noise glitching caused by newer, faster, cheaply made computers. '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 Control Board or Slim Control Board. ver111-33c 'good for serial, 12 Bit Original AtoD Module or SLIM-ADC-12 'serial data out is incremented on the falling SCLK edge. 'MAG is WAIT, PHASE is ACK, SCLK is BD6, CVN is BD7. if cb = 2 then goto[Read22wSlimCB]' if SLIM Contol Board, jump over routine [Read22wOrigCB] [Read22wOrigCB] 'Using the Original Control Board. added by ver115-9b out port, 128 'take CVN high. Begins data conversion inside AtoD, 'and is completed within 3.2 usec. out port, 128:out port, 128 'keep CVN high for 3 port commands to assure full AtoD conversion out port, 64 'CVN low, SCLK=1 'serial data out is still not valid out port, 0 'CVN low, SCLK=0 Status bit 11 is now valid. out port, 64 'CVN low, SCLK=1 stat11 = inp(status) 'read data, statX is 8 bit word out port, 0:out port, 64 'Status bit 10 is now valid stat10 = inp(status) out port, 0:out port, 64 'Status bit 9 is now valid stat9 = inp(status) out port, 0:out port, 64 'Status bit 8 is now valid stat8 = inp(status) out port, 0:out port, 64 'Status bit 7 is now valid stat7 = inp(status) out port, 0:out port, 64 'Status bit 6 is now valid stat6 = inp(status) out port, 0:out port, 64 'Status bit 5 is now valid stat5 = inp(status) out port, 0:out port, 64 'Status bit 4 is now valid stat4 = inp(status) out port, 0:out port, 64 'Status bit 3 is now valid stat3 = inp(status) out port, 0:out port, 64 'Status bit 2 is now valid stat2 = inp(status) out port, 0:out port, 64 'Status bit 1 is now valid stat1 = inp(status) out port, 0 'Status bit 0 is now valid stat0 = inp(status) return 'to [ReadMagnitude]or[ReadPhase]with status words 'a/d outputs would go high z on 13th SCLK trailing edge, but only 12 have been sent. stat0 = inp(status) 'read data, statX is 8 bit word 'we have raw a/d status words in stat11-stat0 return 'to [ReadMagnitude]or[ReadPhase]with status words [Read22wSlimCB] 'Using the SLIM Control Board. added by ver115-9b out port, 128:out control, AUTO:out control, contclear 'take CVN high. Begins data conversion inside AtoD, 'and is completed within 3.2 usec. out control, contclear 'keep CVN high for 3 port commands to assure full AtoD conversion out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 'serial data out is still not valid out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 Bit 11 is now valid. out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat11 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 10 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat10 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 9 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat9 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 8 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat8 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 7 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat7 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 6 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat6 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 5 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat5 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 4 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat4 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 3 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat3 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 2 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat2 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 1 is valid out port, 64:out control, AUTO:out control, contclear 'CVN low, SCLK=1 stat1 = inp(status) 'read data, statX is 8 bit word out port, 0:out control, AUTO:out control, contclear 'CVN low, SCLK=0 'bit 0 is valid 'a/d outputs would go high z on 13th SCLK trailing edge, but only 12 have been sent. stat0 = inp(status) 'read data, statX is 8 bit word 'U3 and P3 on SLIM Control Board is disabled. '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 'modver115-1e if msaMode$<>"ScalarTrans" then gosub [ConvertPhadata]'convert phadata (bits read) to phase (degrees) and thispointphase (pixels) 'ver111-19 gosub [ProcessDataArrays] end if gosub [PlotDataToScreen] return 'from [ProcessAndPrint] [ProcessDataArrays] 'process "thisstep" data for VNA/SNA, filling S21DataArray and/or ReflectArray 'ver115-8b separated this from ProcessAndPrint so it can be called separately. 'Data is calculated from datatable, stored as necessary and graphed. 'For reflection mode; do jig calc and/or apply OSL calibration ver115-1b 'But data as is if we are doing calibration. ver115-1e 'ver115-8b changed to use ActualSignalFrequency function rather than retrieving from graph module. thisfreq=datatable(thisstep,1) 'freq if FreqMode<>1 then thisfreq=ActualSignalFrequency(thisfreq) 'actual signal frequency, not equivalent 1G freq ver115-9b thisDB=datatable(thisstep,2) 'mag db thisAng=datatable(thisstep,3) 'phase 'We save data in S21DataArray for VectorTrans and ScalarTrans modes 'We save data in ReflectArray for Reflection Mode. 'Actual signal frequency, not equivalent 1G freq, gets saved in both places for all non-SA modes. 'Note data in datatable has no adjustment for planeadj, but these other arrays do ReflectArray(thisstep,0)=thisfreq S21DataArray(thisstep,0)=thisfreq 'Note this is actual signal freq for all modes, not just transmission if msaMode$="VectorTrans" or msaMode$="ScalarTrans" then if calInProgress=0 then call uExtendCalPlane thisfreq, thisAng, planeadj,0 'Do plane adjustment ver115-2b S21DataArray(thisstep,1)=thisDB 'mag S21DataArray(thisstep,2)=thisAng 'phase end if if msaMode$="Reflection" then for i=1 to 16 : ReflectArray(thisstep,i)=0 : next i 'Clear all reflection data (except freq) for this point 'ver115-2d ReflectArray(thisstep,constGraphS11DB)=thisDB 'Save raw data in array that will hold reflection related data ReflectArray(thisstep,constGraphS11Ang)=thisAng call ConvertRawDataToReflection thisstep,0 'Calculate all reflection related data; apply OSL if necessary ver115-5f end if return 'from [ProcessDataArrays] 'SEWgraph1 added CalcFreqCorrection sub CalcFreqCorrection 'Calculate power correction factors for each frequency step. for s=0 to globalSteps currFreq=gGetPointXVal(s+1) 'Point number is one more than step num ver115-5c freqCorrection(s)=calConvertFreqError(currFreq) '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 = 360*phadata/maxpdmout 'converts phadata bits to absolute phase. ver15-2d moved rounding to later '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) 'if PDM was inverted, subtract the inverted phase change (norm to inv adds "invdeg" deg) phase = phase - (invdeg * phaarray(thisstep,0)) 'ver111-36g 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 applyCalLevel>0 then phase = phase - lineCalArray(thisstep,2) if phase>=0 then phase=int(phase*100+0.5)/100 else phase=int(phase*100-0.5)/100 'round to two decimal places ver115-2d 'ver115-2b moved the application of planeadj. The data in datatable() never contains that adjustment. '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 'ver115-1a ver 115-1b '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 'ver115-1a call calConvertMagPhase magdata, doPhaseCor, power, difPhase 'ver114-5n thisfreq = datatable(thisstep,1) freqerror=freqCorrection(thisstep) 'find freq cal adjustment SEWgraph1 'In SA mode, if there is an active front end file, we add the front end correction factor if msaMode$="SA" then if frontEndActiveFilePath$<>"" then freqerror=freqerror-frontEndCorrection(thisstep) 'ver115-9d end if else if calInProgress then 'ver115-4d 'If calibrating, we want to use ideal results so when we display the actual doSpecialGraph 'it will come out the way we want. power=0 phase=0 datatable(thisstep,3) = phase else gosub [DoSpecialGraph] end if 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 = power 'ver115-2d 'ver114-5f Apply lineCalArray only if LineCal or BaseLineCal or is active if msaMode$<>"SA" then if applyCalLevel>0 then magpower = magpower - lineCalArray(thisstep,1) 'ver114-5n if magpower>=0 then magpower=int(magpower*100000+0.5)/100000 else magpower=int(magpower*100000-0.5)/100000 'round to five decimal places ver115-4d datatable(thisstep,2) = magpower 'put current power measurement into the array return 'to [ProcessAndPrint] '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) 'linear change over frequency ' phadata =maxpdmout-1000*datatable(thisstep,1) 'For special graph 3, force to a linear function ver114-7b ' while phadata0 'the internally generated data is already S11, and only needs plane extension. 'If we are applying full OSL below we leave it as is as our tentative estimate of reflection, even though 'it is far from true reflection; OSL will take care of the transformation. 'If not appying OSL, we convert it to reflection right now. 'Note we don't get this far if calibrating. 'Convert to impedance based on jig attachment and then to S11db if suppressOSL=0 and doSpecialGraph=0 and (OSLApplyFull=0 or applyCalLevel=0) then 'ver115-5f if S21JigAttach$="Series" then call uSeriesJigImpedance S21JigR0, db, ang, impR, impX 'calc impedance : R, X else 'Note the following will adjust for 21JigShuntDelay if required, but not for doSpecialGraph<>0 if doSpecialGraph=0 then conversionDelay=S21JigShuntDelay else conversionDelay=0 'ver115-4j call uShuntJigImpedance S21JigR0, db, ang, conversionDelay, trueFreq, impR, impX 'calc impedance : R, X 'ver115-4j end if 'Note we use S11BridgeR0 to calculate reflection call uImpedanceToRefco S11BridgeR0, impR, impX, rho, ang db=20*uSafeLog10(rho) else 'Series or shunt when calibrating or when applying full OSL rho=uTenPower(db/20) 'mag made linear end if end if 'db, rho, and ang (degrees) now have the raw reflection data 'If necessary, we apply full OSL to the reflection data, whether it was derived 'from a reflection bridge or a transmission jig. It is possible the OSL cal was not really "full", 'but if two standards were used we would already have included the third as though it were ideal. 'If doing OSL cal, then we don't want to apply whatever coefficients we happen to have now. 'If doSpecialGraph<>0 we don't want to mess with the internally generated data if suppressOSL=0 and doSpecialGraph=0 and (OSLApplyFull and applyCalLevel<>0) then 'ver115-5f rads=ang*uRadsPerDegree() 'angle in radians mR=rho*cos(rads) : mI=rho*sin(rads) 'measured S11, real and imaginary aR=OSLa(currStep,0) : aI=OSLa(currStep,1) 'coefficient a, real and imaginary bR=OSLb(currStep,0) : bI=OSLb(currStep,1) 'coefficient b, real and imaginary cR=OSLc(currStep,0) : cI=OSLc(currStep,1) 'coefficient c, real and imaginary 'calculate adjusted db, ang via OSL. Note OSL must be referenced to S11BridgeR0 calcMethod=1 'For debugging, we have two different methods if calcMethod=1 then 'The first method uses the following formula, and corresponds to CalcOSLCoeff ' S = (M – b) / (a – c*M) 'where S is the actual reflection coefficient and M is the measured reflection coefficient. 'S and M are in rectangular form in this equation. RealCM=cR*mR-cI*mI : ImagCM=cR*mI+cI*mR 'c*M, real and imaginary call cxDivide mR-bR, mI-bI, aR-RealCM,aI-ImagCM,refR, refI 'Divide M-b by a-c*M magSquared=refR^2+refI^2 'mag of S, squared db=10*uSafeLog10(magSquared) 'S mag in db; multiply by 10 not 20 because mag is squared if db>0 then db=0 'Shouldn't happen ang=uATan2(refR, refI) 'angle of S in degrees else 'The second method uses the following formula, and corresponds to CalcOSLCoeff1 '(which assumes a perfect load with SL=0) ' S = (a - cM)/(bM - 1) 'where S is the actual reflection coefficient and M is the measured reflection coefficient. 'S and M are in rectangular form in this equation. RealCM=cR*mR-cI*mI : ImagCM=cR*mI+cI*mR 'c*M, real and imaginary RealBM=bR*mR-bI*mI : ImagBM=bR*mI+bI*mR 'b*M, real and imaginary numR=aR-RealCM : numI=aI-ImagCM 'numerator, real and imaginary denR=RealBM-1 :denI=ImagBM 'denominator, real and imaginary call cxDivide numR, numI, denR, denI, refR, refI 'Divide numerator by denominator; result is reflection coeff. magSquared=refR^2+refI^2 'mag of S, squared db=10*uSafeLog10(magSquared) 'S mag in db; multiply by 10 not 20 because mag is squared if db>0 then db=0 'Shouldn't happen ang=uATan2(refR, refI) 'angle of S in degrees end if 'db, ang (degrees) now have S11 data produced by applying OSL calibration. end if 'Save the angle prior to applying plane extension to make it easier to recalculate with a new extension ReflectArray(currStep, constIntermedS11DB)=db 'ver115-2d ReflectArray(currStep, constIntermedS11Ang)=ang 'ver115-2d 'Note we do apply plane extension even when doSpecialGraph<>0 if planeadj<>0 or S11BridgeR0<>S11GraphR0 then call ApplyExtensionAndTransformR0 ReflectArray(currStep,0), db, ang 'ver115-2d end if 'Note we do not put the reflection data in datatable, which retains the original raw data ReflectArray(currStep,constGraphS11DB)=db 'Save final S11 in db, angle format (in Graph R0, after plane ext) while ang>180 : ang=ang-360 : wend while ang<=-180 : ang=ang+360 : wend ReflectArray(currStep,constGraphS11Ang)=ang 'We now compute the various items in ReflectArray() from S11, but if we are doing calibration we don't need this 'other data, and it probably doesn't make sense anyway. if calInProgress=0 then call CalcReflectDerivedData currStep 'Calc other ReflectArray() data from S11. end sub 'ver115-2d created ApplyExtensionAndR0Transform so it can be called from a couple of places sub ApplyExtensionAndTransformR0 freq, byref db, byref ang 'Apply reflection mode plane extension and transform from bridge R0 to graph R0 for reflection 'freq is in MHz 'apply plane extension. We do this after applying calibration. 'For reflection mode with S21 series jig, plane extension makes no sense, so we don't do it 'For Transmission mode, we don't get here. 'We don't do the adjustment when calibrating, 'because plane extension is used to extend the plane after calibration, and we don't need to do S11GraphR0 'ver115-2b modified this procedure if calInProgress=1 then exit sub if planeadj<>0 then 'Do the extension, but not if series or shunt fixtures is used if S11JigType$="Reflect" then call uExtendCalPlane freq, ang, planeadj,1 '1 means reflection mode ver115-5j end if 'Convert into new R0 if necessary 'ver115-1e moved this here from CalcReflectDerivedData 'We don't convert if calibrating if S11BridgeR0<>S11GraphR0 then 'ver115-1e '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 ver115-1b fixed typo end if end sub [PlotDataToScreen] 'SEWgraph heavily revised PlotDataToScreen to utilize new graphing module. 'Initialization for a series of sweeps is done in the sweep loop. During the first scan we draw traces. 'At the start of each subsequent scan we call gStartNextDynamicScan which prepares for the erase-and-draw. 'At the end of each scan, if the user so selects, the screen is "refreshed", meaning that is quickly redrawn 'from strings or "flush" segments saved during the drawing process. However, if there are more than 1200 steps, 'the refresh is actually a complete redraw from scratch, because it is too time consuming to accumulate the large 'strings needed for the refresh procedure. Repeatedly adding short segments to very large strings is time consuming. 'When the scan is halted, the screen is redrawn 'from scratch using draw commands saved from the scans. However, redrawing and refreshing does not occur 'if we are graphing in one of the "stick" modes. At the end of each sweep we also figure out where the markers go, 'draw them, and display their info below the graph. The user has the option not to show the markers on the 'graph, in which case their info is still displayed. Data for the first, last and center points is displayed 'below the frequency axis (no center point for log sweeps), but those are not considered "markers". 'Data values, and their pixel coordinates, are saved in the 'graphing module. The same values are also saved in the arrays used in software versions prior to the graphing module. 'Pixel coordinates are no longer saved in those pre-existing arrays, but the slots where the pixels were saved 'still exist. 'Trace segments are discarded at the end of a scan, and also every time 1000 have accumulated. Traces are not '"flushed" until the graph is redrawn upon halting. call CalcGraphData thisstep, thispointy1, thispointy2, 0 '0 means use regular data arrays ver114-7f if referenceDoMath=2 then 'ref math is to be done on graph values ver115-5d if (referenceTrace and 1) then _ thispointy1=referenceOpA*referenceTransform(thisstep+1, 1)+referenceOpB*thispointy1 if (referenceTrace and 2) then _ thispointy2=referenceOpA*referenceTransform(thisstep+1, 2)+referenceOpB*thispointy2 end if 'We draw a point after erasing a point (if required). 'We also saves the data to gGraphVal() and the pixel values to gGraphPix() 'X values have been precalculated in gGenerateXValues if thisstep=sweepStartStep then 'ver114-6e added the refreshXXX flags refreshForceRefresh=0 'We normally want refreshGridDirty=0 because we redrew the grid when restarting. But 'for mulitscans, that step is skipped. refreshGridDirty=multiscanInProgress refreshTracesDirty=0 refreshAutoScale=0 refreshRedrawFromScratch=0 if firstScan then refreshMarkersDirty=1 'Signals to relocate any markers to correspond to their frequency. 'If required, do auto scaling of axes at end of first scan if autoScaleY2 or autoScaleY1 then refreshAutoScale=1 'ver115-3b else call gStartNextDynamicScan 'SEWgraph Initializes for erase/draw passes; done at start of scans 2... end if 'ver114-5c moved setting of isStickMode to UpdateGraphParams end if 'useExpeditedDraw is set to 1 for single trace (mag) in non-histo mode for linear y scaling 'The expedited draw procedure is slightly faster than normal drawing, and will almost always be 'used when in SA mode. if useExpeditedDraw then gosub [gDrawSingleTrace] 'Normal SA drawing occurs with this else 'Enter new Y values and draw from last point 'Comment out all but one; two choices allowed for testing 'call gDynamicDrawPoint thispointy1,thispointy2 call gDynamicComboDrawPoint thispointy1,thispointy2 'This is the full-blown drawing procedure end if if steps>=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) then 'ver115-3b 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 ver115-1b end if if varwindow = 1 then gosub [updatevar] 'moved here from [ProcessAndPrint] ver111-34a return 'ver115-1b deleted GetDataAsRefco and GetDataAsImpedance 'CalcReflectDerivedData mod115-1e sub CalcReflectDerivedData currStep 'Calc ReflectArray() data from S11. frequency and S11 must already be in place. 'if currStep<0 then we get the data from uWorkReflectData(x) and put results into uWorkReflectData(x) 'otherwise we get the data from ReflectArray() and put results into ReflectArray(currStep,x) 'S11 is assumed to be re S11GraphR0 if currStep<0 then 'Get frequency and S11; we calculate everything else trueFreq=1000000*uWorkReflectData(0) 'ver115-1f db=uWorkReflectData(constGraphS11DB) ang=uWorkReflectData(constGraphS11Ang) else trueFreq=1000000*ReflectArray(currStep,0) db=ReflectArray(currStep,constGraphS11DB) ang=ReflectArray(currStep,constGraphS11Ang) end if rho=10^(db/20) call uRefcoToImpedance S11GraphR0, rho, ang, serR, serReact call uEquivSeriesLC trueFreq, serR, serReact, serL, serC if abs(serReact)<0.001 then serReact=0 'ver115-5d if serR<0.001 then serR=0 'ver115-5d call uEquivParallelImped serR, serReact, parR, parReact 'Convert imped to equivalent parallel resistance and reactance ver114-7b if abs(parReact)<0.001 then parReact=0 'ver115-5d if parR<0.001 then parR=0 'ver115-5d if trueFreq=0 then parR=constMaxValue: parL=constMaxValue: parC=0 'Set for max impedance else twoPiF = 2.0*uPi() * trueFreq if parReact>=constMaxValue then parL=constMaxValue else parL = parReact/twoPiF if parReact=0 then parC=constMaxValue else parC = -1.0/(twoPiF * parReact) end if if rho>0.999999 then swr=9999 else swr=(1+rho)/(1-rho) 'Impose a max of 1F or 1H if serC>1 then serC=1 if serL>1 then serL=1 if parC>1 then parC=1 if serC>1 then serC=1 if serC<-1 then serC=-1 if serL<-1 then serL=-1 if parC<-1 then parC=-1 if serC<-1 then serC=-1 minC=1e-15 : minL=1e-12 'impose min of 1 fF and 1 pH ver115-2d if abs(serC)=constAux0 and Y1DataType<=constAux5 then 'ver115-4a y1=auxGraphData(currStep, Y1DataType-constAux0) end if if Y2DataType>=constAux0 and Y2DataType<=constAux5 then 'ver115-4a y2=auxGraphData(currStep, Y2DataType-constAux0) end if if msaMode$="Reflection" then call CalcReflectGraphData currStep, y1, y2, useWorkArray else if msaMode$<>"SA" then call CalcTransmitGraphData currStep, y1, y2, useWorkArray else 'Here for spectrum analyzer mode if useWorkArray then db=uWorkArray(currStep+1,1) else db=datatable(currStep,2) end if if referenceDoMath=1 then 'ref math is to be done on db values--only allowed for SA mode ver115-5d db=referenceOpA*referenceTransform(currStep+1, 1)+referenceOpB*db end if for i=1 to 2 'modver115-3b if i=1 then c=Y1DataType else c=Y2DataType select c case constMagDBM y=db case constMagWatts pow=10^(db/20) y=pow/1000 case constMagV pow=10^(db/20) y=sqr(pow/20) 'square root of 50* mw/1000 case constAux0, constAux1, constAux2, constAux3, constAux4, constAux5 'ver115-4a if i=1 then y=y1 else y=y2 'Auxiliary data has already been calculated, so keep it case else 'constNoGraph, or invalid data type y=0 end select if i=1 then y1=y else y2=y next i end if 'end SA mode end if 'end all modes 'The point may not be integral, so we need to interpolate wholeStep=int(currStep) : fract=currStep-wholeStep if wholeStep=globalSteps or fract<0.0000001 then exit sub 'No need to interpolate; we are done 'We interpolate the required data types,not the raw S21, S11, etc. call CalcGraphData wholeStep+1, nextY1, nextY2, useWorkArray 'Get values at next step if Y1DataType<>constNoGraph then y1=LinearInterpolateDataType(Y1DataType, fract, y1, nextY1) if Y2DataType<>constNoGraph then y2=LinearInterpolateDataType(Y2DataType, fract, y2, nextY2) end sub 'ver115-4b added DataTypeIsAngle function DataTypeIsAngle(dataType) 'Return 1 if dataType is an angle; otherwise 0 select case thisType case constGraphS11Ang,constImpedAng,constAdmitAng, constAngle,constRawAngle 'angles--must worry about wraparound DataTypeIsAngle=1 case constAux0, constAux1, constAux2, constAux3, constAux4, constAux5 DataTypeIsAngle=auxGraphDataInfo(thisType,0) 'This has info on auxiliary data case else 'non-angles DataTypeIsAngle=0 end select end function 'ver115-4b added LinearInterpolateDataType function LinearInterpolateDataType(dataType, fract, v1, v2) 'Interpolate between values v1 and v2 based on fract 'If the dataType is an angle, deal with wraparound if DataTypeIsAngle(dataType) then interpVal=intLinearInterpolateDegrees(fract, v1, v2) 'Interpolation can produce an angle that is out-of-bounds, by no more than 360 degrees 'Note this may later be adjusted to the graph range if it is graphed if interpVal<=-180 then interpVal=interpVal+360 if interpVal>180 then interpVal=interpVal-360 LinearInterpolateDataType=interpVal else 'non-angles LinearInterpolateDataType=v1 + fract*(v2-v1) end if end function sub CalcReflectGraphData currStep, byref y1, byref y2, useWorkArray 'Calculate y1,y2 per user request 'If useWorkArray=1 then the data source is uWorkReflectData(); otherwise it is ReflectArray() 'Power is in uWorkArray(currStep+1,1), phase in uWorkArray(currStep+1,2) 'S11 db is in ReflectArray(currStep,2), phase in ReflectArray(currStep,3) for dataNum=2 to 1 step -1 if dataNum=1 then if msaMode$="SA" or msaMode$="ScalarTrans" then exit for 'don't have phase componConst=Y1DataType else componConst=Y2DataType end if select componConst case constGraphS11DB, constGraphS11Ang, constRho, constImpedMag, constImpedAng, constSerR,constSerReact,constParR,constParReact,_ constSerC,constSerL,constParC,constParL,constSWR 'All these have already been computed if useWorkArray then y=uWorkReflectData(componConst) else y=ReflectArray(currStep,componConst) 'ver115-1e case constTheta 'Same as angle if useWorkArray then y=uWorkReflectData(constGraphS11Ang) else y=ReflectArray(currStep,constGraphS11Ang) 'ver115-1e case constReturnLoss if useWorkArray then y=0-uWorkReflectData(constGraphS11DB) else y=0-ReflectArray(currStep,constGraphS11DB) 'ver115-1e case constReflectPower if useWorkArray then y=100*uWorkReflectData(constRho)^2 else y=100*ReflectArray(currStep,constRho)^2 'ver115-2d case constComponentQ 'ver115-2d 'Note that this formula works only for a single L or C. For LC combos, we would need the reactance 'of the individual components if useWorkArray then X=uWorkReflectData(constSerReact) : R=uWorkReflectData(constSerR) else X=ReflectArray(currStep,constSerReact) : R=ReflectArray(currStep,constSerR) end if if R=0 then y=99999 else y=abs(X)/R 'Q=X/R case constAdmitMag, constAdmitAng, constConductance, constSusceptance 'ver115-4a select case componConst case constAdmitMag if useWorkArray then mag=uWorkReflectData(constImpedMag) else mag=ReflectArray(currStep,constImpedMag) if mag=0 then y=constMaxValue else y=1/mag case constAdmitAng if useWorkArray then ang=uWorkReflectData(constImpedAng) else ang=ReflectArray(currStep,constImpedAng) y=0-ang case else 'constConductance, constSusceptance if useWorkArray then R=uWorkReflectData(constSerR) : X=uWorkReflectData(constSerReact) _ else R=ReflectArray(currStep,constSerR) : X=ReflectArray(currStep,constSerReact) call cxInvert R, X, G, S if componConst=constConductance then y=G else y=S end select case constAux0, constAux1, constAux2, constAux3, constAux4, constAux5 'ver115-4a if dataNum=1 then y=y1 else y=y2 'Auxiliary data has already been calculated, so keep it case else y=0 'invalid data, or None end select if dataNum=1 then 'Put data into y1 or y2 y1=y else y2=y end if next dataNum end sub 'ver115-1e added CalcTransmitGraphData sub CalcTransmitGraphData currStep, byref y1, byref y2, useWorkArray 'Calculate y1,y2 per user request 'If useWorkArray=1 then the data source is uWorkArray(); otherwise it is S21DataArray() 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=S21DataArray(currStep,1) 'ver115-2b ang=S21DataArray(currStep,2) 'ver115-2b end if 'ver115-1e deleted impedance transform for transmission mode for dataNum=1 to 2 'ver115-3b if dataNum=1 then componConst=Y1DataType else componConst=Y2DataType end if select componConst case constMagDB y=db case constMagDBM 'Used for transmission mode only ' added by ver115-1i if applyCalLevel=0 then y=db else y=db+lineCalArray(currStep,1) case constMagRatio y=10^(db/20) case constInsertionLoss y=0-db case constAngle 'Source data is raw y=ang case constRawAngle 'Used for transmission mode only ' added by ver115-1i if applyCalLevel=0 then y=ang else y=ang+lineCalArray(currStep,2) case constGD 'calc group delay if startfreq=endfreq then message$= "Can't calculate Group Delay with zero sweep width." : call PrintMessage y=-1 else call gGetSweepStartAndEndPointNum pStart, pEnd dir=gGetSweepDir() '1 or -1 if currStep=pStart-1 then y=-1 'Need two points; only have one at first point else if useWorkArray then y=(uWorkArray(currStep+1,2)-uWorkArray(currStep+1-dir,2))/360 _ else y=(datatable(currStep,3)-datatable(currStep-dir,3))/360 'delta phase in cycles ver114=4h if y>0.5 then y=y-1 else if y<-0.5 then y=y+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 y=0-y/deltaF 'negative of delta phase over delta freq end if end if case constAux0, constAux1, constAux2, constAux3, constAux4, constAux5 'ver115-4a if dataNum=1 then y=y1 else y=y2 'Auxiliary data has already been calculated, so keep it case else y=0 'invalid data, or None end select if dataNum=1 then 'Put data into y1 or y2 y1=y else y2=y end if next dataNum end sub 'ver114-7f added CreateReferenceSource sub CreateReferenceSource 'Return reference trace ver114-7e 'Create referenceSource() data in accordance with referenceLineType and referenceLineSpec$ 'referenceSource entries are numbered from 1 '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 ' referenceLineType=3 use fixed value references '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 'No reference lines needed 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=S11BridgeR0 : doSpecialJig$="S11" 'ver115-2a else doSpecialR0=S21JigR0 if S21JigAttach$="Series" then doSpecialJig$="S21Series" else doSpecialJig$="S21Shunt" end if 'TO DO--Note uRLCComboResponse does not adjust for S21JigShuntDelay. If we need to do so, do it here. 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 if referenceLineType=3 then '3=Fixed value s$=referenceLineSpec$ isErr=uExtractNumericItems(2, s$, ";",v1, v2, v3) referenceSourceNumPoints=gNumDynamicSteps()+1 for i=1 to referenceSourceNumPoints referenceSource(i, 0)=gGetPointXVal(i) 'Actual tuning freq, in MHz referenceSource(i, 1)=v1 'Fixed val for trace 1 referenceSource(i, 2)=v2 'Fixed val for trace 2 next i else 'referenceLineType=1; use current data 'ver115-7a modified this referenceSourceNumPoints=gNumDynamicSteps()+1 if msaMode$="SA"then source1=constMagDBM : source2=constNoGraph if msaMode$="ScalarTrans"then source1=constMagDB : source2=constNoGraph if msaMode$="VectorTrans"then source1=constMagDB : source2=constAngle if msaMode$="Reflection"then source1=constGraphS11DB : source2=constGraphS11Ang for i=1 to referenceSourceNumPoints referenceSource(i, 0)=gGetPointXVal(i) 'Actual tuning freq, in MHz 'No matter what we are doing with the reference, we save dB(m)/angle data as the "source" 'and later do any necessary "transform". call CalcGraphDataType i-1, source1, source2, y1, y2,0 'calc db/angle info referenceSource(i, 1)= y1 'dB or dBm referenceSource(i, 2)=y2 'angle or 0 next i end if end if end sub 'ver115-6d modified CreateReferenceTransform to move much of it to CalcReferencesWholeStep sub CreateReferenceTransform 'Transform referenceSource() data into actual graph data; put it into referenceTransform for i=0 to referenceSourceNumPoints-1 'iterate by step num, though referenceTransform starts at 1 (point num) call CalcReferencesWholeStep i, ref1, ref2 referenceTransform(i+1, 0)=referenceSource(i+1, 0) 'freq referenceTransform(i+1, 1)=ref1 'Trace 1 referenceTransform(i+1, 2)=ref2 'Trace 2 next i end sub 'ver115-6d created CalcReferencesWholeStep sub CalcReferencesWholeStep stepNum, byRef ref1, byRef ref2 'Calculate reference line data at whole step stepNum pointNum=stepNum+1 if referenceLineType=3 then 'Here we have a fixed value reference, which we don't need to transform. 'We just transfer the values. ref1=referenceSource(pointNum, 1) ref2=referenceSource(pointNum, 2) exit sub end if if msaMode$="Reflection" then 'For reflection we have to calculate a bunch of derived data, such as impedance, 'which may be needed to calculate the graph data. This is done frequency by frequency 'using uWorkReflectData() as an intermediary uWorkReflectData(0)=referenceSource(pointNum,0) 'freq uWorkReflectData(1)=referenceSource(pointNum, 1) 'db uWorkReflectData(2)=referenceSource(pointNum, 2) 'ang call CalcReflectDerivedData -1 'Calculate other reflection derived data from the above 'Calc graph data from info just put into uWorkReflectData thispointy1=0 : thispointy2=0 call CalcReflectGraphData -1, ref1, ref2, 1 else 'For non-reflection modes, the only source data we need for the calculations are 'freq, db and ang (or dBm as the case may be). We transfer all the data to uWorkArray 'and then calculate from there uWorkArray(1,0)=referenceSource(pointNum, 0) 'freq uWorkArray(1, 1)=referenceSource(pointNum, 1) 'db uWorkArray(1, 2)=referenceSource(pointNum, 2) 'ang call CalcGraphData 0, ref1, ref2, 1 'calc values from uWorkArray end if end sub 'ver115-6d sub CalcReferences stepNum, ref1IsAngle, byref ref1, ref2IsAngle, byref ref2 'Return value of reference lines at step stepNum, possibly fractional 'We interpolate if necessary. ref1IsAngle=1 means reference 1 is an angle and we have to 'deal with possible wraparound when interpolating. Likewise for ref2IsAngle if stepNum<0 then stepNum=0 if stepNum>globalSteps then stepNum=globalSteps 'The point may not be integral, so we need to interpolate whole=int(stepNum) : fract=stepNum-whole if fract=0 then call CalcReferencesWholeStep stepNum, ref1, ref2 exit sub else 'If we are not at a whole step, we need to interpolate. The regular graph will interpolate the value 'being graphed, not the underlying S11, so we do the same call CalcReferencesWholeStep whole, refA1, refA2 'ref values at wholeStep call CalcReferencesWholeStep whole+1, refB1, refB2 'ref values at wholeStep+1 if (referenceTrace and 1)=0 then ref1=0 'Don't have ref line for axis Y1 else if ref1IsAngle then 'angles--must worry about wraparound ref1=intLinearInterpolateDegrees(fract, refA1, refB1) 'Interpolation can produce an angle that is out-of-bounds, by no more than 360 degrees origY=ref1 call gGetYAxisRange 1, yMin, yMax if ref1>yMax then ref1=ref1-360 else if ref1yMax or ref1yMax then ref2=ref2-360 else if ref2yMax or ref20 then if referenceDoMath=0 then refHeadingColor1$=referenceColor1$ : refHeadingColor2$=referenceColor2$ 'Use ref color if ref line is drawn else call gGetTraceColors refHeadingColor1$, refHeadingColor2$ 'Use trace colors for "REF" if math is used end if if referenceLineType=3 then 'For fixed value ref, print the value semiPos=instr(referenceLineSpec$,";") v1$= "=";Left$(referenceLineSpec$, semiPos-1) 'Up to semicolon is first value v2$= "=";Mid$(referenceLineSpec$, semiPos+1) 'After semicolon is second value else v1$="" : v2$="" end if if (referenceTrace and 2) then call gPrintAxisAnnotation 2, "Ref";v2$, "Tahoma 8 bold", refHeadingColor2$ end if if (referenceTrace and 1) then call gPrintAxisAnnotation 1, "Ref";v1$, "Tahoma 8 bold", refHeadingColor1$ end if end if 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) 'Trace 1 data uWorkArray(i, 2)=referenceTransform(i, 2) 'Trace 2 data 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 'draw final segment (of this larger segment) in reverse to be sure the very last pixel gets drawn. if currPoint=endPoint then t$=t$;";"; "line ";x;" ";y;" ";lastX; " ";lastY 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 call RequireRestart 'ver115-1c 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 call RequireRestart 'ver115-1c 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 call RequireRestart 'ver115-1c 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 call RequireRestart 'ver115-1c 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 call RequireRestart 'ver115-1c 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 call RequireRestart 'ver115-1c 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 'ver115-1c added GetDialogPlacement sub GetDialogPlacement 'calculate top left for placement of dialog 'Dialog height,width are in WindowHeight, WindowWidth. Placement is put into UpperLeftX and UpperLeftY 'Dialog is placed relative to parent window client origin. Place so it does not cover graph area, 'aligned with right graph window edge. call gGetGridCorner "LR", cornerX, cornerY UpperLeftX = currGraphBoxWidth+clientWidthOffset-WindowWidth-30 'puts right edge of dialog near right window edge UpperLeftY=cornerY+30 'puts top of dialog under graph end sub 'ver114-5j added [menuVNARef] [menuVNARef] if haltsweep=1 then gosub [FinishSweeping] WindowWidth = 150 : WindowHeight = 150 call GetDialogPlacement 'ver115-1c BackgroundColor$="gray" 'ver115-5b ForegroundColor$="black" TextboxColor$="white" ComboboxColor$="white" 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 checkbox #VNAref.Line, "Band Sweep Cal", [VNAapplyLineOn], [VNAapplyLineOff], VNAinfoLeft+5,VNAapplyTop+45, 150, 15 checkbox #VNAref.BaseLine, "Baseline Cal", [VNAapplyBaseLineOn], [VNAapplyBaseLineOff], VNAinfoLeft+5,VNAapplyTop+65, 150, 15 checkbox #VNAref.None, "No Reference", [VNAapplyNoneOn], [VNAapplyNoneOff], VNAinfoLeft+5,VNAapplyTop+85, 150, 15 open "Ref" for dialog_modal as #VNAref 'ver115-1b print #VNAref, "trapclose [VNARefFinished]" 'goto [finished] if xit is clicked savedesiredCalLevel=desiredCalLevel 'ver114-5L if desiredCalLevel=0 then #VNAref.None, "set" : wait if desiredCalLevel=2 then #VNAref.Line, "set" : wait #VNAref.BaseLine, "set" wait 'ver114-5j added [VNARefFinished] [VNARefFinished] #VNAref.None, "value? calLevel$" 'ver115-1b applied same procedure to reflection as for transmission if calLevel$="set" then desiredCalLevel=0 else #VNAref.BaseLine, "value? calLevel$" if calLevel$="set" then desiredCalLevel=1 else desiredCalLevel=2 end if 'Implement selected calibration if anything changed if savedesiredCalLevel<>desiredCalLevel then 'ver114-5L created if... applyCalLevel=0 'Pretend nothing is now installed installedBaseLineNumSteps=-1 'ver115-1b call RequireRestart 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 'ver115-1a 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 10" #PDMcal.t2, "!font Times_New_Roman 9" #PDMcal.t3, "!font Times_New_Roman 9" #PDMcal.t4, "!font Times_New_Roman 9" #PDMcal.t5, "!font Times_New_Roman 9" #PDMcal.t6, "!font Times_New_Roman 9" #PDMcal.t7, "!font Times_New_Roman 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 'ver115-3b added [menuPrimaryAxis]; modver115-3c [menuPrimaryAxis] if haltsweep=0 then gosub [FinishSweeping] if ChoosePrimaryAxis()=1 then 'Returns 0 if cancelled ver115-3c call gUsePresetColors gGetLastPresetColors$() 'Reselect same appearance in case primary axis change had effect. select case msaMode$ case "Reflection" goto [RestartReflectionMode] case "ScalarTrans", "VectorTrans" goto [RestartTransmissionMode] case else ' "SA" if gentrk=1 then goto [RestartSATGmode] else goto [RestartPlainSAmode] 'ver115-4f end select end if wait 'ver115-3b added ChoosePrimaryAxis; mod 115-3c function ChoosePrimaryAxis() 'Lets user choose axis 1 or 2 as the primary axis. Return 0 if cancelled; otherwise 1 WindowWidth = 465 WindowHeight = 300 UpperLeftX=100 UpperLeftY=100 ForegroundColor$="black" BackgroundColor$="buttonface" statictext #primaryaxis, "Your may choose either the left axis (axis Y1) or the right axis (axis Y2)", 5, 5, 425, 20 statictext #primaryaxis, "to be the primary axis. When starting up or changing modes, magnitude", 5, 25, 430, 20 statictext #primaryaxis, "will be graphed on the primary axis. Certain analyses, such as Filter", 5, 45, 415, 20 statictext #primaryaxis, "and Crystal Analysis, require dB to be graphed on the primary axis.", 5, 65, 415, 20 statictext #primaryaxis, "You must Restart after changing the primary axis.", 5, 85, 415, 20 checkbox #primaryaxis.Y1, "Left Axis (Y1)", [primarySelY1], [primarySelY1], 145, 147, 101, 25 checkbox #primaryaxis.Y2, "Right Axis (Y2)", [primarySelY2], [primarySelY2], 145, 177, 111, 25 button #primaryaxis.Done,"Done",[primaryDone], UL, 35, 217, 105, 35 button #primaryaxis.Cancel,"Cancel",[primaryCancel], UL, 245, 217, 100, 35 statictext #primaryaxis.statictext9, "Choose Primary Axis", 130, 122, 124, 20 open "Primary Axis" for dialog_modal as #primaryaxis print #primaryaxis, "font ms_sans_serif 10" print #primaryaxis, "trapclose [primaryDone]" if primaryAxisNum=1 then goto [primarySelY1] else goto [primarySelY2] wait [primarySelY1] 'Perform action for the checkbox named 'Y1' #primaryaxis.Y1, "set" : #primaryaxis.Y2, "reset" wait [primarySelY2] 'Perform action for the checkbox named 'Y2' #primaryaxis.Y2, "set" : #primaryaxis.Y1, "reset" wait [primaryDone] 'Perform action for the button named 'Done' #primaryaxis.Y1, "value? primaryY1Val$" if primaryY1Val$="set" then primaryAxisNum=1 else primaryAxisNum=2 call gSetPrimaryAxis primaryAxisNum 'ver115-3c lastCol$=gGetLastPresetColors$ if lastCol$="DARK" or lastCol$="LIGHT" then _ call gUsePresetColors lastCol$ 'Reset colors; may be affected by primary axis change ver115-3c close #primaryaxis ChoosePrimaryAxis=1 exit function [primaryCancel] 'Perform action for the button named 'Cancel' close #primaryaxis ChoosePrimaryAxis=0 exit function end function sub ExplainTransCal h$ 'Put up dialog explaining band/base and transmission cal WindowWidth = 635 WindowHeight = 220 UpperLeftX=0 'Doesn't seem to matter what is specified here UpperLeftY=150 BackgroundColor$="gray" ForegroundColor$="black" statictext #Explain, "Band calibration is performed at the frequency points of immediate interest and is used only as", 10, 10, 630, 20 statictext #Explain, "long as the sweep matches those points. Base calibration is performed over a broad frequency range,", 10, 30, 630, 20 statictext #Explain, "to be interpolated to the current sweep frequencies when there is no current band calibration.", 10, 50, 630, 20 statictext #Explain, "To create a Base calibration you perform a Band calibration and save it as a Base calibration.", 10, 70, 630, 20 statictext #Explain, "It is intended as a convenient coarse reference, especially when phase precision is not required.", 10, 90, 630, 20 statictext #Explain, "In Transmission Mode, Base calibrations are saved in a file for use in future sessions.", 10, 110, 630, 20 statictext #Explain, "In Transmision Mode you also specify the time delay of the calibration Through connection,", 10, 130, 630, 20 statictext #Explain, "which is ideally zero but may be greater if you need to use an adapter.", 10, 150, 630, 20 open "Reflection Calibration Help" for dialog_modal as #Explain #Explain, "trapclose [ExplainTransCalFinished]" print #Explain, "font ms_sans_serif 10" wait [ExplainTransCalFinished] close #Explain end sub 'ver114-5e added [RunVNACal] mod115-1b for reflection cal; ver115-1g revised it [RunVNACal] if haltsweep=1 then gosub [FinishSweeping] WindowWidth = 600 : WindowHeight = 400 call GetDialogPlacement 'set UpperLeftX and UpperLeftY ver115-1c UpperLeftY=UpperLeftY-100 BackgroundColor$="gray" 'ver115-5b changed color ForegroundColor$="black" TextboxColor$ = "white" ComboboxColor$="white" 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,560, 18 statictext #VNAcal.Path3, "for which the calibration will be used, close this window and change the path selection.",25,52,525, 18 statictext #VNAcal.Video, "VIDEO FILTER should be set to NARROW bandwidth for maximum smoothing.",25,75,525, 18 VNAbtnLeft=25 : VNAbtnTop=80 s$="Band Sweep calibration is run at the same frequency points at which it will be used." statictext #VNAcal.BandInst, s$,VNAbtnLeft+25,VNAbtnTop+42,500, 35 s$="You may save the current Band calibration as a Base calibration, to be used as a coarse" s$=s$;" reference when the Band calibration is not current." if steps>2000 then s$="(Saving Base Line calibration is disabled because it is limited to 2,000 steps.)" 'ver115-1b statictext #VNAcal.BaseInst, s$,VNAbtnLeft+25,VNAbtnTop+85,450, 40 if msaMode$="VectorTrans" then 'ver115-4e statictext #VNAcal.connect, "TG output must have THROUGH connection to MSA input.",25,90,550, 18 statictext #VNAcal.DelayLabel, "Delay of Calibration Through Connection (ns):",VNAbtnLeft+10,VNAbtnTop+160,270, 20 textbox #VNAcal.Delay, VNAbtnLeft+282,VNAbtnTop+160,50, 20 else 'Reflection statictext #VNAcal.connect, "Connect TG output and MSA input to test fixture and attach proper cal standards.",25,90,550, 18 end if statictext #VNAcal.LastBandCal, "xx",VNAbtnLeft,VNAbtnTop+62,570, 18 'Description of last calibration statictext #VNAcal.LastBaseCal, "xx",VNAbtnLeft,VNAbtnTop+120,570, 18 'Description of last calibration button #VNAcal.Perform, "Perform Band Cal",[PerformCal], UL, VNAbtnLeft+10, VNAbtnTop+210, 120,25 'ver114-5f button #VNAcal.ClearBand, "Clear Band Cal",[ClearBandCal], UL, VNAbtnLeft+175, VNAbtnTop+210, 120,25 'ver114-5f button #VNAcal.SaveBase, "Save As Base",[SaveBaseCal], UL, VNAbtnLeft+10, VNAbtnTop+250, 120,25 'ver114-5f button #VNAcal.ClearBase, "Clear Base Cal",[ClearBaseCal], UL, VNAbtnLeft+175, VNAbtnTop+250, 120,25 'ver114-5f button #VNAcal.Done, "Done",[VNACalFinished], UL, VNAbtnLeft+375, VNAbtnTop+210, 75,25 button #VNAcal.Explain, "Help",ExplainTransCal, UL, VNAbtnLeft+375, VNAbtnTop+250, 75,25 open "Perform Calibration" for dialog_modal as #VNAcal 'ver114-3g print #VNAcal, "trapclose [VNACalFinished]" 'goto [finished] if xit is clicked print #VNAcal, "font ms_sans_serif 10" ' #VNAcal.Path1, "!font Times_New_Roman 10" ' #VNAcal.Path2, "!font Times_New_Roman 10" ' #VNAcal.Path3, "!font Times_New_Roman 10" ' #VNAcal.Video, "!font Times_New_Roman 10" ' #VNAcal.connect, "!font Times_New_Roman 10" #VNAcal.Path1, "The MSA is currently in "; path$ 'ver114-5p calInProgress=0 BandSweepCalDone=0 'ver114-5L 'ver115-2d if msaMode$="VectorTrans" then 'ver115-4e #VNAcal.Delay, lineCalThroughDelay 'Delay in ns 'ver115-5a end if 'Display info about last band and base cals if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then 'ver115-1b #VNAcal.LastBandCal, "Band: ";CalInfo$(bandLinePath$, bandLineTimeStamp$, bandLineLinear, _ bandLineNumSteps, bandLineStartFreq, bandLineEndFreq) #VNAcal.LastBaseCal, "Base: ";CalInfo$(baseLinePath$, baseLineTimeStamp$, baseLineLinear, _ baseLineNumSteps, baseLineStartFreq, baseLineEndFreq) else #VNAcal.LastBandCal, "Band: ";CalInfo$(OSLBandPath$, OSLBandTimeStamp$, OSLBandLinear, _ OSLBandNumSteps, OSLBandStartFreq, OSLBandEndFreq) #VNAcal.LastBaseCal, "Base: ";CalInfo$(OSLBasePath$, OSLBaseTimeStamp$, OSLBaseLinear, _ OSLBaseNumSteps, OSLBaseStartFreq, OSLBaseEndFreq) end if wait [VNACalFinished] if calInProgress=1 then goto [PostScan] 'Don't allow quit in middle of cal if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then 'ver115-4e if msaMode$="VectorTrans" then 'ver115-4e #VNAcal.Delay, "!contents? s$" lineCalThroughDelay=val(uCompact$(s$)) 'Store in ns; used to initialize if we open dialog again ver115-5a else lineCalThroughDelay=0 end if 'If we did a cal, make it the desired one and force restart to implement if BandSweepCalDone=1 then 'ver114-5L created if... 'ver115-2d if BandSweepCalDone then desiredCalLevel=2 'desire BandSweep; overrides BaseLine ver114-5L 'ver115-2d applyCalLevel=0 'Pretend nothing is now installed, so new cal gets installed on Restart installedBaseLineNumSteps=-1 'ver115-5b call RequireRestart 'To activate desired cal; graph is messed up anyway ver114-5L end if else 'Reflection; handled by [PerformOSLCal] end if close #VNAcal 'ver114-5n moved this outside the if... block wait 'ver114-5j added SetCalButtonStatus sub SetCalButtonStatus stat$ 'Enable or disable all calibration buttons 'stat$ should be "!enable" or "!disable" #VNAcal.Perform, stat$ #VNAcal.SaveBase, stat$ #VNAcal.ClearBand, stat$ #VNAcal.ClearBase, stat$ #VNAcal.Done, stat$ end sub 'ver114-5j added [CalAborted] [CalAborted] 'Common routine for aborting calibration gosub [FinishSweeping] 'Finish nicely 'ver114-7d #VNAcal.Perform, "Perform Band Cal" 'ver115-1e 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 'ver115-1b gosub [PerformOSLCal] 'ver115-5b changed back to gosub so others can call [PerformOSLCal] #VNAcal.LastBandCal, "Band: ";CalInfo$(OSLBandPath$, OSLBandTimeStamp$, OSLBandLinear, _ OSLBandNumSteps, OSLBandStartFreq, OSLBandEndFreq) 'ver115-5b wait else 'ver115-1f moved some items here from [BandLineCal] to make it independent of this dialog if calInProgress then gosub [CalAborted] : wait call SetCalButtonStatus "!disable" #VNAcal.Perform, "!enable" : #VNAcal.Perform, "Abort Cal" if msaMode$="VectorTrans" then 'ver115-5a #VNAcal.Delay, "!contents? s$" lineCalThroughDelay=val(uCompact$(s$)) 'Store in ns; used by [BandLineCal] else lineCalThroughDelay=0 end if gosub [BandLineCal] #VNAcal.Perform, "Perform Band Cal" BandSweepCalDone=1 'ver114-5L #VNAcal.LastBandCal, "Band: ";CalInfo$(bandLinePath$, bandLineTimeStamp$, bandLineLinear, _ bandLineNumSteps, bandLineStartFreq, bandLineEndFreq) call SetCalButtonStatus "!enable" wait end if 'Can't get here [ClearBandCal] if msaMode$="Reflection" then OSLBandNumSteps=-1 else bandLineNumSteps=-1 end if #VNAcal.LastBandCal, "Band: Calibration is cleared." wait [ClearBaseCal] if msaMode$="Reflection" then OSLBaseNumSteps=-1 else 'Clear baseline and delete the file baseLineNumSteps=-1 Kill DefaultDir$;"\MSA_Info\OperatingCal\BaseLineCal.txt" end if #VNAcal.LastBaseCal, "Base: Calibration is cleared." wait 'ver114-5f addedd [LineCal] [BandLineCal] 'Run Line Calibration and return. Can be called from anywhere; lineCalThroughDelay must be set 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=max(wate,110) 'Increase wait time if necessary ver115-4a planeadj=0 'So phase will not be affected applyCalLevel=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 if msaMode$="VectorTrans" then 'ver115-5a degPerMillionHz=360000000*lineCalThroughDelay 'lineCalThroughDelay is delay in ns ver115-5a else degPerMillionHz=0 end if for i=0 to steps 'retrieve data 'ver114-8a added through delay calc freq=gGetPointXVal(i+1) 'freq in MHz actual tuning freq, not equiv 1G freq ver115-5c phaseDelay=degPerMillionHz*freq bandLineCal(i,0)=freq 'frequency bandLineCal(i,1)=datatable(i,2) 'mag p=datatable(i,3)+phaseDelay 'Phase, with through delay removed 'ver115-4g p=p mod 360 if p<=-180 then p=p+360 else if p>180 then p=p-360 'put in range -180 to 180 bandLineCal(i,2)=p next i 'Save the conditions under which the cal was done bandLineStartFreq=startfreq bandLineEndFreq=endfreq bandLineNumSteps=steps bandLineLinear=gGetXIsLinear() bandLineS21JigAttach$=S21JigAttach$ 'ver115-1b bandLineS21JigR0=S21JigR0 'ver115-1b bandLinePath$=path$ bandLineTimeStamp$=date$("mm/dd/yy"); "; ";time$() calInProgress=0 desiredCalLevel=2 'opt for using band cal since we just did it ver114-6b return sub TransferBandToBaseLineCal 'Create base line cal from band line cal but don't save to file ver115-5c baseLineNumSteps=min(bandLineNumSteps,2000) 'Base cal can only have 2000 steps for i=0 to baseLineNumSteps baseLineCal(i,0)=bandLineCal(i,0) 'frequency baseLineCal(i,1)=bandLineCal(i,1) 'mag baseLineCal(i,2)=bandLineCal(i,2) 'phase next i 'Save the conditions under which the cal was done baseLineStartFreq=bandLineStartFreq baseLineEndFreq=bandLineEndFreq baseLineLinear=bandLineLinear baseLineS21JigAttach$=bandLineS21JigAttach$ baseLineS21JigR0=bandLineS21JigR0 baseLinePath$=bandLinePath$ 'ver115-1e baseLineTimeStamp$=bandLineTimeStamp$ end sub sub TransferBandToBaseOSLCal 'Create base OSL cal from band OSL cal but don't save to file ver115-5c OSLBaseNumSteps=min(OSLBandNumSteps,2000) 'Base cal can only have 2000 steps for i=0 to OSLBaseNumSteps 'ver115-2d OSLBaseRef(i,0)=OSLBandRef(i,0) 'Reference, frequency OSLBaseRef(i,1)=OSLBandRef(i,1) 'mag OSLBaseRef(i,2)=OSLBandRef(i,2) 'phase OSLBaseA(i,0)=OSLBandA(i,0) 'Coeff A, real OSLBaseA(i,1)=OSLBandA(i,1) 'Coeff A, imag OSLBaseB(i,0)=OSLBandB(i,0) 'Coeff B, real OSLBaseB(i,1)=OSLBandB(i,1) 'Coeff B, imag OSLBaseC(i,0)=OSLBandC(i,0) 'Coeff C, real OSLBaseC(i,1)=OSLBandC(i,1) 'Coeff C, imag next i OSLBaseStartFreq=OSLBandStartFreq OSLBaseEndFreq=OSLBandEndFreq OSLBaseLinear=OSLBandLinear OSLBasePath$=OSLBandPath$ OSLBaseS11JigType$=OSLBandS11JigType$ OSLBaseS21JigAttach$=OSLBandS21JigAttach$ OSLBaseS11BridgeR0=OSLBandS11BridgeR0 OSLBaseS21JigR0=OSLBandS21JigR0 OSLBaseApplyFull=OSLBandApplyFull OSLBaseTimeStamp$=OSLBandTimeStamp$ end sub 'ver115-1e added [SaveBaseCal] [SaveBaseCal] 'Save current cal as base cal if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then call TransferBandToBaseLineCal 'ver115-5c call SaveBaseLineCalFile 'Save base line in a file #VNAcal.LastBaseCal, "Base: ";CalInfo$(baseLinePath$, baseLineTimeStamp$, baseLineLinear, _ baseLineNumSteps, baseLineStartFreq, baseLineEndFreq) else 'Reflection call TransferBandToBaseOSLCal 'ver115-5c #VNAcal.LastBaseCal, "Base: ";CalInfo$(OSLBasePath$, OSLBaseTimeStamp$, OSLBaseLinear, _ OSLBaseNumSteps, OSLBaseStartFreq, OSLBaseEndFreq) end if wait function CalInfo$(cPath$, dateStamp$, cLinear, nSteps, fStart, fEnd) 'Return line or OSL cal info in a string if nSteps<0 then CalInfo$="Calibration is cleared." : exit function if cLinear then lin$="linear" else lin$="log" CalInfo$="Performed ";dateStamp$;"; ";cPath$;"; ";nSteps;" ";lin$;" steps, ";fStart;" to ";fEnd;" MHz." 'ver115-1g 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 'ver115-1b end function 'ver115-1b 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 ver115-1b 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-1L 'If the installed Base line cal has different time stamp from current Base cal, then current is not installed if installedBaseLineTimeStamp$<>baseLineTimeStamp$ then BaseLineCalIsInstalled=0 : exit function 'ver115-2d call gGetXAxisRange xMin, xMax if globalSteps=installedBaseLineNumSteps and gGetXIsLinear()=installedBaseLineLinear and _ xMin=installedBaseLineStartFreq and xMax=installedBaseLineEndFreq then _ BaseLineCalIsInstalled=1 else BaseLineCalIsInstalled=0 'ver115-1b end function 'ver114-5f added InstallSelectedLineCal sub InstallSelectedLineCal 'Apply full line cal or baseLine cal per applyCalLevel '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 desiredCalLevel=2 and LineCal is current, install it if calInProgress then 'ver115-1e 'Here we want no type of cal, so clear lineCalArray call ClearCalArray globalSteps applyCalLevel=0 'Indicate that no cal is effective exit sub end if if desiredCalLevel=2 then isCurr=BandLineCalIsCurrent() 'If we are already applying cal, and it is valid and the installed time stamp matches the band cal, we are done if installedBandLineTimeStamp$=bandLineTimeStamp$ and applyCalLevel=2 and isCurr then exit sub 'ver115-2d if isCurr then applyCalLevel=2 else applyCalLevel=1 else applyCalLevel=1 'base cal end if if applyCalLevel=2 then installedBaseLineNumSteps=-1 'Indicate that base line cal is not installed ver115-1b fixed typo for i=0 to globalSteps 'retrieve data lineCalArray(i,0)=bandLineCal(i,0) 'freq 'ver115-5c lineCalArray(i,1)=bandLineCal(i,1) 'mag lineCalArray(i,2)=bandLineCal(i,2) 'Phase next i installedBandLineTimeStamp$=bandLineTimeStamp$ 'ver115-2d exit sub end if 'We get here if applyCalLevel<2 or we did not have a current LineCal, so use BaseLineCal if desiredCalLevel>0 then if BaseLineCalIsCurrent() then applyCalLevel=1 else applyCalLevel=0 'ver115-1b else applyCalLevel=0 end if if applyCalLevel=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 1+max(baseLineNumSteps, globalSteps) 'Be sure we have room ver115-9d 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 '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 'ver115-2d eliminated rounding lineCalArray(i,1)=m p=gNormalizePhase(p) 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() installedBaseLineTimeStamp$=baseLineTimeStamp$ 'ver115-2d 'ver115-1b xLL deleted installedBaseLinePath$ 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 ClearLineCalArray; modver115-1b sub ClearCalArray nSteps 'Clear array containing current installed Line or OSL cal data for i=0 to nSteps : lineCalArray(i,0)=0 : lineCalArray(i,1)=0 : lineCalArray(i,2)=0 : next i installedBaseLineNumSteps=-1 applyCalLevel=0 'Signal that none is installed installedOSLBaseNumSteps=-1 'We don't have to actually clear the OSL arrays end sub '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 sub FunctChangeAndSaveSweepParams saveSettings, bandToBase, newSteps, newStart, newEnd, newLinear 'Change sweep params for use in a Function; save old params 'We also set sweep direction, planeadj and wate to default values 'We also save the current band cal as a base cal. If saveSettings=1 we also save the current sweep settings. 'if bandToBase=1, we transfer the existing band cal to the base cal (but not to the file) and use it. 'Caller must set steps (but not globalSteps) before calling us because we can't change steps, but 'we will handle informing the graph module of the new number of steps 'Currently, this does not work for Reflection mode, because OSL is not saved. 'Example of Use: ' steps=100 'Note globalSteps will change in FunctChangeAndSaveSweepParams ' call FunctChangeAndSaveSweepParams 1,1,1, 100, 2, 200, 1 'save settings and cal and change to Linear 2 to 200 MHz, 100 steps ' specialOneSweep=1 'So we return from [Restart] ' gosub [Restart] 'Do actual scan to acquire data ' ...Process data... ' gosub [FunctRestoreSweepParams] ' gosub [PartialRestart] 'or call RequireRestart 'If a function calls several times, the existing settings should be saved only on the first call; otherwise 'the saved data will get overwritten by the previous changes if saveSettings then 'Save existing settings functSaveAlternate=alternateSweep : functSaveSweepDir=sweepDir : functSavePlaneAdj=planeadj : functSaveWate=wate functSaveSteps=globalSteps : functSaveStartFreq=startfreq : functSaveEndFreq=endfreq functSaveAutoY1=autoScaleY1 : functSaveAutoY2=autoScaleY2 functSaveY1Mode=Y1DisplayMode : functSaveY1Mode=Y1DisplayMode functSaveY1DataType=Y1DataType : functSaveY2DataType=Y2DataType call gGetIsLinear functSaveXIsLinear, functSaveY1IsLinear, functSaveY2IsLinear call gGetNumDivisions functSaveNumHorDiv, functSaveNumVertDiv 'Note log sweep changes the hor divisions functSaveDesiredCalLevel=desiredCalLevel end if 'Set up the sweep params we want wate=max(wate,110) 'increase wate to 110; don't decrease it alternateSweep=0 : sweepDir=1 : planeadj=0 globalSteps=newSteps 'Caller must change steps call gSetXIsLinear newLinear call gSetNumDynamicSteps globalSteps 'Tell graph module call SetStartStopFreq newStart, newEnd if bandToBase and (msaMode$="VectorTrans" or msaMode$="ScalarTrans") then call TransferBandToBaseLineCal 'Make current band cal into a base cal so it can be interpolated desiredCalLevel=1 'Use the base cal we just created applyCalLevel=0 'So new cal will be installed on Restart end if end sub [FunctRestoreSweepParams] 'Restore params and base cal to what they were when function was entered 'Not a true subroutine so it can access steps. sweepDir=functSaveSweepDir : alternateSweep=functSaveAlternate planeadj=functSavePlaneAdj : wate=functSaveWate steps=functSaveSteps : startfreq=functSaveStartFreq : endfreq=functSaveEndFreq globalSteps=steps autoScaleY1=functSaveAutoY1 : autoScaleY2=functSaveAutoY2 Y1DisplayMode=functSaveY1Mode : Y1DisplayMode=functSaveY1Mode Y1DataType=functSaveY1DataType : Y2DataType=functSaveY2DataType call gSetIsLinear functSaveXIsLinear, functSaveY1IsLinear, functSaveY2IsLinear call gSetNumDynamicSteps steps 'Tell graph module call SetStartStopFreq functSaveStartFreq, functSaveEndFreq call gSetNumDivisions functSaveNumHorDiv, functSaveNumVertDiv if msaMode$="VectorTrans" or msaMode$="ScalarTrans" then dum=LoadBaseLineCalFile() 'Reload base cal file to restore prior state end if desiredCalLevel=functSaveDesiredCalLevel 'ver115-5e applyCalLevel=0 'So new cal will get installed on Restart 'ver115-5e return '---------------Routines to Handle OSL Calibration------------ added by ver115-1b function BandOSLCalIsCurrent() 'Returns 1 if band OSL cal data was taken at current sweep settings 'Current means the band cal exists and matches current sweep params call gGetXAxisRange xMin, xMax if globalSteps=OSLBandNumSteps and gGetXIsLinear()=OSLBandLinear and path$=OSLBandPath$ and _ xMin=OSLBandStartFreq and xMax=OSLBandEndFreq and _ OSLBandS11JigType$=S11JigType$ then isCurr=1 else isCurr=0 if isCurr then 'do further tests for matching jig characteristics if S11JigType$="Trans" then 'ver115-2c if OSLBandS21JigAttach$<>S21JigAttach$ or OSLBandS21JigR0<>S21JigR0 then isCurr=0 else if OSLBandS11BridgeR0<>S11BridgeR0 then isCurr=0 end if end if BandOSLCalIsCurrent=isCurr end function function BaseOSLCalIsCurrent() 'Returns 1 if OSL base cal has valid data even if different sweep params 'Current does not mean it is actually installed if OSLBaseNumSteps>0 and path$=OSLBasePath$ and OSLBaseS11JigType$=S11JigType$ then _ isCurr=1 else isCurr=0 if isCurr then 'do further tests for matching jig characteristics if S11JigType$="Trans" then if OSLBaseS21JigAttach$<>S21JigAttach$ or OSLBaseS21JigR0<>S21JigR0 then isCurr=0 else if OSLBaseS11BridgeR0<>S11BridgeR0 then isCurr=0 end if end if if isCurr then BaseOSLCalIsCurrent=1 else BaseOSLCalIsCurrent=0 : installedOSLBaseNumSteps=-1 : OSLBaseNumSteps=-1 'Mark everything as not valid end if end function function BaseOSLCalIsInstalled() 'Returns 1 if OSL 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 BaseOSLCalIsCurrent()=0 then BaseOSLCalIsInstalled=0 : exit function 'Don't have current base cal 'If the installed Base cal has different time stamp from current Base cal, then current is not installed if installedOSLBaseTimeStamp$<>OSLBaseTimeStamp$ then BaseOSLCalIsInstalled=0 : exit function 'ver115-2d call gGetXAxisRange xMin, xMax if globalSteps=installedOSLBaseNumSteps and gGetXIsLinear()=installedOSLBaseLinear and _ xMin=installedOSLBaseStartFreq and xMax=installedOSLBaseEndFreq then _ BaseOSLCalIsInstalled=1 else BaseOSLCalIsInstalled=0 end function sub InstallSelectedOSLCal 'Apply base or band OSL cal per applyCalLevel 'We put the necessary data into lineCalArray and OSLx(), and set applyCalLevel to 0(None), 1 (BaseLine) 'or 2 (Full LineCal) to indicate the level of line cal actually installed. 'If desiredCalLevel=2 and Cal is current, install it 'If a calibration is in progress, we don't install a cal, but use a zero line cal reference. if calInProgress then 'ver115-1e 'Here we want no type of cal, so clear lineCalArray call ClearCalArray globalSteps applyCalLevel=0 'Indicate that no OSL is effective installedOSLBaseNumSteps=-1 OSLApplyFull=0 exit sub end if if desiredCalLevel=2 then isCurr=BandOSLCalIsCurrent() 'If we are already applying cal, and it is valid and the installed time stamp matches the band cal, we are done if installedOSLBandTimeStamp$=OSLBandTimeStamp$ and applyCalLevel=2 and isCurr then exit sub 'ver115-2d if isCurr then applyCalLevel=2 else applyCalLevel=1 else applyCalLevel=1 end if if applyCalLevel=2 then 'We have determined to install Band cal installedOSLBaseNumSteps=-1 'Indicate that base cal is not installed else 'We get here if applyCalLevel<2 or we did not have a current band cal, so use base cal if available if desiredCalLevel>0 then if BaseOSLCalIsCurrent() then applyCalLevel=1 else applyCalLevel=0 else applyCalLevel=0 end if end if if applyCalLevel=0 then 'ver115-1e 'Here we want no type of OSL cal, so clear lineCalArray call ClearCalArray globalSteps applyCalLevel=0 'Indicate that no OSL is effective installedOSLBaseNumSteps=-1 OSLApplyFull=0 end if if applyCalLevel=1 then if BaseOSLCalIsInstalled() then exit sub 'Already installed with these sweep params 'install the base reference into lineCalArray if applyCalLevel=1 then 'base cal--must interpolate OSLApplyFull=OSLBaseApplyFull 'Save the sweep params under which we installed base OSL cal installedOSLBaseStartFreq=startfreq installedOSLBaseEndFreq=endfreq installedOSLBaseNumSteps=globalSteps installedOSLBaseLinear=gGetXIsLinear() installedOSLBaseTimeStamp$=OSLBaseTimeStamp$ 'ver115-2d 'Create source interpolation table and fill in desired dest frequencies call intSetMaxNumPoints 1+max(OSLBaseNumSteps, globalSteps) 'Be sure we have room ver115-9d call intClearSrc : call intClearDest ' ver115-2d for i=0 to OSLBaseNumSteps 'copy cal table to intSrc ver115-2d call intAddSrcEntry OSLBaseRef(i,0),OSLBaseRef(i,1),gNormalizePhase(OSLBaseRef(i,2)) next i for i=1 to globalSteps+1 call intAddDestFreq gGetPointXVal(i) 'Install the desired frequencies intDest next i 'Do the actual interpolation into intDest() '1 means data is polar , 0 means do linear interp, 3 means do both params call intSrcToDest 1, 0, 3 'put the data where we want it; it is now in intDest for i=0 to globalSteps call intGetDest i+1,f, m, p lineCalArray(i,0)=f 'ver115-2d eliminated rounding lineCalArray(i,1)=m p=gNormalizePhase(p) lineCalArray(i,2)=p next i else 'Band cal--no interpolation, just copy OSLApplyFull=OSLBandApplyFull installedOSLBandTimeStamp$=OSLBandTimeStamp$ 'ver115-2d for i=0 to globalSteps lineCalArray(i,0)=OSLBandRef(i,0) lineCalArray(i,1)=OSLBandRef(i,1) lineCalArray(i,2)=OSLBandRef(i,2) next i end if 'Next, if we use OSL coefficients, install them if OSLApplyFull=0 then exit sub if applyCalLevel=1 then 'base cal--interpolate coefficients a, b, c 'Note the desired frequencies are already in intDest call intClearSrc 'Clear source from which we interpolate ver115-2d 'First install the a coefficients into OSLa(). Note these are in rectangular form for i=0 to OSLBaseNumSteps 'copy cal table to intSrc call intAddSrcEntry OSLBaseRef(i,0),OSLBaseA(i,0),OSLBaseA(i,1) next i 'Do the actual interpolation into intDest() 'First 0 means not polar, second 0 means do linear interp, 3 means do both params call intSrcToDest 0, 0, 3 for i=0 to globalSteps 'put the data where we want it call intGetDest i+1,f, real, imag OSLa(i,0)=real OSLa(i,1)=imag next i 'install the b coefficients into OSLb(). Note these are in rectangular form call intClearSrc 'Clear source from which we interpolate ver115-2d for i=0 to OSLBaseNumSteps 'copy cal table to intSrc call intAddSrcEntry OSLBaseRef(i,0),OSLBaseB(i,0),OSLBaseB(i,1) next i 'Do the actual interpolation into intDest() 'First 0 means not polar, second 0 means do linear interp, 3 means do both params call intSrcToDest 0, 0, 3 for i=0 to globalSteps 'put the data where we want it call intGetDest i+1,f, real, imag OSLb(i,0)=real OSLb(i,1)=imag next i 'install the c coefficients into OSLc(). Note these are in rectangular form call intClearSrc 'Clear source from which we interpolate ver115-2d for i=0 to OSLBaseNumSteps 'copy cal table to intSrc call intAddSrcEntry OSLBaseRef(i,0),OSLBaseC(i,0),OSLBaseC(i,1) next i 'Do the actual interpolation into intDest() 'First 0 means not polar, second 0 means do linear interp, 3 means do both params call intSrcToDest 0, 0, 3 for i=0 to globalSteps 'put the data where we want it call intGetDest i+1,f, real, imag OSLc(i,0)=real OSLc(i,1)=imag next i else 'band cal--just copy the coefficients for i=0 to globalSteps OSLa(i,0)=OSLBandA(i,0) : OSLa(i,1)=OSLBandA(i,1) OSLb(i,0)=OSLBandB(i,0) : OSLb(i,1)=OSLBandB(i,1) OSLc(i,0)=OSLBandC(i,0) : OSLc(i,1)=OSLBandC(i,1) next i end if end sub 'ver115-1c added [PerformOSLCal] 'ver115-1g merged ReflectionSetup into PerformOSLCal [PerformOSLCal] 'Perform band OSL cal and return 'We ask the user whether to perform O, S or L. When he clicks Done, we use the available data 'to create the calibration results. Any combo of O,S and L is allowed so long as it includes 'O or S. We put the data into OSLcalOpen(),OSLcalOpen() and/or OSLcalOpen for the caller to process. 'We also set flags OSLdoneO, OSLdoneS and OSLdoneL to let the caller know which were performed. OSLdoneO=0 : OSLdoneL=0 : OSLdoneS=0 'For the caller's info. Set to 1 when specified cal is done. WindowWidth = 580 : WindowHeight = 370 UpperLeftX = 0 'Relative to main cal window, since it is a dialog UpperLeftY = -100 BackgroundColor$="gray" ForegroundColor$="black" TextboxColor$ = "white" ComboboxColor$="white" '--Instructions s$="Specify the fixture used. For Shunt fixture, you may specify a delay time." statictext #OSLcal.Inst1, s$,20,15,200,50 s$="Specify the desired calibration. For OSL, specify characteristics of the standards." statictext #OSLcal.Inst2, s$,290,15,200,50 'Option to choose full OSL or reference cal 'added by ver115-1g checkbox #OSLcal.Full, "", [OSLCheckFull], [OSLCheckFull], 300, 100, 20,20 statictext #OSLcal, "Full OSL", 321, 102, 70,20 checkbox #OSLcal.Ref, "", [OSLCheckRef], [OSLCheckRef], 300, 120, 20,20 statictext #OSLcal, "Reference Cal", 321, 122, 70,16 OSLBtnTop=155 : OSLBtnLeft=280 button #OSLcal.O, "Perform Open", [OSLdoOpen],UL,OSLBtnLeft, OSLBtnTop, 85,25 button #OSLcal.S, "Perform Short", [OSLdoShort],UL,OSLBtnLeft, OSLBtnTop+45, 85,25 button #OSLcal.L, "Perform Load", [OSLdoLoad],UL,OSLBtnLeft, OSLBtnTop+90, 85,25 statictext #OSLcal.doneO,"", OSLBtnLeft-33,OSLBtnTop+2,32,20 statictext #OSLcal.doneS,"", OSLBtnLeft-33,OSLBtnTop+47,32,20 statictext #OSLcal.doneL,"", OSLBtnLeft-33,OSLBtnTop+92,32,20 'The shorts model pretty well as a resistor and inductor in series. 'The females come out roughly 100 mOhm in series with 1.8nh; the males come 'out more like 250 mOhm in series with 2.5nh. 'The delay and fringe capacitance values used here need to be refined. The current 'data suggests the fringe capacitance is virtually zero, so 0.040 pF was chosen. 'Preset cal standard sets call OSLGetCalSets 'Loads cal set names into OSLCalSetNames$() ver115-7a OSLCalSetNames$(OSLCalSetNumber)="Custom" 'Add Custom, which has no file OSLCalSetNumber=OSLCalSetNumber+1 combobox #OSLcal.stdSet, OSLCalSetNames$(),[OSLSelectSet], OSLBtnLeft+90,OSLBtnTop+140, 180, 120 'ver115-7a statictext #OSLcal.stdLab, "Calibration Standards",OSLBtnLeft+120, OSLBtnTop+123, 140, 15 'Open Specs statictext #OSLcal.spec1, "Delay", OSLBtnLeft+90,OSLBtnTop-16, 40, 15 textbox #OSLcal.OpenDelay, OSLBtnLeft+90, OSLBtnTop, 35, 19 statictext #OSLcal.spec2, "ps",OSLBtnLeft+127, OSLBtnTop, 20, 19 statictext #OSLcal.spec3, "Fringe Cap", OSLBtnLeft+152,OSLBtnTop-16, 100, 15 textbox #OSLcal.OpenCap, OSLBtnLeft+155, OSLBtnTop, 35, 19 statictext #OSLcal.spec4, "fF", OSLBtnLeft+192, OSLBtnTop, 20, 19 'Short Specs statictext #OSLcal.spec5, "Delay", OSLBtnLeft+90,OSLBtnTop+31, 40, 15 textbox #OSLcal.ShortDelay, OSLBtnLeft+90,OSLBtnTop+47, 35, 19 statictext #OSLcal.spec6, "ps", OSLBtnLeft+127,OSLBtnTop+47, 20, 19 statictext #OSLcal.spec7, "Parallel L and R", OSLBtnLeft+160,OSLBtnTop+31, 100, 15 textbox #OSLcal.ShortL, OSLBtnLeft+155,OSLBtnTop+47, 35, 19 statictext #OSLcal.spec8, "pH", OSLBtnLeft+192,OSLBtnTop+47, 20, 19 textbox #OSLcal.ShortR, OSLBtnLeft+220,OSLBtnTop+47, 35, 19 statictext #OSLcal.spec9, "ohms", OSLBtnLeft+257,OSLBtnTop+47, 30, 19 'Load Specs statictext #OSLcal.spec10, "Delay", OSLBtnLeft+90,OSLBtnTop+78, 40, 15 textbox #OSLcal.LoadDelay, OSLBtnLeft+90,OSLBtnTop+94, 35, 19 statictext #OSLcal.spec11, "ps", OSLBtnLeft+127,OSLBtnTop+94, 20, 19 textbox #OSLcal.LoadR, OSLBtnLeft+155,OSLBtnTop+94, 35, 19 statictext #OSLcal.spec12, "Resist", OSLBtnLeft+155, OSLBtnTop+78,35, 15 statictext #OSLcal.spec13, "ohms", OSLBtnLeft+191,OSLBtnTop+94, 30, 19 textbox #OSLcal.LoadLC, OSLBtnLeft+220,OSLBtnTop+94, 35, 19 button #OSLcal.LoadLCButton, "Cap",[OSLcalLoadLCButton], UL,OSLBtnLeft+220, OSLBtnTop+75,40, 18 statictext #OSLcal.LoadLCUnits, "fF", OSLBtnLeft+261,OSLBtnTop+94, 30, 19 'R0 statictext #OSLcal.statictext15, "Fixture R0 (ohms)", 20, OSLBtnTop-40, 90, 20 textbox #OSLcal.R0, 110, OSLBtnTop-40, 40, 20 'Fixture type groupbox #OSLcal.FixGroup, "Fixture Type", 20, OSLBtnTop, 190, 120 checkbox #OSLcal.Bridge, "", [OSLcalSetBridge], [OSLcalSetBridge], 30, OSLBtnTop+20, 15, 20 checkbox #OSLcal.Series, "", [OSLcalSetSeries], [OSLcalSetSeries], 30, OSLBtnTop+45, 15, 20 checkbox #OSLcal.Shunt, "", [OSLcalSetShunt], [OSLcalSetShunt], 30, OSLBtnTop+70, 15, 20 statictext #OSLcal.BridgeLabel, "Reflection Bridge", 50, OSLBtnTop+21, 150, 20 statictext #OSLcal.SeriesLabel, "Series", 50, OSLBtnTop+46, 50, 20 statictext #OSLcal.ShuntLabel, "Shunt", 50, OSLBtnTop+71, 40, 16 statictext #OSLcal.DelayLabel, "Connector Delay", 110, OSLBtnTop+73, 80, 16 textbox #OSLcal.ShuntDelay, 110, OSLBtnTop+90, 65, 20 'Done, Cancel and Help buttons button #OSLcal.Done, "Done", [OSLDone],UL, 30, OSLBtnTop+140, 70, 30 button #OSLcal.Cancel, "Cancel", [OSLCancel],UL, 120, OSLBtnTop+140, 70, 30 button #OSLcal.Help, "Help", ExplainJigType,UL, 90, 70, 40, 20 button #OSLcal.Help2, "Help", ExplainOSL,UL, 360, 70, 40, 20 'Open the dialog open "Reflection Calibration" for dialog_modal as #OSLcal print #OSLcal, "trapclose [OSLFinished]" #OSLcal.Inst1, "!font Arial 10" #OSLcal.Inst2, "!font Arial 10" OSLSaveLastSelectedCalSet=OSLLastSelectedCalSet 'In case we need to restore on cancel gosub [OSLEnterPresetValues] if OSLCalSetNames$(OSLLastSelectedCalSet-1)="Custom" then 'ver115-4i 'If we start with Custom, enter the most recently used values #OSLcal.OpenDelay, OSLOpenDelay*1e12 'pS #OSLcal.OpenCap, OSLOpenCap*1e15 'fF #OSLcal.ShortDelay, OSLShortDelay*1e12 'pS #OSLcal.ShortL,OSLShortInd*1e12 'pH #OSLcal.ShortR, OSLShortRes 'ohms #OSLcal.LoadR, OSLLoadRes 'Ohms #OSLcal.LoadDelay, OSLLoadDelay*1e12 'pS if OSLLoadHasCap then #OSLcal.LoadLCButton, "Cap" : #OSLcal.LoadLCUnits, "fF" : OSLshowingLoadCap=1 #OSLcal.LoadLC, OSLLoadLC*1e15 'fF else #OSLcal.LoadLCButton, "Ind" : #OSLcal.LoadLCUnits, "pH" : OSLshowingLoadCap=0 #OSLcal.LoadLC, OSLLoadLC*1e12 'pH end if end if #OSLcal.stdSet, "selectindex "; OSLLastSelectedCalSet 'Select proper cal set #OSLcal.stdSet, "setfocus " #OSLcal.ShuntDelay, S21JigShuntDelay #OSLcal.ShuntDelay, "!hide" : #OSLcal.DelayLabel, "!hide" #OSLcal.R0, S21JigR0 'We display either S21JigR0 or S11BridgeR0 if S11JigType$="Reflect" then #OSLcal.Bridge, "set" : #OSLcal.R0, S11BridgeR0 else 'ver115-2a if S21JigAttach$="Series" then #OSLcal.Series, "set" if S21JigAttach$="Shunt" then #OSLcal.Shunt, "set" : #OSLcal.ShuntDelay, "!show" : #OSLcal.DelayLabel, "!show" end if 'call RememberState 'deletedver115-2d We always require restart after calibrating if OSLBandApplyFull then goto [OSLCheckFull] else goto [OSLCheckRef] 'to match last time dialog was open 'can't get here [OSLEnterPresetValues] 'Enter values for preset standard set number presetNum and set box status if OSLCalSetNumber3 then notice "You are missing one of the necessary calibrations for full OSL." : wait else if isBridge then 'Be sure reference cal was done didRef=(OSLdoneO or OSLdoneS) else if isSeries then didRef=OSLdoneS else didRef=OSLdoneO end if if didRef=0 then notice "You have not performed the necessary calibration" : wait end if 'ver115-3f moved the disables to here, after a possible wait occurs call SetOSLCalCheckboxStatus "disable" 'So nothing gets clicked before dialog closes ver115-3a call SetOSLCalButtonStatus "!disable" #OSLcal.stdSet, "selectionindex? OSLLastSelectedCalSet" #OSLcal.OpenDelay, "!contents? s$" : OSLOpenDelay=val(using("####.#",val(uCompact$(s$))))/1e12 'ps #OSLcal.OpenCap, "!contents? s$" : OSLOpenCap=val(using("####.#",val(uCompact$(s$))))/1e15 'fF #OSLcal.ShortDelay, "!contents? s$" : OSLShortDelay=val(using("####.#",val(uCompact$(s$))))/1e12 'ps #OSLcal.ShortL, "!contents? s$" : OSLShortInd=val(using("####.#",val(uCompact$(s$))))/1e12 'pH #OSLcal.ShortR, "!contents? s$" : OSLShortRes=val(using("#.###",val(uCompact$(s$)))) 'ohms #OSLcal.LoadR, "!contents? s$" : OSLLoadRes=val(using("####.###",val(uCompact$(s$)))) 'ohms #OSLcal.LoadDelay, "!contents? s$" : OSLLoadDelay=val(using("####.#",val(uCompact$(s$))))/1e12 'ps #OSLcal.LoadLC, "!contents? s$" OSLLoadHasCap=OSLshowingLoadCap if OSLLoadHasCap then OSLLoadLC=val(using("####.#",val(uCompact$(s$))))/1e15 'fF else OSLLoadLC=val(using("####.#",val(uCompact$(s$))))/1e12 'pH end if 'ver115-2d modified the remainder of this routine desiredCalLevel=2 'desire BandSweep applyCalLevel=0 'Pretend nothing is now installed, so new cal gets installed on Restart installedOSLBaseNumSteps=-1 call RequireRestart 'To activate desired cal; graph is messed up anyway 'ver115-2d moved the following lines here and changed return to wait, because we sometimes 'returned to a strange place. Now we just close our window and wait. These things used 'to be done in the calling routine???? gosub [ProcessOSLBandCal] 'ver115-1g close #OSLcal 'ver115-5b moved update of band cal display to the routines for the basic cal window return 'we will be back in the basic cal window, or whoever called us 'ver115-1c added OSLEnterPresetValues [OSLSelectSet] 'User Selected preset cal standard 'This is separate from OSLEnterPresetValues because when the dialog is first opened we just 'call that routine, since doing the selectionindex? seems to mess up the box. #OSLcal.stdSet, "selectionindex? s" OSLdoneO=0 : OSLdoneL=0 : OSLdoneS=0 #OSLcal.doneO, "" : #OSLcal.doneL, "" : #OSLcal.doneS, "" OSLLastSelectedCalSet=s gosub [OSLEnterPresetValues] wait [OSLdoOpen] if calInProgress then gosub [OSLCalAborted] : wait 'Button says abort when cal is running call SetOSLCalButtonStatus "!disable" #OSLcal.O, "!enable" #OSLcal.O, "Abort Cal" #OSLcal.doneO, "" 'ver115-7a gosub [OSLdoCal] 'get cal data by doing one sweep 'For S11JigType$="Reflect", the data in ReflectArray will be reflection per the bridge R0 w/o OSL adjustment. 'It is normally adjusted for planeadj, but in cal we force planeadj to 0. 'For S11JigType$="Trans", the data in ReflectArray is "S21" of the fixture (unadjusted for any reference) 'which we are treating as the tentative estimate of reflection, even though it is far from true reflection. for i=0 to steps 'retrieve data re bridge R0 OSLcalOpen(i,0)=ReflectArray(i,constIntermedS11DB) 'was put here during scan ver115-7a OSLcalOpen(i,1)=ReflectArray(i,constIntermedS11Ang) 'ver115-7a next i call SetOSLCalButtonStatus "!enable" #OSLcal.O, "Perform Open" #OSLcal.doneO, "Done" OSLdoneO=1 #OSLcal.Full, "value? OSLFullval$" if OSLFullval$="reset" then goto [OSLDone] 'If Reference cal, quit after one is done wait [OSLdoShort] if calInProgress then gosub [OSLCalAborted] : wait 'Button says abort when cal is running call SetOSLCalButtonStatus "!disable" #OSLcal.S, "!enable" #OSLcal.S, "Abort Cal" #OSLcal.doneS, "" 'ver115-7d gosub [OSLdoCal] 'get cal data by doing one sweep for i=0 to steps 'retrieve data re bridge R0 OSLcalShort(i,0)=ReflectArray(i,constIntermedS11DB) 'was put here during scan 'ver115-7a OSLcalShort(i,1)=ReflectArray(i,constIntermedS11Ang) 'ver115-7a next i call SetOSLCalButtonStatus "!enable" #OSLcal.S, "Perform Short" #OSLcal.doneS, "Done" OSLdoneS=1 #OSLcal.Full, "value? OSLFullval$" if OSLFullval$="reset" then goto [OSLDone] 'If Reference cal, quit after one is done wait [OSLdoLoad] if calInProgress then gosub [OSLCalAborted] : wait 'Button says abort when cal is running call SetOSLCalButtonStatus "!disable" #OSLcal.L, "!enable" #OSLcal.L, "Abort Cal" #OSLcal.doneL, "" 'ver115-7a gosub [OSLdoCal] 'get cal data by doing one sweep for i=0 to steps 'retrieve data re bridge R0 OSLcalLoad(i,0)=ReflectArray(i,constIntermedS11DB) 'was put here during scan 'ver115-7a OSLcalLoad(i,1)=ReflectArray(i,constIntermedS11Ang) 'ver115-7a next i call SetOSLCalButtonStatus "!enable" #OSLcal.L, "Perform Load" #OSLcal.doneL, "Done" OSLdoneL=1 'ver115-2c #OSLcal.Full, "value? OSLFullval$" if OSLFullval$="reset" then goto [OSLDone] 'If Reference cal, quit after one is done wait sub SetOSLCalButtonStatus stat$ 'Set button status. stat$ is either "!enable" or "!disable" #OSLcal.O, stat$ #OSLcal.S, stat$ #OSLcal.L, stat$ #OSLcal.Done, stat$ #OSLcal.Cancel, stat$ #OSLcal.Help, stat$ 'ver115-3a #OSLcal.Help2, stat$ 'ver115-3a end sub [OSLCalAborted] 'OSL cal was aborted. Restore status and let user proceed #OSLcal.Bridge, "enable" 'ver115-3a #OSLcal.Series, "enable" #OSLcal.Shunt, "enable" call SetOSLCalButtonStatus "!enable" #OSLcal.O, "Perform Open" 'Restore button names--one was set to Abort Cal #OSLcal.S, "Perform Short" #OSLcal.L, "Perform Load" calInProgress=0 specialOneSweep=0 sweepDir=saveSweepDir : alternateSweep=saveAlternate planeadj=savePlaneAdj : wate=saveWate message$="Cal Aborted" 'ver115-2d call PrintMessage wait [OSLdoCal] 'Run OSL Calibration for specified standard calInProgress=1 call SetOSLCalCheckboxStatus "disable" 'ver115-3a haltsweep=0 'So Restart will actually restart. ver114-4f specialOneSweep=1 saveAlternate=alternateSweep : saveSweepDir=sweepDir : savePlaneAdj=planeadj : saveWate=wate alternateSweep=0 : sweepDir=1 wate=max(wate,110) 'Increase wait time if necessary ver115-4a planeadj=0 'So phase will not be affected applyCalLevel=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 calInProgress=0 call SetOSLCalCheckboxStatus "enable" 'ver115-3a return [ProcessOSLBandCal] 'Process already gathered band cal data applyCalLevel=0 'So cal will reinstall on Restart call ProcessOSLCal desiredCalLevel=2 'opt for using band cal since we just did it if OSLError then BandSweepCalDone=0 : OSLBandNumSteps=-1 : return 'If error, nullify the cal and return 'Save the conditions under which the cal was done OSLBandStartFreq=startfreq OSLBandEndFreq=endfreq OSLBandNumSteps=steps OSLBandLinear=gGetXIsLinear() OSLBandPath$=path$ OSLBandS11JigType$=S11JigType$ OSLBandS21JigAttach$=S21JigAttach$ OSLBandS11BridgeR0=S11BridgeR0 OSLBandS21JigR0=S21JigR0 OSLBandTimeStamp$=date$("mm/dd/yy"); "; ";time$() BandSweepCalDone=1 return sub ExplainOSL h$ 'Put up dialog explaining reflection jig type WindowWidth = 635 WindowHeight = 200 UpperLeftX=0 'Doesn't seem to matter what is specified here UpperLeftY=150 BackgroundColor$="gray" ForegroundColor$="black" statictext #Explain, "All measurements in Reflection mode require some form of calibration. The simplest calibration is", 10, 10, 630, 20 statictext #Explain, "Reference Calibration, which uses either an Open or a Short calibration standard, which essentially", 10, 30, 630, 20 statictext #Explain, "allows the MSA to adjust to set a reference signal level. This works well for precise fixtures at", 10, 50, 630, 20 statictext #Explain, "relatively low frequencies. OSL Calibration involves more steps but is more accurate. OSL involves", 10, 70, 630, 20 statictext #Explain, "sequentially measuring Open, Short and Load calibration standards, in any order. ", 10, 90, 630, 20 statictext #Explain, "For OSL Calibration, you generally specify the electrical characteristics of each of the standards.", 10, 110, 630, 20 statictext #Explain, "At low frequencies it may work well just to treat them as Ideal.", 10, 130, 630, 20 open "Reflection Calibration Help" for dialog_modal as #Explain #Explain, "trapclose [OSLExplainFinished]" print #Explain, "font ms_sans_serif 10" wait [OSLExplainFinished] close #Explain end sub sub ExplainJigType h$ 'Put up dialog explaining reflection jig type WindowWidth = 600 WindowHeight = 370 UpperLeftX=0 'Doesn't seem to matter what is specified here UpperLeftY=150 BackgroundColor$="gray" ForegroundColor$="black" s$="Reflection measurements use one of several types of test fixtures to which the device under test (DUT)" s$=s$;" is attached. Many fixtures are Reflection Bridges, which make an attempt to make their output signal" s$=s$;" correspond closely to the actual reflection from the DUT. Such fixtures can use Reference Calibration" s$=s$;" with either the Open or Short, or for better accuracy can use full OSL calibration." statictext #JigExplain, s$, 20, 20, 550, 80 s$="Other fixtures produce an output which does not directly correspond to the DUT reflection, but can be" s$=s$;" mathematically transformed into a reflection measurement. These test fixtures" s$=s$;" typically consist of an attenuator, then the component, then another attenuator. The component" s$=s$;" may be connected in Series between the attenuators, or may be Shunt to ground, which accounts for the" s$=s$;" two different fixture types. The component will see a certain resistance R0 looking at the incoming signal" s$=s$;" and the outgoing signal. You must specify that R0, usually 50 ohms. The Series fixture is calibrated" s$=s$;" with just the Short or with full OSL. The Shunt fixture is calibrated with just the Open or with full OSL." statictext #JigExplain, s$, 20, 120, 550, 140 s$="If you specify the Shunt Fixture, then you may also specify the one-way connection delay time," s$=s$;" which is used for compensation when you do not use full OSL. A delay of 0.115 ns is typical." s$=s$;" For low frequency use a delay of 0 ns may be adequate." statictext #JigExplain, s$, 20, 270, 550, 60 open "Reflection Fixture Help" for dialog_modal as #JigExplain #JigExplain, "trapclose [JigExplainFinished]" print #JigExplain, "font ms_sans_serif 10" wait [JigExplainFinished] close #JigExplain end sub 'ver115-7a function OSLOpenFile$(fName$, asInput) 'Open file with OSL standards 'fName is full file name, with path and extension 'Returns LB file handle, or blank if error 'asInput=1 means open input file; otherwise open output file On Error goto [noFile] if asInput then open fName$ for input as #calSetFile else open fName$ for output as #calSetFile OSLOpenFile$="#calSetFile" exit function [noFile] OSLOpenFile$="" end function 'ver115-7a sub OSLGetFileData$ fHndl$ 'Get description of OSL standard 'The file handle is in fHndl 'The data is put into global variables describing the current OSL standard 'The file consists of the following lines: 'Name=xxx the name to enter in the combo box 'Open=... 'Short=... 'Load=... 'Each ... spec is in this form: 'R0.1, L1n, C0p, D35f 'This specifies RLC values and a delay, but different standards allow different combinations. 'Open allows only capacitance (fringe) and delay 'Short allows resistance and inductance, which are deemed in parallel 'Load allows delay, resistance and either L or C. If L, it is in series; C is in parallel. 'Values are ohms, henries, farads and seconds, so suffix characters can be used, like 1n for 1 nH. 'Values can be in any order on the line, and the Open, Short and Load lines can be in any order. hadName=0: hadOpen=0 : hadShort=0 : hadLoad=0 while EOF(#fHndl$)=0 Line Input #fHndl$, tLine$ equalPos=instr(tLine$,"=") if equalPos>2 then 'Note that lines without valid tags are allowed; we ignore them OSLid$=Upper$(Trim$(Left$(tLine$, equalPos-1))) 'everything left of the equal sign is the ID tLine$=Mid$(tLine$, equalPos+1) 'We will search everything right of the equal sign select case OSLid$ case "NAME" OSLfileCalSetName$=Trim$(tLine$) : hadName=1 case "OPEN" call OSLGetValue "C", tLine$, OSLfileOpenCap, idFound 'Get fringe cap if idFound=0 then OSLfileOpenCap=0 call OSLGetValue "D", tLine$, OSLfileOpenDelay, idFound 'Get delay if idFound=0 then OSLfileOpenDelay=0 hadOpen=1 case "SHORT" call OSLGetValue "L", tLine$, OSLfileShortInd, idFound 'Get series L if idFound=0 then OSLfileShortInd=0 call OSLGetValue "R", tLine$, OSLfileShortRes, idFound 'Get delay if idFound=0 then OSLfileShortRes=0 call OSLGetValue "D", tLine$, OSLfileShortDelay, idFound 'Get delay if idFound=0 then OSLfileShortDelay=0 hadShort=1 case "LOAD" call OSLGetValue "R", tLine$, OSLfileLoadRes, idFound 'Get delay if idFound=0 then OSLfileLoadRes=50 call OSLGetValue "L", tLine$, OSLfileLoadLC, idFound 'Get series L OSLfileLoadHasCap=0 if idFound=0 then 'Check for C only if no L specified call OSLGetValue "C", tLine$, OSLfileLoadLC, idFound 'Get Parallel C if idFound then OSLfileLoadHasCap=1 else OSLfileLoadLC=0 end if call OSLGetValue "D", tLine$, OSLfileLoadDelay, idFound 'Get delay if idFound=0 then OSLfileLoadDelay=0 hadLoad=1 case else 'Ignore other lines end select end if wend if hadName=0 or hadOpen=0 or hadShort=0 or hadLoad=0 then if hadName then n$=OSLfileCalSetName$ else n$="unnamed standard" notice "Incomplete cal standard file for ";n$;"." end if end sub 'ver115-7a sub OSLGetValue ID$, s$, byref idVal, byref found 'Get specified value (R,L,C or D) from string s$ 's$ has entries of the form R50, C10p ...(comma delimited) 'If entry is found, set found=1 and put value into idVal; otherwise set found=0 pos=instr(s$, ID$) if pos=0 then idVal=0 : found=0 : exit sub found=1 commaPos=instr(s$, ",",pos) 'Find first comma after the ID tag if commaPos=0 then commaPos=len(s$)+1 'If no comma, pretend it is after end of string val$=Mid$(s$, pos+1, commaPos-pos-1) 'stuff between ID and comma idVal=uValWithMult(val$) 'Value adjusted for mulitplier characters. E.g. 1u=0.000001 end sub 'ver115-7a sub OSLSaveCalSetFile fName$ 'Save current cal set data as a file named fName$ (includes full path) fHndl$=OSLOpenFile$(fName$,0) 'Open file for output if fHndl$="" then notice "Error creating cal set file.": exit sub f$="3,2,4//UseMultiplier//DoCompact" print #fHndl$, "Name=";OSLfileCalSetName$ print #fHndl$, "Open=C";uFormatted$(OSLfileOpenCap,f$);", D";uFormatted$(OSLfileOpenDelay,f$) print #fHndl$, "Short=R";uFormatted$(OSLfileShortRes,f$);", L";uFormatted$(OSLfileShortInd,f$);", D";uFormatted$(OSLfileShortDelay,f$) if OSLLoadHasCap then s$="C" else s$="L" s$=s$;uFormatted$(OSLfileLoadLC,f$) print #fHndl$, "Load=R";uFormatted$(OSLfileLoadRes,f$);", ";s$;", D";uFormatted$(OSLfileLoadDelay,f$) close #fHndl$ end sub 'ver115-7a sub OSLGetCalSets 'Load cal set names 'Loads file and set names for all files in the folder \MSA_Info\OperatingCal\CalSets folder filePath$=DefaultDir$;"\MSA_Info\OperatingCal\CalSets" files DefaultDir$;"\MSA_Info\OperatingCal", "", fileInfo$() 'get directory list nFolders=val(fileInfo$(0,1)) folderFound=0 for i=1 to nFolders if fileInfo$(i,1)="CalSets" then folderFound=1 : exit for 'We found the CalSets folder next i if folderFound=0 then if mkDir(filePath$)<>0 then notice "Error creating CalSets folder.": exit sub 'Folder doesn't exist, so make one OSLfileCalSetName$="Ideal 50 ohms" OSLfileOpenCap=3.5e-15 : OSLfileOpenDelay=0 'ver115-8b added 35 fF OSLfileShortInd=0 : OSLfileShortDelay=0 OSLfileLoadRes=50 : OSLfileLoadHasCap=1 : OSLfileLoadLC=0 : OSLLoadDelay=0 call OSLSaveCalSetFile filePath$;"\Ideal 50 ohms.txt" 'Save Ideal 50 ohms file per the above values end if files filePath$, "*.txt", fileInfo$() 'get list of files in CalSets folder nFiles=val(fileInfo$(0,0)) redim OSLCalSetNames$(nFiles+1) : redim OSLCalSetFileNames$(nFiles+1) 'Clear and Make room for list plus "Custom" OSLCalSetNumber=0 for i=1 to nFiles 'Read cal set name of each file fName$=fileInfo$(i,0) 'Name of this file, without path fHndl$=OSLOpenFile$(filePath$;"\";fName$, 1) 'Open this file for input if fHndl$<>"" then 'Blank means error, so we ignore file OSLCalSetFileNames$(i-1)=fName$ 'store file name (without path) call OSLGetFileData$ fHndl$ 'name is the only data we will use here OSLCalSetNames$(i-1)=OSLfileCalSetName$ 'store name that was set in OSLGetFileData$ OSLCalSetNumber=OSLCalSetNumber+1 close #fHndl$ 'Close this file end if next i end sub sub ProcessOSLCal 'Calc coefficients and reference data from raw OSL scan data 'OSLdoneO, OSLdoneSand OSLdoneS indicate which of Open, Short, and Load were performed. 'The relevant calibration data is in OSLcalOpen(), OSLcalShort() and OSLcalLoad() 'Calibration data will be the raw S11 for reflection bridge, and raw S21 for the transmission bridge. 'In the latter case we must convert to S11 before calculating OSL coefficients. ' 'The measured cal data is in OSLcalOpen(), etc. It is reflection data for the reflection bridge, 'For S11JigType$="Reflect", the data in OSLcalOpen(), etc., will be reflection per the bridge w/o OSL adjustment, 'and without being adjusted for planeadj (which we force to 0 in cal). 'For S11JigType$="Trans", the data in OSLcalOpen(), etc., is "S21" of the fixture (unadjusted for any reference) 'which we are treating as the tentative estimate of reflection, even though it is far from true reflection. 'When raw data is collected in future scans, it will be adjusted by a reference installed into the line 'cal array. The reference will be the calibration data from the Open, except for the series jig it is the 'calibration data from the Short. In the case of a Precise Reflection Bridge if we don't have the relevant 'Open data, we compute it from the Short. ' 'If we have only one calibration standard, we do not use OSL coefficients. At the time calibration is applied, 'OSLApplyFull=1 is used to determine whether to apply OSL. ' 'We put the OSL coefficients into OSLBandA(), OSLBandB() and OSLBandC() 'DEBUG ' for i=0 to globalSteps ' OSLcalOpen(i,0)=0 : OSLcalOpen(i,1)=0 ' OSLcalShort(i,0)=42.638 : OSLcalShort(i,1)=-93.4375 ' OSLcalLoad(i,0)=39.166 : OSLcalLoad(i,1)=-92.76 ' next i calType$="Full" 'assume full cal for the moment calSum=OSLdoneO+OSLdoneS+OSLdoneL if calSum=0 then notice "No OSL performed" : exit sub if calSum=1 then 'Only one cal performed if OSLdoneO then calType$="Open" 'We have just Open if OSLdoneS then calType$="Short" 'We have just Short if OSLdoneL then calType$="Load" 'We have just Load end if 'local calType$ will affect how we handle the reference, and whether coefficients are used 'Calc cal standard data for computing coefficients, but only if we are going to use coefficients if calType$="Full" then call CalcOSLStandards 'There are two circumstances for the Precise Reflection Bridge where we need to create missing 'measurements for one of the standards. 'If we have open and short for the bridge, we need to create the Load if S11JigType$="Reflect" then if calSum=2 then 'We have two standards; the cal routine only allows them to be Open and Short 'We make the Load -999 db relative to the Open for i=0 to globalSteps OSLcalLoad(i,0)=OSLcalOpen(i,0)-999 : OSLcalLoad(i,1)=OSLcalOpen(i,1) next i OSLdoneL=1 : calSum=3 'We will now proceed with full OSL end if if calType$="Short" then 'We have Short only; we need Open as the reference. 'Ideal Open in reflect bridge would produce S11 equal to the Short, rotated 180 degrees for i=0 to globalSteps OSLcalOpen(i,0)=OSLcalShort(i,0) 'mag p=OSLcalShort(i,1)+180 : if p>180 then p=p-360 if p<=-180 then p=p+180 OSLcalOpen(i,1)=p 'phase, shifted 180 degrees next i OSLdoneS=0 : OSLdoneO=1 : calType$="Open" 'Pretend we don't have the Short anymore end if end if 'DEBUG ' print "-----------After creating missing standard-----------" ' for i=0 to globalSteps ' print OSLcalOpen(i,0); " ";OSLcalOpen(i,1); " ";OSLcalShort(i,0); " ";OSLcalShort(i,1); " ";OSLcalLoad(i,0); " ";OSLcalLoad(i,1) ' next 'We need to determine the reference that will be installed as the line cal. 'We always use Open data (perhaps created above) except for the Series 'transmission jig, for which we use the Short. 'We must apply the reference to the cal data itself for numerical stability, and then 'calculate the OSL coefficients. for i=0 to globalSteps if S11JigType$="Trans" and S21JigAttach$="Series" then 'Use Short refDB=OSLcalShort(i,0) 'Mag refPhase=OSLcalShort(i,1) 'Phase else 'Use Open refDB=OSLcalOpen(i,0) 'Mag refPhase=OSLcalOpen(i,1) 'Phase if calType$<>"Full" and S11JigType$="Trans" and S21JigAttach$="Shunt" and S21JigShuntDelay<>0 then 'ver115-5d 'For shunt jig we have to adjust for the connector delay (unless doing full OSL) 'We first find the impedance presented by the open transmission line 'We assume the line is effectively terminated by 0.04 pf freq=ReflectArray(i,0) 'Frequency at which cal step was done if freq=0 then freq=0.000001 'To avoid divide by zero K=0.006283*S21JigShuntDelay*freq : TK=tan(K) 'freq is in MHz Creact=-1e14/(2*uPi()*4*freq) 'reactance of 0.04 pf 'ver115-4a 'Z(In)=50* (Zdut + j*50*tan(K)) / (50 + j*Zdut*tan(K)) 'K=0.006283*DF, where F is the frequency in MHz, and D is the one-way delay in ns 'For the open line, Zdut=j*Creact Rnum=0 : Inum=50*(Creact+50*TK) Rden=50-Creact*TK : Iden=0 call cxDivide Rnum, Inum, Rden, Iden, Ropen,Iopen 'Get impedance of "open" line with cap at end 'Now find the S21 that would be produced by the impedance of the open 'S21(Shunt)=2*Z/(2*Z+R0) call cxDivide 2*Ropen, 2*Iopen, S21JigR0+2*Ropen, 2*Iopen, Rres, Ires OpenDeg=uATan2(Rres, Ires) 'phase in degrees OpenDB=10*uSafeLog10(Rres^2+Ires^2) 'magnitude in db; mult by 10 not 20, because magnitude is squared 'The open transmission line caused a phase change of OpenDeg and mag change of OpenDB during calibration; 'we back those out to get what our S21 would be if the transmission line delay and capacitance had not 'been in place during calibration. note they will both be negative values. refDB=refDB-OpenDB refPhase=refPhase-OpenDeg end if end if OSLBandRef(i,0)=ReflectArray(i,0) 'freq--actual tuning freq, not equiv 1G freq OSLBandRef(i,1)=refDB :OSLBandRef(i,2)=refPhase 'save as reference OSLcalOpen(i,0)=OSLcalOpen(i,0)-refDB 'adjusted Open db p=OSLcalOpen(i,1)-refPhase :if p>180 then p=p-360 if p<=-180 then p=p+360 OSLcalOpen(i,1)=p 'adjusted Open phase OSLcalShort(i,0)=OSLcalShort(i,0)-refDB 'adjusted short db p=OSLcalShort(i,1)-refPhase :if p>180 then p=p-360 if p<=-180 then p=p+360 OSLcalShort(i,1)=p 'adjusted short phase OSLcalLoad(i,0)=OSLcalLoad(i,0)-refDB 'adjusted Load db p=OSLcalLoad(i,1)-refPhase :if p>180 then p=p-360 if p<=-180 then p=p+360 OSLcalLoad(i,1)=p 'adjusted Load phase next i 'DEBUG ' print "-----------After adjusting for reference-----------" ' for i=0 to globalSteps ' print OSLcalOpen(i,0); " ";OSLcalOpen(i,1); " ";OSLcalShort(i,0); " ";OSLcalShort(i,1); " ";OSLcalLoad(i,0); " ";OSLcalLoad(i,1) ' next 'Save flag to indicate whether we will apply OSL cal or just use the reference OSLBandApplyFull=(calType$="Full") 'We want to convert the OSLcalxxx() data into S11 in rectangular form (real, imaginary), and calc OSL coefficients. 'We leave the reference data in db, ang (degrees) format. 'Transmission jig data is treates as S11. 'We only need to do this for full OSL; otherwise we are just using one standard as a reference. if OSLBandApplyFull then kDegToRad=uRadsPerDegree() for i=0 to globalSteps rho=10^(OSLcalOpen(i,0)/20) : rad=OSLcalOpen(i,1)*kDegToRad 'to polar, radians OSLcalOpen(i,0)=cos(rad)*rho : OSLcalOpen(i,1)=sin(rad)*rho 'polar to rectangular rho=10^(OSLcalLoad(i,0)/20) : rad=OSLcalLoad(i,1)*kDegToRad OSLcalLoad(i,0)=cos(rad)*rho : OSLcalLoad(i,1)=sin(rad)*rho rho=10^(OSLcalShort(i,0)/20) : rad=OSLcalShort(i,1)*kDegToRad OSLcalShort(i,0)=cos(rad)*rho : OSLcalShort(i,1)=sin(rad)*rho next i OSLError=0 'ver115-4j call CalcOSLCoeff 'Calculate A, B, C coefficients; set OSLError to 1 if math error end if 'DEBUG ' print "-----------After converting to Real, Imaginary-----------" ' for i=0 to globalSteps ' print OSLcalOpen(i,0); " ";OSLcalOpen(i,1); " ";OSLcalShort(i,0); " ";OSLcalShort(i,1); " ";OSLcalLoad(i,0); " ";OSLcalLoad(i,1) ' next 'DEBUG ' print "-----------Calculated A, B, C-----------" ' for i=0 to globalSteps ' print OSLBandA(i,0); " ";OSLBandA(i,1); " ";OSLBandB(i,0); " ";OSLBandB(i,1); " ";OSLBandC(i,0); " ";OSLBandC(i,1) ' next 'DEBUG ' print "-----------Reference-----------" ' for i=0 to globalSteps ' print OSLBandRef(i,0); " ";OSLBandRef(i,1); " ";OSLBandRef(i,2) ' next 'The only relevant data produced by all of this are OSLBandRef(), OSLBaseRef(), OSLBandApplyFull, OSLBaseApplyFull, 'and the arrays for the base and band OSL coefficients; those coefficients are relevant only when xxApplyFull=1. end sub 'Here we use the measured reflection coefficients for the open, load and short 'to determine OSL coefficients a, b and c. These in turn can be used 'to calculate actual reflection coefficients from measured reflection coefficients 'by the following formulas: ' M=(S+a)/(b*S+c) ' S = (a - cM)/(bM - 1) 'where S is the actual reflection coefficient and M is the measured reflection coefficient. 'For subscripting variables in code and in the comments, the suffixes O, L and S mean 'Open, Load and Short, respectively. For example, SL is the actual 'reflection coefficient of the load; MS is the measured reflection loss of the short. ' 'The measured return losses for the open, load and short are determined 'at each frequency step before invoking this method, and placed into the arrays 'OSXOpenR, OSXOpenI, OSXLoadR, OSXLoadI, OSXShortR and OSXShortI. Variable names 'use the suffixes R and I for the real and imaginary parts, respectively. 'We could first do a line calibration with the Open 'and then measure just the load and short, assigning a perfect "1" to the Open. 'But to keep this calculation generic, if that is done the entries for the measured 'Open should just be assigned a value of 1 before invoking CalcOSL. 'We allow for the actual return losses of the open and short 'to be something other than ideal, by using arrays to hold 'their values at each frequency step. 'ver115-1b added CalcOSLCoeff1 sub CalcOSLCoeff1 'Calc coeff a, b, c for base or band OSL cal 'OSLcalOpen(), OSLcalShort() and OSLcalLoad() have the raw calibration data (real, imag form) 'OSLstdOpen and OSLstdOpen() have the S11 data for the Open and Short standards (real, imag form) 'MO,ML, MS are the measured responses with the open, load and short attached 'SO, SL, SS are the actual reflection coeff. of the open, short and load standards '(SL is assumed=0) 'All must be in real, imaginary form 'The adjustment is made by the following formula: ' S = (a - cM)/(bM - 1) This model is different from that used in CalcOSLCoeff 'where S is the actual reflection coefficient and M is the measured reflection coefficient. ' 'The coefficients a, b and c are calculated according to the following formulas: 'K1= ML-MO; approx. -1 'K2= MS-ML; appro.x -1 'K3= MO-MS; approx. 2 ' 'D=MS*SS*K1 + MO*SO*K2; approx -2 ' 'c=SO*SS*K3 / D 'a=ML*c 'b=[SO*K2 + SS*K1] / D for calStep=0 to globalSteps MOr=OSLcalOpen(calStep,0) : MOi=OSLcalOpen(calStep,1) 'Measured open, real and imag MLr=OSLcalLoad(calStep,0) : MLi=OSLcalLoad(calStep,1) 'Measured load, real and imag MSr=OSLcalShort(calStep,0) : MSi=OSLcalShort(calStep,1) 'Measured short, real and imag SOr=OSLstdOpen(calStep,0) : SOi=OSLstdOpen(calStep,1) 'Open standard, real and imag SSr=OSLstdShort(calStep,0) : SSi=OSLstdShort(calStep,1) 'Short standard, real and imag 'Compute Ks K1r=MLr-MOr : K1i=MLi-MOi 'K1, real and imag K2r=MSr-MLr : K2i=MSi-MLi 'K2, real and imag K3r=MOr-MSr : K3i=MOi-MSi 'K3, real and imag 'Compute 1/D Wr=MSr*SSr-MSi*SSi : Wi=MSr*SSi+MSi*SSr 'MS*SS Xr=Wr*K1r-Wi*K1i : Xi=Wr*K1i+Wi*K1r 'MS*SS*K1 Yr=MOr*SOr-MOi*SOi : Yi=MOr*SOi+MOi*SOr 'MO*SO Zr=Yr*K2r-Yi*K2i : Zi=Yr*K2i+Yi*K2r 'MO*SO*K2 Dr=Xr+Zr : Di=Xi+Zi 'D=MS*SS*K1 + MO*SO*K2 if Dr=0 and Di=0 then notice "Divide by zero in calculating OSL coefficients." : OSLError=1 : exit sub 'ver115-4j call cxInvert Dr, Di, DinvR, DinvI 'Invert of D is in Dinv 'Compute c Wr=SOr*SSr-SOi*SSi : Wi=SOr*SSi+SOi*SSr 'SO*SS Xr=Wr*K3r-Wi*K3i : Xi=Wr*K3i+Wi*K3r 'X=SO*SS*K3 cr=DinvR*Xr-DinvI*Xi : ci=DinvR*Xi+DinvI*Xr 'c=X/D 'Compute a ar=MLr*cr-MLi*ci : ai=MLr*ci+MLi*cr 'a=ML*c 'Compute b Wr=SOr*K2r-SOi*K2i : Wi=SOr*K2i+SOi*SSr 'SO*K2 Xr=SSr*K1r-SSi*K1i : Xi=SSr*K1i+SSi*K1r 'SS*K1 Yr=Wr+Xr : Yi=Wi+Xi 'Y=SO*K2 + SS*K1 br=DinvR*Yr-DinvI*Yi : bi=DinvR*Yi+DinvI*Yr 'b=Y/D 'Put coefficients into OSLBandx() OSLBandA(calStep,0)=ar : OSLBandA(calStep,1)=ai OSLBandB(calStep,0)=br : OSLBandB(calStep,1)=bi OSLBandC(calStep,0)=cr : OSLBandC(calStep,1)=ci next calStep end sub 'ver115-1b added CalcOSLCoeff sub CalcOSLCoeff 'Calc coeff a, b, c for base or band OSL cal 'We calculate OSL coefficients for the most general case, where no advance assumptions are 'made about the cal standards. 'OSLcalOpen(), OSLcalShort() and OSLcalLoad() have the raw calibration data (real, imag form) 'OSLstdOpen and OSLstdOpen() have the S11 data for the Open and Short standards (real, imag form) 'MO,ML, MS are the measured responses with the open, load and short attached 'SO, SL, SS are the actual reflection coeff. of the open, short and load standards 'The error model equation is as follows, where S is the actual S11 and M is 'the measured S11: ' S = (M – b) / (a – c*M) 'Using S and M for the Open, Short and Load, we can calculate the 'coefficients a, b and c. 'The double letter variables Mx and Sx are the measured and actual values, with 'the second letter (O, S or L) indicating open, short or load. ' ' K1 = ML-MS ' K2 = MS-MO ' K3 = MO-ML ' K4= SL*SS*K1 ' K5= SO*SS*K2 ' K6= SL*SO*K3 ' K7=SO*K1 ' K8=SL*K2 ' K9=SS*K3 ' ' D = K4 + K5 + K6 ' ' a= (MO*K7 + ML*K8 + MS*K9)/D ' b= (MO*K4 + ML*K5 +MS*K6)/D ' c = (K7 + K8 + K9)/D for calStep=0 to globalSteps MOr=OSLcalOpen(calStep,0) : MOi=OSLcalOpen(calStep,1) 'Measured open, real and imag MLr=OSLcalLoad(calStep,0) : MLi=OSLcalLoad(calStep,1) 'Measured load, real and imag MSr=OSLcalShort(calStep,0) : MSi=OSLcalShort(calStep,1) 'Measured short, real and imag SOr=OSLstdOpen(calStep,0) : SOi=OSLstdOpen(calStep,1) 'Open standard, real and imag SLr=OSLstdLoad(calStep,0) : SLi=OSLstdLoad(calStep,1) 'Load standard, real and imag SSr=OSLstdShort(calStep,0) : SSi=OSLstdShort(calStep,1) 'Short standard, real and imag K1r=MLr-MSr : K1i=MLi-MSi 'K1=ML-MS, real and imag K2r=MSr-MOr : K2i=MSi-MOi 'K2=MS-MO, real and imag K3r=MOr-MLr : K3i=MOi-MLi 'K3=MO-ML, real and imag Wr=SLr*SSr-SLi*SSi : Wi=SLr*SSi+SLi*SSr 'W=SL*SS K4r=Wr*K1r-Wi*K1i : K4i=Wr*K1i+Wi*K1r 'K4=SL*SS*K1 Wr=SOr*SSr-SOi*SSi : Wi=SOr*SSi+SOi*SSr 'W=SO*SS K5r=Wr*K2r-Wi*K2i : K5i=Wr*K2i+Wi*K2r 'K5=SO*SS*K2 Wr=SLr*SOr-SLi*SOi : Wi=SLr*SOi+SLi*SOr 'W=SL*SO K6r=Wr*K3r-Wi*K3i : K6i=Wr*K3i+Wi*K3r 'K6=SL*SO*K3 K7r=SOr*K1r-SOi*K1i : K7i=SOr*K1i+SOi*K1r 'K7=SO*K1 K8r=SLr*K2r-SLi*K2i : K8i=SLr*K2i+SLi*K2r 'K8=SL*K2 K9r=SSr*K3r-SSi*K3i : K9i=SSr*K3i+SSi*K3r 'K9=SS*K3 Dr=K4r+K5r+K6r : Di=K4i+K5i+K6i 'D = K4 + K5 + K6 if Dr=0 and Di=0 then notice "Divide by zero in calculating OSL coefficients." : OSLError=1 : exit sub 'ver115-4j call cxInvert Dr, Di, invDr, invDi 'invD= 1/D 'Now calculate coefficient a Wr=MOr*K7r-MOi*K7i : Wi=MOr*K7i+MOi*K7r 'W=MO*K7 Xr=MLr*K8r-MLi*K8i : Xi=MLr*K8i+MLi*K8r 'X=ML*K8 Yr=MSr*K9r-MSi*K9i : Yi=MSr*K9i+MSi*K9r 'Y=MS*K9 Zr=Wr+Xr+Yr : Zi=Wi+Xi+Yi 'Z=MO*K7 + ML*K8 + MS*K9 ar=Zr*invDr-Zi*invDi : ai=Zr*invDi+Zi*invDr 'a=(MO*K7 + ML*K8 + MS*K9)/D 'The procedure for calculating b is identical to that for a, 'just changing the K values. Wr=MOr*K4r-MOi*K4i : Wi=MOr*K4i+MOi*K4r 'W=MO*K4 Xr=MLr*K5r-MLi*K5i : Xi=MLr*K5i+MLi*K5r 'X=ML*K5 Yr=MSr*K6r-MSi*K6i : Yi=MSr*K6i+MSi*K6r 'Y=MS*K6 Zr=Wr+Xr+Yr : Zi=Wi+Xi+Yi 'Z=MO*K4 + ML*K5 + MS*K6 br=Zr*invDr-Zi*invDi : bi=Zr*invDi+Zi*invDr 'b=(MO*K4 + ML*K5 + MS*K6)/D 'Calculate coefficient c. Wr=K7r+K8r+K9r : Wi=K7i+K8i+K9i 'W = K7 + K8 + K9 cr=Wr*invDr-Wi*invDi : ci=Wr*invDi+Wi*invDr 'c = (K7 + K8 + K9)/D 'Put coefficients into OSLBandx() OSLBandA(calStep,0)=ar : OSLBandA(calStep,1)=ai OSLBandB(calStep,0)=br : OSLBandB(calStep,1)=bi OSLBandC(calStep,0)=cr : OSLBandC(calStep,1)=ci next calStep end sub 'ver115-1b added CalcOSLStandards sub CalcOSLStandards 'Calculate ref. coeff. of OSL standards 'The Open is characterized as a time delay plus a fringe capacitance. The Short is characterized 'as a time delay plus a parallel resistance/inductance shunted to ground. The Load is characterized 'as a delay and resistance, and either a parallel capacitance or a series inductance. 'For each frequency 'in datatable, calculate the Open and Short response. Put the open response into OSLstdOpen() and 'Short response into OSLstdShort(), both in real, imag form. 'The response is calculated relative to the jig or bridge R0, not the graph R0 if S11JigType$="Trans" then R0=S21JigR0 else R0=S11BridgeR0 simpleLoad=((OSLLoadLC=0) and (OSLLoadDelay=0)) 'If load is simple resistance, things are easier if simpleLoad then 'precalculate for simple load ver115-7a call uImpedanceToRefco R0, OSLLoadRes, 0, rho, theta 'refco of Load resistance loadRho=rho*cos(theta) : loadTheta=rho*sin(theta) 'Load refco; the same at all frequencies loadReal=loadRho*cos(loadTheta) : loadImag=loadRho*sin(loadTheta) 'Load refco as real, imag end if for i=0 to globalSteps freq=ReflectArray(i,0)*1000000 'frequency in Hz ver115-7a call uComboImpedance "P", constMaxValue,constMaxValue, OSLOpenCap, constMaxValue,constMaxValue,freq, Zr, Zi 'imped of Open's capacitance ver115-4b call uImpedanceToRefco R0, Zr, Zi, rho, theta 'refco of Open's capacitance phaseDelay=OSLOpenDelay*360*freq 'phase delay (deg)=delay(sec)*degrees/cycle*cycles/sec theta=theta-2*phaseDelay 'Delay reflection by twice phaseDelay, for round trip. ver115-8a changed to subtraction theta=theta*uRadsPerDegree() 'Need radians for sin and cos functions ver115-1e OSLstdOpen(i, 0)=rho*cos(theta) : OSLstdOpen(i,1)=rho*sin(theta) 'Save Open refco as real, imag call uComboImpedance "P", OSLShortRes,OSLShortInd,0,constMaxValue,constMaxValue, freq, Zr, Zi 'imped of Short's res||induct ver115-4b call uImpedanceToRefco R0, Zr, Zi, rho, theta 'refco of Short's res||induct phaseDelay=OSLShortDelay*360*freq 'phase delay (deg)=delay(sec)*degrees/cycle*cycles/sec theta=theta-2*phaseDelay 'Delay reflection by twice phaseDelay, for round trip. ver115-8a changed to subtraction theta=theta*uRadsPerDegree() 'Need radians for sin and cos functions ver115-1e OSLstdShort(i, 0)=rho*cos(theta) : OSLstdShort(i,1)=rho*sin(theta) 'Save Short refco as real, imag if simpleLoad then 'ver115-7a OSLstdLoad(i, 0)=loadReal : OSLstdLoad(i,1)=loadImag 'Save Load refco as real, imag else 'Calc refco for resistance in series with inductance, or in parallel with cap, plus delay if OSLLoadHasCap then call uComboImpedance "P", OSLLoadRes,constMaxValue, OSLLoadLC,constMaxValue,constMaxValue, freq, Zr, Zi 'imped of Short's res||induct ver115-4b else call uComboImpedance "S", OSLLoadRes,OSLLoadLC,constMaxValue, constMaxValue,constMaxValue, freq, Zr, Zi end if call uImpedanceToRefco R0, Zr, Zi, rho, theta 'refco of Load before delay phaseDelay=OSLLoadDelay*360*freq 'phase delay (deg)=delay(sec)*degrees/cycle*cycles/sec theta=theta-2*phaseDelay 'Delay reflection by twice phaseDelay, for round trip. ver115-8a changed to subtraction theta=theta*uRadsPerDegree() 'Need radians for sin and cos functions OSLstdLoad(i, 0)=rho*cos(theta) : OSLstdLoad(i,1)=rho*sin(theta) 'Save Load refco as real, imag end if next i end sub '---------------End Routines to Handle OSL Calibration--------------- '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" menu #handle, "File", "Save Image", [SaveImage], "Load Prefs", [menuLoadPreferenceFile], _ "Save Prefs", menuSavePreferenceFile, _ "Load Data", [menuLoadDataFile], "Save Data", [menuSaveDataFile], _ "Load Front End", [menuLoadFrontEndFile], _ 'ver115-9d "Save Debug Info", [DebugSaveData], "Load Debug Info", [DebugLoadData] menu #handle, "Edit", "Copy Image",[CopyImage] 'SEW if hasVNA then 'Show PDM calibration and Smith Chart options only if we have the VNA menu #handle, "Setup", "Hardware Config Manager", [menuRunConfig], _ "Initial Cal Manager", [menuRunCal], _ "Special Tests", [SpecialTests], "PDM Calibration", [menuCalPDM], _ "Primary Axis", [menuPrimaryAxis] 'ver115-3c menu #handle, "Options", "Appearances",AppearanceDialog,"Markers", mMenuMarkerOptions, _ "Sweep", [menuFreqAxisPreference], "Show Variables", [Showvar], _ "Reference Lines", ReferenceDialog, _ "Smith Chart", smithOpenChart else 'no VNA 'ver 115-9e displayed initial cal manager but not PDM cal when there is no VNA menu #handle, "Setup", "Hardware Config Manager", [menuRunConfig], _ "Initial Cal Manager", [menuRunCal], _ "Special Tests", [SpecialTests], _ "Primary Axis", [menuPrimaryAxis] 'ver115-3c menu #handle, "Options", "Appearances",AppearanceDialog,"Markers", mMenuMarkerOptions, _ "Reference Lines", ReferenceDialog end if menuOptionsPosition=3 'Options menu is fourth, which is position 3 when indexed from zero menu #handle, "Data", "Graph Data", [DataWin_GraphData], "Input Data",[MSAinputData], _ 'Data for all modes "S21 Parameters",[MagPhaS21], "Installed Line Cal",[LineCalArray], _ 'Trans Data "S11 Parameters", [MagPhaS11], "S11 Derived Data",[ReflectDerivedData], _ 'Reflection Data "Cal Reference",[LineCalArray], "OSL Info",[DataWin_OSL] 'Reflection Data menu #handle, "Functions", "Filter Analysis",SetFilterAnalysis , _ 'SA and Trans functions "Component Meter", [menuComponentMeasure], "RLC Analysis", [menuRLCAnalysis], _'Trans and reflection functions "Crystal Analysis", [menuCrystalAnalysis], "Group Delay", [FunctionGroupDelay], _ 'Trans functions "Coax Parameters", [menuCoaxAnalyzeTLScan], "Generate S21", [menuS11ToS21] 'Reflection functions menuDataPosition=4 'Data menu is fifth, which is position 4 when indexed from zero menuFunctionsPosition=5 'Functions menu is sixth, which is position 5 when indexed from zero if TGtop>0 then 'No need for operating cal menu or mode selection if SA is the only possible mode ver114-5n menu #handle, "Operating Cal", "Perform Cal", [RunVNACal], "Reference To",[menuVNARef] menuOperatingCalPosition=6 'Cal menu is 7th, if we have it menuOperatingCalShowing=1 if hasVNA then 'Build level 3 menu #handle, "Mode", "Spectrum Analyzer", [RestartPlainSAmode], _ 'ver115-4f "Spectrum Analyzer with TG", [RestartSATGmode], _ 'ver115-4g "VNA Transmission", [RestartTransmissionMode], _ "VNA Reflection", [RestartReflectionMode] else 'Build level 2 menu #handle, "Mode", "Spectrum Analyzer", [RestartPlainSAmode], _ "Spectrum Analyzer with TG", [RestartSATGmode], "SNA Transmission", [RestartTransmissionMode] 'ver115-4f end if menuMultiscanPosition=8 'Functions menu is 9th, which is position 8 when indexed from zero else menuOperatingCalPosition=0 'No Cal menu menuOperatingCalShowing=0 menuMultiscanPosition=7 'Functions menu is 8th, which is position 7 when indexed from zero end if 'MULTISCAN MENU. menu #handle, "Multiscan", "Run Multiscan",[multiscanMenuRun], "Show Multiscan", multiscanMenuShowAll, _ "Quit Multiscan", menuQuitMultiscan, "Multiscan Help", multiscanHelp 'ver115-8d 'GraphicBox for graphing currGraphBoxHeight=initialGraphWindowHeight-clientHeightOffset-41 'ver115-1b 'ver115-1c currGraphBoxWidth=initialGraphWindowWidth-clientWidthOffset 'ver115-1b 'ver115-1c graphicbox #handle.g, 0,0,currGraphBoxWidth,currGraphBoxHeight 'Marker Selection buttons markTop=currGraphBoxHeight+12 'This isn't the top of anything in particular, just a reference point ver115-1b 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 'ver115-1a del115_1a 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 'ver115-1b button #handle.markInc, "+",[btnIncPoint], LL, markEditLeft+130, -7, 14,13 'ver115-1b 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 'Test Setup Button 'ver115-1g added this and deleted go/save config configLeft=markMiscLeft+70 stylebits #handle.testsetup, _BS_MULTILINE, 0, 0, 0 button #handle.testsetup, "Test Setups", [ManageTestSetups], LL, configLeft, -5, 50, 35 'ver113-1a '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",[RestartButton], LR, 35,-6,60,19 'ver115-8c '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 if graphBox$<>"" then close #handle 'if a window is already open, close it open "" for window as #handle 'Caption is set in ConformMenusToMode ver115-5d graphBox$="#handle.g" 'Used to draw in the graphics box 'ver115-1a hGraphWindow=hwnd(#handle) 'get graph window handle calldll #user32, "GetMenu",_ hGraphWindow as ulong,_ ' graph window handle hGraphMenuBar as ulong 'returns handle of menubar 'Get handles for menus that need to conform to the mode hFileMenu=uSubMenuHandle(hGraphMenuBar, 0) 'File menu is position 0 hOptionsMenu=uSubMenuHandle(hGraphMenuBar, menuOptionsPosition) hDataMenu=uSubMenuHandle(hGraphMenuBar, menuDataPosition) hFunctionsMenu=uSubMenuHandle(hGraphMenuBar, menuFunctionsPosition) if menuOperatingCalPosition=0 then hOperatingCalMenu=0 _ else hOperatingCalMenu=uSubMenuHandle(hGraphMenuBar, menuOperatingCalPosition) hMultiscanMenu=uSubMenuHandle(hGraphMenuBar, menuMultiscanPosition) 'Get ID of various listed menu items that may need to be hidden/shown in certain modes menuDataS21ID=uMenuItemID(hDataMenu, 2) menuDataLineCalID=uMenuItemID(hDataMenu, 3) menuDataS11ID=uMenuItemID(hDataMenu, 4) menuDataS11DerivedID=uMenuItemID(hDataMenu, 5) menuDataLineCalRefID=uMenuItemID(hDataMenu, 6) menuDataLineCalOSLID=uMenuItemID(hDataMenu, 7) if hasVNA=0 then menuOptionsSmithID=0 else menuOptionsSmithID=uMenuItemID(hOptionsMenu, 5) menuFunctionsFilterID=uMenuItemID(hFunctionsMenu, 0) menuFunctionsMeterID=uMenuItemID(hFunctionsMenu, 1) menuFunctionsRLCID=uMenuItemID(hFunctionsMenu, 2) menuFunctionsCrystalID=uMenuItemID(hFunctionsMenu, 3) menuFunctionsGroupDelayID=uMenuItemID(hFunctionsMenu, 4) 'ver115-8b menuFunctionsCoaxID=uMenuItemID(hFunctionsMenu, 5) menuFunctionsGenerateS21ID=uMenuItemID(hFunctionsMenu, 6) menuMode$="" 'because menus don't conform to any mode now. call ConformMenusToMode 'Hide whatever menu items we don't need for current msaMode$ 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$, currGraphBoxWidth, currGraphBoxHeight, _ 'ver115-1c graphMarLeft, graphMarRight, graphMarTop, graphMarBot call gCalcGraphParams 'Calculate new scaling return 'From [CreateGraphWindow] sub menuQuitMultiscan 'Quit multiscan 'This command is made in the main window, so the multiscan windows will already be hidden, 'but haven't actually been closed. multiscanIsOpen=0 multiscanInProgress=0 call multiscanCloseAll end sub 'ver115-5d added ConformMenusToMode sub ConformMenusToMode 'Make menus and window caption match mode. 'msaMode$ is the current mode. menuMode$ is the mode to which the menus are currently conformed. if msaMode$="SA" then if gentrk=0 then modeTitle$="Spectrum Analyzer Mode" else modeTitle$="Spectrum Analyzer with TG Mode" 'ver115-4f end if if msaMode$="ScalarTrans" then modeTitle$="Tracking Generator Mode" if msaMode$="VectorTrans" then modeTitle$="VNA Transmission Mode" if msaMode$="Reflection" then modeTitle$="VNA Reflection Mode" ver$="Ver";msaVersion$;", Rev"; msaRevision$ 'ver115-5f call uSetWindowText hGraphWindow, "MSA Graph Window for ";modeTitle$; "; "; ver$ 'Note we continue even if there is no mode change, mainly to get multiscan window right 'if msaMode$=menuMode$ then exit sub 'Nothing to do wasTransMode= (menuMode$="ScalarTrans" or menuMode$="VectorTrans") 'whether prior mode was transmission isTransMode= (msaMode$="ScalarTrans" or msaMode$="VectorTrans") 'whether current mode is transmission if wasTransMode and isTransMode then menuMode$=msaMode$ : exit sub 'Nothing needs changing 'Hide every menu item that is ever to be hidden, then show what we want. menuOK=uHideCommandItem(hDataMenu, menuDataS21ID) menuOK=uHideCommandItem(hDataMenu, menuDataLineCalID) menuOK=uHideCommandItem(hDataMenu, menuDataS11ID) menuOK=uHideCommandItem(hDataMenu, menuDataS11DerivedID) menuOK=uHideCommandItem(hDataMenu, menuDataLineCalRefID) menuOK=uHideCommandItem(hDataMenu, menuDataLineCalOSLID) if menuOptionsSmithID>0 then menuOK=uHideCommandItem(hOptionsMenu, menuOptionsSmithID) menuOK=uHideCommandItem(hFunctionsMenu, menuFunctionsFilterID) menuOK=uHideCommandItem(hFunctionsMenu, menuFunctionsCrystalID) menuOK=uHideCommandItem(hFunctionsMenu, menuFunctionsGroupDelayID) 'ver115-8b menuOK=uHideCommandItem(hFunctionsMenu, menuFunctionsMeterID) menuOK=uHideCommandItem(hFunctionsMenu, menuFunctionsRLCID) menuOK=uHideCommandItem(hFunctionsMenu, menuFunctionsCoaxID) menuOK=uHideCommandItem(hFunctionsMenu, menuFunctionsGenerateS21ID) 'If we had operating cal menu, hide it if menuOperatingCalShowing then menuOK=uHideSubMenu(hGraphMenuBar, menuOperatingCalPosition) menuOperatingCalShowing=0 end if menuMultiscanPosition=7 'because operating cal menu, even if it exists, is now hidden menuOK=uHideSubMenu(hGraphMenuBar, menuMultiscanPosition) 'We now have bare minimum of menus. 'Make adjustments from here if msaMode$<>"Reflection" then menuOK=uShowMenuItem(hFunctionsMenu, menuFunctionsFilterID,0, "Filter Analysis", 0) frontEndID=uMenuItemID(hFileMenu,5) ' "Load Front End" menu is sixth in File menu, which is position 5 if msaMode$<>"SA" then menuOK=uGrayMenu(hFileMenu, frontEndID) 'Disable Load Front End 'ver115-9d menuOK=uShowMenuItem(hGraphMenuBar, -1, hOperatingCalMenu, "Operating Cal", menuOperatingCalPosition) 'Operating Cal menu menuOperatingCalShowing=1 menuMultiscanPosition=menuMultiscanPosition+1 if msaMode$="Reflection" then 'Reflection Mode menuOK=uShowMenuItem(hDataMenu, menuDataS11ID, 0,"S11 Parameters", 2) 'S11 is third in Data menu menuOK=uShowMenuItem(hDataMenu, menuDataS11DerivedID, 0,"S11 Derived Data", 3) menuOK=uShowMenuItem(hDataMenu, menuDataLineCalRefID, 0, "Cal Reference", 4) menuOK=uShowMenuItem(hDataMenu, menuDataLineCalOSLID, 0, "OSL Info",5) menuOK=uShowMenuItem(hOptionsMenu, menuOptionsSmithID, 0, "Smith Chart", 5) 'Smith chart is 6th in Options list menuOK=uShowMenuItem(hFunctionsMenu, menuFunctionsMeterID, 0,"Component Meter",0) 'Component meter is first on Functions list menuOK=uShowMenuItem(hFunctionsMenu, menuFunctionsRLCID, 0,"RLC Analysis",1) menuOK=uShowMenuItem(hFunctionsMenu, menuFunctionsCoaxID, 0, "Coax Parameters", 2) 'Coax is 3rd on Functions list menuOK=uShowMenuItem(hFunctionsMenu, menuFunctionsGenerateS21ID, 0, "Generate S21", 3) else 'Transmission Mode--Scalar or Vector menuOK=uShowMenuItem(hFunctionsMenu, menuFunctionsMeterID, 0,"Component Meter",1) 'Component meter is second on Functions list menuOK=uShowMenuItem(hFunctionsMenu, menuFunctionsRLCID, 0,"RLC Analysis",2) menuOK=uShowMenuItem(hFunctionsMenu, menuFunctionsCrystalID, 0, "Crystal Analysis", 3) 'Crystal is 4th on Functions list if msaMode$="VectorTrans" then menuOK=uShowMenuItem(hFunctionsMenu, menuFunctionsGroupDelayID, 0, "Group Delay", 4) 'ver115-8b menuOK=uShowMenuItem(hDataMenu, menuDataS21ID, 0,"S21 Parameters", 2) 'S21 is third in Data menu menuOK=uShowMenuItem(hDataMenu, menuDataLineCalID, 0, "Installed Line Cal", 3) end if end if if msaMode$="SA" then menuOK=uEnableMenu(hFileMenu, frontEndID) 'Enable Load Front End 'ver115-9d end if if msaMode$="SA" and gentrk=0 then 'Display Multiscan window only when in SA mode without TG menuOK=uShowMenuItem(hGraphMenuBar, 0, hMultiscanMenu, "Multiscan", menuMultiscanPosition) showID=uMenuItemID(hMultiscanMenu,1) ' "Show Multiscan" menu quitID=uMenuItemID(hMultiscanMenu,2) ' "Quit Multiscan" menu 'If multiscan is open, allow user to Show or Quit if multiscanIsOpen then menuOK=uEnableMenu(hMultiscanMenu, showID) 'Enable Show menuOK=uEnableMenu(hMultiscanMenu, quitID) 'Enable Quit else menuOK=uGrayMenu(hMultiscanMenu, showID) 'Gray Show menuOK=uGrayMenu(hMultiscanMenu, quitID) 'Gray Quit end if end if call uDrawMenu hGraphWindow menuMode$=msaMode$ 'We are now conformed to the current mode. end sub '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 if smithGraphHndl$()<>"" then call smithDrawChart 'To recreate bitmap of background, just in case it is messed up ver115-2c 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 prevFreqMode=FreqMode 'ver115-1c 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 'ver115-1a prevPath$=path$ 'ver115-1a '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. prevY1DataType=Y1DataType 'ver115-1b deleted source constants prevY2DataType=Y2DataType '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 'ver115-1e prevS21JigShuntDelay=S21JigShuntDelay 'ver115-1f prevS11BridgeR0=S11BridgeR0 : prevS11GraphR0=S11GraphR0 prevS11JigType$=S11JigType$ 'ver115-1b '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 prevY1Disp=Y1DisplayMode : prevY2Disp=Y2DisplayMode '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 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 'RBW, 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 'TO DO--The concept has been to take the minimum action necessary, primarily for speed, but also to 'preserve existing data when possible. Now that we have [PartialRestart], it might make more sense 'to require [PartialRestart] whenever there is any doubt, and to zero out the data when it no longer 'makes sense. The caller can then do [PartialRestart] and regraph the data. In fact, we could change 'this subroutine to a gosub, and take all necessary action here. But it may be better for the user to do 'the restart, in case a series of changes are being made--the restart can be done at the end of the series. 'Some things we do here, such as recalculating graph params, would become unnecessary. continueCode=0 'Assume we can continue when we are done here doCalcAndRedraw=0 doTransform=0 dataTypeChanged=0 'ver115-1b '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 prevY1DataType<>Y1DataType or prevY2DataType<>Y2DataType then 'ver115-4g call gSetDoAxis (Y1DataType<>constNoGraph), (Y2DataType<>constNoGraph) 'Tell graph module whether we have graphs ver115-2c call ImplementDisplayModes 'ver114-6e doCalcAndRedraw=1 : dataTypeChanged=1 :doTransform=1 'ver115-1b end if 'Changes to these will require a complete Restart call gGetXAxisRange currStartF, currEndF call gGetIsLinear currXIsLinear, currY1IsLinear, currY2IsLinear if FreqMode<>prevFreqMode or currStartF<>prevStartF or currEndF<>prevEndF or prevSteps<>globalSteps then doRestart=1 'ver115-1c 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 'ver115-1a 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 'ver115-1a 'If in a mode where these are relevant, we need to require Restart, 'but do not do anything to the existing data. Note that the calibration 'will be invalidated elsewhere in these cases, so there is no meaningful way 'to transform the data. if msaMode$="Reflection" then 'ver115-1f if prevS21JigAttach$<>S21JigAttach$ then doRestart=1 if prevS21JigR0<>S21JigR0 then doRestart=1 if prevS21JigShuntDelay<>S21JigShuntDelay then doRestart=1 if prevS11JigType$<>S11JigType$ or prevS11BridgeR0<>S11BridgeR0 then doRestart=1 end if 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 or fixed value reference, recalculate reference data if referenceLineType>1 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 rescaleReferences=0 call gGetYAxisRange 1, currStartY1, currEndY1 call gGetYAxisRange 2, currStartY2, currEndY2 call gGetNumDivisions currHorDiv, currVertDiv if currStartY1<>prevStartY1 or currEndY1<>prevEndY1 then doCalcAndRedraw=1 : rescaleReferences=1 if currStartY2<>prevStartY2 or currEndY2<>prevEndY2 then doCalcAndRedraw=1 : rescaleReferences=1 if currHorDiv<>prevHorDiv or currVertDiv<>prevVertDiv then doCalcAndRedraw=1 if rescaleReferences then call CreateReferenceTransform 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 data changes, recalc x pixel values and require a restart, though proceeding will destroy the new data if msaMode$="Reflection" and prevS11GraphR0<>S11GraphR0 then continueCode=3 : doTransform=1 'ver115-1f 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 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 prevY1Disp<>Y1DisplayMode and (Y1DisplayMode<>0 or prevY1Disp=0) then doRefreshTraces=1 'ver114-7d if prevY2Disp<>Y2DisplayMode and (Y2DisplayMode<>0 or prevY2Disp=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 'Also includes primaryAxisNum, which has no immediate effects except the order of marker info 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 if referenceDoMath=2 then 'ref math is to be done on graph values ver115-5d if (referenceTrace and 1) then _ y1=referenceOpA*referenceTransform(thisstep+1, 1)+referenceOpB*y1 if (referenceTrace and 2) then _ y2=referenceOpA*referenceTransform(thisstep+1, 2)+referenceOpB*y2 end if 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 if referenceLineType>1 then call CreateReferenceSource call CreateReferenceTransform call gClearAllReferences if referenceDoMath=0 then 'don't draw if we are using ref for math ver114-8b if (referenceTrace and 2) then call gAddReference 1,CreateReferenceTraces$(referenceColor2$,referenceWidth2,2) 'Do Y2 reference if (referenceTrace and 1) then _ call gAddReference 2,CreateReferenceTraces$(referenceColor1$,referenceWidth1,1) end if end if call PrintReferenceHeading if referenceDoMath=0 then call gDrawReferences 'don't draw if we are using ref for math ver115-5d 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 if multiscanIsOpen then call multiscanMarkCurrentWindow 'mark current graph 'ver115-9a 'Discard draw commands if scan is still in progress; otherwise flush if haltsweep=1 then #graphBox$, "discard" else #graphBox$, "flush" if smithGraphHndl$()<>"" then 'ver115-1b draw smith chart if we have one call smithSetGraphMarkers doGraphMarkers 'Tell smith whether to draw markers on graph ver115-2c if referenceLineType<>0 and (referenceTrace and 4=4) then _ doSmithRef=(referenceDoMath=0) else doSmithRef=0 'draw non-fixed value reference ver115-7a call smithRefresh doSmithRef 'Draw chart and graph, with possible reference line end if '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 autoscale is on then calculate the scale and redraw from raw values if autoScaleY1 then call CalcAutoScale 1, newMin, newMax : call SetY1Range newMin, newMax 'ver115-3b if autoScaleY2 then call CalcAutoScale 2, newMin, newMax : call SetY2Range 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 axisNum$=str$(primaryAxisNum) 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 primaryAxisNum,pStart, pEnd, minNum, maxNum, minY, maxY 'ver115-3b 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 mDeleteMarker "L" : call mDeleteMarker "R" 'ver115-1e else call gFindDBOffset primaryAxisNum,pNum, doLRRelativeAmount, doLRAbsolute,leftPoint, rightPoint 'ver115-3f if leftPoint>=1 then call mAddMarker "L", leftPoint, axisNum$ else call mDeleteMarker "L" 'ver115-3b if rightPoint>=1 then call mAddMarker "R", rightPoint, axisNum$ else call mDeleteMarker "R" 'ver115-3b 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 primaryAxisNum, peakPoint, 1, 1 'Find points down 3db, x1DBDown and x2DBDown, and ripple min and max; ver115-3b 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, axisNum$ : call mAddMarker "3", x1HighPoint, axisNum$ 'ver115-3b if x2DBDown<>0 then _ call mAddMarker "4", x2LowPoint, axisNum$ : call mAddMarker "5", x2HighPoint, axisNum$ 'ver115-3b 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+2 call gGetInfoColors textColor$, backColor$ #graphBox$, "font Tahoma 8 bold;color ";textColor$;";backcolor ";backColor$ if msaMode$="SA" then 'ver115-1b rewrote this if... block 'SA mode, either with or without TG if gentrk=0 then 'ver115-4f call gPrintText "Spect. Analyzer", InfoX-10,16 else call gPrintText "Spect. Analyzer with TG", InfoX-40,16 end if else if msaMode$="ScalarTrans" then call gPrintText "SNA Transmission", InfoX-10,16 'ver115-4e if msaMode$="VectorTrans" then call gPrintText "VNA Transmission", InfoX-10,16 'ver115-1c revised the printing of the cal level if msaMode$="Reflection" then call gPrintText "VNA Reflection", InfoX-10,16 if applyCalLevel0 then 'ver115-4f if gentrk=0 then freq$=str$(sgout) if len(freq$)<3 then 'ver115-4g call gPrintText "Sig Gen="+freq$, InfoX, InfoY: InfoY=InfoY+16 else call gPrintText "Sig Gen=", InfoX, InfoY: InfoY=InfoY+14 call gPrintText " "+freq$, InfoX, InfoY: InfoY=InfoY+16 end if else if normrev=0 then nr$="TG=Normal" else nr$="TG=Reverse" call gPrintText nr$, InfoX, InfoY: InfoY=InfoY+16 freq$=str$(offset) if len(freq$)<2 then 'ver115-4g call gPrintText "Offset="+freq$, InfoX, InfoY: InfoY=InfoY+16 else call gPrintText "Offset=", InfoX, InfoY: InfoY=InfoY+14 call gPrintText " "+freq$, InfoX, InfoY: InfoY=InfoY+16 end if end if end if if msaMode$<>"SA" and msaMode$<>"ScalarTrans" then call gPrintText "Exten=";str$(planeadj)+" ns", InfoX, InfoY : InfoY=InfoY+16 'ver114-5f end if if msaMode$="Reflection" then call gPrintText "Z0=";S11GraphR0, InfoX, InfoY : InfoY=InfoY+16 if S11JigType$="Reflect" then s$="Bridge" else s$=S21JigAttach$ call gPrintText s$, InfoX, InfoY : InfoY=InfoY+16 end if s$="" if referenceDoMath then 'If doing math with reference line, so indicate if referenceOpA=1 and referenceOpB=1 then s$="Data+Ref" if referenceOpA=1 and referenceOpB=-1 then s$="Ref-Data" if referenceOpA=-1 and referenceOpB=1 then s$="Data-Ref" call gPrintText s$, InfoX, InfoY : InfoY=InfoY+16 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$=str$(primaryAxisNum) 'Always do peak markers on primary trace case "P-" hasMarkPeakNeg=1 markTrace$=str$(primaryAxisNum) 'Always do peak markers on primary trace 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 ver115-1a end if if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then 'ver114-5n IL=gGetPointYVal(peakPoint,primaryAxisNum) : if IL<0 then IL=0-IL 'ver115-4f '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 'ver115-1e 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)) 'ver115-1e 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; Limited to 75 characters; don't print if blank '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$(100), x, y if message$<>"" then call gPrintText "MESSAGE: ";Left$(message$,75), x, y 'ver114-5c Don't print if blank end sub 'ver114-4d added SetY1Range sub SetY1Range bot, top 'Set range of phase axis call gSetYAxisRange 1, bot, top botphase=bot topphase=top end sub 'ver114-4d added SetY2Range sub SetY2Range bot, top 'Set range of mag/power axis call gSetYAxisRange 2, bot, top botref=bot topref=top end sub 'ver115-1g added [ManageTestSetups] [ManageTestSetups] 'Menu item to load/save test setups WindowWidth = 575 WindowHeight = 435 UpperLeftX=int((DisplayWidth-WindowWidth)/2) UpperLeftY=int((DisplayHeight-WindowHeight)/2) ForegroundColor$="black" BackgroundColor$="gray" ListboxColor$ = "white" if haltsweep then gosub [FinishSweeping] setupTotalNum=10 for i=0 to setupTotalNum-1 : setupList$="" : next i listbox #testsetup.List, setupList$(), [setupListClick], 105, 92, 355, 170 statictext #testsetup, "To save a test setup consisting of the current sweep settings and calibration data,", 20, 12, 500, 20 statictext #testsetup, "select a slot, change the name if desired, and click Save.", 20, 32, 450, 20 statictext #testsetup, "To load a test setup, select it and click Load.", 20, 57, 450, 20 TextboxColor$ = "white" textbox #testsetup.Name, 140, 307, 300, 25 button #testsetup.Create,"Create Name",[setupCreateName], UL, 445, 300, 100, 30 button #testsetup.Save,"Save",[setupSave], UL, 40, 352, 100, 40 button #testsetup.Load,"Load",[setupLoad], UL, 160, 352, 100, 40 button #testsetup.Delete,"Delete Setup",[setupDelete], UL, 280, 352, 100, 40 button #testsetup.Done,"Done",[setupDone], UL, 400, 352, 100, 40 statictext #testsetup, "Name:", 90, 307, 40, 20 '-----End GUI objects code open "Test Setups" for dialog_modal as #testsetup print #testsetup, "font ms_sans_serif 10" print #testsetup, "trapclose [setupDone]" #testsetup.List, "singleclickselect" gosub [setupFillList] setupCurrentSelection=-1 'start with none selected #testsetup.Load, "!disable" : #testsetup.Delete, "!disable" : #testsetup.Save, "!disable" 'Can't act without selection setupHaveDonePartialRestart=0 'see setupSave wait [setupSave] 'Save button 'We do a restart but return before taking any data. This makes sure any changes the user has 'made, such as frequency range, are actually implemented so they can be saved properly.But this only 'needs to be done once while in this dialog. #testsetup.Load, "!disable" : #testsetup.Delete, "!disable" : #testsetup.Save, "!disable" : #testsetup.Done, "!disable" if setupHaveDonePartialRestart=0 then setupHaveDonePartialRestart=1 gosub [PartialRestart] 'ver115-3c end if fHndl$=SetupOpenFile$(setupCurrentSelection, 0) '0 means output if fHndl$="" then notice "Error in opening file" #testsetup.Save, "!enable" : #testsetup.Done, "!enable" wait end if 'We save the file description as line 1, preceded by a "!" #testsetup.Name, "!contents? setupName$" newLine$=chr$(13) print #fHndl$, "!";setupName$ 'We then save the necessary info as contexts. 'First, the sweep context. We don't start with StartContext because we know what the file starts with print #fHndl$, TraceContext$();newLine$;"EndContext";newLine$;"StartContext Sweep"; newLine$;SweepContext$();newLine$;"EndContext" 'ver115-4a 'Next any applicable Band cal file. if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then if BandLineCalIsCurrent() then call BandLineCalContextToFile fHndl$ end if if msaMode$="Reflection" then if BandOSLCalIsCurrent() then call OSLCalContextToFile fHndl$, 1 '1 means band cal end if close #fHndl$ : fHndl$="" setupList$(setupCurrentSelection-1)=setupCurrentSelection;". ";setupName$ #testsetup.List, "Reload" #testsetup.Load, "!enable" : #testsetup.Delete, "!enable" : #testsetup.Save, "!enable" : #testsetup.Done, "!enable" wait [setupLoad] 'Load button #testsetup.Load, "!disable" : #testsetup.Delete, "!disable" : #testsetup.Save, "!disable" : #testsetup.Done, "!disable" fHndl$=SetupOpenFile$(setupCurrentSelection, 1) '1 means input if fHndl$="" then notice "Error in opening file" #testsetup.Load, "!enable" : #testsetup.Delete, "!enable" : #testsetup.Save, "!enable" : #testsetup.Done, "!enable" wait end if joint$="" trace$="" : setupIsFirstLine=1 while EOF(#fHndl$)=0 'Assemble the trace context lines into a single string Line Input #fHndl$, s1$ if Upper$(Trim$(s1$))="ENDCONTEXT" then exit while if setupIsFirstLine=0 then 'Skip first line, which is the descriptive file name trace$=trace$;joint$;s1$ joint$=chr$(13) end if setupIsFirstLine=0 wend joint$="" restoreContext$="" :setupIsFirstLine=1 while EOF(#fHndl$)=0 'Assemble the sweep context lines into a single string for [RestoreSweepContext] Line Input #fHndl$, s1$ if Upper$(Trim$(s1$))="ENDCONTEXT" then exit while if setupIsFirstLine=0 then 'Skip first line, which is StartContext Sweep restoreContext$=restoreContext$;joint$;s1$ joint$=chr$(13) end if setupIsFirstLine=0 wend prevMSAMode$=msaMode$ 'So we can detect any change restoreIsValidation=0 'Indicates to actually restore data traceStart=1 restoreErr$=RestoreTraceContext$(trace$,traceStart,0) 'Actual trace restoration if restoreErr$="" then gosub [RestoreSweepContext] 'Actual sweep restoration if restoreErr$<>"" then notice "Error in loading context: ";restoreErr$ else setupNumCalPoints=0 if msaMode$="ScalarTrans" or msaMode$="VectorTrans" then setupNumCalPoints=GetBandLineCalContextFromFile(fHndl$) if msaMode$="Reflection" then setupNumCalPoints=OSLGetCalContextFromFile(fHndl$, 1) '1 means band cal if setupNumCalPoints>0 then desiredCalLevel=2 'So band cal gets used end if close #fHndl$ : fHndl$="" 'We have to close the dialog before a possible mode change, because if 'the msaMode$ gets changed we will close the graph window, which closes the dialog 'and gets us messed up if we try to continue within the dialog. close #testsetup if prevMSAMode$<>msaMode$ then gosub [ChangeMode] 'We do a restart but return before taking any data. This makes sure everything is implemented 'consistently, in case we end up resaving the data we just loaded. gosub [PartialRestart] 'ver115-3c setupHaveDonePartialRestart=1 'In case of Save, we don't need to do the partial restart again 'call RequireRestart 'delver115-2a wait [setupDelete] 'Delete button fName$=DefaultDir$;"\MSA_Info\TestSetups\TestSetup";setupCurrentSelection;".txt" call uDeleteFile fName$ 'Delete the file setupList$(setupCurrentSelection-1)=setupCurrentSelection;". Empty" #testsetup.List, "Reload" #testsetup.Load, "!disable" : #testsetup.Delete, "!disable" 'No existing file; can't load or delete wait [setupDone] 'Done button or dialog closed #testsetup.Done, "!disable" 'Prevents double click which causes trouble in debugger close #testsetup wait [setupFillList] 'fill setupList$ with names of existing files 'The files are in a folder called TestSetups in the MSA_Info folder setupPath$=DefaultDir$;"\MSA_Info\TestSetups" files DefaultDir$;"\MSA_Info", "", fileInfo$() 'get directory list nFolders=val(fileInfo$(0,1)) folderFound=0 for i=1 to nFolders if fileInfo$(i,1)="TestSetups" then folderFound=1 : exit for 'We found the TestSetups folder next i if folderFound=0 then if mkDir(setupPath$)<>0 then notice "Error creating Setup folder.": return 'Folder doesn't exist, so make one end if for i=1 to setupTotalNum 'Check for each of the setupTotalNum possible files 'File exists; we need to get the descriptive name if SetupOpenFile$(i,1)="" then setupList$(i-1)=i;". Empty" else 'File is open. Get its description and close it setupName$=SetupGetDescription$("#setupFile") 'Get description of file #setupFile setupList$(i-1)=i;". ";setupName$ close #setupFile end if next i #testsetup.List, "Reload" 'transfer array info to the visible list return [setupListClick] 'User clicked an item on the list 'Enter name of selected item into name box. #testsetup.List, "selectionIndex? setupCurrentSelection" setupFullName$=setupList$(setupCurrentSelection-1) 'setupCurrentSelection starts with one; array starts with 0 dotPos=instr(setupFullName$, ".") 'Name starts with number then period. Find the period setupShortName$=Mid$(setupFullName$,dotPos+2) 'omit the number, the dot, and the space after the dot. #testsetup.Name, setupShortName$ #testsetup.Save, "!enable" if setupShortName$="Empty" then #testsetup.Load, "!disable" : #testsetup.Delete, "!disable" 'No existing file; can't load or delete #testsetup.Name, SetupName$() 'Print useful name, not "Empty" else #testsetup.Load, "!enable" : #testsetup.Delete, "!enable" 'file exists end if wait [setupCreateName] 'Create name for current setup; put it in name box #testsetup.Name, SetupName$() wait function SetupName$() 'Return descriptive name for current setup select msaMode$ case "SA" s$="SA/" case "ScalarTrans" s$="SA/TG" case "VectorTrans" s$="VNA Trans/" case else ' "Reflection" s$="VNA Reflect/" end select if gGetXIsLinear() then s$=s$;"Linear/" else s$=s$;"Log/" SetupName$=s$;startfreq;" to ";endfreq;"/";path$ end function function SetupOpenFile$(N, isInput) 'Open setup file; return its handle as text or blank if error 'If isInput, open for input, otherwise for output fName$=DefaultDir$;"\MSA_Info\TestSetups\TestSetup";N;".txt" 'Name of file N On Error goto [noFile] if isInput then open fName$ for input as #setupFile else open fName$ for output as #setupFile SetupOpenFile$="#setupFile" exit function [noFile] SetupOpenFile$="" 'ver114-2f end function function SetupGetDescription$(fHndl$) 'Get description of open file whose handle is in fHndl$ 'File exists; we need to get the descriptive name 'The description is the first line of the file, but includes a leading "!" which we delete here SetupGetDescription$="" if EOF(#fHndl$) then notice "Error getting Setup file description" : SetupGetDescription$="" : exit function Line Input #fHndl$, tLine$ SetupGetDescription$=Mid$(tLine$, 2) 'Everything except the exclamation. end function '-------------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=B" 'This item was added in ver114-7n and changed to B in ver115-1b s1$= s1$;newLine$;"msaMode=";msaMode$ 'ver114-6f ver115-1b s1$= s1$;newLine$;"FreqMode=";FreqMode 'ver115-1c s1$= s1$;newLine$;"SpecialGraph=";doSpecialGraph s1$=s1$;newLine$; "RLCSpec=";doSpecialRLCSpec$;";;";doSpecialCoaxName$ 'ver115-4b 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=";Y1DataType;aSpace$; Y2DataType 'ver115-1b deleted source constants s1$= s1$;newLine$;"Autoscale=";autoScaleY1; aSpace$; autoScaleY2 'ver114-7e s1$= s1$;newLine$;"S21Jig=";S21JigAttach$;aSpace$; S21JigR0;aSpace$;S21JigShuntDelay 'modver115-1e s1$= s1$;newLine$;"S11Bridge=";S11BridgeR0; aSpace$; S11GraphR0; aSpace$; S11JigType$ 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 'Note the StartContext line must already have been skipped. 'Get next line and increment startPos to start of the following line startPos=1 tLine$=uGetLine$(restoreContext$, startPos) oldStartPos=startPos contextVersion$="A" while tLine$<>"" origLine$=tLine$ 'ver115-1b 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" 'added by ver114-7n and ver115-1b contextVersion$=Trim$(tLine$) case "MSAMODE" 'if restoreIsValidation=0 and tLine$<>msaMode$ then changeModeTo$=tLine$ : gosub [ChangeMode] 'ver114-6f if restoreIsValidation=0 then msaMode$=tLine$ case "FREQMODE" 'ver115-1c if restoreIsValidation=0 then FreqMode=v1 case "SPECIALGRAPH" if restoreIsValidation=0 then doSpecialGraph=v1 case "RLCSPEC" 'ver115-4b if restoreIsValidation=0 then doSpecialRLCSpec$=uExtractTextItem$(tLine$,";;") doSpecialCoaxName$=tLine$ end if 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 if TGtop>0 then gentrk=v1 else gentrk=0 'Set gentrk only if we have the TG ver115-4f end if case "NORMREV" 'ver114-4i if restoreIsValidation=0 then normrev=v1 case "VIDEOFILTER" 'ver114-5p if restoreIsValidation=0 then videoFilter$=tLine$ case "GRAPHDATA" 'In Version A there was a different format for graph data, so we will 'just use default values. if contextVersion$="A" then v1=0 : v2=0 if msaMode$="SA" then v1=constNoGraph : v2=constMagDBM 'ver115-3b if msaMode$="ScalarTrans" then v1=constNoGraph : v2=constMagDB if msaMode$="VectorTrans" then v1=constAngle : v2=constMagDB if msaMode$="Reflection" then v1=constGraphS11Ang : v2=constGraphS11DB else isErr=uExtractNumericItems(2, tLine$, " ", v1, v2, v3) 'isErr if not two items end if 'Be sure data types are valid ver115-1b. An old preference file 'may use different data codes. call FilterDataType v1,1 'ver115-3b call FilterDataType v2,2 'ver115-3b if isErr=0 and restoreIsValidation=0 then Y1DataType=v1 : Y2DataType=v2 case "AUTOSCALE" 'ver114-7e if restoreIsValidation=0 then isErr=uExtractNumericItems(2, tLine$, " ", v1, v2, v3) 'ver115-1f 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$=uExtractTextItem$(tLine$," ") 'ver115-1f if w$<>"Series" and w$<>"Shunt" then isErr=1 if isErr=0 then S21JigAttach$=w$ isErr=uExtractNumericItems(2, tLine$, " ", v1, v2, v3) 'ver115-1f if v1<=0 then isErr=1 'modver115-1e if isErr=0 then S21JigR0=v1 : S21JigShuntDelay=v2 'modver115-1e end if case "S11BRIDGE" 'ver114-7e modver115-1b if restoreIsValidation=0 then isErr=uExtractNumericItems(2,tLine$, " ", v1, v2, v3) 'Extract three items and leave the third, a text item if v1<=0 or v2<=0 then isErr=1 tLine$=Trim$(tLine$) : if tLine$<>"Reflect" and tLine$<>"Trans" then tLine$="Trans" 'For backward compatibility if isErr=0 then S11BridgeR0=v1 : S11GraphR0=v2 : S11JigType$=tLine$ 'ver115-1e 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 restoreErr$="Sweep Context Error in: "; origLine$: return 'ver115-1b '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 delver115-1a steps=globalSteps sweepDir=gGetSweepDir() 'ver114-4n gosub [SelectFilter] 'selects filter for path$ ver114-4c return 'ver115-2a added GridContext$() function GridContext$() 'Get grid context as string s$="CustomNames=" for i=1 to 5 s$=s$;customPresetNames$(i);";:" 'use a goofy separator so user won't have used it next GridContext$=s$;gGridContext$() end function 'ver115-2a added RestoreGridContext$() 'ver115-1b added FilterDataType sub FilterDataType byref t, axisNum 'Make sure data types are valid for current msaMode$ 'Change to default values if invalid 'ver115-3b changed to do only a single variable, so we get called once per axis. select msaMode$ case "SA" if t<>constMagDBM and t<>constMagWatts and t<>constMagV and t<>constNoGraph then if axisNum<>gGetPrimaryAxis() then t=constNoGraph else t=constMagDBM 'ver115-7a end if case "ScalarTrans" if t<>constMagDB and t<>constMagRatio and t<>constInsertionLoss and t<>constNoGraph then if axisNum<>gGetPrimaryAxis() then t=constNoGraph else t=constMagDB 'ver115-7a end if case "VectorTrans" 'ver115-1i added raw mag and phase to transmission mode if t<>constMagDB and t<>constMagDBM and t<>constMagRatio and t<>constAngle _ and t<>constRawAngle and t<>constGD and t<>constInsertionLoss _ and t<>constNoGraph then 'ver115-2c if axisNum<>gGetPrimaryAxis() then t=constGraphS11Ang else t=constMagDB 'ver115-7a end if case "Reflection" if (tconstGraphS11SWR) and _ t<>constImpedMag and t<>constImpedAng and t>constReflectPower and t>constComponentQ _ and t<>constReturnLoss and t<>constNoGraph _ and t<>constAdmitMag and t<>constAdmitAng _ and t<>constConductance and t<>constSusceptance then 'ver115-4a if axisNum<>gGetPrimaryAxis() then t=constGraphS11Ang else t=constGraphS11DB 'ver115-7a end if case else t=constNoGraph end select end sub '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=";Y1DisplayMode;",";Y2DisplayMode 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$ 'ver115-1b 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 Y1DisplayMode=v1 : Y2DisplayMode=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 'ver115-1b '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 grid 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 'Return error message if error startPos=1 tLine$=uGetLine$(s$, startPos) oldStartPos=startPos contextVersion$="A" while tLine$<>"" origLine$=tLine$ 'ver115-1b 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 "CUSTOMNAMES" 'List of custom color preset names if isValidation=0 then for i=1 to 5 customPresetNames$(i)=uExtractTextItem$(tLine$, ";:") '5 items,separated by ";:" next i 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 'Get next line and increment startPos to start of the following line oldStartPos=startPos tLine$=uGetLine$(s$, startPos) wend 'process the data for the graph module call gGetGraphicsSize oldWidth, oldHeight 'save so we can restore errMsg$=gRestoreGridContext$(s$, startPos, isValidation) RestoreGridContext$=errMsg$ if errMsg$<>"" or isValidation=1 then exit function primaryAxisNum=gGetPrimaryAxis() 'ver115-3c 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 'ver115-1b 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 band 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$ uTextPointArray$(4)=sweep$;baseLinePath$;"; S21Jig=";baseLineS21JigAttach$; "; S21JigR0="; baseLineS21JigR0 'ver115-1b 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 'ver115-1b 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 'ver115-1b 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 'ver115-1b 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 'ver115-1b 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 'ver115-1g added OSLCalContextAsTextArray() function OSLCalContextAsTextArray(isBand) 'Put cal points into uTextPointArray$, with header info 'isBand=1 means we do band cal; =0 means base cal '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 uTextPointArray$(1)="! OSL Calibration Data" uTextPointArray$(2)="!" if isBand then if OSLBandLinear then sweep$="!Linear Sweep; " else sweep$="!Log Sweep " uTextPointArray$(3)="!";OSLBandTimeStamp$ 'Save sweep info: log/linear ; path info (in form Path N); Jig attachment and R0 uTextPointArray$(4)=sweep$;OSLBandPath$;"; S11Jig=";OSLBandS11JigType$; "; S11BridgeR0=";S11BridgeR0; _ 'ver115-9d "; S21Jig=";OSLBandS21JigAttach$; "; S21JigR0="; OSLBandS21JigR0 'ver115-1b, ver115-1g else if OSLBaseLinear then sweep$="!Linear Sweep; " else sweep$="!Log Sweep " uTextPointArray$(3)="!";OSLBaseTimeStamp$ 'Save sweep info: log/linear ; path info (in form Path N); Jig attachment and R0 uTextPointArray$(4)=sweep$;OSLBasePath$;"; S11Jig=";OSLBaseS11JigType$; "; S11BridgeR0=";S11BridgeR0; _ 'ver115-9d "; S21Jig=";OSLBaseS21JigAttach$; "; S21JigR0="; OSLBaseS21JigR0 'ver115-1b, ver115-1g end if uTextPointArray$(5)="!" aSpace$=" " 'if the appropriate OSLApplyFull is 1 then we save the A, B and C coefficients and the reference 'otherwise we save just the reference. if (isBand and OSLBandApplyFull) or (isBand=0 and OSLBaseApplyFull) then uTextPointArray$(6)="! MHz A_real A_imag B_real B_imag C_Real C_Imag RefDB RefDeg" else uTextPointArray$(6)="! MHz RefDB RefDeg" end if for i=0 to globalSteps 'save freq, mag and phase if isBand then 'Band cal if OSLBandApplyFull=0 then s$="" else s$=OSLBandA(i,0);aSpace$;OSLBandA(i,1);aSpace$;OSLBandB(i,0);_ aSpace$;OSLBandB(i,1);aSpace$; OSLBandC(i,0);aSpace$;OSLBandC(i,1);aSpace$ uTextPointArray$(i+7)=OSLBandRef(i,0);aSpace$;s$;OSLBandRef(i,1);aSpace$;OSLBandRef(i,2) else 'Base cal if OSLBaseApplyFull=0 then s$="" else s$=OSLBaseA(i,0);aSpace$;OSLBaseA(i,1);aSpace$;OSLBaseB(i,0);_ aSpace$;OSLBaseB(i,1);aSpace$; OSLBaseC(i,0);aSpace$;OSLBaseC(i,1);aSpace$ uTextPointArray$(i+7)=OSLBaseRef(i,0);aSpace$;s$;OSLBaseRef(i,1);aSpace$;OSLBaseRef(i,2) end if next i OSLCalContextAsTextArray=globalSteps+7 'Number of lines end function 'ver115-1g added OSLCalContextToFile sub OSLCalContextToFile fHndl$, isBand 'save OSL cal points to file 'isBand=1 means we do band cal; =0 means base cal '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=OSLCalContextAsTextArray(isBand) 'Assemble strings into uTextPointArray$ for i=1 to nLines print #fHndl$, uTextPointArray$(i) next i end sub 'ver115-1g added OSLGetCalContextFromFile function OSLGetCalContextFromFile(fHndl$, isBand) 'get points from file; return number of points 'isBand=1 means we do band cal; =0 means base cal '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$,100) 'Get data, 100 means number per line to be determined if isErr then OSLGetCalContextFromFile=-1 if isBand then OSLBandNumSteps=-1 else OSLBaseNumSteps=-1 'Indicates no data exit function end if 'Move the data from uWorkArray to gGraphVal if isBand then 'Band Cal if uWorkNumPerPoint=3 then OSLBandApplyFull=0 else OSLBandApplyFull=1 '3 data per line means not full OSL, just reference if uWorkNumPoints<1 then OSLBandApplyFull=0 'overrides the foregoing, since we have no points for i=1 to uWorkNumPoints OSLBandRef(i-1,0)=uWorkArray(i, 0) 'freq if OSLBandApplyFull=0 then 'we have only the reference if not full OSL OSLBandRef(i-1,1)=uWorkArray(i, 1) : OSLBandRef(i-1,2)=uWorkArray(i, 2) 'Mag and phase for ref else OSLBandA(i-1,0)=uWorkArray(i, 1) : OSLBandA(i-1,1)=uWorkArray(i, 2) 'Coeff A real and imag OSLBandB(i-1,0)=uWorkArray(i, 3) : OSLBandB(i-1,1)=uWorkArray(i, 4) 'Coeff B real and imag OSLBandC(i-1,0)=uWorkArray(i, 5) : OSLBandC(i-1,1)=uWorkArray(i, 6) 'Coeff C real and imag OSLBandRef(i-1,1)=uWorkArray(i, 7) : OSLBandRef(i-1,2)=uWorkArray(i, 8) 'Mag and phase for ref end if next i OSLGetCalContextFromFile=uWorkNumPoints 'Now derive the sweep parameters from the array and the title ver114-5h if uWorkNumPoints<1 then exit function OSLBandNumSteps=uWorkNumPoints-1 OSLBandStartFreq=OSLBandRef(0,0) : OSLBandEndFreq=OSLBandRef(OSLBandNumSteps,0) OSLBandTimeStamp$=uWorkTitle$(3) 'uArrayFromFile put date/time stamp here sweep$=uWorkTitle$(4) 'uArrayFromFile put sweep info here if instr(sweep$,"Linear")>0 then OSLBandLinear=1 else OSLBandLinear=0 'ver115-1b 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 calPathNum$=uGetParamText$(sweep$, "Path ", ";") 'Gets text after "Path " to semicolon or end if calPathNum$="" then OSLBandPath$="Path 1" else OSLBandPath$="Path ";calPathNum$ OSLBandS11JigType$=uGetParamText$(sweep$, "S11Jig=", ";") 'Gets text after S11Jig= to semicolon or end ver115-1g if OSLBandS11JigType$="" then OSLBandS11JigType$="Reflect" 'ver115-1g if OSLBandS11JigType$="Reflect" then 'ver115-9d 'If using bridge, get bridge R0 OSLBandS11BridgeR0=val(uGetParamText$(sweep$, "S11BridgeR0=", ";")) 'Gets text after S11BridgeR0= to semicolon or end if OSLBandS11BridgeR0<=0 then OSLBandS11BridgeR0=50 else 'If using S21 fixture for reflection measurements, get attachment and R0 OSLBandS21JigAttach$=uGetParamText$(sweep$, "S21Jig=", ";") 'Gets text after S21Jig= to semicolon or end if OSLBandS21JigAttach$="" then OSLBandS21JigAttach$="Series" OSLBandS21JigR0=val(uGetParamText$(sweep$, "S21JigR0=", ";")) 'Gets text after S21Jig= to semicolon or end if OSLBandS21JigR0<=0 then OSLBandS21JigR0=50 end if else 'Base if uWorkNumPerPoint=3 then OSLBaseApplyFull=0 else OSLBaseApplyFull=1 '3 data per line means not full OSL, just reference if uWorkNumPoints<1 then OSLBaseApplyFull=0 'overrides the foregoing, since we have no points for i=1 to uWorkNumPoints OSLBaseRef(i-1,0)=uWorkArray(i, 0) 'freq if OSLBaseApplyFull=0 then 'we have only the reference if not full OSL OSLBaseRef(i-1,1)=uWorkArray(i, 1) : OSLBaseRef(i-1,2)=uWorkArray(i, 2) 'Mag and phase for ref else OSLBaseA(i-1,0)=uWorkArray(i, 1) : OSLBaseA(i-1,1)=uWorkArray(i, 2) 'Coeff A real and imag OSLBaseB(i-1,0)=uWorkArray(i, 3) : OSLBaseB(i-1,1)=uWorkArray(i, 4) 'Coeff B real and imag OSLBaseC(i-1,0)=uWorkArray(i, 5) : OSLBaseC(i-1,1)=uWorkArray(i, 6) 'Coeff C real and imag OSLBaseRef(i-1,1)=uWorkArray(i, 7) : OSLBaseRef(i-1,2)=uWorkArray(i, 8) 'Mag and phase for ref end if next i OSLGetCalContextFromFile=uWorkNumPoints 'Now derive the sweep parameters from the array and the title ver114-5h if uWorkNumPoints<1 then exit function OSLBaseNumSteps=uWorkNumPoints-1 OSLBaseStartFreq=OSLBaseRef(0,0) : OSLBaseEndFreq=OSLBaseRef(OSLBaseNumSteps,0) OSLBaseTimeStamp$=uWorkTitle$(3) 'uArrayFromFile put date/time stamp here sweep$=uWorkTitle$(4) 'uArrayFromFile put sweep info here if instr(sweep$,"Linear")>0 then OSLBaseLinear=1 else OSLBaseLinear=0 'ver115-1b 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 calPathNum$=uGetParamText$(sweep$, "Path ", ";") 'Gets text after "Path " to semicolon or end OSLBaseS11JigType$=uGetParamText$(sweep$, "S11Jig=", ";") 'Gets text after S11Jig= to semicolon or end ver115-1g if OSLBaseS11JigType$="" then OSLBaseS11JigType$="Reflect" 'ver115-1g if calPathNum$="" then OSLBasePath$="Path 1" else OSLBasePath$="Path ";calPathNum$ if OSLBandS11JigType$="Reflect" then 'ver115-9d 'If using bridge, get bridge R0 OSLBaseS11BridgeR0=val(uGetParamText$(sweep$, "S11BridgeR0=", ";")) 'Gets text after S11BridgeR0= to semicolon or end if OSLBaseS11BridgeR0<=0 then OSLBaseS11BridgeR0=50 else 'If using S21 fixture for reflection measurements, get attachment and R0 OSLBaseS21JigAttach$=uGetParamText$(sweep$, "S21Jig=", ";") 'Gets text after S21Jig= to semicolon or end if OSLBaseS21JigAttach$="" then OSLBaseS21JigAttach$="Series" OSLBaseS21JigR0=val(uGetParamText$(sweep$, "S21JigR0=", ";")) 'Gets text after S21Jig= to semicolon or end if OSLBaseS21JigR0<=0 then OSLBaseS21JigR0=50 end if end if end function 'ver115-1d added GraphDataContextAsTextArray() function GraphDataContextAsTextArray() 'Put graph 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 call gGetPointVal i+1, f, y1, y2 'point num is one more than step num. uTextPointArray$(i+7)=f;aSpace$;y2;aSpace$;y1 'Save freq, Y2, Y1 next i GraphDataContextAsTextArray=maxStep+7 end function 'ver115-1d added GraphDataContext$() function GraphDataContext$() 'Return data points as string, with title in first 3 lines 'We do not include !StartContext or !EndContext lines nLines=GraphDataContextAsTextArray() 'Assemble strings into uTextPointArray$ GraphDataContext$=uTextArrayToString$(1,nLines) 'Assemble array of strings into one string end function 'ver115-1d added GraphDataContextToFile() sub GraphDataContextToFile 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=GraphDataContextAsTextArray() 'Assemble strings into uTextPointArray$ for i=1 to nLines print #fHndl$, uTextPointArray$(i) next i end sub 'ver115-1d added RestoreGraphDataContext$ function RestoreGraphDataContext(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 RestoreGraphDataContext=-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 call gSetNumDynamicSteps uWorkNumPoints-1 call gClearPoints for i=1 to uWorkNumPoints overflow=gAddPoints(uWorkArray(i, 0), uWorkArray(i, 2), uWorkArray(i, 1)) 'Freq, Phase, Mag 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. 'Note we do not call gSetNumDynamicSteps; that must be set elsewhere. 'Caller must also separately conform datatable() with the graph data RestoreGraphDataContext=uWorkNumPoints prevDataChanged=1 end function 'ver115-1d added GetGraphDataContextFromFile function GetGraphDataContextFromFile(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 GetGraphDataContextFromFile=-1 : exit function 'Move the data from uWorkArray to gGraphVal if uWorkNumPoints>gMaxNumPoints() then call ResizeArrays uWorkNumPoints 'Make sure we have enough room call gClearPoints for i=1 to uWorkNumPoints overflow=gAddPoints(uWorkArray(i, 0), uWorkArray(i, 2), uWorkArray(i, 1)) 'Freq, Phase, Mag 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. 'Note we do not call gSetNumDynamicSteps; that must be set elsewhere. 'Caller must also separately conform datatable() with the graph data GetGraphDataContextFromFile=uWorkNumPoints prevDataChanged=1 end function 'ver115-1d added DataTableContextAsTextArray() function DataTableContextAsTextArray() 'Put data points into uTextPointArray$, with header info 'We save the full datatable() even if data for some steps has not been collected yet. '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$=" " for i=0 to globalSteps y1=datatable(i,3) y2=datatable(i,2) uTextPointArray$(i+7)=datatable(i,1);aSpace$;y2;aSpace$;y1 'Save freq, Y2, Y1 next i DataTableContextAsTextArray=maxStep+7 end function 'ver115-1d added DataTableContext$() function DataTableContext$() 'Return data points as string, with title in first 3 lines 'We do not include !StartContext or !EndContext lines nLines=DataTableContextAsTextArray() 'Assemble strings into uTextPointArray$ DataTableContext$=uTextArrayToString$(1,nLines) 'Assemble array of strings into one string end function 'ver115-1d added DataTableContextToFile() sub DataTableContextToFile fHndl$ 'save data points to file 'We save the full datatable() even if data for some steps has not been collected yet. '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=DataTableContextAsTextArray() 'Assemble strings into uTextPointArray$ for i=1 to nLines print #fHndl$, uTextPointArray$(i) next i end sub ''ver115-1d added RestoreDataTableContext$ function RestoreDataTableContext(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 RestoreDataTableContext=-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. 'Note we do not call gSetNumDynamicSteps; that must be set elsewhere. 'Caller must also separately conform datatable() with the graph data RestoreDataTableContext=uWorkNumPoints prevDataChanged=1 end function 'ver115-1d added GetDataTableContextFromFile() function GetDataTableContextFromFile(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 GetDataTableContextFromFile=-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. 'Also note that we do not change anything in the graph module. Neither its data nor number of steps will 'necessarily match ours. It must be dealt with separately. 'We also don't set steps or globalSteps to match our number of points GetDataTableContextFromFile=uWorkNumPoints prevDataChanged=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$;doLRRelativeAmounts$;s$;doLRAbsolute 'ver115-3f 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$ 'ver115-1b 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 'modver115-3f isErr=uExtractNumericItems(1,tLine$, nonTextDelims$,v1, v2, v3) doPeaksBounded=v1 doLRRelativeTo$=uExtractTextItem$(tLine$," ") isErr=uExtractNumericItems(2,tLine$, nonTextDelims$,v1, v2, v3) doLRRelativeAmount=v1 doLRAbsolute=v2 end if case "FILTANALYSIS" if isValidation=0 then 'modver115-3f isErr=uExtractNumericItems(1,tLine$, nonTextDelims$,v1, v2, v3) doFilterAnalysis=v1 x1DBDown=v2 x2DBDown=v3 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 'ver115-1b '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 'ver115-8c [LoadBasicContextsFromFile] 'Load contexts from file restoreFileHndl$; set restoreErr$ to error message or "" 'User must call RememberState before coming here and then DetectFullChanges after returning, to deal with changes. 'The file must already be open. We do not close it. 'restoreFileHndl$ contains LB file handle, e.g. "#prefs" 'restoreLastLineNum will be set to the last line we read, in case the caller wants to back up one line. '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. 'There may already have been other data read from the file. We start wherever Line Input reads. 'The entries of contextTypes will be set to 1 if the corresponding context was read: 'See Select statement for contextTypes values for i=0 to 30 : contextTypes(i)=0 : next i 'Clear contextTypes we actually only need four restoreErr$="" 'assume no error restoreLastLineNum=0 : foundData=0 while EOF(#restoreFileHndl$)=0 'Find next "StartContext" or "!". The exclamation point means a data section has been 'encountered that is not marked with "StartContext", which is OK but is the end of preferences contextName$="" while EOF(#restoreFileHndl$)=0 Line Input #restoreFileHndl$, tLine$ restoreLastLineNum=restoreLastLineNum+1 tLine$=Upper$(Trim$(tLine$)) if Left$(tLine$,1)="!" then foundData=1: exit while 'Exclamation means data starts 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 if foundData then exit while select contextName$ case "HARDWARE" errMsg$="Can't restore Hardware Context" case "GRID", "TRACE", "SWEEP", "MARKER" 'These are read into a string and then processed ver115-8c restoreContext$="" 'Assemble context into string, without StartContext and EndContext lines joint$="" while EOF(#restoreFileHndl$)=0 Line Input #restoreFileHndl$, tLine$ restoreLastLineNum=restoreLastLineNum+1 if Upper$(Trim$(tLine$))="ENDCONTEXT" then exit while restoreContext$=restoreContext$;joint$;tLine$ joint$=chr$(13) wend 'Process with proper routine select contextName$ case "GRID" contextTypes(constGrid)=1 errMsg$=RestoreGridContext$(restoreContext$,1,0) 'Actual restoration case "TRACE" errMsg$=RestoreTraceContext$(restoreContext$,1,0) contextTypes(constTrace)=1 case "SWEEP" contextTypes(constSweep)=1 restoreIsValidation=0 gosub [RestoreSweepContext] 'Actual restoration errMsg$=restoreErr$ case "MARKER" contextTypes(constMarker)=1 restoreIsValidation=0 gosub [RestoreMarkerContext] 'Actual restoration errMsg$=restoreErr$ end select if errMsg$<>"" then restoreErr$=errMsg$ : exit while case "DATATABLE" exit while 'Datatable context can mark the end, but is not error case else restoreErr$="UNKNOWN CONTEXT: ";contextName$ : exit while 'Unknown context name; may not actually be error end select wend 'Reach here when entire file has been processed up to an unknown context or a "!", or error occurred return '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) contextCount=0 if contextTypes(constHardware)=1 then contextCount=contextCount+1 : print #fHndl$, "StartContext Hardware";newLine$;configHardwareContext$();newLine$;"EndContext" if contextTypes(constGrid)=1 then contextCount=contextCount+1 : print #fHndl$, "StartContext Grid";newLine$;GridContext$();newLine$;"EndContext" 'ver115-2a if contextTypes(constTrace)=1 then contextCount=contextCount+1 : print #fHndl$, "StartContext Trace";newLine$;TraceContext$();newLine$;"EndContext" if contextTypes(constSweep)=1 then contextCount=contextCount+1 : print #fHndl$, "StartContext Sweep";newLine$;SweepContext$();newLine$;"EndContext" if contextTypes(constMarker)=1 then contextCount=contextCount+1 : print #fHndl$, "StartContext Marker";newLine$;mMarkerContext$();newLine$;"EndContext" if contextTypes(constBand)=1 then contextCount=contextCount+1 print #fHndl$, "!StartContext BandLineCal" call BandLineCalContextToFile fHndl$ print #fHndl$, "!EndContext" end if if contextTypes(constBase)=1 then contextCount=contextCount+1 print #fHndl$, "!StartContext BaseLineCal" call BaseLineCalContextToFile fHndl$ print #fHndl$, "!EndContext" end if if contextTypes(constGraphData)=1 then contextCount=contextCount+1 print #fHndl$, "!StartContext GraphData" 'ver115-1d call GraphDataContextToFile fHndl$ 'ver115-1d print #fHndl$, "!EndContext" end if if contextTypes(constDatatable)=1 then 'ver115-1d added type 8 contextCount=contextCount+1 'Print the StartContext line only if preceded by some other context if contextCount>1 then print #fHndl$, "!StartContext DataTable" call touchWriteParameters fHndl$ 'Write data to file if contextCount>1 then print #fHndl$, "!EndContext" end if close #fHndl$ SaveContextFile$="" end function 'ver114-3f added menuSavePreferenceFile sub menuSavePreferenceFile 'Save current preferences file to user-specified location. filter$="Text files" + chr$(0) + "*.txt" + chr$(0) + "All files" + chr$(0) + "*.*" 'ver115-6b defaultExt$="txt" initialDir$=DefaultDir$+"\MSA_Info\MSA_Prefs\" initialFile$="Prefs.txt" fileName$=uSaveFileDialog$(filter$, defaultExt$, initialDir$, initialFile$, "Save Preference File") if fileName$<>"" then call SavePreferenceFile fileName$ 'blank means cancelled 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