'****************************  TESTHV3  ***********************************
' NAME:         TESTHV3.BAS
' PURPOSE:      AUTOMATED TEST SOFTWARE FOR HIGH-VOLTAGE
'               VOLTAGE-INPUT PRODUCT TESTING
' COMPILER:     Quick Basic 4.5
' AUTHOR:       John Lehman
' DATE:         06/18/99

'*************************  REVISION RECORD *******************************
'DATE       REV     APPR    DESCRIPTION
'----       ---     ----    -----------
'06/18/99   1.00    JL      Initial Release
' ...
' ...                       See "Revs.txt" file for program update comments within this time interval.
' ...
'2014/10/10 B.01    PWR     Code cleanup and updates for datasheet and work order status file
'                           generation, etc., and use of the updated library (NLIBATE3) with
'                           work order number restrictions for the datasheet naming convention.
'                           Operator-entry pauses were removed in CHECKFILECREATE, etc. The
'                           ENABLE and HVRELAY subs were changed to properly update the DIO word
'                           and to check for invalid parameters. Added common variable DEBUGFLAG%
'                           to control debug messages and pauses in various routines. Updated
'                           Individual Test menu to remove non-HV tests and updated the INDIVID
'                           sub to account for the menu-number changes and to add form-feed
'                           as one of the choices. Added REPORT sub to FUNCTEST to display the
'                           test results, and updated the sub to use the global variable TTYPE%
'                           to leave out the accuracy results display in the functional test.
'                           Added INSTRERROR$ function and INSTRERRORS sub (replacing DASERROR$
'                           and DASERRORS) to read the error status from either the Agilent
'                           33120A or 34970A instruments. Added FINISHSUB declaration and call from
'                           the F10 trap. Added OUTSWITCH test to FUNCTEST (for SCM5B modules only).
'
'10-21-16      MF           Added limits for SETDAC3

'2-7-20        MF           ADDED DELAY AT HS1 FUNCTION

CONST PROGNAME$ = "TESTHV3.EXE"                             'Executable file name of the program.
CONST VERSION$ = "B.01 2014.10.10 PWR"                      'Version (Revision Date) and initials of engr.
CONST SOURCEFILES$ = "TESTHV3.BAS TESTHV4.BAS NLIBATE3.BAS" 'Source file names

'******** Declare some useful constants *******
CONST MAXSTATUSINDEX = 17   'Maximum index of the Status array

'***************** DEVICE COMMUNICATIONS ROUTINES *************************
'Kepco DPS 125-0.5M control routines via RS-232C
DECLARE SUB INIT488 (DEVADDR%)
DECLARE SUB INITPS (DPSADDR%, OVERI!, OVERV!)       'Initializes supply
DECLARE SUB SETDPS (DPSADDR%, VSUPPLY!)             'Sets Kepco DPS power supply
DECLARE FUNCTION GETPSID% ()
DECLARE FUNCTION POWERIO$ (DPSADDR%, CMD$)          'Actual I/O commands
DECLARE FUNCTION SETSCM5BPWR! (VSUPPLY!)            'Sets SCM5B supply voltage

'HP33120A (function generator) control routines via GPIB
DECLARE SUB CONFDUTIN (ONOFF%)  'Configure test head for inverted or non-inverted DUT input power supply conn.
DECLARE SUB IO488 (DDATA$, DEVADDR%, SEL%)

'HP34970A (data acquisition/switch unit) control routines via GPIB
DECLARE SUB DVMCONF (CH%, FUNC$, RANGETXT$, RANGENUM!, RESOLTXT$, RESOLNUM!) 'Configure DVM
DECLARE SUB DVMSENS (CH%, FUNC1$, FUNC2$, SETTXT$, SETNUM!) 'Configure DVM
DECLARE SUB HVRELAY (RELAY%, ONOFF%)
DECLARE SUB SETDAC3 (DACNUM%, VOLTAGE!)         'Set 34907 DACs
DECLARE SUB SETSWITCH (CH%, STATE%)             'Set switch on 34903A 20-ch actuator
DECLARE FUNCTION GETREADING! ()                 '** Send trigger & read DVM
DECLARE FUNCTION READDVM! (CH%, FUNC$, RANGETXT$, RANGENUM!, RESOLTXT$, RESOLNUM!)

'Fluke 760A (meter calibrator) routines
DECLARE SUB FLUKE760APANEL (VALUE!, UNITS%)        'Display front panel settings

'********************* TOP LEVEL TEST ROUTINES ****************************
DECLARE SUB COMPTEST (STATUS$(), ITERATION%, CAL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, TTYPE%, TSPEC$(), SERNO$()) 'Complete set of tests

'DECLARE SUB FUNCTEST (CAL%, STATUS$(), NUMDUT%) 'Routines for functional test
DECLARE SUB FUNCTEST (STATUS$(), CAL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, TTYPE%, TSPEC$(), SERNO$()) 'Routines for functional test

DECLARE SUB INDIVID (SEL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), STATUS$(), NUMDUT%) 'Performs the tests individually

'********* USER INTERFACE, REPORTING, AND LOGGING ROUTINES ****************
DECLARE FUNCTION MENU1% ()                          'Gets the Test Group selection
DECLARE FUNCTION MENU2% ()                          'Gets the individual test #
DECLARE FUNCTION MENU3% ()                          'Gets the module family
DECLARE FUNCTION SNMENU$ (SLOTNO%, SERNO$, SNFLAG%) 'Selection menu to change the SN information of unit in slots 2 or higher
DECLARE SUB CHANGEDN (SN$)                          'Allow user to change dash number
DECLARE SUB FOOTER (STATUS$(), L%)                  'Sends footer to printer if all tests passed
DECLARE SUB GETNEXTSN (TIME2!, SERNO$(), NUMDUT%)   'Allows user the change the SN info for a new group of modules
DECLARE SUB GETSN (SN$)                             'Gets DUT serial number from user
DECLARE SUB HEADERA (SN$)                           'Prints test sheet header
DECLARE SUB HEADERB (TESTTITLE$, L%)                'Prints test screen header
DECLARE SUB INPUTSN (SN$, SERNO$(), NUMDUT%)        'Gathers the SN information for the unit in channel 1
DECLARE SUB LOGIT (STATUS$(), SN$, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), L%)  'Logs test results to disk
DECLARE SUB MODOUTLINE ()                           'Draw module bottom view.
DECLARE SUB NOTES ()                                'Notes on ATE operation
DECLARE SUB REPORT (STATUS$(), SN$, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), TSPEC$(), NUMDUT%, TTYPE%)       'Prints test data on screen
DECLARE SUB SORTDB (ENDFLAG%)                       'Sort model database

'*********************** DATABASE OPERATIONS ******************************
DECLARE SUB GETADD ()               'Get system component addresses
DECLARE SUB GETSPECS (NUMDUT%)      'Gets module type and specifications
DECLARE SUB TSPECS (TSPEC$())       'Creates a string array of test specifications

'**************** TEST DECISIONING / CALCULATION ROUTINES ******************
DECLARE FUNCTION BESTFIT! (SLOPE!, OFFSET1!, INSIM!(), NUMPTS%, ERROROUT!(), L%)
DECLARE FUNCTION FAILS% (STATUS$(), NUMDUT%)   'Tests for failed tests
DECLARE FUNCTION REPEAT$ (MN$, ELAP2!, TIME2!) 'Ask if you would like to repeat test
DECLARE FUNCTION MEASRES! (OHM!, RESNUM%, L%)  'Measure specified sense resistor
DECLARE FUNCTION MODULEOUT! (SENOUT!)   'calculates DUT output based on input
DECLARE SUB INSTALLDUT (NUMDUT%)        'Direct installation of DUTs and return #
DECLARE SUB SETOUTLOAD (LOAD!, NUMDUT%) 'Set output load for current output

'*********************** CALIBRATION ROUTINES ******************************
DECLARE SUB CALSEQ (NUMDUT%, STATUS$()) 'Determine & perform calibration sequence
DECLARE SUB GAINCAL (CAL%, AMPL!, INTERACT!, OSERR2!(), NUMDUT%, STATUS$()) 'Performs Gain Calibration
DECLARE SUB OFFSETCAL (CAL%, NUMDUT%, STATUS$()) 'Performs Offset Calibration
DECLARE FUNCTION SETDUTIN! (DUTIN!)    'Set high level RMS input to D.U.T.

'************************* ACCURACY ROUTINES *******************************
DECLARE SUB LINTEST (INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, STATUS$()) 'Performs Accuracy and Linearity Tests

'************************* OTHER DUT TESTS *********************************
DECLARE SUB ENABLE (DUT%, ONOFF%)       'Sets the state of the SCM5B output switch
DECLARE SUB IOUTMAXL (NUMDUT%, STATUS$())  'Test current source compliance
DECLARE SUB OUTPUTNOISE (NUMDUT%, STATUS$())  'Test module output noise
DECLARE SUB OUTSWITCH (NUMDUT%, STATUS$()) 'Test SCM5B output switch operation
DECLARE SUB SUPPLYI (NUMDUT%, STATUS$()) 'Measure module supply current
DECLARE SUB SUPPLYSEN (NUMDUT%, STATUS$()) 'Measure module supply sensitivity

'***************** MISCELLANEOUS HOUSEKEEPING ROUTINES *********************
DECLARE SUB CONTINUE ()                 'Waits for a key press
DECLARE SUB PAUSE (TIME!)               'Delays program for TIME!
DECLARE FUNCTION KEYBDIN$ ()            'Gets input from keyboard
DECLARE FUNCTION UPSN$ (OLDSN$)         '** Increments dash# of serial#

'******* Added Functions and Subs for Work Order Status File (etc.) version **********
DECLARE FUNCTION LIBVERVAL$ ()              'Function to return the library source file version
DECLARE FUNCTION PROGVERVAL$ ()             'Function to return the program source file version
DECLARE FUNCTION PROGNAMEVAL$ ()            'Function to return the program executable file name
DECLARE SUB CHECKRESOURCES (CHECKFILES%)    'Checks whether the datasheet and work order status files can be written.
DECLARE FUNCTION CHECKFILECREATE% (FOLDERNAME$, FILENAME$, KEYTOPRESS$) 'Checks whether the file can be written to the folder.
DECLARE FUNCTION CHECKPRINTER% (PrinterMessage$)    'Checks to see of the printer can print.
DECLARE SUB FAILSTATUS (TSITE%, TESTVALUE$, YLOC%, XLOC%, TEXTVALUE$, SPACES%)
DECLARE SUB INTERLUDE () ' WAIT FOR USER
DECLARE SUB WORKORDERLINE (FAILSTATE%, SN$)
DECLARE SUB WORKORDERPRINT (SN$)
DECLARE SUB WORKORDERHEADER (SN$)
DECLARE SUB GETDSFNAME (SN$, DSSNAME$, DSFNAME$)    'Gets datasheet search and file names from serial number
DECLARE SUB HARDCOPY ()
DECLARE SUB SNPARSE (SN$, WO$, DS$)
DECLARE FUNCTION WAITFORKEY$ (KEY$, TABPOS%, FORECOL%, BACKCOL%)
DECLARE FUNCTION GETWOSFNAME$ (SN$)         'Returns work order status file name from serial number
DECLARE SUB STARTCFG ()     'Performs module-input configuration before testing
DECLARE SUB ENDCFG ()       'Performs module-input configuration after testing
DECLARE SUB CLEARUNITSMSG () 'Displays message to clear modules from testhead
DECLARE FUNCTION GETWO$ ()                      'Gets and returns the work order number
DECLARE FUNCTION GETDS$ (ISNEWDS%, SN$)         'Gets and returns the dash number
DECLARE FUNCTION ISDUPLICATESN% (SERNO$, NUMDUT%) 'Check for duplicate serial numbers
DECLARE FUNCTION INSTRERROR$ (INSTRADDR%)           'Reads error status from the Agilent 33120A or 33970A
DECLARE SUB INSTRERRORS (INSTRADDR%, DISPLAYERRS%)  'Clears the Agilent 33120A or 34970A error queue by reading all errors
DECLARE SUB SHOWDIO (DIODATA%, WORNO%, DEBUGVAL%)   'Displays stored value for DIO word.
DECLARE SUB FINISHSUB ()                    'Subroutine to run at "FINISH" label (after F10 keypress).

'Database Record definition for the specifications
TYPE DBASE
	MODNAME         AS STRING * 13  'DSCA-XXXX or SCM5B-XXXX
	INTYPE          AS STRING * 3   ''V' OR 'A'
	MININ           AS SINGLE       'Minus F.S. input (V or I)
	MAXIN           AS SINGLE       'Plus F.S. input (V or I)
	OUTSIGTYPE      AS STRING * 7   ''VOLTAGE' or 'CURRENT'
	MINOUT          AS SINGLE       'Minus F.S. output (V or I)
	MAXOUT          AS SINGLE       'Plus F.S. output (V or I)
	WAVESHPCAL      AS STRING * 8   ''SINE', 'SQUARE', 'TRIANGLE', 'RAMP'
	FINCAL          AS SINGLE       'Calibration Frequency input (Hz)
	FINMIN          AS SINGLE       'Minimum Std. Frequency input (Hz)
	FINMAX          AS SINGLE       'Highest Std. Frequency input (Hz)
	FINEXTMIN       AS SINGLE       'Minimum Extd. Frequency input (Hz)
	FINEXTMAX       AS SINGLE       'Highest Extd. Frequency input (Hz)
	INPROTECT       AS SINGLE       'Rated input Protection (V or I)
	IOUTLIM         AS SINGLE       'Current output limit (mA)
	VOUTLIM         AS SINGLE       'Voltage output limit (V)
	OUTRES          AS SINGLE       'Output resistance
	OUTNOISE        AS SINGLE       'Output noise/ripple 100kHz BW (RMS)
	OSCALIN         AS SINGLE       'Module input for offset calibration
	GNCALIN         AS SINGLE       'Module input for gain calibration
	OSCALPT         AS SINGLE       'Offset cal point (%span)
	GNCALPT         AS SINGLE       'Gain cal point (%span)
	CALTOL          AS SINGLE       'Calibration tolerance (%span)
	ADJ             AS SINGLE       'User Adjustability Range (%span)
	LINEAR          AS SINGLE       'Linearity (% span) at sine input and FINCAL
	ACCSINCAL       AS SINGLE       'Sine accuracy (%span) at CALFIN
	ACCSINSTD       AS SINGLE       'Sine accuracy (%span) from FINMIN to FIMMAX
	ACCSINEXT       AS SINGLE       'Sine accuracy (%span) from FINEXTMIN to FINEXTMAX
	ACCCF12         AS SINGLE       'C.F. = 1 TO 2 accuracy (%span) at FINCAL
	ACCCF23         AS SINGLE       'C.F. = 2 TO 3 accuracy (%span) at FINCAL
	ACCCF34         AS SINGLE       'C.F. = 3 TO 4 accuracy (%span) at FINCAL
	ACCCF45         AS SINGLE       'C.F. = 4 TO 5 accuracy (%span) at FINCAL
	CMR             AS SINGLE       'Common Mode Rejection (dB)
	STEPTIME        AS SINGLE       'Test time for step response
	STEPPERC        AS SINGLE       '% F.S. @ STEPTIME
	STEPTOL         AS SINGLE       'STEPPERC measurement tolerance
	LOOPVMIN        AS SINGLE       'Output Loop Voltage min (V)
	LOOPVNOM        AS SINGLE       'Output Loop Voltage nom (V)
	LOOPVMAX        AS SINGLE       'Output Loop Voltage max (V)
	MAXLOADR        AS SINGLE       'Maximum load resistance (ohms)
	MINVS           AS SINGLE       'Lowest supply voltage (V)
	NOMVS           AS SINGLE       'Nominal supply voltage (V)
	MAXVS           AS SINGLE       'Highest supply voltage (V)
	ISMIN           AS SINGLE       'Minimum supply current (mA)
	ISMAX           AS SINGLE       'Supply current, full load (mA)
	PSS             AS SINGLE       'Power supply sensitivity (ppm/% or %/% Delta Vs)
END TYPE
		  
TYPE DBASE2
	RECNUM          AS INTEGER
	MODNAME         AS STRING * 13
END TYPE

'$INCLUDE: 'QB.BI2'

'Define common variables
COMMON SHARED /SAMPLE/ SPECS     AS DBASE
COMMON SHARED /SAMPLE/ SORTDATA1 AS DBASE2
COMMON SHARED /SAMPLE/ SORTDATA2 AS DBASE2

COMMON SHARED IINSEN1.MEAS!
COMMON SHARED IOUTSEN1.MEAS!()
COMMON SHARED IOUTSEN2.MEAS!()
COMMON SHARED IOUTSEN11.MEAS!()
COMMON SHARED SERNO$()
COMMON SHARED SN$                   ' unit serial number
COMMON SHARED PSCOM$
COMMON SHARED PSPORT%
COMMON SHARED GENOUTMAX!
COMMON SHARED PCBNO$
COMMON SHARED BADDRS%
COMMON SHARED DPSADDR%
COMMON SHARED DASADDR%
COMMON SHARED GENADDR%
COMMON SHARED DIOCH01DATA%
COMMON SHARED DIOCH02DATA%
COMMON SHARED /PRTSCR/ inreg  AS RegType
COMMON SHARED /PRTSCR/ outreg AS RegType
COMMON SHARED PON%, TX%, TESTPAUSE%, LOGDAT%
COMMON SHARED DPSVINADDR%, DPSVINADDR2%
COMMON SHARED DEBUGFLAG%, CAL%, TTYPE%

REM $DYNAMIC

'DIM  STATUS(17, 4) AS STRING
'DIM  TSPEC(17) AS STRING
DIM STATUS(MAXSTATUSINDEX, 4)  AS STRING
DIM TSPEC(MAXSTATUSINDEX)  AS STRING
DIM INSIM!(4, 25)
DIM OUTCALC!(4, 25)
DIM OUTMEAS!(4, 25)
DIM ERROROUT!(4, 25)
DIM ACCSTAT$(4, 25)
DIM IOUTSEN1.MEAS!(4)
DIM IOUTSEN2.MEAS!(4)
DIM IOUTSEN11.MEAS!(4)
DIM SHARED SERNO$(1 TO 4)
	  
