Introduction to I/O

This chapter is an introduction to I/O (Input/Output) programming concepts and programming techniques. The remainder of this manual (chapters 15 through 21) covers specific interfacing topics.

Interfacing Concepts

This section introduces some interfacing concepts important to I/O programming. Let's begin by defining some terms.

Terminology

These terms are important to your understanding of the text of the remainder of this manual. The purpose of this section is to make sure that our terms have the same meanings.
computer is defined for our purposes to be the processor, its support hardware, and the BASIC-language operating system; together these system elements manage all computer resources.
hardware describes both the electrical connections and electronic devices that make up the circuits within the computer; any piece of hardware is an actual physical device.
software describes the user-written, BASIC-language programs.
firmware refers to the pre-programmed, machine-language programs that are invoked by BASIC-language statements and commands. As the term implies, firmware is not usually modified by BASIC users. The machine-language routines of the operating system are firmware programs.
computer resource is used in this manual to describe all of the "data-handling" elements of the system. Computer resources include: internal memory, CRT display, keyboard, and disk drive, and any external devices that are under computer control.

Block Diagram of the Computer

I/O is an acronym that comes from "Input and Output"; it refers to the process of copying data to or from computer memory.
output involves moving data from computer memory to another resource. During output, the source of data is computer memory and the destination is any resource, including memory.
input is moving data from a resource to computer memory; the source is any resource and the destination is a variable in computer memory. Inputting data is also referred to as "entering data" in this manual for the sake of avoiding confusion with the INPUT statement.
bus refers to a common group of hardware lines that are used to transmit information between computer resources. The computer communicates directly with the internal resources through the data and control buses.
computer backplane is an extension of these internal data and control buses. The computer communicates indirectly with the external devices through interfaces connected to the backplane hardware.

Backplane Hardware

Why Do You Need an Interface?

The primary function of an interface is, obviously, to provide a communication path for data and commands between the computer and its resources. Interfaces act as intermediaries between resources by handling part of the "bookkeeping" work, ensuring that this communication process flows smoothly. The following paragraphs explain the need for interfaces.

First, even though the computer backplane is driven by electronic hardware that generates and receives electrical signals, this hardware was not designed to be connected directly to external devices. The electronic backplane hardware has been designed with specific electrical logic levels and drive capability in mind.
CAUTION
Exceeding backplane hardware ratings will damage this electronic hardware.

Second, you cannot be assured that the connectors of the computer and peripheral are compatible. In fact, there is a good probability that the connectors may not even mate properly, let alone that there is a one-to-one correspondence between each signal wire's function.

Third, assuming that the connectors and signals are compatible, you have no guarantee that the data sent will be interpreted properly by the receiving device. Some peripherals expect single-bit serial data while others expect data to be in 8-bit parallel form.

Fourth, there is no reason to believe that the computer and peripheral will be in agreement as to when the data transfer will occur; and when the transfer does begin the transfer rates will probably not match. As you can see, interfaces have a great responsibility to oversee the communication between computer and its resources. The functions of an interface are shown in the following block diagram.

Functional Diagram of an Interface

Electrical and Mechanical Compatibility

Electrical compatibility must be ensured before any thought of connecting two devices occurs. Often the two devices have input and output signals that do not match; if so, the interface serves to match the electrical levels of these signals before the physical connections are made.

Mechanical compatibility simply means that the connector plugs must fit together properly. All of the HP 9000 Series 200/300 interfaces have 100-pin DIO (Device I/O) connectors that mate with the computer backplane. HP 9000 Series 400 computers may have either DIO or, optionally, EISA (Extended Industry Standard Architecture) connectors. HP BASIC/UX supports only the DIO interfaces on Series 400 computers. HP 9000 Series 700 computers have EISA connectors and HP BASIC/UX 700 supports those EISA connectors.

The peripheral end of these interfaces may have unique configurations because several types of peripherals are available that can be operated with the computer. Most of the interfaces have cables available that you can connect directly to the device so that you don't have to wire the connector yourself.

Data Compatibility

Just as two people must speak a common language, the computer and peripheral must agree upon the form and meaning of data before communicating it. As a programmer, one of the most difficult compatibility requirements to fulfill before exchanging data is that the format and meaning of the data being sent is identical to that anticipated by the receiving device. Even though some interfaces format data, most interfaces have little responsibility for matching data formats; most interfaces merely move agreed-upon quantities of data to or from computer memory. The computer must generally make the necessary changes, if any, so that the receiving device gets meaningful information.

Timing Compatibility

Since all devices do not have standard data-transfer rates, nor do they always agree as to when the transfer will take place, a consensus between sending and receiving device must be made. If the sender and receiver can agree on both the transfer rate and beginning point (in time), the process can be made readily.

If the data transfer is not begun at an agreed-upon point in time and at a known rate, the transfer must proceed one data item at a time with acknowledgement from the receiving device that it has the data and that the sender can transfer the next data item; this process is known as a "handshake". Both types of transfers are utilized with different interfaces and both will be fully described as necessary.

Additional Interface Functions

Another powerful feature of some interface cards is to relieve the computer of low-level tasks, such as performing data-transfer handshakes. This distribution of tasks eases some of the computer's burden and also decreases the otherwise-stringent response-time requirements of external devices. The actual tasks performed by each type of interface card vary widely.

Data Representations

As long as data is only being used internally, it really makes little difference how it is represented; the computer always understands its own representations. However, when data is to be moved to or from an external resource, the data representation is of paramount importance.

