Next: unlock.bas Up: Code Listing Previous: rti-815.bas

tek222.bas


'
'  Author:  Terence Kelly
'  Date:    5 September 1995
'
'  This module contains functions for talking to the Tektronix 222
'  oscilloscope through a serial port.
'
'  On 8/22/95 Prof. Littman and I spent a great deal of time
'  configuring the serial port on the 486 used with the WEBRTI
'  project in order to enable it to speak to the Tektronix 222.
'  Here are the settings for COM1 and COM2 that we finally
'  settled on (we use COM1 for Tektronix communications):
'
'                                   COM1            COM2
'
'           Memory address:         03F8            02F8
'           Baud rate:              2400            2400
'           Parity:                 N               N
'           Data bits:              8               8
'           Stop bits:              1               1
'           IRQ:                    4               3
'
'----------------------------------------------------------------------------

Global Const Tek_COMPortNumber% = 1
Global Const Tek_COMPortSettings$ = "2400,N,8,1"

'  Keeps track of how many waveforms we've captured; used in
'  naming output files.
Global WaveformCount As Integer

Function Tek_AcqMode (ByVal N%) As String
    '
    '  Given a number in the range 0-3, return the corresponding
    '  acquisition mode string from table 5, page 13 of "222 RS-232
    '  Interface Guide."
    '

    R$ = ""

    If N% < 0 Or N% > 3 Then
        R$ = "Error in routine Tek_AcqMode: "
        Tek_AcqMode = R$ & Str$(N%) & " not valid parameter"
        Exit Function
    End If

    Select Case N%
    Case 0
        R$ = "NORM"
    Case 1
        R$ = "ENV"
    Case 2
        R$ = "AVG"
    Case 3
        R$ = "CENV"
    Case Else
        R$ = "Error in routine Tek_AcqMode: unclassified parameter"
    End Select

    Tek_AcqMode = R$

End Function

Function Tek_CPLG (ByVal N%) As String
    '
    '  Given a number in the range 0-3, return the corresponding
    '  CPLG string from tables 1 and 2, pp. 10-11 of "222 RS-232
    '  Interface Guide."
    '

    R$ = ""

    If N% < 0 Or N% > 3 Then
        R$ = "Error in routine Tek_CPLG: "
        Tek_CPLG = R$ & Str$(N%) & " is an invalid parameter"
        Exit Function
    End If

    Select Case N%
    Case 0
        R$ = "DC"
    Case 1
        R$ = "AC"
    Case 2
        R$ = "GND"
    Case 3
        R$ = "OFF"
    Case Else
        R$ = "Error in routine Tek_CPLG: unclassified parameter"
    End Select

    Tek_CPLG = R$

End Function

Function Tek_ErrorMsg (ByVal in$) As String
    '
    '  Given a string, search it for a Tektronix error message.  If
    '  an Error message is found in the input string, return the
    '  "long version" of the error message.  See p. 14 of the "222
    '  RS-232 Interfacing Guide" for details.  This function only
    '  handles status codes, not diagnostic error codes.  I've never
    '  had the scope give me a diagnostic error code, but it has
    '  often spit back status codes complaining about commands I've
    '  sent it.
    '

    R$ = ""
    S$ = Trim$(CondenseWhitespace(in$))
    I% = InStr(S$, "STA")
    If I% > 0 Then
        C$ = Mid$(S$, I%)
        Select Case Mid$(Split(C$, 2, " "), 1, 4)
        Case "0001"
            R$ = "Unrecognized command"
        Case "0002"
            R$ = "Unrecognized character"
        Case "0003"
            R$ = "Command is query only"
        Case "0004"
            R$ = "Command has no query"
        Case "0005"
            R$ = "Bad command argument"
        Case "0006"
            R$ = "Bad data"
        Case "0007"
            R$ = "Data is required"
        Case "0008"
            R$ = "Argument is required"
        Case "0009"
            R$ = "Communication task busy"
        Case "000A"
            R$ = "CURV command had bad checksum"
        Case "000B"
            R$ = "Bad task name for message"
        Case "FFFF"
            R$ = "User pressed escape"
        Case Else
            R$ = "WEBRTI function Tek_ErrorMsg does not recognize"
            R$ = R$ & " this status code"
        End Select
    End If

    If InStr(UCase$(S$), "ERR") Then
        If R$ <> "" Then R$ = R$ & ".  "
        R$ = R$ & "Diagnostic error code: see 222 RS-232 user "
        R$ = R$ & "interface guide"
    End If

    Tek_ErrorMsg = R$

