Turbo Pascal Communications Library 1.0 Introduction Turbo Pascal provides a fairly uniform programming environment for a variety of microcomputers running CP/M and MS-DOS. It is fast, and the differences between versions can, in general, be worked around. Certain areas are a problem, however - communications, and system dependent function. This set of routines is intended to address the first of these problems, difficulty in communicating with the outside world. Each operating system is different in the way it handles communications, and different hardware implementations create problems when trying to use communications ports. There is a need for a standard set of routines that provide the basic communications needs for most programs. If the routines are rewritten for various micros, generalized communications programs can be written. Any programming tricks can be used to perform the actual functions, but a uniform calling sequence can be used. 1.1 Sample Programs A sample communications library is available as 'CLIB180.INC'. This library includes an example of each function and procedure listed below. Some of the functions are very simple, as the VT180 has PSETUP available to set parity and/or baudrates. CLIB180 also supports the RAINBOW (100A,100B) running CP/M version 2 or higher. A sample of the use of the communications library is given in the program 'COMDEMO.PAS'. This program implements a 'connect' mode and allows simple file transfer by capturing data from the communications port and storing it in a file, or sending a file to a remote system. COMDEMO.PAS was written as a 'test-case' for CLIB180.INC - it's also useful as the "first piece" to "customize" a "text-capture" utility for a new micro-system, which doesn't have yet a way to "talk protocol". TURBO-Pascal's inherent compilation-speed and (relatively high - see above) portability will help in getting the "first" and "crucial" step accomplished : Enable TEXT-capture "to" and "from" another system. The typical "next step" seen is to establish an (preferably) Error-Correcting protocol like KERMIT. 2.0 General Library Description 2.1 Variables, Constants, and Typed Variables All library functions, procedures, and global variables begin with 'c_'. This should minimize collisions with other program variables. Any variables that begin with 'c__' are for the use of the library itself, and should NEVER be modified by the main program. All variables required by the library only should be included here. This would include such variables as IOBYTE definitions for CP/M, etc. The following are predefined types, constants, and variables in the library: Types c__string10 = string[10]; c__string5 = string[5]; c__port_names = an array of string10's that will list the possible ports for the computer. c__baud_names = an array of string10's that will list the possible baud rates for the computer. c__parity_names = an array of string10's that will list the possible parity settings for the computer. Constants c_lib_version = computer type, revision of library, and date. c_port_str = all possible strings that the available ports are equivalent to. The first two MUST be 'NOT SET' and 'DEFAULT'. After all ports are defined, the last element in the array MUST be null (''). c_baud_str = all possible strings that the available baud rates are equivalent to. The first two MUST be 'NOT SET' and 'DEFAULT'. After all baud rates are defined, the last element in the array MUST be null (''). c_parity_str = all possible strings that the available parity settings are equivalent to. The first two MUST be 'NOT SET' and 'DEFAULT'. After all ports are defined, the last element in the array MUST be null (''). Variables c_kbd_char : The returned keyboard character. c_comm_char : The returned comm port character. c_current_port : The number of the current port. the string equivalent of the port number is : c_port_str(c_current_value). c_current_baud : The number of the current baud rate. The string equivalent of the baud rate is : c_baud_str(c_current_baud). c_current_parity : The number of the current parity setting. The string equivalent if the parity is : c_parity_str(c_current_parity). 2.2 Functions 2.2.1 C_INIT Initialize a communications port. Initialization is system dependent, but should include such items as setting hardware specific values, obtaining the initial value of the IOBYTE in CP/M systems, etc. It should be run at the beginning of each program that uses the communications library. The way the port, baud rate, and parity variables are set up, executing c_init(1,1,1) will set up a default communications port. This is a good way to begin any program so the at least some communication port is initialized. For some systems, having no port set up will cause system hangups. c_init(port, baud, parity : integer) : boolean; Inputs : port - Number of the port. This can be obtained by scanning the list of ports contained in the array c_port_str. parity - desired parity setting on port. The number of the available parity values for the particular computer. These can be obtained by scanning the list of parity settings available in the array c_parity_str. speed - desired port speed. The number of the available baud rate settings can be obtained by scanning the list of available baud rate settings in the array c_baud_str. Output : Function returns TRUE if the desired setup is valid, and FALSE if the setup is invalid. Variables affected : c_current_port, c_current_baud, and c_current_parity are set to their new values if the operation was successfull. Other effects: depends on implementation. 2.2.2 C_SET_PORT Select the desired communications port. c_set_port(port : integer) : boolean; Input : port - Number of the port. System dependent. A list of the available ports can be found in the array c_port_str. Output : Function returns TRUE if new port was selected, and FALSE if the new port was an invalid port. Variables affected : sets c_current_port, c_current_baud, and c_current_parity to those for the new port. Other variables are system dependent. Other effects : current port should not be changed if function returns FALSE. 2.2.3 C_SET_PARITY Set the parity on the current port, if possible. c_set_parity(parity : integer) : boolean; Input : port - Number of the port. System dependent. A list of the available ports can be found in the array c_port_str. parity - desired parity setting on port. The number of the available parity values for the particular computer. These can be obtained by scanning the list of parity settings available in the array c_parity_str. Output: Function returns TRUE if the parity is reset to the new value, and FALSE if the parity could not be set. Variables affected: c_current_parity is changed to the new parity if the operation was successfull. Other variables are system dependent. Other effects: should leave same parity if result is FALSE. 2.2.4 C_SET_BAUD Set the baud rate on the specified port, if possible. c_set_baud(speed : integer) : boolean; Inputs : speed - desired port speed. The number of the available baud rate settings can be obtained by scanning the list of available baud rate settings in the array c_baud_str. Output: Function returns TRUE if the baud rate can be set and FALSE if the baud rate cannot be set. Variables Affected: c_current_baud is set to the number of the new baud rate if the operation successfull. Other variables are system dependent. Other effects : Should leave the baud rate the same if error. 2.2.5 C_GET_KBD_CHAR Check the keyboard for an available character. c_get_kbd_char : boolean; Input : none. Output : Function returns TRUE if a character is available and false if no character is available. Variables affected : c_kbd_char is changed to new character if function returns true. Other effects : function must always leave the computer in the same state as it was found, i.e. for CP/M the IOBYTE must be returned so that CON: is set to main console. 2.2.6 C_GET_COMM_CHAR Check the currently selected communications port for an available character. c_get_comm_char : boolean; Input : none. Output : Function returns TRUE if a character is available and false if no character is available. Variables affected : c_comm_char is changed to new character if function returns true. Other effects : Function must always leave the computer in the same state as it was found, i.e. for CP/M the IOBYTE must be returned so that CON: is set to main console. 2.3 Procedures 2.3.1 C_PUT_SCR_CHAR Send a character to the console screen. c_put_scr_char(character : char); Input : character to be output. Output : none. Variables affected : none. Other effects : Function must always leave the computer in the same state as it was found, i.e. for CP/M the IOBYTE must be returned so that CON: is set to main console. 2.3.2 C_PUT_COMM_CHAR Send a character to the selected communications port. c_put_comm_char(character : char); Input : character to be output. Output : none. Variables affected : none. Other effects : Function must always leave the computer in the same state as it was found, i.e. for CP/M the IOBYTE must be returned so that CON: is set to main console. 3.0 VT180 Communications Library This is an implementation of a standard set of routines for communications, for the DEC VT180 (Robin). The VT180's main features are as follows: Microprocessor: Z80A Memory: 64k bytes Operating system: CP/M-80 Communications ports: 4 serial CRT: hard-wired terminal port to VT100 terminal LPT: printer port UC1: user defined console port PTR: high speed reader port PTP: high speed punch port The VT180 uses the Digital Research standard IOBYTE for port switching. 3.1 The IOBYTE A few words about the IOBYTE are in order. The ports on a CP/M-80 computer are described by PHYSICAL names (CRT:, LPT:, etc.). When the IOBYTE is used, they are mapped to LOGICAL ports, and the IOBYTE allows reassignment of the physical ports to different logical ports. For example, on the VT180, the pysical ports UC1: and CRT: can be assigned to be the logical port CON:. When booted normally all console I/O goes to CRT:, the internal VT100 port. If desired, the UC1: port can be assigned to be CON: and an external device can act as the system console. I use this method with a modem so I can dial up my computer and use the remote terminal as the console. The IOBYTE is the device that allows this reassignment of physical ports. The IOBYTE is a byte in memory, normally located at address 0003. This may vary in some implementation of CP/M. There are four fields to the IOBYTE: LIST PUNCH READER CONSOLE bits 6,7 bits 4,5 bits 2,3 bits 0,1 The values below are the possible IOBYTE assignments: Console field (bits 0,1) 00 console is assigned to the console printer device (TTY:) 01 console is assigned to the CRT device (CRT:) 10 batch mode, RDR: is console input device, LST: device is console output. 11 console is assigned to the user defined console (UC1:) READER field (bits 2,3) 00 reader is teletype device (TTY:) 01 reader is the high speed reader device (PTR:) 10 reader is user defined reader #1 (UR1:) 11 reader is user defined reader #2 (UR2:) PUNCH field (bits 4,5) 00 punch is teletype device (TTY:) 01 punch is high speed punch device (PTP:) 10 punch is user defined punch #1 (UP1:) 11 punch is user defined punch #2 (UP2:) LIST field (bits 6,7) 00 list device is teletype (TTY:) 01 list device is CRT device (CRT:) 10 list device is lineprinter device (LPT:) 11 list device is user defined list device (UL1:) Two of the serial ports on the VT180 can be used for serial communication, the READER/PUNCH port, and the UC1 (user defined console) port. From the chart above, setting the two least significant bits of the IOBYTE to 01 will allow normal console I/O to the VT100 terminal. Setting the same two bits to 11 will allow the UC1: port to be the system console. Working with the READER/PUNCH port is a little different. This is because the status of the reader port cannot be obtained directly with reader system calls. If a call to get character from reader is done, the routine will hang there until a character is available. This will not allow the alternating status checking required. However, there is a way. The reader port can be made the console port (IOBYTE value xxxxxx10). Now the status of the reader can be obtained without waiting. The characters received from the keyboard are sent to the punch port with a system call to punch output. 2.5.3 Eight Bit Data The Digital Research manual for CP/M specifies that the hight order bit of a character obtained with the CONIN bios call will be zero. This is not the case with the VT180. All 8 bits are significant. This allows binary data to be transmitted and received by the VT180. Other systems may vary. 2.5.4 Function Descriptions 2.5.4.1 Function C_INIT The c_init function sets up the intial values for the communications library. This function MUST be executed at the beginning of any program that will use the comm library. It initializes the iobyte settings, and sets up the default values for all the possible ports. On entry, it sets all the ports to their default values. Since the parity and baud rate on the VT180 cannot be easily set, DEFAULT is all that is allowed for these settings. The default port is the comm port, which is the normal VT180 comm port. If an illegal port, baud rate, or parity is requested, the function returns FALSE. 2.5.4.2 Function C_SET_PORT Two ports are allowed for the VT180. Valid values for port are 1, 2, and 3, yielding default (COMM), COMM, and UC1, respectively. 2.5.4.3 Function C_SET_BAUD In this version of the library, baud rates cannot be set, and the function will return FALSE if any value other than 1 (default) is requested. 2.5.4.4 Function C_SET_PARITY In this version of the library, parity cannot be set, and the function will return FALSE if any value other than 1 (default) is requested. 2.5.4.5 Function C_GET_KBD_CHAR This function uses bios(1) to obtain keyboard status and bios(2) to obtain a character. 2.5.4.6 Function C_GET_COMM_CHAR This function uses bios(1) to obtain port status and bios(2) to obtain a character. 2.5.5 Procedures 2.5.5.1 Procedure C_PUT_SCR_CHAR This procedure uses bios(3) to send a character the screen. 2.5.5.2 Procedure C_PUT_COMM_CHAR This function checks whether the selected port is the reader or the UC1 port and uses bios(5) to write to the punch port or bios(3) to write to UC1.