Bits and Bytes

Computer memory is no more than a large collection of individual bits (binary digits), each of which can take on one of two logic levels (high or low). Depending on how the computer interprets these bits, they may mean on or off, true or false, one or zero, busy or not busy, or any other two-state or binary condition. These logic levels are actually voltage levels at hardware circuit nodes within the computer. The following diagram shows the voltage at a node versus time, and relates the voltage levels to logic levels.

Voltage and Positive-True Logic

In some cases, you want to determine the state of an individual bit (of a variable in computer memory, for instance). The logical binary functions BIT, BINCMP, BINIOR, BINEOR, BINAND, ROTATE, and SHIFT provide access to the individual bits of data.

Bit Naming Conventions

Bits are grouped together to form fundamental blocks. These groups have different sizes and names:
byte 8 bits
word 16 bits
long word 32 bits
long 32 bits

On the HP 9000 Series 700/800/900 a word is actually 32 bits, however, HP BASIC will always refer to a word as 16 bits.

The most common architecture for BASIC is the HP Series 200/300/400 workstation. These workstations are based on the Motorola MC680x0 processors which number their bits starting at the LSB. The Intel I80x86 processors also number their bits this way.
Motorola MC680x0 and Intel I80x86 bit naming
MSB LSB
bit bit bit bit bit bit bit bit bit bit bit bit bit bit bit bit
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

On some other processor architectures, such as the HP-PA in the HP Series 700/800/900, the bits are numbered starting with the MSB.
HP-PA processor bit naming
MSB LSB
bit bit bit bit bit bit bit bit bit bit bit bit bit bit bit bit
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
NOTE
HP BASIC/UX 700 does not follow the above convention. In HP BASIC the LSB is always bit 0.

With a 16-bit word, 65 536 (65 536=216) different bit patterns can be produced. The computer can also use groups of eight bits at a time; this size group is known as a byte. With this smaller size of bit group, 256 (256=28) different patterns can be produced. How the computer and its resources interpret these combinations of ones and zeros is very important and gives the computer all of its utility.

Representing Numbers

The following binary weighting scheme is often used to represent numbers with a single data byte. Only the non-negative integers 0 through 255 can be represented with this particular scheme.
<—Most-Significant Bit Least-Significant Bit—>
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
1 0 0 1 0 1 1 0
value=128 value=64 value=32 value=16 value=8 value=4 value=2 value=1

Notice that the value of a 1 in each bit position is equal to the power of two of that position. For example, a 1 in the 0th bit position has a value of 1 (1=20), a 1 in the 1st position has a value of 2 (2=21), and so forth. The number that the byte represents is then the total of all the individual bit's values.

The preceding representation is used by the "NUM" function when it interprets a byte of data. The next section explains why the character "A" can be represented by a single byte.

 
100  Number=NUM("A")
110  PRINT " Number = ";Number
120  END
 
 
Number = 65 Printed Result
 

Representing Characters

Data stored for humans is often alphanumeric-type data. Since less than 256 characters are commonly used for general communication, a single data byte can be used to represent a character. The most widely used character set is defined by the ASCII standard. (ASCII stands for "American Standard Code for Information Interchange". See the Useful Tables section in volume 2 of the HP BASIC Language Reference for the complete table.)

The ASCII standard defines the correspondence between characters and bit patterns of individual bytes. Since the ASCII standard defines only 128 patterns (i.e., all values with the MSB = 0), the remaining 128 characters are defined by the computer (i.e., those values with the MSB = 1). The entire set of 256 characters on the computer is hereafter called the "extended ASCII" character set.

When the CHR$ function is used to interpret a byte of data, its argument must be specified by its binary-weighted value. The single (extended ASCII) character returned corresponds to the bit pattern of the function's argument.

 
100   Number=65             !  Bit pattern is "01000001"
110   PRINT " Character is ";
120   PRINT CHR$(Number)
130   END
 
 
Character is A Printed Result
 

Representing Signed Integers

There are two ways that the computer represents signed integers. The first uses a binary weighting scheme similar to that used by the NUM function. The second uses ASCII characters to represent the integer in its decimal form.

Internal Representation of Integers

Bits of computer memory are also used to represent signed (positive and negative) integers. Since the range allowed by eight bits is only 256 integers, a 16 bit word is used to represent integers. With this size of bit group, 65536 (65536=216) unique integers can be represented.

The range of integers that can be represented by 16 bits can arbitrarily begin at any point on the number line. In the computer, this range of integers has been chosen for maximum utility; it has been divided as symmetrically as possible about zero, with one of the bits used to indicate the sign of the integer.

With this "2's-complement" notation, the most significant bit is weighted –(215) or -32768, and can be thought of as a sign bit. A sign bit of 0 indicates positive numbers and a sign bit of 1 indicates negatives. You still have the full range of numbers to work with, but the range of absolute magnitudes is divided in half (-32768 through 32767). The following 16-bit integers are represented using this 2's-complement format.

       Binary Representation          Decimal Equivalent

    1111   1111   1111   1111          -1
    0000   0000   0000   0000           1
    1111   1111   0000   0001        -255
    0000   0000   1111   1111         255
-215 214 213      28   27             20

The representation of an integer is generated according to place value, just as when bytes are interpreted as numbers. As a shortcut to generate a negative number's representation, first derive the positive number's representation. Complement (change the ones to zeros and the zeros to ones) all bits, and then to this result add 1. The final result is the two's-complement representation of the negative integer. This notation is very convenient to use when performing math operations. Let's look at a simple addition of 2 two's-complement integers.

