We ❤️ Open Source

A community education resource

5 min read

How slow was the Teletype?

Slow down the output of a program to see what it was like to use an original terminal.

For years, computers didn’t use networks to talk to one another; instead they “dialed up” other computers using a device called a modem which modulated and demodulated signals over a phone line, like whistling at different pitches.

The first modems were very essential with a speaker and microphone, and you socketed your phone’s handset into a special receiver with rubber pads that acted as sound insulation. These acoustic coupler modems were typically capable of transmission speeds of about 150 bits per second, called 150 baud.

An acoustic coupler modem.
Photo of an acoustic coupler modem (image: Rama, CC-By-SA), source WikiMedia Commons.

This worked well for terminals of the era, like the Teletype Model 33, which could print at about 10 characters per second. Ken Thompson created Unix at Bell Labs using a Teletype 33. Later, Bell Labs upgraded to the Teletype Model 37, which could print in both uppercase and lowercase letters, and included a limited set of mathematical symbols—useful for printing scientific documents. The Teletype Model 37 ran slightly faster at 15 characters per second.

Photo of the Teletype Model 33.
Photo of the Teletype Model 33 (image: Jim Hall, CC-By-SA)

Doing the math: If we assume 1 byte per character and 8 bits per byte, we can convert “characters per second” to “baud” by multiplying by 8, or convert “baud” to “characters per second” by dividing by 8. For example, if the Teletype 37 could print 15 characters per second, that’s about 15 × 8 = 120 baud.

In an era where home Internet speeds might be 25 Mbps, or 25 mega bits per second, it’s hard to imagine computers running as slow as 120 baud. To see what “120 baud” looked like, we have to do some trickery at the terminal to effectively slow down the output of a program.

Slowing down the output

Printing to a terminal app window is almost instantaneous, but we can simulate this slower transmission speed by inserting a pause between printing each character. To convert “baud” into “seconds per character,” we just invert the math. Given a baud rate of “120 baud” (the printing speed of a Teletype Model 37 terminal) we can divide 8 by the baud rate, and wait that many seconds between printing each character. So to simulate “120 baud,” we need to wait 8 ÷ 120 = 0.0666 … seconds between each character.

The unistd.h library has a function called usleep which pauses for a certain number of microseconds. This is enough for us to emulate slower modem speeds from back in the day. At 1,000,000 microseconds in one second, the math is 8,000,000 ÷ 120 = 66,666 microseconds delay between printing each letter to simulate the “120 baud” printing speed of the original Teletype Model 37.

With this conversion, we can write a short C program to simulate any baud rate, by displaying the contents of a file. The pseudocode for this program is this:

  1. Convert “baud rate” to microseconds
  2. Read a file from standard input
  3. For each character in the file:
    • Print the character
    • Wait for the “microsecond” delay

Converting to microseconds

Programs are more flexible if they can take options from the command line. For this program, assume the first command line option is the “baud rate” that we need to simulate. We can use atoi to convert this string into an integer, or atol to convert the string to a long integer. After that, we only need to divide 8,000,000 by the “baud rate” to get the microsecond delay. A simple implementation might look like this:

int main(int argc, char **argv)
{
   long baud;
   useconds_t udelay;


   if (argc >= 2) {
     baud = atol(argv[1]);
   }
   else {
     baud = 120;
   }


   udelay = 8000000 / baud;


   return 0;
}

This tests if the command line has at least one option. The argument count or argc will be 1 if there are no options, because the argument vector or argv will only contain the name of the program. Similarly, argc will be 2 if the command line has just one option, and so on.

Printing with a delay

Once we have the microsecond delay, we can use that when printing text to the screen. Let’s say the udelay variable has the value of 66666, which is the microsecond delay for 120 baud. A simple program to read from standard input or stdin and print to standard output or stdout, might look like this:

int main()
{
   useconds_t udelay;
   int ch;

   udelay = 66666;

   while ((ch = getchar()) != EOF) {
       usleep(udelay);
       putchar(ch);
       fflush(stdout);
   }

   return 0;
}

This uses the simple method of reading and writing one character at a time, which is usually slow for most file operations, but fast enough to simulate a very slow baud rate. Usually, the standard output will display the output one line at a time, because it “flushes” the output after each newline. To see each character as it is printed to the terminal, we need to use the fflush function to flush the standard output on our own.

A sample program

Using these examples, we can create a program that takes the “baud rate” as the first command line option, then prints each character with an appropriate delay to simulate that baud rate:

#include <stdio.h>
#include <stdlib.h>                    /* atol */
#include <unistd.h>                    /* usleep */

int main(int argc, char **argv)
{
   long baud;
   useconds_t udelay;
   int ch;

   if (argc > 2) {
       fputs("usage: baud [ baudrate ]\n", stderr);
       return 1;
   }

   /* get delay */

   if (argc == 2) {
       baud = atol(argv[1]);

       if (baud < 1) {
           fputs("baud rate too low\n", stderr);
           return 2;
       }
   }
   else {
       baud = 120;
   }

   udelay = 8000000 / baud;

   /* read from input, print to output */

   while ((ch = getchar()) != EOF) {
       usleep(udelay);
       putchar(ch);
       fflush(stdout);
   }

   return 0;
}

Save this file as baud.c and compile it using the GNU C Compiler:

$ gcc -o baud baud.c

See it in action

Because the program reads from the standard input, you can use this program as a filter to slow down how text is printed to the screen. For example, to display the contents of a file at 120 baud, you can use cat to read a file and display the contents with baud:

$ cat file | ./baud

But a more direct method is to use the “less than” operator (<) to redirect a file as the standard input to the baud program:

$ ./baud < file

About the Author

Jim Hall is an open source software advocate and developer, best known for usability testing in GNOME and as the founder + project coordinator of FreeDOS. At work, Jim is CEO of Hallmentum, an IT executive consulting company that provides hands-on IT Leadership training, workshops, and coaching.

Read Jim's Full Bio

The opinions expressed on this website are those of each author, not of the author's employer or All Things Open/We Love Open Source.

Register for All Things Open 2024

Join thousands of open source friends October 27-29 in downtown Raleigh for ATO 2024!

Upcoming Events

We do more than just All Things Open and Open Source 101. See all upcoming events here.

Open Source Meetups

We host some of the most active open source meetups in the U.S. Get more info and RSVP to an upcoming event.