'********************************************************************
'Assign constants to Kepco DPS power supply commands:
CONST PSVOLT$ = "STV="                  'Set terminal voltage
CONST SUPPLYON$ = "SOP=ON"              'Set output to ON
CONST SUPPLYOFF$ = "SOP=OFF"            'Set output to OFF
CONST ISTAT$ = "RCS"                    'Read Current protection status
CONST SETIMAX$ = "SOC="                 'Set overcurrent limit...4mA resolution.
CONST CURRENT$ = "RTC"                  'Read output current
CONST OVERV.DSCA! = 125                  'Module power supply over voltage limit, DSCA
CONST OVERV.SCM5B! = 48                 'Current loop power supply over voltage limit, SCM5B
CONST PSILIMIT! = 2                  'Module power supply over current limit
					'(max spec multiplier), DSCA
CONST PSID$ = "ID"                      'Power supply ID
'********************************************************************
'Assign constants to HP freq. gen. commands
CONST FREQ$ = "FREQ", VOLT$ = "VOLT", OFFS$ = "VOLT:OFFS"
CONST VUNIT$ = "VOLT:UNIT"
CONST SINE$ = "FUNC:SHAP SIN", SQUARE.CF1$ = "FUNC:SHAP SQU", TRIANGLE$ = "FUNC:SHAP TRI"
CONST SQUARE.CF2$ = "FUNC:USER ARB1", SQUARE.CF3$ = "FUNC:USER ARB2"
CONST SQUARE.CF4$ = "FUNC:USER ARB3", SQUARE.CF5$ = "FUNC:USER ARB4"
CONST BURSTON$ = "BM:STAT ON", BURSTOFF$ = "BM:STAT OFF"
CONST BURSTCNT$ = "BM:NCYC", BURSTSRCINT$ = "BM:SOUR INT"
CONST SETOUTP$ = "OUTP:LOAD INF"        'Generator output load is infinity
CONST INITWAVE$ = "APPL:SIN 60, .1, 0"   'Sine wave, .1Vrms, 60Hz, 0V offset

'********************************************************************
'Assign constants to HP DAS commands
CONST VDC$ = "VOLT:DC", VAC$ = "VOLT:AC", RES2W$ = "RES", RES4W$ = "FRES"
CONST ADC$ = "CURR:DC", AUTO$ = "AUTO"
CONST INTTIME$ = "NPLC", BW$ = "BAND", RANGE$ = "RANG"
CONST OSCOMP$ = "OCOM"
CONST DIGOUT$ = "SOUR:DIG:DATA", SETDAC$ = "SOUR:VOLT"
CONST GENOUTMIN! = .1                   'HP33120A minimum output amplitude
CONST GENOUTMAXHF! = 7.07               '7.07Vrms max output, sine, any freq.,
										'HP33120A direct to D.U.T.
'
'********************************************************************
'Assign constants to HP DAS configuration
CONST IINSEN2SOUR.CH% = 101             'Input current sense resistor, 100 ohm, source lines
CONST VOUTDUT1.CH% = 102                'DUT#1 output
CONST VOUTDUT2.CH% = 103                'DUT#2 output
CONST VOUTDUT3.CH% = 104                'DUT#3 output
CONST VOUTDUT4.CH% = 105                'DUT#4 output
CONST IOUTSENDUT1SOUR.CH% = 106         'Output current sense resistor DUT#1, source lines
CONST IOUTSENDUT1SEN.CH% = 116          'Output current sense resistor DUT#1, sense lines
CONST IOUTSENDUT2SOUR.CH% = 107         'Output current sense resistor DUT#2, source lines
CONST IOUTSENDUT2SEN.CH% = 117          'Output current sense resistor DUT#2, sense lines
CONST IOUTSENDUT3SOUR.CH% = 108         'Output current sense resistor DUT#3, source lines
CONST IOUTSENDUT3SEN.CH% = 118          'Output current sense resistor DUT#3, sense lines
CONST IOUTSENDUT4SOUR.CH% = 109         'Output current sense resistor DUT#4, source lines
CONST IOUTSENDUT4SEN.CH% = 119          'Output current sense resistor DUT#4, sense lines
'CH 10 NOT USED
CONST IINSEN2SEN.CH% = 111              'Input current sense resistor, 100 ohm, sense lines
CONST SCM5BVS.CH% = 112                 'Supply voltage, SCM5B
CONST VIN.CH% = 113                     'DUT input
'CH 14 NOT USED
CONST IINSEN1.CH% = 115                 'Input current sense resistor, 0.15 ohm
CONST MEASISUPPLY1.CH% = 121            'Supply current, DUT#1 & DUT#2
CONST MEASISUPPLY2.CH% = 122            'Supply current, DUT#3 & DUT#4
'CH 20 NOT USED

CONST SWITCHISDUT1.CH% = 201            'DUT #1 supply current routing
CONST SWITCHISDUT2.CH% = 202            'DUT #2 supply current routing
CONST SWITCHISDUT3.CH% = 203            'DUT #3 supply current routing
CONST SWITCHISDUT4.CH% = 204            'DUT #4 supply current routing
CONST VLOOPDUT1.CH% = 205               'Connect Vloop to Vout, DUT#1 (SCM5B current out only)
CONST VLOOPDUT2.CH% = 206               'Connect Vloop to Vout, DUT#2 (SCM5B current out only)
CONST VLOOPDUT3.CH% = 207               'Connect Vloop to Vout, DUT#3 (SCM5B current out only)
CONST VLOOPDUT4.CH% = 208               'Connect Vloop to Vout, DUT#4 (SCM5B current out only)
CONST IOUTLOAD1DUT1.CH% = 209           'Current output main load, DUT#1, 250 ohm
CONST IOUTLOAD2DUT1.CH% = 210           'Current output max load, DUT#1, 600 ohm typ.
CONST IOUTLOAD1DUT2.CH% = 211           'Current output main load, DUT#2, 250 ohm
CONST IOUTLOAD2DUT2.CH% = 212           'Current output max load, DUT#2, 600 ohm typ.
CONST IOUTLOAD1DUT3.CH% = 213           'Current output main load, DUT#3, 250 ohm
CONST IOUTLOAD2DUT3.CH% = 214           'Current output max load, DUT#3, 600 ohm typ.
CONST IOUTLOAD1DUT4.CH% = 215           'Current output main load, DUT#4, 250 ohm
CONST IOUTLOAD2DUT4.CH% = 216           'Current output max load, DUT#4, 600 ohm typ.
CONST DUT3INPUT.CH% = 217               'DUT #1 input, V or A
CONST DUT2INPUT.CH% = 218               'DUT #2 input, V or A
CONST DUT1INPUT.CH% = 219               'DUT #3 input, V or A
CONST VSSOURCE.CH% = 220                'D.U.T. Supply Voltage

CONST HVRELAY.CH% = 301                 'DIO LSB, Test head high voltage relay control
CONST RDEN.CH% = 302                    'DIO MSB, RD EN/, DUT 1-4
CONST DAC1.CH% = 304                    'DAC #1
CONST DAC2.CH% = 305                    'DAC #2

'********************************************************************

'assign specifications which are constant for all modules
CONST IINSEN1! = .15                    'Input current source sense resistor, 0.15 ohm
CONST IINSEN2! = 100                    'Input current source sense resistor, 100 ohm
CONST IOUTSEN1! = 250                   'Output current sense resistor, 250 ohm.
CONST IOUTSEN2! = 600                   'Output current sense resistor, 600 ohm.
CONST DELTALOADTOL! = 1                 'Max change in output with load (%)
					'Allows for 5.4 ohm lead resistance
					'and 0.1% output change
CONST NOISEFILTERR! = 160               'RC located @ meter input.  160 ohm series, 0.01uF shunt
CONST IOUTSEN3! = 10001                 'Disconnect output loading

CONST WORD2INIT = 255                   'Initial value of DIOCH02DATA%
'CONST WORD2INIT = 15                   'Initial value of DIOCH02DATA%

' Variable initialization
DEBUGFLAG% = 0  'Debug flag, "1" for debug (see in subs and functions).
TESTPAUSE% = 0  '1 = Pause after the status display of each test
TX% = 0         '1 = generate text files (datasheet and work order status)
PON% = 0        '1 = print test data to screen
LOGDAT% = 0     'Log linearity test data OFF
BADDRS% = &H250                         'Base address of PC4311 '488 controller
DIOCH01DATA% = 0                        'Digital I/O initialization, &H0
DIOCH02DATA% = WORD2INIT                      'Digital I/O initialization, &HFF
COLOR 11, 0, 0  'Cyan on black background

'HP34901A, 20 Channel Mux, Configuration
'Channel    Description
'-------    ---------------------------------------------------
'   1       Iin sense resistor, 100 ohm, 4W, source lines
'   2       Vout, DUT1
'   3       Vout, DUT2
'   4       Vout, DUT3
'   5       Vout, DUT4
'   6       Iout sense resistor, DUT1, 250 ohm or 600 ohm, 4W or 2W, source lines
'   7       Iout sense resistor, DUT2, 250 ohm or 600 ohm, 4W or 2W, source lines
'   8       Iout sense resistor, DUT3, 250 ohm or 600 ohm, 4W or 2W, source lines
'   9       Iout sense resistor, DUT4, 250 ohm or 600 ohm, 4W or 2W, source lines
'  10       Vin
'  11       Iin sense resistor, 100 ohm, 4W, sense lines
'  12       SCM5B Supply Voltage
'  13       NC
'  14       NC
'  15       Iin sense resistor, 0.1 ohm, 2W
'  16       Iout sense resistor, DUT1, 250 ohm, 4W, sense lines
'  17       Iout sense resistor, DUT2, 250 ohm, 4W, sense lines
'  18       Iout sense resistor, DUT3, 250 ohm, 4W, sense lines
'  19       Iout sense resistor, DUT4, 250 ohm, 4W, sense lines
'  20       NC
'  21       SCM5B Supply Current, DUT1 & DUT2
'  22       SCM5B Supply Current, DUT3 & DUT4

'HP34903A, 20 Channel Actuator, Configuration
'Channel    Description
'-------    ---------------------------------------------------
'   1       NC = Select SCM5B Supply Current, DUT1
'   2       NO = Select SCM5B Supply Current, DUT2
'   3       NC = Select SCM5B Supply Current, DUT3
'   4       NO = Select SCM5B Supply Current, DUT4
'   5       NC = Measure Vout DUT1, NO = Connect Vloop to SCM5B DUT1 Vout
'   6       NC = Measure Vout DUT2, NO = Connect Vloop to SCM5B DUT2 Vout
'   7       NC = Measure Vout DUT3, NO = Connect Vloop to SCM5B DUT3 Vout
'   8       NC = Measure Vout DUT4, NO = Connect Vloop to SCM5B DUT4 Vout
'   9       NO = DUT1 Output Load 1, 250 ohm
'  10       NO = DUT1 Output Load 2, 600 ohm
'  11       NO = DUT2 Output Load 1, 250 ohm
'  12       NO = DUT2 Output Load 2, 600 ohm
'  13       NO = DUT3 Output Load 1, 250 ohm
'  14       NO = DUT3 Output Load 2, 600 ohm
'  15       NO = DUT4 Output Load 1, 250 ohm
'  16       NO = DUT4 Output Load 2, 600 ohm
'  17       NO = Vin DUT3, NC = Iin DUT1
'  18       NO = Vin DUT2, NC = Iin DUT2
'  19       NO = Vin DUT1, NC = Iin DUT3
'  20       NO = Vsupply is Kepco DPS125 +15 to +30V, NC = Vsupply is +5V


'HP34907A, Multi-function Module, Configuration
'Port    Line      Assignment
'----   ------     ----------
' 1      7 MSB     NC
'        6         NC
'        5         HVRELAY #6  0 = HP33120A input to Fluke 760A, 1 = HP33120A disconnected from Fluke 760A
'        4         HVRELAY #5  0 = Fluke 760A input to D.U.T., 1 = HP33120A input to D.U.T.
'                  * set lines 4 and 5 simultaneously low or high
'        3         HVRELAY #4  1 = Rsense Bypass
'        2         HVRELAY #3  1 = D.U.T. 2 Input Bypass
'        1         HVRELAY #2  1 = D.U.T. 3 Input Bypass
'        0 LSB     HVRELAY #1  1 = D.U.T. 4 Input Bypass
'
' 2      7 MSB     NC
'        6         NC
'        5         NC
'        4         NC
'        3         0 = D.U.T. 1 RD EN/
'        2         0 = D.U.T. 2 RD EN/
'        1         0 = D.U.T. 3 RD EN/
'        0 LSB     0 = D.U.T. 4 RD EN/
'
'        DAC       CH4

'****************** MAIN PROGRAM ******************
KEY(10) ON                              'Activates F10 key
ON KEY(10) GOSUB FINISH                 'Traps for F10 key Exits if pressed

CLS
CALL GETADD

COLOR 11, 0 'Text color  to light cyan (blue)

'CLS
LOCATE 5, 20:  PRINT "Initializing test system.  Please wait."
LOCATE 7, 10:  PRINT "EXECUTABLE:   "; PROGNAMEVAL$ 'Executable file name
LOCATE 8, 10:  PRINT "VERSION:      "; PROGVERVAL$  'Main source code version
LOCATE 9, 10:  PRINT "LIB.VERSION:  "; LIBVERVAL$   'Library code version
LOCATE 10, 10: PRINT "SOURCE FILES: "; SOURCEFILES$ 'List of all code files for the program
CALL CONTINUE
CLS

LOCATE 12
'PRINT TAB(10); "Initializing Function Generator..."

'PRINT TAB(10); "Storing Arbitrary Waveforms in Generator"
'PRINT TAB(10); "Please wait...."

PRINT TAB(20); "Initializing Function Generator..."
CALL IO488("*RST", GENADDR%, 1)
PRINT

PRINT TAB(10); "Initializing Data Acquisition System..."
CALL IO488("ABOR", DASADDR%, 1)                 'Abort any scans in progress.
CALL IO488("*CLS", DASADDR%, 1)                 'Clear status (clear errors)
CALL INSTRERRORS(DASADDR%, 1)  'Clears and displays Agilent 34970A error queue.

CLS
'Clear messages.
LOCATE 10, 10: PRINT SPC(70);
LOCATE 11, 10: PRINT SPC(70);
LOCATE 12, 10: PRINT SPC(70);
LOCATE 13, 10: PRINT SPC(70);
LOCATE 14, 10: PRINT SPC(70);
LOCATE 15, 10: PRINT SPC(70);
'Display initial message.
LOCATE 10, 10: PRINT "-----------------------------------------------"
LOCATE 11, 10: PRINT "Initializing 34970A Data Acquisition System...."
LOCATE 12, 10: PRINT "-----------------------------------------------"
LOCATE 13, 10: PRINT "Please wait...."
CALL PAUSE(1)   'Pause to message can be read.

'Initialize function generator.
CALL INSTRERRORS(DASADDR%, 0)       'Clear Agilent 34970A errors.
LOCATE 14, 10: PRINT "Resetting the 34970A data acquisition system."
CALL IO488("*RST", DASADDR%, 1)     'Send a "clear status" command to the function generator (should clear errors).
PAUSE (1)   'Pause so message can be read.
LOCATE 14, 10: PRINT SPC(70);

LOCATE 14, 10: PRINT "Aborting any scans in progress in 34970A."
CALL IO488("ABOR", DASADDR%, 1) 'Abort any scans in progress.
PAUSE (1)   'Pause so message can be read.
LOCATE 14, 10: PRINT SPC(70);

LOCATE 14, 10: PRINT "Clearing the 34970A data acquisition system."
CALL IO488("*CLS", DASADDR%, 1)                 'Send a "clear status" command to the function generator (should clear errors).
PAUSE (1)   'Pause so message can be read.
LOCATE 14, 10: PRINT SPC(70);

LOCATE 14, 10: PRINT "Deleting stored states in Agilent 34970A (may beep)."
CALL IO488("MEM:STAT:DEL 0", DASADDR%, 1)       'Delete store state 0.
CALL IO488("MEM:STAT:DEL 1", DASADDR%, 1)       'Delete store state 1.
CALL IO488("MEM:STAT:DEL 2", DASADDR%, 1)       'Delete store state 2.
CALL IO488("MEM:STAT:DEL 3", DASADDR%, 1)       'Delete store state 3.
CALL IO488("MEM:STAT:DEL 4", DASADDR%, 1)       'Delete store state 4.
CALL IO488("MEM:STAT:DEL 5", DASADDR%, 1)       'Delete store state 5.
CALL INSTRERRORS(DASADDR%, 0)       'Clear Agilent 34970A errors.
PAUSE (1)   'Pause so message can be read.

'Clear messages.
LOCATE 10, 10: PRINT SPC(70);
LOCATE 11, 10: PRINT SPC(70);
LOCATE 12, 10: PRINT SPC(70);
LOCATE 13, 10: PRINT SPC(70);
LOCATE 14, 10: PRINT SPC(70);
LOCATE 15, 10: PRINT SPC(70);

'CALL DVMSENS(VIN.CH%, VAC$, BW$, "", 3)        'Set bandwidth for max accuracy.

PRINT TAB(10); "Initializing Power Supply..."
SP$ = POWERIO$(DPSADDR%, SUPPLYOFF$)            'Disable power supply
SP$ = POWERIO$(DPSADDR%, PSID$)
'
SP$ = POWERIO$(DPSVINADDR%, SUPPLYOFF$)          'Disable power supply
SP$ = POWERIO$(DPSVINADDR%, PSID$)
'
SP$ = POWERIO$(DPSVINADDR2%, SUPPLYOFF$)          'Disable power supply
SP$ = POWERIO$(DPSVINADDR2%, PSID$)


PRINT
PRINT TAB(10); USING "&&"; SP$ + " = " + PSCOM$
PRINT TAB(10); "#1 KEPCO DPS125-0.5M Address = "; DPSADDR%
PRINT TAB(10); "#2 KEPCO DPS125-0.5M Address = "; DPSVINADDR%
PRINT TAB(10); "#3 KEPCO DPS125-0.5M Address = "; DPSVINADDR2%
PRINT TAB(10); "HP34970A GPIB Address     = "; DASADDR%
PRINT TAB(10); "HP33120A GPIB Address     = "; GENADDR%
'IF ASC(SP$) <> 75 THEN
'    PRINT
'    PRINT TAB(20); "Programmable Power Supply Failure"
'    CALL CONTINUE
'    GOTO FINISH
'END IF