ASCII Representation of Integers

ASCII digits are often used to represent integers. In this representation scheme, the decimal (rather than binary) value of the integer is formed by using the ASCII digits 0 through 9 {CHR$(48) through CHR$(57), respectively}. An example is shown below. Example

The decimal representation of the binary value "1000 0000" is 128. The ASCII-decimal representation consists of the following three characters.
Character Decimal
Code
Binary Code
1 49 00110001
2 50 00110010
8 56 00111000

Representing Real Numbers

Real numbers, like signed integers, can be represented in one of two ways with the computers. They are represented in a special binary mantissa-exponent notation within the computers for numerical calculations. During output and enter operations, they can also be represented with ASCII-decimal digits.

Internal Representation of Real Numbers

Real numbers are represented internally by using a special binary notation. With this method, all numbers of the REAL data type are represented by eight bytes: 52 bits of mantissa magnitude, 1 bit for mantissa sign, and 11 bits of exponent. The following equation and diagram illustrate the notation; the number represented is 1/3.
NOTE
The internal representation used for real numbers is the IEEE standard 64-bit floating-point notation. For further details, refer to chapter 3, "Numeric Computation."

Even though this notation is an international standard, most external devices don't use it; most use an ASCII-digit format to represent decimal numbers. The computer provides a means so that both types of representations can be used during I/O operations.

ASCII Representation of Real Numbers

The ASCII representation of real numbers is very similar to the ASCII representation of integers. Sign, radix, and exponent information are included with ASCII-decimal digits to form these number representations. The following example shows the ASCII representation of 1/3. Even though, in this case, 18 characters are required to get the same accuracy as the eight-byte internal representation shown above, not all real numbers represented with this method require this many characters.
ASCII characters 0 . 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 Decimal value of characters 48 46 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51

The I/O Process

When using statements that move data between memory and internal computer resources, you do not usually need to be concerned with the details of the operations. However, you may have wondered how the computer moves the data. This section takes you "behind the scenes" of I/O operations to give you a better intuitive feel for how the computer outputs and enters data.

I/O Statements and Parameters

The I/O process begins when an I/O statement is encountered in a program. The computer first determines the type of I/O statement to be executed (such as, OUTPUT, ENTER USING, etc.). Once the type of statement is determined, the computer evaluates the statement's parameters.

Specifying a Resource

Each resource must have a unique specifier that allows it to be accessed to the exclusion of all other resources connected to the computer. The methods of uniquely specifying resources (output destinations and enter sources) are device selectors, string variable names, and I/O path names. These specifiers are further described in the section "Directing Data Flow," later in this chapter.

For instance, before executing an OUTPUT statement, the computer first evaluates the parameter which specifies the destination resource. The source parameter of an ENTER statement is evaluated similarly.

 
OUTPUT Dest_parameter;Source_item

ENTER Sourc_parameter;Dest_item
 
Firmware

After the computer has determined the resource with which it is to communicate, it "sets up" the moving process. The computer chooses the method of moving the specified data according to the type of resource specified and the type of I/O statement. The actual machine-language routine that executes the moving procedure is in firmware. Since there are differences in how each resource represents and transfers data, a dedicated firmware routine must be used for each type of resource. After the appropriate firmware routine has been selected, the next parameter(s) must be evaluated (i.e., source items for OUTPUT statements and destination items for ENTER statements).

Registers

The computer must often read certain memory locations to determine which firmware routines will be called to execute the I/O procedure. The content of these locations, known as registers, store parameters such as the type of data representation to be used and type of interface involved in the I/O operation.

An example of register usage by firmware is during output to the CRT. Characters output to this device are displayed beginning at the current screen coordinates. After the computer has evaluated the first expression in the source-item list, it must determine where to begin displaying the data on the screen. Two memory locations are dedicated to storing the "X" and "Y" screen coordinates. The firmware determines these coordinates and begins copying the data to the corresponding locations in display memory.

The program can also determine the contents of these registers. The statements that provide access to the registers are described in chapter 17. The contents of all registers accessible by the program are described in the HP BASIC Interface Reference manual.

Data Handshake

Each byte (or word) of data is transferred with a procedure known as a data-transfer handshake (or simply "handshake"). It is the means of moving one byte of data at a time when the two devices are not in agreement as to the rate of data transfer or as to what point in time the transfer will begin. The steps of the handshake are as follows.

  1. The sender signals to get the receiver's attention.
  2. The receiver acknowledges that it is ready.
  3. A data byte (or word) is placed on the data bus.
  4. The receiver acknowledges that it has gotten the data item and is now busy. No further data may be sent until the receiver is ready.
  5. Repeat these steps if more data items are to be moved.

I/O Examples

Now that you have seen all of the steps taken by the computer when executing an I/O statement, let's look at how two typical I/O statements are executed by the computer.

Example Output Statement

Data can be output to only one resource at a time with the OUTPUT statement (with the exception of the HP-IB Interface). This destination can be any computer resource, which is specified by the destination parameter as shown below.

 
           Destination parameter
           
OUTPUT Destination;String$,CHR$(C+32),"That's all"
                   |   Source items are expressions  |
 

The source of data for output operations is always memory. Either string or numeric expressions can specify the actual data to be output. The flow of data during output operations is shown below. Notice that all data copied from memory to the destination resource by the OUTPUT statement passes through the processor under the control of operating-system firmware.