End Function

Function Tek_FP (ByVal logfp$) As String
    '
    '  Get the front panel settings of the Tektronix scope and return
    '  them along with a human-readable decoding.
    '

    FP$ = Tek_send("3", "FP? " & logfp$)
    R$ = Trim$(Tek_InsertErrorMsgs(CondenseWhitespace(FP$)))

    If InStr(R$, "STA") Or InStr(R$, "ERR") Then
        Tek_FP = R$
    Else
        R$ = R$ & CRLF()
        Tek_FP = R$ & Tek_FPDecode(Mid$(FP$, InStr(FP$, ":") + 1, 10))
    End If

End Function

Function Tek_FPDecode (ByVal FP$) As String
    '
    '  Given a ten-character string representing the Tektronix 222
    '  response to the FP? command, decode this string into human-
    '  readable form according to tables 1 through 5, pp. 10 - 13
    '  of the "222 RS-232 Interface Guide."
    '

    If Len(FP$) <> 10 Then
        R$ = "Error in routine Tek_FPDecode: Len(parameter) != 10"
        Tek_FPDecode = R$
        Exit Function
    End If

    C$ = CRLF()
    R$ = ""

    ' channel 1
    Ch$ = Mid$(FP$, 1, 1)
    R$ = R$ & " CH1INV="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 0, 1), "On/Off")) & C$
    R$ = R$ & " CH1VAR="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 1, 1), "On/Off")) & C$
    R$ = R$ & "CH1CPLG=" & Tek_CPLG(HexExtract(Ch$, 2, 2)) & C$
    R$ = R$ & " CH1V/D=" & Tek_VoltsDiv(Mid$(FP$, 2, 1)) & C$
    
    ' channel 2
    Ch$ = Mid$(FP$, 3, 1)
    R$ = R$ & " CH2INV="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 0, 1), "On/Off")) & C$
    R$ = R$ & " CH2VAR="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 1, 1), "On/Off")) & C$
    R$ = R$ & "CH2CPLG=" & Tek_CPLG(HexExtract(Ch$, 2, 2)) & C$
    R$ = R$ & " CH2V/D=" & Tek_VoltsDiv(Mid$(FP$, 4, 1)) & C$

    ' Table 3: Sec/Div and Misc. settings
    Ch$ = Mid$(FP$, 5, 2)
    R$ = R$ & " RO-OFF="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 0, 1), "On/Off")) & C$
    R$ = R$ & "     XY="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 1, 1), "On/Off")) & C$
    R$ = R$ & " X10MAG="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 2, 1), "On/Off")) & C$
    R$ = R$ & "SEC/DIV=" & Tek_SecDiv(HexExtract(Ch$, 3, 5)) & C$

    ' Table 4:  Trigger Position, Slope, Source and Mode Settings
    Ch$ = Mid$(FP$, 7, 2)
    R$ = R$ & "TRIGPOS=" & Tek_TrigPos(HexExtract(Ch$, 0, 2)) & C$
    R$ = R$ & "  SLOPE=" & Tek_TrigSlope(HexExtract(Ch$, 2, 1)) & C$
    R$ = R$ & "TRIGSRC=" & Tek_TrigSource(HexExtract(Ch$, 3, 2)) & C$
    R$ = R$ & "TRIGMOD=" & Tek_TrigMode(HexExtract(Ch$, 5, 3)) & C$

    ' Table 5:  Acquisition Mode and Misc. Settings
    Ch$ = Mid$(FP$, 9, 2)
    ' Decoding of Timeout is perverse; see table 5
    R$ = R$ & "    TIMEOUT="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 0, 1) - 1, "Yes/No")) & C$
    R$ = R$ & "    CHANSEL="
    R$ = R$ & IIf(HexExtract(Ch$, 1, 1), "CH1", "CH2") & C$
    R$ = R$ & "RECALLEDWFM="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 2, 1), "Yes/No")) & C$
    R$ = R$ & " VALIDSTORE="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 3, 1), "Yes/No")) & C$
    R$ = R$ & "    ACQMODE=" & Tek_AcqMode(HexExtract(Ch$, 4, 2)) & C$
    R$ = R$ & "  STOREMODE="
    R$ = R$ & IIf(HexExtract(Ch$, 6, 1), "STORE", "NONSTORE") & C$
    R$ = R$ & "   AUTOTRIG="
    R$ = R$ & UCase$(Format$(HexExtract(Ch$, 7, 1), "Yes/No")) & C$
    
    Tek_FPDecode = R$

