'****************************  TESTHV3  ***********************************
' NAME:         TESTHV4.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/06/25 B.1     PWR     See TESTHV3.BAS for update notes.
'
'******** 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 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%, TSPEC$()) '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
DECLARE FUNCTION GETWO$ ()                      'Gets and returns the work order number
DECLARE FUNCTION GETDS$ (ISNEWDS%, SN$)         'Gets and returns the dash number

'*********************** 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 SUB CHECKFORPAPERMSG () 'Displays message to check for paper in the printer
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%

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! = 35                  'Module power supply over voltage limit, DSCA
CONST OVERV.SCM5B! = 48                 'Current loop power supply over voltage limit, SCM5B
CONST PSILIMIT! = 1.4                   '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! = .1                     'Input current source sense resistor, 0.1 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


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

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

FINISH:
	CALL FINISHSUB
	END 'End of program
	
'******************* Test Titles and Units *****************************************
LINES:  DATA "Supply Current","mA","Output Switch",""
		DATA "See REPORT SUB","%","See REPORT SUB","%"
		DATA "See REPORT SUB","%","See REPORT SUB","%"
		DATA "See REPORT SUB","%","See REPORT SUB","%"
		DATA "See REPORT SUB","%","See REPORT SUB","%"
		DATA "See REPORT SUB","%","Power Supply Sensitivity",""
		DATA "Offset Error","%","Gain Error","%"
		DATA "Step Response @ 120ms","%"
		DATA "Output Noise","%","Change in Iout with Max Load","%"

FUNCTION CHECKFILECREATE% (FOLDERNAME$, FILENAME$, KEYTOPRESS$)
	'Function to check for the existence of the folder passed by
	'FOLDERNAME$ by creating the file passed by FILENAME$. At the
	'end, the function deletes the test file and waits for the
	'operator to press the key specified by KEYTOPRESS$ to ensure
	'that the messages about whether the file could be created (or
	'that the folder exists and can be written to) are acknowledged.
	'Since the addition of an error handler tends to cause the program
	'to run out of memory to compile, this function depends on messages
	'to the test operator about which files and folders are being
	'checked, so if the program crashes out (which it will if there is
	'an error without an error handler), the previously-displayed
	'message can point to the problem file or folder.
	'
	CHECKFILECREATE% = 1    'Initialize to "error" return for function
	PRINT TAB(10); "Attempting to open a temporary";
	PRINT TAB(10); "file in the following folder...";
	PRINT SPC(50);
	COLOR 15, 0 'Text color to bright white on black
	PRINT TAB(10); "Folder name: "; FOLDERNAME$
	PRINT SPC(50);
	COLOR 14, 0 'Text color to bright yellow on black
	PRINT TAB(10); "Record the folder name and notify engineering";
	PRINT TAB(10); "if the program crashes after this message!";
	PRINT SPC(50);
	COLOR 11, 0 'Text color back to light cyan (blue) on black
	OPEN FOLDERNAME$ + FILENAME$ FOR OUTPUT AS #9
	CLOSE #9
	'Delete the file
	KILL FOLDERNAME$ + FILENAME$
	'CLS
	'PRINT TAB(10); "Press any key to continue."
	'a$ = KEYBDIN$
	'DUMKEY$ = WAITFORKEY(KEYTOPRESS$, 10, 14, 0)   'Waits for specified key press (display bright yellow on black)

	CHECKFILECREATE% = 0    'Return of "no error" for function (if processing gets this far)

END FUNCTION

FUNCTION CHECKPRINTER% (PrinterMessage$)
	'Function to check that the printer can be written to for automatic
	'printing of the work order status file at the end of testing or
	'when a work order number is changed.  Since the addition of an
	'error handler tends to cause the program to run out of memory to
	'compile, this function depends on messages to the test operator
	'about the printer and the message that should be printed, so if
	'the program crashes out (which it will if there is an error without
	' an error handler), the previously-displayed message can point to
	'the problem.
	'
	CHECKPRINTER% = 1   'Initialize to "error" return for function
	CLS
	'LOCATE 10
	LOCATE 5
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(10); "-----------------------------------------------------------------"
	COLOR 28, 0, 0  'Flashing light red
	PRINT TAB(10); "Verify that there is plenty of paper in the printer!"
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(10); "-----------------------------------------------------------------"
	COLOR 11, 0, 0  'Cyan on black background
	PRINT SPC(50);
	PRINT TAB(10); "Enough paper should be loaded in the printer to print"
	PRINT TAB(10); "the W.O. Status Report in addition to any hardcopy or"
	PRINT TAB(10); "datasheet printouts that may be selected."
	PRINT SPC(50);
	COLOR 14, 0 'Text color to bright yellow on black
	PRINT TAB(10); "Notify engineering if the printer does not print the";
	PRINT TAB(10); "message listed below or if the program crashes      ";
	PRINT TAB(10); "before the question can be answered.... ";
	PRINT SPC(50);
	COLOR 11, 0, 0  'Cyan on black background
	PRINT TAB(10); "Now attempting to verify that the printer can print."
	PRINT SPC(50);
	COLOR 14, 0 'Text color to bright yellow on black
	PRINT TAB(10); "Did the printer eject a sheet of paper with         "
	PRINT TAB(10); "the following message printed on it?                "
	PRINT SPC(50);
	COLOR 15, 0 'Text color to bright white on black
	PRINT TAB(10); PrinterMessage$
	PRINT SPC(50);
	'Print to printer.
	OPEN "LPT1:" FOR RANDOM AS #14
	PRINT #14, PrinterMessage$
	PRINT #14, CHR$(12) 'Form feed
	CLOSE #14
	COLOR 14, 0 'Text color to bright yellow on black
	PRINT TAB(10); "Enter Y or y for YES, N or n for NO"
	DO
		KEYRTN$ = INKEY$
		KEYRTN$ = UCASE$(KEYRTN$)
	LOOP WHILE (KEYRTN$ <> "N") AND (KEYRTN$ <> "Y")
	IF (KEYRTN$ = "Y") THEN
		CHECKPRINTER% = 0   'Return of "no error" for function (if processing gets this far)
	ELSE
		CHECKPRINTER% = 1   'Return of "is error" for function (if processing gets this far)
	END IF
	COLOR 11, 0, 0  'Cyan on black background
	
END FUNCTION

