Perhaps more than any other type of software, communications programs are surrounded by an aura of mystery. If you've done any kind of programming you probably have a good idea what it is to write a word processing, database management, or spreadsheet program. Sure it'd be tough, but at least you know generally what's involved. Communications programs are not quite like that. The typical communications program puts such a heavy layer of software between you and the modem that its inner workings are often obscured. Part of the problem results from the fact that communications soft- ware works in such close interdependence with the modem. Since the modem itself is programmable, the software is written to let the modem do part of the job. In one way, of course, that makes communications program simpler. unless you know what the modem is capable of doing, however, it may make understanding the related communications program more difficult. By letting your modem do its own thing, it's possible to write rudimentary communications programs with only a few lines of code. I'll show you how. Doing so, in fact, will help you both to explore the functions built into the modem and to discover how such small communications programs must be supplemented to provide the functionality of larger ones. THE TINIEST COMM PROGRAM Figure 1 shows how you can use DEBUG to create TINYCOMM, which i belive to be just about the smallest possible "functional" assembly language communication program. It's 49 bytes long. You'll see later the reason for the qualifying quotation marks when I call it "functional". TINYCOMM has many limitations, but, by strpping one part of the software/modem connection to the bare bones, TINYCOMM will help you explore some of the factors involved in modem communications software. =============================================================================== debug -A XXXX:0100 MOV DL,[005D] ; GET PARAMETER XXXX:0104 AND DX,0001 XXXX:0108 MOV AH,03 ; GET COMM STATUS XXXX:010A INT 14 XXXX:010C TEST AH,01 ; IF NOTHING, GO ON XXXX:010F JZ 011F XXXX:0111 MOV AH,O2 ; READ CHARACTER XXXX:0113 INT 14 XXXX:0115 PUSH DX XXXX:0116 MOV DL,AL XXXX:0118 MOV AH,02 ; WRITE TO DISPLAY XXXX:011A INT 21 XXXX:011C POP DX XXXX:011D JMP 0108 ; LOOP AROUND XXXX:011F MOV AH,0B ; CHECK KEYBOARD XXXX:0121 INT 21 XXXX:0123 OR AL,AL XXXX:0125 JZ 0108 XXXX:0127 MOV AH,08 ; IF CHAR, READ IT XXXX:0129 INT 21 XXXX:012B MOV AH,01 ; SEND TO MODEM XXXX:012D INT 14 XXXX:012F JMP 0108 ; LOOP AROUND XXXX:0131 -N TINYCOMM.COM -R CX CX 0000 :31 -W WRITING 0031 BYTES -Q Figure 1; if you have DOS's DEBUG.COM on your floppy or hard disk, you can create a 49-byte communications program called TINYCOMM by simply typing the lines above, starting from the DOS> prompt. Do not enter the addresses (XXXX:XXXX)--DOS will do that for you. Further, you dont need to type the semicolons and the comments after them. =============================================================================== TINYCOMM uses the ROM BIOS Interrupt 14h to read incomming data from the modem and to write outgoing data to the modem. It uses DOS Interrupt 21h function calls to read what you type at the keyboard and to write to the display. (Interrupt 14h is documented in the BIOS listing contained in the TECHNICAL REFERENCE manuals for the PC, XT, and AT. Interrupt 21h is documented in the DOS TECHNICAL REFERENCE manual.) TINYCOMM first makes a status call to Interrupt 14h. If the status word returned in register AX indicates that the modem has received a character, TINYCOMM calls Interrupt 14h again to get the character, then displays it to the screen through DOS. If no character has been received yet, TINYCOMM goes on to check if anything has been typed at the keyboard. If so, it sends the typed character to the modem, again by Interrupt 14h. Then it goes back to the top. Notice that in both cases (reading the modem and reading the keyboard), TINYCOMM first checks if anything is ready. It doesn't want to get stuck waiting for a character from either source if none is available. To use TINYCOMM, first turn on your modem and execute the PC-DOS MODE command to set it up for 300 bps, no parity, 8 data bits, and 1 stop bit: MODE COM1:300,N,8,1 Do not try 1,200 bps just yet. If your modem is connected to COM2, use that instead of COM1 in the MODE command above. Now run TINYCOMM by entering: TINYCOMM for a modem connected to COM1, or TINYCOMM 1 for COM2. You're not on-line yet, but you are in direct connection with your modem. TALKING WITH YOUR MODEM If you have a Hayes Smartmodem or compatible, you can now type in any of the AT attention codes documented in the user's guide or reference manual that came with the unit. For instance, with the Smartmodem 1200 or 1200B, you can enter: ATI0 to see the product's revision number, ATI1 for the modem's ROM checksum, and (with the 1200 but not the 1200B) ATI2 to check the integrity of its internal memory. This last instruction will return either OK or ERROR. The "Smart" in Smartmodem refers to the modem's ability to interpret such AT codes and to send back appropriate responses. If your phone happens to ring while you're experimenting like this, TINYCOMM will display the word RING. Similarly, when using your normal communications programs, you may have noticed the words CONNECT or NO CARRIER displayed when you attempted to place a telephone call. These messages are not produced by your communications package; they all come straight from the modem, whose internal programming generates them. Now let's make a call to the PC Magazine Interactive reader Service bulletin board. To do this, enter ATD 212-696-0360 If you have Touch-Tone service, you can use ATDT instead of ATD. (Even if you only have pulse dialing, you might try this command anyway: at the risk of having the telephone company read this, I'll tell you that I dont have Touch-Tone service but I have been dialing modems with touch-tone for years.) If you have an external modem, You'll see your modem's OH (Off Hook) light go on and you'll hear the dialing. If the PC-IRS has a free line, you'll hear the PC-IRS carrier signal, quickly followed by your modem answering that carrier signal with its own. The CD (Carrier Detect) light on your modem will go on, you'll see the word CONNECT on the screen, and the the modem will go silent. you're on-line. (When you eventually want to break out of TINYCOMM, just press Cntrl-Break.) If you get a busy signal, eventually your modem will give up and you'll get a NO CARRIER message on your screen. You can redial by typing: A/ which is the only Hayes control sequence that does not require a preceeding AT. Notice that TINYCOMM is doing very little in establishing this connection. Almost everything is handled by the modem itself. After you enter ATD and the phone number, the modem waits a couple of seconds for the dial tone before dialing the number and, if it doesn't detect a carrier, waits another period of time before sending back the NO CARRIER message and placing the phone back on the hook. You can set these two timings and many other variable aspects of the Smartmodem with modem control sequences (see S Registers table). Specifically, ATS6, followed by the time in seconds, controls the dial-tone wait; ATS7 similarly controls the carrier-detect wait. If you want to listen continuously to the carrier signals while you're on-line, you can enter ATM2 before making the call. =============================================================================== S REGISTERS FOR HAYES-COMPATIBLE MODEMS REGISTER RANGE DESCRIPTION DEFAULT S0 0-225 rings Ring to answer telephone on 0 or 1* S1 0-63/0-225rings Signal quality/number of rings - S2 0-127 ASCII Escape code character 43(+) S3 0-127 ASCII Character recognized as 13(CR) carriage return S4 0-127 ASCII Character recognized as line feed 10(LF) S5 0-32,127 ASCII Character recognized as backspace 8(BS) S6 2-225 sec. Wait time for dial tone 2 S7 1-60 sec. Wait time for carrier 30 S8 0-225 sec Pause time caused by comma 2 S9 1-225 1/10 sec. Carrier detect response time 6 S10 1-225 1/10 sec. Delay between loss of carrier and 7 hang up S11 50-255 msec. Duration and spacing of Touch-tones 70 S12 20-225 1/50 sec. Escape code guard time 50 S13 bit mapped UART status register - S14 bit mapped Option register - S15 bit mapped Flag register - S16 0,1,2,4 Test modes 0 S-REGISTER TABLE; This is the S-Register set for the Hayes 1200.Any Hayes-compatible modem generally follows this command set. To set any of the registers, type ATS, the register number, the value you want to store, and hit the Enter Key. For instance, To set the S0 (auto answer) register to not answer (to Hayes, not answer means answer after zero rings), type ATS0=0. =============================================================================== You can't enter these AT codes directly while you're on-line because the modem has no way of determining that you want to talk to it instead of the remote computer. To give commands while on-line, you first enter the Hayes escape sequence, which consists of three plus signs: +++ in a row typed quickly. You must wait a second before typing in the first plus sign, and wait a second afterwards before typing anything else. (The modem used these brief pauses to distinguish its escape sequence from three plus signs that may occur in transmitted data.) Having entered the +++ code properly, you'll get an OK from the moden indicating that you're in the command state instead of on-line. After you finish giving commands, ATO returns the modem on-line. if you want an escape sequence other than three plus signs, that too is programmable, as the Hayes manual explains. SPLIT-LEVEL DUPLEX You'll notice that the TINYCOMM program uses the DOS Function Call 08h for reading your keystrokes. According to the DOS Technical Reference manual, however, this function call does not echo keystrokes to the screen. So why then can you see your keystrokes as you type them? Some of the characters you enter at the keyboard will be modem AT control sequences. The modem itself echoes these characters back, so TINYCOMM reads them as characters coming from the modem. You can turn off this modem echoing with the command: ATE0 Then when you type an AT code, you won't see it on the screen. Turn this type of modem echoing back on with: ATE1 When you get on-line with a remote computer, however-whether it's an information service such as CompuServe, The Source, or Dow Jones News/Retrieval or with a bulletin board such as PC Magazine's IRS- the host computer echoes back most of the characters it receives. That's why you'll sense a slight delay between the time you type characters and their display on the screen. This echoing is often innacurately referred to as full-duplex communication. A better term is remote-echo or echoplex. It requires that the two computers handle data differently. On your end, your communications program is reading the keyboard and sending the characters out to the modem without echoing them to the display. The host computer to which you are connected sends most of these characters back to you (with a few exceptions) in addition to sending you its own data. On your receiving end, your program really can't tell whether a particular character was sent by the remote computer or echoed. If you also echoed back to the host computer everything you received, you'd really be thrown for a loop, because the characters would be continually tossed back and forth between the communicating computers. When you use a modem to communicate with another PC or some other small computer, you'll probably want to use local echo (often innacurately called half-duplex). With local echo, each communication program handles the data the same way: by echoing keyboard characters to the screen a they are being typed and sending them out to the modem at the same time. If you get on-line but find that you can't see what you type, it simply means that your software is set up for remote echo, but the computer you're talking with thinks you're using local echo. If you see two of every character you type, the cause is just the opposite. GETTING TWO PCs TALKING If you want to connect with another pc over the telephone lines, you'll probably want to use local echo. You can do this in one of two ways. First, you can change TINYCOMM to use Function Call 01 instead of Function Call 08 for reading from the keyboard. A better way, however, is to instruct the modem itself to echo what you type by entering the control sequence: ATF0 You can later return to remote echo by typing: ATF1 Another consideration that arises when two PCs are to communicate is the carrier frequencies. Two separate sets of frequencies are used by communicating modems. They are called "answer" and "originate" frequencies, but are really independent of which modem is making the phone call. When you call an information service or bulletin board, by convention your modem uses the originate frequencies. When you connect with another PC, however, you must decide which PC will use answer and which will use originate. The easiest way to establish a connection between two PCs over the telephone lines is to first establish a voice communication. After you decide upon a common speed, data bits, parity, and stop bit and have everything set up, the person using originate frequencies enters ATD and the other person using answer frequencies enters ATA The answer carrier will sound first, then the tone from the originate modem. Now hang up the phone and start typing. At this point another consideration arises that must be addressed: the problem of line feeds. When you press the Enter key, you generate only one character-ASCII 13, the Carriage Return. When your screen receives this this character,its proper response is simply to move the cursor to the beginning of the current line. However, the carriage rturn code does not tell the cursor to move down to the beginning of the next line: to move the cursor down one line, you need a Line Feed character (ASCII 10). Most real communications programs will add the extra line feed, but TINYCOMM will not. Unless you want to change TINYCOMM to do this, you can get around it by typing a Ctrl-J (line feed) after every Enter. Or, instead of pressing Enter, you can press Ctrl-M and Ctrl-J Yes, you can get accustomed to it. THE AMAZING CTTY COMMAND When you use TINYCOMM to go on-line with another microcomputer, you'll have a chance to try out one of the most interesting DOS commands, CTTY. TINYCOMM is ideal for CTTY for two reasons. First, TINYCOMM will not break the modem connection when you leave it by using Ctrl-Break. Many other communications programs will. Second, unlike other communications programs, TINYCOMM just uses Interrupt 14h instead of doing anything fancy. You'll later see that this is a deficiency when it comes to more serious communications work. To try out CTTY, first use TINYCOMM to establish a modem connection with another microcomputer operated by a friend you would trust with your PC. This friend does not need to be using TINYCOMM or even an IBM PC. Now instruct your friend to turn off his/her local echo. Then, exit TINYCOMM with Ctrl-Break and at the DOS command level simply enter: CTTY COM1 (or COM2 if that's where your modem is). Your Dos prompt will then appear on your friend's screen and not on yours. If your friend enters DIR, you won't see it but your disk drives will whir, and the directory listing wil appear on the other computer's diplay. (Now you see why this person should be someone you trust. That Dir could just as easily be a DEL *.*). After your friend has been fully amused by using your PC over the telephone line, he/she can enter: CTTY CON At that point your DOS prompt will appear back on your screen, and you can reenter your on-line communication. WHAT'S GOING ON HERE? CTTY allows another device (in this case the communications port) to be substituted for DOS's normal standard input device (the keyboard) and standard output device (the screen). Any program that uses DOS function calls for keyboard and screen display will then use this alternative device instead of the default CON device. Any of the DOS internal commands (with the exception of CLS) will work, as well as most of the DOS programs such as CHKDSK, EDLIN, and DEBUG. If your friend tries to run Lotus 1-2-3, however, it will appear on your screen and accept input from your keyboard. This is because 1-2-3 (like most spreadsheet and word processing programs) does not use DOS for keyboard input and screen output. The BASIC interpreter also deos not use use DOS for keybaord and screen and will not work with CTTY. For a rel treat, If your friend's communication program supports terminal emulation (ANSI or VT-100, for example), you can patch Wordstar to tell it that it's not running on an IBM-PC, in which case it will use DOS for the keyboard and screen. you then patch Wordstar to use screen control sequences for positioning the cursor and anything else the terminal emulation program allows. Your friend can then use Wordstar over the telephone lines, even on a Macintosh (on a Macintosh?). To work with Wordstar at a 300-bps screen update rate is a facinating experience and one that will allow you to catch a few winks after every Ctrl-C (Page Down). THE LIMITATIONS OF TINYCOMM When I introduced TINYCOMM above, I said it would produce some problems. If you've been using it to communicate with information services or bulletin boards, you've probably already notices some of these oddities. Although TINYCOMM is programmed in assembly language and thus, in theory, is vey fast, you can't use it at 1,200 bps. Don't beleive me? Try it out by changing the bps setting with MODE and connecting to an information service or bulletin board. If you start at the top of the screen, things seem to go fairly well at first, but once you get down to the bottom of the screen, you'll notice that TINYCOMM starts missing the first few letters of each line that is sent from the remote computer. COmmunications programs do not normally use Interupt14h, as TINYCOMM does. This is because Interrupt 14h is missing two very important ingredients of normal communications software: buffering and interrupt control. Instead, TINYCOMM simply polls the serial port for data, and if it can't do it's polling fast enough, it misses characters. This is what happens when the screen scrolls at 1,200 bps. During the time it takes the screen to scroll, several characters at the start of the line are coming through. Real communications programs don't have this problem because they use the serial port's interrupts and buffer all the data. Let's see how this works. THE UART PORTS The Interrupt 14h code in the ROM BIOS is not very big as assembly language goes-just a bit over two pages in the Technical Reference manual. It works by accessing the 8250 UART (Universal Asynchronous Receiver Transmitter) through I/O ports. These ports are at addresses 3F8h through 3FFh for COM1 and 2F8h through 2FFh for COM2. Where you can find documentation on these serial I/O ports depends upon what type of modem you have. The Hayes 1200B internal board modem comes with a Hardware Reference Manual that discusses the ports in detail, since the UART is part of the board. The standalone modem connects by cable to an asynchronous communications port and the registers involved are also discussed in the documentation for the serial board in any of the Technical Reference manuals for the PC. If you are new to UART programming and want to learn how to do it right (instead of using Interrupt 14h), be prepared to spend many long hours with these few pages of documentation-studying the Interrupt 14h code until you understand every single line of it-and in doing lots of experimentation. The greatest advantage to programming the UART directly through the I/O ports is the ability to enable its interrupts. Instead of polling the UART status, as TINYCOMM does, a real communications program is driven by hardware interrupts. The uart can be programmed to generate an interrupt whenever it receives a character or is ready to send another character. A real communications program will also buffer outgoing and incoming data. When a new character is received, the interrupt routine stores it in a circular buffer. When the main communications program access incoming data, it retrieves it from this buffer instead of from the port. Similarly, typed keyboard input goes into another circular buffer. As the UART sends this data, it generates a hardware interrupt when it's done with one and ready for another. That way, the main program can shovel a lot of data to the buffer and not wait for the UART to transmit it all. (If you want to try programming something like this, you might also benefit from looking at the code for keyboard Interrupts 9 and 16h, in the ROM BIOS listing. That will show you how circular buffers work.) THE SOLUTION IS BASIC If we were to add direct UART programming, interrupt control, and buffering to TINYCOMM, it would not stay tiny for long. So let's change direction. Let's use some software supplied with PC-DOS that already has built-in data buffering and interrupt-driven communication logic. You didn't know you already had such software? Sure you do. It's all there in the BASIC interpreter. Figure 2 shows another simple communications program called BASCOMM. Let me say first that this program also has some deficienciies, some of which are repeated from TINYCOMM, some of which are new. Otherwise it works the same as TINYCOMM. You enter the modem control sequences directly nad press Ctrl-Break when you want to get out. =============================================================================== 10 OPEN "COM2:300,E,7,1" AS #1 15 OPEN "SCRN:" FOR OUTPUT AS #2 20 IF NOT EOF(1) THEN PRINT #2,INPUT$(1,1); 30 A$ = INKEY$ : IF A$ <> "" THEN PRINT #1,A$; 40 GOTO 20 Figure 2; A small comunications program written in BASIC. More sophisticated BASIC communications programs are shown in the IBM BASIC manual and included with PC-DOS (COMM.BAS). PC-Talk III is an example of an extremely sophisticated BASIC program. =============================================================================== The new problem you'll encounter is double spacing of all incoming lines of data. This is BASIC "helping" you out by sticking a line feed onto each carriage return. Unfortunately, in remote-echo communications, you dont want that extra line feed. You'll also notice (as you probably did with TINYCOMM) that at various times you'll see two odd characters appear on your display: the double exclamation point (ASCII 19 0r Ctrl-S) and the left pointing triangle (ASCII 17 or Ctrl-Q). These characters have formal ASCII names of DC3 and DC1. The DC stands for Device Control, but in modem communications they are more commonly referred to as XOFF and XON. When your communications program receives a Ctrl-S (XOFF) character, that is a signal to tell you that your program to stop sending data. The computer you are connected to is telling you (by sending XOFF) that is doing something else and may suffer a buffer overflow if you continue. Likewise, when the remote computer sends a Ctrl-Q (XON), it is signalling that it can resume receiving data from you. Your communications program might also want to send XOFF and XON to the remote computer. With the simple BASCOMM program, you can do that yopurself simply by pressing Ctrl-S and Ctrl-Q. Generally you stop the flow of data to give you time to read it. XOFF and XON become more important during ASCII file transfers. For instance, if you add some file-transfer logic to the BASCOMM program. you must send XOFF when beginning a disk access. This prevents a buffer overflow while you are using the disk. When you are done with the file access and have enough characters from the buffer to deplete it, you can then send an XON to signal that data transfeer may be resumed. BASIC has several other built-in functions that will help you manage the input buffer. these include LOC (which tells you the number of characters in the input buffer) and LOF (the buffer's free space). At this point, however, instead of fixing up BASCOMM to include these additional features, let me direct you to Appendix F of IBM's BASIC 2.0 manual or to Appendix C of the BASIC 3.0 manual. Under the heading"An Example Program," you'll find a 20-line BASIC program (documented with lots of comments) that handles both line feed problems and the XON/XOFF protocol. PC-DOS also comes with a free communications program called COMM.BAS. This one has a menu to set thte bps rate, parity, and data bits, but it's really just a fancy version of the small program shown in the BASIC manual. Once you print out COMM.BAS and get familiar with its workins, your next step can be to look at a real communications program written entirely in BASIC: the famous freeware program, PC-TALK III. If you use this program, you probably use the compiled version, but the 800 tightly coded lines of BASIC source code are available on many bulletin boards. IN PRAISE OF SMALL PROGRAMS Although it's tough to beat the power of several recent (and large) communications programs, such as Ascom or Microsoft Access, you may find a samller communications program is sometimes preferable-for the same reasons that people sometimes prefer riding a bicycle to driving a car. You're more in control, closer to the ground, unsheltered, and feel every bump. It's more adventurous and also, of course, much more fun.