Home .. Personal .. ARTICLES .. Software .. MUD .. Links .. Search

AUTO BAUD RATE DETECTION
by Eddy Carroll, April 1989

The following discussion explains how it is possible to determine the baud rate of a serial terminal by examining a single character received from that terminal.
   The character used here is the RETURN character, since its binary pattern has certain desirable properties (and it's also a nice big key for people to hit). However, the technique described here can be applied to other characters.
   The approach we use is to set the receive baud rate to 9600 baud and wait for a character to be received from the terminal. The baud rate this character is being transmitted at can fall into one of three main categories:
            Baud > 9600
            Baud > 1200 and Baud <= 9600
            Baud < 1200
These three cases are handled separately as follows.

Analysing a Return character
The binary pattern for a RETURN character (0x0D) as transmitted over the serial line looks like this:

            0 1 0 1 1 0 0 0 0 1
            | \_____________/ |
            |    Data bits    |
          Start              Stop
           bit               bit

(The least significant data bits are always transferred first.)
   The time taken to transmit each bit, T, depends on the baud rate. T19200 = T9600 / 2 for example. Thus, in the time taken to transmit a single bit at 9600 baud, two bits could be transmitted at 19200 baud.
   Similarly, If two bits are transmitted at 9600 baud, only a single bit can be transmitted in the same time at 4800 baud. If the receiver is using a fixed rate of 9600 baud, it will interpret the RETURN character in a variety of ways, depending on what speed it was transmitted at. The following table describes this:

 Baud  Bit pattern received at 9600 baud        Byte
19200  01011000011111111111                     0xF?
 9600  0 1 0 1 1 0 0 0 0 1                      0x0D
 4800  0 0 1 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1  0xE6
 2400  0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1  0x78
 1800  0 0 0 0 0 x 1 1 1 1 x 0 0 0 0 0 1 1 1 1  0xE0
 1800  0 0 0 0 0 x 1 1 1 1 x 0 0 0 0 0 1 1 1 1  0xF0
 1200  0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0  0x80
  600  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1  0x00
  300  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00
  150  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00
  110  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00

With the exception of the entries for 19200 and 1800 baud, all these bit patterns are exact transformations of the pattern for 9600. The first ten bits of each pattern correspond to a complete byte at 9600 baud, and this byte is listed in the Byte column in the table above. The absence of a '1' stop bit in some of the patterns will cause a Frame Error to occur, but this can be ignored -- the byte received will still be as shown.
   Thus, if RETURN is pressed at 1200 baud, the receiver at 9600 baud will receive the byte value 0x80. All the bytes are unique, so that it is possible to uniquely determine the baud rate.
   19200 is slightly different, since every two bits sent at 19200 baud are interpreted as a single bit at 9600 baud. The bit pairs 01 and 10 could be interpreted as either a 0 or a 1, depending on the serial hardware. Fortunately, only bits 0-4 exhibit this problem, with the remainder being set to a 1.
   Thus, at 9600 baud, the high nibble of the byte received will always be 0xF. The low nibble could be one of several values, but it will not be a 0, since there is a pair of adjacent 1 bits which will cause at least one 1 to appear in the low nibble. So, the entire byte will be of the form 0xF?, where the low nibble is not 0.
   At 1800 baud, things are slightly complicated by the fact that T1800 = T9600 * 16/3. Hence, transitions from 0 to 1 do not take place on bit boundaries with respect to 9600 baud. The table shows that exactly one such transition occurs within the first 10 bits, and so by allowing two possibilities (depending on whether the bit at that position gets interpreted as a 1 or a 0), one of two bytes will be received when the transmit speed is 1800 baud.
   A similar technique could be applied to speeds of 3600 and 7200 but the number of 'unstable' bits would increase, and result in more combinations to check. Since baud rates of 3600 and 7200 are almost never used anyway, this is not a major problem.

Detecting slower baud rates
We can now uniquely distinguish between all the speeds from 19200 to 1200 baud on the basis of a single byte received. Speeds below 1200 baud however all return a byte of 0x00, so while we can detect that the speed is below 1200, nothing more can be determined from the byte value alone.
   To get around this problem, we simply wait for the next byte to be received at 9600 baud. Since each bit transmitted at low speeds corresponds to at least one complete byte at 9600 baud, each transition from 1 to 0 will cause the serial hardware to appear receive a new byte at 9600 baud.
   Let's look at the start of our RETURN character again, for rates less than 1200 baud:

Baud    Bit Pattern at 9600 baud    Delay   Time
 600     16 0's   16 1's   16 0's     32   3.33 ms
 300     32 0's   32 1's   32 0's     64   6.66 ms
 150     64 0's   64 1's   64 0's    128  13.33 ms
 110     87 0's   87 1's   87 0's    174  18.13 ms
  75    128 0's  128 1's  128 0's    256  26.66 ms
  50    192 0's  192 1's  192 0's    384  40.00 ms

At 600 baud, the first transition from 1 to 0 occurs immediately, and this is what triggers off the initial 0x00 byte we receive. The next transition occurs exactly (16 + 16) * T9600 seconds after the initial transition, and this will cause the serial hardware to think another byte is about to arrive.
   The serial hardware tells us the first byte has arrived exactly 10 * T9600 seconds after the first transition, and tells us about the second byte (16 + 16 + 10) * T9600 after the first transition. Hence, the delay between the first and second bytes arriving when the transmission speed is 600 baud is (16 + 16 + 10 - 10) * T9600 seconds, which is 32 * T9600 seconds.
   The number of T9600 periods which pass is shown in the Delay column in the table above. T9600 is actually 104.16 microseconds, so multiplying these together gives us the actual delay in seconds between the two bytes. This is listed in the final column.
   Armed with this information, we can now easily determine the transmission baud rate: simply time the delay between the arrival of the first and second bytes, then scan a table of time constants to see which baud rate it most closely matches. This approach allows the timing to be a little off while still producing an accurate estimate of the baud rate.

An algorithm for auto baud rate detection
Now that we know how to detect all the baud rates, we can present a complete algorithm that combines all the techniques just described:

;
;   Pseudo code to determine what baud rate a
;   transmitter is at, on the basis of a single
;   RETURN (0x0D) character received from it.
; 
;
Initialise receive baud rate to 9600
Wait for Byte to be received

IF Byte = 0x00 THEN
    Start Timer
    REPEAT
    UNTIL (Timer > 50 ms OR New Byte Received)

    CASE Timer IN
         1 ms - 4  ms:  --> 600 Baud
         5 ms - 10 ms:  --> 300 Baud
        11 ms - 15 ms:  --> 150 Baud
        16 ms - 22 ms:  --> 110 Baud
        23 ms - 32 ms:  -->  75 Baud
        33 ms - 49 ms:  -->  50 Baud
                 ELSE:  --> Timed out; reset
    END CASE;
ELSIF Byte >= 0xF1 THEN
    --> 19200 Baud
ELSE
    CASE Byte IN
        0x0D: --> 9600 Baud
        0xE6: --> 4800 Baud
        0x78: --> 2400 Baud
   0xE0,0xF0: --> 1800 Baud
        0x80: --> 1200 Baud
        ELSE: --> Line noise; reset
    END CASE
END IF

Home .. Personal .. ARTICLES .. Software .. MUD .. Links .. Search

Last updated 26 November 2000. Comments to ecarroll@iol.ie.