Data Flow During Output Operations

Source-Item Evaluation

The source items, listed after the semicolon and separated by commas, can be any valid numeric or string expression. As the statement is being executed, these expressions must be individually evaluated and the resultant data representation sent to the specified destination. The results of the evaluation depend on the type of expression (numeric or string) and on which data representation (ASCII or internal) is to be used during the I/O operation.

If the expression is a variable and the internal data representation is to be used, the data is ready to be copied byte-serially (or word-serially) to the destination; otherwise, the expression must be completely evaluated. The representation generated during the evaluation is stored in a temporary variable within memory. In both cases, once the beginning memory location and length of the data are known, the copying process can be initiated.

Copying Data to the Destination

The computer employs "memory-mapped" I/O operations; all devices are addressable as memory locations. All output operations involve a series of two-step processes. The first step is to copy one byte (or word) from memory into the processor. The second step is then to copy this byte (or word) into the destination location (a memory address). Each item in the list is output in this serial fashion. The appropriate handshake firmware routine is executed for each byte (or word) to be copied.

Since there may be several data items in the source list, it may be necessary to output an item-terminator character after each item to communicate the end of the item to the receiver. If the item is the last item in the source list, the computer may signal the receiver that the output operation is complete. Either an item terminator or end-of-line sequence of characters can be sent to the receiver to signal the end of this data transmission. The OUTPUT statement is described in full detail in chapter 15.

Example Enter Statement

Data can be entered from only one resource at a time. This source can be any resource and is specified by the source parameter as shown in the following statement.

 
           Source parameter
        
ENTER Source;Number,String$
                         
       Destination items are program variables
 

The destinations of enter operations are always variables in memory. Both string and numeric variables can be specified as the destinations. The flow of data during enter operations is shown below.

Data Flow During Enter Operations

Destination-Item Evaluation

The destination(s) of data to be entered is (are) specified in the destination list. Either string or numeric variables can be specified, depending on the type of data to be entered. In general, as each destination item is evaluated, the computer finds its actual memory location so that data can be copied directly into the variable as the enter operation is executed. However, if the ASCII representation is in use, numeric data entered is stored in a temporary variable during entry.

Copying Data into the Destinations

As with output operations, entering data is a series of two-step processes. Each data byte (or word) received from the sender is entered into the processor by the appropriate handshake firmware. It is then copied into either a temporary variable or a program variable. If more than one variable is to receive data, each incoming data item must be properly terminated. If the internal representation is in use, the computer knows how many characters are to be entered for each variable. If the ASCII representation is in use, a terminator character (or signal) must be sent to locate the end of each data item. When all data for the item has been received, it is evaluated, and the resultant internal representation of the number is placed into the appropriate program variable. Further details concerning the ENTER statement are contained in chapter 16.

Sharing Resources in a\Multi-Tasking/Multi-User Environment\(BASIC/UX only)

HP-UX provides BASIC/UX with a multi-tasking/multi-user environment. This section explains the concepts of multi-tasking and multi-user environments and some of the things you need to be aware of in these environments. Topics covered are:

What Is Multi-Tasking?

Multi-tasking means you can perform more than one task at a time. These tasks are referred to as processes when running BASIC/UX on HP-UX. For example, you can run BASIC/UX in two windows at the same time and have a different program or process running in each window. This capability helps you to be more productive as a programmer.

What Does Multi-User Mean?

Multi-user systems allow more than one user to be on the computer at the same time. What this means is your computer can have several terminals connected to it with each terminal having access to all of the system resources.

Using I/O Resources in a \Multi-Tasking/Multi-User Environment

With BASIC/UX running on HP-UX, you need to be alert to the fact that the shared resources such as disks, I/O interfaces, printers, plotters, etc. may be used by other people on the system. Therefore, it is a good idea to practice good "system citizenship" and not try to use a resource that someone else is currently using. In the case of printer and plotter spoolers, good citizenship is enforced.

As a BASIC/UX user on HP-UX you are responsible for the following:

For further information about I/O in the HP-UX environment, refer to HP BASIC Advanced Programming Techniques.

Directing Data Flow

As described previously in this chapter, data can be moved between computer memory and several resources, including:

Here is where to learn about how to use each of these I/O resources:
I/O Resource Where Covered
String variables, devices, pipes, and windows are described in this chapter.
Files are briefly described in the "I/O Path Attributes" chapter of this manual, and more fully in the "Data Storage and Retrieval" chapter.
Buffers are described in the "Transfers and Buffered I/O" chapter of this manual.

Specifying a Resource

Each resource must have a specifier that allows it to be accessed to the exclusion of all other computer resources. String variables are specified by variable name, while devices can be specified by either their device selector or a data type known as an I/O path name. This section describes how to specify these resources in OUTPUT and ENTER statements.

String-Variable Names

Data is moved to and from string variables by specifying the string variable's name in an OUTPUT or ENTER statement. Examples of each are shown in the following program (lines 200 and 240).

 
100  DIM To_string$[80],From_string$[80]
110  DIM Data_out$[80]
120  !
130  From_string$="Source data"
140  Data_out$="OUTPUT data"
150  !
160  PRINTER IS CRT
170  PRINT "To_string$ before OUTPUT = ";To_string$
180  PRINT
190  !
200  OUTPUT To_string$;Data_out$; ! ";" suppresses CR/LF.
210  PRINT "To_string$ after OUTPUT = ";To_string$
220  PRINT
230  !
240  ENTER From_string$;To_string$
250  PRINT "To_string$ after ENTER = ";To_string$
260  PRINT
270  !
280  END
 

