Copyright (c) (2015) Fluke Corporation                      MET/CAL Procedure
=============================================================================
INSTRUMENT:            Sub Initialize /PGEN
INSTRUMENT:            Sub Reset /PGEN
INSTRUMENT:            Sub Output Off /PGEN
INSTRUMENT:            Sub Apply /PGEN
DATE:                  2016-08-11 13:39:42
AUTHOR:                Fluke Calibration
REVISION:              $Revision: 24551 $
ADJUSTMENT THRESHOLD:  70%
NUMBER OF TESTS:       5
NUMBER OF LINES:       469
CONFIGURATION:         Pulse Generator
=============================================================================
#
#  Procedure Author:
#        DAC, DFM, CAD
#
#  Compatibility:
#        MET/CAL 7.2 or later
#
#  Subprocedures:
#        Sub Send Command /PGEN
#
#  Required Files:
#        user_config_instr.ini
#
#  This procedure is intended for use with MET/CAL calibration software;
#  the terms and conditions set forth in your MET/CAL license apply to this
#  procedure.
#
#  Due to Fluke's policy of continuously updating our products, this procedure
#  may contain minor differences in methods used and/or specifications to
#  those found in the manual or other documentation. While every effort has
#  been made to ensure that this procedure is accurate, Fluke cannot be held
#  responsible for the consequences of error or omissions found within this
#  procedure.
#
#  The copyright in this procedure is owned by Fluke Corporation.
#
#  Parameters        Values
#  ----------------  -------------------------------------------------------
#  @PGEN_Imp         Min | Max | Infinity | <NR3>[][<prefix>]Ohm
#
#  @PGEN_Polarity    Normal | Inverted
#
#  @PGEN_Freq        <NR3>[][<prefix>]Hz
#
#  @PGEN_Period      <NR3>[][<prefix>]s
#
#  @PGEN_PulseWidth  <NR3>[][<prefix>]s
#
#  @PGEN_HighLevel   <NR3>[][<prefix>]V
#
#  @PGEN_LowLevel    <NR3>[][<prefix>]V             (defaults to 0 if omitted)
#
#  @PGEN_Ampl        <NR3>[][<prefix>]V   | <NR3>[][<prefix>]Vp |
#                    <NR3>[][<prefix>]Vpp | <NR3>[]dBm
#
#  @PGEN_Offs        <NR3>[][<prefix>]V             (defaults to 0 if omitted)
#
#  @PGEN_RiseTime    <NR3>[][<prefix>]s
#
#  @PGEN_FallTime    <NR3>[][<prefix>]s
#
#  @PGEN_TrigType    FreeRun | Line | Ext       (uses PGEN default if omitted)
#
#  Example Usage:
#
#      CALL         Sub Initialize /PGEN
#      CALL         Sub Reset /PGEN
#
#      MATH         @PGEN_Freq       = "144 kHz"
#      MATH         @PGEN_PulseWidth = "200 ns"
#      MATH         @PGEN_HighLevel  = "5 V"
#      MATH         @PGEN_LowLevel   = "0 V"
#
#      CALL         Sub Apply /PGEN
#
#  NOTE: This flexible driver will attempt to sequentially program Pulse
#        Width, then Frequency or Period.  If the requested values conflict
#        with the PGEN's current state, the PGEN may generate an error.
#
#        To prevent this conflict, the procedure writer may set an interim
#        state to conditions that avoid conflict.
#
#        Use of Amplitude + Offset assumes that the configured pulse generator
#        (PGEN) ouputs a zero-centered waveform.  Use of High + Low levels
#        assumes that the PGEN will produce the levels as defined.
#
 STEP    FSC    RANGE NOMINAL        TOLERANCE     MOD1        MOD2  3  4 CON

  1.001  JMPL         INITIALIZE                   PSUBI("Initialize")
  1.002  JMPL         RESET                        PSUBI("Reset")
  1.003  JMPL         OUTPUT_OFF                   PSUBI("Output Off")
  1.004  JMPL         APPLY                        PSUBI("Apply")
  1.005  DISP         Subprocedure not found!
  1.006  END

  1.007  EVAL   Increment test number