PRINT
PRINT TAB(10); "Setting Internal Vsupply to Zero..."
SP! = SETSCM5BPWR!(.01)                 'Set Vsupply to zero

PRINT
PRINT TAB(10); "Initializing Test Head..."
CALL PAUSE(1)
										   
DDATA$ = DIGOUT$ + STR$(DIOCH01DATA%) + ",(@" + STR$(HVRELAY.CH%) + ")"
CALL IO488(DDATA$, DASADDR%, 1)         'Write configuration
										   
'Port 2, data = WORD2INIT
DIOCH02DATA% = WORD2INIT                      'Digital I/O initialization, &HFF
DDATA$ = DIGOUT$ + STR$(DIOCH02DATA%) + ",(@" + STR$(RDEN.CH%) + ")"
CALL IO488(DDATA$, DASADDR%, 1)         'Write configuration


CALL HVRELAY(4, 1)                      'Bypass 100 ohm sense resistor
CLS
LOCATE 10
PRINT TAB(10); "Remove all modules from the test head."
PRINT
COLOR 14, 0, 0  'Yellow on black
PRINT TAB(6); "-----------------------------------------------------------------"
COLOR 28, 0, 0  'Flashing light red
PRINT TAB(5); "Verify that there are no modules of any type currently installed "
PRINT TAB(5); "in the test head!                                                "
COLOR 14, 0, 0  'Yellow on black
PRINT TAB(6); "-----------------------------------------------------------------"
'BEEP
DUMKEY$ = WAITFORKEY("N", 10, 14, 0)    'Waits for "N" key press (display bright yellow on black)
CLS
LOCATE 10, 10: PRINT "Measuring output current sense resistors."
LOCATE 16, 10: PRINT "Please wait...."

'NOMVS! = 0, Vloop not connected during SETOUTLOAD.
CALL SETOUTLOAD(IOUTSEN1!, 4)           'Set current output sense resistor
FOR L% = 1 TO 4
	IOUTSEN11.MEAS!(L%) = MEASRES!(IOUTSEN1!, 2, L%) 'Measure current output sense resistor
NEXT
CALL SETOUTLOAD(IOUTSEN2!, 4)           'Set max load resistor
FOR L% = 1 TO 4
	IOUTSEN2.MEAS!(L%) = MEASRES!(IOUTSEN2!, 3, L%) 'Measure current output sense resistor
NEXT

LOGDAT% = 0         'Log linearity test data OFF

'*********************   MAIN LOOP   ****************************
DO      'Main program loop
	SN$ = ""                            'Reset serial number
	SEL% = MENU1%                       'Gets the # of the sub program
	
	SELECT CASE SEL%                    'Branches to the specific Tests
		'**************** Pre-Burn In Functional Test *******************
		CASE 1
			TTYPE% = 1              'Test type flag
			CAL% = 2                'Measure offset and gain, don't calibrate
			ITERATION% = 1          'Sets # of times to repeat offset/gain cal
			CALL GETSPECS(NUMDUT%)  'Gets module test specs
			CALL CLEARUNITSMSG      'Displays message to clear modules from testhead

			IF LEFT$(SPECS.MODNAME, 2) = "8B" THEN
				PCBNO$ = "0000"
			END IF

			IF LEFT$(SPECS.MODNAME, 4) <> "EXIT" THEN
				SN$ = "-1"      'Dummy value
				'CALL INSTALLDUT(NUMDUT%)   'Gets number of modules to test
				'CALL FUNCTEST(CAL%, STATUS$(), NUMDUT%) ' test
				CALL FUNCTEST(STATUS$(), CAL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, TTYPE%, TSPEC$(), SERNO$())  'Routines for functional test
				CALL SETDPS(DPSVINADDR%, 0)
				CALL SETDPS(DPSVINADDR2%, 0)
				CALL INSTRERRORS(DASADDR%, 1)  'Clears and displays Agilent 34970A error queue.
				PON% = 0    'Print Flag Printer OFF
			END IF

	'*********************** Pre-Encap Complete Test ******************************
	CASE 2
		TTYPE% = 2              'Test type flag
		CAL% = 0                'Calibrate offset & gain.
		ITERATION% = 1          'Sets # of times to repeat offset/gain cal
		CALL GETSPECS(NUMDUT%)  'Gets module test specs
			CALL CLEARUNITSMSG  'Displays message to clear modules from testhead
		IF LEFT$(SPECS.MODNAME, 2) = "8B" THEN
			PCBNO$ = "0000"
		END IF

		IF LEFT$(SPECS.MODNAME, 4) <> "EXIT" THEN
			SN$ = "-1"                          'Dummy value
			CALL COMPTEST(STATUS$(), ITERATION%, CAL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, TTYPE%, TSPEC$(), SERNO$())  'Complete set of tests
			CALL ENDCFG     'Performs module-input configuration after testing
			CALL SETDPS(DPSVINADDR%, 0)
			CALL SETDPS(DPSVINADDR2%, 0)
			CALL INSTRERRORS(DASADDR%, 1)  'Clears and displays Agilent 34970A error queue.
			PON% = 0    'Print Flag Printer OFF
		END IF

	'**************** Post-Encap Complete Test  ***********************************
	CASE 3
		TTYPE% = 3                               'Test type flag
		CAL% = 0                                'calibrate offset & gain
		ITERATION% = 1                          'Sets # of times to repeat offset/gain cal
		CALL GETSPECS(NUMDUT%)                  'Gets module test specs
		CALL CLEARUNITSMSG  'Displays message to clear modules from testhead
		IF LEFT$(SPECS.MODNAME, 2) = "8B" THEN
			PCBNO$ = "0000"
		END IF
		IF LEFT$(SPECS.MODNAME, 4) <> "EXIT" THEN
			CALL COMPTEST(STATUS$(), ITERATION%, CAL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, TTYPE%, TSPEC$(), SERNO$())  'Complete set of tests
			CALL ENDCFG     'Performs module-input configuration after testing
			CALL SETDPS(DPSVINADDR%, 0)
			CALL SETDPS(DPSVINADDR2%, 0)
			CALL INSTRERRORS(DASADDR%, 0)       'Clear Agilent 34970A errors.
			PON% = 0    'Print Flag Printer OFF
		END IF
		  
	'**************** Sealed Module Re-Test  ***********************************
	CASE 4
		TTYPE% = 4                               'Test type flag
			'CAL% = 0                       'Calibrate offset & gain
		ITERATION% = 0                          'Sets # of times to repeat offset/gain cal
		CALL GETSPECS(NUMDUT%)                  'Gets module test specs
		CALL CLEARUNITSMSG  'Displays message to clear modules from testhead
		IF LEFT$(SPECS.MODNAME, 2) = "8B" THEN
			PCBNO$ = "0000"
		END IF
		IF LEFT$(SPECS.MODNAME, 4) <> "EXIT" THEN
			CALL COMPTEST(STATUS$(), ITERATION%, CAL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, TTYPE%, TSPEC$(), SERNO$())  'Complete set of tests
			CALL ENDCFG     'Performs module-input configuration after testing
			CALL SETDPS(DPSVINADDR%, 0)
			CALL SETDPS(DPSVINADDR2%, 0)
			CALL INSTRERRORS(DASADDR%, 1)  'Clears and displays Agilent 34970A error queue.
			PON% = 0    'Print Flag Printer OFF
		END IF
		 
	'***********************Individual Test Routines******************************
	CASE 5
			TTYPE% = 5  'Test type flag.
			'PON% = 0   'Print Flag Printer OFF.
		DO  'Start of Individual Tests loop.
			SEL% = MENU2%           'Gets # of test.
			'IF SEL% <> 20 THEN     'Checks for exit.
			IF SEL% <> 13 THEN      'Checks for exit.
				'IF SEL% = 17 THEN  'Checks for printer toggle.
				IF SEL% = 9 THEN    'Checks for printer toggle.
						'Toggles printer status
						IF PON% = 1 THEN
							PON% = 0
						ELSE
							PON% = 1
						END IF
				'ELSEIF SEL% = 16 THEN
				ELSEIF SEL% = 8 THEN
					CALL NOTES      'Show ATE notes.
				'ELSEIF SEL% = 18 THEN
				'       'Toggles log status
				'       'LOGDAT% = -LOGDAT%
				'       IF LOGDAT% = 1 THEN
				'           LOGDAT% = 0
				'       ELSE
				'           LOGDAT% = 1      
				'       END IF
				'ELSEIF SEL% = 19 THEN
				ELSEIF SEL% = 10 THEN
					'Checks for pause on each test toggle (character A).
					'
					'Toggles "pause on each test" flag
					IF TESTPAUSE% = 1 THEN
						TESTPAUSE% = 0
					ELSE
						TESTPAUSE% = 1
					END IF
				ELSEIF SEL% = 11 THEN
					'Checks for debug flag toggle (character B).
					'
					'Toggles debug flag
					IF DEBUGFLAG% = 1 THEN
						DEBUGFLAG% = 0
					ELSE
						DEBUGFLAG% = 1
					END IF
				ELSEIF SEL% = 12 THEN
					'Character C
					LPRINT CHR$(12) 'Form feed
				ELSE
					'Individual Tests.
					CALL GETSPECS(NUMDUT%)  'Gets module specs.
					IF LEFT$(SPECS.MODNAME, 4) <> "EXIT" THEN
						SN$ = "-1"               'Dummy value
						TESTPAUSE% = 1  'Turn on "pause on each test" flag.
						CALL CLEARUNITSMSG  'Displays message to clear modules from testhead
						CALL INDIVID(SEL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), STATUS$(), NUMDUT%) 'Performs individual test
						TESTPAUSE% = 0  'Turn off "pause on each test" flag.
						CALL ENDCFG     'Performs module-input configuration after testing
					END IF
				END IF
			END IF
		'LOOP UNTIL SEL% = 20               'End of loop
		LOOP UNTIL SEL% = 13                'End of loop (character D).

	'*************************** End Program Selection *********************************
	CASE 6
		ENDPROG% = 1                            'Sets end program flag
   END SELECT
LOOP WHILE ENDPROG% <> 1                            'Loops until end program flag set
'******************** End Program Selection *******************
  
FINISH:
	CALL FINISHSUB
	END 'End of program

'***********************************
SUB CALSEQ (NUMDUT%, STATUS$())
	'Determine which calibration sequence is required for the module
	'and perform the offset and gain calibration.
	'
	'Inputs;    None
	'Outputs;   WONTCAL%    0 = Module calibrated
	'                       1 = Module won't calibrate, exit sequence
	'
	MAXOUT! = SPECS.MAXOUT
	MINOUT! = SPECS.MINOUT
	ACCLIM! = SPECS.ACCSINCAL

	ORANGE! = MAXOUT! - MINOUT!

	DIM OSERR2!(5), GNERR2!(5)

	IF (ABS(MINOUT!) <> MAXOUT! AND MINOUT! <> 0) OR SPECS.OSCALIN <> 0 THEN
		PEDOFFSET$ = "Y"
		INTERACT! = .0909       'Change in offset with change in gain.
								'average value determined from data in CALDATA.DAT
		ITERATION% = 4          '4 passes MAX on initial cal
	ELSE
		PEDOFFSET$ = "N"
		INTERACT! = 1
		ITERATION% = 1
	END IF

	IF PEDOFFSET$ = "N" THEN                        'Standard calibration sequence
		DO
			CAL% = 0
			CALL OFFSETCAL(CAL%, NUMDUT%, STATUS$()) 'Calibrate offset
			CALL GAINCAL(CAL%, 0, INTERACT!, OSERR2!(), NUMDUT%, STATUS$()) 'Calibrate gain
			ITERATION% = ITERATION% - 1
		LOOP WHILE ITERATION% > 0  'Tests for Offset/Gain calibration end
	ELSE
		CAL% = 1
		CALL OFFSETCAL(CAL%, NUMDUT%, STATUS$())     'Measure offset error after adjust
		FOR L% = 1 TO NUMDUT%
			IF LEFT$(STATUS$(1, L%), 4) <> "FAIL" AND LEFT$(STATUS$(13, L%), 4) <> "FAIL" AND LEFT$(STATUS$(14, L%), 4) <> "FAIL" THEN 'Check if module passes
				DATALEN% = LEN(STATUS$(13, L%))
				OSERR2!(L%) = VAL(MID$(STATUS$(13, L%), 5, DATALEN% - 4))
			END IF
		NEXT
		 
		DO
			CAL% = 0
			CALL GAINCAL(CAL%, 0, INTERACT!, OSERR2!(), NUMDUT%, STATUS$()) 'Calibrate gain
			CALL OFFSETCAL(CAL%, NUMDUT%, STATUS$()) 'Calibrate offset
			OSPASS% = 1
			FOR L% = 1 TO NUMDUT%
				IF LEFT$(STATUS$(1, L%), 4) <> "FAIL" AND LEFT$(STATUS$(13, L%), 4) <> "FAIL" AND LEFT$(STATUS$(14, L%), 4) <> "FAIL" THEN  'Check if module passes
					DATALEN% = LEN(STATUS$(13, L%))             'Get offset error
					OSERR2!(L%) = VAL(MID$(STATUS$(13, L%), 5, DATALEN% - 4))
					IF ABS(OSERR2!(L%)) >= ACCLIM! THEN OSPASS% = 0
				END IF
			NEXT
			CAL% = 0
			CALL GAINCAL(CAL%, 0, INTERACT!, OSERR2!(), NUMDUT%, STATUS$()) 'Calibrate gain
			GNPASS% = 1
			FOR L% = 1 TO NUMDUT%
				IF LEFT$(STATUS$(1, L%), 4) <> "FAIL" AND LEFT$(STATUS$(13, L%), 4) <> "FAIL" AND LEFT$(STATUS$(14, L%), 4) <> "FAIL" THEN 'Check if module passes
					DATALEN% = LEN(STATUS$(14, L%))             'Get gain error
					GNERR2! = VAL(MID$(STATUS$(14, L%), 5, DATALEN% - 4))       'Measured gain error in mV or uA
					IF ABS(GNERR2!(L%)) >= ACCLIM! THEN GNPASS% = 0
				END IF
			NEXT
			ITERATION% = ITERATION% - 1
		LOOP UNTIL (OSPASS% = 1 AND GNPASS% = 1) OR ITERATION% = 0
	END IF
  
END SUB

SUB CLEARUNITSMSG
	'Sub to display a message about what kind of modules can be tested,
	'and the restriction against testing one type of module with other
	'modules in the testhead. Then a message is displayed to remove ALL
	'modules from the testhead. The sub is generally run only at the
	'start of any kind of test.
	'
	'First message screen
	CLS
	LOCATE 1, 20: PRINT "SCM5B, 8B & DSCA AUTOMATED TEST EQUIPMENT"
	PRINT
	PRINT TAB(5); "Module type selected: "; SPECS.MODNAME
	PRINT
	PRINT
	PRINT TAB(5); "Up to 4 modules of a single type (SCM5B, 8B or DSCA can be"
	PRINT TAB(5); "tested at the same time. However, only ONE (1) type of module can"
	PRINT TAB(5); "be installed while testing!"
	PRINT
	PRINT
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(6); "-----------------------------------------------------------------"
	COLOR 28, 0, 0  'Flashing light red
	PRINT TAB(5); "Verify that there are no modules of any type currently installed "
	PRINT TAB(5); "in the test head!                                                "
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(6); "-----------------------------------------------------------------"
	COLOR 11, 0, 0  'Cyan on black background
	PRINT
	'BEEP
	DUMKEY$ = WAITFORKEY("N", 10, 14, 0)    'Waits for "N" key press (display bright yellow on black)
END SUB