End Function

Function Tek_get () As String
    '
    '  Get waveforms CH1 and CH2, store them in files.  Use global
    '  integer to keep track of how many non-null waveform files
    '  we've succeeded in grabbing from the scope.  Return a string
    '  containing information on the number of bytes
    '
    '  We assume that the scope is in SSEQ trigger mode and that
    '
    '  See the Tektronix manual entitled "222 RS-232 Interface Guide"
    '  for details on the button numbering scheme, trigger modes, etc.
    '

    Const Delay$ = "7"     ' CURV? commands take a while.

    R$ = ""

    ' record the time that this routine is invoked
    CapTime$ = Format$(Now, "hh:mm:ss m/d/yy")
    ' grab the waveforms
    CH1$ = Tek_send(Delay$, "curv? ch1")
    CH2$ = Tek_send(Delay$, "curv? ch2")
    ' store nonzero length waveforms to disk
    If CH1$ <> "" Then
        WaveformCount = WaveformCount + 1
        Filename$ = RTIDir$ & "TEK_" & Format$(WaveformCount, "0000")
        Filename$ = Filename$ & ".WFM"
        Call ClobberFile(Filename$, CH1$)
    End If
    If CH2$ <> "" Then
        WaveformCount = WaveformCount + 1
        Filename$ = RTIDir$ & "TEK_" & Format$(WaveformCount, "0000")
        Filename$ = Filename$ & ".WFM"
        Call ClobberFile(Filename$, CH2$)
    End If
    R$ = " Bytes received: CH1=" & Trim$(Str$(Len(CH1$)))
    R$ = R$ & ", CH2=" & Trim$(Str$(Len(CH2$))) & " at " & CapTime$

    Tek_get = R$

End Function

Function Tek_initialize () As String
    '
    '  Initialize the MSCOMM control used to communicate with the
    '  222 oscilloscope. Return any error messages that occur during
    '  this process.
    '

    On Error GoTo Tek_Initialize_Error

    strErrors$ = ""
    Tek_initialize = ""
    frmWEBRTIcontrols.Hide   ' form containing MSCOMM control
    frmWEBRTIcontrols.Comm1.CommPort = Tek_COMPortNumber%
    frmWEBRTIcontrols.Comm1.settings = Tek_COMPortSettings$
    frmWEBRTIcontrols.Comm1.InputLen = 0
    frmWEBRTIcontrols.Comm1.InBufferSize = 4096
    frmWEBRTIcontrols.Comm1.PortOpen = True
    frmWEBRTIcontrols.Comm1.OutBufferCount = 0
    frmWEBRTIcontrols.Comm1.InBufferCount = 0
    frmWEBRTIcontrols.Comm1.Output = Chr$(13)
    Delay (1)
    strReply$ = Trim$(CondenseWhitespace(frmWEBRTIcontrols.Comm1.Input))
    frmWEBRTIcontrols.Comm1.PortOpen = False
    Tek_initialize = Tek_InsertErrorMsgs(strReply$) & strErrors$

Exit Function

Tek_Initialize_Error:
    If strErrors$ <> "" Then strErrors$ = strErrors$ & CRLF()
    T$ = strErrors$ & "Error " & Str$(Err)
    strErrors$ = T$ & " (VB) in function Tek_initialize: " & Error(Err)
    Resume Next

End Function

