'Automated Test Software for SCT1Px-xx and DSCTx-xx Voltage,
'Current, TC and RTD input models.

'AUTHOR:        John Lehman
'DATE:          4/9/98
'USES LIBRARY = LIBATE.BAS

'       REVISION RECORD

'DATE     APPR    DESCRIPTION
'----     ----    -----------
'SEE TST4SCT1.BAS

DECLARE SUB CALDAC (TE$)
DECLARE SUB COMPTEST (STATUS$(), ITERATION%, cal%, GENAMPL!, TSIM!(), IOUTCALC!(), IOUTMEAS!(), ERRORPERC!(), ERRORA$(), LOWMA!, HIGHMA!, TOTLRESPEC!) 'Complete set of tests
DECLARE SUB CONTINUE ()
DECLARE SUB FOOTER (STATUS$())                  'Sends footer to printer if all tests passed
DECLARE SUB FUNCTEST (cal%)                     'Routines for functional test
DECLARE SUB GENSET (GENAMPL!)                   'Displays message to set signal generator
DECLARE SUB GETADD (FILENAME$)                  'Gets parallel port/Mux/Testhead address
DECLARE SUB GETSN (SN$)                         'Gets serial number
DECLARE SUB GETSPECS ()                         'Gets transmitter type and specifications
DECLARE SUB GETSPECS2 ()                        'Gets SCMVAS module data
DECLARE SUB HEADERA (SN$)                       'Prints test sheet header
DECLARE SUB HEADERB (TESTTITLE$)                'Prints test screen header
DECLARE SUB INDIVID (SEL%)                      'Performs the tests individually
DECLARE SUB INIT488 (DEVADDR%)
DECLARE SUB INITPS (ADDR%, OVERI!, OVERV!)
DECLARE SUB LOADMUX (CH%, CHON%)
DECLARE SUB LOGIT (STATUS$(), SN$, TSIM!(), IOUTCALC!(), IOUTMEAS!(), ERRORPERC!(), ERRORA$(), LOWMA!, HIGHMA!, TOTLRESPEC!)              'Logs test results to disk
DECLARE SUB MODOUTLINE ()
DECLARE SUB NOTES ()                            'Notes on ATE operation
DECLARE SUB OHMSET (OHM!)
DECLARE SUB ONESHOTTEST ()                      'Tests one-shot pulse width
DECLARE SUB PAUSE (TIME!)
DECLARE SUB REPORT (STATUS$(), TSPEC$())        'Prints test data on screen
DECLARE SUB RESETTH ()                          'Reset test head to known condition
DECLARE SUB SETDAC (VOLTAGE!, CH%, VSENATTEN!)
DECLARE SUB SETDACFAST (VOLTAGE!)
DECLARE SUB SETTEST (TEST%)
DECLARE SUB SETTH (DOUT%, CB%)
DECLARE SUB SETTHFAST (DOUT%, CB%)
DECLARE SUB SORTDB (ENDFLAG%)
DECLARE SUB TSPECS (TSPEC$(), LOWMA!, HIGHMA!, TOTLRESPEC!) 'Creates a string array of test specifications
DECLARE SUB WRITEDVM (FUNC$, VALUE!)
DECLARE SUB TCDUTCONNECT ()
DECLARE SUB TCDUTDISCONNECT ()


DECLARE FUNCTION BESTFIT! (SLOPE!, OFFSETS!, TSIM!(), NUMPTS%, ERRO!())
                        'Library fn. Calculates besfit line and max error
DECLARE FUNCTION CJCCAL$ ()                     'Calibrate ambient temp sensor
DECLARE FUNCTION FAILS% (STATUS$())             'Tests for failed tests
DECLARE FUNCTION FREQRESP$ (GENAMPL!)           'Performs Frequency response Test
DECLARE FUNCTION GAINCAL$ (cal%, CONTRES!, PFSMEAS!, INTERACT!, DELTAOS!)  'Performs Gain Calibration
DECLARE FUNCTION GAINCALINT$ (cal%)
DECLARE FUNCTION GAINERR! (cal%, CONTRES!, PFSMEAS!, INTERACT!, OSERR2!)
DECLARE FUNCTION GENATTENR! ()                  'Calculate fn gen attenuator
DECLARE FUNCTION GETTHID% ()                    'Library fn. Get test head id #
DECLARE FUNCTION IEXC1$ (IEXCSENSE!)            'Measure excitation I source #1
DECLARE FUNCTION IEXC2$ (IEXCSENSE!)            'Measure excitation I source #2
DECLARE FUNCTION IMATCH$ (I1$, I2$)             'Check current source matching
DECLARE FUNCTION INPUTR$ ()                     'Performs Input Resistance Test
DECLARE FUNCTION Iout! (SENOUT!)                'Calculates transmitter output for a given input
DECLARE FUNCTION KEYBDIN$ ()                    'Library fn. Get keyboard input
DECLARE FUNCTION LEADREFF$ (TOTLRESPEC!)        'Measure lead resistance effects
DECLARE FUNCTION LINTEST$ (ACC$, CONTRES!, TSIM!(), IOUTCALC!(), IOUTMEAS!(), ERRORPERC!(), ERRORA$())      'Performs Accuracy and Linearity Tests
DECLARE FUNCTION LOOPVSEN$ ()                   'Performs Power Supply Sensitivity
DECLARE FUNCTION MEASRES! (OHM!, RESNUM%, TE$)  'Measure loop current sense resistor
DECLARE FUNCTION MENU0% ()                      'Choose model family to test
DECLARE FUNCTION MENU1% ()                      'Gets the Test Group selection
DECLARE FUNCTION MENU2% ()                      'Gets the individual test #
DECLARE FUNCTION MENU3% ()                      'Gets the transmitter family
DECLARE FUNCTION MINLOOPV$ ()                   'check operation at min loop V
DECLARE FUNCTION MAXLOOPV$ ()                   'check operation at max loop V
DECLARE FUNCTION OFFSETCAL$ (cal%, CONTRES!)    'Performs Offset Calibration
DECLARE FUNCTION OFFSETERR! (cal%, CONTRES!)
DECLARE FUNCTION OPENTC$ ()                     'Measure open thermocouple response
DECLARE FUNCTION OUTNOISE$ ()                   'Performs Output Noise Test
DECLARE FUNCTION OVERRANGE$ ()                  'Measure over-range current
DECLARE FUNCTION PARASITICTCV! (VCJC!)          'Measure VCJC and calculate PTC
DECLARE FUNCTION POWERIO$ (ADDR%, CMD$)         'Library fn. Kepco DPS power supply I/O
DECLARE FUNCTION READDVM! (TOL!)                'Library fn. Reads Fluke meter to TOL!
DECLARE FUNCTION READGPIB$ (ADDR%, CMD$)
DECLARE FUNCTION REPEAT$ (N$)                   'Ask if you would like to repeat test
DECLARE FUNCTION RTDOHMS! (TEMP!, SENTYPE$)     'Library fn. Convert RTD in temp to ohms
DECLARE FUNCTION RTDTEMP! (OHMS!, SENTYPE$)     'Library fn. Convert RTD ohms to temp
DECLARE FUNCTION SENSORIEXC$ (PERCFS%)          'Measures the resistor input exc. current
DECLARE FUNCTION SENSORIN! (PVIN!, PTCV!)       'Calculates sensor input
DECLARE FUNCTION SENSORNUM% ()                  'Assign a number to each sensor type
DECLARE FUNCTION SENSOROUT! (PVIN!, PTCV!)      'Calculates transmitter input
DECLARE FUNCTION SETAC! (ONOFF%, GENAMPL!)      'Sets AC in Off or On
DECLARE FUNCTION SETATTEN% (VOLTAGE!)           'Library fn. Sets test head R/2R ladder
DECLARE FUNCTION SETCURRENTIN! (MODIN!)         'Set input current source
DECLARE FUNCTION SETPOWER$ (ADDR%, VSUPPLY!, FUNC$)    'Library fn. Sets supply voltage
DECLARE FUNCTION STEPRESP$ ()                   'Performs Step Response Test
DECLARE FUNCTION STRINGVAL% (A$)                'Library fn.
DECLARE FUNCTION SUPPLYI$ (EXCL%)               'Measure transmitter supply current
DECLARE FUNCTION TCTEMP! (TCV!, SENTYPE$)       'Library fn. Convert TC volts to deg. C
DECLARE FUNCTION TCVOLTS! (TEMP!, TCTYPE$)      'Library fn. Convert TC in temp to V
DECLARE FUNCTION UNDERRANGE$ ()                 'Measure under-range current
DECLARE FUNCTION UPSN$ (SN$)                    'Increments dash# of serial#

'Database Record defintion for the specifications
    TYPE DBASE
    MODNAME         AS STRING * 14  'SCT1P47X-XXXX, DSCT47X-XXXX
    SENTYPE         AS STRING * 7   'mV, V, mA, xTC, xxRTDxW
    MININ           AS SINGLE
    MAXIN           AS SINGLE
    IEXCMFS         AS SINGLE
    IEXCPFS         AS SINGLE
    RCONV           AS SINGLE
    MINOUT          AS SINGLE
    MAXOUT          AS SINGLE
    OSCALPT         AS SINGLE
    GNCALPT         AS SINGLE
    LINEAR          AS SINGLE
    ACCURACY        AS SINGLE
    TESTFREQ        AS INTEGER
    ATTEN           AS INTEGER
    ATTENTOL        AS INTEGER
    STEPRMIN        AS SINGLE
    STEPRMAX        AS SINGLE
    OUTNOISE        AS SINGLE
    INPUTRES        AS SINGLE
    IOPENTC         AS SINGLE
    LEADRERR        AS SINGLE
    LINEARIZED      AS INTEGER  '1 = linearized, 0 = non-linearized
    OSCALIN         AS SINGLE   'input for offset calibration
    GNCALIN         AS SINGLE   'input for gain calibration
    BANDWIDTH       AS SINGLE   'filter -3dB point
    IMATCHTOL       AS SINGLE   'current source matching tolerance
    CALTOL          AS SINGLE   'Calibration tolerance
    VSEN            AS SINGLE   'Loop voltage sensitivity
    END TYPE
          
    TYPE DBASE2
    RECNUM          AS INTEGER
    MODNAME         AS STRING * 14
    END TYPE

'$INCLUDE: 'QB.BI2'

'define common variables
COMMON SHARED /SAMPLE/ SPECS AS DBASE, SORTDATA1 AS DBASE2, SORTDATA2 AS DBASE2
COMMON SHARED /SAMPLE/ PON%, RSENSE!, SN$, LOGDAT%, IINSEN.MEAS!
COMMON SHARED CB0VAL%, CB1VAL%, CB2VAL%, CB3VAL%
COMMON SHARED MAINMAX!, MAINMIN!, VERNMAX!, VERNMIN!
COMMON SHARED BADDRS%, LPTADDR%, MUXADDR%, THADDR%, PSADDR%, VINADDR%
COMMON SHARED PSPORT%, DVMADDR%, GENADDR%
COMMON SHARED DPSPSADDR%, DPSVINADDR%, ABCPSADDR%, ABCVINADDR%
COMMON SHARED PSMODEL$, VINMODEL$
COMMON SHARED TH$
COMMON SHARED /PRTSCR/ inreg AS RegType, outreg AS RegType

                    'assign constants to Fluke meter commands
CONST OHM4$ = "F4", OHM2$ = "F3", VODC$ = "F1", VOAC$ = "F2", MADC$ = "F5"

                    'assign constants to test head variables
CONST CB0% = 0, CB1% = 1, CB2% = 2, CB3% = 3  'control bank addresses
CONST CON% = 1, COFF% = 0               'channel 'on' defined as '1'
                    'off' defined as '0'