# =====  Sub Initialize /PGEN  ================================

  2.001  LABEL        INITIALIZE

# Get and store:
#   device name
#   programming section name for looking up programming codes in .ini file.
#   FSC used for IEEE-488 I/O
#   Connection terminal names
  2.002  MATH         @PGEN_DevName     = INSTR("PGEN")
  2.003  MATH         @PGEN_ProgSecName = RINFE(@PGEN_DevName, "ProgSecName")
  2.004  MATH         @PGEN_FSC         = RINFE(@PGEN_ProgSecName, "FSC")
  2.005  MATH         @PGEN_Output      = RINFE(@PGEN_ProgSecName, "Output")
  2.006  MATH         @PGEN_TrigOut     = RINF(@PGEN_ProgSecName, "TrigOut")

# Initialize parameters to the empty string (unset).
  2.007  MATH         @PGEN_Imp        = ""
  2.008  MATH         @PGEN_Polarity   = ""
  2.009  MATH         @PGEN_Freq       = ""
  2.010  MATH         @PGEN_Period     = ""
  2.011  MATH         @PGEN_PulseWidth = ""
  2.012  MATH         @PGEN_HighLevel  = ""
  2.013  MATH         @PGEN_LowLevel   = ""
  2.014  MATH         @PGEN_Ampl       = ""
  2.015  MATH         @PGEN_Offs       = ""
  2.016  MATH         @PGEN_RiseTime   = ""
  2.017  MATH         @PGEN_FallTime   = ""
  2.018  MATH         @PGEN_TrigType   = ""

# Get programming string for RESET FSC.
  2.019  MATH         ResetCmd = RINF(@PGEN_ProgSecName, "ResetFSC")

# If RESET_FSC is defined, establish the RESET FSC.
  2.020  IF           NOT(EMPTY(ResetCmd))

  2.021  IF           ZCMPI(ResetCmd, "[SDC]")
  2.022  RESET        [@PGEN][SDC]
  2.023  ELSE
  2.024  RESET        [@PGEN][V ResetCmd]
  2.025  ENDIF

  2.026  ENDIF

  2.027  END

  2.028  EVAL   Increment test number


# =====  Sub Reset /PGEN  =====================================

  3.001  LABEL        RESET
  3.002  MATH         @PGEN_Cmd = RINFE(@PGEN_ProgSecName, "Reset")
  3.003  CALL         Sub Send Command /PGEN
  3.004  END

  3.005  EVAL   Increment test number


# =====  Sub Output Off /PGEN  ================================

  4.001  LABEL        OUTPUT_OFF
  4.002  MATH         @PGEN_Cmd = RINF(@PGEN_ProgSecName, "OutputOff")

# If "Output_Off" is defined, send the command.
  4.003  IF           NOT(EMPTY(@PGEN_Cmd))
  4.004  CALL         Sub Send Command /PGEN
  4.005  ENDIF

  4.006  END

  4.007  EVAL   Increment test number


# =====  Sub Apply /PGEN  =====================================

  5.001  LABEL        APPLY
# See if pulse must be selected.
  5.002  MATH         @PGEN_Cmd = RINF(@PGEN_ProgSecName, "Pulse")

# If not, see if negative or positive pulse must be selected.
  5.003  IF           EMPTY(@PGEN_Cmd)

  5.004  IF           ZCMPI(@PGEN_Polarity, "Inverted")
  5.005  MATH         @PGEN_Cmd = RINFE(@PGEN_ProgSecName, "NegPulse")
  5.006  ELSE
  5.007  MATH         @PGEN_Cmd = RINFE(@PGEN_ProgSecName, "PosPulse")
  5.008  ENDIF

  5.009  ENDIF        ; EMPTY(@PGEN_Cmd)

  5.010  IF           NOT(EMPTY(@PGEN_Cmd))
  5.011  CALL         Sub Send Command /PGEN
  5.012  ENDIF