'************************************
SUB COMPTEST (STATUS$(), ITERATION%, CAL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, TTYPE%, TSPEC$(), SERNO$()) 'Complete set of tests
	'Sub to run a complete set of tests, looping once each pass (and individually through each test channel
	'for each test). In other legacy test code, the "once per test pass" loop was done in the MENU1% selection
	'code, not within COMPTEST.
	'
	NOMVS! = SPECS.NOMVS
	'WAVESHPCAL$ = "FUNC:SHAP " + LEFT$(SPECS.WAVESHPCAL$, 3)
	FINCAL! = SPECS.FINCAL
	FINMAX! = SPECS.FINMAX
	FINEXTMAX! = SPECS.FINEXTMAX
	ACCCF12! = SPECS.ACCCF12
	ACCCF23! = SPECS.ACCCF23
	ACCCF34! = SPECS.ACCCF34
	ACCCF45! = SPECS.ACCCF45
	ACCSINCAL! = SPECS.ACCSINCAL
	ACCSINSTD! = SPECS.ACCSINSTD
	ACCSINEXT! = SPECS.ACCSINEXT
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE
	LOOPVNOM! = SPECS.LOOPVNOM + SPECS.MAXOUT * NOISEFILTERR!

	DIM NOMOUTERR!(4)
	'DIM TSPEC(17) AS STRING

	LOOPCYC% = 0

	'Clear serial numbers and file flag
	FOR L% = 1 TO 4
		SERNO$(L%) = ""
	NEXT
	LOCALSN$ = ""
	SN$ = ""
	TX% = 0 '   'Text-file flag "off"
	
	IF ((TTYPE% = 3) OR (TTYPE% = 4)) THEN
		'Post-Encap or Sealed Module test. Hardcopy (to printer) or
		'not is asked, as well as the number of modules inserted.
		'The module serial number or numbers is also determined and
		'the "TX%" flag is set "on" (to create work order status and
		'datasheet text files).
		'
		TX% = 1 '   'Text-file flag "on"

		'Get information required before the first test pass
		CALL INSTALLDUT(NUMDUT%)    'Gets number of modules to test
		CALL INPUTSN(SN$, SERNO$(), NUMDUT%)    'Gets module serial # THIS IS WHERE YOU ENTER SN down the line calls GETSN
		CALL HARDCOPY               'Ask for hardcopy printout
		
		CALL CHECKRESOURCES(1)      'Check for ability to write datasheet and status files and to printer.
		TIME2! = TIMER  'Start (or re-start) test timer)

		'Get channel 1 serial number (there will always be at least a module in channel 1)
		LOCALSN$ = SERNO$(1)
		CALL WORKORDERHEADER(LOCALSN$)  'Write header to work order status file
	ELSE
		'NOT Post-Encap or Sealed Module: only the number of modules inserted
		'is needed initially.
		TX% = 0 '   'Text-file flag "off"
		CALL INSTALLDUT(NUMDUT%)    'Gets number of modules to test
		IF (PON% = 1) THEN
			CALL CHECKRESOURCES(0)      'Check for ability to write to printer.
		END IF
	END IF
	
	'Configure module input
	CALL STARTCFG   'Performs module-input configuration before testing
	
	DO  'Complete test loop start (each loop is a complete test pass)
		LOOPCYC% = LOOPCYC% + 1
		TIME2! = TIMER
		IF LOOPCYC% > 1 AND TTYPE% = 2 THEN
			'Pre-Encap: only the number of modules inserted is needed for the
			'next test pass. No serial numbers need to be entered.
			CALL INSTALLDUT(NUMDUT%)    'Gets number of modules to test
		ELSEIF LOOPCYC% > 1 AND (TTYPE% = 3 OR TTYPE% = 4) THEN
			'Post-Encap or Sealed Module: the number of modules inserted and their
			'serial numbers need to be entered before the next test pass.
			CALL GETNEXTSN(TIME2!, SERNO$(), NUMDUT%)   'Gets next # of modules and their serial numbers
		END IF

		IF LOOPCYC% = 1 THEN
			IF OUTSIGTYPE$ = "CURRENT" THEN
				CALL SETOUTLOAD(IOUTSEN1!, 4) 'Set current output sense resistor
				FOR L% = 1 TO 4
					IOUTSEN1.MEAS!(L%) = IOUTSEN11.MEAS!(L%)
				NEXT
			ELSE    'IF OUTSIGTYPE$ = "VOLTAGE" THEN
				CALL SETOUTLOAD(1000000!, 4)  'Remove current output sense resistor
				FOR L% = 1 TO 4
					IOUTSEN1.MEAS!(L%) = 1
				NEXT
			END IF
		END IF

		'FOR x% = 1 TO 17
		FOR x% = 1 TO MAXSTATUSINDEX
			FOR L% = 1 TO NUMDUT%
				STATUS$(x%, L%) = ""    'Clear test result array
			NEXT
		NEXT

		IF NOT (LEFT$(SPECS.MODNAME, 5) = "SCM5B") THEN
			'Turn off internal SCM7B (RDEN isolator) supply if not SCM5B.
			CALL ENABLE(5, 0)
		END IF
		
		'************************ ALL *****
		IF OUTSIGTYPE$ <> "CURRENT" THEN CALL SETOUTLOAD(IOUTSEN3!, 4) 'TURN-OFF ALL RELAYS

		IF NOMVS! = 5 THEN
			'Nom volts = 5V (8B or SCM5B)
			'***************************** SCM5B and 8B use 5V ******************************
			CALL SETSWITCH(VSSOURCE.CH%, 0)         'DUT power is test head VCVS
			SP! = SETSCM5BPWR!(NOMVS!)              'Set Vsupply to nominal value
			IF SP! = -1 THEN
				CLS
				LOCATE 10
				PRINT TAB(10); "One or more of the modules has high supply current."
				PRINT TAB(10); "Run the Supply Current test under the Individual Test Menu"
				PRINT TAB(10); "to find the faulty modules."
				CALL CONTINUE
				GOTO EXITTEST                       'High supply current
			END IF

			IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
				'Enable output switch only for SCM5B (PWR 2014-05-08)
				FOR L% = 1 TO NUMDUT%
					CALL ENABLE(L%, 0)  'Enable output switch
				NEXT
			END IF
				
			IF OUTSIGTYPE$ = "CURRENT" THEN CALL SETDPS(DPSADDR%, LOOPVNOM!)    'Set Vloop to nominal value

		ELSE                                        ' nom volts != 5v
			'****************** DSCA does not use 5v *********************************
			CALL SETSWITCH(VSSOURCE.CH%, 1)         'D.U.T. Power is Kepco DPS
			CALL INITPS(DPSADDR%, SPECS.ISMAX! * PSILIMIT! * 4, OVERV.DSCA!)
			CALL SETDPS(DPSADDR%, NOMVS!)           'Set Vsupply to nominal value
		END IF
		'*************************************

		CALL SUPPLYI(NUMDUT%, STATUS$())            'Supply current test
		
		F% = 0  'Initialize failure count (number of channels that have failed Supply Current test)
		FOR L% = 1 TO NUMDUT%
			IF LEFT$(STATUS$(1, L%), 4) = "FAIL" THEN F% = F% + 1
		NEXT

		'Exit if all modules failed supply current or one or more
		'remaining modules has a high supply current
		IF F% = NUMDUT% THEN GOTO EXITTEST

		FOR L% = 1 TO ITERATION%                    'Offset/Gain calibration loop
			CALL CALSEQ(NUMDUT%, STATUS$())
			L% = L% + 1
		NEXT
		F% = 0
		FOR L% = 1 TO NUMDUT%
			IF LEFT$(STATUS$(13, L%), 4) = "FAIL" OR LEFT$(STATUS$(14, L%), 4) = "FAIL" THEN
				F% = F% + 1
			END IF
		NEXT

		IF F% = NUMDUT% THEN GOTO EXITTEST          'All modules failed offset and/or gain calibration
		CALL LINTEST(INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, STATUS$())          'Performs linearity and
																								 'accuracy tests
		'IF NOMVS! = 5 THEN                          'Nominal voltage is 5v 8b and 5B SCM5B

		IF (LEFT$(SPECS.MODNAME, 5) = "SCM5B") THEN 'SCM5B
			CALL OUTSWITCH(NUMDUT%, STATUS$())      'SCM5B output switch operation
		END IF

		F% = 0
		FOR L% = 1 TO NUMDUT%
			IF LEFT$(STATUS$(2, L%), 4) = "FAIL" THEN F% = F% + 1
		NEXT

		IF F% = NUMDUT% THEN GOTO EXITTEST          'All modules failed output switch test

		CALL SUPPLYSEN(NUMDUT%, STATUS$())          'Power supply sensitivity
		NOMOUTERR!(1) = 1000  'Dummy value (+1000%) Measure 1st time, pass result for following tests

		'************** ALL ********************


		CALL OUTPUTNOISE(NUMDUT%, STATUS$())        'Test Output Noise

		IF SPECS.OUTSIGTYPE$ = "CURRENT" THEN       'Max load resistance test
			CALL IOUTMAXL(NUMDUT%, STATUS$())
		END IF

EXITTEST:
		IF NOMVS! = 5 THEN                          'Nominal voltage is 5v 8b and 5B SCM5B
				SP! = SETSCM5BPWR!(.01)                 'Set Vsupply to zero
				IF OUTSIGTYPE$ = "CURRENT" THEN
					SP$ = POWERIO$(DPSADDR%, SUPPLYOFF$)    'Disable power supply
				END IF
				IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
					FOR L% = 1 TO NUMDUT%
						CALL ENABLE(L%, 1)                  'Disable output switch
					NEXT
				END IF
		ELSE    'IF NOMVS! = 24 THEN
			SP$ = POWERIO$(DPSADDR%, SUPPLYOFF$)    'Disable power supply
		END IF

		'LOCATE 10, 10: PRINT "Initializing Agilent DAS.                    "
		'CALL IO488("*RST", DASADDR%, 1)
		'CALL IO488("ABOR", DASADDR%, 1)                 'Abort any scans in progress.
		'CALL IO488("*CLS", DASADDR%, 1)                 'Clear status (clear errors)

		CALL INSTRERRORS(DASADDR%, 1)  'Clears and displays Agilent 34970A error queue.
		'Port 2, data = WORD2INIT
		LOCATE 10, 10: PRINT "Initializing Output Enable DIO lines.        "
		DIOCH02DATA% = WORD2INIT                      'Digital I/O initialization, &HFF
		DDATA$ = DIGOUT$ + STR$(DIOCH02DATA%) + ",(@" + STR$(RDEN.CH%) + ")"
		CALL IO488(DDATA$, DASADDR%, 1)         'Write configuration
		'CALL SHOWDIO(DIOCH02DATA%, 2, 1)
		CALL INSTRERRORS(DASADDR%, 1)  'Clears and displays Agilent 34970A error queue.

		CALL TSPECS(TSPEC$())                       'Sets up a string with the test specifications

		WIDTH , 43  'Change screen lines to 43
		CALL INSTRERRORS(DASADDR%, 1)  'Clears and displays Agilent 34970A error queue.
		CALL REPORT(STATUS$(), SN$, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), TSPEC$(), NUMDUT%, TTYPE%)'Prints test data on screen
		WIDTH , 25  'Change screen lines to 25
		ELAP2! = TIMER - TIME2!

		IF NOT LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
			'Turn internal SCM7B (RDEN isolator) supply back on if not SCM5B.
			CALL ENABLE(5, 1)
		END IF

		CALL INSTRERRORS(DASADDR%, 1)  'Clears and displays Agilent 34970A error queue.

		'=============================================================
		'BELOW: The following code writes the datasheet file(s),
		'stores the status for the tested module(s) in the work order
		'status file, and asks to print the datasheet file(s).
		'=============================================================
		KEY(10) OFF 'Deactivates F10 key
		CLS

		'Ask to print datasheet file(s)
		IF (TX% = 1) THEN
			'Only if text-file flag is on (Post-Encap and
			'Sealed Module tests)
			'
			'Determine if there are any datasheet files
			'(at least one good module)
			GOODMCOUNT% = 0 'Initialize to zero good modules
			FOR L% = 1 TO NUMDUT%
				IF (FAILS%(STATUS$(), L%) = 0) THEN
					'Only count modules that pass
					GOODMCOUNT% = GOODMCOUNT% + 1
				END IF
			NEXT

			'Only ask whether to print the datasheets if there is
			'at least one good module (and therefore at least one
			'datasheet file)
			IF GOODMCOUNT% > 0 THEN
			
				COLOR 15, 0, 0  'Clear screen to bright white on black background
				CLS
				LOCATE 8, 10: PRINT "Do you want to print the datasheet file(s)?"
				FOR L% = 1 TO NUMDUT%
					IF (FAILS%(STATUS$(), L%) = 0) THEN 'Only list modules that pass
						LOCALSN$ = SERNO$(L%)
						CALL GETDSFNAME(LOCALSN$, DSSNAME$, DSFNAME$)
						PRINT TAB(10); "Module # "; L%; " File name: "; DSFNAME$
					END IF
				NEXT
				PRINT TAB(10); "Either the 'Y' or 'N' must be pressed."
				DO  'Loop until the "Y" or "N" key is pressed
					A$ = INKEY$
					A$ = UCASE$(A$) 'Set key value to uppercase
				LOOP WHILE (A$ <> "N") AND (A$ <> "Y")

				IF (A$ = "Y") THEN
					'Print the datasheet file(s)
					FOR L% = 1 TO NUMDUT%
						LOCALSN$ = SERNO$(L%)
						IF (FAILS%(STATUS$(), L%) = 0) THEN
							'If the current module has not failed any tests
							CLS
							'Get datasheet search and file names from serial number
							CALL GETDSFNAME(LOCALSN$, DSSNAME$, DSFNAME$)
							LOCATE 8
							PRINT TAB(10); "Printing: " + DSFNAME$ + ", wait until printing is complete."
							SHELL "COPY C:\STAGE\" + DSFNAME$ + " LPT1 > NUL"       'Print datasheet file
							LPRINT CHR$(12) 'Form feed
							COLOR 15, 0, 0  'Bright white on black background
							PRINT
							PRINT TAB(10); "Has the: " + DSFNAME$ + " file finished printing?"
							COLOR 11, 0, 0  'Cyan on black background
							DUMKEY$ = WAITFORKEY("F", 10, 14, 0)    'Waits for "F" key press (display bright yellow on black)
						END IF
					NEXT
				END IF
			END IF

		END IF
		COLOR 11, 0, 0  'Cyan on black background
		KEY(10) ON  'Reactivates F10 key
		
		'=============================================================
		'ABOVE: The preceding code writes the datasheet file(s),
		'stores the status for the tested module(s) in the work order
		'status file, and asks to print the datasheet file(s).
		'=============================================================
		
		'*******************************************
	LOOP WHILE REPEAT$(SPECS.MODNAME, ELAP2!, TIME2!) <> "N" 'End of Complete Test loop

	'Added for work order status file (PWR 2014-05-08)
	IF ((TTYPE% = 3) OR (TTYPE% = 4)) THEN
		CLS
		LOCATE 5
		PRINT TAB(10); "Printing work order status file: "; WO$ + ".TXT"
		'Print the work order status file after an "N" entry for the
		'REPEAT$ function above (not testing more of same module type).
		'Using the serial number of channel 1 (there will always at least
		'be a module in channel 1) to generate the work order status file
		'name (within the WORKORDERPRINT sub).
		CALL WORKORDERPRINT(SERNO$(1))
		PRINT
		COLOR 15, 0, 0  'Bright white on black background
		PRINT
		PRINT TAB(10); "Has the work order status file finished printing?"
		COLOR 11, 0, 0  'Cyan on black background
		DUMKEY$ = WAITFORKEY("F", 10, 14, 0)    'Waits for "F" key press (display bright yellow on black)
		CLS
	END IF
END SUB

'****************************************
SUB CONFDUTIN (ONOFF%)
	'Configure the test head for HV power supply connection to the DUT inputs through the
	'HV test cable:
	'   ONOFF% = 1: Selects the HV power supply connection through the 33120A BNC to the DUT inputs.
	'               This is the non-inverting connection to the HV DUT input power supply.
	'   ONOFF% = 0: Selects the HV power supply connection through the 760A "pigtail connector".
	'               This is the inverting connection to the HV DUT input power supply (the power
	'               supply leads are swapped in the pigtail connector compared to the BNC connector).
	'
	IF ONOFF% = 1 THEN
		'CALL HVRELAY(6, 1) 'Disconnect the HP33120A BNC from the Fluke 760A BNC.
		'NOTE:  The RMS test program controlled both relays, but the HV test program only
		'needs to control the input-swap relay (relay 5, DIO bit 4 - see below), not the
		'BNC to BNC connect relay (relay 6, DIO bit 5 - see above), which is why the
		'relay 6 command above is commented out.
		CALL HVRELAY(5, 1)  'Connect the HP33120A BNC to the DUT inputs (rather than the 760A "pigtail" conn.)
	ELSE
		CALL HVRELAY(5, 0)  'Connect the the 760A "pigtail" conn. to the DUT inputs (rather than the 760A BNC)
		'NOTE:  The RMS test program controlled both relays, but the HV test program only
		'needs to control the input-swap relay (relay 5, DIO bit 4 - see above), not the
		'BNC to BNC connect relay (relay 6, DIO bit 5 - see below), which is why the
		'relay 6 command below is commented out.
		'CALL HVRELAY(6, 0) 'Connect the HP33120A BNC to the Fluke 760A BNC
	END IF

END SUB

'**********************************
SUB CONTINUE
	'Preserve cursor position
	x% = POS(0)
	Y% = CSRLIN
	
	'LOCATE 24, 10: PRINT "Press any key to continue               "
	LOCATE 23, 10: PRINT "Press any key to continue               "
	A$ = KEYBDIN$
	
	'Clear message
	'LOCATE 24, 10: PRINT "                                        "
	LOCATE 23, 10: PRINT "                                        "

	'Go back to preserved cursor position
	LOCATE Y%, x%
END SUB

'**********************************
SUB ENABLE (DUT%, ONOFF%)
	'Sub to set the DIO lines in the Agilent 34970A Data Acquisition
	'System (DAS) for the Output (Read) Enable (RDEN) lines for the
	'SCM5B modules.
	'
	'Parameters:
	'   DUT%:   Selects the DUT channel (1 through 4) for which
	'           the active-low read enable (RDEN) line is to be
	'           enabled (set low) or disabled (set high).
	'           Special value of 5 is to enable or disable the
	'           the supply for the SCM7B modules inside the
	'           testhead that are used to isolate the RDEN lines
	'           from the 34970A DIO lines to the SCM5B DUTs.
	'   ONOFF%: State of the controlled lines. For DUT = 1
	'           through 4 (the SCM5B RDEN lines:
	'           '0' = "On", '1' = "Off".
	'           For DUT = 5, the line to control the SCM7B
	'           supply:
	'           '1' = "On", '0' = "Off".
	'
	'Debug code.
	IF (DEBUGFLAG% = 1) THEN
		PRINT TAB(10); "...................................."
		PRINT TAB(10); "Initial values...."
		PRINT TAB(10); "ENABLE: DUT% = "; DUT%; " ONOFF% = "; ONOFF%
		PRINT TAB(10); "DIOCH02DATA% = "; DIOCH02DATA%
	END IF
	
	'Check for proper parameter values.
	IF ((DUT% < 0) OR (DUT% > 5)) THEN
		PRINT TAB(10); "........................"
		PRINT TAB(10); "Error in "; "ENABLE"; " sub!"
		PRINT TAB(10); "DUT value = "; DUT%
		PRINT TAB(10); "No changes made!"
		PRINT TAB(10); "........................"
		EXIT SUB
	END IF
	IF ((ONOFF% <> 0) AND (ONOFF% <> 1)) THEN
		PRINT TAB(10); "........................"
		PRINT TAB(10); "Error in "; "ENABLE"; " sub!"
		PRINT TAB(10); "On/Off value = "; ONOFF%
		PRINT TAB(10); "No changes made!"
		PRINT TAB(10); "........................"
		EXIT SUB
	END IF
	
	'Change word value based on parameters.
	BITWEIGHT% = 2 ^ (DUT% - 1)
	IF ONOFF% = 0 THEN
		'Enable output switch.
		'DIOCH02DATA% = DIOCH02DATA% - BITWEIGHT%
		DIOCH02DATA% = DIOCH02DATA% AND (NOT BITWEIGHT%)
	ELSE
		'Disable output switch.
		'DIOCH02DATA% = DIOCH02DATA% + BITWEIGHT%
		DIOCH02DATA% = DIOCH02DATA% OR BITWEIGHT%
	END IF
	
	'Set GPIB string and send to Agilent 34970A.
	DDATA$ = DIGOUT$ + STR$(DIOCH02DATA%) + ",(@" + STR$(RDEN.CH%) + ")"
	CALL IO488(DDATA$, DASADDR%, 1)         'Write configuration

	'Debug code.
	IF (DEBUGFLAG% = 1) THEN
		PRINT TAB(10); "...................................."
		PRINT TAB(10); "Final values...."
		PRINT TAB(10); "BITWEIGHT% =   "; BITWEIGHT%
		PRINT TAB(10); "DIOCH02DATA% = "; DIOCH02DATA%
		PRINT TAB(10); "DDATA$: "; DDATA$
		PRINT TAB(10); "...................................."
		CALL CONTINUE
	END IF