'CONST DVMADDR% = 1                      'GPIB address of Fluke 8842A meter

                    'assign constants to Kepco DPS power
                    'supply commands
CONST VOLT$ = "STV=", LOOPON$ = "SOP=ON", LOOPOFF$ = "SOP=OFF"
CONST CURRENT$ = "RTC", ISTAT$ = "RCS"
'CONST PSADDR% = 1                       'Power supply for transmitter power
'CONST VINADDR% = 2                      'Power supply for high voltage signal input

'assign specifications which are constant for all transmitters
CONST IINSEN! = 250                     'Input current source sense resistor, 250ohm
CONST ICL! = .036                       'Max. loop current (over current limit)
CONST LPSEN! = 250                      'Loop current sense resistor, 250 ohm
CONST IEXCSEN! = 2500                   'Iexc sense resistor, 2.5Kohm
CONST IUR1! = .0015                     'Min under-range current (A)
CONST IUR2! = .0038                     'Max under-range current (A)
CONST RSERIES! = 5100000!               '5.1M ohm, test head series input R
CONST RFNGN! = 6800                     'Function generator attenuator series R, 6.8Kohm
CONST ERRFACT! = 1'2 changed 7/10/12 TSO   'Max error in offset allowed (factor)

'******************* Test Titles and Units *****************************************

LINES:  DATA "Under-range Limit","mA","Over-range Limit","mA"
    DATA "Error @ Vloop = 10.8V","%","Error @ Vloop = 60V","%"
    DATA "Minus f.s. Exc. Current","uA","Plus f.s. Exc. Current","uA"
    DATA "Current Source Matching","%","Linearity / Conformity","%"
    DATA "Accuracy","%","Lead Resistance Effects","C/ohm"
    DATA "Loop Voltage Sensitivity","%/V","Input Resistance","Mohm"
    DATA "Open Thermocouple Response","mA","Frequency Response","dB"
    DATA "Step Response","%","Output Noise","uArms"

FUNCTION MAXLOOPV$

    'Test transmitter operation at maximum loop voltage
    MAXIN! = SENSOROUT!(SPECS.MAXIN, 0)
    MINOUT! = SPECS.MINOUT / 1000!                  'Convert to A
    MAXOUT! = SPECS.MAXOUT / 1000!
    
    MAXLPVOLT! = 60!                   'Max loop v spec is 60V
    ORANGE! = MAXOUT! - MINOUT!
    ACC! = 1 'SPECS.ACCURACY               '.01 ' 1%    OR SPECS.ACCURACY! / 100!

    CLS
    TESTTITLE$ = "Maximum Loop Voltage Test"
    CALL HEADERB(TESTTITLE$)
    LOCATE 10, 10
    PRINT "Testing, please wait."

    SNM% = SENSORNUM%
   
    IF SNM% >= 5 AND SNM% <= 7 THEN                 'Check if resistance in
    CALL OHMSET(MAXIN!)                         'Set Rin for +f.s input
    ELSE
    IF SNM% = 2 THEN
        A! = SETCURRENTIN!(MAXIN!)
    ELSE
        CALL SETDAC(MAXIN!, 1, 0)
    END IF
    END IF

    SL$ = SETPOWER$(PSADDR%, 24!, FUNC$)       'Set loop V to 24.0V
    CALL LOADMUX(2, CON%)                           'Measure Vsense
    CALL WRITEDVM(VODC$, MAXOUT! * RSENSE!)         'Sets up Meter
    ILOOP1! = READDVM(.0001) / RSENSE!               'Loop current in A

'    SL$ = SETPOWER$(PSADDR%, 999!, LOOPOFF$)               'Turn off loop power for range switch
'    CALL PAUSE(.5)

    SL$ = SETPOWER$(PSADDR%, MAXLPVOLT! + ILOOP1! * RSENSE!, FUNC$) 'Set tx voltage to 100V
                             '0.5V resolution
    IF SETPOWER$(PSADDR%, 999!, ISTAT$) = "RCS=01" THEN    'Check for over-current
    SL$ = SETPOWER$(PSADDR%, MAXLPVOLT! + ILOOP1! * RSENSE!, FUNC$) 'Set tx voltage to 100V
    END IF

    ILOOP2! = READDVM(.0001) / RSENSE!               'Loop current in A
    CALL LOADMUX(2, COFF%)                          'Clear mux lines

    SL$ = SETPOWER$(PSADDR%, 24!, FUNC$)       'Set loop V to 24.0V
    IF SETPOWER$(PSADDR%, 999!, ISTAT$) = "RCS=01" THEN    'Check for over-current
    SL$ = SETPOWER$(PSADDR%, 24!, FUNC$)   'Set tx voltage to 24.0V
    END IF

    DELTAIO! = (ILOOP2! - ILOOP1!) / ORANGE! * 100  '%
    IF ABS(DELTAIO!) <= ACC! THEN
    LPSTAT$ = "PASS"
    ELSE
    LPSTAT$ = "FAIL"
    SOUND 1000, .5
    END IF

    LOCATE 10, 10
    PRINT "Status: "; LPSTAT$;
    PRINT SPC(20);
    PRINT TAB(10); USING "Measured change in Iout at Vloop = ### V is"; MAXLPVOLT!;
    PRINT TAB(55); USING "  ###.### %"; DELTAIO!
    PRINT TAB(10); "Required change in current is";
    PRINT TAB(55); USING "+/- #.### %"; ACC!

    MAXLOOPV$ = LPSTAT$ + STR$(DELTAIO!) + "3"  '3 decimal places in display
   
    CALL RESETTH                                    'Reset test head
    CALL PAUSE(1!)

END FUNCTION

FUNCTION MEASRES! (OHM!, RESNUM%, TE$)
    
    'Measure specified resistance
    'Legend:
    'RESNUM%        Resistor
    '-------        --------
    '   1           Loop current sense resistor, 250 ohm
    '   2           Iexc sense resistor, RTD or pot input, 2.5Kohm
    '   3           Simulated sensor input, RTD or pot, 8-20Mohm
    '   4           Contact resistance, RTD or pot input, milli-ohm
    '   5           Current source sense resistor, 250 ohm
    '   6           Simulated sensor input, RDAC test
      
    SELECT CASE RESNUM%                     'Branches to the specific measurement
    CASE 1
        CB3VAL% = CB3VAL% AND &HF7              '1 1 1 1  0 1 1 1
        CALL SETTH(CB3VAL%, CB3%)               'Disconnect Rsense from loop
        CALL WRITEDVM(OHM4$, OHM! / 1000)       'Sets meter
        CALL LOADMUX(2, CON%)                 'Sets mux channel
        IF TE$ = "TE1088" THEN
            CALL LOADMUX(6, CON%)               'set sense channel for the voltage input test head
        ELSE
            CALL LOADMUX(7, CON%)               'set sense channel for the resistance input test head
        END IF
        MEASTOL! = .0001                        '0.01% measurement tolerance
        INITTOL! = .05                          '5% initial tolerance
    CASE 2
        CALL WRITEDVM(OHM2$, OHM! / 1000)       'Sets meter
        CALL LOADMUX(4, CON%)                   'Sets mux channel
        MEASTOL! = .001                         '0.1% measurement tolerance
        INITTOL! = .05                          '5% initial tolerance
    CASE 3
        CALL SETTEST(7)                         'Open series relay
        CALL WRITEDVM(OHM4$, OHM! / 1000)       'Sets meter
        CALL LOADMUX(1, CON%)                   'Sets mux channel
        CALL LOADMUX(8, CON%)                   'set sense channel
        MEASTOL! = .00005                       '0.005% measurement tolerance
        INITTOL! = .15                          '15% initial tolerance
    CASE 4
        CALL OHMSET(1E+10)                      'Open all relays
        CALL SETTEST(3)                         'Measure contact resistance
        CALL WRITEDVM(OHM4$, OHM! / 1000)       'Sets meter
        CALL LOADMUX(1, CON%)                   'Sets mux channel
        CALL LOADMUX(6, CON%)                   'set sense channel
        MEASTOL! = .00005                       '0.005% measurement tolerance
        INITTOL! = .15                          '15% initial tolerance
    CASE 5
        CALL SETTH((CB1VAL% OR &HC0), CB1%)     'Clear R/2R ladder
        CALL SETTH((CB2VAL% OR &HFF), CB2%)
        CALL SETTH((CB3VAL% OR &H20), CB3%)     'Disable input current source
                            '0 0 1 0  0 0 0 0
        CALL WRITEDVM(OHM4$, OHM! / 1000)       'Sets meter
        CALL LOADMUX(7, CON%)                   'Sets mux channel
        CALL LOADMUX(8, CON%)                   'set sense channel
        MEASTOL! = .00001                       '0.001% measurement tolerance
        INITTOL! = .05                          '5% initial tolerance
    CASE 6
        CALL SETTEST(7)                         'Open series relay
        IF OHM! < 1000 THEN
            CALL WRITEDVM(OHM4$, OHM! / 1000)   'Sets meter
            CALL LOADMUX(1, CON%)               'Sets mux channel
            CALL LOADMUX(8, CON%)               'set sense channel
        ELSE
            CALL WRITEDVM(OHM2$, OHM! / 1000)   'Sets meter
            CALL LOADMUX(1, CON%)               'Sets mux channel
        END IF
        INITTOL! = .05                          '5% initial tolerance
        MEASTOL! = .0005                        '0.05% measurement tolerance
    END SELECT
      
    TEMP! = READDVM!(OHM! * MEASTOL!)        'Measure resistor value
      
    IF OHM! > 1! AND ABS(TEMP! - OHM!) > (OHM! * INITTOL!) THEN   'Test for deviation
        CLS
        LOCATE 10, 10
        PRINT "Measured resistance = "; TEMP!; " ohms."
        PRINT TAB(10); USING "Required resistance = #######.## ohms to #######.## ohms"; OHM! * (1 - INITTOL!); OHM! * (1 + INITTOL!)
        PRINT TAB(10); "Check system setup and restart program."
        PRINT TAB(10); "If the failure continues, notify engineering."
        END
    END IF

    IF RESNUM% = 1 THEN
        CB3VAL% = CB3VAL% OR &H8                '0 0 0 0  1 0 0 0
        CALL SETTH(CB3VAL%, CB3%)               'Connect Rsense to loop
    ELSEIF RESNUM% = 3 THEN
        CALL SETTEST(2)                         'Reset to standard operation
    ELSEIF RESNUM% = 4 THEN
        CALL LOADMUX(0, CON%)                           'Clears mux
        CALL SETTEST(2)
        IF TEMP! > 1 THEN                       'Contact res. out of spec
            PRINT
            PRINT TAB(10); "Contact resistance = "; TEMP!; "ohms."
            PRINT TAB(10); "This test head requires repair."
            PRINT TAB(10); "Please notify engineering."
            CALL CONTINUE
            END
        END IF
    END IF

    IF RESNUM% <> 6 THEN CALL WRITEDVM(VODC$, 1!)   'Resets meter
    CALL LOADMUX(0, CON%)                           'Clears mux
    MEASRES! = TEMP!                                'Passes resistor value back

END FUNCTION

FUNCTION MENU0%

    ' ***** PROGRAM CONTROL MENU 0 *****
    CLS
    LOCATE 5, 16
    COLOR 14, 0, 0
    PRINT "DSCTxx-xx and SCMHVAS-Mxxx AUTOMATED TEST EQUIPMENT"
    PRINT TAB(15); "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
     
    LOCATE 8
    COLOR 15, 0, 0
    PRINT TAB(20); "Please select the TYPE of module to test"
    PRINT
    COLOR 11, 0, 0
    PRINT TAB(22); "1.) DSCT Testing"
    PRINT TAB(22); "2.) SCMHVAS Testing"
    PRINT TAB(22); "3.) Return to the FAMILY TYPE menu"
    LOCATE 22
    PRINT TAB(16); "Press the F10 key at any time to exit the program."

    DO
        A$ = INKEY$
    LOOP WHILE VAL(A$) < 1 OR VAL(A$) > 3
      
    MENU0% = VAL(A$)