SUB CHECKRESOURCES (CHECKFILES%)
	'Sub to check for the presence of a printer attached to the test station
	'and for enough properly-loaded paper, and if CHECKFILES% is "1", to
	'check for the datasheet and work order status file directories and
	'the ability to create a file in those directories. Error messages will be
	'displayed if there is a problem with these, and then the program will
	'exit. This sub should not normally be run with CHECKFILES% = 1 unless
	'the test type is one that normally produces datasheet and work order
	'status report files (post-encap or sealed module testing).
	'
	ISERROR% = 0    'Initialize to "no error"

	'---------------------------------------------------
	'Selectively check for the ability to create a file
	'in the STAGE directory (datasheet file directory).
	'---------------------------------------------------
	IF (CHECKFILES% = 1) THEN
		CLS
		LOCATE 10
		PRINT TAB(10); "Checking for the ability to create a datasheet file."
		PRINT TAB(10); "----------------------------------------------------"
		PRINT SPC(50);
		IF (CHECKFILECREATE%("C:\STAGE\", "temp.fil", "S") = 1) THEN
			ISERROR% = 1    'Error flag set
		END IF
	END IF
	
	'---------------------------------------------------
	'Selectively check for the ability to create a file
	'in the REPORT directory (work order status report
	'file directory).
	'---------------------------------------------------
	IF (CHECKFILES% = 1) THEN
		CLS
		LOCATE 10
		PRINT TAB(10); "Checking for the ability to create a work order status file."
		PRINT TAB(10); "------------------------------------------------------------"
		PRINT SPC(50);
		IF (CHECKFILECREATE%("C:\REPORTS\", "temp.fil", "R") = 1) THEN
			ISERROR% = 1    'Error flag set
		END IF
	END IF
	
	'------------------------------------------------
	'Check for ability to write to the printer (and
	'display message to check for properly loaded
	'and sufficient paper).
	'------------------------------------------------
	PrinterMessage$ = "Printer OK"  'Message to be printed by the printer
	CLS
	LOCATE 10
	PRINT TAB(10); "Checking for the ability to write to the printer."
	PRINT TAB(10); "-------------------------------------------------"
	PRINT SPC(50);
	IF (CHECKPRINTER%(PrinterMessage$) = 1) THEN
		'Error when printing
		ISERROR% = 1    'Error flag set
	ELSE
		CLS
	END IF
	
	'Exit program if there is an error
	IF (ISERROR% = 1) THEN
		CLS
		COLOR 12, 0 'Red on black background for fails
		LOCATE 10
		PRINT TAB(10); "Error encountered! Notify engineering!";
		COLOR 11, 0     'Back to light cyan (blue) on black background              
		PRINT SPC(50);
		PRINT TAB(10); "Program will end now. Press any key.";
		'a$ = KEYBDIN$
		PRINT TAB(10); "Program will end now. Press the specified key.";
		a$ = WAITFORKEY("A", 10, 14, 0) 'Waits for "A" key press (display bright yellow on black)
		END 'End program
	END IF
END SUB

SUB FAILSTATUS (TSITE%, TESTVALUE$, YLOC%, XLOC%, TEXTVALUE$, SPACES%)
	'Sub to format and print the test value to the screen. The TSITE%
	'parameter lists the test channel ("Module #" in the text), while
	'TESTVALUE$ is the "PASS" or "FAIL" status. TEXTVALUE$ is the
	'text before the test value (usually "Status: "), while XLOC%
	'and YLOC% locate the displayed message on the screen. In the
	'special case of "XLOC%" = "-1", "YLOC%" contains the number of
	'spaces to tab over before displaying the message. SPACES%
	'then pads out the displayed line with the specified number of
	'spaces, in case messages written earlier need to be blanked
	'out. The "TESTVALUE$" string also sets the formatting: if the
	'leftmost 4 characters are "FAIL", the display is formatted to
	'red. Otherwise, it is formatted to green.
	'
	IF (LEFT$(TESTVALUE$, 4) = "FAIL") THEN
		COLOR 12, 0 'Test value text color to light red on black
	ELSE
		COLOR 10, 0 'Test value text color to light green on black
	END IF

	IF (XLOC% = -1) THEN
		'Tab over and print status text
		'PRINT TAB(YLOC%); TEXTVALUE$; TESTVALUE$; SPC(SPACES%);
		PRINT TAB(YLOC%); "MODULE #"; TSITE%; TEXTVALUE$; TESTVALUE$; SPC(SPACES%);
	ELSE
		'Locate and print status text
		'LOCATE YLOC%, XLOC%: PRINT TEXTVALUE$; TESTVALUE$; SPC(SPACES%)
		LOCATE YLOC%, XLOC%: PRINT "MODULE #"; TSITE%; TEXTVALUE$; TESTVALUE$; SPC(SPACES%);
	END IF

	IF (LEFT$(TESTVALUE$, 4) = "FAIL") THEN
		CALL CONTINUE
	ELSE
		IF (TESTPAUSE% = 1) THEN
			EATTHIS$ = INKEY$
			CALL CONTINUE
			'"Eat" the unnecessary yet possible "any" keystroke
			'press (likely the spacebar) after the status display.
		ELSE
			'If the test passed, "eat" the unnecessary yet possible "any" keystroke
			'press (likely the spacebar) after the status display.
			EATTHIS$ = INKEY$
			CALL PAUSE(1!)  'Wait 1 sec to view results
		END IF
	END IF
	
	'Text color back to light cyan (blue)
	COLOR 11, 0, 0  'Cyan on black background
		
END SUB

SUB HARDCOPY
	'Sub to ask if hardcopy printout is desired
	'
	COLOR 15, 0, 0  'Bright white on black
	CLS
	COLOR 20, 0, 0
	LOCATE 8, 15: PRINT "                   --  NOTE  --                   "
	COLOR 8, 0, 0   'Grey on black
	LOCATE 9, 15: PRINT "**************************************************"
	COLOR 14, 0, 0              'Yellow text on black
	LOCATE 11, 15: PRINT "      DO YOU WANT A HARD COPY PAPER PRINTOUT?     "
	LOCATE 12, 15: PRINT "           Y or y for YES, N or n for NO"
	COLOR 8, 0, 0   'Grey on black
	LOCATE 14, 15: PRINT "**************************************************"
	SOUND 400, 1
	PON% = 0
	COLOR 14, 0, 0  'Yellow on black
	DO
		HRDCPY$ = INKEY$
		HRDCPY$ = UCASE$(HRDCPY$)
	LOOP WHILE (HRDCPY$ <> "N") AND (HRDCPY$ <> "Y")

	IF HRDCPY$ = "Y" THEN
		PON% = 1
		CLS
		COLOR 15, 0, 0      'White text on black
		LOCATE 8, 15: PRINT "**************************************************"
		COLOR 14, 0, 0      'Yellow text on black
		LOCATE 10, 15: PRINT "ENSURE THAT THE PRINTER PAPER IS ALIGNED CORRECTLY"
		COLOR 15, 0, 0
		LOCATE 12, 15: PRINT "**************************************************"
		CALL CONTINUE
	END IF
	COLOR 11, 0, 0  'Cyan on black background
	CLS
END SUB

FUNCTION INSTRERROR$ (INSTRADDR%)
	'Function to read an error from the Agilent 34970A Data Acquisition System (DAS)
	'or 33120A Function Generator, depending on which instrument address is called
	'by the "INSTRADDR%" parameter. An error message is displayed if an invalid
	'instrument address is passed.
	'
	'The instrument error is cleared once it is read. The errors are stored FIFO
	'in the 34970A or 33120A, and the error indicator on the instrument is not
	'cleared until all errors are read. The instrument error string read is
	'passed as the return value of the function.
	'
	'Determine if a valid instrument address is passed.
	IF NOT ((INSTRADDR% = GENADDR%) OR (INSTRADDR% = DASADDR%)) THEN
		CLS
		LOCATE 10, 10: PRINT "                                                           "
		LOCATE 11, 10: PRINT "Invalid address in call to "; "INSTRERROR$"; " function!"
		LOCATE 12, 10: PRINT "Instrument address = "; INSTRADDR%
		CALL CONTINUE
		CLS
		INSTRERROR$ = "Invalid Error"   'Set function return to error string.
		EXIT FUNCTION   'Exit the function.
	END IF

	DDATA$ = "SYST:ERR?"    'Command to retrieve an error
	CALL IO488(DDATA$, INSTRADDR%, 1)   'Write command to instrument address.
	CALL IO488(DDATA$, INSTRADDR%, 2) 'Read string from instrument address (to DDATA$).
	'PRINT TAB(10); "Error string = "; DDATA$
	 INSTRERROR$ = DDATA$   'Set function return to string received from the instrument.
END FUNCTION

SUB INSTRERRORS (INSTRADDR%, DISPLAYERRS%)
	'Sub that clears the Agilent 34970A or 33120A error queue
	'(depending on which address is called by the "INSTRADDR%"
	'parameter). An error message is displayed if an invalid
	'instrument address is passed. If the "DISPLAYERRS%"
	'parameter is "1", the errors are also displayed to the
	'screen.
	'
	'The selected instrument error queue is cleared by
	'reading (and displaying) all of the stored errors.
	'
	'Determine if a valid instrument address is passed.
	IF NOT ((INSTRADDR% = GENADDR%) OR (INSTRADDR% = DASADDR%)) THEN
		CLS
		LOCATE 10, 10: PRINT "                                                           "
		LOCATE 11, 10: PRINT "Invalid address in call to "; "INSTRERRORS"; " sub!"
		LOCATE 12, 10: PRINT "Instrument address = "; INSTRADDR%
		CALL CONTINUE
		CLS
		EXIT SUB    'Exit the subroutine.
	END IF
	
	'Initialize error count
	ERRCOUNT% = 0
	DO  ' Error-read loop.
		ERRCOUNT% = ERRCOUNT% + 1           'Increment pass through error loop (error count)
		ERRVAL$ = INSTRERROR$(INSTRADDR%)   'Get error string from instrument using function.
		IF (VAL(ERRVAL$) <> 0) THEN         'If the error code is not zero (i.e., an actual error)
			IF (ERRCOUNT% = 1) THEN
				IF (DISPLAYERRS% = 1) THEN
					'Display messages (only) if flag is "1".
					'CLS
					'LOCATE 5
					PRINT
					PRINT "=========================================="
					IF (INSTRADDR% = GENADDR%) THEN
						PRINT "ERROR(S) WERE DETECTED IN AGILENT 33120A!"
					ELSE
						PRINT "ERROR(S) WERE DETECTED IN AGILENT 34970A!"
					END IF
					PRINT "ERROR CODES ARE SHOWN BELOW:"
				END IF
			END IF
			IF (DISPLAYERRS% = 1) THEN
				'Display messages (only) if flag is "1".
				PRINT "ERROR STRING = "; ERRVAL$
			END IF
		END IF
	LOOP WHILE VAL(ERRVAL$) <> 0            ' Exit loop when the error code is zero.
	IF (ERRCOUNT% > 1) THEN
		IF (DISPLAYERRS% = 1) THEN
			'Display messages (only) if flag is "1".
			PRINT "=========================================="
			PRINT
			CALL CONTINUE
		END IF
	END IF
END SUB

SUB INTERLUDE
	'Wait for user input. Prints message based on current cursor row, unlike
	'the library "CONTINUE" which prints on a fixed row
	COLOR 15, 0     'Bright white, black background
	'Y% = CSRLIN + 1
	'LOCATE Y%, 10: Print "Press any key to continue"
	PRINT ""
	PRINT TAB(10); "Press any key to continue"
	DO
		KB$ = INKEY$
	LOOP WHILE KB$ = ""
	COLOR 11, 0, 0  'Cyan on black background
END SUB

'***********************************
SUB LOGIT (STATUS$(), SN$, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), L%)
	'Sub to log test data to a ".DAT" file.
	'
	'NOTE:  Unlike most other legacy code, this version of LOGIT logs test data for
	'       both passing and failing modules.
	'
	'Open appropriate .DAT file.
	IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN OPEN "C:\ATE\5BLOG\" + RTRIM$(MID$(SPECS.MODNAME, 6, 8)) + ".DAT" FOR APPEND AS #4
	IF LEFT$(SPECS.MODNAME, 2) = "8B" THEN OPEN "C:\ATE\8BLOG\" + RTRIM$(MID$(SPECS.MODNAME, 3, 8)) + ".DAT" FOR APPEND AS #4
	IF LEFT$(SPECS.MODNAME, 4) = "DSCA" THEN OPEN "C:\ATE\DSCLOG\" + RTRIM$(MID$(SPECS.MODNAME, 5, 8)) + ".DAT" FOR APPEND AS #4

	NUMPTS% = 5 'Number of points for accuracy/linearity data
	
	'Build the sequential test-data (.DAT) file.  Seventeen (17) records (not
	'counting the accuracy/linearity data) is required for 1 module.
		WRITE #4, SPECS.MODNAME

	'Store accuracy/linearity data
		FOR INC% = 1 TO NUMPTS%
			WRITE #4, INSIM!(L%, INC%), OUTCALC!(L%, INC%), OUTMEAS!(L%, INC%), ERROROUT!(L%, INC%), ACCSTAT$(L%, INC%)
		NEXT

	'Store complete test data
		FOR INC% = 0 TO 14 STEP 5
			WRITE #4, STATUS$(INC% + 1, L%), STATUS$(INC% + 2, L%), STATUS$(INC% + 3, L%), STATUS$(INC% + 4, L%), STATUS$(INC% + 5, L%)
		NEXT
		WRITE #4, STATUS$(16, L%), STATUS$(17, L%)

		WRITE #4, SN$, DATE$
			 
		CLOSE #4
 
END SUB

'*********************************************
FUNCTION MEASRES! (OHM!, RESNUM%, L%)

	'Measure specified resistance
	'Inputs;    OHM!  Nominal value of resistor to be measured
	'           RESNUM%  Resistor to be measured
	'               1    Input current source sense resistor, 100 ohm
	'               2    Output current sense resistor, 250 ohm
	'               3    Output current sense resistor, 600 ohm
	'           L%    Channel where resistor is located (output sense only)
	 
	SELECT CASE RESNUM%                     'Branches to the specific measurement
	  
		CASE 1
			INITTOL! = .05                          '5% initial tolerance
			CALL DVMCONF(IINSEN2SOUR.CH%, RES4W$, "", OHM! * 1.2, "", 0)
			CALL DVMSENS(IINSEN2SOUR.CH%, RES4W$, INTTIME$, "", 20)   '6 1/2 digits, 25 bit resolution
			CALL DVMSENS(IINSEN2SOUR.CH%, RES4W$, OSCOMP$, "ON", 0)   'offset compensation ON
			RTEMP! = GETREADING!
			CALL DVMSENS(IINSEN2SOUR.CH%, RES4W$, OSCOMP$, "OFF", 0)  'offset compensation ON
		CASE 2
			INITTOL! = .05                          '1% initial tolerance
			CALL DVMCONF(IOUTSENDUT1SOUR.CH% + L% - 1, RES4W$, "", OHM! * 1.2, "", 0)
			CALL DVMSENS(IOUTSENDUT1SOUR.CH% + L% - 1, RES4W$, INTTIME$, "", 20)   '6 1/2 digits, 25 bit resolution
			CALL DVMSENS(IOUTSENDUT1SOUR.CH% + L% - 1, RES4W$, OSCOMP$, "ON", 0)   'offset compensation ON
			RTEMP! = GETREADING!
			CALL DVMSENS(IOUTSENDUT1SOUR.CH% + L% - 1, RES4W$, OSCOMP$, "OFF", 0)  'offset compensation ON
			CALL DVMCONF(IOUTSENDUT1SOUR.CH%, VDC$, "AUTO", 0, "", 0)
		CASE 3
			INITTOL! = .05                          '5% initial tolerance
			CALL DVMCONF(IOUTSENDUT1SOUR.CH% + L% - 1, RES2W$, "", OHM! * 1.2, "", 0)
			CALL DVMSENS(IOUTSENDUT1SOUR.CH% + L% - 1, RES2W$, INTTIME$, "", .02)    '4 1/2 digits, 15 bit resolution
			RTEMP! = GETREADING!
	END SELECT

	IF ABS(RTEMP! - OHM!) > (OHM! * INITTOL!) THEN  'Test for 15% deviation
		CLS
		LOCATE 10, 10
		PRINT "Channel number "; L%
		PRINT TAB(10); "Resistor number "; RESNUM%
		PRINT TAB(10); "Measured resistance = "; RTEMP!; " ohms."
		PRINT TAB(10); "Required resistance = "; OHM!; "ohms."
		PRINT TAB(10); "Check system setup and restart program."
		PRINT TAB(10); "If the failure continues, notify engineering."
		CALL SETDPS(DPSVINADDR%, 0) 'Set input voltage (at ext. supply) to 0V
		CALL SETDPS(DPSVINADDR2%, 0)
		SP1! = SETSCM5BPWR!(.01)                    'Set Vsupply to zero
		SP2$ = POWERIO$(DPSADDR%, SUPPLYOFF$)       'Turn off loop power
		SP2$ = POWERIO$(DPSADDR%, "LOC")            'Return to local mode
		END
	END IF

	MEASRES! = RTEMP!                               'Passes resistor value back

END FUNCTION

'*********************************
FUNCTION MENU1%
	KEY(10) ON  'Reactivates F10 key
	' ***** PROGRAM CONTROL MENU 1 *****
	CLS
	LOCATE 5, 20
	COLOR 14, 0, 0
	PRINT "SCM5Bxx, 8Bxx & DSCAxx AUTOMATED TEST EQUIPMENT"
	PRINT TAB(20); "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
	COLOR 11, 0, 0
	LOCATE 8
	PRINT TAB(24); "1.) Functional Test"
	'PRINT TAB(24); "2.) Complete Test (No Printout)"
	PRINT TAB(24); "2.) Pre-Encap Complete Test"
	PRINT TAB(24); "    (No Print)"
	'PRINT TAB(24); "3.) Complete Test (Print Results)"
	PRINT TAB(24); "3.) Post-Encap Complete Test"
	PRINT TAB(24); "    (Optional Print)"
	PRINT TAB(24); "4.) Sealed Module Retest"
	'PRINT TAB(28); "(Print Results, No Adjustments)"
	PRINT TAB(24); "    (Optional Print, No Adjustments)"
	PRINT TAB(24); "5.) Individual Test Menu"
	PRINT TAB(24); "6.) Return to the FAMILY TYPE menu"
	PRINT
	PRINT TAB(16); "Press the F10 key at any time to exit the program."
  
	DO
		I$ = INKEY$
	LOOP WHILE VAL(I$) < 1 OR VAL(I$) > 6

	MENU1% = VAL(I$)

END FUNCTION

'**********************************
FUNCTION MENU2%
	'Show Individual Test menu selections, and return number
	'for CASE statement of selected test.
	'
	CLS
	COLOR 14, 0, 0
	LOCATE , 20: PRINT "SCM5B & DSCA AUTOMATED TEST EQUIPMENT"
	LOCATE , 20: PRINT "-----------------------------------------"
	COLOR 11, 0, 0
	PRINT TAB(20); "1.) Supply Current Test"
	PRINT TAB(20); "2.) Output Switch Test"
	PRINT TAB(20); "3.) Offset & Gain Calibration"
	PRINT TAB(20); "4.) Linearity / Accuracy Test"
	'PRINT TAB(20); "5.) Accuracy Test, Std. Frequency Squarewave Input, C.F. = 1"
	'PRINT TAB(20); "6.) Accuracy Test, Std. Frequency Squarewave Input, C.F. = 2"
	'PRINT TAB(20); "7.) Accuracy Test, Std. Frequency Squarewave Input, C.F. = 3"
	'PRINT TAB(20); "8.) Accuracy Test, Std. Frequency Squarewave Input, C.F. = 4"
	'PRINT TAB(20); "9.) Accuracy Test, Std. Frequency Squarewave Input, C.F. = 5"
	'PRINT TAB(20); "A.) Accuracy Test, Min. Extended Frequency Sinewave Input"
	'PRINT TAB(20); "B.) Accuracy Test, Max. Extended Frequency Sinewave Input"
	PRINT TAB(20); "5.) Power Supply Sensitivity Test"  'Was C.
	'PRINT TAB(20); "D.) Step Response Test"
	PRINT TAB(20); "6.) Output Noise Test"              'Was E.
	PRINT TAB(20); "7.) Output Current @ Max. Load Test"    'Was F.
	PRINT TAB(20); "    (SCM5B\DSCAxx-xxC,E ONLY)"
	PRINT TAB(20); "8.) Notes On ATE Operation"         'Was G.
	PRINT TAB(20); "9.) Printer Output = ";             'Was H.
	IF PON% = 1 THEN
		PRINT "ON"
	ELSE
		PRINT "OFF"
	END IF
	'PRINT TAB(20); "I.) Log Linearity Test Data = ";
	''IF LOGDAT% > 0 THEN
	'IF LOGDAT% = 1 THEN
	'   PRINT "ON"
	'ELSE
	'   PRINT "OFF"
	'END IF
	PRINT TAB(20); "A.) Pause after each test  = ";     'Was J.
	IF TESTPAUSE% = 1 THEN
		PRINT "ON"
	ELSE
		PRINT "OFF"
	END IF
	PRINT TAB(20); "B.) Debug message flag     = ";     'Added.
	IF DEBUGFLAG% = 1 THEN
		PRINT "ON"
	ELSE
		PRINT "OFF"
	END IF
	PRINT TAB(20); "C.) Eject paper from printer";
	PRINT TAB(20); "D.) Exit to Main Menu"              'Was K, was C.
	PRINT
	PRINT TAB(20); "Enter your selection.  "
	'Get key.
	DO
		DO
			I$ = UCASE$(INKEY$)
		LOOP WHILE I$ = ""
		C% = ASC(I$)
		'Loop while screen entry is 1 to 9 (codes 49 to 57) or
		'A through Z (codes 65 to 90).
	LOOP WHILE (C% < 49 OR C% > 57) AND (C% < 65 OR C% > 90)
	'Change key value to case value.
	IF C% > 57 THEN
		'Really, this should be ">= 65" since the values between 57 ("9") and
		'64 ("@") are not valid.
		'
		'Translate character values of A to Z (65 to 90) to integer values of 10 through 35
		MENU2% = C% - 55
	ELSE
		'Translate character values of 1 to 9 to integer values of 1 through 9
		MENU2% = C% - 48
	END IF

END FUNCTION

'********************************8
FUNCTION MENU3%
	  
	CLS
	COLOR 14, 0, 0
	LOCATE 3, 26: PRINT "Module Family Selection Menu"
	PRINT TAB(26); "----------------------------"
	PRINT
	COLOR 11, 0, 0
	PRINT TAB(26); "1.) SCM5Bxx-xxxx"
	PRINT TAB(26); "2.) DSCAxx-xxxx"
	PRINT TAB(26); "3.) 8Bxx-xxxx"
	PRINT TAB(26); "4.) Return to the FAMILY TYPE menu"

	DO
		I$ = INKEY$
	LOOP WHILE VAL(I$) < 1 OR VAL(I$) > 4

	MENU3% = VAL(I$)

END FUNCTION

'*********************************
SUB MODOUTLINE

	'print a bottom view of the module showing potentiometer location
	
	IF SPECS.NOMVS = 5 THEN             '8B and SCM5B
	  
										'print module pins and potentiometers
		LOCATE 4
		PRINT TAB(25); " x  x  x        x  x  x  x"
		PRINT TAB(25); "x  x  x          x  x  x  x"
		LOCATE 5, 40
		PRINT CHR$(233)
		LOCATE 5, 54
		PRINT CHR$(233)
		LOCATE 3, 23
		PRINT CHR$(201)
	  
		FOR a = 4 TO 5                  'print left vertical line
			LOCATE a, 23
			PRINT CHR$(186)
		NEXT a
  
		LOCATE 6, 23
		PRINT CHR$(200)
		FOR a = 24 TO 55                'print top horizontal line
			LOCATE 3, a
			PRINT CHR$(205)
		NEXT a

		LOCATE 3, 56
		PRINT CHR$(187)
		FOR a = 4 TO 5                  'print right vertical line
			LOCATE a, 56
			PRINT CHR$(186)
		NEXT a
  
		LOCATE 6, 56
		PRINT CHR$(188)
		FOR a = 24 TO 55                'print bottom horizontal line
			LOCATE 6, a
			PRINT CHR$(205)
		NEXT a
  
	ELSE                                'DSCA
	  
		LOCATE 4, 36                    'print potentiometer locations
		PRINT CHR$(233)
		LOCATE 4, 44
		PRINT CHR$(233)
		LOCATE 5, 40
		PRINT CHR$(15)                  'print LED
	  
		LOCATE 3, 25                    'print top left corner
		PRINT CHR$(201)
	  
		FOR a = 4 TO 5                  'print left vertical line
			LOCATE a, 25
			PRINT CHR$(186)
		NEXT a
	
		LOCATE 6, 25
		PRINT CHR$(200)
		FOR a = 26 TO 54                'print top horizontal line
			LOCATE 3, a
		PRINT CHR$(205)
		NEXT a

		LOCATE 3, 55
		PRINT CHR$(187)
		FOR a = 4 TO 5                  'print right vertical line
			LOCATE a, 55
			PRINT CHR$(186)
		NEXT a
	
		LOCATE 6, 55
		PRINT CHR$(188)
		FOR a = 26 TO 54                'print bottom horizontal line
			LOCATE 6, a
			PRINT CHR$(205)
		NEXT a

	END IF

END SUB

'***********************************
FUNCTION MODULEOUT! (SENOUT!)

	'Calculates the module output for a given input (sensor output)

	MINOUT! = SPECS.MINOUT                  'V or A
	MAXOUT! = SPECS.MAXOUT
	MININ! = SPECS.MININ
	MAXIN! = SPECS.MAXIN
   
	ORANGE! = MAXOUT! - MINOUT!             'Output range (V or A)
	INRANGE! = MAXIN! - MININ!              'Input range
 
	XFERFN! = ORANGE! / INRANGE!
	YINT! = MINOUT! - MININ! * XFERFN!      'Y-intercept
	MODULEOUT! = XFERFN! * SENOUT! + YINT!  'Output voltage (V or mA)

END FUNCTION

'******************************
SUB NOTES
	  
	'Notes on ATE operation

	CLS
	LOCATE 5, 25
	PRINT "AUTOMATED TEST EQUIPMENT NOTES"
	PRINT
	PRINT TAB(10); "1.) During the calibration subroutines the following keystrokes"
	PRINT TAB(14); "can be used:"
	PRINT
	PRINT TAB(14); "(C)alibrate will exit the routine and continue"
	PRINT TAB(14); "program execution."
	PRINT
	PRINT TAB(10); "2.) Press (F10) at any time to break out of the program and"
	PRINT TAB(14); "return to DOS."
	CALL CONTINUE

END SUB

'*********************************
SUB OFFSETCAL (CAL%, NUMDUT%, STATUS$())
	'Calibrate module offset
	'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
	'       NUMDUT% = number of Devices Under Test
	'
	'Outputs        STATUS$(13, n)   array of results
	'
	MINOUT! = SPECS.MINOUT                  'V or A
	MAXOUT! = SPECS.MAXOUT
	CALOS! = SPECS.OSCALPT / 100!           'Convert from %
	INITTOL! = 8                            'Uncalibrated offset tolerance (%)
	CALTOL! = SPECS.CALTOL                  'Calibration tolerance (%)
	OSCALIN! = SPECS.OSCALIN                'Module input for offset calibration
	FINCAL! = SPECS.FINCAL                  'Input waveshape frequency (Hz)
	ADJ! = SPECS.ADJ! / 100!                'Adjustment range, %
	NOMVS! = SPECS.NOMVS!
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE$
 
	ORANGE! = MAXOUT! - MINOUT!             'Output range (V or A)
	CALSPAN! = ORANGE!
	 
	CLS
	TESTTITLE$ = "Offset Calibration"
	CALL HEADERB(TESTTITLE$, 0)
  
	'IF CAL% = 2 THEN
	IF (CAL% = 2) OR (TTYPE% = 1) THEN
		ZERROR! = INITTOL!                  'Offset tolerance for func. test (%)
		TOL! = .0001 * ORANGE!              'Measurement tolerance, 1 pass test
	ELSE
		IF CAL% = 0 THEN
			CALL MODOUTLINE
			LOCATE 7
			TB1% = 26
			TB2% = 29
			PRINT TAB(TB1%); "Refer to label on board for";
			PRINT TAB(TB2%); "offset potentiometer";
		END IF
		ZERROR! = CALTOL!                   'Offset calibration tolerance (%)
		TOL! = 0!                           'Measurement tolerance, continuous test
	END IF

	LOCATE 12, 10
	PRINT TAB(10); "Measuring input.  Please wait...          "
  
	FOR L% = 1 TO NUMDUT%
		CONREADS% = 0
		LOCATE 1
		IF L% <> 1 THEN
			CALL HEADERB(TESTTITLE$, 0)
		END IF
		
		'Check if module previously failed supply current
		'(removed from test head), offset cal or gain cal.
		IF LEFT$(STATUS$(1, 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%

			MININMEAS! = SETDUTIN!(OSCALIN!)
			OUTCALC! = MODULEOUT!(MININMEAS!) + CALOS! * ORANGE!
			
			IF OUTSIGTYPE$ = "CURRENT" THEN
				CH% = IOUTSENDUT1SEN.CH%
			ELSE
				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)
		  
			LOCATE 12, 10
			PRINT "Offset Error =";
			PRINT SPC(30);
	  
			DO
				ERROROUT! = (GETREADING! / IOUTSEN1.MEAS!(L%) - OUTCALC!) / CALSPAN! * 100!'Error in %
				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!) < ZERROR! THEN
					SOUND 200, .5
					PRINT "Stop turning offset potentiometer          "
					CONREADS% = CONREADS% + 1
				ELSEIF ERROROUT! < 0 THEN
					PRINT "Turn offset potentiometer clockwise        "
					CONREADS% = 0
				ELSE
					PRINT "Turn offset 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
			LOOP WHILE CONREADS% < 5

			IF CAL% = 0 OR CAL% = 2 THEN
				'DIG$ = "5"     'Flag.  Don't print result
				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!) <= ZERROR! THEN
					OFF$ = "PASS"
				ELSE
					OFF$ = "FAIL"
					SOUND 1000, .5
					'Display results if test failed.
					DIG$ = "3"  'Display/print result to # of decimal places.
				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: "; OFF$;
				LOCATE 16, 10   'Added
				PRINT SPC(31);
				PRINT TAB(10); "Offset calibration error is";
				PRINT TAB(50); USING " +###.### %"; ERROROUT!
				PRINT TAB(10); "Max. offset calibration error is";
				PRINT TAB(50); USING "+/-##.### %"; ZERROR!
				CALL FAILSTATUS(L%, OFF$, 15, 10, "Status: ", 20)       'Print test status to screen
			ELSE
				OFF$ = "PASS"
				DIG$ = "5"                  'Flag.  Don't print result
			END IF
		  
			STATUS$(13, L%) = OFF$ + STR$(ERROROUT!) + DIG$

		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!)
		LOCATE 15, 10
		PRINT SPC(55);
		LOCATE 16, 10
		PRINT SPC(55);
		LOCATE 17, 10
		PRINT SPC(55);
		PRINT
		CLS
	NEXT

	SN$ = SERNO$(1)

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

'*****************************
SUB OUTPUTNOISE (NUMDUT%, STATUS$())
	'Measure module output noise (Vrms or mArms)
	'Inputs;    NUMDUT% = number of Devices Under Test
	'Outputs;   STATUS$(16, n)   array of results
	'
	MAXIN! = SPECS.MAXIN
	MINOUT! = SPECS.MINOUT
	MAXOUT! = SPECS.MAXOUT
	FINCAL! = SPECS.FINCAL
	SPEC! = SPECS.OUTNOISE                  '% span, RMS
	MEASTOL! = .04                          '4%
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE
	NOMVS! = SPECS.NOMVS

	ORANGE! = MAXOUT! - MINOUT!

	 IF OUTSIGTYPE$ <> "CURRENT" THEN
	 CALL SETOUTLOAD(IOUTSEN3!, 4)
	 END IF

	CLS
	TESTTITLE$ = "Output Noise Test"
	CALL HEADERB(TESTTITLE$, 0)
 
	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
		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%
  
		  
			IF OUTSIGTYPE$ = "CURRENT" THEN
				CALL SETOUTLOAD(IOUTSEN2!, NUMDUT%)  'Set max load resistor
				RL! = IOUTSEN2!
			ELSE
				RL! = 1
			END IF

			IF OUTSIGTYPE$ = "CURRENT" THEN
				CH% = IOUTSENDUT1SEN.CH%
			ELSE
				IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
				'IF NOMVS! = 5 THEN                      'SCM5B
					'CH% = IOUTSENDUT1SOUR.CH%
					CH% = VOUTDUT1.CH%
				ELSE                                    'DSCA
					CH% = IOUTSENDUT1SOUR.CH%
				END IF
			END IF
			CALL DVMCONF(CH% + L% - 1, VAC$, AUTO$, 0, "", 0)
			CALL DVMSENS(CH% + L% - 1, VAC$, BW$, "", 20)      'Set bandwidth for fastest reading.
			I = 0
			DO                  'Make sure noise reading is stable
			   
			OUTRMS! = GETREADING! / RL! / ORANGE! * 100 'Dummy reading, first reading
													'can be high.
			'OUTRMS! = GETREADING! / RL! / ORANGE! * 100
			  I = I + 1
			 LOOP WHILE (OUTRMS! > SPEC! AND I < 3)

			IF OUTRMS! <= SPEC! THEN
				NOISE$ = "PASS"
			ELSE
				NOISE$ = "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: "; NOISE$;
			LOCATE 16, 10   'Added
			PRINT SPC(20);
			PRINT TAB(10); "Measured output noise is";
			PRINT TAB(50); USING "#.### % span "; OUTRMS!
			PRINT TAB(10); "Maximum output noise is";
			PRINT TAB(50); USING "#.### % span "; SPEC!

			CALL FAILSTATUS(L%, NOISE$, 15, 10, "Status: ", 20)         'Print test status to screen
			
			STATUS$(16, L%) = NOISE$ + STR$(OUTRMS!) + "3"
	
			IF OUTSIGTYPE$ = "CURRENT" THEN
				CALL SETOUTLOAD(IOUTSEN1!, NUMDUT%) 'Set current output sense resistor
			END IF
		  
		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)