END SUB

SUB ENDCFG
	'Sub to perform module-input configuration after testing
	'
	CALL SETDPS(DPSVINADDR%, 0) 'Set input voltage (at ext. supply) to 0V
	CALL SETDPS(DPSVINADDR2%, 0)
END SUB

'*************************************
FUNCTION FAILS% (STATUS$(), L%)

	FAILS% = 0

	'FOR x% = 1 TO 17
	FOR x% = 1 TO MAXSTATUSINDEX
		IF LEFT$(STATUS$(x%, L%), 1) = "F" THEN     'Tests for failed tests
			FAILS% = 1
		END IF
	NEXT

END FUNCTION

SUB FINISHSUB
	'Sub to run code at "FINISH" label (usually after F10 key is pressed).
	'
	CLS
	LOCATE 10, 10: PRINT "Resetting Data Acquisition System via GPIB. "
	
	CALL IO488("*RST", DASADDR%, 1)
	CALL IO488("ABOR", DASADDR%, 1)                 'Abort any scans in progress.
	CALL IO488("*CLS", DASADDR%, 1)                 'Clear status (clear errors)
	
	LOCATE 10, 10: PRINT SPC(70);
	LOCATE 10, 10: PRINT "Resetting Function Generator via GPIB.      "
		CALL IO488("*RST", GENADDR%, 1)
	LOCATE 10, 10: PRINT SPC(70);
	LOCATE 10, 10: PRINT "Initializing Data Acquisition System.       "
		CALL INIT488(DASADDR%)                  'clear bus
	LOCATE 10, 10: PRINT SPC(70);
	LOCATE 10, 10: PRINT "Set DUT input supply to 0V.                    "
	CALL SETDPS(DPSVINADDR%, 0) 'Set input voltage (at ext. supply) to 0V
	CALL SETDPS(DPSVINADDR2%, 0)
	LOCATE 10, 10: PRINT SPC(70);
	LOCATE 10, 10: PRINT "Write Data Acquisition System configuration."; "."
	'Port 2, data = WORD2INIT
	DIOCH02DATA% = WORD2INIT                      'Digital I/O initialization, &HFF
	DDATA$ = DIGOUT$ + STR$(DIOCH02DATA%) + ",(@" + STR$(RDEN.CH%) + ")"
	CALL IO488(DDATA$, DASADDR%, 1)         'Write configuration
	'CALL SHOWDIO(DIOCH02DATA%, 2, 1)
						'Port 1, data = 8
	LOCATE 10, 10: PRINT SPC(70);
	LOCATE 10, 10: PRINT "Disconnect HP33120A as input to HP760A.     "
	CALL HVRELAY(6, 1)                       'Disconnect HP33120A as input to Fluke 760A
	LOCATE 10, 10: PRINT SPC(70);
	LOCATE 10, 10: PRINT "Select HP33120A as D.U.T. input.            "
	CALL HVRELAY(5, 1)                      'Select HP33120A as D.U.T. input
	LOCATE 10, 10: PRINT SPC(70);
	LOCATE 10, 10: PRINT "Set Vsupply to zero.                        "
	SP1! = SETSCM5BPWR!(.01)                        'Set Vsupply to zero
	LOCATE 10, 10: PRINT SPC(70);
	LOCATE 10, 10: PRINT "Turn off loop power.                        "
	SP2$ = POWERIO$(DPSADDR%, SUPPLYOFF$)           'Turn off loop power
	LOCATE 10, 10: PRINT SPC(70);
	LOCATE 10, 10: PRINT "Return to local mode.                       "
	SP2$ = POWERIO$(DPSADDR%, "LOC")                'Return to local mode

	CHAIN "C:\ATE\MENUX"
END SUB

'************************************
SUB FOOTER (STATUS$(), L%)
	'Sub to create footer (if there are no fails). The footer be sent to two
	'places (screen and printer), so when updating remember to make any
	'changes to both the "PRINT" and "LPRINT" sections.
	'
	'NOTE:  Currently, the footer is only printed to the printer, not the screen.
	'
	IF FAILS%(STATUS$(), L%) = 0 THEN
		'If module did not fail any tests
	   
		'Send to screen
		'PRINT TAB(5); "240 VAC Withstand"; TAB(71); "PASS"
		'PRINT TAB(5); "Hi-Pot "; TAB(71); "PASS"
		'PRINT TAB(5);
		'FOR x = 5 TO 75
		'   PRINT "_";
		'NEXT x
		'PRINT TAB(35); "Check List"
		'PRINT
		'
		'IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" OR LEFT$(SPECS.MODNAME, 2) = "8B" THEN
		'   PRINT TAB(5); "Module Appearance:      _____"; TAB(45); "Mounting Screw:           _____"
		'   PRINT
		'   PRINT TAB(5); "Pins Straight:          _____"; TAB(45); "Module Header:            _____"
		'   PRINT
		'END IF
		'
		'PRINT TAB(5); "Tested by:      _____________"; TAB(45); "QC:             _______________"
		'PRINT
		'PRINT TAB(5); "It is hereby certified that the above product is in conformance with"
		'PRINT TAB(5); "all requirements to the extent specified.  This product is not"
		'PRINT TAB(5); "authorized or warranted for use in life support devices and/or systems."
		'PRINT
		'PRINT TAB(5); "* NIST traceable calibration certificates support Measured Value data."
		'PRINT TAB(5); "  Calibration services are available through ANSI/NCSL Z540-1 and"
		'PRINT TAB(5); "  ISO Guide 25 Certified Metrology Labs."
	  
		'Send to printer
		IF PON% = 1 THEN
			LPRINT TAB(5); "240 VAC Withstand"; TAB(71); "PASS"
			LPRINT TAB(5); "Hi-Pot "; TAB(71); "PASS"
		  
			LPRINT TAB(5);
			FOR x = 5 TO 75
				LPRINT "_";
			NEXT x
			LPRINT TAB(35); "Check List"
			LPRINT
			
			IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" OR LEFT$(SPECS.MODNAME, 2) = "8B" THEN
				LPRINT TAB(5); "Module Appearance:      _____"; TAB(45); "Mounting Screw:           _____"
				LPRINT
				LPRINT TAB(5); "Pins Straight:          _____"; TAB(45); "Module Header:            _____"
				LPRINT
			END IF
			
			LPRINT TAB(5); "Tested by:      _____________"; TAB(45); "QC:             _______________"
			LPRINT
			LPRINT TAB(5); "It is hereby certified that the above product is in conformance with"
			LPRINT TAB(5); "all requirements to the extent specified.  This product is not"
			LPRINT TAB(5); "authorized or warranted for use in life support devices and/or systems."
			LPRINT
			LPRINT TAB(5); "* NIST traceable calibration certificates support Measured Value data."
			LPRINT TAB(5); "  Calibration services are available through ANSI/NCSL Z540-1 and"
			LPRINT TAB(5); "  ISO Guide 25 Certified Metrology Labs."
		END IF
	END IF
	IF PON% = 1 THEN LPRINT CHR$(12)    'Send form feed to printer (regardless of module test status)
END SUB

'************************************
SUB FUNCTEST (STATUS$(), CAL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, TTYPE%, TSPEC$(), SERNO$()) 'Routines for functional test
	'Sub to run a short set of tests, looping once each pass (and individually through each test channel
	'for each test) to determine if the main module circuits are functional.
	'
	NOMVS! = SPECS.NOMVS
	MAXOUT! = SPECS.MAXOUT                      'V or A
	WAVESHPCAL$ = "FUNC:SHAP " + LEFT$(SPECS.WAVESHPCAL$, 3)
	FINCAL! = SPECS.FINCAL
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE
	LOOPVNOM! = SPECS.LOOPVNOM + MAXOUT! * NOISEFILTERR!

	DIM OSERR2!(5)
	LOOPCYC% = 0

	CALL INSTALLDUT(NUMDUT%)    'Get number of modules installed
	IF (PON% = 1) THEN
		CALL CHECKRESOURCES(0)      'Check for ability to write to printer.
	END IF
	
	DO
		LOOPCYC% = LOOPCYC% + 1
		TIME2! = TIMER
		IF LOOPCYC% > 1 THEN
			CALL INSTALLDUT(NUMDUT%)
		END IF

		IF LOOPCYC% = 1 THEN
			IF OUTSIGTYPE$ = "CURRENT" THEN
				CALL SETOUTLOAD(IOUTSEN1!, 4) 'Set current output sense resistor
				FOR L% = 1 TO 4
					IOUTSEN1.MEAS!(L%) = IOUTSEN11.MEAS!(L%)
				NEXT
			ELSE
				CALL SETOUTLOAD(1000000!, 4)  'Remove current output sense resistor
				FOR L% = 1 TO 4
					IOUTSEN1.MEAS!(L%) = 1
				NEXT
			END IF
		END IF

		'FOR x% = 1 TO 17
		FOR x% = 1 TO MAXSTATUSINDEX
			FOR L% = 1 TO NUMDUT%
				STATUS$(x%, L%) = ""    'Clear test result array
			NEXT
		NEXT

		CONFLAG% = 0

		IF NOT LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
			'Turn off internal SCM7B (RDEN isolator) supply if not SCM5B.
			CALL ENABLE(5, 0)
		END IF

		IF OUTSIGTYPE$ <> "CURRENT" THEN
			CALL SETOUTLOAD(IOUTSEN3!, 4)  ' should be IF OUTSIGTYPE$ = "VOLTAGE"
		END IF
		
		IF NOMVS! = 5 THEN                          'SCM5B
			CALL SETSWITCH(VSSOURCE.CH%, 0)         'D.U.T. Power is test head VCVS
			SP! = SETSCM5BPWR!(NOMVS!)              'Set Vsupply to nominal value

			IF SP! = -1 THEN EXIT SUB               'High supply current

			IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
				FOR L% = 1 TO NUMDUT%
					CALL ENABLE(L%, 0)                  'Enable output switch
				NEXT
			END IF

			IF OUTSIGTYPE$ = "CURRENT" THEN
				CALL SETDPS(DPSADDR%, LOOPVNOM!)    'Set Vloop to nominal value
			END IF
		ELSE    'IF NOMVS! = 24 THEN                ' nom volts != 5v i.e. DSCA
				CALL SETSWITCH(VSSOURCE.CH%, 1)         'D.U.T. Power is Kepco DPS
				CALL INITPS(DPSADDR%, SPECS.ISMAX! * PSILIMIT! * 4, OVERV.DSCA!)
				CALL SETDPS(DPSADDR%, NOMVS!)           'Set Vsupply to nominal value
		END IF

		FOR FTEST% = 1 TO 3
			SELECT CASE FTEST%
				CASE 1
					CALL SUPPLYI(NUMDUT%, STATUS$())
					FOR L% = 1 TO NUMDUT%
						IF LEFT$(STATUS$(1, NUMDUT%), 4) = "FAIL" THEN 'Check supply current
							CONFLAG% = 1                        'Sets exit flag
						END IF
					NEXT
				CASE 2
					CALL OFFSETCAL(CAL%, NUMDUT%, STATUS$())
					FOR L% = 1 TO NUMDUT%
						IF LEFT$(STATUS$(13, NUMDUT%), 4) = "FAIL" THEN
							CONFLAG% = 1
						END IF
					NEXT
					CALL GAINCAL(CAL%, 0, 1, OSERR2!(), NUMDUT%, STATUS$())
					FOR L% = 1 TO NUMDUT%
						IF LEFT$(STATUS$(14, NUMDUT%), 4) = "FAIL" THEN
							CONFLAG% = 1
						END IF
					NEXT
				CASE 3
					IF (LEFT$(SPECS.MODNAME, 5) = "SCM5B") THEN 'SCM5B
						CALL OUTSWITCH(NUMDUT%, STATUS$())      'SCM5B output switch operation
					END IF
					FOR L% = 1 TO NUMDUT%
						IF LEFT$(STATUS$(2, NUMDUT%), 4) = "FAIL" THEN
							CONFLAG% = 1
						END IF
					NEXT
			END SELECT
			IF CONFLAG% <> 0 THEN EXIT FOR
		NEXT

		IF NOMVS! = 5 THEN                          'SCM5B
			SP! = SETSCM5BPWR!(.01)                 'Set Vsupply to zero
			IF OUTSIGTYPE$ = "CURRENT" THEN
				SP$ = POWERIO$(DPSADDR%, SUPPLYOFF$)    'Disable power supply
			END IF
			IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
				FOR L% = 1 TO NUMDUT%
					CALL ENABLE(L%, 1)                  'Disable output switch
				NEXT
			END IF
		ELSE    'IF NOMVS! = 24 THEN        ' nom volts != 5v i.e. DSCA
			SP$ = POWERIO$(DPSADDR%, SUPPLYOFF$)    'Disable power supply
		END IF

		ELAP2! = TIMER - TIME2!

		IF NOT LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
			'Turn internal SCM7B (RDEN isolator) supply back on if not SCM5B.
			CALL ENABLE(5, 1)
		END IF

		CALL TSPECS(TSPEC$())                       'Sets up a string with the test specifications

		'PWR 2014-09-11:    Lines below added to display test status
		'                   at the end of the functional test.
		WIDTH , 43  'Change screen lines to 43
		CALL INSTRERRORS(DASADDR%, 1)  'Clears and displays Agilent 34970A error queue.
		CALL REPORT(STATUS$(), SN$, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), TSPEC$(), NUMDUT%, TTYPE%)'Prints test data on screen
		WIDTH , 25  'Change screen lines to 25
		
	LOOP WHILE REPEAT$(SPECS.MODNAME, ELAP2!, TIME2!) <> "N"        'Repeat for another set of modules
		  
END SUB