END FUNCTION

FUNCTION MENU1%
     
    ' ***** PROGRAM CONTROL MENU 1 *****
    CLS
    LOCATE 5, 24
    COLOR 14, 0, 0
    PRINT "DSCTxx-xx AUTOMATED TEST EQUIPMENT"
    PRINT TAB(18); "----------------------------------------------"
    PRINT TAB(18); "*************** TEST TYPE MENU ***************"
    PRINT TAB(18); "=============================================="
     
    LOCATE 9
    COLOR 11, 0, 0
    PRINT TAB(22); "1.) Functional Test"
    PRINT TAB(22); "2.) Pre-Burn In Complete Test (NO printout)"
    PRINT TAB(22); "3.) Post-Burn In Complete Test (PRINT results)"
    PRINT TAB(22); "4.) Sealed Module Retest (Print Results, No Adjustments)"
    PRINT TAB(22); "5.) Individual Test Menu"
    PRINT TAB(22); "6.) Offset/Gain Calibration"
    PRINT TAB(22); "7.) Exit to the DSCT Main Menu"
    PRINT
    PRINT
    COLOR 15, 0, 0
    PRINT TAB(16); "Press the F9 key at any time to return to this menu"
    PRINT TAB(16); "Press the F10 key at any time to exit the program"
    COLOR 11, 0, 0
 
    DO
    I$ = INKEY$
    LOOP WHILE VAL(I$) < 1 OR VAL(I$) > 7

    MENU1% = VAL(I$)

END FUNCTION

FUNCTION MENU2%
   
    CLS
    LOCATE 2, 24
    COLOR 14, 0, 0
    PRINT "DSCTxx-xx AUTOMATED TEST EQUIPMENT"
    PRINT TAB(18); "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
    LOCATE 4, 12
    COLOR 11, 0, 0
    PRINT "1.) Under-range Test"
    PRINT TAB(12); "2.) Over-range Test"
    PRINT TAB(12); "3.) Minimum Loop Voltage Test"
    PRINT TAB(12); "4.) Maximum Loop Voltage Test"
    PRINT TAB(12); "5.) Ambient Temp. Sensor Calibration (DSCT37, 47 ONLY)"
    PRINT TAB(12); "6.) Current Source Operation & Matching (DSCT34, 36 ONLY)"
    PRINT TAB(12); "7.) Offset & Gain Calibration"
    PRINT TAB(12); "8.) Linearity / Accuracy Test"
    PRINT TAB(12); "9.) Lead Resistance Effects Test (DSCT34, 36 ONLY)"
    PRINT TAB(12); "A.) Loop Voltage Sensitivity Test"
    PRINT TAB(12); "B.) Input Resistance & Bias Current (DSCT30, 31 ONLY)"
    PRINT TAB(12); "C.) Open Thermocouple Detect Test (DSCT37, 47 ONLY)"
    PRINT TAB(12); "D.) Frequency Response Test"
    PRINT TAB(12); "E.) Step Response Test"
    PRINT TAB(12); "F.) Output Noise Test"
    PRINT TAB(12); "G.) Notes On ATE Operation"
    PRINT TAB(12); "H.) Printer Output = ";
 
    IF PON% > 0 THEN
        PRINT "ON"
    ELSE
        PRINT "OFF"
    END IF
   
    PRINT TAB(12); "I.) Log Linearity Test Data = ";
    IF LOGDAT% > 0 THEN
        PRINT "ON"
    ELSE
        PRINT "OFF"
    END IF
   
    PRINT TAB(12); "J.) Exit to the DSCT Main Menu"
    PRINT
    PRINT TAB(12); "Enter your selection.  "
      
    DO
      
        DO
            I$ = UCASE$(INKEY$)
        LOOP WHILE I$ = ""
        C% = ASC(I$)
          
    LOOP WHILE (C% < 49 OR C% > 57) AND (C% < 65 OR C% > 75)
      
    IF C% > 57 THEN
        MENU2% = C% - 55
    ELSE
        MENU2% = C% - 48
    END IF

END FUNCTION

FUNCTION MENU3%
      
    CLS
    LOCATE , 21
    COLOR 14, 0, 0
    PRINT "Module Family Selection Menu"
    PRINT TAB(21); "----------------------------"
    PRINT
    COLOR 11, 0, 0
    PRINT TAB(32); "1.)  DSCT30-xx"
    PRINT TAB(32); "2.)  DSCT31-xx"
    PRINT TAB(32); "3.)  DSCT32-xx"
    PRINT TAB(32); "4.)  DSCT34-xx"
    PRINT TAB(32); "5.)  DSCT36-xx"
    PRINT TAB(32); "6.)  DSCT37-xx"
    PRINT TAB(32); "7.)  DSCT47x-xx"
    PRINT TAB(32); "8.)  Exit"

    DO
        A$ = INKEY$
        M3% = VAL(A$)
    LOOP WHILE M3% < 1 OR M3% > 8

    M3% = M3% + 1
   
    IF M3% = 5 OR M3% = 6 THEN 'Parallel port, mux & test head addresses
        TE$ = "TE1089"                      'Resistance input test head
        FILENAME$ = "KSCTRIN.ADR"
    ELSE
        TE$ = "TE1088"                      'Voltage/current input test head
        FILENAME$ = "KSCTVIN.ADR"            'Parallel port, mux & test head addresses
    END IF

    CALL GETADD(FILENAME$)              'Gets the Parallel port, Mux and Testhead address
    MENU3% = M3%

END FUNCTION

FUNCTION MINLOOPV$

    'Test transmitter operation at minimum loop voltage

    MININ! = SENSOROUT!(SPECS.MININ, 0)
    MAXIN! = SENSOROUT!(SPECS.MAXIN, 0)
    MINOUT! = SPECS.MINOUT / 1000!                  'Convert to A
    MAXOUT! = SPECS.MAXOUT / 1000!

    MINLPVOLT! = 10.8               'Minimum loop v spec is 10.8V
    INITTOL! = .32                  '32% initial gain error allowed
                    '16% o.s. & 16% gain error, non-calibrated unit
    IOUTTOL! = .01                  '1% loop current tolerance, Vloop = 20V
    TESTTOL! = 2                    '2% test tolerance
    ACCTOL! = 1 ' SPECS.ACCURACY
    INRANGE! = MAXIN! - MININ!
    ORANGE! = MAXOUT! - MINOUT!     'Output range in A
    XFERCHAR! = ORANGE! / INRANGE!  'Gain in A/V, or A/ohm

    CLS
    TESTTITLE$ = "Minimum Loop Voltage Test"
    CALL HEADERB(TESTTITLE$)
    LOCATE 10, 10
    PRINT "Testing, please wait."
    
    SNM% = SENSORNUM%
  
    IF SNM% >= 5 AND SNM% <= 7 THEN                 'Check if resistance in
    CALL OHMSET(MAXIN!)                         'Set Rin for +f.s input
    ELSE
    IF SNM% = 2 THEN
        A! = SETCURRENTIN!(MAXIN!)
    ELSE
        CALL SETDAC(MAXIN!, 1, 0)
    END IF
    END IF

    CALL LOADMUX(2, CON%)                           'Measure Vsense
    CALL WRITEDVM(VODC$, MAXOUT! * RSENSE!)         'Sets up Meter
    ILOOPMAX! = READDVM(.001) / RSENSE!             'Loop current in A
    CALL LOADMUX(2, COFF%)

    IF (ILOOPMAX! - MAXOUT!) > MAXOUT! * INITTOL! THEN
    PRINT TAB(10); USING "Loop current = ##.# mA"; ILOOPMAX! * 1000
    PRINT TAB(10); "Transmitter is not working properly."
    CALL PAUSE(1!)
    EXIT FUNCTION
    END IF

    'Adjust input voltage for 20mA +/-1% loop current.  This adjustment
    'allows the testing of uncalibrated transmitters
    N% = 0
    WHILE ABS(ILOOPMAX! - MAXOUT!) > MAXOUT! * IOUTTOL! AND N% < 20
    N% = N% + 1
    IERR! = ILOOPMAX! - MAXOUT!
    INRANGE! = INRANGE! - IERR! / XFERCHAR!
    IF SNM% >= 5 AND SNM% <= 7 THEN             'Check if resistance in
        CALL OHMSET(MININ! + INRANGE!)          'Adjust input
    ELSE
                            'Fine adjustment not possible
                            'with high voltage power supply
                            '0.5V resolution.
        IF MININ! + INRANGE! > 10 THEN
        MAXOUT! = ILOOPMAX!
        N% = 20
        ELSE
        CALL SETDAC(MININ! + INRANGE!, 1, 0)    'Adjust input
        END IF
    END IF
    CALL LOADMUX(2, CON%)                           'Measure Vsense
    CALL WRITEDVM(VODC$, MAXOUT! * RSENSE!)         'Sets up Meter
    ILOOPMAX! = READDVM(.0001) / RSENSE!
    CALL LOADMUX(2, COFF%)
    WEND

    SL$ = SETPOWER$(PSADDR%, MINLPVOLT! + ILOOPMAX! * RSENSE! + .5, FUNC$)     'Set tx voltage to 10.8V
                                '0.5V resolution
    CALL LOADMUX(2, CON%)                           'Measure Vsense
    CALL WRITEDVM(VODC$, MAXOUT! * RSENSE!)         'Sets up Meter
    ILOOP! = READDVM(.0001) / RSENSE!
    CALL LOADMUX(2, COFF%)

    'Iout is +/-1%, allow another +/-1% variation
    'DELTAIO! = (ILOOP! - MAXOUT!) / ORANGE! * 100!
    DELTAIO! = (ILOOP! - ILOOPMAX!) / ORANGE! * 100!
   
    'IF ABS(DELTAIO!) <= TESTTOL! THEN
    IF ABS(DELTAIO!) <= ACCTOL! THEN
    LPSTAT$ = "PASS"
    ELSE
    LPSTAT$ = "FAIL"
    SOUND 1000, .5
    END IF

    LOCATE 10, 10
    PRINT "Status: "; LPSTAT$;
    PRINT SPC(20);
    PRINT TAB(10); USING "Measured change in Iout at Vloop = ## V is"; MINLPVOLT!;
    PRINT TAB(55); USING "  ###.### %"; DELTAIO!
    PRINT TAB(10); "Required change in Iout is";
    PRINT TAB(55); USING "+/- #.### %"; ACCTOL!

    MINLOOPV$ = LPSTAT$ + STR$(DELTAIO!) + "3"  '3 decimal places in display
    
    CALL RESETTH                                    'Reset test head
    CALL PAUSE(1!)

END FUNCTION

SUB MODOUTLINE
       
        'print a bottom view of the module showing potentiometer location
         
        LOCATE 3, 25
        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

        LOCATE 5, 36
        PRINT CHR$(233)
        LOCATE 5, 44
        PRINT CHR$(233)
        LOCATE 4, 34
        PRINT CHR$(233)

END SUB

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(14); "(T)roubleshoot will pause the program.  The DVM will continuously"
    PRINT TAB(14); "display the calibration reading."
    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

