Serial communications

From BR Wiki
Jump to navigation Jump to search

The "OPEN communications" statement matches a file number in a program with a serial port used for communications. See the Open Communications statement for details.

The syntax for the OPEN communications statement consists of many of the parameters for the OPEN display statement (RECL=, WAIT=, TRANSLATE= and EOL=), plus several optional communications parameters (BUFSIZE=, BAUD=, PARITY=, DATABITS=, STOPBITS= and RETRY=). The following are examples of OPEN statements for communications files that use the defaults for all of the optional parameters:

00100 OPEN #1: "NAME=COM1:,FORMAT=ASYNC",DISPLAY,OUTIN ! for IBM PC
00200 OPEN #2: "NAME=:/dev/tty22,FORMAT=ASYNC",DISPLAY,OUTIN ! Unix

OUTIN is not valid for disk-based display files (NOTE: only INPUT or OUTPUT is valid for display files on disk). OUTIN on a communications file allows INPUT, LINPUT and PRINT statements to be used with the same file number. OUTIN is always necessary for proper line initialization to be sure the modem connections have been successful. After an OPEN statement, INPUT, LINPUT, PRINT and CLOSE statements may be used with communications files.

Connecting Via Serial Port

When calling another computer, it is necessary to establish communication between the modem and the program to assure that a connection is made before transmitting data. The following sequence of events would typically occur in dialing out using a modem which supports the AT command set (Hayes compatible):

1.) Open the communications file.
2.) Print "AT"
3.) If EOL=NONE then a routine must be written to accumulate the data until an EOL occurs (simulate LINPUT).
4.) If data from LINPUT is not "OK" then the physical link is not yet established (modem is not turned on, etc.), go back to step 2.
5.) After "OK" is received, print "ATDT" along with the telephone number to be dialed. An example is "ATDT16123319012" (this is the dial command for the Business Rules Board).
6.) If data from LINPUT is not "CONNECT" then redial. NOTE: that error 4270 (EOF) simply means no data has been received since the last LINPUT, which is similar to error code 4271 (incomplete record received). It does not mean the link is terminated or that processing should not continue.
7.) After "CONNECT" is received, the connection is established and data transmission can begin.
8.) when the file is closed, a CLOSE FREE should be used to disconnect the line (hang up).

As of BR version 4.0 now opens serial ports to 9600 bits/second, with no PARITY, eight data bits, one stop bit (an exception is that communications files default to 1200 bits/second). Formerly, the default was 300 bits/second.

SAMPLE PROGRAM

The program below implements the above concepts and adds some further details. It assumes that you are using a Hayes compatible modem. Although the program may beep and display error codes for timeout and other problems because the error checking is not complete, the program is complete enough to illustrate the typical logic needed for communicating with another computer.

Lines 20-35 accept a phone number from the keyboard. The communications file is opened in line 40 where a 5- second waiting period is specified before a timeout error occurs. Line initialization occurs in lines 50- 90.

NOTICE that after the PRINT statement in line 50, the LINPUT statement will receive an echo of the previous PRINT. Programmers must allow for this echo. The LINPUT statement in line 80 is the first statement looking for a response from the other computer.

Lines 100-110 check the response from the other computer. The response must be OK before going further into the program.

Line 120 dials the phone number. Line 140 closes the file without hanging up, so that it can be re-opened in line 150 with a longer timeout period during the actual dialing and ringing of the phone connection. Lines 150 and 160 check for a DIAL COMPLETE message before continuing.

Lines 180 to 230 make sure that the response received is RINGING; then lines 240-260 make sure that the next response is CONNECT. Lines 280-290 shorten the timeout interval to one second.

Lines 300-305 are the main loop to read the incoming data, print it on the screen and monitor the status of the phone line (the CARRIER). Any input error, including timeout errors, in line 300 of this loop will transfer control to an error handling routine in line 320. If the error code (ERR) indicates a timeout due to an end-of-file (4270) or incomplete record (4271), then the operator has a chance to enter the next string to be sent; at this point, the operator can enter the string ATH0 to hang up.