Printed Results

 
To_string$ before OUTPUT=(null string)

To_string$ after OUTPUT= OUTPUT data 

To_string$ after ENTER= Source data 
 

Data is always copied to the destination string (or from the source string) beginning at the first position of the variable; subscripts cannot be used to specify any other beginning position within the variable.

Formatted String I/O

The use of outputting to and entering from string variables is a very powerful method of buffering data to be output to other resources. With OUTPUT and ENTER statements that use images, the data sent to the string variables can be explicitly formatted before being sent to (or while being received from) the variable. Further uses of string variables are described in the "Concepts of Unified I/O" chapter in HP BASIC Advanced Programming Techniques.

Device Selectors

Devices include the built-in CRT and keyboard, external printers and instruments, and all other physical entities that can be connected to the computer through an interface. Each interface has a unique number by which it is identified, its interface select code.

In order to send data to or receive data from a device, merely specify the select code of its interface in an OUTPUT or ENTER statement. Examples of using select codes to access devices are shown below.

OUTPUT 1;"Data to CRT"
ENTER CRT;Crt_line$
The expressions 1 and CRT are device selectors for the CRT display.
Serial=9 ENTER Serial;Serial_data$ OUTPUT Serial;"To serial card" 9 is the device selector for a serial interface.
Hpib_device=722 OUTPUT 722;"F1R1" ENTER Hpib_device;Reading 722 is the device selector of an HP-IB device.

The following pages explain select codes and device selectors for HP 9000 computers. For information about select codes for the HP Measurement Coprocessor, refer to Installing and Using HP BASIC/DOS 6.2.
NOTE
When using devices with BASIC/UX from within a multi-user environment, you should either:
  • Use a pipe to a spooler associated with a device.
  • Lock the interface connected to a device before using it.

Select Codes of Built-In Interfaces (Series 200/300 & 400 with DIO)

The internal devices are accessed with the following interface select codes. These are permanent select code assignments on older systems, but can be changed on newer systems which contain configurable boot ROMs.
Select Codes of Built-In Devices
Built-In Interface/Device Select Code
Alpha Display 1
Keyboard 2
Graphics Display (non-bit mapped alpha/graphics displays)1 3
Flexible Disk Drive (Models 226 and 236 only)1 4
Built-In Serial Interface 2 (Model 362, 382, & Series 400) 52
Built-In Serial Interface 3 (Model 362, 382, & Series 400) 62
Graphics Display (bit-mapped alpha/graphics displays) 6 or 132
Built-in HP-IB interface 7
Built-in serial interface 9
SCSI (Models 345, 362, 375, 380, and 382) 14
Local Area Network (LAN) 21
HP Parallel (Models 345, 362, 375, 380, 382) 23
SCSI (Model 340) 28
Parity-checking (memory), cache, and floating-point math hardware 32 (pseudo)
EXT SIGNAL Registers (BASIC/UX) 33 (pseudo)

1 Available for BASIC/WS only.
2 These interfaces are not accessible unless the interface is mapped to a number that is greater than or equal to 7 and less than or equal to 31 (HP BASIC/UX only).

Select Codes of Optional Interfaces (Series 200/300 & 400 with DIO)

Optional interfaces all have switch-settable select codes. The valid range of select codes is 8 through 31 (they cannot use select codes 1 through 7, since these are reserved for built-in devices). The following settings on optional interfaces have been made at the factory but can be reset to any unique select code between 8 and 31. See the interface's installation manual for further instructions.
Factory Select-Code Settings for Optional Interfaces
Optional Interface Default
Select
Code
HP-IB (HP 98624) 8
Serial (HP 98626, HP 98644) 91
BCD (HP 98623)2 11
GPIO (HP 98622) 12
High-Speed (HP-IB) Disk (HP 98625) 14
SCSI (HP 98658A) 14
4-channel Multiplexer (HP 98642)3 16
Data Communications (HP 98628) 20
Local Area Network (LAN) (HP 98643) 211
Shared Resource Manager (HP 98629) 21
EPROM Programmer (HP 98253)2 27
Color Output (HP 98627) 28
Bubble Memory (HP 98259)2 30

1 Use another select code if there is already a built-in serial interface at this select code.
2 Available for BASIC/WS only.
3 Available for BASIC/UX only.

Select Codes of Interfaces (Series 700)

The HP 9000 Series 700 computers do not have an architecture based on physical select codes. However, to maintain compatibility with Series 200/300/400 computers, HP BASIC/UX internally maps the select codes for the following devices to the appropriate hardware.
HP BASIC/UX Series 700 Internal Devices
Internal Device Select
Code
Alpha Display 1
Keyboard 2
Graphics Display (and windows) 6

To support I/O interfaces, HP BASIC/UX 700 uses the SICL library (Standard Instrument Control Library). SICL simulates physical select codes with logical units (LU). HP BASIC/UX treats LUs as if they were select codes.

The SICL configuration file,

 /usr/pil/etc/hwconfig.cf 

specifies which LU (select code) to use for each supported interface. The LUs are configurable and have the following default values.
Select Codes for SICL Devices
SICL Device Select
Code
Built-In HP-IB or HP-IB in EISA slot 1 7
HP-IB in EISA slot 2 8
HP-IB in EISA slot 3 9
HP-IB in EISA slot 4 10
Built-In RS-232 Port A 9
Built-In RS-232 Port B 10
MXI in EISA slot 1 16
MXI in EISA slot 2 18
MXI in EISA slot 3 20
MXI in EISA slot 4 22

