The 1090 Megahertz Riddle (second edition)

A Guide to Decoding Mode S and ADS-B Signals
By: Junzi Sun (

Quick Start: Hardware and Software to Receive Mode S Signals

Chapter 1 introduced several fundamental concepts about Mode S communication. This chapter focuses on the practical aspects of acquiring Mode S data, specifically, how to receive and obtain messages that are transmitted in Mode S downlink communications. Mode S signals are transmitted using 1090 MHz radio waves. Hence, the receiver and antenna have to be designed to work with this frequency. Nowadays, all necessary components required to obtain the Mode S data can be easily made with low-cost off-the-shelf components. Several open-source software tools are available to support the extraction and decoding of data from Mode S signals. In this chapter, we explain how to step up a functional hardware and software system to receive Mode S data.


Since Mode S uses L band signals that follow the line-of-sight propagation, any obstructions between the transmitter and receiver can cause a significant amount of signals to be blocked. Assuming that no obstacle exists between the aircraft and the receiver, and the transmitter has a sufficient amount of power, the maximum range of the receiver is determined by the curvature of the earth. Figure 1.1 illustrates how the maximum range of the receiver can be obtained.

Knowing the altitude of the receiver antenna, it is possible to determine the maximum range (\(d\)) of a Mode S receiver as:

\[\begin{aligned} d &= (\alpha_r + \alpha_t) R \\ & = \left( \arccos \frac{R}{R+h_r} + \arccos \frac{R}{R+h_t} \right) R\end{aligned}\]

where \(R\) is the radius of the earth, while \(h_t\) and \(h_r\) are the height of the aircraft and receiver above the sea level. Using this equation, we can calculate the maximum receiving range for aircraft flying at different altitudes. Figure 1.2 shows the maximum range curves calculated using several receiver heights.

It should be noted that this figure shows the maximum radio range due to the curvature of the Earth. However, in real-life applications, Mode S signal follows the Friis transmission model, which states that the maximum distance also depends on the power of the transmitter, as well as the directivities of the transmission and receiving antennas. When considering these factors, the actual radio range for the receiver is typically lower than the theoretical values shown in the previous figure.


In principle, any antenna designed for the radio frequency around 1 GHz can be used for receiving Mode S signals. A large variety of commercial off-the-shelf antennas can be found nowadays.

However, it is not difficult to design your own antenna. The carrier frequency of Mode S is 1090 MHz, which corresponds to the wavelength of 27.5 centimeters. In order to have an antenna that is tuned to this specific frequency, one can design the antenna simply using a piece of a conductor (metal wire) and a coaxial feeder cable. Figure 1.3 shows a few common antenna designs.

The monopole antenna and the dipole antenna both are half-wavelength (\(\lambda/2\)) antennas with a total conductor length of 13.75 cm. The ground plane antenna is a quarter-wavelength (\(\lambda/4\)) antenna, where the main pole is 6.875 cm.

All these previous antennas are omnidirectional. Some time is also desirable to make use of directional antennas (such a Yagi antenna), for example, to receive messages coming from the airport direction with a higher receiving gain.

For a remote installation where the antenna is far from the receiver (i.e., long coaxial cable between the antenna and receiver), the high-frequency signal of Mode S can attenuate quickly. When the signal has arrived at the receiver end, the signal-to-noise ratio can become quite high. To overcome this limitation, an active antenna may be used.

The active antenna (see Figure 1.4) has a low-noise amplifier integrated on the antenna side. Sometimes, it also includes a band-pass filter that is designed for 1090 MHz. The active antenna requires additional powering. Power is commonly supplied through a bias-tee device connected at the receiver end, which is on the left-hand side of the diagram. On the right-hand side, the radio frequency is mixed with the DC component, which allows the electronic circuit to be powered close to the receiver end.


Many modern Mode S receivers are built using software-defined radio (SDR). An SDR usually can be tuned to a wide range of radio frequencies. The user can conveniently select the center frequency of the receiver and the sampling rate, as well as define the bandwidth of the onboard low-pass filter if it is supported.

For receiving ADS-B (and other types of Mode S message), a RTL-SDR is the most common type of low-cost receiver to choose. Many different brands of RTL-SDR receivers exist; they are often built with the Realtek RTL2832U chipset. It can work with radio frequencies from 24 to 1766 MHz. The maximum sampling rate is 2.8 million samples per second (MSPS). Given that a Mode S bit consists of a pulse cycle of 0.5 μs (see Figure [fig:mode_s_uplink_pulses]), the minimum SDR sampling rate required for Mode S is 2 MSPS. RLT-SDR devices just barely manage to meet this requirement.

Note The maximum frequency range of RTL-SDR can be from 0 to 2220 MHz. However, the sensitivity drops off significantly outside the 24 – 1766 MHz range. The sampling rate can actually go up to a maximum of 3.2 million samples per second, but some samples may be dropped at this sampling rate. So, it is not stable.

SDRs that offer a higher performance also exist. They often support a larger frequency range with higher sampling rates. Some offer multiple transmitting (TX) and receiving (RX) channels. Table 1.1 lists a few examples of common SDR devices. The performance of RTL-SDR is listed as a comparison.

Examples of common software defined radio devices
RTL-SDR AirSpy R2 HackRF 1 LimeSDR BladeRF 2
Frequency (from) 24 MHz 24 MHz 1 MHz 100 KHz 47 MHz
Frequency (to) 1766 MHz 1700 MHz 6000 MHz 3800 MHz 6000 MHz
Max sample rate 2.8 MSPS 10 MSPS 20 MSPS 61.44 MSPS 61.44 MSPS
RX channels 1 1 1 2 2
TX channels 0 1 1 2 2
Open hardware No Partially Full Full Partially

Software tools

Several software tools are available to work with some of these SDR devices and decode Mode S and ADS-B signals directly. In this section, we explain how to use two open-source tools, which are dump1090 and pyModeS.


dump1090 is the most well-known open-source Mode S decoder currently available. The software is written in C programming language and was originally developed by Salvatore Sanfilippo 1 under the BSD-3-Clause license.

Since its release in 2013, the repository has been forked and extended intensively on GitHub, creating more than 900 forks so far. Many of the branched versions contain different variations, such as support for additional hardware, additional decoded Mode S messages, and additional output format. Currently, one of the most comprehensive forks is the repository maintained by FlightAware.2 The following examples will be based on the FlightAware version of dump1090, using a Debian-based Linux system.

Installation of dump1090

The latest version of dump1090 source code can download as follows:

$ git clone

Before compiling the code, following dependencies must be installed:

sudo apt-get install build-essential debhelper librtlsdr-dev \
  pkg-config dh-systemd libncurses5-dev libbladerf-dev

Next, we can compile the source code as:

$ cd dump1090
$ make

It is worth noting that the FlightAware version of dump1090 supports both RTL-SDR and BladeRF devices by default.

Default usage of dump1090

Once it is compiled and the RTL-SDR receiver is connected, we can run the following command to start receiving and decoding signals:

$ ./dump1090

With the default option, Mode S messages and decoded information are displayed in the terminal. For example:

CRC: 000000
RSSI: -20.6 dBFS
Score: 1800
Time: 9214131.08us
DF:17 AA:451DBD CA:5 ME:9905B501800400
 Extended Squitter Airborne velocity over ground, subsonic (19/1)
  ICAO Address:  451DBD (Mode~S / ADS-B)
  Air/Ground:    airborne
  Ground track   271.4
  Groundspeed:   436.1 kt
  Geom rate:     0 ft/min
  NACv:          0

Raw Mode S messages

If we only want to display the raw messages, the —-raw option can be provided, as follows:

$ ./dump1090 --raw

In this case, the terminal output will only contain the raw messages, for example:


Interactive mode

dump1090 can also provide a live view of all aircraft seen by the receiver through the use of the —-interactive option:

$ ./dump1090 --interactive

An example of the terminal output is shown in Figure 1.5.

Example of a dump1090 interactive output


pyModeS is an open-source Mode S decoder project that I started in 2015. It is a library that was originally designed to focus on lower level inference and decoding of individual raw Mode S messages. Later on, hardware support and live decoding were added, which made it more akin to dump1090 of late.

Note Some technical terms related to ADS-B and Mode S are used in this section. They will be explained in detail in later chapters.

Installation of pyModeS

As a Python library, it is possible to install the most recent stable version of pyModeS as:

pip install --upgrade pyModeS

The latest development version for the GitHub can be installed as:

pip install --upgrade git+

Live traffic view

pyModeS provides the possibility to view live traffic through the modeslive command. The usage of this command is shown as follows:

$ modeslive [-h] --source SOURCE [--connect SERVER PORT DATAYPE]
            [--latlon LAT LON] [--show-uncertainty] [--dumpto DUMPTO]

 -h, --help            Show this help message and exit
 --source SOURCE       Choose data source, "rtlsdr" or "net"
                       Define server, port and data type. Supported data
                       types are: ['raw', 'beast', 'skysense']
 --latlon LAT LON      Receiver latitude and longitude, needed for the surface
                       position, default none
 --show-uncertainty    Display uncertainty values, default off
 --dumpto DUMPTO       Folder to dump decoded output, default none

When an RTL-SDR device is connected, the following command can be used to display live traffic:

$ modeslive --source rtlsdr

Data source can also be supplied through the network (for example, from dump1090 TCP output stream) as:

$ dump1090 --net --quiet
$ modeslive --source net --connect localhost 30002 raw

An example of the live view is shown in Figure 1.6.

Example of a live view of modeslive from pyModeS

Real-time flight states are shown, including, for example, ICAO transponder code, call sign, position, altitude, ground speed, true airspeed, indicated airspeed, Mach number, rate of climb, track angle, and heading.

Programming interface

Since pyModeS is originally designed as a library aimed for research, and thanks to the use of Python programming language, one can easily make use of its low-level decoding functionalities.

For example, core functions of pyModeS can be used to decode Downlink Format, ICAO address, ADS-B Type Code, as well as to perform parity check:

import pyModeS as pms

pms.df(msg)         # Downlink Format
pms.icao(msg)       # Infer the ICAO address from the message
pms.crc(msg)        # Perform parity check
pms.typecode(msg)   # Obtain ADS-B message Type Code

ADS-B related functions allow information such as identity, position, and velocities to be decoded. For example:

# position messages
pms.adsb.position(msg_even, msg_odd, t_even, t_odd)

# velocity messages

There are also a number of functions designed to infer and decode Mode S downlink messages. For example:

pms.common.altcode(msg)   # Mode S altitude code (DF=4/20)
pms.common.idcode(msg)    # Mode S squwak code (DF=5/21)
pms.bds.infer(msg)        # Infer Modes S BDS code

Once a Mode S message type is identified, type specific functions can be used to decode corresponding parameters.

# BDS 4,0
pms.commb.selalt40mcp(msg)  # MCP/FCU selected altitude (ft)
pms.commb.selalt40fms(msg)  # FMS selected altitude (ft)
pms.commb.p40baro(msg)      # Barometric pressure setting (mb)

# BDS 5,0
pms.commb.roll50(msg)       # Roll angle (deg)
pms.commb.trk50(msg)        # True track angle (deg)
pms.commb.gs50(msg)         # Ground speed (kt)
pms.commb.rtrk50(msg)       # Track angle rate (deg/sec)
pms.commb.tas50(msg)        # True airspeed (kt)

# BDS 6,0
pms.commb.hdg60(msg)        # Magnetic heading (deg)
pms.commb.ias60(msg)        # Indicated airspeed (kt)
pms.commb.mach60(msg)       # Mach number (-)
pms.commb.vr60baro(msg)     # Barometric altitude rate (ft/min)
pms.commb.vr60ins(msg)      # Inertial vertical speed (ft/min)

These are some commonly used functions related to Mode S decoding. A complete list of the APIs can be found in the pyModeS library API documentation.

These functionalities may seem complicated at this moment. In the rest of this book, I will explain all the details related to the decoding of these ADS-B and Mode S messages. Throughout the rest of chapters, I will make use of pyModeS to demonstrate the decoding.



© Copyright 2021 Junzi Sun. Build with LaTeX, Pandoc, and GitHub