FUNCTION OFFSETCAL$ (cal%, CONTRES!)

    'Calibrate transmitter offset
    'Inputs;        calibration flag
    '               measured contact resistance (used for resistance in only)

    SENSOR$ = SPECS.SENTYPE
    MAXIN! = SENSOROUT!(SPECS.MAXIN, 0)     'Used to check for high voltage input
    MINOUT! = SPECS.MINOUT / 1000!          'Convert to A
    MAXOUT! = SPECS.MAXOUT / 1000!          'Convert to A
    CALOS! = SPECS.OSCALPT / 100!           'Convert from %
    INITTOL! = 12                           'Uncalibrated offset tolerance
    CALTOL! = SPECS.CALTOL                  'Calibration tolerance (% span)
    OSCALIN! = SPECS.OSCALIN                'transmitter input for offset calibration
    GNCALIN! = SPECS.GNCALIN                'transmitter input for gain calibration
    BANDWIDTH! = SPECS.BANDWIDTH
    LIN% = SPECS.LINEARIZED
    SNM% = SENSORNUM%

    ORANGE! = MAXOUT! - MINOUT!             'Output range (V)
       
    IF (SNM% >= 3 AND SNM% <= 6) AND LIN% = 0 THEN
    CALSPAN! = Iout!(SENSOROUT!(GNCALIN!, 0)) - Iout!(SENSOROUT!(OSCALIN!, 0)) 'Adjustment range is +/- x% of +f.s.
                        'Output not linear w/ input
    ELSE                                        'temperature.
    CALSPAN! = Iout!(GNCALIN!) - Iout!(OSCALIN!) 'Adjustment range is +/- x% of +f.s.
    END IF
   
    CLS
    TESTTITLE$ = "Offset Calibration"
    CALL HEADERB(TESTTITLE$)
       
        CALL MODOUTLINE
        LOCATE 7
        PRINT TAB(36); CHR$(24);
        PRINT TAB(26); "OFFSET POTENTIOMETER";
     
    IF cal% = 2 THEN
    ZERROR! = INITTOL!                      'Offset tolerance for func. test (%)
    TOL! = .0001                            'Measurement tolerance, 1 pass test
    ELSE
    ZERROR! = CALTOL!                       'Offset calibration tolerance (%)
    TOL! = 0!
    END IF

    IF SNM% >= 5 AND SNM% <= 7 THEN         'Check if RTD in
    MININ! = SENSOROUT!(OSCALIN!, 0)    'Calc. +f.s. ohms
    CALL OHMSET(MININ!)                 'Set -f.s. input
    END IF

    DO
    TIME1! = TIMER                          'Start timer
    
    LOCATE 10, 10
    PRINT TAB(10); "Measuring input.  Please wait..."
    IF SNM% >= 5 AND SNM% <= 7 THEN         'Check if RTD in
        IF cal% = 0 THEN CALL WRITEDVM("S0", 0)     'Slow reading rate for max accuracy
        SL$ = SETPOWER$(PSADDR%, 999!, LOOPOFF$)       'Disable power supply
        MININMEAS! = MEASRES!(MININ!, 3, "") + CONTRES! 'Measure simulated resistor
        SL$ = SETPOWER$(PSADDR%, 24!, FUNC$)           'Set Vsupply to 24.0V
        PAUSE (1)'(2)
    ELSE
        SL$ = SETPOWER$(PSADDR%, 24!, FUNC$)           'Set Vsupply to 24.0V
        IF SNM% = 3 THEN
        PTCV! = PARASITICTCV!(VCJC!)
        IF VCJC! = 99! THEN EXIT FUNCTION
        END IF
        MININ! = SENSOROUT!(OSCALIN!, PTCV!) 'Calc. minin volts, meas. vcjc
        IF SNM% = 2 THEN
        MININMEAS! = SETCURRENTIN!(MININ!)
        ELSE
        CALL SETDAC(MININ!, 1, 0)                   'Sets DAC
        IF cal% = 0 OR ABS(MININ!) > 10! THEN       'Always measure high voltage
                                'input to get exact reading
            CALL WRITEDVM("S0", 0)                  'Slow reading rate for max accuracy
            CALL LOADMUX(1, CON%)
            CALL WRITEDVM(VODC$, MININ!)            'Sets meter to read
            MININMEAS! = READDVM!(MININ! * .0002)   '0.02% tolerance
            CALL LOADMUX(1, COFF%)
        ELSE
            MININMEAS! = MININ!
        END IF
        END IF
    END IF
      
    CALL WRITEDVM("S1", 0)       'Medium reading rate
       
    IF (SNM% >= 3 AND SNM% <= 6) AND LIN% = 0 THEN
        IOUTCALC! = Iout!(MININMEAS! + PTCV!) + CALOS! * ORANGE!
                        'Output not linear w/ input
    ELSE                                'temperature.
        IOUTCALC! = Iout!(SENSORIN!(MININMEAS!, PTCV!)) + CALOS! * ORANGE!
    END IF
    
    CALL LOADMUX(2, CON%)                'Measure Vsense
    CALL WRITEDVM(VODC$, (IOUTCALC! + CALSPAN! * INITTOL / 100!) * RSENSE!) 'Scale meter
    CALL PAUSE(1!)'(2!)                      'Wait for output to settle.
      
    LOCATE 10, 10
    PRINT "Offset Error =";
    PRINT SPC(20);
      
    L% = 0

    DO
        L% = L% + 1
        ERRORPERC! = (READDVM!(TOL!) / RSENSE! - IOUTCALC!) / ORANGE! * 100! 'Error (%)
       
        LOCATE 10, 24
        PRINT USING "+###.### %"; ERRORPERC!
       
        LOCATE 15, 10
        IF cal% > 0 THEN
        CONREADS% = 5
        ELSEIF ABS(ERRORPERC!) < ZERROR! THEN
        SOUND 200, .5
        PRINT "Stop turning offset potentiometer          "
        CONREADS% = CONREADS% + 1
        ELSEIF ERRORPERC! < 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$) = "T" THEN
        PRINT TAB(10); "Trouble Shooting Mode"
        CALL WRITEDVM("*", IOUTCALC! * RSENSE!)
        CALL CONTINUE
            CALL WRITEDVM("*T2S1", 0)          'Initialize Fluke meter
        LOCATE 20, 10
        PRINT SPC(22);
        ELSEIF UCASE$(A$) = "C" THEN
        CONREADS% = 5
        END IF
                            're-measure input
                            'once every 40 cycles
        CALL PAUSE(.2)                          'Slow down loop
    LOOP WHILE CONREADS% < 5 AND L% < 150
    CALL LOADMUX(2, COFF%)
'        IF CAL% = 0 OR MAXIN! > 10! THEN
'            CALL WRITEDVM("S1", 0)       'Medium reading rate
'        END IF
    LOOP WHILE CONREADS% < 5

    IF ABS(ERRORPERC!) <= ZERROR! THEN
    OFF$ = "PASS"
    ELSE
    OFF$ = "FAIL"
    SOUND 1000, .5
    END IF

    LOCATE 15, 10
    PRINT "Status: "; OFF$;
    PRINT SPC(31);
    PRINT TAB(10); "Offset calibration error is";
    PRINT TAB(50); USING "  +###.### %"; ERRORPERC!
    PRINT TAB(10); "Max. offset calibration error is";
    PRINT TAB(50); USING "+/-###.### %"; ZERROR!
   
    OFFSETCAL$ = OFF$ + STR$(ERRORMV!)
    
    CALL RESETTH                                    'Reset the test head
    CALL PAUSE(1)

END FUNCTION

FUNCTION OFFSETERR! (cal%, CONTRES!)

    'Calibrate transmitter offset
    'Inputs;        calibration flag
    '               measured contact resistance (used for resistance in only)

    SENSOR$ = SPECS.SENTYPE
    MAXIN! = SENSOROUT!(SPECS.MAXIN, 0)     'Used to check for high voltage input
    MINOUT! = SPECS.MINOUT / 1000!          'Convert to A
    MAXOUT! = SPECS.MAXOUT / 1000!          'Convert to A
    CALOS! = SPECS.OSCALPT / 100!           'Convert from %
    INITTOL! = 12                           'Uncalibrated offset tolerance
    CALTOL! = SPECS.CALTOL                  'Calibration tolerance (% span)
    OSCALIN! = SPECS.OSCALIN                'transmitter input for offset calibration
    GNCALIN! = SPECS.GNCALIN                'transmitter input for gain calibration
    BANDWIDTH! = SPECS.BANDWIDTH
    LIN% = SPECS.LINEARIZED
    SNM% = SENSORNUM%

    ORANGE! = MAXOUT! - MINOUT!             'Output range (V)
      
    IF (SNM% >= 3 AND SNM% <= 6) AND LIN% = 0 THEN
    CALSPAN! = Iout!(SENSOROUT!(GNCALIN!, 0)) - Iout!(SENSOROUT!(OSCALIN!, 0)) 'Adjustment range is +/- x% of +f.s.
                        'Output not linear w/ input
    ELSE                                        'temperature.
    CALSPAN! = Iout!(GNCALIN!) - Iout!(OSCALIN!) 'Adjustment range is +/- x% of +f.s.
    END IF
  
    CLS
    TESTTITLE$ = "Offset Calibration Verification"
    CALL HEADERB(TESTTITLE$)
    
    ZERROR! = CALTOL! * ERRFACT!            'Offset calibration tolerance (%) * factor
    TOL! = 0!

    IF SNM% >= 5 AND SNM% <= 7 THEN         'Check if RTD in
    MININ! = SENSOROUT!(OSCALIN!, 0)    'Calc. +f.s. ohms
    CALL OHMSET(MININ!)                 'Set -f.s. input
    END IF

   
    LOCATE 10, 10
    PRINT TAB(10); "Measuring input.  Please wait..."
    IF SNM% >= 5 AND SNM% <= 7 THEN         'Check if RTD in
        IF cal% = 0 THEN CALL WRITEDVM("S0", 0)     'Slow reading rate for max accuracy
        SL$ = SETPOWER$(PSADDR%, 999!, LOOPOFF$)       'Disable power supply
        MININMEAS! = MEASRES!(MININ!, 3, "") + CONTRES! 'Measure simulated resistor
        SL$ = SETPOWER$(PSADDR%, 24!, FUNC$)           'Set Vsupply to 24.0V
        PAUSE (1)'(2)
    ELSE
        SL$ = SETPOWER$(PSADDR%, 24!, FUNC$)           'Set Vsupply to 24.0V
        IF SNM% = 3 THEN
        PTCV! = PARASITICTCV!(VCJC!)
        IF VCJC! = 99! THEN EXIT FUNCTION
        END IF
        MININ! = SENSOROUT!(OSCALIN!, PTCV!) 'Calc. minin volts, meas. vcjc
        IF SNM% = 2 THEN
        MININMEAS! = SETCURRENTIN!(MININ!)
        ELSE
        CALL SETDAC(MININ!, 1, 0)                   'Sets DAC
        IF cal% = 0 OR ABS(MININ!) > 10! THEN       'Always measure high voltage
                                'input to get exact reading
            CALL WRITEDVM("S0", 0)                  'Slow reading rate for max accuracy
            CALL LOADMUX(1, CON%)
            CALL WRITEDVM(VODC$, MININ!)            'Sets meter to read
            MININMEAS! = READDVM!(MININ! * .0002)   '0.02% tolerance
            CALL LOADMUX(1, COFF%)
        ELSE
            MININMEAS! = MININ!
        END IF
        END IF
    END IF
     
    CALL WRITEDVM("S1", 0)       'Medium reading rate
      
    IF (SNM% >= 3 AND SNM% <= 6) AND LIN% = 0 THEN
        IOUTCALC! = Iout!(MININMEAS! + PTCV!) + CALOS! * ORANGE!
                        'Output not linear w/ input
    ELSE                                'temperature.
        IOUTCALC! = Iout!(SENSORIN!(MININMEAS!, PTCV!)) + CALOS! * ORANGE!
    END IF
   
    CALL LOADMUX(2, CON%)                'Measure Vsense
    CALL WRITEDVM(VODC$, (IOUTCALC! + CALSPAN! * INITTOL / 100!) * RSENSE!) 'Scale meter
    CALL PAUSE(1!)'(2!)                      'Wait for output to settle.
     
    LOCATE 10, 10
    PRINT "Offset Error =";
    PRINT SPC(20);
     
    DO
        ERRORPERC! = (READDVM!(TOL!) / RSENSE! - IOUTCALC!) / ORANGE! * 100! 'Error (%)
      
        LOCATE 10, 24
        PRINT USING "+###.### %"; ERRORPERC!
      
        SOUND 200, .5
        CONREADS% = CONREADS% + 1
       
        LOCATE 20, 10
        A$ = INKEY$
        IF UCASE$(A$) = "T" THEN
        PRINT TAB(10); "Trouble Shooting Mode"
        CALL WRITEDVM("*", IOUTCALC! * RSENSE!)
        CALL CONTINUE
        LOCATE 20, 10
        PRINT SPC(22);
        ELSEIF UCASE$(A$) = "C" THEN
        CONREADS% = 5
        END IF
                            're-measure input
                            'once every 40 cycles
        CALL PAUSE(.2)                          'Slow down loop
    LOOP WHILE CONREADS% < 5

    IF ABS(ERRORPERC!) <= ZERROR! THEN
    OFF$ = "PASS"
    ELSE
    OFF$ = "FAIL"
    SOUND 1000, .5
    END IF

    LOCATE 15, 10
    PRINT "Status: "; OFF$;
    PRINT SPC(31);
    PRINT TAB(10); "Offset calibration error is";
    PRINT TAB(50); USING "  +###.### %"; ERRORPERC!
    PRINT TAB(10); "Max. offset calibration error is";
    PRINT TAB(50); USING "+/-###.### %"; ZERROR!
  
    IF OFF$ = "FAIL" THEN