HP-IB Device Selectors

Each device on the HP-IB interface has a primary address by which it is uniquely identified; each address must be unique so that only one device is accessed when one address is specified. The device selector is then a combination of the interface select code and the device's address. Some examples are shown below. (The HP-IB also has additional capabilities that add to this definition of device selectors. See the chapter called "The HP-IB Interface" for further details.)
HP-IB Device Selector Examples
Device Location Device\Selector Example I/O Statement
interface select code 7, primary address 22 722 OUTPUT 722;"Data" ENTER 722;Number
interface select code 10, primary address 13 1013 OUTPUT 1013;"Data" ENTER 1013;Number
interface select code 10, primary address 01 1001 OUTPUT 1013;"Data" ENTER 1013;Number

Multiplexer Device Selectors (BASIC/UX 300 Only)

Each device on an HP 98642 Multiplexer interface has a channel number by which it is uniquely identified. (This channel number is similar to the primary address of the HP-IB device selectors shown above.) Some examples are shown below.
Multiplexer Device Selector Examples
Multiplexer\Channel Device\Selector Example I/O Statement
interface select code 10, channel 0 1000 OUTPUT 1000;"Data" ENTER 1000;Number
interface select code 16, channel 3 1603 OUTPUT 1603;"Data" ENTER 1603;Number

I/O Path Names

An I/O path name is a data type that describes an I/O resource. With this BASIC system, you can assign I/O path names to:
Devices ASSIGN @Device TO 722
HP-UX pipes ASSIGN @Device TO "| lp" (BASIC/UX only) (HP-UX pipes are supported by BASIC/UX only. Refer to the "I/O in the HP-UX Environment" chapter in HP BASIC Advanced Programming Techniques for more information.)
Files ASSIGN @File TO "MyFile" (See the "Data Storage and Retrieval" chapter for details.)
Buffers ASSIGN @Buff TO Buffer$ (See the "Transfers and Buffered I/O" chapter of this manual for details.)

An I/O path name is any valid name preceded by the "@" character. A name is a combination of 1 to 15 characters, beginning with an upper-case alphabetical character or one of the characters CHR$(161) through CHR$(254) and followed by up to 14 lower-case alphanumeric characters, the underbar character (_), or the characters CHR$(161) through CHR$(254). Numeric-variable names are examples of valid names.

Assigning names to I/O paths provides many improvements in performance and additional capabilities over using device selectors, described in "Benefits of Using I/O Path Names" at the end of this chapter.
More Examples
ASSIGN @Display TO 1 OUTPUT @Display;"Data" Assigns the I/O path name @Display to the CRT. Sends characters to the display.
ASSIGN @Printer TO 701 OUTPUT @Printer;"Data" Assigns @Printer to HP-IB device 701. Sends characters to the printer.
ASSIGN @Printer TO "| lp" Assigns @Printer to a pipe connected to the HP-UX lp command (the "line printer" spooler). (BASIC/UX only)
OUTPUT @Printer;"Data" Sends characters to the spooler file. (See "Using HP-UX Printer Spoolers" in the chapter titled "Using a Printer." for further information.)
ASSIGN @Serial TO 9 ENTER @Serial;String$ Assigns @Serial to the interface at select code 9. Enters data from the serial interface into a string variable.
ASSIGN @Gpio TO 12 ENTER @Gpio;A_number Assigns @Gpio to the interface at select code 12. Enters one numeric value from the interface.
ASSIGN @Window TO 601 PRINTER IS 601 Assigns @Window to window number 601. Assigns the window to be the "system printer". (BASIC/UX only)
ASSIGN @Date_pipe TO "date |" Assigns the I/O path name @Date_pipe to a pipe connected to the HP-UX command named date. (BASIC/UX only)
ENTER @Date_pipe;Date_info$ Enters output from the date command into the BASIC string named Date_info$. (BASIC/UX only)

I/O Path Variable Contents

Since an I/O path name is a data type, a fixed amount of memory is allocated, or "reserved", for the variable similar to the manner in which memory is allocated for other program variables (INTEGER, REAL, COMPLEX, and string variables). Since the variable does not initially contain usable information, the validity flag, shown below, is set to false. When the ASSIGN statement is actually executed, the allocated memory space is then filled with information describing the I/O path between the computer and the specified resource, and the validity flag is set to true. The I/O path contents are the following:

Attempting to use an I/O path name that does not appear in any program line results in error 910 (Identifier not found in this context). This error message indicates that memory space has not been allocated for the variable. However, attempting to use an I/O path name that does appear in an ASSIGN statement in the program, but which has not yet been executed, results in error 177 (Undefined I/O path name). This error indicates that the memory space was allocated but the validity flag is still false; no valid information has been placed into the variable since the I/O path name has not yet been assigned to a resource.

This I/O path information is only accessible to the context in which it was allocated, unless it is passed as a parameter or appears in the proper COM statements. (See the HP BASIC Language Reference for details.) Thus, an I/O path name cannot be initially assigned from the keyboard, and it cannot be accessed from the keyboard unless it is presently assigned within the current context. However, an I/O path name can be re-assigned from the keyboard, as described in the next section.

This information describing the I/O path is accessed by the operating system whenever the I/O path name is specified in subsequent I/O statements. A portion of this information can also be accessed with the STATUS and CONTROL statements described in the "Registers" chapter. For now, the important point is that it contains a description of the resource sufficient to allow its access.