Function Tek_InsertErrorMsgs (ByVal in$) As String
    '
    '  Given a reply string from the Tektronix scope, insert a
    '  parenthesized error message within every semicolon-delimited
    '  individual reply containing a STA or ERR notice.
    '
    '  We assume that the last semicolon-delimited field of the
    '  string returned by the Tektronix scope is empty.
    '
    R$ = ""

    For I% = 1 To NumOccur(in$, ";")
        Msg$ = Split(in$, I%, ";")
        E$ = Tek_ErrorMsg(Msg$)
        If E$ <> "" Then
            R$ = R$ & Msg$ & " (" & E$ & "); "
        Else
            R$ = R$ & Msg$ & "; "
        End If
    Next

    Tek_InsertErrorMsgs = R$

End Function

Function Tek_SecDiv (ByVal N%) As String
    '
    '  Given an integer in the range 0 - 26 return a string
    '  containing the corresponding Seconds/Division setting listed
    '  in Table 3, p. 12 of the Tektronix "222 RS-232 Interface
    '  Guide " or an error message."
    '
    If N% < 0 Or N% > 26 Then
        R$ = "Error in routine Tek_SecDiv: " & Str$(N%)
        Tek_SecDiv = R$ & " not a valid parameter (out of range)"
        Exit Function
    End If

    Select Case N%
    Case 0
        R$ = "50 nS"
    Case 1
        R$ = "0.1 uS"
    Case 2
        R$ = "0.2 uS"
    Case 3
        R$ = "0.5 uS"
    Case 4
        R$ = "1 uS"
    Case 5
        R$ = "2 uS"
    Case 6
        R$ = "5 uS"
    Case 7
        R$ = "10 uS"
    Case 8
        R$ = "20 uS"
    Case 9
        R$ = "50 uS"
    Case 10
        R$ = "0.1 mS"
    Case 11
        R$ = "0.2 mS"
    Case 12
        R$ = "0.5 mS"
    Case 13
        R$ = "1 mS"
    Case 14
        R$ = "2 mS"
    Case 15
        R$ = "5 mS"
    Case 16
        R$ = "10 mS"
    Case 17
        R$ = "20 mS"
    Case 18
        R$ = "50 mS"
    Case 19
        R$ = "0.1 S"
    Case 20
        R$ = "0.2 S"
    Case 21
        R$ = "0.5 S"
    Case 22
        R$ = "1 S"
    Case 23
        R$ = "2 S"
    Case 24
        R$ = "5 S"
    Case 25
        R$ = "10 S"
    Case 26
        R$ = "20 S"
    Case Else
        R$ = "Error in routine Tek_SecDiv: unclassified parameter"
    End Select

    Tek_SecDiv = R$

End Function

Function Tek_send (ByVal Delay$, ByVal S$) As String
    '
    '  Send the given string to the Tektronix scope and return
    '  whatever the scope replies.  Wait Delay$ seconds before
    '  reading the scope's reply.  It is the user/programmer's
    '  responsibility to choose Delay$ wisely.
    '

    On Error GoTo Tek_send_Error

    D% = IIf(Val(Delay$) > 0, Val(Delay$), 1)
    frmWEBRTIcontrols.Comm1.PortOpen = True
    frmWEBRTIcontrols.Comm1.OutBufferCount = 0
    frmWEBRTIcontrols.Comm1.InBufferCount = 0
    frmWEBRTIcontrols.Comm1.Output = S$ & Chr$(13)
    Delay (D%)
    strReply$ = frmWEBRTIcontrols.Comm1.Input
    frmWEBRTIcontrols.Comm1.PortOpen = False

    Tek_send = strReply$

Exit Function

Tek_send_Error:
    R$ = "Error " & Str$(Err) & " (VB) in function Tek_send: "
    Tek_send = R$ & Error$(Err)
    Exit Function

End Function