'        PRINT TAB(10); ""
'        PRINT TAB(10); "Offset error is bigger than allowed. Software will loop back for recalibration";
        PAUSE (.2)
    END IF


    OFFSETERR! = ERRORPERC!

    CALL RESETTH                                    'Reset the test head
    CALL PAUSE(.2) '(1)

END FUNCTION

SUB ONESHOTTEST
       
    'Provide a continuous strobe to test one-shot pulse width
    'Trigger line (E07) is on '123 pin 1, S/H pulse is on pin 13 for TE1088.
    'Trigger line (E06) is on '123 pin 1, S/H pulse is on pin 13 for TE1089.

    CALL GETSPECS

    CLS
    LOCATE 10, 10
     
    IF TE$ = "TE1088" THEN
    PRINT TE$
    PRINT "Trigger line (E07) is on '123 pin 1, S/H pulse is on pin 13."
    ELSE                'TE1089
    PRINT TE$
    PRINT "Trigger line (E06) is on '123 pin 1, S/H pulse is on pin 13."
    END IF

    PRINT
    PRINT "Press any key to exit test"

    SNM% = SENSORNUM%

    DO
    IF SNM% >= 5 AND SNM% <= 7 THEN             'Check if resistance in
        CB0VAL% = CB0VAL% AND &HBF              '1 0 1 1  1 1 1 1
    ELSE
        CB0VAL% = CB0VAL% AND &H7F              '0 1 1 1  1 1 1 1
    END IF
      
    CALL SETTH(CB0VAL%, CB0%)                   'set step relay, k7
                            'start one-shot 185ms pulse
    
    CALL PAUSE(.5)                              'wait for pulse
      
    IF SNM% >= 5 AND SNM% <= 7 THEN             'Check if resistance in
        CB0VAL% = CB0VAL% OR &H40               '0 1 0 0  0 0 0 0
    ELSE
        CB0VAL% = CB0VAL% OR &H80               '1 0 0 0  0 0 0 0
    END IF
       
    CALL SETTH(CB0VAL%, CB0%)                   'reset test
     
    I$ = INKEY$
   
    LOOP WHILE I$ = ""

END SUB

FUNCTION OPENTC$
      
    MINOUT! = SPECS.MINOUT / 1000           'Convert to A
    MAXOUT! = SPECS.MAXOUT / 1000
    MININ! = SENSOROUT!(SPECS.MININ!, 0)    'Approximate -f.s. in, not including
                        'parasitic TC

    SPEC! = SPECS.IOPENTC! / 1000
    ORANGE! = MAXOUT! - MINOUT!

    CLS
    TESTTITLE$ = "Open Thermocouple Detect Test"
    CALL HEADERB(TESTTITLE$)
    LOCATE 10, 10

    SNM% = SENSORNUM%
      
    IF SNM% < 3 OR SNM% > 4 THEN                    'Check for TC in
    PRINT "This test is not performed on model "; SPECS.MODNAME
    EXIT FUNCTION
    ELSE
    PRINT "Testing, please wait."
    END IF

    CALL SETDAC(MININ!, 1, 0)                       'Set -f.s. input, zero
                            'input underranges some transmitters

    CALL PAUSE(.5)
                            'Remove short on inputs
    CALL SETTH(CB0VAL% OR &H8, CB0%)                '0 0 0 0  1 0 0 0
    CALL SETTH((CB1VAL% OR &HC0), CB1%)             'Clear R/2R ladder
    CALL SETTH((CB2VAL% OR &HFF), CB2%)

    CALL PAUSE(2.5)                                 'Wait 2.5s (spec is 10s)
    CALL LOADMUX(2, CON%)                           'Measure Vsense
    CALL WRITEDVM(VODC$, MAXOUT! * RSENSE!)
    ILOOP! = READDVM!(.001) / RSENSE!               'Loop current (A)
                            'Use 1mV tolerance in case
                            'output is still changing.
    CALL LOADMUX(2, COFF%)

    IF SPEC! > MAXOUT! THEN                 'Check for upscale open TC detect
    COND$ = ">"
    IF ILOOP! >= SPEC! THEN
        OTC$ = "PASS"
    ELSE
        OTC$ = "FAIL"
        SOUND 1000, .5
    END IF
    ELSE                                    'else downscale open TC detect
    COND$ = "<"
    IF ILOOP! <= SPEC! THEN
        OTC$ = "PASS"
    ELSE
        OTC$ = "FAIL"
        SOUND 1000, .5
    END IF
    END IF
      
    LOCATE 10, 10
    PRINT "Status: "; OTC$;
    PRINT SPC(20);
    PRINT TAB(10); "Open thermocouple response is";
    PRINT TAB(50); USING "  ##.# mA"; ILOOP! * 1000!
    PRINT TAB(10); "Required response is";
    PRINT TAB(50); USING "& ##.# mA"; COND$; SPEC! * 1000!

    OPENTC$ = OTC$ + STR$(ILOOP! * 1000!) + "1"
     
    CALL RESETTH                                    'Reset test head
    CALL PAUSE(1!)

END FUNCTION

FUNCTION OUTNOISE$

    '8842A displays a non-zero reading of < 300 digits in the 200mVAC range.
    'This equates to 300uVrms.  Typical readings are 150uVrms, but testing of
    'several meters shows readings from 90uVrms to 900uVrms.  Readings are not
    'always consistent between the front panel and rear panel input terminals.
    'As long as the voltage being measured is 1000 counts or more (>=1mVrms), the
    'reading will be within rated accuracy.  However, this is not the case for the
    'narrow bandwidth signal conditioners and transmitters.
    'The displayed reading is the sum of the squares of the signal, the rms converter
    'error and the internally generated noise.
    'i.e.  Vn,rms = sqr(signal(mVrms)^2 + 0.300^2)
    'or signal(mVrms) = SQR(Vn,rms^2 - 0.300^2)
    'Assume the typical non-zero error is 200 digits
    'This error should also be taken into account when using low value Vrms readings
    'to determine filter performance (frequency response test).
    'Some 8842A meters read 0 digits of noise on the 2VAC scale (80 digits max).
    'In these cases, measured signal conditioner output noise matches that made
    'with other test equipment.
    'The -3dB bandwidth for AC measurements is 300KHz.  Accuracy is specified for
    'signals with frequency components up to 100KHz.
    'A 100KHz pole has been added to the input leads at the 8842A to eliminate
    'high frequency pickup and switching spike amplification from the computers
    'and long signal lines.
    'Crest factors beyond 3.0 can exceed the 8842A's dynamic range limitations and
    'cause large errors.  Large crest factors are typical of waveforms with spikes.
    'Use caution when measuring waveforms with significant spikes in bandwidths
    'less than 300KHz.
      
    MININ! = SENSOROUT!(SPECS.OSCALIN, 0)           'Calculate transmitter input
    SPEC! = SPECS.OUTNOISE / 1000000!               'convert to uA

    CLS
    TESTTITLE$ = "Output Noise Test"
    CALL HEADERB(TESTTITLE$)
    LOCATE 10, 10
    PRINT "Testing, please wait."

    SNM% = SENSORNUM%

    IF SNM% >= 5 AND SNM% <= 7 THEN                 'Check if resistance in
    CALL OHMSET(MININ!)                     'Set -f.s. input
    ELSE
    IF SNM% = 2 THEN
        A! = SETCURRENTIN!(MININ!)
    ELSE
        CALL SETDAC(MININ!, 1, 0)
    END IF
    END IF

    CALL LOADMUX(2, CON%)                           'Measure Vsense
    CALL WRITEDVM(VOAC$, SPEC! * RSENSE!)           'Sets Fluke
      
    VRMS! = READDVM!(.04 * SPEC!)                   'Output noise (A)
   
    IF VRMS! > .0002 THEN
    VRMS! = SQR(VRMS! ^ 2 - .0002 ^ 2) 'Account for meter zero-input error
    END IF
   
    IRMS! = VRMS! / RSENSE!                         'Output noise (A)
       
    CALL LOADMUX(2, COFF%)
      
    IF IRMS! <= SPEC! THEN
    INOISE$ = "PASS"
    ELSE
    INOISE$ = "FAIL"
    SOUND 1000, .5
    END IF

    LOCATE 10, 10
    PRINT "Status: "; INOISE$;
    PRINT SPC(20);
    PRINT TAB(10); "Measured output noise is";
    PRINT TAB(50); USING "###.# uA rms"; IRMS! * 1000000!
    PRINT TAB(10); "Maximum output noise is";
    PRINT TAB(50); USING "###.# uA rms"; SPEC! * 1000000!

    OUTNOISE$ = INOISE$ + STR$(IRMS! * 1000000!) + "1"  'Convert to uV
      
    CALL RESETTH                                    'Reset test head
    CALL PAUSE(1!)

END FUNCTION