Re-Assigning I/O Path Names

If an I/O path name already assigned to a resource is to be re-assigned to another resource, the preceding form of the ASSIGN statement is also used. The resultant action is that the validity flag is first set false, implicitly "closing" the I/O path name to the device. A "new assignment" is then made just as if the first assignment never existed. Making this new assignment places information describing the specified device into the variable and sets the validity flag true. An example is shown below.

 
100   ASSIGN @Printer TO 1    ! Initial assignment.
110   OUTPUT @Printer;"Data1"
120   !
130   ASSIGN @Printer TO 701  ! 2nd ASSIGN closes 1st
140   OUTPUT @Printer;"Data2" ! and makes a new assignment.
150   PAUSE
160   END
 

The result of running the program is that "Data1" is sent to the CRT, and "Data2" is sent to HP-IB device 701. Since the program was paused (which maintains the program context), the I/O path name @Printer can be used in an I/O statement or re-assigned to another resource from the keyboard.

Closing I/O Path Names

A second use of the ASSIGN statement is to explicitly close the name assigned to an I/O path. When the name is closed, the validity flag is set false, labeling the information as invalid. (Additional action may also be taken when the I/O path name assigned to a mass storage file is closed.) Attempting to use the closed name results in error 177 (Undefined I/O path name). Examples of statements that close path names are as follows. Examples

 
ASSIGN @Printer TO *  

ASSIGN @Serial TO *  

ASSIGN @Window TO *  BASIC/UX only

ASSIGN @Gpio TO *   
 

After executing this statement for a particular I/O path name, the name cannot be used in subsequent I/O statements until it is re-assigned. This same name can be assigned either to the same or to a different resource with a subsequent ASSIGN statement. However, if it is used prior to being re-assigned, error 177 occurs.

I/O Path Names in Subprograms

When a subprogram or user-defined function is called, the context is changed to that of the called subprogram. The statements in the subprogram have access only to the data of the new context. Thus, in order to use an I/O path name in any statement within a subprogram, one of the following conditions must be true:

Subprograms and user-defined functions are discussed in detail in the "Subprograms and User-Defined Functions" chapter.

Benefits of Using I/O Path Names

Devices can be accessed with both device selectors and I/O path names, as shown in the previous discussions. With the information presented thus far, you may not see much difference between using these two methods of accessing devices. This section describes these differences in order to help you decide which method may be better for your application.

Execution Speed

When a device selector is used in an I/O statement to specify the I/O path to a device, the numeric expression must be evaluated by the computer every time the statement is executed. If the expression is complex, this evaluation might take several milliseconds.

 
OUTPUT Value_1+BIT(Value_2,5)*2^3;"Data"
       |  Device selector expression  |
 

If a numeric variable is used to specify the device selector, this expression-evaluation time is reduced; this is the fastest execution possible when using device selectors. However, more information about the I/O process must be determined before it can be executed.

In addition to evaluating the numeric expression, the computer must determine which type of interface (HP-IB, GPIO, etc.) is present at the specified select code. Once the type of interface has been determined, the corresponding attributes of the I/O path must then be determined before the computer can use the I/O path. Only after all of this information is known can the process of actually copying the data be executed.

If an I/O path name is specified in an OUTPUT or ENTER statement, all of this information has already been determined at the time the name was assigned to the I/O path. Thus, an I/O statement containing an I/O path name executes slightly faster than using the corresponding I/O statement containing a device selector (for the same set of source-list expressions).

Re-Directing Data

Using numeric-variable device selectors, as with I/O path names, allows a single statement to be used to move data between the computer and several devices. Simple examples of re-directing data in this manner are shown in the following programs. Example of Re-Directing with Device Selectors

 
100   Device=1
110   GOSUB Data_out
       .
       .
       .
200   Device=9
210   GOSUB Data_out
       .
       .
       .
410   Data_out: OUTPUT Device;Data$
420             RETURN
 

Example of Re-Directing with I/O Path Names

 
100   ASSIGN @Device TO 1
110   GOSUB Data_out
       .
       .
       .
200   ASSIGN @Device TO 9
210   GOSUB Data_out
       .
       .
       .
410   Data_out: OUTPUT @Device;Data$
420             RETURN
 

The preceding two methods of re-directing data execute in approximately the same amount of time. As a comparison of the two methods, executing the "Device=" statement takes less time than executing the "ASSIGN @Device" statement. Conversely, executing the "OUTPUT Device" statement takes more time than executing the "OUTPUT @Device". However, the overall time for each method is approximately equal.

There are two additional factors to be considered. First, device selectors cannot be used to direct data to mass storage files; I/O path names are the only access to files. If the data is ever to be directed to a file, you must use I/O path names. A good example of re-directing data to mass storage files is given in the "I/O Path Attributes" chapter. The second additional factor is described below.

Attribute Control

I/O paths have certain "attributes" which control how the system handles data sent through the I/O path. For example, the FORMAT attribute possessed by an I/O path determines which data representation will be used by the path during communications. If the path possesses the attribute of FORMAT ON, the ASCII data representation will be used. This is the default attribute automatically assigned by the computer when I/O path names are assigned to device selectors. If the I/O path possesses the attribute of FORMAT OFF, the internal data representation is used; this is the default format for BDAT files. Further details of these and additional attributes are discussed in the "I/O Path Attributes" chapter.