# -----  Output Impedance  ------------------------

  5.013  IF           NOT(EMPTY(@PGEN_Imp))

  5.014  IF           ZCMPI(@PGEN_Imp, "Min")
  5.015  MATH         ImpType = "ImpMin"
  5.016  ELSEIF       ZCMPI(@PGEN_Imp, "Max")
  5.017  MATH         ImpType = "ImpMax"
  5.018  ELSEIF       ZCMPI(@PGEN_Imp, "Infinity")
  5.019  MATH         ImpType = "ImpInfinity"
  5.020  ELSE         ; Get desired output impedance in base units.
  5.021  MATH         Imp = BASE(@PGEN_Imp)
# Check for fixed output impedance.
  5.022  MATH         FixedImp = RINF(@PGEN_ProgSecName, "ImpFixed")

  5.023  IF           NOT(EMPTY(FixedImp))

# Check to make sure the fixed impedance is the desired impedance.
  5.024  IF           BASE(FixedImp) != Imp
  5.025  DISP         [V @PGEN_DevName] has a [V FixedImp] fixed output
  5.025  DISP         impedance.  Requested output impedance [V Imp].
  5.026  END
  5.027  ENDIF

  5.028  MATH         ImpType = "ImpFixed"
  5.029  ELSE
  5.030  MATH         ImpType = "Imp"
  5.031  ENDIF        ; NOT(EMPTY(FixedImp))

  5.032  ENDIF        ; ZCMPI(@PGEN_Imp, "Min")

# If not fixed impedance, get the command and send it to the instrument.
  5.033  IF           NOT(ZCMPI(ImpType, "ImpFixed"))
  5.034  MATH         @PGEN_Cmd = RINFE(@PGEN_ProgSecName, ImpType)

  5.035  IF           ZCMPI(ImpType, "Imp")
  5.036  MATH         @PGEN_Cmd = REPL("<val>", Imp, @PGEN_Cmd)
  5.037  ENDIF

  5.038  CALL         Sub Send Command /PGEN
  5.039  ENDIF        ; Not fixed output impedance

  5.040  ENDIF        ; Output Impedance

# -----  Output Polarity  -------------------------

  5.041  IF           NOT(EMPTY(@PGEN_Polarity))

  5.042  IF           ZCMPI(@PGEN_Polarity, "Inverted")
  5.043  MATH         Polarity = "PolarityInverted"
  5.044  ELSE
  5.045  MATH         Polarity = "PolarityNormal"
  5.046  ENDIF

  5.047  MATH         @PGEN_Cmd = RINFE(@PGEN_ProgSecName, Polarity)
  5.048  CALL         Sub Send Command /PGEN
  5.049  ENDIF        ; Output Polarity

# -----  High/Low Levels  -------------------------

  5.050  IF           NOT(EMPTY(@PGEN_HighLevel))

  5.051  MATH         High = BASE(@PGEN_HighLevel)
  5.052  MATH         HighCmd = RINFE(@PGEN_ProgSecName, "PulseTopline")
  5.053  MATH         @PGEN_Cmd = REPL("<val>", High, HighCmd)
  5.054  CALL         Sub Send Command /PGEN

# If LowLevel is not defined, default to 0.
  5.055  IF           EMPTY(@PGEN_LowLevel)
  5.056  MATH         Low = 0
  5.057  ELSE
  5.058  MATH         Low = BASE(@PGEN_LowLevel)
  5.059  ENDIF

  5.060  MATH         LowCmd = RINFE(@PGEN_ProgSecName, "PulseBaseline")
  5.061  MATH         @PGEN_Cmd = REPL("<val>", Low, LowCmd)
  5.062  CALL         Sub Send Command /PGEN

# -----  Amplitude  -------------------------------

  5.063  ELSEIF       NOT(EMPTY(@PGEN_Ampl))
  5.064  MATH         Ampl = BASE(@PGEN_Ampl); Units = UNIT(@PGEN_Ampl)

  5.065  IF           ZCMPI(Units, "dBm")

# Use the discrete command for positive or negative dBm, if one exists.
  5.066  IF           Ampl < 0
  5.067  MATH         AmplCmd = RINF(@PGEN_ProgSecName,  "Ampl_dBmNeg")
  5.068  MATH         Ampl = ABS(Ampl)
  5.069  ELSE
  5.070  MATH         AmplCmd = RINF(@PGEN_ProgSecName,  "Ampl_dBmPos")
  5.071  ENDIF        ; Discrete dBm.