FUNCTION OVERRANGE$

    'Test the over-range limit of the transmitter
    MININ! = SENSOROUT!(SPECS.MININ, 0)
    MAXIN! = SENSOROUT!(SPECS.MAXIN, 0)
    MAXOUT! = SPECS.MAXOUT / 1000!                  'Convert to A

    INRANGE! = MAXIN! - MININ!
     
    CLS
    TESTTITLE$ = "Over-Range Test"
    CALL HEADERB(TESTTITLE$)
    LOCATE 10, 10
     
    SNM% = SENSORNUM%
    IF SNM% >= 5 AND SNM% <= 7 THEN     'Check if resistance in
    PRINT "Testing, please wait."
    OVEROHM! = MAXIN! + .8 * (INRANGE!)     'Set Rin for 80% over-range
    CALL OHMSET(OVEROHM!)
    ELSE
    IF SNM% = 2 THEN
        OVERI! = MAXIN! + .8 * (INRANGE!)
        IF OVERI! > 31.5 THEN               'Highest limit current from the test head
            OVERI! = 31.5
        END IF
        A! = SETCURRENTIN!(OVERI!)
    ELSE
        IF MAXIN! + .8 * INRANGE! > 9.75 THEN       'Test voltage is beyond DAC capability
        PRINT "This test is not performed on model "; SPECS.MODNAME
        OVERRANGE$ = "PASS"
        EXIT FUNCTION
        ELSE
        PRINT "Testing, please wait."
        OVERVOLT! = MAXIN! + .8 * INRANGE!      'Set Vin for 80% over-range
        CALL SETDAC(OVERVOLT!, 1, 0)
        END IF
    END IF
    END IF
   
    CALL LOADMUX(2, CON%)                           'Measure Vsense

    'CALL LOADMUX(1, COFF%) 'incidentally turned on
    CALL WRITEDVM(VODC$, MAXOUT! * RSENSE!)         'Sets up Meter
    OVERI! = READDVM(.001) / RSENSE!                'Loop current in A
    CALL LOADMUX(2, COFF%)                          'Clear mux lines

    IF OVERI! < ICL! AND OVERI! > MAXOUT! THEN
    OISTAT$ = "PASS"
    ELSE
    OISTAT$ = "FAIL"
    SOUND 1000, .5
    END IF

    LOCATE 10, 10
    PRINT "Status: "; OISTAT$;
    PRINT SPC(20);
    PRINT TAB(10); "Measured over-range current is";
    PRINT TAB(50); USING "##.## mA"; OVERI! * 1000
    PRINT TAB(10); "Required over-range current is";
    PRINT TAB(50); USING "##.## mA to ##.## mA "; MAXOUT! * 1000; ICL! * 1000

    OVERRANGE$ = OISTAT$ + STR$(OVERI! * 1000!) + "1"   '1 decimal place in display
     
    CALL RESETTH                                    'Reset test head
    CALL PAUSE(1!)

END FUNCTION

FUNCTION PARASITICTCV! (VCJC!)

    'Measures CJC input to transmitter and calculates compensation voltage to
    'be added to transmitter input.
         
    SENSOR$ = SPECS.SENTYPE
    TCTYPE$ = LEFT$(SENSOR$, 1)
 
    SEEBECK! = (TCVOLTS!(50!, TCTYPE$) - TCVOLTS!(0!, TCTYPE$)) / 50!
    VTC25C! = TCVOLTS!(25!, TCTYPE$)        'Calculate TC voltage @ 25C
    CALL LOADMUX(4, CON%)                   'Measure test head CJC output
    CALL WRITEDVM(VODC$, .5)                'Vcjc(25C) = 0.5100V
    VCJC! = READDVM(.0001)
    CALL LOADMUX(4, COFF%)
    IF ABS(VCJC! - .51) > .05 THEN          '+/- 25C error for malfunction
    SOUND 1000, .5                      'This means 0C <= Ta <= 50C
    PRINT
    PRINT TAB(10); "TE10302 temperature sensor malfunction."
    PRINT TAB(10); USING "Vcjc = #.### V"; VCJC!
    CALL CONTINUE
    VCJC! = 99!
    EXIT FUNCTION
    END IF
    AMBTEMPDIFF! = (VCJC! - .51) / -.0025  'Temp. difference from 25C.
    'PARASITICTCV! = TCVOLTS!(25 + AMBTEMPDIFF!, TCTYPE$)
    PARASITICTCV! = VTC25C! + AMBTEMPDIFF! * SEEBECK!  'Parasitic TC voltage

END FUNCTION

SUB REPORT (STATUS$(), TSPEC$())

'Output format
'1        10        20        30        40        50        60        70        80
'         |         |         |         |         |         |         |         |
'            Parameter          Measured Value*     Specification     Status
'    =========================  ===============  ===================  ======
'                                 ###### uVrms     ## to ### uVrms     PASS
'                                                            ohm/ohm
    RESTORE LINES
      
    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); "======"
      
    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 16
    READ A$, B$
    IF LEN(STATUS$(X)) > 4 THEN         'Check for test data
        IF X = 5 AND (SENSORNUM% = 5 OR SENSORNUM% = 7) AND (LEFT$(SPECS.MODNAME, 4) <> "DSCT") THEN
        A$ = "Excitation Current #1"
        ELSEIF X = 7 AND (SENSORNUM% = 5 OR SENSORNUM% = 7) AND (LEFT$(SPECS.MODNAME, 4) <> "DSCT") THEN
        A$ = "Excitation Current #2"
        END IF
        PRINT TAB(5); A$;
        IF PON% = 1 THEN LPRINT TAB(5); A$;
        'STATUS$(x) format = <pass/fail>+<measured data>+<# decimal places>
        '                      4 char.      ? char          1 char.
        DATALEN% = LEN(STATUS$(X))
        NUMDATA! = VAL(MID$(STATUS$(X), 5, DATALEN% - 5))
                    'print using requested # of decimal places
        IF X = 10 AND SENSORNUM% = 7 THEN
        B$ = "ohm/ohm"          'Set proper units
        END IF
        IF RIGHT$(STATUS$(X), 1) = "0" THEN
           PRINT TAB(34); USING "###### &"; NUMDATA!; B$;
           IF PON% = 1 THEN LPRINT TAB(34); USING "###### &"; NUMDATA!; B$;
        ELSEIF RIGHT$(STATUS$(X), 1) = "1" THEN
           PRINT TAB(34); USING "####.# &"; NUMDATA!; B$;
           IF PON% = 1 THEN LPRINT TAB(34); USING "####.# &"; NUMDATA!; B$;
        ELSEIF RIGHT$(STATUS$(X), 1) = "2" THEN
           PRINT TAB(34); USING "###.## &"; NUMDATA!; B$;
           IF PON% = 1 THEN LPRINT TAB(34); USING "###.## &"; NUMDATA!; B$;
        ELSEIF RIGHT$(STATUS$(X), 1) = "3" THEN
           PRINT TAB(34); USING "##.### &"; NUMDATA!; B$;
           IF PON% = 1 THEN LPRINT TAB(34); USING "##.### &"; NUMDATA!; B$;
        ELSEIF RIGHT$(STATUS$(X), 1) = "4" THEN
           PRINT TAB(34); USING "#.#### &"; NUMDATA!; B$;
           IF PON% = 1 THEN LPRINT TAB(34); USING "#.#### &"; NUMDATA!; B$;
        END IF
          
        SPECLEN% = LEN(TSPEC$(X))
        PRINT TAB(60 - SPECLEN%); TSPEC$(X);
        PRINT TAB(61); B$;
        PRINT TAB(71); LEFT$(STATUS$(X), 4)
       
        IF PON% = 1 THEN
            LPRINT TAB(60 - SPECLEN%); TSPEC$(X);
            LPRINT TAB(61); B$;
            LPRINT TAB(71); LEFT$(STATUS$(X), 4)
        END IF
   
    END IF
    NEXT

END SUB

SUB RESETTH
      
    'reset the voltage or RTD test head to a known, desired condition.
      
    SNM% = SENSORNUM%
    IF SNM% >= 5 AND SNM% <= 7 THEN         'Check if resistance in
    CALL OHMSET(100!)                   'Nominal resistance value
    CALL SETTEST(2)                     'Standard operation
    ELSE
    IF SNM% <> 2 AND SNM% <> 9 AND SENSOROUT!(SPECS.MAXIN, 0) > 10! THEN
        SL$ = SETPOWER$(VINADDR%, 999!, LOOPOFF$)  'Disable power supply
                        'Remove high voltage from +/-IN
        CB3VAL% = CB3VAL% OR &HC0           '1 1 0 0  0 0 0 0
        CALL SETTH(CB3VAL%, CB3%)
    END IF
    CALL SETDAC(0!, 1, 0)   'Clear attenuator, short transmitter inputs
    END IF

END SUB

FUNCTION SENSORIEXC$ (PERCFS%)
     
    'This routine tests the RTD or resistance excitation current source
    'with plus or minus full scale input.

    IF PERCFS% = 0 THEN
        IEXC! = SPECS.IEXCMFS           'Nominal excitation current (uA)
        RIN! = SENSOROUT!(SPECS.MININ, 0) 'Test with -f.s. input
        INCOND$ = "Minus Full Scale"
    ELSE
        IEXC! = SPECS.IEXCPFS           'Nominal excitation current (uA)
        RIN! = SENSOROUT!(SPECS.MAXIN, 0) 'Test with +f.s. input
        INCOND$ = "Plus Full Scale"
    END IF
      
    ITOL! = .05                         'Exctiation current tolerance, +/-5%

    CLS
    TESTTITLE$ = "Excitation Current Source Test, " + INCOND$ + " Input"
    CALL HEADERB(TESTTITLE$)
    LOCATE 10, 10
     
    SNM% = SENSORNUM%
    IF SNM% < 5 OR SNM% > 7 THEN   'Check if resistance in
        PRINT "This test is not performed on model "; SPECS.MODNAME
        EXIT FUNCTION
    ELSE
        PRINT "Testing, please wait..."
    END IF

    SL$ = SETPOWER$(PSADDR%, 999!, LOOPOFF$)       'Disable power supply

    CALL OHMSET(RIN!)                   'Set input R = high ohms
    RINPUT! = MEASRES!(RIN!, 3, "")
  
    CALL SETTEST(2)
       
    SL$ = SETPOWER$(PSADDR%, 24!, FUNC$)           'Set Vsupply to 24.0V
    PAUSE (1)
    VSENSE! = RINPUT! * IEXC! / .000001
    CALL WRITEDVM(VODC$, VSENSE!)
    CALL LOADMUX(1, CON%)
    IEXCMEAS! = READDVM!(VSENSE! * .0001) / RINPUT! * 1000000!
                                        'Measured excitation current (uA)
                                        'Tolerance = .01% reading
    CALL LOADMUX(1, COFF%)
 
    IF ABS(IEXCMEAS! - IEXC!) < IEXC! * ITOL! THEN
        IXSTAT$ = "PASS"
    ELSE
        IXSTAT$ = "FAIL"
        SOUND 1000, .5
        LOCATE 10, 10
        PRINT "Excitation current source out of tolerance."
    END IF

    LOCATE 15, 10
    PRINT "Status: "; IXSTAT$;
    PRINT TAB(10); "Measured excitation current is";
    PRINT TAB(50); USING "####.# uA"; IEXCMEAS!
    PRINT TAB(10); "Required value of excitation current is";
    PRINT TAB(50); USING "####.# uA to ####.# uA"; IEXC! * (1 - ITOL!); IEXC! * (1 + ITOL!)
   
    SENSORIEXC$ = IXSTAT$ + STR$(IEXCMEAS!) + "1"
 
    SL$ = SETPOWER$(PSADDR%, 999!, LOOPOFF$)       'Disable power supply

    CALL PAUSE(1!)

END FUNCTION

FUNCTION SENSORIN! (MEASIN!, PTCV!)
      
    'Calculates simulated sensor input based on the measured ATE transmitter input
    'Inputs;    MEASIN! = process variable input to sensor, i.e. temperature, voltage, current
    '           PTCV! = measured value of parasitic TC voltage

    SENSOR$ = SPECS.SENTYPE
    SNM% = SENSORNUM%
                
                'Voltage, Current or Potentiometer
    IF SNM% = 1 OR SNM% = 2 OR SNM% = 7 THEN
    SENSORIN! = MEASIN!
    ELSEIF SNM% = 3 OR SNM% = 4 THEN                'TC in
    TCTYPE$ = LEFT$(SENSOR$, 1)
    TCT! = TCTEMP!(MEASIN! + PTCV!, TCTYPE$)
    SENSORIN! = TCT!
    ELSEIF SNM% = 5 OR SNM% = 6 THEN                'RTD in
    RTDTYPE$ = LEFT$(SENSOR$, 2)
    RTDI! = RTDTEMP!(MEASIN!, RTDTYPE$)         'Calculate actual simulated temp.
    SENSORIN! = RTDI!
    ELSE
    UNKNOWN% = 1
    END IF

    IF TCT! = 99! OR RTDI! = 99! OR UNKNOWN% = 1 THEN
    SOUND 1000, .5
    PRINT
    PRINT TAB(10); "Sensor type unknown.  Check database."
    SENSORIN! = 99!                             'Value indicates error
    CALL CONTINUE
    ELSEIF TCT! = 98! OR RTDI! = 98! THEN
    SOUND 1000, .5
    PRINT
    PRINT TAB(10); "Sensor polynomial limits have been exceeded."
    SENSORIN! = 99!                             'Value indicates error
    CALL CONTINUE
    END IF