'********************************
 SUB GAINCAL (CAL%, AMPL!, INTERACT!, OSERR2!(), NUMDUT%, STATUS$())
	'Calibrate module gain
	'Inputs:        calibration flag
	'       CAL%    0 = calibrate module; high accuracy input, loop until calibrated,
	'                   narrow error tolerance, AMPL! = 0, use SPECS.GNCALIN for DUT input
	'               1 = measure once and exit, high accuracy input,
	'                   narrow error tolerance, use AMPL! for DUT input.
	'               2 = functional test; coarse input setting, wide error tolerance,
	'                   measure once and exit, AMPL! = 0, use SPECS.GNCALIN for DUT input
	'               3 = Use HP33120A direct to DUT, bypassing Fluke 760A
	'                   Use AMPL! for DUT input, measure once and exit
	'       AMPL!       Signal amplitude to be used for module input
	'       INTERACT!   Calibration interaction factor
	'       OSERR2!(n)  Measured offset error
	'       NUMDUT% = number of Devices Under Test
	'
	'Outputs        STATUS$(14, n)   array of results
	'
	MINOUT! = SPECS.MINOUT                  'V or A
	MAXOUT! = SPECS.MAXOUT
	INITTOL! = 8                            'Uncalibrated gain tolerance (%)
	CALTOL! = SPECS.CALTOL                  'Calibration tolerance (%)
	FINCAL! = SPECS.FINCAL                  'Input wave frequency (Hz)
	FINEXTMAX! = SPECS.FINEXTMAX
	CALGN! = SPECS.GNCALPT / 100            '
	ORANGE! = MAXOUT! - MINOUT!             'Output range (V or A)
	NOMVS! = SPECS.NOMVS!
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE
  
	CALSPAN! = ORANGE!                      'Adjustment range is +/- x% of +f.s.
   
	IF CAL% = 1 OR CAL% = 3 THEN            'Special input required for cal measurement
		GNCALIN! = AMPL!
	ELSE
		GNCALIN! = SPECS.GNCALIN            'input for gain calibration from database
	END IF

	IF (CAL% = 2) OR (TTYPE% = 1) THEN
		CLS
		TESTTITLE$ = "Gain Calibration"
		CALL HEADERB(TESTTITLE$, 0)
		GERROR! = INITTOL!                  'Gain tolerance for func. test (%)
		TOL! = .0001 * ORANGE!              'Measurement tolerance, 1 pass test
	ELSE
		IF CAL% = 0 THEN
			CLS
			TESTTITLE$ = "Gain Calibration"
			CALL HEADERB(TESTTITLE$, 0)
			CALL MODOUTLINE
			LOCATE 7
			TB1% = 26
			TB2% = 31
			PRINT TAB(TB1%); "Refer to label on board for";
			PRINT TAB(TB2%); "gain potentiometer";
		END IF
		GERROR! = CALTOL!                   'Gain calibration tolerance (%)
		TOL! = 0!                           'Measurement tolerance, continuous test
	END IF
		  
	OUTCALC! = MAXOUT!                      'seed value for 1st pass

	TIME1! = TIMER
	FIRSTTIMETHRU% = 1

	FOR L% = 1 TO NUMDUT%
		CONREADS% = 0
		LOCATE 1
		IF L% <> 1 AND CAL% <> 1 AND CAL% <> 3 THEN
			CALL HEADERB(TESTTITLE$, 0)
		END IF
		
		'Check if module previously failed supply current
		'(removed from test head), offset cal or gain cal
		'(not functional) or output switch test (not functional)
		IF LEFT$(STATUS$(1, L%), 4) <> "FAIL" AND LEFT$(STATUS$(2, L%), 4) <> "FAIL" AND LEFT$(STATUS$(13, L%), 4) <> "FAIL" AND LEFT$(STATUS$(14, L%), 4) <> "FAIL" THEN
		
			LOCATE 10, 25: PRINT "TESTING DEVICE IN CHANNEL #"; L%

			MAXINMEAS! = SETDUTIN!(GNCALIN!)
			
			DO
				IF FIRSTTIMETHRU% = 1 OR TIMER - TIME1! > 30 THEN
					LOCATE 12, 10
					PRINT TAB(10); "Measuring input.  Please wait...          "
					MAXINMEAS! = SETDUTIN!(GNCALIN!)
					TIME1! = TIMER
				END IF

				LOCATE 12, 10
				PRINT "Gain Error =  ";
				PRINT SPC(30);
				
				IF OUTSIGTYPE$ = "CURRENT" THEN
					CH% = IOUTSENDUT1SEN.CH%
				END IF

				IF OUTSIGTYPE$ = "VOLTAGE" THEN
					IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
						CH% = VOUTDUT1.CH%
					ELSE
						CH% = IOUTSENDUT1SOUR.CH%
					END IF
				END IF

				CALL DVMCONF(CH% + L% - 1, VDC$, "AUTO", 0, "", 0)
				CALL DVMSENS(CH% + L% - 1, VDC$, INTTIME$, "", 2)   '6 1/2 digits, 21 bit resolution
				CALL PAUSE(.1)

				IF INTERACT! <> 1 THEN
					PFSMEAS! = GETREADING! / IOUTSEN1.MEAS!(L%)  'CALOS! is included in OSERR2!()
					OUTCALC! = PFSMEAS! - (1 / (1 - INTERACT!)) * (PFSMEAS! - MODULEOUT!(MAXINMEAS!) - ORANGE! * OSERR2!(L%) / 100!)
				ELSE
					OUTCALC! = MODULEOUT!(MAXINMEAS!) + CALGN! * ORANGE!
				END IF

				DO
					ERROROUT! = (GETREADING! / IOUTSEN1.MEAS!(L%) - OUTCALC!) / CALSPAN! * 100! 'Error (%)
					LOCATE 12, 24
					PRINT USING "+###.### %"; ERROROUT!

					LOCATE 15, 10
					IF CAL% > 0 THEN                'Non-calibration mode
						CONREADS% = 5
					ELSEIF ABS(ERROROUT!) > INITTOL! * 1.5 THEN     'Circuit error, exit
						CONREADS% = 5
					ELSEIF ABS(ERROROUT!) < GERROR! THEN
						SOUND 400, .5
						PRINT "Stop turning gain potentiometer          "
						CONREADS% = CONREADS% + 1
					ELSEIF ERROROUT! < 0 THEN
						PRINT "Turn gain potentiometer clockwise        "
						CONREADS% = 0
					ELSE
						PRINT "Turn gain potentiometer counter-clockwise"
						CONREADS% = 0
					END IF

					LOCATE 20, 10
					A$ = INKEY$
					IF UCASE$(A$) = "C" THEN
						CONREADS% = 5
					END IF
					CALL PAUSE(.3)                          'Slow down loop
					IF TIMER - TIME1! > 30 THEN EXIT DO
				LOOP WHILE CONREADS% < 5
			LOOP WHILE CONREADS% < 5

			IF CAL% = 0 OR CAL% = 2 THEN
				IF (TTYPE% = 1) THEN
					'Functional test.
					DIG$ = "3"  'Display/print result to # of decimal places.
				ELSE
					'Not functional test.
					DIG$ = "5"  'Flag: do not display/print result.
				END IF
				IF ABS(ERROROUT!) <= GERROR! THEN
					GN$ = "PASS"
				ELSE
					GN$ = "FAIL"
					'Display results if test failed.
					DIG$ = "3"  'Display/print result to # of decimal places.
					SOUND 1000, .5
				END IF
				
				'Set DUT input voltage power supply to 0V (PWR 2014-10-08)
				CALL SETDPS(DPSVINADDR%, 0!)
				CALL SETDPS(DPSVINADDR2%, 0)
				'LOCATE 15, 10: PRINT "MODULE #"; L%; " Status: "; GN$;
				LOCATE 16, 10   'Added
				PRINT SPC(30);
				PRINT TAB(10); "Gain calibration error is";
				PRINT TAB(50); USING " +###.### %"; ERROROUT!
				PRINT TAB(10); "Max. gain calibration error is";
				PRINT TAB(50); USING "+/-##.### %"; GERROR!
				CALL FAILSTATUS(L%, GN$, 15, 10, "Status: ", 20)        'Print test status to screen
			ELSE
				GN$ = "PASS"
				DIG$ = "5"                  'Flag.  Don't print result
			END IF

			FIRSTTIMETHRU% = FIRSTTIMETHRU% + 1
			STATUS$(14, L%) = GN$ + STR$(ERROROUT!) + DIG$
		END IF  'End if previous set of four tests passed.

		IF L% < NUMDUT% THEN           'Prevent to assign a not valid serial number
			SN$ = SERNO$(L% + 1)       'Use the next serial number on the array
		END IF
		CALL PAUSE(1!)
		IF L% <> NUMDUT% THEN
			LOCATE 15, 10
			PRINT SPC(55);
			LOCATE 16, 10
			PRINT SPC(55);
			LOCATE 17, 10
			PRINT SPC(55);
			PRINT
		END IF
		CLS
	NEXT

	SN$ = SERNO$(1)

	CALL SETDPS(DPSVINADDR%, 0) 'Set input voltage (at ext. supply) to 0V
	CALL SETDPS(DPSVINADDR2%, 0)
END SUB

SUB GETADD
	'Retrieve test system component addresses from address file.
	'
	OPEN "C:\ATE\ADDR\HVIN.ADR" FOR RANDOM AS #3 LEN = 12
	FIELD #3, 2 AS SUPPLYPORT$, 2 AS POWERSPLY$, 2 AS PS1ADDR$, 2 AS PS2ADDR$, 2 AS DASADDRESS$, 2 AS GENADDRESS$
	GET #3

	PSPORT% = VAL(SUPPLYPORT$)
	DPSADDR% = VAL(POWERSPLY$)
	DPSVINADDR% = VAL(PS1ADDR$)
	DPSVINADDR2% = VAL(PS2ADDR$)
	DASADDR% = VAL(DASADDRESS$)
	GENADDR% = VAL(GENADDRESS$)
	CLOSE #3
	REM PRINT PSORT%, DPSADDR%, DPSVINADDR%, DPSVINADDR2%, DASADDR%, GENADDR%
	REM CALL CONTINUE
	REM DPSVINADDR% = DPSADDR% + 1   'Address of DUT input power supply
	REM DPSVINADDR2% = DPSADDR% + 2' Address of 2nd DUT input power supply
END SUB

SUB GETNEXTSN (TIME2!, SERNO$(), NUMDUT%)
	'Sub to the next set of serial numbers after at least one
	'pass through testing
	'
	PRENUMDUT% = NUMDUT%                    'Number of units just tested
	LASTSN$ = SERNO$(PRENUMDUT%)
	CALL INSTALLDUT(NUMDUT%)                'Gets number of modules to test
	DO  'Loop until serial numbers are confirmed good
		SERNO$(1) = SNMENU$(1, LASTSN$, 0)
		FOR I% = 2 TO NUMDUT%
			LOCALSN$ = SERNO$(I% - 1)   'Get serial number of module in previous test channel
			SERNO$(I%) = SNMENU$(I%, LOCALSN$, 1)   '
		NEXT

		'Display the serial numbers entered.
		CLS
		LOCATE 5
		IF (NUMDUT% > 1) THEN
			PRINT TAB(5); "The following serial numbers were entered:"
		ELSE
			PRINT TAB(5); "The following serial number was entered:"
		END IF
		FOR I% = 1 TO NUMDUT%
			PRINT TAB(5); "Test channel # "; I%; ": Serial number = "; SERNO$(I%)
		NEXT
		TIME2! = TIMER
		SN$ = SERNO$(1) 'Set initial serial number
		
		'Check to see if there are any duplicate serial numbers
		IF (ISDUPLICATESN%(SERNO$, NUMDUT%) = 1) THEN
			'There are duplicate serial numbers
			PRINT
			PRINT
			COLOR 28, 0, 0  'Flashing light red
			PRINT TAB(6); "DUPLICATE SERIAL NUMBERS WERE SET!"
			COLOR 11, 0, 0  'Cyan on black background
			PRINT
			PRINT
			PRINT TAB(5); "Retry entering the serial numbers after"
			PRINT TAB(5); "pressing the key listed below."
			PRINT
			BEEP
			DUMKEY$ = WAITFORKEY("S", 10, 14, 0)    'Waits for "S" key press (display bright yellow on black)
		ELSE
			'There are no duplicate serial numbers - ask if the serial numbers are good
			PRINT
			PRINT
			PRINT TAB(10); "Are the serial numbers valid?"
			PRINT
			PRINT TAB(10); "Must enter 'Y' or 'N' (upper or lower case)."
			PRINT
			PRINT
			'Get keyboard entry (must be 'Y' or 'N')
			DO
				ANS2$ = INKEY$
				ANS2$ = UCASE$(ANS2$)
			LOOP WHILE (ANS2$ <> "N") AND (ANS2$ <> "Y")
			IF ANS2$ = "N" THEN
				PRINT
				PRINT TAB(5); "Retry entering the serial numbers after"
				PRINT TAB(5); "pressing the key listed below."
				PRINT ;
				DUMKEY$ = WAITFORKEY("S", 10, 14, 0)    'Waits for "S" key press (display bright yellow on black)
			END IF
		END IF
	LOOP WHILE (ANS2$ <> "Y")

	'Set initial serial number and proceed on to testing
	SN$ = SERNO$(1) 'Set initial serial number
	'Wait to acknowledge serial number(s)
	PRINT
	PRINT
	PRINT
	PRINT
	PRINT TAB(5); "Ready to start testing...."
	DUMKEY$ = WAITFORKEY("T", 10, 14, 0)    'Waits for "T" key press (display bright yellow on black)
	PRINT
	PRINT TAB(5); "Testing...."
	TIME2! = TIMER
END SUB

FUNCTION GETPSID%
CLS
LOCATE 3
PRINT TAB(10); "Identifying power supplies connected to test system"
PRINT
'****** First, assume KEPCO DPS125 for PSMODEL$ string assignment.
'        PSMODEL$ = "DPS125"

'****** Assign corresponding address obtained from address file dependent
'****** on if the Power supply is DPS125 or ABC125.

				DPSPSFLAG! = 0!

'****** Check for High Voltage Power Supply

		VINILIMIT! = 125!   'Set DUT input power supply voltage limit to 125V
		VINOVERV! = .05     'Set DUT input power supply current limit to 50mA (0.050A)
	   
		PRINT TAB(10); "KEPCO DPS125 High-Voltage Input: ";
		DPSVIN$ = POWERIO$(DPSVINADDR%, "ID")

		IF DPSVIN$ = "KEPCO DPS 125-0.5M" THEN
				VINADDR% = DPSVINADDR%
				PRINT TAB(45); "Yes!"
				PRINT
				PSMODEL$ = "DPS125"
				CALL INITPS(DPSVINADDR%, VINILIMIT!, VINOVERV!)
				CALL INITPS(DPSVINADDR2%, VINILIMIT!, VINOVERV!)
				DPSVINFLAG! = 1!
		ELSE
				PRINT TAB(45); "Not present"
				DPSVINFLAG! = 0!
				VINADDR% = 0!
		END IF

		IF DPSPSFLAG! = 0! AND DPSVINFLAG! = 0! THEN
				  
				PSMODEL$ = "ABC125"
				PRINT TAB(10); "KEPCO ABC-125 High-Voltage Input: ";
				'ABCVIN$ = READGPIB$(ABCVINADDR%, "*IDN?")
						   IF LEFT$(ABCVIN$, 14) = "KEPCO,ABC-1251" THEN
								VINADDR% = ABCVINADDR%
								CALL INITPS(ABCVINADDR%, VINILIMIT!, VINOVERV!)
								PRINT TAB(45); "Yes!"
								PRINT
						   ELSE
								PRINT TAB(45); "Not present"
								PRINT
						   END IF
		END IF
						
				IF PSADDR% = 0! AND VINADDR% = 0! THEN
						PRINT TAB(15); ">>>>>>>> No Power Supplies are connected <<<<<<<<"
						'CALL CONTINUE
				END IF
		 
		GETPSID% = 99      'This has yet to be utilized.  At this time there is
						   'no requirement to pass anything back to function call
END FUNCTION

'*****************************************
SUB GETSN (SN$)
	'Sub to get work order number and dash number to generate serial number for module
	'
	'Get work order number
	WO$ = GETWO$    'Get work order number from function

	'Get dash number
	DS$ = GETDS$(0, SN$)    'Get (starting) dash number from function
	
	'Create serial number from work order number and dash number
	SN$ = WO$ + "-" + DS$
	'CALL CONTINUE
	
END SUB

SUB GETSPECS (NUMDUT%)
	'Sub to get the module inputs, outputs and limits from the
	'module database
	'
	DIM POINTER%(1000)

	TESTV! = 5  'Test current to measure sense resistor (50mADC = 5VDC/100ohm)

	CALL SORTDB(ENDFLAG%)
	IF ENDFLAG% = 1 THEN
		SPECS.MODNAME = "EXIT"
		EXIT SUB
	END IF

	CLS
	LOCATE , 30
	PRINT "Model Selection Menu"
	PRINT TAB(30); "--------------------"
	PRINT

	YINIT% = CSRLIN                 'Initialize starting rows

	OPEN "C:\ATE\HVDATA\HVSORT.DAT" FOR RANDOM AS #2 LEN = LEN(SORTDATA1)

	DO
		'Loop through database program limits
		I% = I% + 1
		GET #2, I%, SORTDATA1
		IF SORTDATA1.RECNUM <> -1 THEN NUMRECORD! = NUMRECORD! + 1
	LOOP WHILE SORTDATA1.RECNUM <> -1

	SCRNCTR% = 40                   'display center
	NUMCHAR% = 19                   '13 char + 4 char for # + 2 spaces
	NUMLINES! = 19                  '# of lines for model display below header


	'Set number of columns for the displayed model menu, given
	'that the model # length is 20 characters max and there
	'are a maximum of 3 columns per screen:
	'3 columns x 26 char = 78 spaces
	NUMCOLUMNS! = 1 + INT(NUMRECORD! / NUMLINES!)

	I% = 1  'Initialize
	FOR C% = 0 TO NUMCOLUMNS! - 1
		Y% = YINIT%
		TB% = SCRNCTR% - NUMCHAR% / 2 * NUMCOLUMNS! + NUMCHAR% * C%
		DO
			GET #2, I%, SORTDATA1
			IF SORTDATA1.RECNUM <> -1 THEN
				POINTER%(I%) = SORTDATA1.RECNUM
				LOCATE Y%, TB%
				PRINT USING "##.) &"; I%; SORTDATA1.MODNAME
				I% = I% + 1
				Y% = Y% + 1
			END IF
		LOOP WHILE SORTDATA1.RECNUM <> -1 AND Y% - YINIT% < NUMLINES!
	NEXT C%

	LOCATE Y%, TB%
	PRINT USING "##.) Exit"; I%

	CLOSE #2

	DO
		LOCATE 23, SCRNCTR% - NUMCHAR% / 2 * NUMCOLUMNS!
		PRINT "Enter Selection ";
		INPUT SEL%
	LOOP WHILE SEL% < 1 OR SEL% > I%

	IF SEL% = I% THEN
		SPECS.MODNAME = "EXIT"
	ELSE
		OPEN "C:\ATE\HVDATA\HVIN.DAT" FOR RANDOM AS #1 LEN = LEN(SPECS)
		GET #1, POINTER%(SEL%), SPECS
		CLOSE #1

		'CALL INSTALLDUT(NUMDUT%)

		IINSEN1.MEAS! = 1
	END IF

	SEL% = POINTER%(SEL%)       'pass back to main code for use in SAVEDATA

END SUB

SUB HEADERA (SN$)
	'Sub to print datasheet header section to printer if print flag is "on"
	'
   IF PON% = 1 THEN
		LPRINT TAB(5); "DATAFORTH CORPORATION"; TAB(51); "Phone: (520) 741-1404"
		LPRINT TAB(5); "3331 E. Hemisphere Loop"; TAB(51); "Fax:   (520) 741-0762"
		LPRINT TAB(5); "Tucson, AZ  85706  USA"; TAB(51); "email: info@dataforth.com"
		LPRINT
		LPRINT TAB(33); "TEST DATA SHEET"
		LPRINT TAB(5);
		FOR x = 5 TO 75
				LPRINT "~";
		NEXT
		LOCATE 8
		LPRINT TAB(5); "Date:  "; DATE$
		LPRINT TAB(5); "Model: "; SPECS.MODNAME
		LPRINT TAB(5); "SN:    "; TAB(12); SN$
		LPRINT
	END IF

END SUB

'***************************************
SUB HEADERB (TESTTITLE$, L%)
	'Sub to display test title, model under test, and SN at top of the screen.
	'
	IF L% = 0 THEN
		TITLEN = LEN(TESTTITLE$) + LEN(SPECS.MODNAME)
		PRINT TAB(40 - TITLEN / 2); SPECS.MODNAME; " "; TESTTITLE$;
	ELSE
		TITLEN = LEN(TESTTITLE$)
		PRINT TAB(40 - TITLEN / 2); TESTTITLE$;
	END IF

	IF SN$ <> "" AND LEFT$(TESTTITLE$, 6) <> "Fluke 760A" THEN
		PRINT TAB(66); "SN: "; SN$          'print SN if available
	ELSE
		PRINT
	END IF

	LOCATE , 40 - TITLEN / 2
	FOR L% = 1 TO TITLEN + 1                'underline test title
		PRINT "-";
	NEXT
	PRINT
END SUB