# Otherwise use the general command for amplitude in dBm.
  5.072  IF           EMPTY(AmplCmd)
  5.073  MATH         AmplCmd = RINFE(@PGEN_ProgSecName, "Ampl_dBm")
  5.074  ENDIF        ; Units = dBm

  5.075  ELSEIF       ZCMPI(Units, "V")
  5.076  MATH         AmplCmd = RINFE(@PGEN_ProgSecName, "Ampl_Vrms")

  5.077  ELSEIF       ZCMPI(Units, "Vp")
  5.078  MATH         AmplCmd = RINF(@PGEN_ProgSecName,  "Ampl_Vp")

# If there is no Vp command, check for Vpp command and convert Ampl to Vpp.
  5.079  IF           EMPTY(AmplCmd)
  5.080  MATH         AmplCmd = RINFE(@PGEN_ProgSecName, "Ampl_Vpp")
  5.081  MATH         Ampl = Ampl * 2
  5.082  ENDIF

  5.083  ELSEIF       ZCMPI(Units, "Vpp")
  5.084  MATH         AmplCmd = RINF(@PGEN_ProgSecName, "Ampl_Vpp")

# If there is no Vpp command, check for Vp command and convert Ampl to Vp.
  5.085  IF           EMPTY(AmplCmd)
  5.086  MATH         AmplCmd = RINFE(@PGEN_ProgSecName, "Ampl_Vp")
  5.087  MATH         Ampl = Ampl / 2
  5.088  ENDIF

  5.089  ENDIF        ; Unit check.

  5.090  MATH         @PGEN_Cmd = REPL("<val>", Ampl, AmplCmd)
  5.091  CALL         Sub Send Command /PGEN

# -----  Offset  ----------------------------------

# If Offset is not defined, default to 0.
  5.092  IF           EMPTY(@PGEN_Offs)
  5.093  MATH         Offs = 0
  5.094  ELSE
  5.095  MATH         Offs = BASE(@PGEN_Offs)
  5.096  ENDIF

  5.097  MATH         OffsCmd = RINFE(@PGEN_ProgSecName, "DC_Offset")
  5.098  MATH         @PGEN_Cmd = REPL("<val>", Offs, OffsCmd)
  5.099  CALL         Sub Send Command /PGEN

  5.100  ENDIF        ; Amplitude/Offset or High/Low Voltage Levels.

# -----  Trigger Type  ----------------------------

  5.101  IF           NOT(EMPTY(@PGEN_TrigType))

  5.102  IF           ZCMPI(@PGEN_TrigType, "FreeRun")
  5.103  MATH         TrigType = "FreeRun"
  5.104  ELSEIF       ZCMPI(@PGEN_TrigType, "Line")
  5.105  MATH         TrigType = "TrigLine"
  5.106  ELSE
  5.107  MATH         TrigType = "TrigExt"
  5.108  ENDIF

  5.109  MATH         @PGEN_Cmd = RINFE(@PGEN_ProgSecName, TrigType)
  5.110  CALL         Sub Send Command /PGEN

  5.111  ENDIF        ; NOT(EMPTY(@PGEN_TrigType))

# -----  Period  ----------------------------------

  5.112  IF           NOT(EMPTY(@PGEN_Period))
  5.113  MATH         Value = BASE(@PGEN_Period)
# If there is a pulse period command, use it.
  5.114  MATH         Cmd = RINF(@PGEN_ProgSecName, "PulsePeriod")

  5.115  IF           EMPTY(Cmd)
# If there is a period command, use it.
  5.116  MATH         Cmd = RINF(@PGEN_ProgSecName, "Period")

  5.117  IF           EMPTY(Cmd)
# If there is a frequency command, use it.
  5.118  MATH         Cmd = RINFE(@PGEN_ProgSecName, "Freq")
  5.119  MATH         Value = 1 / Value
  5.120  ENDIF

  5.121  ENDIF

# -----  Frequency  -------------------------------

  5.122  ELSEIF       NOT(EMPTY(@PGEN_Freq))
  5.123  MATH         Value = BASE(@PGEN_Freq)