END SUB

SUB OUTSWITCH (NUMDUT%, STATUS$())
	'This routine tests the operation of the SCM5B module output switch
	'Inputs;    NUMDUT% = number of Devices Under Test
	'Outputs;   STATUS$(2,n)   array of results
	'
	MAXIN! = SPECS.MAXIN
	MAXOUT! = SPECS.MAXOUT
	FINCAL! = SPECS.FINCAL                  'Input wave frequency (Hz)
	NOMVS! = SPECS.NOMVS
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE
	TOL! = .15  '15% reading tolerance allows for offset & gain not calibrated.

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

	IF (LEFT$(SPECS.MODNAME, 4) = "DSCA") OR (LEFT$(SPECS.MODNAME, 2) = "8B") THEN         '8B or DSCA
		LOCATE 10, 10: PRINT "This test is not performed on model "; SPECS.MODNAME
		EXIT SUB
	END IF

	MAXINMEAS! = SETDUTIN!(MAXIN!)
	OUTCALC! = MODULEOUT!(MAXINMEAS!)

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

		MAXINMEAS! = SETDUTIN!(MAXIN!)
		OUTCALC! = MODULEOUT!(MAXINMEAS!)
		
		'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 10, 25: PRINT "TESTING DEVICE IN CHANNEL #"; L%
			CH% = ERRORVALUE                    ' dummy value
			IF OUTSIGTYPE$ = "CURRENT" THEN
				CH% = IOUTSENDUT1SEN.CH%
			ELSE    'IF OUTSIGTYPE$ = "VOLTAGE" THEN
				'IF NOMVS! = 5 THEN
				IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
					CH% = VOUTDUT1.CH%
				ELSE
					'DSCA or 8B
					CH% = IOUTSENDUT1SOUR.CH%
				END IF
			END IF
			CALL DVMCONF(CH% + L% - 1, VDC$, "", OUTCALC! * IOUTSEN1.MEAS!(1), "", 0)
			CALL DVMSENS(CH% + L% - 1, VDC$, INTTIME$, "", .02)'4 1/2 digits, 15 bit resolution
		 
			'Measure output (enabled "no load").
			OUTNL! = GETREADING! / IOUTSEN1.MEAS!(L%)
			OUTREQ! = MAXOUT!

			OUTMEAS! = OUTNL!
			OUTSW$ = "PASS"     'Initialize to passing status.

			IF ABS(OUTNL! - MAXOUT!) > MAXOUT! * TOL! THEN
				'Enabled "no load" output test failed.
				OUTSW$ = "FAIL"
				'PRINT "FAIL - ON"
				'PRINT "OUTNL = "; OUTNL!
				'PRINT "MAXOUT = "; MAXOUT!
				'CALL CONTINUE
			ELSE
				'If the "no load" measurement passes, set up and measure the "disabled" output.
				CALL ENABLE(L%, 1)      'Disable output switch.
				CALL PAUSE(.5)          '1Mohm load takes time to pull output down.
				OUTDIS! = GETREADING! / IOUTSEN1.MEAS!(L%)   'Measure output.
				IF ABS(OUTDIS!) > MAXOUT! * TOL! THEN
					'Disabled output test failed.
					OUTSW$ = "FAIL"
					OUTREQ! = 0!
					OUTMEAS! = OUTDIS!
					'PRINT "FAIL - OFF"
					'PRINT "OUTDIS = "; OUTDIS!
					'PRINT "MAXOUT = "; MAXOUT!
					'CALL CONTINUE
				END IF
			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: "; OUTSW$;
			LOCATE 16, 10   'Added
			UNIT$ = ""
			IF OUTSIGTYPE$ = "CURRENT" THEN UNIT$ = "mA"
			IF OUTSIGTYPE$ = "VOLTAGE" THEN UNIT$ = "V"
			PRINT TAB(10); "Measured "; "no load"; " output is";
			'PRINT TAB(50); USING "+##.## &"; OUTMEAS!; UNIT$
			PRINT TAB(50); USING "+##.## &"; OUTNL!; UNIT$
			PRINT TAB(10); "Required output is";
			PRINT TAB(50); USING "+##.## & to ##.## &"; OUTREQ! - (MAXOUT! * TOL!); UNIT$; OUTREQ! + (MAXOUT! * TOL!); UNIT$
			'Added.
			PRINT TAB(10); "Measured "; "disabled"; " output is";
			PRINT TAB(50); USING "+##.## &"; OUTDIS!; UNIT$
			PRINT TAB(10); "Required output is";
			PRINT TAB(50); USING "+##.## & to ##.## &"; -(MAXOUT! * TOL!); UNIT$; (MAXOUT! * TOL!); UNIT$
			
			CALL FAILSTATUS(L%, OUTSW$, 15, 10, "Status: ", 20)         'Print test status to screen
			
			IF OUTSW$ = "FAIL" THEN
				SOUND 1000, .5
				LOCATE 21, 10   'Added
				PRINT TAB(10); "Check for correct signals on output switch."
				CALL CONTINUE
			END IF
			IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
				CALL ENABLE(L%, 0)                  'Enable output switch
			END IF
			'Append # decimal places: 6 = don't print numerical data
			STATUS$(2, L%) = OUTSW$ + "6"
		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)