'************************************
SUB HVRELAY (RELAY%, ONOFF%)
	'Sub to set the DIO lines in the Agilent 34970A Data Acquisition
	'System (DAS) for the high voltage/high current relays in the
	'testhead.
	'
	'Parameters:
	'   RELAY%: Selects the RELAY (1 through 6) that is to
	'           be turned on or off.
	'   ONOFF%: New state of the specified relay:
	'           '1' = "On", '0' = "Off".
	'
	'Debug code.
	IF (DEBUGFLAG% = 1) THEN
		PRINT TAB(10); "...................................."
		PRINT TAB(10); "Initial values...."
		PRINT TAB(10); "ENABLE: RELAY% = "; RELAY%; " ONOFF% = "; ONOFF%
		PRINT TAB(10); "DIOCH01DATA% = "; DIOCH01DATA%
	END IF
	
	'Check for proper parameter values.
	IF ((RELAY% < 1) OR (RELAY% > 6)) THEN
		PRINT TAB(10); "........................"
		PRINT TAB(10); "Error in "; "HVRELAY"; " sub!"
		PRINT TAB(10); "Relay number = "; RELAY%
		PRINT TAB(10); "No changes made!"
		PRINT TAB(10); "........................"
		EXIT SUB
	END IF
	IF ((ONOFF% <> 0) AND (ONOFF% <> 1)) THEN
		PRINT TAB(10); "........................"
		PRINT TAB(10); "Error in "; "HVRELAY"; " sub!"
		PRINT TAB(10); "On/Off value = "; ONOFF%
		PRINT TAB(10); "No changes made!"
		PRINT TAB(10); "........................"
		EXIT SUB
	END IF

	'Change word value based on parameters.
	BITWEIGHT% = 2 ^ (RELAY% - 1)
	IF ONOFF% = 1 THEN
		'Disable relay.
		'DIOCH01DATA% = DIOCH01DATA% + BITWEIGHT%
		DIOCH01DATA% = DIOCH01DATA% OR BITWEIGHT%
	ELSE
		'Enable relay.
		'DIOCH01DATA% = DIOCH01DATA% - BITWEIGHT%
		DIOCH01DATA% = DIOCH01DATA% AND (NOT BITWEIGHT%)
	END IF
	
	'Set GPIB string and send to Agilent 34970A.
	DDATA$ = DIGOUT$ + STR$(DIOCH01DATA%) + ",(@" + STR$(HVRELAY.CH%) + ")"
	CALL IO488(DDATA$, DASADDR%, 1)         'Write configuration

	'Debug code.
	IF (DEBUGFLAG% = 1) THEN
		PRINT TAB(10); "...................................."
		PRINT TAB(10); "Final values...."
		PRINT TAB(10); "BITWEIGHT% =   "; BITWEIGHT%
		PRINT TAB(10); "DIOCH01DATA% = "; DIOCH01DATA%
		PRINT TAB(10); "DDATA$: "; DDATA$
		PRINT TAB(10); "...................................."
		CALL CONTINUE
	END IF

END SUB

'***********************************
SUB INDIVID (SEL%, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), STATUS$(), NUMDUT%)
	'Sub to run the individual tests.
	'
	NOMVS! = SPECS.NOMVS
	WAVESHPCAL$ = "FUNC:SHAP " + LEFT$(SPECS.WAVESHPCAL$, 3)
	FINCAL! = SPECS.FINCAL
	FINMAX! = SPECS.FINMAX
	FINEXTMAX! = SPECS.FINEXTMAX
	ACCCF12! = SPECS.ACCCF12
	ACCCF23! = SPECS.ACCCF23
	ACCCF34! = SPECS.ACCCF34
	ACCCF45! = SPECS.ACCCF45
	ACCSINCAL! = SPECS.ACCSINCAL
	ACCSINSTD! = SPECS.ACCSINSTD
	ACCSINEXT! = SPECS.ACCSINEXT
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE
	LOOPVNOM! = SPECS.LOOPVNOM + SPECS.MAXOUT * NOISEFILTERR!

	DIM NOMOUTERR!(4)
	LOOPCYC% = 0

	CALL INSTALLDUT(NUMDUT%)
	DO
		LOOPCYC% = LOOPCYC% + 1
		NOMOUTERR!(1) = 1000                        'Flag indicating measure gain error
		IF LOOPCYC% > 1 THEN
			CALL INSTALLDUT(NUMDUT%)
		END IF

		IF LOOPCYC% = 1 THEN
			IF OUTSIGTYPE$ = "CURRENT" THEN
				CALL SETOUTLOAD(IOUTSEN1!, 4) 'Set current output sense resistor
				FOR L% = 1 TO 4
					IOUTSEN1.MEAS!(L%) = IOUTSEN11.MEAS!(L%)
				NEXT
			ELSE    'IF OUTSIGTYPE = "VOLTAGE" THEN
				CALL SETOUTLOAD(1000000!, 4)  'Remove current output sense resistor
				FOR L% = 1 TO 4
					IOUTSEN1.MEAS!(L%) = 1
				NEXT
			END IF
		END IF
		 
		'FOR x% = 1 TO 17
		FOR x% = 1 TO MAXSTATUSINDEX
			'Clear test results.
			FOR L% = 1 TO NUMDUT%
				STATUS$(x%, L%) = ""
			NEXT
		NEXT
		   
		TIME2! = TIMER

		IF NOT LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
			'Turn off internal SCM7B (RDEN isolator) supply if not SCM5B.
			CALL ENABLE(5, 0)
		END IF
		
		IF OUTSIGTYPE$ <> "CURRENT" THEN
			CALL SETOUTLOAD(IOUTSEN3!, 4)
		END IF
		IF NOMVS! = 5 THEN
			'*************** SCM5B and 8B ***********************
			CALL SETSWITCH(VSSOURCE.CH%, 0)         'D.U.T. Power is test head VCVS
			SP! = SETSCM5BPWR!(NOMVS!)              'Set Vsupply to nominal value
			IF SP! = -1 THEN EXIT SUB               'High supply current
			IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
				FOR L% = 1 TO NUMDUT%
					CALL ENABLE(L%, 0)                  'Enable output switch
				NEXT
			END IF
			IF OUTSIGTYPE$ = "CURRENT" THEN
				CALL SETDPS(DPSADDR%, LOOPVNOM!)    'Set Vloop to nominal value
			END IF
		ELSE    'IF NOMVS! = 24 THEN
			'************* DSCA only ***************
				CALL SETSWITCH(VSSOURCE.CH%, 1)         'D.U.T. Power is Kepco DPS
				CALL INITPS(DPSADDR%, SPECS.ISMAX! * PSILIMIT! * 4, OVERV.DSCA!)
				CALL SETDPS(DPSADDR%, NOMVS!)           'Set Vsupply to nominal value
		END IF
  
		SELECT CASE SEL%
			CASE 1
				CALL SUPPLYI(NUMDUT%, STATUS$())
			CASE 2
				IF (LEFT$(SPECS.MODNAME, 4) = "DSCA") OR (LEFT$(SPECS.MODNAME, 2) = "8B") THEN
					'8B or DSCA
					CLS
					LOCATE 10, 10: PRINT "This test is not performed on model "; SPECS.MODNAME
				ELSE
					CALL OUTSWITCH(NUMDUT%, STATUS$())
				END IF
			CASE 3
				CAL% = 0
				CALL CALSEQ(NUMDUT%, STATUS$())
			CASE 4
				CALL LINTEST(INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, STATUS$())
			CASE 5  'Was 12.
				CALL SUPPLYSEN(NUMDUT%, STATUS$())
			CASE 6  'Was 14.
				CALL OUTPUTNOISE(NUMDUT%, STATUS$())
			CASE 7  'Was 15.
				IF OUTSIGTYPE$ = "VOLTAGE" THEN
					CLS
					LOCATE 10, 10: PRINT "This test is not performed on model "; SPECS.MODNAME
				ELSE
					CALL IOUTMAXL(NUMDUT%, STATUS$())
				END IF
		END SELECT
				  
		IF NOMVS! = 5 THEN
			'SCM5B and 8B
			SP! = SETSCM5BPWR!(.01)                 'Set Vsupply to zero
			IF OUTSIGTYPE$ = "CURRENT" THEN
				SP$ = POWERIO$(DPSADDR%, SUPPLYOFF$)    'Disable power supply
			END IF
			IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
				FOR L% = 1 TO NUMDUT%
					CALL ENABLE(L%, 1)                  'Disable output switch
				NEXT
			END IF
		ELSE    'IF NOMVS! = 24 THEN
			'DSCA
			SP$ = POWERIO$(DPSADDR%, SUPPLYOFF$)    'Disable power supply
		END IF
		  
		ELAP2! = TIMER - TIME2!
		   
		IF NOT LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
			'Turn internal SCM7B (RDEN isolator) supply back on if not SCM5B.
			CALL ENABLE(5, 1)
		END IF

		CALL PAUSE(1!)
		'CALL CONTINUE
   
	LOOP WHILE REPEAT$(SPECS.MODNAME, ELAP2!, TIME2!) <> "N"
  
END SUB

'**************************
SUB INPUTSN (SN$, SERNO$(), NUMDUT%)
	'Sub to get the serial number(s) for the modules under test by getting
	'the work order number and starting dash number. If the passed number
	'of modules to test (NUMDUT%) is more than one (1), questions are asked
	'to determine the dash numbers (and ultimately the serial numbers) for
	'the modules in test channels (slots) 2 through NUMDUT%. The sub also
	'returns the current (channel 1) serial number as a parameter.
	'
	DO  'Loop until serial numbers are confirmed good
		CALL GETSN(SN$)     'Get serial number for initial module
		CLS
		SERNO$(1) = SN$     'Set channel 1 module serial number to initial serial number

		'Determine serial numbers for modules in subsequent test channels (if any)
		IF NUMDUT% > 1 THEN
			'If more than one module ask for custom or ordered numbering
			LOCATE 5
			PRINT TAB(10); "Are the modules in channels 1 to"; NUMDUT%
			PRINT TAB(10); "in sequential order?";
			PRINT
			PRINT
			PRINT TAB(10); "Must enter 'Y' or 'N' (upper or lower case)."
			PRINT
			PRINT
			'Get keyboard entry (must be 'Y' or 'N')
			DO
				ANS$ = INKEY$
				ANS$ = UCASE$(ANS$)
			LOOP WHILE (ANS$ <> "N") AND (ANS$ <> "Y")
			IF ANS$ = "Y" THEN
				'Create sequential serial numbers
				FOR I% = 2 TO NUMDUT%
					LOCALSN$ = SERNO$(I% - 1)   'Get serial number of module in previous test channel
					SERNO$(I%) = UPSN(LOCALSN$) 'Get incremented (or new) serial number for this test channel
				NEXT
			ELSE
				'Enter custom dash numbers to create custom serial numbers
				FOR I% = 2 TO NUMDUT%
					LOCALSN$ = SERNO$(I% - 1)   'Get serial number of module in previous test channel
					SERNO$(I%) = SNMENU$(I%, LOCALSN$, 1)   '
				NEXT
			END IF
		END IF

		'Display the serial numbers entered.
		CLS
		LOCATE 5
		IF (NUMDUT% > 1) THEN
			PRINT TAB(5); "The following serial numbers were entered:"
		ELSE
			PRINT TAB(5); "The following serial number was entered:"
		END IF
		FOR I% = 1 TO NUMDUT%
			PRINT TAB(5); "Test channel # "; I%; ": Serial number = "; SERNO$(I%)
		NEXT

		'Check to see if there are any duplicate serial numbers
		IF (ISDUPLICATESN%(SERNO$, NUMDUT%) = 1) THEN
			'There are duplicate serial numbers
			PRINT
			PRINT
			COLOR 28, 0, 0  'Flashing light red
			PRINT TAB(6); "DUPLICATE SERIAL NUMBERS WERE SET!"
			COLOR 11, 0, 0  'Cyan on black background
			PRINT
			PRINT
			PRINT TAB(5); "Retry entering the serial numbers after"
			PRINT TAB(5); "pressing the key listed below."
			PRINT
			BEEP
			DUMKEY$ = WAITFORKEY("S", 10, 14, 0)    'Waits for "S" key press (display bright yellow on black)
		ELSE
			'There are no duplicate serial numbers - ask if the serial numbers are good
			PRINT
			PRINT
			PRINT TAB(10); "Are the serial numbers valid?"
			PRINT
			PRINT TAB(10); "Must enter 'Y' or 'N' (upper or lower case)."
			PRINT
			PRINT
			'Get keyboard entry (must be 'Y' or 'N')
			DO
				ANS2$ = INKEY$
				ANS2$ = UCASE$(ANS2$)
			LOOP WHILE (ANS2$ <> "N") AND (ANS2$ <> "Y")
			IF ANS2$ = "N" THEN
				PRINT
				PRINT TAB(5); "Retry entering the serial numbers after"
				PRINT TAB(5); "pressing the key listed below."
				PRINT ;
				DUMKEY$ = WAITFORKEY("S", 10, 14, 0)    'Waits for "S" key press (display bright yellow on black)
			END IF
		END IF
	LOOP WHILE (ANS2$ <> "Y")

	'Set initial serial number and proceed on to testing
	SN$ = SERNO$(1) 'Set initial serial number
	'Wait to acknowledge serial number(s)
	PRINT
	PRINT
	PRINT
	PRINT
	PRINT TAB(5); "Ready to start testing...."
	DUMKEY$ = WAITFORKEY("T", 10, 14, 0)    'Waits for "T" key press (display bright yellow on black)
	PRINT
	PRINT TAB(5); "Continuing on to test...."
	TIME2! = TIMER
END SUB

'********************************
SUB INSTALLDUT (NUMDUT%)
	'Sub to display information about installation of the DUTs in the appropriate
	'channels (test channels). The module checks the specified nominal supply voltage
	'from the database for the module type already selected (SPECS.NOMVS) and uses
	'this information to warn to remove
	'Inputs:    None
	'Output:    By reference parameter NUMDUT% = Number of Devices Under Test (1 to 4)
	'
	'First message screen
	CLS
	'LOCATE 1, 20: PRINT "SCM5B, 8B & DSCA AUTOMATED TEST EQUIPMENT"
	'PRINT
	'PRINT TAB(5); "Module type selected: "; SPECS.MODNAME
	'PRINT
	'PRINT
	'PRINT TAB(5); "Up to 4 modules of a single type (SCM5B, 8B or DSCA can be"
	'PRINT TAB(5); "tested at the same time. However, only ONE (1) type of module can"
	'PRINT TAB(5); "be installed while testing!"
	'PRINT
	'PRINT
	'PRINT TAB(5); "Verify that there are no modules of any type currently installed"
	'PRINT TAB(5); "in the test head!"
	'DUMKEY$ = WAITFORKEY("N", 10, 14, 0)   'Waits for "N" key press (display bright yellow on black)
	'Second message screen
	CLS
	LOCATE 1, 20: PRINT "SCM5B, 8B & DSCA AUTOMATED TEST EQUIPMENT"
	LOCATE 3
	PRINT TAB(5); "Module type selected: "; SPECS.MODNAME
	LOCATE 10
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(5); "-----------------------------------------------------------------"
	COLOR 15, 0, 0  'Bright white on black background
	PRINT TAB(10); "Install the modules to be tested in the test head sockets."
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(5); "-----------------------------------------------------------------"
	COLOR 11, 0, 0  'Cyan on black background
	PRINT   'Blank line
	PRINT TAB(5); "Start with channel 1 and continue with channel 2, channel 3"
	PRINT TAB(5); "and channel 4, in that order. If there are fewer than 4    "
	PRINT TAB(5); "modules, leave the higher channels empty.                  "
	PRINT   'Blank line
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(5); "For the selected module type, do not leave channel 1"
	PRINT TAB(5); "empty or skip any channels if there is more than one"
	PRINT TAB(5); "module!                                          "
	COLOR 11, 0, 0  'Cyan on black background
	CALL CONTINUE
	CLS

	'Wait for valid keyboard entry (number of modules installed)
	DO
		'List allowable values if a good entry was not found the first time through
		COLOR 15, 0, 0  'White on black
		'Clear line of previous answer
		LOCATE 17, 5: PRINT "                                                        "
		'Ask question
		LOCATE 17, 5: INPUT "How many modules are installed in the test head: "; KBINPUT$
		NUMENTERED% = VAL(KBINPUT$)

		'Clear any previous warning lines
		LOCATE 15, 5: PRINT "                                            "
		PRINT TAB(5); "                                    "

		'Check for invalid entry
		IF (NUMENTERED% < 1) OR (NUMENTERED% > 4) THEN  'Invalid value (not 1 to 4)
			'Warn of invalid value entered
			COLOR 28, 0, 0  'Flashing light red
			LOCATE 15, 5: PRINT "INVALID VALUE ENTERED FOR NUMBER OF MODULES!"
			COLOR 12, 0, 0  'Light red
			PRINT TAB(5); "Value entered = "; KBINPUT$
			COLOR 15, 0, 0  'White on black
			BEEP
			LOOPEXIT% = 0   'Flag set for invalid value entered
		ELSE
			LOOPEXIT% = 1   'Flag set for valid value entered
		END IF
	LOOP WHILE (LOOPEXIT% <> 1)

	'Set and display value entered
	NUMDUT% = NUMENTERED%   'Set return value (in parameter)
	COLOR 11, 0, 0  'Cyan on black background
	CLS
	LOCATE 1, 20: PRINT "SCM5B, 8B & DSCA AUTOMATED TEST EQUIPMENT"
	PRINT   'Blank line
	PRINT TAB(5); "Module type selected: "; SPECS.MODNAME
	COLOR 15, 0, 0  'White on black
	PRINT   'Blank line
	PRINT   'Blank line
	PRINT TAB(5); "Number of modules in test head: "; NUMDUT%
	PRINT   'Blank line
	PRINT   'Blank line
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(6); "-----------------------------------------------------------------"
	COLOR 28, 0, 0  'Flashing light red
	PRINT TAB(6); " MAKE SURE THAT THE PROTECTIVE COVER IS CLOSED ON THE TESTHEAD!  "
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(6); "-----------------------------------------------------------------"
	PRINT
	PRINT
	PRINT TAB(5); "Continue on to testing after verifying that the cover"
	PRINT TAB(5); "is closed by pressing the key listed below."
	PRINT
	'BEEP
	DUMKEY$ = WAITFORKEY("C", 10, 14, 0)    'Waits for "C" key press (display bright yellow on black)
	CLS
	LOCATE 5: PRINT TAB(5); "Continuing on to testing...."
END SUB