END FUNCTION

FUNCTION SENSORNUM%

    'Assign a number to each sensor type for ease of handling
    'Sensor types;
    '1 = millvolt, volt
    '2 = milliamp
    '3 = thermocouple, except type B
    '4 = type B thermocouple (no cjc)
    '5 = 3-wire RTD
    '6 = 4-wire RTD
    '7 = potentiometer

    SENSOR$ = SPECS.SENTYPE
    TCTYPE$ = LEFT$(SENSOR$, 1)

    IF UCASE$(LEFT$(SENSOR$, 1)) = "V" THEN
    SENSORNUM% = 1
    ELSEIF UCASE$(LEFT$(SENSOR$, 2)) = "MA" THEN
    SENSORNUM% = 2
    ELSEIF UCASE$(MID$(SENSOR$, 2, 2)) = "TC" THEN
    IF UCASE$(TCTYPE$) = "B" THEN
        SENSORNUM% = 4
    ELSE
        SENSORNUM% = 3
    END IF
    ELSEIF UCASE$(MID$(SENSOR$, 3, 5)) = "RTD3W" THEN
    SENSORNUM% = 5
    ELSEIF UCASE$(MID$(SENSOR$, 3, 5)) = "RTD4W" THEN
    SENSORNUM% = 6
    ELSEIF UCASE$(LEFT$(SENSOR$, 3)) = "POT" THEN
    SENSORNUM% = 7
    END IF

END FUNCTION

FUNCTION SENSOROUT! (PVIN!, PTCV!)
      
    'Calculates transmitter input voltage based on the sensor type and output
    'Inputs;    PVIN! = process variable input to sensor, i.e. temperature, voltage, current
    '           PTCV! = measured value of parasitic TC voltage

    SENSOR$ = SPECS.SENTYPE
    SNM% = SENSORNUM%
               
                'Voltage, Current or Potentiometer in
    IF SNM% = 1 OR SNM% = 2 OR SNM% = 7 THEN
        SENSOROUT! = PVIN!
    ELSEIF SNM% = 3 OR SNM% = 4 THEN                'TC in
        TCTYPE$ = LEFT$(SENSOR$, 1)
        TCV! = TCVOLTS!(PVIN!, TCTYPE$)
        SENSOROUT! = TCV! - PTCV!
    ELSEIF SNM% = 5 OR SNM% = 6 THEN                'RTD in
        RTDTYPE$ = LEFT$(SENSOR$, 2)
        RTDO! = RTDOHMS!(PVIN!, RTDTYPE$)
        SENSOROUT! = RTDO!
    ELSE
        UNKNOWN% = 1
    END IF

    IF TCV! = 99! OR RTDO! = 99! OR UNKNOWN% = 1 THEN
    SOUND 1000, .5
    PRINT
    PRINT TAB(10); "Sensor type unknown.  Check database."
    SENSOROUT! = 99!
    CALL CONTINUE
    ELSEIF TCV! = 98! OR RTDO! = 98! THEN
    SOUND 1000, .5
    PRINT
    PRINT TAB(10); "Sensor polynomial limits have been exceeded."
    SENSOROUT! = 99!                          'Value indicates error
    CALL CONTINUE
    END IF

END FUNCTION

FUNCTION SETAC! (ONOFF%, GENAMPL!)

    SNM% = SENSORNUM%

    IF ONOFF% = 1 THEN
    IF SNM% >= 5 AND SNM% <= 7 THEN         'Check if resistance in
        CALL SETTEST(6)                     'Connect function generator
    ELSEIF SNM% = 2 THEN                    'mA input transmitter
        CB3VAL% = (CB3VAL% OR &H10) AND &HDF'0 0 0 1  0 0 0 0
                        'D.U.T. input = current source
                        '1 1 0 1  1 1 1 1
        CALL SETTH(CB3VAL%, CB3%)           'Input current sourced from +15V
        CB0VAL% = (CB0VAL% AND &HE9) OR &H8 '1 1 1 0  1 0 0 1
        CALL SETTH(CB0VAL%, CB0%)           'ground inputs, short series R
                        'remove short on inputs
    ELSE
        CB0VAL% = (CB0VAL% AND &HFD) OR (&H8)   '1 1 1 1  1 1 0 1
                            '0 0 0 0  1 0 0 0
        CALL SETTH(CB0VAL%, CB0%)               'Select function gen., input
                            'remove input short.
    END IF

    CALL WRITEDVM(VOAC$, GENAMPL!)          'set meter range
       
    IF SNM% = 2 THEN
        CH% = 7                             'Current input
    ELSE
        CH% = 3                             'Attenuator input, voltage
                        'and RTD input
    END IF
    CALL LOADMUX(CH%, CON%)

    DO
        VIN! = READDVM!(.005)
        IF VIN! < GENAMPL! / 2! / SQR(2) * .75 THEN     'Check for adequate amplitude
        LOCATE 20, 15
        PRINT "WARNING!  Increase function generator amplitude."
        END IF
    LOOP WHILE VIN! < GENAMPL! / 2! / SQR(2) * .75

    LOCATE 20, 15
    PRINT SPC(48);
       
    ELSE
    IF SNM% >= 5 AND SNM% <= 7 THEN             'Check if resistance in
        CALL RESETTH                            'Reset the test head
    ELSE
        CB0VAL% = CB0VAL% OR &H2                '0 0 0 0  0 0 1 0
        CALL SETTH(CB0VAL%, CB0%)               'De-select function gen., input
        CALL SETDAC(0!, 1, 0)                   'Clear attenuator, short transmitter inputs
                            'DUT input = R/2R ladder
    END IF
    END IF

    CALL LOADMUX(CH%, COFF%)
    SETAC! = VIN!

END FUNCTION

FUNCTION SETCURRENTIN! (MODIN!)

    'Sets the input current source to the D.U.T.
    'Inputs;    Desired input current in mA.
    'Outputs;   Measured input current in mA.
    '
    'Schematic; Current Input
    '             -------
    '   Vdac-----|       |----- +15V
    '            |       |  --> Iout = Vdac / (IINSEN.MEAS + RCONV)
    '            |       |---
    '            |       |  |
    '             -------   IINSEN.MEAS
    '                       |
    '                       RCONV
    '                       |
    '                       GND
    '
    '
    'Schematic; Two-Wire Transmitter Input
    '             -------
    '   Vdac-----|       |----- +EXC
    '            |       |  --> Iout = Vdac / IINSEN.MEAS
    '            |       |---
    '            |       |  |
    '             -------   IINSEN.MEAS
    '                       |
    '                       |
    '                       GND

  
    IF SENSORNUM% = 2 THEN                  'mA input transmitter
    RCONV! = SPECS.RCONV                'transmitter current conversion resistor
    CB3VAL% = CB3VAL% OR &H10           '0 0 0 1  0 0 0 0
    CALL SETTH(CB3VAL%, CB3%)           'Input current sourced from +15V
    ELSE                                    '2W TX input transmitter w/ loop excitation
    RCONV! = 0                          'transmitter current conversion resistor
                        'Not used to set input current
    CB3VAL% = CB3VAL% AND &HEF          '1 1 1 0  1 1 1 1
    CALL SETTH(CB3VAL%, CB3%)           'Input current sourced from +EXC
    END IF

    VSENSE! = MODIN! / 1000! * IINSEN.MEAS! 'Iin, desired * current source sense R
    VSENATTEN! = (IINSEN.MEAS! + RCONV!) / IINSEN.MEAS!
    CALL SETDAC(VSENSE!, 7, VSENATTEN!)     'Sets DAC
    SETCURRENTIN! = VSENSE! / IINSEN.MEAS! * 1000! 'Measured, Vsense passed back from SETDAC

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\SCTDATA\DBSORT2.DAT" FOR RANDOM AS #2 LEN = LEN(SORTDATA1)
    OPEN "C:\ATE\SCTDATA\SCTMAIN.DAT" FOR RANDOM AS #1 LEN = LEN(SPECS)
    NUMRECORD% = LOF(1) / LEN(SPECS)

   
    IF TH$ = "TE1164" THEN
        'Display VAS modules
        SELFAM% = 1
    ELSE
        'Display DSCT modules
        SELFAM% = MENU3%
        IF SELFAM% = 9 THEN
            ENDFLAG% = 1
            CLOSE #1
            CLOSE #2
            EXIT SUB        'exit selected from MENU3%
        END IF
    END IF

    N% = 0

    FOR I% = 1 TO NUMRECORD%
        GET #1, I%, SPECS
        SORTDATA1.MODNAME = SPECS.MODNAME
        SORTDATA1.RECNUM = I%
       
        SELECT CASE SELFAM%    'Pick models in selected family

            CASE 1
                'SPECS.MODNAME = "SCMVAS-MXXX
                IF LEFT$(SPECS.MODNAME, 7) = "SCMHVAS" THEN
                    PUT #2, , SORTDATA1        'write record # and model number
                    N% = N% + 1                'found a record
                END IF
            CASE 2
                'SPECS.MODNAME = "DSCT30-xxxx "
                IF LEFT$(SPECS.MODNAME, 6) = "DSCT30" THEN
                    PUT #2, , SORTDATA1        'write record # and model number
                    N% = N% + 1                'found a record
                END IF
            CASE 3
                'SPECS.MODNAME = "DSCT31-xxxx "
                IF LEFT$(SPECS.MODNAME, 6) = "DSCT31" THEN
                    PUT #2, , SORTDATA1        'write record # and model number
                    N% = N% + 1                'found a record
                END IF
            CASE 4
                'SPECS.MODNAME = "DSCT32-xxxx "
                IF LEFT$(SPECS.MODNAME, 6) = "DSCT32" THEN
                    PUT #2, , SORTDATA1        'write record # and model number
                    N% = N% + 1                'found a record
                END IF
            CASE 5
                'SPECS.MODNAME = "DSCT34-xxxx "
                IF LEFT$(SPECS.MODNAME, 6) = "DSCT34" THEN
                    PUT #2, , SORTDATA1        'write record # and model number
                    N% = N% + 1                'found a record
                END IF
            CASE 6
                'SPECS.MODNAME = "DSCT36-xxxx "
                IF LEFT$(SPECS.MODNAME, 6) = "DSCT36" THEN
                    PUT #2, , SORTDATA1        'write record # and model number
                    N% = N% + 1                'found a record
                END IF
            CASE 7
                'SPECS.MODNAME = "DSCT37x-xxxx"
                IF LEFT$(SPECS.MODNAME, 6) = "DSCT37" THEN
                    PUT #2, , SORTDATA1        'write record # and model number
                    N% = N% + 1                'found a record
                END IF
            CASE 8
                'SPECS.MODNAME = "DSCT47x-xxxx"
                IF LEFT$(SPECS.MODNAME, 6) = "DSCT47" THEN
                    PUT #2, , SORTDATA1        'write record # and model number
                    N% = N% + 1                'found a record
                END IF
        END SELECT
    NEXT

    SORTDATA1.MODNAME = "999999999-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

END SUB