END SUB

'****************************
SUB REPORT (STATUS$(), SN$, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), TSPEC$(), NUMDUT%, TTYPE%)       'Prints test data on screen
	'Sub to print or display the test results. The data be sent to two
	'three places (screen, printer, and datasheet file), so when updating,
	'remember to make any changes to both the "PRINT" and "LPRINT" sections
	'in the initial part of the sub, and to the datasheet file write section
	'at the end of the sub.
	'
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE          'Used to set output display units
	FINCAL! = SPECS.FINCAL
	FINMAX! = SPECS.FINMAX
	FINEXTMAX! = SPECS.FINEXTMAX
	NUMPTS% = 5                             'Number of points (steps) in accuracy/linearity test
	MAXIN! = SPECS.MAXIN                    'Use to set input display units
	INPUTTYPE$ = "ERROR"                    'Used to set input display units (initialize to dummy value)
	
	'Initialize input type and output units and scaling
	INPUTTYPE$ = "ERROR"
	UNIT$ = ""
	IF OUTSIGTYPE$ = "VOLTAGE" THEN
		UNIT$ = "V"
		OUTSCALE! = 1!
	END IF
	IF OUTSIGTYPE$ = "CURRENT" THEN
		UNIT$ = "mA"
		OUTSCALE! = 1000!
	END IF
	IF MAXIN! >= 1 THEN
		INPUTTYPE$ = " Vin (VDC)"
	ELSE
		INPUTTYPE$ = "Vin (mVDC)"
	END IF
   
	FOR L% = 1 TO NUMDUT%
		RESTORE LINES   'Get test names and units
		CLS
		LOCATE 5, 5: PRINT "THE FOLLOWING DATA IS FOR THE DEVICE IN CHANNEL #"; L%
		PRINT
		PRINT
		'CALL PAUSE(1)
		
		LOCALSN$ = SERNO$(L%)   'Get current serial number (serial number for channel being tested)
		CALL HEADERA(LOCALSN$)  'Prints data sheet header on printer using the current serial number
		
		'Accuracy/linearity test results
		IF LEFT$(STATUS$(1, L%), 4) <> "FAIL" AND LEFT$(STATUS$(13, L%), 4) <> "FAIL" AND LEFT$(STATUS$(14, L%), 4) <> "FAIL" THEN
			'If the module did not fail Supply Current, Offset or Gain tests
			'

			IF (TTYPE% <> 1) THEN   'If not functional test.
					'****************** screen display ********************
					PRINT TAB(34); "ACCURACY TEST"
					PRINT
					PRINT TAB(20); "Calculated"; TAB(38); "Measured"
					
					PRINT TAB(5); INPUTTYPE$;
					
					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); "--------"
					FOR INC% = 1 TO NUMPTS%
						PRINT TAB(6); USING "+###.###      +###.###         +###.###        +###.###"; INSIM!(L%, INC%); (OUTCALC!(L%, INC%)) * OUTSCALE!; OUTMEAS!(L%, INC%); ERROROUT!(L%, INC%);       _