The second additional factor that favors using I/O path names is that you can control which attribute(s) are to be assigned to the I/O path to devices (and also to the I/O paths to files and buffers). If device selectors are used, this control is not possible. The "I/O Path Attributes" chapter describes how to specify the attributes to be assigned to an I/O path and gives several useful techniques for using the available attributes.

Interface Locking

Interface locking is not new to BASIC/UX 700. Some locking capabilities existed in previous versions of BASIC/UX 300/400. However, the Series 700 version can lock more kinds of interfaces, and many locking details have changed from the Series 300/400 implementation. The key issues are explained in the following subsections. For more information, refer to the HP BASIC Interface Reference manual.

Who Participates in Locks?

BASIC/UX 300/400 locks applied to HP-IB and GPIO interfaces. Those locks were honored by other BASIC processes and by processes using DIL intrinsics. BASIC/UX 300/400 could not lock RS-232 interfaces (serial ports) or HP-IB interfaces being used by the file system.

BASIC/UX 700 supports locks on RS-232 interfaces and HP-IB interfaces. Those locks are honored by other BASIC processes and by processes using SICL intrinsics. Because Series 700 HP-IB interfaces are never used by the file system, that Series 300/400 locking restriction is irrelevant.

When BASIC/UX cannot execute a statement because of another process's lock, it will block (wait) until the lock is released or an ON TIMEOUT branch is taken. If there is no ON TIMEOUT established, then BASIC will continue with normal program flow after the other process releases the lock. If you are expecting to share an interface with other processes, and you don't want indefinite wait times, then ON TIMEOUT is an effective way to determine when the interface is locked.

Locks and Boot-Time Initialization

When BASIC/UX 700 boots (starts running), it identifies and initializes all the interfaces available to it. The list of available interfaces is in the /usr/pil/etc/hwconfig.cf file. That list can be reduced (but not increased) by using SELECTIVE_OPEN in an rmbrc configuration file.

If another process has an available interface locked when BASIC/UX 700 boots, BASIC will not be able to initialize that interface. When this happens, the following message is displayed:

 
Select code N not initialized; locked by another process
 

Subsequent attempts to access that interface will result in the message:

 
ERROR 163  I/O interface/driver not present
 

There are two general ways to deal with this issue, depending upon your situation. One possibility is that the other process has the interface locked indefinitely. Therefore, you will not be able to access the interface now or later. In this case, you can speed up the boot process by using SELECTIVE_OPEN to ignore the locked interface. For more information, see the previous section "Changes to the rmbrc Configuration File."

The other possibility is that the other process only locked the interface briefly. You will be able access the interface later after the other lock is removed. In this case, you can reclaim the interface by executing SCRATCH A. This command causes BASIC/UX 700 to repeat the scan and initialization of available interfaces.

Locks and Reset Initialization

When the [Reset] key is pressed, BASIC/UX 700 performs some initialization of its interfaces. If an available interface was claimed at boot time, but is subsequently found locked at [Reset] time, the following message is displayed:

 
Cannot reset select code N; interface locked by another process
 

This condition does not interfere with the normal operation of your BASIC program. It is just a reminder that you cannot access that interface until the other process unlocks it.

If your application expects an initialized interface, it is best to execute a RESET command or press the [Reset] key after the interface is released by the other process. (See the "Interface Reset Table" in the HP BASIC Language Reference.)

Automatic Relocation of Locks

BASIC/UX 700 may need to move or alter an interface lock as one of the low-level details of certain commands. One example is the TRANSFER statement, where the lock must be moved from the parent process to the child process. Another example is the PASS CONTROL statement, where the lock must be changed from a controller type to a non-controller type.

During these operations, the old lock must be removed before the new lock is applied. This creates a very brief instant during which BASIC has no lock on the interface. Unfortunately, the brevity of this exposure is not significant if another process has a lock request pending. It is normal for lock requests to block (wait) until the instant an interface becomes available. A blocked lock request could "steal" BASIC's lock during one of these transition times.

In most cases, this loss of a lock is not harmful. It just means that the first process will wait until the other process releases the lock, and then it can continue. A problem exists if the other process holds its lock indefinitely. Such situations are a symptom of multi-user interactions that are combative rather than cooperative. If multiple users will be accessing the same HP-IB, it is important for all of them to understand the need for cooperation.

If you want to design multiple processes that cooperate on a high level, synchronizing blocks of activity on the same HP-IB, you should design a more robust protocol than simply locking the interface. For example, you can use a lock file as an indicator of interface ownership. Before a process uses the HP-IB, it first tries to lock the chosen file. If it succeeds in locking the file, it uses the HP-IB then unlocks the file. If it cannot get a file lock, then it knows that the HP-IB is being used by another process.

Passing Control from a Locked HP-IB

The SICL standard specifies that interface (controller) locks and non-controller locks are independent. With this definition, locks behave as expected when the interface retains Active Control and when the interface is Non System Controller. The vast majority of HP-IB applications are in one of these two categories. However, an unexpected problem can occur in those rare applications when the interface is System Controller, but not Active Controller (it has passed control).

When control is passed to another device, the lock is changed from a controller lock to a non-controller lock. Resetting the interface (sending IFC) is allowed as a controller function. Having a non-controller lock does not prevent another process from accessing controller functions on that interface. Therefore, even when BASIC/UX 700 has the non-active controller HP-IB "locked," another process can open that interface and assert IFC. This will have significant, undesired effects on BASIC's non-controller activities.

The solution is to use a high-level cooperation method as described in a preceding section.