Function Tek_TrigMode (ByVal N%) As String
    '
    '  Given a number in the range 0-3, return the corresponding
    '  trigger mode string from table 4, page 13 of "222 RS-232
    '  Interface Guide."
    '

    If N% < 0 Or N% > 3 Then
        R$ = "Error in routine Tek_TrigMode: " & Str$(N%)
        Tek_TrigMode = R$ & " not valid parameter (out of range)"
        Exit Function
    End If

    Select Case N%
    Case 0
        R$ = "NORM"
    Case 1
        R$ = "AUTOLVL"
    Case 2
        R$ = "AUTOBL"
    Case 3
        R$ = "SSEQ"
    Case Else
        R$ = "Error in routine Tek_TrigMode: unclassified parameter"
    End Select

    Tek_TrigMode = R$

End Function

Function Tek_TrigPos (ByVal N%) As String
    '
    '  Given an integer in the range 0-2, return the corresponding
    '  trigger position string from table 4, p. 13 of "222 RS-232
    '  Interface Guide."
    '
    If N% < 0 Or N% > 2 Then
        R$ = "Error in routine Tek_TrigPos: " & Str$(N%)
        Tek_TrigPos = R$ & " not valid parameter (out of range)"
        Exit Function
    End If

    Select Case N%
    Case 0
        R$ = "POST"
    Case 1
        R$ = "MID"
    Case 2
        R$ = "PRE"
    Case Else
        R$ = "Error in routine Tek_TrigPos: unclassified parameter"
    End Select

    Tek_TrigPos = R$

End Function

Function Tek_TrigSlope (ByVal N%) As String
    '
    '  Given a number in the range 0-1, return the corresponding
    '  trigger slope string from table 4, page 13 of "222 RS-232
    '  Interface Guide."
    '
    '  This function could really be replaced with an IIf statement.
    '

    If N% < 0 Or N% > 1 Then
        R$ = "Error in routine Tek_TrigSlope: " & Str$(N%)
        Tek_TrigSlope = R$ & " not valid parameter"
        Exit Function
    End If

    Select Case N%
    Case 0
        R$ = "NEG"
    Case 1
        R$ = "POS"
    Case Else
        R$ = "Error in routine Tek_TrigSlope: unclassified parameter"
    End Select

    Tek_TrigSlope = R$

End Function

Function Tek_TrigSource (ByVal N%) As String
    '
    '  Given a number in the range 0-3, return the corresponding
    '  trigger source string from table 4, page 13 of "222 RS-232
    '  Interface Guide."
    '

    If N% < 0 Or N% > 3 Then
        R$ = "Error in routine Tek_TrigSource: " & Str$(N%)
        Tek_TrigSource = R$ & " not valid parameter"
        Exit Function
    End If

    Select Case N%
    Case 0
        R$ = "VERT"
    Case 1
        R$ = "CH1"
    Case 2
        R$ = "CH2"
    Case 3
        R$ = "EXT"
    Case Else
        R$ = "Error in routine Tek_TrigSource: unclassified parameter"
    End Select

    Tek_TrigSource = R$

End Function

Function Tek_VoltsDiv (ByVal Ch$) As String
    '
    '  Given a hex character in the range 0 - C, return the
    '  corresponding volts/division setting from tables 1 and 2,
    '  pp. 10-11 of the "222 RS-232 Interface Guide"
    '

    N% = Val("&H" & Ch$)
    If Len(Ch$) <> 1 Or N% > 12 Or N% < 0 Then
        R$ = "Error in routine Tek_VoltsDiv: " & Ch$
        Tek_VoltsDiv = R$ & " is not a valid parameter (out of range)"
        Exit Function
    End If

    Select Case N%
    Case 0
        R$ = "5 mV"
    Case 1
        R$ = "10 mV"
    Case 2
        R$ = "20 mV"
    Case 3
        R$ = "50 mV"
    Case 4
        R$ = "0.1 V"
    Case 5
        R$ = "0.2 V"
    Case 6
        R$ = "0.5 V"
    Case 7
        R$ = "1 V"
    Case 8
        R$ = "2 V"
    Case 9
        R$ = "5 V"
    Case 10
        R$ = "10 V"
    Case 11
        R$ = "20 V"
    Case 12
        R$ = "50 V"
    Case Else
        R$ = "Error in routine Tek_VoltsDiv: unclassified parameter"
    End Select

    Tek_VoltsDiv = R$

End Function


tpkelly@cs.CS.Princeton.EDU
Thu Sep 14 02:35:48 EDT 1995