00010 DIM A$*80
00020 PRINT "Enter phone number to be dialed"
00030 LINPUT NUMBER$
00035 IF NUMBER$="" THEN PRINT "Program Ended" : STOP
00036 !
00037 ! begin communications processing here
00038 ! first, initialize modem
00040 OPEN #3: "name=com1:,format=async,wait=5",DISPLAY,OUTIN
00050 PRINT #3: "AT"
00060 LINPUT #3: A$ ! read echo of output
00070 PRINT A$ ! should print "AT"
00080 LINPUT #3: A$ ! get response from serial port/modem
00090 IF A$ = "" THEN PRINT "No response yet" !:
GOTO 80 ! no input, just keep trying
00091 !
00095 ! some response was received
00100 PRINT A$ ! should print "OK"
00110 IF A$ = "OK" THEN PRINT "Modem initialization is OK" !:ELSE PRINT "Response was ";A$ !:PRINT "Now in PAUSE mode  - type GO to try again" !:PAUSE !:GOTO 50 ! try initialization string again
00114 !
00115 ! modem is OK, now dial number
00120 PRINT #3: "ATDT";NUMBER$
00130 LINPUT #3: A$ ! read echo of output
00132 PRINT A$ ! BBS at ABCDS should be "ATDT16123319012"
00135 !
00140 CLOSE #3: ! keep line open, change to 15 second wait
00150 OPEN #3:"name=com1:,format=async,wait=15",DISPLAY,OUTIN
00160 LINPUT #3: A$ : PRINT A$ ! dial complete
00170 IF A$ = "DIAL COMPLETE" THEN GOTO 180
00172 PRINT "Dial not complete yet" : GOTO 160
00175 !
00176 ! next response should be RINGING or BUSY
00180 LINPUT #3: A$
00190 PRINT A$ ! expect RINGING, BUSY or garbage
00207 IF A$ = "RINGING" THEN GOTO 240
00208 IF A$(1:4) <> "BUSY" THEN GOTO 120 ! unexpected response
00210 FOR I = 1 TO 17000 ! BUSY, wait awhile, then re-dial
00220  NEXT I
00230  GOTO 120
00235 !
00236 ! next response should be CONNECT
00240 LINPUT #3: A$ : PRINT A$ ! CONNECT
00260 IF A$ <> "CONNECT" THEN PRINT "Not connected yet" !:
GOTO 240
00275 !
00276 ! after dialing is done, return to smaller wait interval
00280 CLOSE #3:
00290 OPEN #3: "name=com1:,format=async,wait=1",DISPLAY,OUTIN
00295 !
00296 ! loop to read incoming file
00300 LINPUT #3: A$ IOERR 320
00302 PRINT A$ ! echo input to screen
00305 IF A$="NO CARRIER" OR A$="CARRIER LOST" THEN !:
CLOSE #3,FREE: : GOTO 20 ! hang up, dial again !:
ELSE GOTO 300 ! loop back for more input
00315 !
00316 ! error handling routine
00320 IF ERR <> 4270 AND ERR <> 4271 THEN !:PRINT "PAUSE due to Unexpected Error ";ERR !:PAUSE
00330 PRINT "Enter error recovery command to be sent by modem"
00335 PRINT "Example: ATH0 = hang up"
00340 LINPUT A$
00350 PRINT #3: A$
00360 IF A$ = "ATH0" THEN CLOSE #3,FREE: ! hang up !:
ELSE RETRY

Record Processing

Linputs

For processing an entire record, LINPUT is preferred to INPUT unless the fields in the input data are separated by commas. Note that it is permissible to use LINPUT on strings longer than or shorter than the specified record length (RECL) regardless of the status of the EOL= parameter.

Inputs

The INPUT statement works the same with communications files as it does with disk files. Each record is received as with the LINPUT statement. The LINPUT statement is generally preferred for receiving data with communications files because the INPUT statement requires both that values be separated with commas, and that the complete I/O variable list be satisfied before the end of the record. After the I/O list has been satisfied, any extra values (fields) at the end of the record are ignored.

In the event that error 4271 occurs, LINPUT should be used to read the remainder of the record before INPUT processing is resumed. Using INPUT with files opened EOL=NONE is not recommended because INPUT is field oriented and EOL=NONE indicates character stream processing. With EOL=NONE, use LINPUT instead.

Print

When PRINT is used with communications files, data is output the same as with other display files (for example, to a printer or disk file). The EOL character(s) are output at the end of each record or after the number of characters specified by RECL= have been written, whichever comes first. If EOL=NONE is in effect, no characters are added.

Close

Advanced buffering occurs until a CLOSE statement is issued. When a CLOSE statement is processed, any output data in the buffer is transmitted. For example:

00940 PRINT #1: X$
00950 PRINT #1: Y$;
00960 CLOSE #1:

In line 00940, the data from X$ will be sent immediately because there is no ending punctuation (comma or semi- colon) to suppress line output. However, the data from line 950 will not be sent immediately because there is ending punctuation (semi-colon) on line 950. The CLOSE statement in line 960 will clear the buffer by forcing all remaining data to be transmitted. The CLOSE statement also frees the space for buffers before control is returned to the program. If CLOSE FREE is specified then the telephone link is also disconnected. If CLOSE FREE is not specified, subsequent OPEN statements may access the line without redialing.