FUNCTION STEPRESP$

    STEPMAXIN! = SENSOROUT!(SPECS.MAXIN, 0)         'Use for checking if test is run
    MININ! = SPECS.OSCALIN
    MINOUT! = SPECS.MINOUT / 1000!                  'Convert to A
    MAXOUT! = SPECS.MAXOUT / 1000!
    LOWLIM! = SPECS.STEPRMIN                        '%
    HIGHLIM! = SPECS.STEPRMAX

    CLS
    TESTTITLE$ = "Step Response Test"
    CALL HEADERB(TESTTITLE$)
    LOCATE 10, 10
                               
    SNM% = SENSORNUM%
     
                            'Output sample is at 0.2s
    IF LOWLIM! > 97 OR STEPMAXIN! > 25! OR SNM% = 2 THEN
                            'Current source not set up for SETTHFAST
                            'Check for b.w. > approx 10Hz
                            'or high voltage input
                            'Voltages < 25V will use
                            'MAINMAX! and have less than
                            'full output span transition
    PRINT "This test is not performed on model "; SPECS.MODNAME
    EXIT FUNCTION
    ELSE
    PRINT "Testing, please wait..."
    END IF

    IF SNM% = 3 THEN
    PTCV! = PARASITICTCV!(VCJC!)
    IF VCJC! = 99! THEN EXIT FUNCTION
    END IF
    STEPMININ! = SENSOROUT!(MININ!, PTCV!)          'Calculate transmitter input
    STEPMAXIN! = SENSOROUT!(SPECS.MAXIN, PTCV!)     'Re-calculate w/ known PTCV!

    IF SNM% >= 5 AND SNM% <= 7 THEN                 'Check if resistance in
    CALL OHMSET(STEPMININ!)
    ELSE
    THATTEN! = SETATTEN%(STEPMAXIN!)            'Set test head attenuator
                            'remove short on inputs
                            'This setting will be used
                            'for minin and maxin for speed.
    CB0VAL% = (CB0VAL% AND &HEB) OR &H8         '1 1 1 0  1 0 1 1
    CALL SETTH(CB0VAL%, CB0%)                   'ground inputs, short series R
                            'remove short on inputs
    CALL SETDACFAST(STEPMININ! * THATTEN!)      'Set -f.s. input
    END IF
      
    CALL LOADMUX(2, CON%)                           'Measure Vsense
    CALL WRITEDVM(VODC$, Iout!(MINOUT!) * RSENSE!)
    'CALL CONTINUE
    IOUTLO! = READDVM(.0001) / RSENSE!              'Read -f.s. output (A)
    CALL LOADMUX(2, COFF%)

    IF SNM% >= 5 AND SNM% <= 7 THEN                 'Check if resistance in
    'TIME1! = TIMER
    CB0VAL% = CB0VAL% AND &HBF                  '1 0 1 1  1 1 1 1
    CALL SETTHFAST(CB0VAL%, CB0%)               'Set step relay, K18
                            'Start one-shot timer
    'PRINT TIMER - TIME1!
                '** elapsed time = 0 using SETTHFAST in OHMSET
    CALL OHMSET(STEPMAXIN!)
    'PRINT TIMER - TIME1!
                '** elapsed time = 0 using SETTHFAST in OHMSET
    'Measured delay between one-shot pulse start and input voltage step
    'is 20ms, therefore, set timer pulse to 220ms.
       
    CALL PAUSE(.2)                              'Wait for 165ms pulse
    CB0VAL% = CB0VAL% OR &H40                   '0 1 0 0  0 0 0 0
    CALL SETTH(CB0VAL%, CB0%)                   'reset test
    ELSE
    'TIME1! = TIMER
    CB0VAL% = CB0VAL% AND &H7F                  '0 1 1 1  1 1 1 1
    CALL SETTHFAST(CB0VAL%, CB0%)               'Set step relay, k7
                            'Start one-shot timer
    'PRINT TIMER - TIME1!
                '** elapsed time = 0 using SETTHFAST
                '** elapsed time = 50ms using SETTH, regardless
                '   of pause time in SETTH.  Pause is required.
    
    CALL SETDACFAST(STEPMAXIN! * THATTEN!)      'Set +f.s input
    'PRINT TIMER - TIME1!
                '** elapsed time = 0 using SETDACFAST
                '** elapsed time = 50ms using SETDAC
    'Measured delay between one-shot pulse start and input voltage step
    'is 1ms.
     
    CALL PAUSE(.2)                              'Wait for 165ms pulse
    CB0VAL% = CB0VAL% OR &H80                   '1 0 0 0  0 0 0 0
    CALL SETTH(CB0VAL%, CB0%)                   'reset test
    END IF

    IOUTFINAL! = READDVM(.0001) / RSENSE!           'Read final +f.s. output (A)
    CALL LOADMUX(2, COFF%)
    CALL LOADMUX(5, CON%)                           'S/H Output
    CALL WRITEDVM(VODC$, MAXOUT! * RSENSE!)
    IOUTHI! = READDVM(.001) / RSENSE!               'Read sampled output (A)
    CALL LOADMUX(5, COFF%)

    CALL PAUSE(.5)                                  'Allow output to settle
                            'to final value
    CALL LOADMUX(2, CON%)                           'Measure Vsense
    IOUTFINAL! = READDVM(.001) / RSENSE!            'Read final +f.s. output (A)
    CALL LOADMUX(2, COFF%)
    IOUTHIPERC! = (IOUTHI! - IOUTLO!) / (IOUTFINAL! - IOUTLO!) * 100!
    
    IF IOUTHIPERC! >= LOWLIM! AND IOUTHIPERC! <= HIGHLIM! THEN
    ST$ = "PASS"
    ELSE
    ST$ = "FAIL"
    SOUND 1000, .5
    END IF

    LOCATE 10, 10
    PRINT "Status: "; ST$;
    PRINT SPC(20);
    PRINT TAB(10); "Output after 165ms is";
    PRINT TAB(61); USING "+###.# %"; IOUTHIPERC!
    PRINT TAB(10); "Required output after 165ms is";
    PRINT TAB(50); USING "+##.# % to +###.# %"; LOWLIM!; HIGHLIM!

    STEPRESP$ = ST$ + STR$(IOUTHIPERC!) + "1"

    CALL RESETTH                                    'Reset test head
    CALL PAUSE(1!)

END FUNCTION

SUB TSPECS (TSPEC$(), LOWMA!, HIGHMA!, TOTLRESPEC!)

    ORANGE! = SPECS.MAXOUT - SPECS.MINOUT

    TSPEC$(1) = " < " + STR$(IUR2! * 1000!)         'Under-range spec
    TSPEC$(2) = " < " + STR$(ICL! * 1000!)          'Over-range spec
    TSPEC$(3) = " < " + STR$(1) 'SPECS.ACCURACY)        'Min. loop V spec
    TSPEC$(4) = " < " + STR$(1) 'SPECS.ACCURACY)        'Max. loop V spec
    IF LEFT$(SPECS.MODNAME, 4) = "DSCT" THEN
        CURRTOLM! = .05 * SPECS.IEXCMFS  '5% tolerance
        CURRTOLP! = .05 * SPECS.IEXCPFS  '5% tolerance
    ELSE
        CURRTOLM! = .02 * SPECS.IEXCMFS '2% tolterance
        CURRTOLP! = .02 * SPECS.IEXCPFS '2% tolerance
    END IF
    TSPEC$(5) = STR$(CINT(SPECS.IEXCMFS)) + "+/-" + STR$(CINT(CURRTOLM!)) 'Excitation current #1
    TSPEC$(6) = STR$(CINT(SPECS.IEXCPFS)) + "+/-" + STR$(CINT(CURRTOLP!)) 'Excitation current #2
    TSPEC$(7) = "+/-" + STR$(SPECS.IMATCHTOL!)      'Current source matching
    TSPEC$(8) = "+/-" + STR$(SPECS.LINEAR)          'Linearity/conformity spec
    TSPEC$(9) = "+/-" + STR$(SPECS.ACCURACY)        'Accuracy spec
    TSPEC$(10) = "+/-" + LEFT$(STR$(TOTLRESPEC!), 4) 'Lead resistance effects
    TSPEC$(11) = "+/-" + STR$(SPECS.VSEN!)          'Loop voltage sensitivity
    TSPEC$(12) = " >=" + STR$(SPECS.INPUTRES!)      'Input R, bias I effects
       
    IF SPECS.IOPENTC > SPECS.MAXOUT THEN
    COND$ = " > "
    ELSE
    COND$ = " < "
    END IF
    TSPEC$(13) = COND$ + STR$(SPECS.IOPENTC)        'Open tc detect
    TSPEC$(14) = RIGHT$(STR$(SPECS.ATTEN), 2) + "+/-" + RIGHT$(STR$(SPECS.ATTENTOL), 2)
                            'Frequency response
    TSPEC$(15) = LEFT$(STR$(SPECS.STEPRMIN), 3) + " to" + LEFT$(STR$(SPECS.STEPRMAX), 4)
                            'Step response
    TSPEC$(16) = " < " + STR$(SPECS.OUTNOISE)       'Output noise

END SUB

FUNCTION UNDERRANGE$

    'Test the under-range limit of the transmitter
    MININ! = SENSOROUT!(SPECS.MININ, 0)
    MAXIN! = SENSOROUT!(SPECS.MAXIN, 0)
    MAXOUT! = SPECS.MAXOUT / 1000!          'Convert to A

    INRANGE! = MAXIN! - MININ!
      
    CLS
    TESTTITLE$ = "Under-Range Test"
    CALL HEADERB(TESTTITLE$)
    LOCATE 10, 10
      
    SNM% = SENSORNUM%
    IF SNM% = 2 OR SNM% = 7 THEN
    PRINT "This test is not performed on this model."
    CALL CONTINUE                           'Pot in & current in can't be under-ranged
    EXIT FUNCTION
    ELSEIF SNM% = 5 OR SNM% = 6 THEN    'Check if RTD in
    UNDEROHM! = 8     'Set Rin for the minimum possible (8ohms)
    CALL OHMSET(UNDEROHM!)
    PRINT "Testing, please wait."
    ELSE
    IF MININ! - .25 * (INRANGE!) < -9.75 THEN 'Test voltage is beyond DAC capability
        PRINT "This test is not performed on model "; SPECS.MODNAME
        UNDERRANGE$ = "PASS"
        EXIT FUNCTION
    ELSE
        UNDERVOLT! = MININ! - .5 * (INRANGE!)  'Set Vin for 50% underrange
        CALL SETDAC(UNDERVOLT!, 1, 0)
        PRINT "Testing, please wait."
    END IF
    END IF
      
    CALL LOADMUX(2, CON%)                           'Measure Vsense
    CALL WRITEDVM(VODC$, MAXOUT! * RSENSE!)         'Sets up Meter
    UNDERI! = READDVM(.001) / RSENSE!               'Loop current in A
    CALL LOADMUX(2, COFF%)                          'Clear mux lines

    IF UNDERI! > IUR1! AND UNDERI! < IUR2! THEN
    UISTAT$ = "PASS"
    ELSE
    UISTAT$ = "FAIL"
    SOUND 1000, .5
    END IF

    LOCATE 10, 10
    PRINT "Status: "; UISTAT$;
    PRINT SPC(20);
    PRINT TAB(10); "Measured under-range current is";
    PRINT TAB(50); USING "##.## mA"; UNDERI! * 1000
    PRINT TAB(10); "Required under-range current is";
    PRINT TAB(50); USING "##.## mA to ##.## mA"; IUR1! * 1000; IUR2! * 1000
    
    UNDERRANGE$ = UISTAT$ + STR$(UNDERI! * 1000!) + "1"   '1 decimal place in display
      
    CALL RESETTH                                    'Reset test head
    CALL PAUSE(1!)

END FUNCTION

