An exercise that contains lots of good stuff, including information on printers
In another place, the classic mechanical, Baudot-code teletypewriter is described. In this page, the construction of an emulator for such a teletypewriter is explained. The emulator could send to a mechanical teletypewriter, or receive from one, if this is desired, but the main reason for considering this exercise is that it involves a lot of interesting and instructive lore about commonly-found devices, such as keyboards and printers, and confronts the problems of code translation and interface handshaking as well.
There are four parts to the emulator: the keyboard, the printer, the code translation, and the circuits that connect them. Each is discussed below in that order.
Although the Cherry Pro keyboard, the PC-Write word processor, and the Panasonic KX-P1123 are used as concrete examples here, they will show what you can do with whatever keyboard, word processor and printer you may have available. It is not easy to go out and purchase these things today, but you may have them available or can find them second-hand. A printer is a big, interesting puzzle that is seldom used to the limit of its capabilities, and understanding it will help you use printers better. The first step, of course, is to obtain a good printer manual.
The keyboard is perhaps the most efficient form of human input to an electronic system. Our faculties are specially adapted to hand and finger movements (we can learn to type without having to think about it consciously, and some of us can play pianos). In fact, two-hand typing is an essential skill, the only one I ever learned in public school.
The principle of the electronic keyboard is shown at the right. It is essentially crossbar switching, or a key matrix. There are multiple rows "x" that may be connected individually to ground, and multiple columns "y" with pullup resistors as shown. When the keyswitch at the intersection of row x, currently grounded, and column y is pressed, the output voltage of column y goes from +5 to ground, which can be sensed by the controlling circuit, identifying the key that was pressed. For eight rows and eight columns, 64 keys can be employed. The controlling circuit is continuously grounding successive rows, and scanning the columns for each row, to detect a keypress. This can be done much more rapidly than a person can press keys.
At least two details must be considered. First, since the keyswitches are mechanical, they may "bounce" for a few milliseconds when pressed. The circuit testing the columns must read a column it finds low a second time to see if it is still low, to verify that the keypress is real, and not just a bounce of a previous keypress (computers are very fast, and could process a keypress and return while the key was still bouncing, so instead of A you would see AAA). An interval of 20 ms is usually sufficient for this "debouncing." The second problem is the simultaneous pressing of two or more keys. There is an order of priority established by the scanning sequence that normally takes care of this well enough.
A keyboard can be managed by a computer with ease. At the parallel port, we have 8 output data bits, and 5 input bits, which could scan an 8 x 5 key matrix handling 40 keys without further complication. A keyboard can also be managed by fixed logic, and present the decoded data without the aid of a computer. Computer keyboards are, in fact, managed by an embedded microcomputer that sends keypresses to the BIOS keyboard buffer using a keyboard interrrupt. I have a Cherry Pro B70-05AB keyboard with discrete logic. While a key is pressed, the ASCII code for the corresponding character appears at the output, while a strobe signal STB ouputs a positive pulse lasting 100 μs. There is also a complementary strobe output /STB. The 8th bit of the data is an even parity bit, which should usually be ignored.
An interface for the keyboard is shown at the left. Since the data disappears when the key is released, the data must be latched. A 74LS374 is appropriate for this task. The STB signal latches the output data so that it persists. The output enable /OE is shown tied high, so the output is permanently enabled. For a computer bus interface, this pin would normally be high except on a read cycle from the assigned address. A bidirectional parallel port can receive data from the latch as shown. The msb of the data can be hard-wired to 0 or 1, as desired. Most printers respond to all 8 bits, and give different results for the msb 0 and 1.
There is also a 74LS74 flip-flop used for handshaking. The same STB pulse that latches new data also causes the output of the flip-flop to go high. This is a "data available" or DAV signal that the computer can poll (sample repeatedly) to see when new data is available. When the computer reads the data, it also pulses the "data accepted" or DAC line low, which clears the flip-flop, making DAV 0. This two-line polling handshaking works very well, in cases where an interrupt would be wasted. To use an interrupt, the /STB signal would be connected to an interrupt request line. When a new character was available, the computer would service the interrupt and read the character immediately (in this case, a latch would not be necessary).
The serial-impact dot-matrix printer is a much simpler and cheaper device than the teletype printer with its type bars. It was made possible by the microprocessor, leading to much cheaper and faster printing. The small print head moves instead of the platen, and (usually) carries the inked ribbon with it. Together with the paper feed mechanism, these are the only mechanical parts, driven by two stepping motors. Serial-impact means that the letters are formed by vertical columns of pixels. The original printers had 9 pins, but 24-pin printers came in later and gave very good results. The inkjet print head is even simpler mechanically, using small spurts of ink controlled electrostatically instead of impact pins and a ribbon. Fanfold paper, a long strip 9-1/2" wide with sprocket holes (0.5" spacing) down each side that was laser-scored to peel down to 8-1/2 x 11, has been replaced by single-sheet feeders on recent printers.
Printers typically fill a print buffer and print out what is in it on receiving a carraige return. Data transfer is much faster than printing, so this saves computer time. To simulate a teletype, we would like a printer that prints each character as it is received. It is possible to do this by flushing the print buffer after each character. The printer I used here is the Panasonic (Matshusita) KX-P1123 24-pin dot matrix printer. This is an excellent printer making copy almost as good as an inkjet's, but the fanfold paper loading is diabolical. I also used an Okidata Microline 192, a 9-pin printer with IBM-compatible codes that is typical of earlier dot-matrix printers. In this page, we are talking about character-based printers, which accept a byte and then construct and print the corresponding character themselves. Most printers used now mostly accept graphic data from Windows, not individual characters.
The KX-P1123 and the 192 were furnished with manuals listing control codes and programming information, which is necessary for making full use of the printers. Some word processors need these codes so they can print intelligently to your printer. Recent printers, such as the HP-540 Deskjet, are not furnished with this information, though it is mentioned that a technical manual can be ordered, which probably is expensive and contains a lot of information one does not need to know. This seems mainly to be a business ploy to screw the user so that the software has to be obtained from the company. It is very easy to write printer drivers for simple uses, incidentally, especially for DOS. Another reason for this is not just weaselly greed, but that most computer equipment is now bought by "consumers" who don't know what they are doing, and don't care to find out--they just want it to work when plugged in, so that any information would be wasted on them. In line with this, the KX-P1123 has an elaborate front panel (that takes intelligence to operate), while the HP-540 has only an on-off switch and a button to press to restart is after running out of paper. Such printers are furnished with Windows drivers, which have not always been written correctly. It was easy to write DOS drivers, which acted like files you could send data to, and were loaded with the AUTOEXEC file when the computer was booted. One can actually send ASCII data directly to the parallel port quite successfully, bypassing DOS, BIOS and any drivers.
On the subject of HP printers, it is droll that the much-overrated company now derives most of its revenue from printers, having finally designed a product with consumer appeal that sold for a reasonable price. Now prices are climbing above those of competitors with excellent products, and ink cartridges are becoming equipped with chips that mark them as "empty" when they have been used once, and with terminal dates after which they will not be accepted by the printer. Most of the printer profit actually comes from cartridges, so this is understandable. One can always make more money in business by cheating people than by being honest, a fact not lost on businessmen, as we have recently observed. It's time for HP's printer bubble to burst.
It is tedious to investigate how a printer works with DEBUG, as will be seen below, so it is better to write a program (in C, for example) that can select different ports, report the status and control conditions on the interface, send individual bytes and strobe them in, type characters to send to the printer, flush the print buffer, and perform a number of other functions. My program can select superscript, subscript, underline, emphasized, double height, double width, character set, and a few other things as well. Making and testing such a program will verify that you understand how to control the functions, and will enable you to write printer drivers, at least for DOS. You will discover many surprises in how your printer works!
The KX-P1123 print head contains a vertical staggered column of 24 pins, 1/180" apart vertically, and 1/120" apart horizontally. The pins fire through an inked ribbon, making a dot on the paper. Since the pins are 1/127" in diameter, the dots made by them can overlap. The print quality is very good, and the dots are not seen in letter-quality printing. The size of the print head controls the size of the characters, which are usually 0.11" high, or 8-point (1 point = 1/72"). This leaves two rows of pins above and below, used for superscripts, subscripts and underlining. The normal line feed amount is 1/6", though any amount from 1/360" to 2" can be selected. This is handled by the paper drive, and can be programmed. The print head moves left to right or right to left, and can overprint any position. The printing is based on a pixel matrix, 24 x 11 for draft-quality and 24 x 37 for letter-quality. The printer is capable of graphics printing as well.
Letters are spaced horizontally at 10 c.p.i. (pica), 12 c.p.i. (elite), 15 c.p.i. (micron) and 17 c.p.i. or 20 c.p.i. (compressed). Pica spacing was the earlier rule, with 6 lines per inch. The difference between pica and elite is just the space between the letters (which can be programmed). This means that one 7" line can contain 70 pica, 84 elite, 105 micron or 140 compressed characters. The page length is 11" by default, but can be set for up to 22" as well as shorter. If 9" is used for printing, leaving 1" margins at top and bottom, there will be 54 printed lines. Therefore, one page of elite pitch text will require 4644 bytes. By comparison, 9" x 7" graphics with 72 pixels per inch would take at least 36,288 bytes, about 7.8 times as much. Page layout and line feed are important considerations in using a printer.
The parallel interface is the Centronics standard, which agrees with the original PC printer port. The printer has a female Centronics connector, while the printer port has a DB-25S connector. Special printer cables compromise between these connectors. If you simply plug in the printer to a parallel port and turn it on, it will usually work with any standard printing program, such as the PRINT command in DOS. To see that your printer works, connect it to a parallel port, say LPT2, and turn it on. Prepare a short ASCII text file with any utility, and call it, say TEST.TXT. At the DOS prompt, type PRINT TEST.TXT. DOS will ask you for what device, and tell it LPT2. It will tell you that it has installed the resident part of PRINT, and will then print out the file. This at least will tell you if the printer has been properly installed.
The parallel interface signals are the 8 data bits (input to printer), on pins 2-9, the data strobe /STB on pin 1 (input), the interfacing signals BUSY (inverted on pin 11) and /ACK on pin 10, both outputs, the printer reset signal /PRIME on pin 16 (input), the paper out signal PO on pin 12 (output), the SELECT signal on pin 13 (output) that signals that the printer is ON LINE, an /ERROR signal on pin 15 (outupt) that shows when the printer is offended, and finally an /AUTO FEED signal on pin 14 (input) that tells the printer to add a LF (line feed) after every CR (carriage return) automatically when low.
The handshaking is very important, since the computer is faster than the printer buffer, and the printer buffer is faster than the printing mechanism. Two signals are provided, BUSY for polling and /ACK for interrupt. Only one need be used and the other ignored. I will use BUSY here. The BUSY signal must read high (the level is inverted) when the printer buffer is ready to receive a new character. The normal initialization of the parallel port makes pin 16 low, which causes the printer to be in a reset state. Pin 16 must be pulled high for the printer to work. All other inputs and outputs can be neglected for the purposes of testing.
Let's suppose the printer is connected to LPT2, with base address 278. Start DEBUG. To initialize the printer, 04H must be output to 27a to pull /PRIME high, using -o27a 04. Read the status at 279 (i279) with /PRIME low, then high. A status of DE=11011110 is normal, and shows that the printer is on line, not in reset, and ready to receive a byte (the low 3 bits have no meaning). Put the byte 07 (all such numbers are hex here) on the data, with -o278 07. Nothing will happen. Now pull /STB low with -o27a 05, and you should hear the printer beep. Restore /STB with -o27a 04. This shows that data must be strobed into the printer. Characters such as 07 that call for some action by the printer are executed at once, and not put in the print buffer.
Now output 41 to 278. This is the ASCII for A. Strobe it into the buffer. You will observe that nothing happens (unfortunately for us). The printer has a 10KB buffer, enough for about 126 lines of 81 characters each. The computer could fill this buffer in a few seconds if it wanted to, and nothing would print. Only a few bytes cause the buffer to be printed. These are CR (carriage return, 0D), LF (line feed, 0A), FF (form feed 0C), BS (backspace 08), and the control sequences for line feeds of n/180 inches up and down. Output 0D to 278, then strobe it in. An "A" should appear, with the print head again at the leftmost position. The buffer is probably a circular buffer, with top and bottom pointers that move as characters are received and printed, respectively. This procedure means that the computer can transfer many bytes to the printer in a hurry, without waiting for each one to be printed. Unfortunately, this opposes our desire to see individual characters appear as they are typed, as would happen on an actual teletypewriter. This can be worked-around with the aid of a computer or equivalent.
The operation of a printer can be controlled by commands, called control sequences, or control codes, received in the data stream. The ASCII control characters, among which are found CR, LF, HT, FF and BEL, are single-byte commands that are executed, not printed, when they are received. More detailed commands begin with ESC (1B hex) followed by one or several bytes. Standard printer control codes were established by IBM with the PC, and were published in the Technical Manual. An "IBM-compatible" printer will recognize these commands, and will print the IBM-standard character sets 1 and 2, as selected. For some reason, manufacturers have deviated from this standard, changing some codes and introducing many new ones. The 192 is IBM-compatible, but the KX-P1123 can select either the Epson LQ-850 control codes (widely used), or the IBM Proprinter X24 codes, which are IBM compatible. The printer must be set to one or the other by front-panel controls.
The buffer can be flushed by outputting a space, 20, followed by backspace, 08, which will leave us where we were on the page. A control sequence will also work. For flushing the buffer and moving the paper n/180 inches up, the command is "J" followed by n, 0≤n≤255. We want no paper feed, so our flush command is ESC + J + 0, or 1b 4a 00.
Some functions can be done with "hardware" commands, as well as by control codes. For example, automatically adding an LF after CR (not in LQ-850 mode) or resetting the computer (ESC-@) can be done either by setting a bit in the control port byte, or by control codes. Taking the printer ON LINE and OFF LINE can also be done by ASCII DC1 and DC3, or by the front panel.
It is very tedious to enter this sequence manually, so we write a short routine in DEBUG to do it. This exercise will help when you write a C program. The routine should strobe in the byte currently on the data, then strobe in the control sequence. Subroutines are very convenient here. We need one subroutine to strobe in a byte (strb), one to output a byte (outb), and one to send the control sequence (flsh). The "outb" routine should first wait until the printer is not busy, then write the byte to 278, and strobe it out. The wait for "not busy" is absolutely necessary when sending multiple bytes. The computer can send bytes faster than the printer can eat them. The "flsh" routine simply calls "outb" once for each of the three bytes, while "outb" calls "strb" to strobe the bytes in. My routine was 55 (hex 37) bytes long, and used 26 instructions. It was saved as ponec.bin by using the DEBUG commands -nponec.bin and -w. CX was set to 0037 before the write command was executed. I cannot express how annoyed you will be if you forget to set CX and your disk fills up with a gigabyte of garbage.
If this routine is executed for a series of bytes (all you have to do is -g), they will each appear individually on the paper. This solves the problem of making the printer act like a typewriter. It is possible to avoid using a computer by making a sequential machine that strobes in a byte offered, and then strobes in the control code automatically following it.
If you turn on the KX-P1123 while pressing the LF and FF buttons on the front panel, it will come up in Hex Dump mode, where the incoming bytes will be printed in DEBUG-like format, instead of the usual text. This shows you what the printer thinks it is receiving. To exit this mode, cycle the power.
Keyboard and printer use the 7- or 8-bit ASCII alphabet, while the teletypewriter uses the 5-bit Baudot alphabet. We are not concerned here with the start and stop bits added by an asynchronous serial interface, which will be generated and received automatically by a UART, but only the bits identifying the character. The translation between codes is made interesting by the fact that they do not include exactly the same characters, and even more interesting because of the LTRS-FIGS shift of the teletype code. This means that each Baudot code corresponds to two, usually different, characters depending on the state of the shift mode. Reception of either LTRS (1F=11111) or FIGS (1B=11011) causes the state to change correspondingly. This means that there must be a flip-flop to remember the shift mode at the receiving end. At the transmitting end, the same Baudot code is sent for either shift state, and the receiver is depended upon to sort things out. In ASCII, there are two control characters called SI (shift in, 0F) and SO (shift out, 0E) which could be imagined to correspond to the same idea. Therefore, we use SI for FIGS, and SO for LTRS, on the keyboard, which will be translated to the corresponding Baudot codes at the other end.
A circuit to handle the shift is shown at the right. We note that FIGS and LTRS are the only two Baudot characters beginning and ending with 11. Only the middle bit distinguishes the two. Therefore, a 4-bit comparator such as the 74LS85 is sufficient, with the center bit controlling a set-reset flip-flop when the characters are recognized. The circuit is shown with LED's for testing. The ASCII characters ? and ESC are like FIGS and LTRS in their last five bits, and can be used for testing the circuit with the ASCII keyboard.
For once, the easiest way to solve our problem is not with a computer, though a computer can handle the translation easily and quickly. Instead, an EPROM can be prepared where the address is used to look up the corresponding code, and the data is the translation. For example, addresses from 00 to 1F can give the ASCII codes for the LTRS shift, while 20 to 3F can do the same for the FIGS shift. The output of the top NAND gate of the shift flip-flop can be used for address line A5. When this is 1, the FIGS translation is used; when it is 0, the LTRS translation. Going the other way, the locations from 80 to FF can be addressed by each of the ASCII codes with bit 7 set to 1, and the corresponding Baudot codes will appear on the data pins. These codes are not unique, of course, since the same code is used for different characters in the two shift states, exactly as in an actual teletypewriter.
The RS-232 serial interface is electrically very similar to a classic polar teletype circuit, so very little has to be done here. For details, see the page on serial communication. Buffers such as the 1488 and 1489 convert between mark and space line voltages and TTL levels. The bytes from the keyboard are supplied to the UART from a data latch after translation to Baudot, and the UART sends them to the line buffers. The AY3-1015D UART can send 5-bit data with 1-1/2 stop bits at 50 bits/s, just like a teletypewriter. The received code from the UART must be translated back into ASCII, and sent to the printer, each character followed by flushing the buffer, unless it is satisfactory to wait for a CR before a line is printed.
The original PC Asynchronous Communications Adapter could be programmed to emulate a teletype (5 data, 1-1/2 stop, no parity, 50 bits/s) using DEBUG, but this may not be possible with later adapters. The Borland C function bioscom() and the DOS 3.2 MODE command for initializing a serial port do not support teletype emulation.
I have used PC-Write, a "shareware" character-based word processor for the IBM PC, that first appeared in 1983, for a long time, but much less recently. It is still excellent for preparing straight ASCII files, and other such jobs--more capable and pleasing than Notepad. It is a well-written and almost bugless program that is a good example of character-based word processors. Its two parts, editor ed.exe (56 KB) and printer pr.exe (24 KB), are no larger than an average Word .DOC file, and can be stored anywhere they may be needed. Wordpad is 200 KB, and Winword is 5.2 MB, for comparison. Windows word processors like Word are graphic based, not character-based, and send graphics to the printer, not characters. This is extravagant of computing and data, but gives the excellent results we have come to enjoy. Here we will discuss character-based word processors like PC-Write, which depend on the printer to generate and print the characters.
In PC-Write, the editor (ed.exe) accepts input from the keyboard and adds it to a text file arranged as lines ending in CR-LF, which is displayed on the video screen. This results in WYSIAWYG--what you see is almost what you get. Different character sizes, pitches and fonts cannot be displayed as they will be printed, but as the character-based video BIOS displays them. However, lines, margins and centering are all faithfully represented. If you use only the "typewriter" keys, the result is a "straight ASCII" file of lines ending in CR LF that can be sent directly to a printer. As an editor, ed.exe allows you to enter and edit characters, copy, move and delete blocks, find and replace, and other typical editor actions.
However, to be a word processor, the program must control the printer to change fonts, emphasize text, and so forth, which is done by sending control codes to it that are embedded in the text to be printed. To do this, the editor interprets certain keystrokes as font controls. This is done in PC-Write by holding down the Alt key while typing in a letter A-Z, so there are 26 different choices. This combination inserts selected bytes with values between 00 and 1F in the text, that appear as certain odd characters on the screen. Whenever they appear in the file, they will be interpreted as font controls, so cannot be used for anything else. Important control functions are not used (CR, LF, etc), so nothing is lost if you do not want these funny IBM characters. Messages are also sent to pr.exe by ed.exe by "dot commands" that are a dot (".") followed by a letter or letters. The dot must be the first non-blank character on the line. For example, .P:W tells pr.exe to use the W font as the default font for the file. You can embed printer control codes in the text directly, if you wish.
The completed text file is sent to pr.exe for printing. Each byte is examined, and when font controls or dot commands are discovered, the necessary actions are taken, which usually means sending extra bytes to the printer. These extra bytes are taken from a table in the file ruler.prt that contains a list of the font letters, A-Z, with the corresponding control codes to be sent to the printer. These tables were supplied with the program for a number of printers, but are easy to create for any printer. For the KX-P1123, the .prt file contained 15 font controls, but I added 9 new ones to get 24 in all and modified a few that were originally there. This gives excellent control of the printer's capabilities, which go beyond those originally furnished. I wish I had studied this better when character-based printers were all that were available! This method allows the word processor to work with any printer simply by selecting the proper ruler.prt file.
On the PC, every byte from 00 to FF can be produced by keystrokes, and each is displayed on the video screen as an IBM graphic, the ones that include happy faces and card suit symbols. The bytes below 20 are produced by holding down Ctrl and typing a letter, while those above 7F are made by holding down Alt and typing a three-digit number on the numeric keypad. When selecting a font control, Alt+letter does not always give the same result as Ctrl+letter. For example, the L font is given by Ctrl-X, while the X font is given by Ctrl-M. It is ed.exe that interprets the Alt combinations, while BIOS interprets the Ctrl combinations. The BIOS receives keycodes from the keyboard, not ASCII characters, and these keycodes can be examined by any program, which can also use the translated characters available from BIOS in addition.
A text file is printed by submitting it to pr.exe. For example, pr mytext.txt lpt2 reads mytext.txt and outputs it to LPT2 (if the destination, port or file, is omitted, it defaults to PRN = LPT1). The font controls and dot commands are interpreted by pr.exe. The file does not have to be created by ed.exe, so you can add font enhancements to any text file using DEBUG. An easy way to create an ASCII file is with the DOS command COPY. Begin with C>copy con mytext.txt, which will create a file mytext.txt if it does not already exist and accept input from the keyboard. The end of file must be marked with Ctrl-Z (hex 1A). The next time you press Enter, the file will be written and the command exited. COPY automatically adds CR LF when you press Enter, and may respond to some control bytes (like ESC, 1B) in ways you do not want. It is happy with typewriter keys, and you can backspace to correct errors.
The DOS command PRINT will send a file to a printer. The first time you use this command, it will ask for the device to be used. Respond with LPT1, LPT2 or whatever you want. PRINT adds a FF (form feed) to the end of the file, just like pr.exe, so if you PRINT a file produced by pr.exe, you will get two blank pages at the end. Also, pr.exe seems to add a number of useless 0D 0A newlines to the end of a file. These, and the final FF (0C), can be trimmed off in DEBUG.
Bob Wallace, PC-Write, ver. 2.5 (Seattle, WA: Quicksoft, 1985).
___________, Operating Instructions, Impact Dot Matrix Printer KX-P1123 (Secaucus, NJ: Panasonic Communications & Systems Company, no date).
Composed by J. B. Calvert
Created 10 August 2002
Last revised 24 August 2002