SUB IOUTMAXL (NUMDUT%, STATUS$())
	'Test operation of current output modules with max load resistance.
	'Inputs;    NUMDUT% = number of Devices Under Test
	'Outputs;   STATUS$(17, n)   array of results
	'
	MAXIN! = SPECS.MAXIN
	FINCAL! = SPECS.FINCAL                  'Input waveshape frequency (Hz)
	MINOUT! = SPECS.MINOUT                  'V or A
	MAXOUT! = SPECS.MAXOUT
	ORANGE! = MAXOUT! - MINOUT!             'Output range (V or A)
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE
	MEAS.ACC! = SPECS.CALTOL / 100 / 10     'Measurement accuracy
	NOMVS! = SPECS.NOMVS
	LOOPVMIN! = SPECS.LOOPVMIN + MAXOUT! * (IOUTSEN2! + NOISEFILTERR!)
	LOOPVNOM! = SPECS.LOOPVNOM + MAXOUT! * NOISEFILTERR!

	CLS
	TESTTITLE$ = "Maximum Output Load Test"
	CALL HEADERB(TESTTITLE$, 0)

	IF OUTSIGTYPE$ = "VOLTAGE" THEN
	LOCATE 10, 10: PRINT "This test is not performed on model "; SPECS.MODNAME
	EXIT SUB
	ELSEIF NOMVS! = 5 THEN
	CALL SETDPS(DPSADDR%, LOOPVMIN!)    'Set Vloop to nominal value
	END IF

	MAXINMEAS! = SETDUTIN!(MAXIN!)

	FOR L% = 1 TO NUMDUT%
		LOCATE 1
		IF L% <> 1 THEN CALL HEADERB(TESTTITLE$, 0)

		'Check if module previously failed supply current
		'(removed from test head), offset cal or gain cal
		'(not functional) or output switch test (not functional)
		IF LEFT$(STATUS$(1, L%), 4) <> "FAIL" AND LEFT$(STATUS$(2, L%), 4) <> "FAIL" AND LEFT$(STATUS$(13, L%), 4) <> "FAIL" AND LEFT$(STATUS$(14, L%), 4) <> "FAIL" THEN
			LOCATE 10, 25: PRINT "TESTING DEVICE IN CHANNEL #"; L%
   
			CALL DVMCONF(IOUTSENDUT1SEN.CH% + L% - 1, VDC$, "", MAXOUT! * IOUTSEN1.MEAS!(1), "", 0)
			CALL DVMSENS(IOUTSENDUT1SEN.CH% + L% - 1, VDC$, INTTIME$, "", .02)   '4 1/2 digits, 15 bit resolution
	   
			OUTNOMLOAD! = GETREADING! / IOUTSEN1.MEAS!(L%) 'output at nominal load (250 ohm)

			CALL SETOUTLOAD(IOUTSEN2!, NUMDUT%)             'Set max load resistor

			CALL DVMCONF(IOUTSENDUT1SOUR.CH% + L% - 1, VDC$, "", MAXOUT! * IOUTSEN2! * 1.1, "", 0)
			CALL DVMSENS(IOUTSENDUT1SOUR.CH% + L% - 1, VDC$, INTTIME$, "", .02)   '4 1/2 digits, 15 bit resolution
			OUTMAXLOAD! = GETREADING! / IOUTSEN2.MEAS!(L%) 'output at max. load (600 ohm)
	   
			PERCOUTCHG! = (OUTMAXLOAD! - OUTNOMLOAD!) / ORANGE! * 100!

			IF ABS(PERCOUTCHG!) <= DELTALOADTOL! THEN
				ML$ = "PASS"
			ELSE
				ML$ = "FAIL"
				SOUND 1000, .5
			END IF

			'Set DUT input voltage power supply to 0V (PWR 2014-10-08)
			CALL SETDPS(DPSVINADDR%, 0!)
			CALL SETDPS(DPSVINADDR2%, 0)
			'LOCATE 15, 10: PRINT TAB(10); "MODULE #"; L%; " Status: "; ML$;
			LOCATE 16, 10   'Added
			PRINT SPC(30);
			PRINT TAB(10); "Change in output current at max load is";
			PRINT TAB(50); USING " +###.### %"; PERCOUTCHG!
			PRINT TAB(10); "Max. change in output current is";
			PRINT TAB(50); USING "+/-##.### %"; DELTALOADTOL!
 
			CALL FAILSTATUS(L%, ML$, 15, 10, "Status: ", 20)        'Print test status to screen
 
			STATUS$(17, L%) = ML$ + STR$(PERCOUTCHG!) + "1"

			CALL SETOUTLOAD(IOUTSEN1!, NUMDUT%) 'Set current output sense resistor
		   
		END IF
		   
		IF L% < NUMDUT% THEN           'Prevent to assign a not valid serial number
			SN$ = SERNO$(L% + 1)       'Use the next serial number on the array
		END IF
		CALL PAUSE(1!)
		IF L% <> NUMDUT% THEN
			FOR M% = 15 TO 17
				LOCATE M%, 10: PRINT SPC(65);
			NEXT
			PRINT
		END IF
		CLS
	NEXT

	SN$ = SERNO$(1)

	CALL SETDPS(DPSVINADDR%, 0) 'Set input voltage (at ext. supply) to 0V
	CALL SETDPS(DPSVINADDR2%, 0)
	IF NOMVS! = 5 THEN
		CALL SETDPS(DPSADDR%, LOOPVNOM!)        'Set Vloop to nominal value
	END IF

END SUB

FUNCTION ISDUPLICATESN% (SERNO$, NUMDUT%) 'Selection menu to change the SN information of unit in channels 2 or higher
	'Function that returns "1" if there are duplicate serial numbers set
	'and "0" if no serial number set matches any other.
	'
	ISDUPLICATESN% = 0  'Initialize to "not duplicate"
	'Dual loops. For each channel, check the complete serial number (work order/serial)
	'against all others.
	FOR iIdx1 = 1 TO NUMDUT%
		FOR iIdx2 = 1 TO NUMDUT%
			IF (SERNO$(iIdx1) = SERNO$(iIdx2)) THEN
				IF NOT (iIdx1 = iIdx2) THEN 'Do not check to see if same serial number matches itself
					IF NOT (SERNO$(iIdx1) = "" OR SERNO$(iIdx2) = "") THEN  'Skip checking if the serial number is blank
						' Duplicate work order/serial number for the channel.
						ISDUPLICATESN% = 1  'Set to "duplicate"
					END IF
				END IF
			END IF
		NEXT iIdx2
	NEXT iIdx1

END FUNCTION

SUB LINTEST (INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), NUMDUT%, STATUS$())
	'Measure accuracy over input range
	'Inputs;
	'       NUMDUT% = number of Devices Under Test
	'
	'Outputs;
	'       INSIM!(m, n)    array of measured input voltages or currents
	'       OUTCALC!(m, n)  array of calculated output voltages or currents
	'       OUTMEAS!(m, n)  array of measured output voltages or currents
	'       ERROROUT!(m, n) array of calculated error from ideal (% span)
	'       ACCSTAT$(m, n)  array of accuracy status at each test point (PASS/FAIL)
	'       STATUS$(3, n)   array of results, measured accuracy
	'       STATUS$(4, n)   array of results, best fit linearity
	'
	OSCALIN! = SPECS.OSCALIN
	FINCAL! = SPECS.FINCAL                  'Input waveshape frequency (Hz)
	MAXIN! = SPECS.MAXIN
	MINOUT! = SPECS.MINOUT                  'V or A
	MAXOUT! = SPECS.MAXOUT
	MAXLINERR! = SPECS.LINEAR               ' %
	MAXACCERR! = SPECS.ACCSINCAL            ' %
	MEAS.ACC! = SPECS.CALTOL / 100 / 10     'Measurement accuracy
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE
	NOMVS! = SPECS.NOMVS
	MININ! = SPECS.MININ
	NUMPTS% = 5
	
	ORANGE! = MAXOUT! - MINOUT!             'Output range (V or A)
	IRANGE! = MAXIN! - MININ!               'Input range (V for HV modules)

	IF OUTSIGTYPE$ = "VOLTAGE" THEN
		UNIT$ = "V"
		OUTSCALE! = 1!
	ELSE
		UNIT$ = "mA"
		OUTSCALE! = 1000!
	END IF

	LINSTEP! = (MAXIN! - MININ!) / (NUMPTS% - 1)
	
	CALL CONFDUTIN(0)
	CALL CONFDUTIN(1)
														'LINSTEP!/2 ensures NUMPTS% test point
	FOR L% = 1 TO NUMDUT%
		CLS
		TESTTITLE$ = "Accuracy Test"
		CALL HEADERB(TESTTITLE$, 0)

		IF OUTSIGTYPE$ <> "CURRENT" THEN
			CALL SETOUTLOAD(10001, 4)
		END IF
   
		'Header format:
		'
		'5             19               36               53            67
		'Iin (mAAC)
		'Vin (mVAC)    Output (mADC)    Output (mADC)     Error (%)     Status
		'----------    -------------    -------------    ----------    --------
		'  ###.###         ##.###           ##.###        +###.###       &&&&
		'
		PRINT TAB(20); "Calculated"; TAB(38); "Measured"
		IF MAXIN! >= 1 THEN
			PRINT TAB(6); "Vin (VDC)";
			INSCALE! = 1
		ELSE
			PRINT TAB(5); "Vin (mVDC)";
			INSCALE! = 1000
		END IF
		PRINT TAB(19); "Output ("; UNIT$; "DC)"; TAB(36); "Output ("; UNIT$; "DC)";
		PRINT TAB(54); "Error (%)"; TAB(68); "Status"
		PRINT TAB(5); "----------"; TAB(19); "------------"; TAB(36); "------------";
		PRINT TAB(53); "----------"; TAB(67); "--------"

		'Check if module previously failed supply current
		'(removed from test head), offset cal or gain cal
		'(not functional).
		IF LEFT$(STATUS$(1, L%), 4) <> "FAIL" AND LEFT$(STATUS$(13, L%), 4) <> "FAIL" AND LEFT$(STATUS$(14, L%), 4) <> "FAIL" THEN

			LOCATE 12, 10
			PRINT "TESTING DEVICE IN CHANNEL #"; L%

			INC% = 0                                        'Array element
			FAILED% = 0
			ACCERR! = 0
			SMODIN! = 0
			SSMODIN! = 0
			SERR! = 0
			SPROD! = 0
			LOCATE 6
			
			IF OUTSIGTYPE$ = "CURRENT" THEN
				CH% = IOUTSENDUT1SEN.CH%
			ELSE
				IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
					CH% = VOUTDUT1.CH%
				ELSE                                    'DSCA
					CH% = IOUTSENDUT1SOUR.CH%
				END IF
			END IF
			'CALL DVMSENS(CH% + L% - 1, VDC$, RANGE$, "", MAXOUT!)'Set range
			
			FOR MODIN! = MININ! TO MAXIN! + LINSTEP! / 2 STEP LINSTEP!
				INC% = INC% + 1
				
				INSIM!(L%, INC%) = SETDUTIN!(MODIN!) * INSCALE!
				
				'Expected DUT input voltage (set voltage) is "MODIN!", while the measured input
				'voltage is "INSIM!(L%, INC%) / INSCALE!" (see above, with the scaling factor
				'removed. The error between the two is the difference from the measured to the
				'expected, divided by the input range. Times 100 give the percentage error
				'of the measured input against the input range.
				'
				'Calculate the percentage error of the input here, then check to make sure it
				'does not exceed the specified tolerance below.
				'INPUTERR! = 100! * ((INSIM!(L%, INC%) / INSCALE!) -  MODIN!) / MODIN!
			
				INPUTERR! = 100! * ((INSIM!(L%, INC%) / INSCALE!) - MODIN!) / IRANGE!  'Input err. % of input range (PWR 2014-07-25)
				OUTCALC!(L%, INC%) = MODULEOUT!(INSIM!(L%, INC%) / INSCALE!)
		   
				CALL DVMCONF(CH% + L% - 1, VDC$, "", ABS(OUTCALC!(L%, INC%) * IOUTSEN1.MEAS!(1)), "", 0)
				CALL DVMSENS(CH% + L% - 1, VDC$, INTTIME$, "", 2)'6 1/2 digits,1 bit resolution
				PAUSE (1)
				OUTMEAS!(L%, INC%) = GETREADING! / IOUTSEN1.MEAS!(L%) * OUTSCALE!
				ERROROUT!(L%, INC%) = (OUTMEAS!(L%, INC%) / OUTSCALE! - OUTCALC!(L%, INC%)) / ORANGE! * 100!'Error (% span)
				
				'Check for input error more than 10% of the expected voltage, in
				'addition to the accuracy-step error (PWR 2014-07-24)
				IF (ABS(INPUTERR!) > 10!) THEN
					'Input error more than 10% of set value = FAIL
					ACCSTAT$(L%, INC%) = "FAIL"
					FAILED% = FAILED% + 1
					SOUND 800, .5
				ELSEIF ABS(ERROROUT!(L%, INC%)) <= MAXACCERR! THEN
					'Output error within limits = PASS
					ACCSTAT$(L%, INC%) = "PASS"
				ELSE
					'Output error exceeds limits = FAIL
					ACCSTAT$(L%, INC%) = "FAIL"
					FAILED% = FAILED% + 1
					SOUND 800, .5
				END IF
				
				'Original code commented out below (PWR 2014-07-24)
				'IF ABS(ERROROUT!(L%, INC%)) <= MAXACCERR! THEN
				'       ACCSTAT$(L%, INC%) = "PASS"
				'ELSE
				'       ACCSTAT$(L%, INC%) = "FAIL"
				'       FAILED% = FAILED% + 1
				'       SOUND 800, .5
				'END IF
				   
				PRINT TAB(6); USING "+###.###      +###.###         +###.###        +###.###"; INSIM!(L%, INC%); (OUTCALC!(L%, INC%)) * OUTSCALE!; OUTMEAS!(L%, INC%); ERROROUT!(L%, INC%);
				
				'PRINT TAB(69); ACCSTAT$(L%, INC%)
				IF (LEFT$(ACCSTAT$(L%, INC%), 4) = "FAIL") THEN
					COLOR 12, 0 'Test value text color to light red
				ELSE
					COLOR 10, 0 'Test value text color to light green
				END IF
				PRINT TAB(69); ACCSTAT$(L%, INC%)
				COLOR 11, 0     'Back to light cyan (blue) on black background.
		
				IF ABS(ERROROUT!(L%, INC%)) > ABS(ACCERR!) THEN
					ACCERR! = ERROROUT!(L%, INC%)
				END IF
				  
				'Variables used to calculate the best fit line using linear regression.
				SMODIN! = SMODIN! + INSIM!(L%, INC%)
				SSMODIN! = SSMODIN! + INSIM!(L%, INC%) ^ 2
				SERR! = SERR! + ERROROUT!(L%, INC%)
				SPROD! = SPROD! + INSIM!(L%, INC%) * ERROROUT!(L%, INC%)
		  
			NEXT
				  
			SLOPE! = ((NUMPTS% * SPROD!) - (SMODIN! * SERR!)) / ((NUMPTS% * SSMODIN!) - (SMODIN! ^ 2))
			OFFSET1! = ((SERR! * SSMODIN!) - (SMODIN! * SPROD!)) / ((NUMPTS% * SSMODIN!) - (SMODIN! ^ 2))
	   
			BFERR! = ABS(BESTFIT!(SLOPE!, OFFSET1!, INSIM!(), NUMPTS%, ERROROUT!(), L%))
	   
			IF FAILED% = 0 THEN
				ACC$ = "PASS"
			ELSE
				ACC$ = "FAIL"
				SOUND 800, .5
			END IF
			IF ABS(BFERR!) <= MAXLINERR! THEN
				BF$ = "PASS"
			ELSE
				SOUND 600, .5
				BF$ = "FAIL"
			END IF

			'Set DUT input voltage power supply to 0V (PWR 2014-10-08)
			CALL SETDPS(DPSVINADDR%, 0!)
			CALL SETDPS(DPSVINADDR2%, 0)
			'LOCATE 13
			'PRINT TAB(10); "Accuracy status: "; ACC$
			LOCATE 14   'Added.
			PRINT TAB(10); "Measured accuracy error is";
			PRINT TAB(50); USING " +###.### %"; ACCERR!
			PRINT TAB(10); "Maximum accuracy error is";
			PRINT TAB(50); USING "+/-##.### %"; MAXACCERR!
			PRINT
			'PRINT TAB(10); "Linearity status: "; BF$
			PRINT TAB(10); "Measured best-fit linearity error is";
			PRINT TAB(50); USING "+/-###.### %"; BFERR!
			PRINT TAB(10); "Maximum best-fit linearity error is";
			PRINT TAB(50); USING "+/- ##.### %"; MAXLINERR!

			STATUS$(3, L%) = ACC$ + STR$(ACCERR!) + "3"         '% span
			STATUS$(4, L%) = BF$ + STR$(BFERR!) + "3"   'append # decimal places

			CALL FAILSTATUS(L%, ACC$, 13, 10, "Accuracy status: ", 20)      'Print test status to screen
			CALL FAILSTATUS(L%, BF$, 16, 10, "Linearity status: ", 20)      'Print test status to screen
		   
		END IF
		   
		IF L% < NUMDUT% THEN           'Prevent to assign a not valid serial number
			SN$ = SERNO$(L% + 1)       'Use the next serial number on the array
		END IF
		CALL PAUSE(1!)
		
		CALL INSTRERRORS(DASADDR%, 1)  'Clears and displays Agilent 34970A error queue.
		CLS
	NEXT
  
	SN$ = SERNO$(1)

	'CALL FUNGEN33120A(VOLT$, GENOUTMIN!)          'Set lowest input signal
	CALL SETDPS(DPSVINADDR%, 0!)    'Set DUT input voltage power supply to 0V (PWR 2014-07-24)
	CALL SETDPS(DPSVINADDR2%, 0)
END SUB

FUNCTION PROGNAMEVAL$
	'Function to return the library source file version
	PROGNAMEVAL$ = PROGNAME$
END FUNCTION

FUNCTION PROGVERVAL$
	'Function to return the library source file version
	PROGVERVAL$ = VERSION$
END FUNCTION

SUB STARTCFG
	'Sub to perform module-input configuration before testing
	'
	'---------------------------------------------------------------------------
	'Configure to measure input current sense resistors if current-input module
	'---------------------------------------------------------------------------
	'CALL INSTALLDUT(NUMDUT%)
	IINSEN1.MEAS! = 1
	
	'----------------
	'Set module input
	'----------------
	CLS
	LOCATE 5
	PRINT TAB(10); "Module input successfully set for testing.....";
	PRINT
	PRINT
END SUB