# If there is a frequency command, use it.
  5.124  MATH         Cmd = RINF(@PGEN_ProgSecName, "Freq")

  5.125  IF           EMPTY(Cmd)
  5.126  MATH         Value = 1 / Value
# If there is a pulse period command, use it.
  5.127  MATH         Cmd = RINF(@PGEN_ProgSecName, "PulsePeriod")

  5.128  IF           EMPTY(Cmd)
# If there is a period command, use it.
  5.129  MATH         Cmd = RINFE(@PGEN_ProgSecName, "Period")
  5.130  ENDIF

  5.131  ENDIF

  5.132  ENDIF

# Strip leading zeros from exponent to prevent PGEN errors on certain models.
  5.133  WHILE        FINDI(Value, "E-0", 0) || FINDI(Value, "E+0", 0)

  5.134  IF           FINDI(Value, "E-0", 0)
  5.135  MATH         Value = REPL("-0", "-", Value)
  5.136  ELSEIF       FINDI(Value, "E+0", 0)
  5.137  MATH         Value = REPL("+0", "+", Value)
  5.138  ENDIF

  5.139  ENDW

  5.140  MATH         @PGEN_Cmd = REPL("<val>", Value, Cmd)
  5.141  CALL         Sub Send Command /PGEN

# -----  Pulse Width  -----------------------------

  5.142  IF           NOT(EMPTY(@PGEN_PulseWidth))
  5.143  MATH         PulseWidthCmd = RINFE(@PGEN_ProgSecName, "PulseWidth")
  5.144  MATH         Width = BASE(@PGEN_PulseWidth)

# Strip leading zeros from exponent to prevent PGEN errors on certain models.
  5.145  WHILE        FINDI(Width, "E-0", 0) || FINDI(Width, "E+0", 0)

  5.146  IF           FINDI(Width, "E-0", 0)
  5.147  MATH         Width = REPL("-0", "-", Width)
  5.148  ELSEIF       FINDI(Width, "E+0", 0)
  5.149  MATH         Width = REPL("+0", "+", Width)
  5.150  ENDIF

  5.151  ENDW

  5.152  MATH         @PGEN_Cmd = REPL("<val>", Width, PulseWidthCmd)
  5.153  CALL         Sub Send Command /PGEN
  5.154  ENDIF

# -----  Rise Time  ----------------------------------

  5.155  IF           NOT(EMPTY(@PGEN_RiseTime))
  5.156  MATH         Value = BASE(@PGEN_RiseTime)
# If there is a pulse rise time command, use it.
  5.157  MATH         Cmd = RINF(@PGEN_ProgSecName, "PulseRiseTime")

  5.158  IF           EMPTY(Cmd)
# If there is a rise time command, use it.
  5.159  MATH         Cmd = RINFE(@PGEN_ProgSecName, "RiseTime")
  5.160  ENDIF

  5.161  MATH         @PGEN_Cmd = REPL("<val>", Value, Cmd)
  5.162  CALL         Sub Send Command /PGEN
  5.163  ENDIF

# -----  Fall Time  ----------------------------------

  5.164  IF           NOT(EMPTY(@PGEN_FallTime))
  5.165  MATH         Value = BASE(@PGEN_FallTime)
# If there is a pulse rise time command, use it.
  5.166  MATH         Cmd = RINF(@PGEN_ProgSecName, "PulseFallTime")

  5.167  IF           EMPTY(Cmd)
# If there is a rise time command, use it.
  5.168  MATH         Cmd = RINFE(@PGEN_ProgSecName, "FallTime")
  5.169  ENDIF

  5.170  MATH         @PGEN_Cmd = REPL("<val>", Value, Cmd)
  5.171  CALL         Sub Send Command /PGEN
  5.172  ENDIF

# -----  Output On  -------------------------------

# If "OutputOn" is defined, send the command.
  5.173  MATH         @PGEN_Cmd = RINF(@PGEN_ProgSecName, "OutputOn")

  5.174  IF           NOT(EMPTY(@PGEN_Cmd))
  5.175  CALL         Sub Send Command /PGEN
  5.176  ENDIF

  5.177  END
