v5.0 / 9 of 23 / 01 sep 99 / gvg
* This chapter provides studies of advanced I/O techniques.
* The IEEE 488.2 HPIB spec defines a binary-block (BINBLOCK) transfer format
that follows a simple and intelligent scheme. The header is of the form:
Reading and sending such a stream with VEE is easy because VEE supports this
type directly with the BINBLOCK data type. This section outlines how to use
it by demonstrating how to read and store a "learn string" from a 54600 scope
using VEE direct I/O (DIO) objects.
* The example performs these steps:
The architecture is shown below (source is in the file xlrnstrn.vee).
A few notes:
The first DIO object simply clears and resets the scope, then gets the ID
string. This is a standard block I put in most of my DIO programs and not of
great interest:
* The second DIO object is more interesting. It performs the read of the
arbitrary-block data:
In this case, the learn string doesn't correspond to any particular
numeric type (and in the case of the 54600 it's an odd number as well) so
BYTE data is appropriate.
* The data is stored in a file using the "To File" object as follows:
Note that it is stored in arbitrary-block format in the file and has the
appropriate header information. While this is convenient, you could also
store the data simply as a byte array with the transaction:
The default setting for byte order (in the I/O configuration dialog under the
VEE "I/O > Instrument > Edit Instrument" dialog) is MSB (most-significant
byte first), and all (as far as I know) HP instruments conform to that order.
VEE is smart enough to perform the proper byte-order reversal when necessary,
so most of the time you'll get the proper byte ordering by default. The only
time you'll run into trouble is when you get some odd instrument (I am told
some Tek scopes are like this) that provides LSB byte ordering. In that rare
case you will need to change the setting from the default MSB to LSB.
* So much for getting the arbitrary-block data. Now to retrieve it. A From
File object gets the data from the file:
If you had chosen to store the data as binary data instead of a BINBLOCK, you
would use the following transaction to retrieve it:
The last two transactions simply get the error status from the scope. If all
goes well, it will return a "+0".
* The preceding steps should be enough to allow you to work with
arbitrary-block data with VEE, but there are a few fine points to consider
further.
The keys to these features are found in the "I/O -> Instrument -> Edit
Instrument -> Direct I/O Configuration" dialog:
The "Conformance" field specifies the binary-block transfer standard level:
"IEEE 488" or "IEEE 488.2". If you specify "IEEE 488", you can select from
the available block-transfer methods allowed under the original 488 spec; if
you specify "IEEE 488.2", only the block-transfer methods defined in the
more-specific 488.2 spec are allowed.
Let's assume for the moment that we stay with "IEEE 488" conformance (488.2
conformance has some implications that we need to lay some groundwork for).
Then you can specify the block-transfer protocol using the "Binblock" field
in the configuration dialog:
* The "State (Learn String)" field provides an additional capability for DIO
objects: the ability to read and write an instrument state through learn
strings.
While the example that forms the main body of this article used learn strings
to demonstrate how to perform arbitrary-block transfers, it only used them as
a form of data little different from any other. But the DIO object allows
you to store an instrument state in a cleaner fashion: you can read the
instrument state using the DIO object's "Upload State" menu entry, and you
can restore the instrument to a previous state using the WRITE STATE
transaction. (There is no READ STATE transaction and no way to get the
"Upload State" menu entry to an input pin.)
If you leave this field at "Not Configured", this scheme will not work. If
you switch this to "Configured", you get two more fields to specify the learn
string commands:
* In some cases, reading arbitrary-block data with VEE using a BINBLOCK
transaction won't work, for a rather subtle reason. Certain instruments will
send learn strings with this scheme and will assume that "N" is 8 and pad
with zeroes. For example:
This leads to trouble with VEE because if you read a BINBLOCK under VEE and
store it to a file, any leading zeroes in the BINBLOCK header will be lost --
you can read the learn string in from the device, but you can't write it back
out to the device without getting a device error. The only alternative is to
reconstruct the binblock header "manually".
* The first thing to do is to make sure the learn string is not stored as a
BINBLOCK, just stored as binary data without a header. Since you have to
reconstruct the header anyway, no point in storing it. You could do this
with:
The trick here is the Formula box that creates the BINBLOCK header. It
accepts the array size and outputs a header with leading zeroes of the form:
The Formula box contains:
Creating the string of padding zeroes of the proper length is the central
trick, and it uses the function:
Now there is still the problem of termination conditions for the output
binary block: does it require a line-feed or not? How about an EOI?
However, that concern is left as an exercise for the reader.
* We occasionally get complaints from users concerning the operation of
trace-type devices, such as oscilloscopes. For example, an HP field person
reported a problem with VEE and a scope driver with a program as follows:
If you run the program, it executes up the OK button and stops. No trouble
so far. Then you hit the OK button, and the 54600 reports on its display
that there is a "Setting Conflict", but VEE never gives a timeout error and
VEE won't respond to user inputs.
Actually, what is happening is that the instrument driver has sent the
command to get the waveform and is doing serial polls to see if the command
is complete. All the serial polls work perfectly without timing out, so the
driver stays stuck in that loop forever.
The solution is to either turn off the scope and let the serial poll time out
(not much of a problem to do since the VEE program handles all the scope
settings anyway, and little is lost), or add additional logic to the VEE
program to get more control.
* In general, such a problem will occur in a scope the instrument setup sets
"Sweep Mode" to "Triggered", indicating that you want the instrument to wait
to make a waveform acquisition until a trigger signal of some sort occurs at
its input connectors. If the trigger condition never occurs -- say, because
the scope inputs aren't connected to the signal source -- then the scope
driver is hung up indefinitely.
The illustration below shows a simple VEE program which could potentially see
this problem. Note that the DIGITIZE data input terminal is the stimulus
which causes the scope to try to acquire a waveform.
The normal way to get a measurement from a scope is with a DIGITIZE command.
This tells the scope to acquire a new waveform and copy it into its internal
memory. Sending a new command before DIGITIZE has completed may give you an
error message, and so to perform this operation, you:
These are the steps the scope IDs perform when you ask them to give you a
waveform. Now if the scope never sees a signal that satisfies its trigger
conditions, the DIGITIZE command will not complete, and the ID will just keep
looping mindlessly for a bit that will never be set. Each serial poll works
just fine, however, so you never get a timeout.
* The solution to this problem is to break the sequence of instructions into
separate objects that perform the steps outlined above. This gives you the
opportunity to add a timeout mechanism to keep from hanging up VEE.
The first step in doing this is to configure the scope by setting up an
instrument driver, and then command it to DIGITIZE a waveform:
The second transaction line -- WRITE TEXT "*CLS;*SRE 32;*ESE 1" EOL -- is of
particular interest. The *CLS instruction causes the scope to clear its
status byte, so that we don't mistake any status from an earlier scope
operation for the current one. The *ESE 1 instruction tells the scope to set
bit 0 of its event status register (the "operation complete" bit) when
requested operations complete. The *SRE 32 instruction allows an event from
the event status register to propagate to the status byte register and be
reflected in bit 5 of the scope's status byte.
So, the combination of *ESE 1 and *SRE 32 tells the scope to set the event
status bit in the status byte register when an operation -- a DIGITIZE in
this case -- has completed so we can check for completion with a serial poll.
This configured, the third line sends the DIGITIZE command, followed by the
*OPC command to tell the scope to update the contents of the status byte
register when the conditions set in the event status register become true --
or, in this case, when DIGITIZE has completed, set bit 5 in the status byte.
Having sent the commands to perform the DIGITIZE, the next thing to do is
perform the serial polls (and time out if we don't get the status bit set
within the proper interval). These objects do the serial poll in a loop:
If it isn't set, the If-Then-Else object checks to see if the elapsed time is
greater than five seconds; if it is, the program performs error handling. If
not, the loop is repeated.
The "get scope data" box above is a UserObject that contains the following
pieces:
Note that performing all these tasks in a UserObject allows you to create a
UserFunction that could be called from other parts of the program to perform
the same task. UserObjects also allow you to add an error-output pin, and so
provide a clean error-output mechanism.
* After going through all this, the question is: why is it necessary? If an
error would cause this problem, why not check for an error before trying to
get the waveform?
The answer relates to the "use model" of the scope. In a practical test
setup, the act of requesting that the scope digitize a waveform causes it to
arm its trigger and wait for a trace. If the scope is reading a continuous
waveform, the trigger occurs (effectively) immediately, a trace is digitized,
and the waveform is returned. No problem.
But if you're trying to capture a single-trace event, the scope will arm its
trigger and then wait for the trigger event to occur. In this case, assuming
that the trigger will happen immediately is not valid. The trigger will
occur when the user gets around to pushing a button, or another instrument
generates a trigger, or whatever, something that could take much longer than
the timeout period to occur. It's a "real-time" event, in the sense that it
happens whenever it wants to.
This is why the serial-polling scheme is used in the scope driver. Relying
on the timeout period would cause more trouble than cycling through serial
polls in a continuous loop. Since the scope can in principle hang
indefinitely waiting for the trigger, the design decision was made so that
the driver would, too.
But then the next question arises: if there's actually an error on the
scope, then the polling loop will go forever. So why not check for an error
after sending the digitizing commands?
If there is an error, this would work OK. You'll get back an error code
and be able to terminate the loop. However, if you don't have an error,
you won't get back an error code until the scope has completed the digitizing
operation. Since we're working on the assumption that the trigger is a
real-time (indefinite) event, the digitizing operation can take as long as it
likes, and timing out on the error query would defeat the purpose of
performing serial polls.
In short, the scope ID features a design trade-off for the sake of simplicity
of construction and operation. It could be argued that the driver should
have options to allow the user more choice, but once we start moving up to
that level of enhanced complexity then the user might as well just go to a
lower level of detail (using Direct I/O and the like) and be done with it.
* One of the features introduced in VEE 3.0 was the ability to release the
HPIB ATN line under program control. This leads to the obvious question: so
who cares?
The ability to release ATN under program control is only used in two
circumstances:
Under normal circumstances, all VEE HPIB transactions suppose that VEE is
either the talker or listener and a single remote device is the corresponding
listener or talker. The bus transactions that VEE generates with instrument
drivers or Direct I/O all are designed according to this assumption.
The two circumstances outlined above, however, require that VEE set up a
remote device as a talker and one or more remote devices as listeners. The
standard VEE HPIB transactions won't allow this, but you can (as of VEE 3.0)
use the Interface Operations object to create the proper HPIB transactions.
For example, I have a 54600 scope. I can send it a "PRINT?" query, and when
I then address it to talk, it will dump its display (in HP standard printer
graphics format) to the HPIB, with the assumption that there is a printer out
there listening so it can print the data.
My 54600 has an HPIB address of 13. I have a ThinkJet printer with an
address of 1. I can direct the 54600 to dump its display to the ThinkJet by
using direct I/O to send the "PRINT?" command, and then by using an
interface operations object to perform the following HPIB transactions:
[9.1] ACCESSING ARBITRARY-BLOCK DATA WITH DIRECT-I/O
[9.2] BUILDING A FIXED LENGTH BINBLOCK HEADER
[9.3] SCOPE DRIVERS & TIMEOUTS
[9.4] PERFORMING DEVICE-TO-PRINTER DUMPS
[9.1] ACCESSING ARBITRARY-BLOCK DATA WITH DIRECT-I/O
#NDDDDD<byte><byte> ... <byte><byte>
It begins with a "#" character, followed by a single ASCII digit ("N") from 1
to 9 that specifies a number of ASCII digits to follow. These following
ASCII digits ("DDDDD" in this case, though they could actually be anything
from "D" to "DDDDDDDDD") give the number of actual data bytes to follow. For
example:
#3128<byte1><byte2> ... <byte128>
-- specifies a block of 128 data bytes.
displays ID string
+--------------+ +--------------------------------------+
| DIO | | AlphaNumeric |
+--------------+ +--------------------------------------+
| JEDI (@ 713) +------------->| HEWLETT-PACKARD,54600A,0,2.3 |
+------+-------+ +--------------------------------------+
| clears scope
| & gets ID
|
| gets learn string
| from scope
+------+-------+ +---------+
| DIO +--------->| To File | stores learn string to file
+--------------+ +----+----+
| JEDI (@ 713) +--+ |
+--------------+ | +-----+------+ +--------------+ +-------+
| | From File +----->| DIO | | err |
+----------------+ +------------+ +--------------+ +-------+
| +-------+ reclaims string | JEDI (@ 713) +-->| +0 |
| | err | +--------------+ +-------+
| +-------+ writes learn
+-->| +0 | string to scope
+-------+
* Now let's go through this and examine the important objects in detail.
+-------------------------------------+
| JEDI (@ 713) |
+---------------------------------+---+
| EXECUTE CLEAR | | Clear scope interface.
| WRITE TEXT "*RST;*CLS" EOL | | Reset & clear status.
| WRITE TEXT "*IDN?" | X | Query for ID.
| READ TEXT X STR | | Get back ID string.
| | |
+---------------------------------+---+
Note how the last transaction reads in the ID string as TEXT in string (STR)
format, with a maximum string size of 50 characters (which is more than
needed for the ID string).
+--------------------------------------+
| JEDI (@ 713) |
+----------------------------------+---+
| WRITE TEXT "*LRN?" EOL | X | Query for learn string.
| READ BINBLOCK X BYTE | | Get block (specify LF end byte).
| WRITE TEXT ":SYSTEM:ERROR?" EOL | | Ask for error status.
| READ TEXT Y STR | Y | Get back error status.
+----------------------------------+---+
The transactions are simple:
+-------------------------------------------------+
| To File |
+-----+-------------------------------------------+
| | To File: [ LRNSTR.BIN ] |
| | [X] Clear File At Prerun & Open |
| A +-------------------------------------------+
| | WRITE BINBLOCK A BYTE | Build file.
| | | Build file.
| | |
+-----+-------------------------------------------+
Not much to this. The first transaction deletes the file and the second
simply rebuilds the file and writes the binary data (the learn string) to it.
WRITE BINARY A BYTE
* If you are getting other data types -- 16- or 32-bit integer or 32- or
64-bit float -- you should remember that the byte order on your instrument
may not be the same as byte order on your computer. If you get numbers in
the wrong order, the numeric values will look like gibberish.
+---------------------------------------------+
| From File |
+-----------------------------------------+---+
| From File: [ LRNSTR.BIN ] | |
+-----------------------------------------+ |
| READ BINBLOCK X BYTE | X | Get file.
| | |
| | |
+-----------------------------------------+---+
Not much to this, either. The object reads the data as a BINBLOCK and shoves
it out the "X" pin.
READ BINARY X BYTE ARRAY:*
* The last DIO object is relatively straightforward:
+-------------------------------------------+
| JEDI (@ 713) |
+---+-----------------------------------+---+
| | WRITE TEXT ":SYSTEM:SETUP " | | Send command.
| | WRITE BINBLOCK A BYTE EOL | | Send block.
| A | WRITE TEXT ":SYSTEM:ERROR?" EOL | X | Query for error.
| | READ TEXT X STR | | Get back error string.
| | | |
+---+-----------------------------------+---+
The first transaction sends the ":SYSTEM:SETUP " string to start the learn
string download. Note the " " at the end of the string; if you don't use
that you'll get a bad-parameter error. This is immediately followed (no
intervening EOL) by the block, which is terminated by an EOL.
+----------------------------------------+
| Direct I/O Configuration |
+----------------------------------------+
| Read Terminator [ "\n" ] |
| Write |
| Eol Sequence [ "\n" ] |
| Multi-Field as: [ Data Only ] |
| Array Separator: [ "." ] |
| END (EOI) on EOL: [ NO ] |
| |
| Conformance: [ IEEE 488 ] |
| Binblock: [ None ] |
| State (Learn String): [ Not Config'd ] |
| |
| [ OK ] [ Help ] |
| |
+----------------------------------------+
The relevant fields are the last three -- "Conformance", "Binblock", and
"State (Learn String)".
+-----------------------------------------+
| Select Binblock: |
+--------+-----------------------+--------+
| | None | |
| | #A | |
| | #I | |
| | #T | |
| | | |
| | | |
+--------+-----------------------+--------+
| None |
+-----------------------------------------+
| [ OK ] [ Cancel ] |
+-----------------------------------------+
If you specify "None", the DIO object will generate definite-length
arbitrary-block data as defined at the beginning of this document. The other
selections generate data in one of the "IEEE 728" block data formats:
#A<count><data>
#I<data><EOI>
#T<count><data>
The DIO object will be able to read all these formats (as well as the
so-called "indefinite-length arbitrary block format" defined as
"#0<data><EOI>").
| |
| Conformance: [ IEEE 488 ] |
| Binblock: [ None ] |
| State (Learn String): [ Configured ] |
| Upload String: [ "" ] |
| Download String: [ "" ] |
| |
| [ OK ] [ Help ] |
| |
+----------------------------------------+
In the case of the 54600 scope, these fields could be set to:
| State (Learn String): [ Configured ] |
| Upload String: [ "*LRN?" ] |
| Download String: [":SYST:SETUP" ] |
| |
| [ OK ] [ Help ] |
| |
+----------------------------------------+
* This is all appropriate if you leave the "Conformance" to "IEEE 488.2". If
you switch to "IEEE 488", the dialog simplifies to:
| Conformance: [ IEEE 488.2 ] |
| |
| [ OK ] [ Help ] |
| |
+----------------------------------------+
Where did all the fields go? They went away because they were no longer
necessary. The "Binblock" format now is restricted to definite-length
arbitrary-block format on output, and to definite- or indefinite-length
arbitrary-block format on input. The "State (Learn String)" field is assumed
to be configured to the default 488.2 commands, "*LRN?" and "*LRN".
[9.2] BUILDING A FIXED LENGTH BINBLOCK HEADER
#800000128<byte1><byte2> ... <byte128>
This isn't a problem in itself, it's acceptable within spec. The problem is
that they may not accept the learn string back unless the header is in
exactly the same format. Sending back:
#3128<byte1><byte2> ... <byte128>
-- gives a device error, even though it is legal.
+----------------------------+
| To File |
+----------------------------------+ +---+------------------------+
| Direct I/O | | | To File: [LRNSTR.BIN] |
+------------------------------+---+ | +------------------------+
| READ BINBLOCK x BYTE ARRAY:* | x +-->| a | WRITE BINARY A BYTE |
+------------------------------+---+ | | |
+---+------------------------+
To send it back to the device, you use the following objects:
+--------------------------------+
| From File |
+----------------------------+---+
| From File: [LRNSTR.BIN] | |
+----------------------------+ | +---------+ +---------+
| READ BINARY X BYTE ARRAY:* | X +--+-->| totSize +-->| Formula +---+
| | | | +---------+ +---------+ |
+----------------------------+---+ | |
| +---<-- BINBLOCK header ---+
| |
data | +--------------------------+
| | | Direct I/O |
| | +---+----------------------+
| +-->| A | WRITE TEXT A STR |
+------->| B | WRITE BINARY B BYTE |
+---+----------------------+
Source for an extended version of this program can be found in
xfixblok.vee.
#800000128
The output Direct I/O box then outputs this header, followed by the learn
string data bytes.
"#8" + strFromLen( "00000000", 0, 8-StrLen(asText(A))) + asText(A)
To figure this out, please note that "+" is a string-concatenation operator
under VEE, and "asText()" converts a numeric value to a string (this isn't a
documented function for some odd reason). So the Formula concatenates the
"#8" with a string of padding zeroes, and ends with an ASCII string giving
the numeric digits.
strFromLen( <string>, <start_index>, <string_length> )
-- which extracts a substring of a given length from a given string, starting
from a given index value. In this case we have a string of 8 zeroes
("00000000") and take a substring of it, starting at the beginning of the
source string ( 0 ) and of the length of the required number of padding
zeroes ( 8-StrLen(AsText(A)) ). Works like a charm.
[9.3] SCOPE DRIVERS & TIMEOUTS
+-----------------------------------+
| 54600 | state (panel) driver
+----------+------------------------+
+---+ | | |
| 1 +-->| VIEW_CH1 | |
+---+ | | |
| | |
+---+ | | |
| 0 +-->| VIEW_CH2 | |
+---+ | | |
+----------+------+-----------------+
|
+--+--+
| OK +--+
+-----+ |
|
+-------+-------+
| 54600 | component driver
+------+--------+
| | WF_CH2 +--> To XY Graph
+------+--------+
Note that "VIEW_CH1" is activated, while the component driver is trying to
fetch the waveform from channel 2.
+------------------------------------------------------------+
| E1426A (NOT LIVE) |
+--------+----------------------------+----------------------+
| | |[Reset] [ Main Panel ]|
| | +----------------------+
| | | Timebase [ 100 n ]|
+-----+ | | | Sweep Mode [ Trig'd ]|
|1 +-->|DIGITIZE| | Trg [1][ 5 ][ Pos ]+--+
+-----+ | Int16 | | CH1 [ 500 m ][ 1 ]| |
| +----------------------------+ CH2 [ 500 m ][ 1 ]| |
| |[no inst] [ZOOM IN] | CH3 [ 500 m ][ 1 ]| |
| |[ Dig ][ Autoscale ][ Run ]| CH4 [ 500 m ][ 1 ]| |
| |[ CH1 ][ CH2 ][ CH3 ][ CH3 ]| | |
+--------+----------------------------+----------------------+ |
|
+------------------------------------+
|
| +-------------+
+-->| Do Whatever |
+-------------+
Once the driver is executed, control flow stays stuck there until it is done
what is trying to do, or it times out.
+---------------------------------------------------+
| E1426A (NOT LIVE) |
+----------------------------+----------------------+
| |[Reset] [ Main Panel ]|
| +----------------------+
| | Timebase [ 100 n ]|
| | Sweep Mode [ Trig'd ]| Panel
| | Trg [1][ 5 ][ Pos ]|
| | CH1 [ 500 m ][ 1 ]|
+----------------------------+ CH2 [ 500 m ][ 1 ]|
|[no inst] [ZOOM IN] | CH3 [ 500 m ][ 1 ]|
|[ Dig ][ Autoscale ][ Run ]| CH4 [ 500 m ][ 1 ]|
|[ CH1 ][ CH2 ][ CH3 ][ CH3 ]| |
+-------------------------+--+----------------------+
|
+-----------------------------+-----------------------------+
| E1426A (NOT LIVE) |
+-----------------------------------------------------------+
| WRITE TEXT ":WAVEFORM:FORMAT:WORD;:SOURCE:CHANNEL1" EOL |
| WRITE TEXT "*CLS;*SRE 32;*ESE 1" EOL | DIO1
| WRITE TEXT ":DIGITIZE:CHANNEL1;*OPC" EOL |
| |
| |
+-----------------------------+-----------------------------+
|
The instrument driver sets up the instrument to the desired general
configuration, and then the DIO box sends the commands to perform the
digitization. The first transaction sets up the waveform format and channel;
the second one programs the scope to set a status flag when it has completed
an operation; and the third instructs the scope to DIGITIZE the waveform.
transactions in
previous illustration
| +-----> value
+---+---+ |
| now() +-------------------------------------|-----> initial
+---+---+ | time
| |
+------+------+ |
| Until Break +----+ |
+-------------+ | |
| |
+---------------+-----------------------+ |
| E1426A (NOT LIVE) | |
+------------------------------+--------+ |
| Device [ E1426A (NOT LIVE) ] | | |
| Event [ Spoll ] | | |
| Action [ NO WAIT ] | Status +-----+
| Mask [ #H0 ] | |
| | | Spoll Scope
+------------------------------+--------+
-- and these objects interpret the results:
+--------------+ +--------------------------------+
| Formula | | If/Then/Else |
spoll +--------------+ +-------+--------------+---------+
value -->| bitAnd(a,32) +---->| A Any |[ A>0 ]| Then +-----+
+-------+------+ | | | | |
initial -----------|----------->| B Any |[ C>(B+5) ]| Else if +--+ |
time +---+---+ | | | | | |
| now() +------->| C Any | Else | Else | | |
+-------+ +-------+--------------+---------+ | |
| |
+---------------------------------------------------+ |
| |
| +-----------------------+
| |
+-------------+-------------+ +-------+--------+ +----------+
| E1426A (NOT LIVE) | | get scope data +---->| |
+---------------------------+ +-------+--------+ | XY Trace |
| EXECUTE CLEAR | | +->| |
| | +---+---+ | +-----+----+
| | | Break | +--------+
+-------------+-------------+ +-------+
|
+------+------+
| Raise Error |
+-------------+
The status byte is ANDed with 32 to mask for bit 5, which was defined above
as the bit that indicates the DIGITIZE has completed. If it is set, as
determined by the If-Then-Else box, the program gets the scope data and
displays it (and breaks out of the polling loop).
+--------------------------------------------------------------------------+
| U_GetScope |
+------------------------------------------------------------------------+-+
| | |
| +-------------------------------------+ | |
| | E1426A (NOT LIVE) | | |
| +-------------------------------------+ | |
| | WRITE TEXT ":WAVEFORM:DATA?" EOL | | |
| | | | |
| | | | |
| +------------------+------------------+ | |
| | | |
| +--------------+ | |
| | +--------------+ | |
| +---+---+ +----->| Then +-----+ | |
| | now() +--------------|----->| If/Then/Else | | | |
| +---+---+ | +-->| ElseIf +--+ | +-->|X|
| | +-------+ | | +--------------+ | | | | |
| | | now() +--|--+ | | | | |
| | +-------+ | +-----------------+ | | | |
| +---+---+ | | | | | |
| | Until | | +---+---+ +-----------+-----------+ | | |
| | Break +--+ | | Raise | | E1426A (NOT LIVE | | | |
| +-------+ | | | Error | +-----------------------+ | | |
| | | +-------+ |[READ BINBLOCK x INT16]+--+ | |
| | | | | | |
| | | +-----------+-----------+ | |
| | | | | |
| | +-------------------+ +---+---+ | |
| | | | Break | | |
| +---------+---------+ +--------------+ | +-------+ | |
| | E1426A (NOT LIVE) +-->| bitAnd(A,16) +--+ | |
| +-------------------+ +--------------+ | |
| Spoll Scope | |
+------------------------------------------------------------------------+-+
This UserObject requests the waveform and performs serial polls in a fashion
similar to that used for the DIGITIZE. The WAVEFORM:DATA? command is sent,
and then serial polls are conducted to get the status byte. The UserObject
tests for bit 4 of the status byte, which indicates that a measurement is
available, and the polls are conducted in a loop that tests for a timeout.
When the measurement is available, it is returned with a READ BINBLOCK
transaction.
[9.4] PERFORMING DEVICE-TO-PRINTER DUMPS
UNLISTEN
UNTALK
LISTEN 1
TALK 13
RELEASE ATN
This can be done with the following program (see the file xprscope.vee
for the source):
+--------------------------+
| 54600 (54600A @ 713) |
+--------------------------+
| WRITE TEXT "PRINT?" EOL |
| |
+-------------+------------+
|
+-------------+------------+
| Interface Op's hpib7 @ 7 |
+--------------------------+
| SEND UNL |
| SEND UNT |
| SEND LISTEN 1 |
| SEND TALK 13 |
| SEND DATA "" |
+--------------------------+
Note how ATN is released with the Interface Operations transaction:
SEND DATA ""
This was the transaction that was missing in earlier versions of VEE.