' 02/15/06  1.15        MR
						'PRINT TAB(69); ACCSTAT$(L%, INC%)
						IF (LEFT$(ACCSTAT$(L%, INC%), 4) = "FAIL") THEN
							COLOR 12, 0 'Test value text color to light red on black
						ELSE
							COLOR 10, 0 'Test value text color to light green
						END IF
						PRINT TAB(69); ACCSTAT$(L%, INC%)
						COLOR 11, 0, 0  'Cyan on black background
					NEXT
					'DUMKEY$ = WAITFORKEY("F", 10, 14, 0)   'Waits for "F" key press (display bright yellow on black)
					'*********************************

					'****************** paper print ********************
					IF PON% = 1 THEN
						LPRINT TAB(34); "ACCURACY TEST"
						LPRINT
						LPRINT TAB(20); "Calculated"; TAB(38); "Measured"
						
						LPRINT TAB(5); INPUTTYPE$;
						
						LPRINT TAB(19); "Output ("; UNIT$; "DC)"; TAB(36); "Output ("; UNIT$; "DC)*";
						LPRINT TAB(54); "Error (%)"; TAB(68); "Status"
						LPRINT TAB(5); "----------"; TAB(19); "------------"; TAB(36); "-------------";
						LPRINT TAB(53); "----------"; TAB(67); "--------"
						FOR INC% = 1 TO NUMPTS%
							LPRINT TAB(6); USING "+###.###      +###.###         +###.###        +###.###"; INSIM!(L%, INC%); (OUTCALC!(L%, INC%)) * OUTSCALE!; OUTMEAS!(L%, INC%); ERROROUT!(L%, INC%);
							LPRINT TAB(69); ACCSTAT$(L%, INC%)
						NEXT
					END IF
					'*********************************
			END IF
		END IF
		
		'Main test results
		'
		'Output format
		'1        10        20        30        40        50        60        70        80
		'         |         |         |         |         |         |         |         |
		'            Parameter          Measured Value*     Specification     Status
		'    =========================  ===============  ===================  ======
		'                                 ###### uVrms     ## to ### uVrms     PASS
		'                                                            ohm/ohm
		'******************** screen display ********************************
		'CLS
		PRINT
		PRINT TAB(31); "FINAL TEST RESULTS"
		PRINT
		PRINT TAB(13); "Parameter"; TAB(32); "Measured Value*"; TAB(52); "Specification ";
		PRINT TAB(70); "Status"
		PRINT TAB(5); "========================="; TAB(32); "===============";
		PRINT TAB(49); "==================="; TAB(70); "======"
		'*********************************

		'******************** Paper Print ********************************
		IF PON% = 1 THEN
			LPRINT
			LPRINT TAB(31); "FINAL TEST RESULTS"
			LPRINT
			LPRINT TAB(13); "Parameter"; TAB(32); "Measured Value*"; TAB(52); "Specification ";
			LPRINT TAB(70); "Status"
			LPRINT TAB(5); "========================="; TAB(32); "===============";
			LPRINT TAB(49); "==================="; TAB(70); "======"
		END IF
		'*********************************

		'FOR X% = 1 TO 17
		FOR x% = 1 TO MAXSTATUSINDEX
			READ a$, B$ 'Read test names and units from LINES data.
			'Locally set the test names and units for selected tests
			SELECT CASE x%
				CASE 3
					'A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz Sine"
					a$ = "Accuracy"
				CASE 4
					'A$ = "Linearity, " + LTRIM$(STR$(FINCAL!)) + "Hz Sine"
					a$ = "Linearity"
				'The following lines were inherited from the RMS test program.
				'These tests are not run for the high-voltage voltage-input
				'modules, so the lines are commented out.
				'CASE 5
				'   A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz Square"
				'CASE 6
				'   A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz, C.F.= 2"
				'CASE 7
				'   A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz, C.F.= 3"
				'CASE 8
				'   A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz, C.F.= 4"
				'CASE 9
				'   A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz, C.F.= 5"
				'CASE 10
				'   A$ = "Accuracy, " + LTRIM$(STR$(FINMAX!)) + "Hz Sine"
				'CASE 11
				'   A$ = "Accuracy, " + LTRIM$(STR$(FINEXTMAX!)) + "Hz Sine"
			END SELECT


			IF RIGHT$(STATUS$(x%, L%), 1) <> "5" AND LEN(STATUS$(x%, L%)) > 0 THEN
				'-------------------------------------------------------------------------------
				'Parse the STATUS (test results) data if the number of characters
				'is more than zero and the rightmost character (the # of decimal
				'places to be displayed) is not "5". The general format of the
				'STATUS data is shown below:
				'
				'STATUS$(X%, L%) format = <pass/fail> + <measured data> + <# decimal places>
				'                            4 char.         ? char            1 char.
				'
				'The number of decimal places character is used to control the
				'display/print format of the test results, and usually specifies
				'the number of decimal places to show. The special value of "5"
				'for # of decimal places is used by the OFFSET and GAIN (and
				'perhaps other) tests as a flag to prevent the display or printing
				'of the results of that test.
				'-------------------------------------------------------------------------------

				'Display (and print) test name
				PRINT TAB(5); a$;
				IF PON% = 1 THEN LPRINT TAB(5); a$;
				
				DATALEN% = LEN(STATUS$(x%, L%))
				NUMDATA! = VAL(MID$(STATUS$(x%, L%), 5, DATALEN% - 5))

				'Set test units for Supply Sensitivity test depending on module supply voltage
				IF x% = 12 THEN
					IF SPECS.NOMVS = 5 THEN         'SCM5B or 8B
						B$ = "ppm/%"
					ELSE                            'DSCA
						B$ = "%/%"
					END IF
				END IF

				'Display or print using requested # of decimal places
				IF RIGHT$(STATUS$(x%, L%), 1) = "0" THEN
					PRINT TAB(34); USING "###### &"; NUMDATA!; B$;
					IF PON% = 1 THEN LPRINT TAB(34); USING "###### &"; NUMDATA!; B$;
				ELSEIF RIGHT$(STATUS$(x%, L%), 1) = "1" THEN
					PRINT TAB(34); USING "####.# &"; NUMDATA!; B$;
					IF PON% = 1 THEN LPRINT TAB(34); USING "###### &"; NUMDATA!; B$;
				ELSEIF RIGHT$(STATUS$(x%, L%), 1) = "2" THEN
					PRINT TAB(34); USING "###.## &"; NUMDATA!; B$;
					IF PON% = 1 THEN LPRINT TAB(34); USING "###.## &"; NUMDATA!; B$;
				ELSEIF RIGHT$(STATUS$(x%, L%), 1) = "3" THEN
					PRINT TAB(34); USING "##.### &"; NUMDATA!; B$;
					IF PON% = 1 THEN LPRINT TAB(34); USING "##.### &"; NUMDATA!; B$;
				ELSEIF RIGHT$(STATUS$(x%, L%), 1) = "4" THEN
					PRINT TAB(34); USING "#.#### &"; NUMDATA!; B$;
					IF PON% = 1 THEN LPRINT TAB(34); USING "#.#### &"; NUMDATA!; B$;
				END IF
				'DP = 5: don't display or print spec. in final report.
				'DP = 6: don't display or print numerical data

				SPECLEN% = LEN(TSPEC$(x%))
				IF (TTYPE% = 1) THEN
					'Functional test. Set different limits for
					'offset and gain measurements.
					IF (x% = 13) OR (x% = 14) THEN
						'Offset or measurement. Hardcoded value (check
						'against the INITTOL! value hardcoded in OFFSETCAL
						'or GAINCAL).
						PRINT TAB(60 - SPECLEN%); 8!;
						IF PON% = 1 THEN
							LPRINT TAB(60 - SPECLEN%); 8!;
						END IF
					END IF
				ELSE
					'Not a functional test. Get limits from TSPEC$ array.
					PRINT TAB(60 - SPECLEN%); TSPEC$(x%);
					IF PON% = 1 THEN
						LPRINT TAB(60 - SPECLEN%); TSPEC$(x%);
					END IF
				END IF
				PRINT TAB(61); B$;
				IF PON% = 1 THEN
					LPRINT TAB(61); B$;
				END IF

				'PRINT TAB(71); LEFT$(STATUS$(X%, L%), 4)
				IF (LEFT$(STATUS$(x%, L%), 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(71); LEFT$(STATUS$(x%, L%), 4)
				COLOR 11, 0, 0  'Cyan on black background

				IF PON% = 1 THEN LPRINT TAB(71); LEFT$(STATUS$(x%, L%), 4)

			END IF
		NEXT

		IF (TTYPE% <> 1) AND (TTYPE% <> 2) THEN
			'Call FOOTER routine if not Functional or Pre-Encap test.
			CALL FOOTER(STATUS$(), L%)          'Prints footer if no fails
		ELSE
			IF PON% = 1 THEN LPRINT CHR$(12)    'Send form feed to printer (regardless of module test status)
		END IF
		
		'NOTE:  if the printer is slow, may need to ask if the sheet has
		'       printed for each page (within the DO/NEXT loop, above)
		'       or the printer buffer may overrun and cause the program
		'       to crash.
		PRINT
		IF (PON% = 1) THEN
			PRINT TAB(10); "Has the hardcopy finished printing for channel "; L%; " ?"
		END IF
		DUMKEY$ = WAITFORKEY("F", 10, 14, 0)    'Waits for "F" key press (display bright yellow on black)
		
		'-------------------------------------------------------------------------
		'BELOW: Code to write to datasheet file(s) if the module has passed
		'       all tests and the text file flag is "on", to write a status
		'       line to the work order status file if the text file
		'       flag is "on" (regardless of the pass/fail status of the
		'       tested module), and to log the test data.
		'-------------------------------------------------------------------------
		IF (TX% = 1) AND (FAILS%(STATUS$(), L%) = 0) THEN
			'No failures and text file flag is "on"

			KEY(10) OFF 'Deactivates F10 key to keep datasheet file process from being interrupted

			LOCALSN$ = SERNO$(L%)   'Get current serial number (serial number for channel being tested)
			CALL GETDSFNAME(LOCALSN$, DSSNAME$, DSFNAME$)   'Get datasheet search and file names from serial number
			CLS
			LOCATE 10
			PRINT ""    'Blank line
			PRINT TAB(10); "Writing data for module in channel #: "; L%

			CALL GETDSFNAME(LOCALSN$, DSSNAME$, DSFNAME$)
			PRINT TAB(10); "Writing datasheet file: "; DSFNAME$
			'Get datasheet search and file names from serial number

			'Open datasheet file
			OPEN "C:\STAGE\" + DSFNAME$ FOR OUTPUT AS #9    'Open datasheet file

			'------------
			'Write header
			'------------
			PRINT #9, TAB(5);
			FOR x = 5 TO 75
			PRINT #9, "=";
			NEXT

			PRINT #9, TAB(5); "DATAFORTH CORPORATION"; TAB(51); "Phone: (520) 741-1404"
			PRINT #9, TAB(5); "3331 E. Hemisphere Loop"; TAB(51); "Fax:   (520) 741-0762"
			PRINT #9, TAB(5); "Tucson, AZ  85706  USA"; TAB(51); "email: info@dataforth.com"
			PRINT #9,
			PRINT #9, TAB(33); "TEST DATA SHEET"
			PRINT #9, TAB(5);
			FOR x = 5 TO 75
					PRINT #9, "~";
			NEXT
			PRINT #9, TAB(5); "Date:  "; DATE$
			PRINT #9, TAB(5); "Model: "; SPECS.MODNAME
			PRINT #9, TAB(5); "SN:    "; TAB(12); LOCALSN$
			PRINT #9,
			
			'NOTE:  Most values, calculations, and input type,
			'       scaling and units have already been
			'       calculated or selected above.

			'-----------------------
			'Write accuracy results
			'-----------------------
			'Write accuracy header
			PRINT #9, TAB(34); "ACCURACY TEST"
			PRINT #9,
			PRINT #9, TAB(20); "Calculated"; TAB(38); "Measured"

			PRINT #9, TAB(5); INPUTTYPE$;

			PRINT #9, TAB(19); "Output ("; UNIT$; "DC)"; TAB(36); "Output ("; UNIT$; "DC)*";
			PRINT #9, TAB(54); "Error (%)"; TAB(68); "Status"
			PRINT #9, TAB(5); "----------"; TAB(19); "------------"; TAB(36); "-------------";
			PRINT #9, TAB(53); "----------"; TAB(67); "--------"

			'Write accuracy results
			FOR INC% = 1 TO NUMPTS% STEP 1
				PRINT #9, TAB(6); USING "+###.###      +###.###         +###.###        +###.###"; INSIM!(L%, INC%); (OUTCALC!(L%, INC%)) * OUTSCALE!; OUTMEAS!(L%, INC%); ERROROUT!(L%, INC%);
				PRINT #9, TAB(69); ACCSTAT$(L%, INC%)
			NEXT
			
			'-------------------------------------------
			'Write test results (except accuracy steps)
			'-------------------------------------------
			'Output format
			'1        10        20        30        40        50        60        70        80
			'         |         |         |         |         |         |         |         |
			'            Parameter          Measured Value*     Specification     Status
			'    =========================  ===============  ===================  ======
			'                                 ###### uVrms     ## to ### uVrms     PASS
			'                                                            ohm/ohm
			'
			'Write all-tests header
			PRINT #9,
			PRINT #9, TAB(31); "FINAL TEST RESULTS"
			PRINT #9,
			PRINT #9, TAB(13); "Parameter"; TAB(32); "Measured Value*"; TAB(52); "Specification ";
			PRINT #9, TAB(70); "Status"
			PRINT #9, TAB(5); "========================="; TAB(32); "===============";
			PRINT #9, TAB(49); "==================="; TAB(70); "======"

			'Write all-tests results
			RESTORE LINES   'Get test names and units from data listing
			FOR x% = 1 TO MAXSTATUSINDEX
				READ a$, B$ 'Read test names and units from LINES data
				'Locally set the test names and units for selected tests
				SELECT CASE x%
					CASE 3
						'A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz Sine"
						a$ = "Accuracy"
					CASE 4
						'A$ = "Linearity, " + LTRIM$(STR$(FINCAL!)) + "Hz Sine"
						a$ = "Linearity"
					'The following lines were inherited from the RMS test program.
					'These tests are not run for the high-voltage voltage-input
					'modules, so the lines are commented out.
					'CASE 5
					'   A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz Square"
					'CASE 6
					'   A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz, C.F.= 2"
					'CASE 7
					'   A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz, C.F.= 3"
					'CASE 8
					'   A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz, C.F.= 4"
					'CASE 9
					'   A$ = "Accuracy, " + LTRIM$(STR$(FINCAL!)) + "Hz, C.F.= 5"
					'CASE 10
					'   A$ = "Accuracy, " + LTRIM$(STR$(FINMAX!)) + "Hz Sine"
					'CASE 11
					'   A$ = "Accuracy, " + LTRIM$(STR$(FINEXTMAX!)) + "Hz Sine"
				END SELECT
				
				IF RIGHT$(STATUS$(x%, L%), 1) <> "5" AND LEN(STATUS$(x%, L%)) > 0 THEN
					'-------------------------------------------------------------------------------
					'Parse the STATUS (test results) data if the number of characters
					'is more than zero and the rightmost character (the # of decimal
					'places to be displayed) is not "5". The general format of the
					'STATUS data is shown below:
					'
					'STATUS$(X%, L%) format = <pass/fail> + <measured data> + <# decimal places>
					'                            4 char.         ? char            1 char.
					'
					'The number of decimal places character is used to control the
					'display/print format of the test results, and usually specifies
					'the number of decimal places to show. The special value of "5"
					'for # of decimal places is used by the OFFSET and GAIN (and
					'perhaps other) tests as a flag to prevent the display or printing
					'of the results of that test.
					'-------------------------------------------------------------------------------

					'Write test name to file.
					PRINT #9, TAB(5); a$;
					DATALEN% = LEN(STATUS$(x%, L%))
					NUMDATA! = VAL(MID$(STATUS$(x%, L%), 5, DATALEN% - 5))
					'Set test units for Supply Sensitivity test depending on module supply voltage
					IF x% = 12 THEN
						IF SPECS.NOMVS = 5 THEN         'SCM5B or 8B
							B$ = "ppm/%"
						ELSE                            'DSCA
							B$ = "%/%"
						END IF
					END IF

					'Display or print using requested # of decimal places
					IF RIGHT$(STATUS$(x%, L%), 1) = "0" THEN
						PRINT #9, TAB(34); USING "###### &"; NUMDATA!; B$;
					ELSEIF RIGHT$(STATUS$(x%, L%), 1) = "1" THEN
						PRINT #9, TAB(34); USING "####.# &"; NUMDATA!; B$;
					ELSEIF RIGHT$(STATUS$(x%, L%), 1) = "2" THEN
						PRINT #9, TAB(34); USING "###.## &"; NUMDATA!; B$;
					ELSEIF RIGHT$(STATUS$(x%, L%), 1) = "3" THEN
						PRINT #9, TAB(34); USING "##.### &"; NUMDATA!; B$;
					ELSEIF RIGHT$(STATUS$(x%, L%), 1) = "4" THEN
						PRINT #9, TAB(34); USING "#.#### &"; NUMDATA!; B$;
					END IF
					'DP = 5: don't display or print spec. in final report.
					'DP = 6: don't display or print numerical data
					SPECLEN% = LEN(TSPEC$(x%))
					PRINT #9, TAB(60 - SPECLEN%); TSPEC$(x%);
					PRINT #9, TAB(61); B$;
					PRINT #9, TAB(71); LEFT$(STATUS$(x%, L%), 4)
				END IF
			NEXT

			'------------
			'Write footer
			'------------
			PRINT #9, TAB(5); "240 VAC Withstand"; TAB(71); "PASS"
			PRINT #9, TAB(5); "Hi-Pot "; TAB(71); "PASS"
			PRINT #9, TAB(5);
			FOR x = 5 TO 75
				PRINT #9, "_";
			NEXT x
			PRINT #9, TAB(35); "Check List"
			PRINT #9,
			IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" OR LEFT$(SPECS.MODNAME, 2) = "8B" THEN
				'PRINT #9, TAB(5); "Module Appearance:      _____"; TAB(45); "Mounting Screw:           _____"
				PRINT #9, TAB(5); "Module Appearance:      __X__"; TAB(45); "Mounting Screw:           __X__"
				PRINT #9,
				'PRINT #9, TAB(5); "Pins Straight:          _____"; TAB(45); "Module Header:            _____"
				PRINT #9, TAB(5); "Pins Straight:          __X__"; TAB(45); "Module Header:            __X__"
				PRINT #9,
			END IF

			'PRINT #9, TAB(5); "Tested by:      _____________"; TAB(45); "QC:             _______________"
			PRINT #9,
			PRINT #9, TAB(5); "It is hereby certified that the above product is in conformance with"
			PRINT #9, TAB(5); "all requirements to the extent specified.  This product is not"
			PRINT #9, TAB(5); "authorized or warranted for use in life support devices and/or systems."
			PRINT #9,
			PRINT #9, TAB(5); "* NIST traceable calibration certificates support Measured Value data."
			PRINT #9, TAB(5); "  Calibration services are available through ANSI/NCSL Z540-1 and"
			PRINT #9, TAB(5); "  ISO Guide 25 Certified Metrology Labs."

			'--------------------
			'Close datasheet file
			'--------------------
			CLOSE #9

			PRINT TAB(10); "Finished writing datasheet file: "; DSFNAME$
			
			KEY(10) ON  'Reactivates F10 key

		ELSE
			'Set up display in lieu of missing datasheet file print statements
			CLS
			LOCATE 10
			PRINT ""    'Blank line
			PRINT ""    'Blank line
			PRINT ""    'Blank line
			PRINT ""    'Blank line
		END IF  'End if text file flag is "on" and there are no test failures

		'-------------------------------------------
		'Write status line to work order status file
		'and log the test data
		'-------------------------------------------
		IF TX% = 1 THEN
			KEY(10) OFF 'Deactivates F10 key
			'CLS
			'Write line to work order status file
			'LOCATE 5
			PRINT
			PRINT TAB(10); "About to write to work order status file."
			CALL WORKORDERLINE(FAILS%(STATUS$(), L%), LOCALSN$)
			PRINT TAB(10); "Finished writing work order status to file."
			PRINT ""    'Blank line
			'Log test data
			PRINT
			PRINT TAB(10); "Logging test data...."
			CALL LOGIT(STATUS$(), LOCALSN$, INSIM!(), OUTCALC!(), OUTMEAS!(), ERROROUT!(), ACCSTAT$(), L%)
			PRINT TAB(10); "Finished logging test data...."
			KEY(10) ON  'Reactivates F10 key
			CALL CONTINUE
		END IF

		'-------------------------------------------------------------------------
		'ABOVE: Code to write to datasheet file(s) if the module has passed
		'       all tests and the text file flag is "on", to write a status
		'       line to the work order status file if the text file
		'       flag is "on" (regardless of the pass/fail status of the
		'       tested module), and to log the test data.
		'-------------------------------------------------------------------------
		
	NEXT

END SUB

'*********************************
FUNCTION SETDUTIN! (DUTIN!)
	'In the HV test configuration with the HV cable from the HV power supply,
	'this function sets the voltage of the HV power supply and the connection
	'of the supply through either the 760A "pigtail" connector (inverted input
	'from the supply) or the 33120A BNC (non-inverted input from the supply),
	'depending on whether the "DUTIN!" parameter is negative or not (inverted
	'if negative). See comments in the "CONFDUTIN" sub. This function then
	'measures the DUT input voltage and returns the measured voltage.
	'
	'NOTE:  The DUT input voltage is set in one write to the HV power supply,
	'       not successively measured/adjusted (similar functions that set the
	'       DUT input in other test programs often loop through set/measure
	'       loops until the measured input matches the expected within a certain
	'       tolerance. This function does not do that, but simply sets once,
	'       then measures.
	'
	'Set HV supply connection and voltage
	IF (DUTIN! < 0!) THEN
		'Inverted input
		CALL CONFDUTIN(0)   'Connect HV supply to DUT inputs through the 760A "pigtail" conn.
	ELSE
		'Non-inverted input
		CALL CONFDUTIN(1)   'Connect HV supply to DUT inputs through the 33120A BNC
	END IF
	CALL SETDPS(DPSVINADDR%, ABS(DUTIN! / 2)) 'Set supply voltage (absolute value of passed voltage)
	CALL SETDPS(DPSVINADDR2%, ABS(DUTIN! / 2))
	'Measure DUT input voltage
	CH% = VIN.CH%
	CALL DVMCONF(CH%, VDC$, "AUTO", 0, "", 0)
	CALL DVMSENS(CH%, VDC$, INTTIME$, "", 2) '6 1/2 digits, 21 bit resolution

	CALL SETSWITCH(DUT3INPUT.CH%, 1)    'All 4 D.U.T. inputs in parallel
	CALL SETSWITCH(DUT2INPUT.CH%, 1)
	CALL SETSWITCH(DUT1INPUT.CH%, 1)

	CALL PAUSE(1) 'WAIT 1 SEC
       
	SETERROR! = GETREADING! / IINSEN1.MEAS! - DUTIN! 'Error in Vrms

	SETDUTIN! = DUTIN! + SETERROR!

END FUNCTION

'**********************************
SUB SETOUTLOAD (LOAD!, NUMDUT%)

	'Set the specified output load.
	'Inputs;
	'       LOAD!   specified load resistor to set
	'       NUMDUT% = number of Devices Under Test
	'
	'Outputs;  None

	NOMVS! = SPECS.NOMVS

	IF LOAD! >= 10000 THEN                  'load = open
		FOR L% = 1 TO NUMDUT%
			CALL SETSWITCH(IOUTLOAD1DUT1.CH% + L% * 2 - 2, 0)   'disconnect 250 ohm
			CALL SETSWITCH(IOUTLOAD2DUT1.CH% + L% * 2 - 2, 0)   'disconnect 600 ohm
			CALL SETSWITCH(VLOOPDUT1.CH% + L% - 1, 0)       'disconnect Vloop
		NEXT
	ELSEIF LOAD! > 599 THEN                 'load = 600 ohm
		FOR L% = 1 TO NUMDUT%
			CALL SETSWITCH(IOUTLOAD2DUT1.CH% + L% * 2 - 2, 1)   'connect 600 ohm
			CALL SETSWITCH(IOUTLOAD1DUT1.CH% + L% * 2 - 2, 0)   'disconnect 250 ohm
			IF NOMVS! = 5 THEN              'SCM5B, connect loop excitation
				CALL SETSWITCH(VLOOPDUT1.CH% + L% - 1, 1)
			END IF
		NEXT
	ELSE                                    'load = 250 ohm
		FOR L% = 1 TO NUMDUT%
			CALL SETSWITCH(IOUTLOAD1DUT1.CH% + L% * 2 - 2, 1)   'connect 250 ohm
			CALL SETSWITCH(IOUTLOAD2DUT1.CH% + L% * 2 - 2, 0)   'disconnect 600 ohm
			IF NOMVS! = 5 THEN              'SCM5B, connect loop excitation
				CALL SETSWITCH(VLOOPDUT1.CH% + L% - 1, 1)
			END IF
		NEXT
	END IF

END SUB

'************************************
FUNCTION SETSCM5BPWR (VSUPPLY!)

	'Set the voltage controlled voltage source used for SCM5B power
	'Inputs;    VSUPPLY!, Required supply voltage
	'Output;    VSUPPLY!, Measured supply voltage

	VSNOM! = 5                      'Define as constant.  SPECS.VSNOM not known
									'upon program start.

	CALL SETSWITCH(VSSOURCE.CH%, 0)         'D.U.T. Power is test head VCVS
	CALL DVMCONF(SCM5BVS.CH%, VDC$, "", VSNOM!, "", 0)
	CALL DVMSENS(SCM5BVS.CH%, VDC$, INTTIME$, "", .02)    '4 1/2 digits, 15 bit resolution
   
	IF VSUPPLY! <= .1 THEN
		VSTOL! = .1                 'Set error (V)
	ELSE
		VSTOL! = .005
	END IF
   
	VSERROR! = 0
	VOLTAGE! = VSUPPLY!
	ITER% = 0

	DO
		ITER% = ITER% + 1
		VOLTAGE! = VOLTAGE! - VSERROR!
	   
	   
	   
		IF (VOLTAGE! < 0) THEN 'SETS LIMITS
	  
		VOLTAGE! = 0
	  
		ELSEIF (VOLTAGE! > 6) THEN
	  
		VOLTAGE! = 6
		END IF
	   
	   
		CALL SETDAC3(1, VOLTAGE!)
		'PRINT VOLTAGE!: CALL CONTINUE
		VSERROR! = GETREADING! - VSUPPLY!           'error (V)
	LOOP WHILE ABS(VSERROR!) > VSTOL! AND ITER% < 40
  
	IF VSUPPLY! > 1 AND ITER% = 40 THEN
		PRINT "Error!  5V power supply not operational.  Contact engineering."
		PRINT "VSUPPLY! = "; VSUPPLY!, "VSERROR! = "; VSERROR!
		PRINT
		'PRINT TAB(10); "High supply current!  Remove module from test fixture."
		'PRINT
		CALL SETDAC3(1, 0!)
		CALL SETDPS(DPSVINADDR%, 0) 'Set input voltage (at ext. supply) to 0V
		CALL SETDPS(DPSVINADDR2%, 0)
		CALL CONTINUE
		VSUPPLY! = -1
		'STOP
	END IF

	IF VSUPPLY! = 5! THEN CALL PAUSE(1!)    'Allow module output to settle.
											'Usually power was previously off.
	SETSCM5BPWR! = VSUPPLY! + VSERROR!      'Pass actual Vs back

END FUNCTION

SUB SHOWDIO (DIODATA%, WORNO%, DEBUGVAL%)
	'Sub to display the value of the word storing the DIO state in the
	'Agilent DAS (Data Acquisition System). Parameters include the word
	'value, the word number (1 or 2) and the debug flag ("1" to enable
	'the display of the values).
	'
	IF (DEBUGVAL% = 1) THEN
		PRINT "==========================="
		IF (WORNO% = 1) THEN
			PRINT "PRINTING DATA FOR WORD 1"
		ELSEIF (WORNO% = 2) THEN
			PRINT "PRINTING DATA FOR WORD 2"
		ELSE
			PRINT "INVALID WORD!"
		END IF
		PRINT "DIODATA% = "; DIODATA%
		PRINT "......................"
		PRINT "==========================="
		PRINT
		CALL CONTINUE
	END IF
END SUB

'******************************************
FUNCTION SNMENU$ (SLOTNO%, SERNOOLD$, SNFLAG%)
	'Function that returns the serial number of the next module. If SNFLAG% is "1",
	'the serial number (work order and dash (sequential) number) to start a new set
	'units is obtained, but if SNFLAG% is "0", the serial number of the next installed
	'module (the module in the next test channel) is entered.
	'
	PREVSLOT% = SLOTNO% - 1     'Set previous channel number
	CLS
	LOCATE 5
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(6); "-----------------------------------------------------------------"
	PRINT TAB(6); "                  Serial Number Selection Menu                   "
	PRINT TAB(6); "-----------------------------------------------------------------"
	PRINT
	PRINT TAB(6); "         Setting dash number for the unit in test channel #:"; SLOTNO%; ""
	COLOR 15, 0, 0  'Bright white on black
	PRINT TAB(6); "                       CHANNEL: "; SLOTNO%; "                                     "
	COLOR 14, 0, 0  'Yellow on black
	PRINT TAB(6); "-----------------------------------------------------------------"
	PRINT
	'Display lines below depend on the state of SNFLAG%
	COLOR 15, 0, 0  'Bright white on black
	IF SNFLAG% <> 0 THEN
		PREVSLOT% = SLOTNO% - 1
		PRINT TAB(8); "The serial number of the DUT in test channel#"; PREVSLOT%; " is: "; SERNOOLD$
	ELSE
		PRINT TAB(8); "The serial number of the last unit tested is: "; SERNOOLD$
	END IF
	'Display selection menu
	PRINT
	COLOR 15, 0, 0  'Bright white on black
	PRINT TAB(8); "Choose from the following options:"
	PRINT
	COLOR 11, 0, 0  'Cyan on black background
	PRINT TAB(8); "1.) Next sequential number from previous DUT"
	PRINT TAB(8); "2.) Non-sequential serial number (but same"
	PRINT TAB(8); "    work-order number) as previous DUT    "
	PRINT
	'Loop to get valid keyboard entry
	LOOPSTAY% = 1   'Initialize flag to stay in loop
	DO
		I$ = INKEY$
		IF SNFLAG% = 1 THEN
			'Starting serial number for a new set of modules
			IF (VAL(I$) < 1 OR VAL(I$) > 2) THEN
				'A "1" or "2" was not entered
				LOOPSTAY% = 1
			ELSE
				'A "1" or "2" was entered
				LOOPSTAY% = 0
			END IF
		ELSE
			'Serial number for a module within a set of modules
			'IF (VAL(I$) < 1 OR VAL(I$) > 3) THEN
				'A "1", "2" or "3" was not entered
			IF (VAL(I$) <> 1 AND VAL(I$) <> 2) THEN
				'A "1" or "2" was not entered
				LOOPSTAY% = 1
			ELSE
				'A "1", "2" or "3" was entered
				LOOPSTAY% = 0
			END IF
		END IF
	LOOP WHILE (LOOPSTAY% = 1)
	SEL4% = VAL(I$)

	'Increment, change dash (sequential) number, or get new (entire) serial number,
	'depending on menu selection (and SNFLAG%).
	SELECT CASE SEL4%                       'Changes S/N information as selected
		CASE 1
			SERNONEW$ = UPSN$(SERNOOLD$)    'Increments the Dash# of the serial #
		CASE 2
			SERNONEW$ = SERNOOLD$
			CALL CHANGEDN(SERNONEW$)        'Changes dash number only
	END SELECT
   
	'Set function return to new serial number
	SNMENU$ = SERNONEW$

END FUNCTION

'*************************************
SUB SORTDB (ENDFLAG%)

	'This sub does a bubble sort of the model numbers in the database
	'records FOR A SELECTED MODEL FAMILY

	'CONST FALSE = 0, TRUE = NOT FALSE
  
	'Create a file containing just the model numbers of all of the
	'records in the database for the model family selected

	OPEN "C:\ATE\HVDATA\HVSORT.DAT" FOR RANDOM AS #2 LEN = LEN(SORTDATA1)
	OPEN "C:\ATE\HVDATA\HVIN.DAT" FOR RANDOM AS #1 LEN = LEN(SPECS)
	NUMRECORD% = LOF(1) / LEN(SPECS)

	SELFAM% = MENU3%
	IF SELFAM% = 4 THEN
		ENDFLAG% = 1
		CLOSE #1
		CLOSE #2
		CLOSE #3
		EXIT SUB        'exit selected from MENU3%
	END IF

	n% = 0

	FOR I% = 1 TO NUMRECORD%
		GET #1, I%, SPECS
		MN$ = SPECS.MODNAME
		SORTDATA1.MODNAME = MN$
		SORTDATA1.RECNUM = I%

		SELECT CASE SELFAM%    'Pick models in selected family

			CASE 1
				'SPECS.MODNAME = "SCM5B-xxxx "
				IF LEFT$(MN$, 5) = "SCM5B" THEN
					PUT #2, , SORTDATA1        'write record # and model number
					n% = n% + 1                'found a record
				END IF
			   
			CASE 2
				'SPECS.MODNAME = "DSCA-xxxx "
				IF LEFT$(MN$, 4) = "DSCA" THEN
					PUT #2, , SORTDATA1        'write record # and model number
					n% = n% + 1                'found a record
				END IF
			   
				 
			CASE 3
				'SPECS.MODNAME = "8B-xxxx  "
				IF LEFT$(MN$, 2) = "8B" THEN
					PUT #2, , SORTDATA1        'write record # and model number
					n% = n% + 1                'found a record
				END IF
		END SELECT
	NEXT

	SORTDATA1.MODNAME = "99999999-9999"         'always sorted to last value.
	SORTDATA1.RECNUM = -1        'flag indicating end of new data (over writes old)
	PUT #2, , SORTDATA1

	CLOSE #1
	CLOSE #2
	CLOSE #3
END SUB

'******************************
SUB SUPPLYI (NUMDUT%, STATUS$())
	'Measure DUT quiescent supply current at +f.s. output
	'Inputs;    NUMDUT% = number of Devices Under Test
	'Outputs;   STATUS$(1,n)   array of results
	'
	MAXIN! = SPECS.MAXIN
	MAXOUT! = SPECS.MAXOUT      'V or A
	FINCAL! = SPECS.FINCAL      'Input waveshape frequency (Hz)
	ISMIN! = SPECS.ISMIN

	
	'IF LEFT$(SPECS.MODNAME, 9) = "DSCA41-03" THEN
	'   ISMIN! = 10!    'Hardcode for DSCA debug.
	'END IF

	ISMAX! = SPECS.ISMAX        'Isupply with max current out if applicable.
	NOMVS! = SPECS.NOMVS

	MAXINMEAS! = SETDUTIN!(MAXIN!)
  
	LOCATE 8, 10
	PRINT SPC(45);
	
	CLS
	TESTTITLE$ = "Supply Current Test"
 
	FOR L% = 1 TO NUMDUT%
		CLS
		LOCATE 1
		CALL HEADERB(TESTTITLE$, 0)
   
		LOCATE 8, 25: PRINT "TESTING DEVICE IN CHANNEL #"; L%
  
		IF L% < 3 THEN
			IF L% = 1 THEN
				SWITCHSTATE% = 0
			ELSE
				SWITCHSTATE% = 1
			END IF
			
			CALL SETSWITCH(SWITCHISDUT1.CH%, SWITCHSTATE%)
			CALL SETSWITCH(SWITCHISDUT2.CH%, SWITCHSTATE%)
			IS.CH% = MEASISUPPLY1.CH%
		ELSE
			IF L% = 3 THEN
				SWITCHSTATE% = 0
			ELSE
				SWITCHSTATE% = 1
			END IF
			
			CALL SETSWITCH(SWITCHISDUT3.CH%, SWITCHSTATE%)
			CALL SETSWITCH(SWITCHISDUT4.CH%, SWITCHSTATE%)
			IS.CH% = MEASISUPPLY2.CH%
		END IF
		
		CALL DVMCONF(IS.CH%, ADC$, "", ISMAX! * 2 / 1000, "", 0)
		CALL DVMSENS(IS.CH%, ADC$, INTTIME$, "MIN", 0) '4 1/2 digits, 15 bit resolution
		ISUP! = GETREADING! * 1000
		CALL PAUSE(1)
		ISUP! = GETREADING! * 1000
		

		ST$ = " "
		IF ISUP! < 1 AND VSNOM! <> 5 THEN   'DSCA
			IF POWERIO$(DPSADDR%, ISTAT$) = "RCS=01" THEN    'Check for over-current
				LOCATE 10
				PRINT TAB(10); "One or more of the modules has high supply current."
				PRINT TAB(10); "Remove all of the modules and test them one at at time"
				PRINT TAB(10); "to find the faulty modules."
				FOR M% = 1 TO NUMDUT%
					STATUS$(1, M%) = "FAIL5"
				NEXT
				EXIT SUB               'High supply current
			END IF
		END IF
	 
		IF ISUP! < ISMAX! AND ISUP! > ISMIN! THEN
			SUPI$ = "PASS"
		ELSE
			SUPI$ = "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 10, 10: PRINT "MODULE #"; L%; " Status: "; SUPI$;
		LOCATE 11, 10   'Added
		PRINT TAB(10); "Measured supply current is";
		PRINT TAB(50); USING "&###.# mA"; ST$; ISUP!
		PRINT TAB(10); "Required supply current is";
		PRINT TAB(50); USING " ###.# mA to ###.# mA"; ISMIN!; ISMAX!

		CALL FAILSTATUS(L%, SUPI$, 10, 10, "Status: ", 20)      'Print test status to screen
		
		IF SUPI$ = "FAIL" THEN
			CALL SETDPS(DPSVINADDR%, 0) 'Set input voltage (at ext. supply) to 0V
			CALL SETDPS(DPSVINADDR2%, 0)
			IF NOMVS! <> 5 THEN                         'DSCA
				SP$ = POWERIO$(DPSADDR%, SUPPLYOFF$)    'Disable power supply
			ELSE                                        'SCM5B
				SP! = SETSCM5BPWR!(.01)                 'Set Vsupply to zero
			END IF
			CLS
			LOCATE 10
			'PRINT
			COLOR 28, 0, 0  'Flashing light red
			PRINT TAB(10); "Remove unit #"; L%; " from the test head."
			COLOR 11, 0, 0  'Cyan on black background                                           'from test head, input current can't be set.
			BEEP
			CALL CONTINUE
			'MAXINMEAS! = SETDUTIN!(MAXIN!)             'Reset input to +f.s.
			CLS
			IF NOMVS! <> 5 THEN                         'DSCA
				CALL SETDPS(DPSADDR%, NOMVS!)           'Set Vsupply to nominal value
				IF POWERIO$(DPSADDR%, ISTAT$) = "RCS=01" THEN    'Check for over-current
					MOREFAIL% = 1
				END IF
			ELSE                                        'SCM5B and 8B
				SP! = SETSCM5BPWR!(NOMVS!)              'Set Vsupply to nominal value
				IF SP! = -1 THEN
					MOREFAIL% = 1
				END IF
			END IF
			IF MOREFAIL% = 1 THEN
				CLS
				LOCATE 10
				PRINT TAB(10); "One or more of the remaining modules has high supply current."
				PRINT TAB(10); "Remove all of the modules and test them one at at time to find"
				PRINT TAB(10); "the faulty modules."
				CALL CONTINUE
				CLS
				FOR M% = L% TO NUMDUT%
					STATUS$(1, M%) = "FAIL5"
				NEXT
				EXIT SUB               'High supply current
			END IF
		END IF

		STATUS$(1, L%) = SUPI$ + STR$(ISUP!) + "1"       'append # decimal places
	  
		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!)
		CLS
	NEXT

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

'**********************************
SUB SUPPLYSEN (NUMDUT%, STATUS$())
	'Measure module power supply sensitivity
	'Inputs;    NUMDUT% = number of Devices Under Test
	'Outputs;   STATUS$(2,n)   array of results,
	'           Supply sensitivity in ppm / % (5B) or % / % (DSCA)
	'
	MAXIN! = SPECS.MAXIN                    'Module input (V or A)
	FINCAL! = SPECS.FINCAL                  'Input waveshape frequency (Hz)
	MINOUT! = SPECS.MINOUT                  'Module output (V or A)
	MAXOUT! = SPECS.MAXOUT
	PSS! = SPECS.PSS                        'Spec, ppm / % (5B) or % / % (DSCA)
	MINVS! = SPECS.MINVS
	MAXVS! = SPECS.MAXVS
	NOMVS! = SPECS.NOMVS
	ORANGE! = MAXOUT! - MINOUT!
	OUTSIGTYPE$ = SPECS.OUTSIGTYPE$

	IF NOMVS! = 5 THEN                      'SCM5B
		CONV! = 10000
		' what about the 8B ?
	ELSE                                    'DSCA
		CONV! = 1                           'Conversion factor,  % / %
	END IF

	CLS
	TESTTITLE$ = "Power Supply Sensitivity Test"
	
	CALL HEADERB(TESTTITLE$, 0)
  
	MAXINMEAS! = SETDUTIN!(MAXIN!)
	OUTCALC! = MODULEOUT!(MAXINMEAS!)
	   
	FOR L% = 1 TO NUMDUT%
		LOCATE 1
		IF L% <> 1 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%
		  
			IF NOMVS! = 5 THEN                          'SCM5B
				MINVS.MEAS! = SETSCM5BPWR!(MINVS!)      'Set Vsupply to minimum value
			ELSE
				CALL SETDPS(DPSADDR%, MINVS!)           'Set Vsupply to minimum value
				MINVS.MEAS! = MINVS!
			END IF
			
			CALL PAUSE(.5)
							'Dummy value
			IF OUTSIGTYPE$ = "CURRENT" THEN
				CH% = IOUTSENDUT1SEN.CH%
			ELSE    'OUTSIGTYPE$ = "VOLTAGE"
				IF LEFT$(SPECS.MODNAME, 5) = "SCM5B" THEN
					CH% = VOUTDUT1.CH%          'SCM5B module output.
				ELSE
					CH% = IOUTSENDUT1SOUR.CH%   'DSCA and 8B module outputs.
				END IF
			END IF
			
			CALL DVMCONF(CH% + L% - 1, VDC$, "", OUTCALC! * IOUTSEN1.MEAS!(1), "", 0)
			CALL DVMSENS(CH% + L% - 1, VDC$, INTTIME$, "", 2)    '6 1/2 digits, 21 bit resolution
		  
			CALL PAUSE(1)
			OUT1! = GETREADING! / IOUTSEN1.MEAS!(L%)     'Output @ MINVS

			IF NOMVS! = 5 THEN                          'SCM5B
				MAXVS.MEAS! = SETSCM5BPWR!(MAXVS!)      'Set Vsupply to maximum value
				CALL DVMCONF(CH% + L% - 1, VDC$, "", OUTCALC! * IOUTSEN1.MEAS!(1), "", 0)
				CALL DVMSENS(CH% + L% - 1, VDC$, INTTIME$, "", 2)   '6 1/2 digits, 21 bit resolution
			
			ELSE    'IF NOMVS! = 24 THEN
				CALL SETDPS(DPSADDR%, MAXVS!)           'Set Vsupply to maximum value
				MAXVS.MEAS! = MAXVS!
			END IF
		   
			CALL PAUSE(1)
			
			OUT2! = GETREADING! / IOUTSEN1.MEAS!(L%)     'Output @ MAXVS
			DELTAOUT! = ((OUT2! - OUT1!) / ORANGE! * CONV!) / ((MAXVS.MEAS! - MINVS.MEAS!) / NOMVS!)  'Change in output (ppm/% or %/%)
	
			IF ABS(DELTAOUT!) <= PSS! THEN
				PSSSTAT$ = "PASS"
			ELSE
				PSSSTAT$ = "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 "MODULE #"; L%; " Status: "; PSSSTAT$;
			LOCATE 16, 10   'Added
			PRINT SPC(20);
			IF NOMVS! = 5 THEN                          'SCM5B
				PRINT TAB(10); "Measured change in output voltage is";
				PRINT TAB(47); USING "   ##### ppm / %"; DELTAOUT!
				PRINT TAB(10); "Required change in output voltage is";
				PRINT TAB(47); USING " <  #### ppm / %"; PSS!
				STATUS$(12, L%) = PSSSTAT$ + STR$(DELTAOUT!) + "0"
			ELSE                                            'DSCA
				PRINT TAB(10); "Measured change in output voltage is";
				PRINT TAB(47); USING "   #.#### % / %"; DELTAOUT!
				PRINT TAB(10); "Required change in output voltage is";
				PRINT TAB(47); USING " < #.#### % / %"; PSS!
				STATUS$(12, L%) = PSSSTAT$ + STR$(DELTAOUT!) + "4"
			END IF

			CALL FAILSTATUS(L%, PSSSTAT$, 15, 10, "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!)
		IF L% <> NUMDUT% THEN
			FOR M% = 15 TO 17
				LOCATE M%, 10
				PRINT SPC(65);
			NEXT
			PRINT
		END IF
		CLS
	NEXT

	SN$ = SERNO$(1)
  
	IF NOMVS! = 5 THEN                          'SCM5B
		SP! = SETSCM5BPWR!(NOMVS!)              'Set Vsupply to nominal value
	ELSE
		CALL SETDPS(DPSADDR%, NOMVS!)           'Set Vsupply to nominal value
	END IF
	CALL SETDPS(DPSVINADDR%, 0) 'Set input voltage (at ext. supply) to 0V
	CALL SETDPS(DPSVINADDR2%, 0)
END SUB

'**********************************
SUB TSPECS (TSPEC$())
'    STEPPERC! = 90                                  '% span @ 120ms
'    STEPTOL! = 5                                    '+/-5% tolerance
	TSPEC$(1) = " < " + STR$(SPECS.ISMAX)           'Isupply spec, max load
	TSPEC$(2) = ""                                  'Output switch
	TSPEC$(3) = "+/-" + STR$(SPECS.ACCSINCAL)       'Accuracy spec
	TSPEC$(4) = "+/-" + STR$(SPECS.LINEAR)          'Linearity/conformity spec
	TSPEC$(5) = "+/-" + STR$(SPECS.ACCSINCAL)       'Accuracy, CF = 1
	TSPEC$(6) = "+/-" + STR$(SPECS.ACCSINCAL + SPECS.ACCCF12) 'Accuracy, CF = 2
	TSPEC$(7) = "+/-" + STR$(SPECS.ACCSINCAL + SPECS.ACCCF23) 'Accuracy, CF = 3
	TSPEC$(8) = "+/-" + STR$(SPECS.ACCSINCAL + SPECS.ACCCF34) 'Accuracy, CF = 4
	TSPEC$(9) = "+/-" + STR$(SPECS.ACCSINCAL + SPECS.ACCCF45) 'Accuracy, CF = 5
	TSPEC$(10) = "+/-" + STR$(SPECS.ACCSINCAL + SPECS.ACCSINSTD) 'Fin = FINMAX
	TSPEC$(11) = "+/-" + STR$(SPECS.ACCSINCAL + SPECS.ACCSINEXT) 'Fin = FINEXTMAX
	TSPEC$(12) = "+/-" + STR$(SPECS.PSS)            'Power supply sensitivity
	TSPEC$(13) = "+/-" + STR$(SPECS.ACCSINCAL)      'Offset calibration spec
	TSPEC$(14) = "+/-" + STR$(SPECS.ACCSINCAL)      'Gain calibration spec
	TSPEC$(15) = STR$(SPECS.STEPPERC) + " +/-" + STR$(SPECS.STEPTOL)  'Response time
	TSPEC$(16) = " <=" + STR$(SPECS.OUTNOISE)       'Output noise
	TSPEC$(17) = "+/-" + STR$(DELTALOADTOL!)        'Output change with max load
	  
END SUB

FUNCTION WAITFORKEY$ (KEY$, TABPOS%, FORECOL%, BACKCOL%)
	'Wait for the user to press the key specified by the "KEY$" parameter (upper or lower case).
	'A message is displayed on row after the current row of the screen cursor row, tabbed over
	'the number of spaces specified by the "TABPOS%" parameter. This sub is used in situations
	'where a specific key should be pressed, rather than "any" key, such as after the final test
	'status is displayed on the screen (so that the operator is sure to see the "PASS" or "FAIL"
	'status) or in any situation when previous keystrokes need to be ignored. For distinction,
	'the message is displayed in the passed foreground and background colors.
	COLOR FORECOL%, BACKCOL%    'Set to passed foreground and background colors
	EATTHIS$ = INKEY$   '"Eat" any keystrokes in the buffer.
	KEYUC$ = UCASE$(KEY$)
	KEYLC$ = LCASE$(KEY$)
	PRINT ""
	'PRINT TAB(10); "Press the '"; KEY$ ;"'key to continue..."
	PRINT TAB(TABPOS%); "Either '"; KEYUC$; "' or '"; KEYLC$; "' must be pressed."
	DO
		KB$ = INKEY$
		KB$ = UCASE$(KB$)
	LOOP WHILE (KB$ <> KEY$)
	COLOR 11, 0, 0  'Cyan on black background

	WAITFORKEY$ = KB$   'Set function return.
	
END FUNCTION

SUB WORKORDERHEADER (SN$)
	'Sub to print the header for the work order status file.
	'
	'Column numbers (for reference) below:
	'         1         2    2    3   3     4       4 5         6         7         8
	'1        0         0    5    0   4     0       8 0         0         0         0
	'
	'Example header format (example not necessarily for this test program):
	'
	'
	'===================================================================
	'WO#: 103456
	'
	'Date:  06-03-2014
	'
	'Work order status file for work order #: 103456
	
	'Program:   RMSMN6-2.EXE
	'Version:   B.1 2014.05.14 PWR
	'Lib. Ver.: B.1 2014.05.14 PWR
	'
	'-------------------------------------------------------------------
	'Status   Serial#   DS File Name  Model         Date        Time
	'-------- --------- ------------  ------------- ----------  --------
	'
	KEY(10) OFF 'Deactivates F10 key

	'CLS
	PRINT TAB(10); "Writing header to work order status file."
	
	WOSFNAME$ = GETWOSFNAME$(SN$)  'Get work order status file name
	CALL SNPARSE(SN$, WO$, DS$) 'Get current work order and dash numbers from module serial number
	OPEN "C:\REPORTS\" + WOSFNAME$ FOR APPEND AS #10
	'OPEN "C:\REPORTS\" + WOSFNAME$ FOR OUTPUT AS #10
	'PRINT #10, 'Blank line
	PRINT #10,  'Blank line
	PRINT #10, "==================================================================="
	PRINT #10, "WO#: "; WO$
	PRINT #10,  'Blank line
	PRINT #10, "Date:  "; DATE$
	PRINT #10,  'Blank line
	PRINT #10, "Work order status file for work order #: "; WO$
	PRINT #10,  'Blank line
	'Program name and version and library version.
	PRINT #10, "Program:   "; PROGNAMEVAL$
	PRINT #10, "Version:   "; PROGVERVAL$
	PRINT #10, "Lib. Ver.: "; LIBVERVAL$
	PRINT #10,  'Blank line
	PRINT #10, "-------------------------------------------------------------------"
	PRINT #10, "Status"; TAB(10); "Serial#"; TAB(20); "DS File Name"; TAB(34); "Model"; TAB(48); "Date"; TAB(60); "Time"
	PRINT #10, "--------"; TAB(10); "---------"; TAB(20); "------------"; TAB(34); "-------------"; TAB(48); "----------"; TAB(60); "--------"
	CLOSE #10

	KEY(10) ON  'Reactivates F10 key
	
END SUB

SUB WORKORDERLINE (FAILSTATE%, SN$)
	'Sub to write status lines for tested module in work order status file.
	'
	'Example line formats (below column numbers):
	'         1         2    2    3   3     4       4 5         6         7         8
	'1        0         0    5    0   4     0       8 0         0         0         0
	'FAIL<<<< 103456-49 A3456-49.TXT  SCM5B48-01    02-19-2014  17:23:04
	'PASS     103456-50 A3456-50.TXT  SCM5B48-01    02-19-2014  22:28:31
	'
	'KEY(10) OFF    'Deactivates F10 key

	'PRINT TAB(10); "Writing status to work order status file."
	
	CALL GETDSFNAME(SN$, DSSNAME$, DSFNAME$)    'Gets datasheet search and file names from serial number
	
	IF FAILSTATE% = 1 THEN
		STATE$ = "FAIL<<<<"
		DSFNAME$ = ""   'Set datasheet file name blank for failing modules (since file is not generated)
	ELSE
		STATE$ = "PASS"
	END IF
	WOSFNAME$ = GETWOSFNAME$(SN$)  'Get work order status file name
	
	PRINT TAB(10); "Writing work order status to file: "; WOSFNAME$
	
	OPEN "C:\REPORTS\" + WOSFNAME$ FOR APPEND AS #10
	'PRINT #10, STATE$; TAB(10); RTRIM$(SN$); TAB(25); RTRIM$(SPECS.MODNAME$); TAB(45); DATE$; TAB(65); TIME$
	PRINT #10, STATE$; TAB(10); RTRIM$(SN$); TAB(20); RTRIM$(DSFNAME$); TAB(34); RTRIM$(SPECS.MODNAME$); TAB(48); DATE$; TAB(60); TIME$

	CLOSE #10

	'KEY(10) ON 'Reactivates F10 key
	
END SUB

SUB WORKORDERPRINT (SN$)
	'Sub to print work order status file

	KEY(10) OFF 'Deactivates F10 key
	
	COLOR 15, 0, 0  'Clear screen to bright white on black background
	CLS
	LOCATE 5, 5: PRINT "PLEASE WAIT WHILE PRINTER PRINTS YOUR TEST RESULTS"

	WOSFNAME$ = GETWOSFNAME$(SN$)  'Get work order status file name
	CALL GETDSFNAME(SN$, DSSNAME$, DSFNAME$)    'Gets datasheet search and file names from serial number

	'Append list of related datasheet files
	OPEN "C:\REPORTS\" + WOSFNAME$ FOR APPEND AS #10
	PRINT #10, "--------------------------------------------------------"
	'PRINT #10, "List of datasheet files created:"
	PRINT #10, "Below is a list of the datasheet files actually created."
	PRINT #10, "This list must correspond one for one with the list in"
	PRINT #10, "the 'DS File Name' column above. If it does not, there"
	PRINT #10, "is a problem with one (or more) of the datasheet files!"
	
	PRINT #10, "------------"
	CLOSE #10
	'Append list of text files to work order status file
	SHELL "DIR C:\STAGE\" + DSSNAME$ + "*.TXT /B >> C:\REPORTS\" + WOSFNAME$

	'Print file
	SHELL "COPY C:\REPORTS\" + WOSFNAME$ + " LPT1 > NUL"'Print work order status file
	LPRINT CHR$(12) 'Form feed

	'PRINT
	'PRINT TAB(10); "Has the: " + WOSFNAME$ + " file finished printing?"
	'DUMKEY$ = WAITFORKEY("F", 10, 14, 0)   'Waits for "F" key press (display bright yellow on black)

	COLOR 11, 0, 0  'Cyan on black background
	CLS

	KEY(10) ON  'Reactivates F10 key
	
END SUB

