Peter created a system that receives and decodes data transmissions
from ships and other vessels via the Universal Automatic
Identification System. Built around a Luminary Micro LM3S811
evaluation board, the decoder displays a "virtual" radar screen,
showing the position of vessels in the area.
As a ham radio and embedded hardware/ software engineer, I have
long been interested in decoding off-air data transmissions. From
an early interest in radio teletype (RTTY) transmissions,I moved on
to DOS programs to decode the data from trunked radio systems and
paging systems. When I heard about a new marine data system
carrying ships‘ positions, I just had to have a go at decoding the
data!
The Universal Automatic Identification System (AIS) is a data
system that operates on two frequencies in the marine VHF FM band.
Ships, and other fixed installations, make frequent broadcast
transmissions that may be received by other vessels in range. The
transmissions carry both "dynamic"information (i.e., position and
speed)
and "static" information (i.e., name,call sign, and more)。 A
decoder receiving the transmissions can display a"virtual" radar
screen showing the position of other vessels in the area.
The Luminary Micro LM3S811 evaluation board seemed like the ideal
platform for developing an AIS decoder (see Figure 1)。 The
Stellaris microcontroller has a low-interrupt latency, and it is
ideal for decoding a serial stream in software. Also, a USB COM
port is connected to one of the microcontroller‘s UARTs. This is
perfect for transferring data back to a PC program with serial
data.
In addition to the microcontroller, I needed a modem to demodulate
the Gaussian minimum shift-keying(GMSK) transmissions used by the
AIS. I used a CML Microcircuits CMX589A modem for this purpose (see
Figure 2)。My complete system, including the modem and the LM3S811
module, is shown in Photo 1.
HARDWAREAIS transmissions can be heard on two frequencies in the marine VHF
band,161.975 and 162.025 MHz. To receive the transmissions, a
narrow-band FM(NBFM) receiver that is capable of covering the VHF
marine band is required. I used an Icom IC-R7000 communications
receiver. This is a fairly old, but very able, communications
receiver that covers the 25-MHz to 2-GHz frequency range. My
receiver was modified to bring the discriminator output out to an
RCA jack in the rear. This provides the linearity and DC coupling
required by the GMSK modulation scheme.
Of course, the receiver also requires a suitable antenna to be
within receiving range of shipping traffic! Luckily, I live within
10 miles of the River Mersey,a busy shipping area in northwest
England.
DECODER BOARD
Figure 1 shows the entire system. Audio from my receiver‘s
discriminator output is demodulated by the CMX589A, which outputs
clock and data signals at a rate of 9,600 bps. The signals are
interfaced to I/O pins on the LM3S811 microcontroller. Other I/O
pins enable you to monitor a received signal/noise ratio and
control the modem's acquisition sequence.
UART 0 on the LM3S811 is connected to a Future Technology Devices
International FT2232C USB device controller on the evaluation
board. This appears as a COM port on the PC, enabling communication
with the UART via a standard communications program.
GMSK DEMODULATOR
Figure 2 shows the GMSK modem section, which I constructed on
stripboard. I followed the recommendations given in the CMX589A
datasheet. Note that the CMX589A is a full modem, enabling both
transmitting and receiving of GMSK signals, but only the reception
section is used in this application.
The discriminator audio is DC-coupled into the modem with a gain
and a DC-level adjusting circuit. This is designed to give a
roughly 1-VPP signal on the RX FB pin, centered on VBIAS. Because
the discriminator output of my receiver has a DC offset of around 4
V, I had to add the DC balance circuit comprising RV1 and R5 to
achieve the VBIAS level.
In addition to the 9,600 bps and clock outputs, the modem has an RX
SN output, giving an indication of the received signal/noise ratio.
This is a useful test point for monitoring with an oscilloscope
during debugging.
The PLLAcq and RxDCAcq pins control the start-up and acquisition
sequence of the CMX589A. The pins are connected to the
microcontroller‘s I/O pins and controlled by software.
At initial power-up, both of the pins need to be low and stay in
that state for at least 1,024 bit times to initialize the device.
Both pins are then taken high, while no data is received, putting
the device into the "acquire"state with wide PLL bandwidth. As soon
as a packet preamble is detected and data is received, the PLLAcq
pin is taken low, narrowing the PLL bandwidth. When packet
reception is complete,the pin is taken high again.
In addition, the RXHOLDN pin enables the correction of the clock
frequency and the DC level to be stopped during a signal fade. I
interfaced the pin to the microcontroller, but it is not currently
used by the software.
The CMX589A requires a single supply rail between 3 and 5.5 V. I
powered the circuit from the 3.3-V rail on the LM3S811 evaluation
board, which is regulated down from the 5-V supply from the USB
port.
INTERFACE TO THE LM3S811I fitted two strips of 0.1″ sockets to my LM3S811 evaluation board,
enabling it to plug into headers on my decoder board. This makes it
easy to move the evaluation board onto other projects, if required,
or to operate it on its own.
Figure 3 shows how I interfaced my GMSK modem to the evaluation
board. As you can see, I used only a few GPIO pins. I chose them to
avoid pins already used by peripherals on the evaluation board.
I defined GPIO pin PD0 as a test point, which was used to connect
an oscilloscope during debugging. This allowed me to check that my
interrupt service routine was running and to measure the amount of
time spent in the routine.
SOFTWARE
Before writing any code, I had to understand the low-level coding
and packet structure used by the AIS data. The information is
freely available in public domain documents.
AIS data is low-level coded using non-return-to-zero-insertion
(NRZI)coding. This gives a change in level when a zero is
encountered in the data to be transmitted. To decode the NRZI, I
need to compare each received bit with the previous bit. If the
level has changed, the decoded data is a zero; otherwise, it is a
one.
Figure 4 shows the AIS packet structure,which is based on the
high-level data link control (HDLC) protocol. It is a bit-oriented
protocol, which needs to be processed one bit at a time in
software.
The message starts with a training sequence consisting of either 24
or 32 bits of alternating ones and zeros(1010101...。)。 This
sequence is modified by NRZI coding to 001100110011.
The start of the message is identified by a start flag (Hex 7E),
which is followed by the message data. To prevent the false
detection of flag characters,the data is subject to bit stuffing.
This means that an extra zero is inserted after a string of five
ones in the data.
A 2-byte frame check sequence follows the data. This is a 16-bit
CRC conforming to the HDLC standard. The standard CCITT polynomial
is used (X16 + X12 + X5 + 1)。
The end of the message is identified by the end flag(Hex 7E)。 After
the end flag,buffering time is allowed. This is to allow for bit
stuffing and various radio transmission delays.
PROGRAM STRUCTURE
My code was written entirely in C. I used the Keil RealView MDK for
compilation and debugging. My program does not use an RTOS. It
relies on simple round-robin processing.
At power-up, the start-up code is executed. It is contained in the
module Startup.s on the Circuit Cellar FTP site. This is standard
assembler startup code that is modified to add the IntGPIOE handler
to the vector table for GPIO port E interrupts.
The start-up code passes control to the main() function (in the
module main.c on the Circuit Cellar FTP site)。The function first
initializes the processor and peripherals before entering the main
program loop. As part of the processor initialization, the PLL has
to be set up, setting the instruction clock rate used by the
processor. Although the LM3S811 will operate at up to 50 MHz, I
decided to clock my project at 20 MHz. I suspected that I did not
need the full 50-MHz rate. Running at 20 MHz will enable me to move
to a low-end Stellaris device in the future.
The main loop is an infinite loop that continuously checks if a
packet has been received by the interrupt handler and stored in a
FIFO buffer. If so,the packet is extracted from the FIFO. Next, the
function NMEA_Send() is called to convert the packet to NMEA format
and send it out serially.
INTERRUPT HANDLER
The heart of the decoder is the interrupt handler IntGPIOE() in the
module rxint.c, which is posted on the Circuit Cellar FTP site. The
handler is responsible for receiving AIS packets one bit at a time.
It is executed on each rising edge of the clock coming from the
CMX589A modem.
The first job of the interrupt handler is to decode the NRZI data
by comparing each received bit with the last bit. The resulting
data is then shifted into a 16-bit register. The remainder of the
handler is implemented as a state machine, with five states
corresponding to the progress with receiving a packet. The current
state is held in the rxstate variable.
The initial state is RX_INIT, which is entered at start-up. After
1,024 bit times, this state raises the RxDCacq and PLLacq control
lines going to the CMX589A and changes the state to RX_PREAMBLE.
The RX_PREAMBLE state waits for 16 bits of valid training sequence
to be received. It then drops PLLacq, clears the bit count, and
changes the state to RX_START.
The RX_START state waits for a start flag (0x7E) to be received.
When found, the bit count is cleared and the state is changed to
RX_PRELOAD. If a start flag is not found within 24 bits, then the
PLLacq is raised again and the state is changed back to
RX_PREAMBLE.
The RX_PRELOAD state waits for 8 bits to be received and preloaded
into the shift register. This means that when the end flag is
found, you will have just passed the last bit of the FCS through
the CRC calculation. After 8 bits, the state is changed to RX_DATA.
The RX_DATA state receives data and waits for an end flag to be
detected. While data is received, stuffing bits are removed and
each bit is passed through the CRC calculation. Every 8 bits, a new
byte is loaded into the receive FIFO. When an end flag is found,
the CRC is checked. If it is good, the new packet is released into
the FIFO for processing by the main loop.
To measure the amount of time spent in the interrupt handler, my
code sets the test point pin high at the start of the routine and
low at the end. By observing this pin on an oscilloscope, it is
possible to measure the width of the pulse,which equates to the
time spent in the routine. With the processor running at 20 MHz, I
found that the interrupt handler took about 5 μs to execute every
100 μs, only 5% of the available processing time (see Figure 5)。
PACKET FIFO
To enable the interrupt routine to continue receiving while the
main program is processing, I decided that a FIFO structure was
required to store received packets. Because the packets are of a
variable length, I chose the structure shown in Figure 6, which
uses indirect addressing.
The two index values-In_index and Out_index-point to a table of
eight packet index values, which in turn point into a 1,024-byte
circular buffer. The two values are used as indirect pointers to
the locations where the next packet in may be written and the next
packet out read.
This structure enables up to eight packets of variable lengths to
be stored, up to a total size of 1,024 bytes. These sizes are
fairly arbitrary and are easily configurable by means of #defines
at the start of the module. The fifo.c module on the Circuit Cellar
FTP site contains the functions necessary to initialize the FIFO
structure, write packets into the FIFO, and check for and recover
packets from the FIFO.
NMEA OUTPUTThe International Electrotechnical Commission‘s IEC Standard
61162-1 specifies a serial interface between pieces of marine
electronic equipment. It is closely related to the National Marine
Electronics Association's NMEA 0183 specification.
A VDM "VHF Data-Link" sentence has been defined, allowing the
entire contents of a received AIS packet to be transmitted. I used
this format for the output from the decoder, enabling it to link to
standard PC plotting software.
The VDM sentence is normally transmitted at the NMEA high speed of
38,400 bps. Its format is:
!AIVDM,n,m,i,c,s......s,f*hh
n is the number of sentences needed to transfer the message (1 to
9)。 m is the message sequence number (1 to 9)。
i is a sequential identifier used to link multiple messages (0 to
9)。 c is the AIS channel number (1 or 2)。 s......s is the AIS
packet, encoded using a 6-bit field type. f is the number of "fill
bits" added to complete the last 6-bit character. hh is a
two-character hex checksum, computed by XORing all of the
characters between the ! and the *. Depending on the packet
length,one to nine VDM sentences may be required to transmit it.
The packet data uses an encoding scheme that splits the binary
packet into 6-bit fields. Each field is then assigned to a unique,
printable ASCII character.
My code to encode and transmit NMEA VDM sentences is contained in
the nmea.c module on the Circuit Cellar FTP site. When the main
loop has a packet to send, it calls the function NMEA_Send(), which
encodes the packet according to the 6-bit encoding scheme. It then
calculates how many VDM sentences are required to send the packet.
The VDM_Send() function is then called to build and transmit each
required VDM sentence.
OPERATION
I used the Tera Term communications program to verify the correct
output of NMEA sentences, although any PCbased serial terminal
program could have been used. Tera Term was set up to connect to
COM4, the port used by the USB serial port on the LM3S811
evaluation board. Photo 2 shows a typical output of AIVDM sentences
in Tera Term.

After checking that the NMEA output from the decoder looked
correct, I was ready to display some real ships‘ positions. There
are a number of pieces of software available that enable NMEA data
to be plotted on a PC. I chose a package called ShipPlotter by
COAA. ShipPlotter requires a chart for the area of interest, as
well as calibration data,enabling positions on the chart to be
located by latitude and longitude. I found a handy chart generator
on the Internet that uses NASA satellite imagery and created a
chart for the River Mersey area (see Photo 3)。
As soon as ShipPlotter was configured to use the correct COM port,
small ship icons started to appear on the chart. This was
confirmation that my project was correctly decoding the data and
formatting the NMEA sentences.
AREAS FOR IMPROVEMENT
The goal of this project was to show how off-air AIS transmissions
can be decoded with the aid of a Stellaris microcontroller. This
has been achieved, and I have learned a lot about AIS and the
Stellaris range in the process.
There are a number of areas for improvement. Measurement of the
interrupt processing time has shown that the LM3S811 still has
plenty of processor cycles available, in addition to decoding the
data. Also note that this project has used only a small part of the
I/O and memory on this part. The decoder software could form the
heart of a complete display system,built around the LM3S811, and
drive a graphical LCD directly.
Adding Ethernet to the decoder board could produce a dedicated AIS
server, making position information available via the Internet.
Those are just a couple of ideas. I hope this project will inspire
you to come up with more!
Editor‘s note: This project received Honorable Mention in the
Luminary Micro Designstellaris2006 Contest
(www.circuitcellar.com/designstellaris 2006/winners/1740.html)。
Peter Baston (pete@petebaston.co.uk)is an electronic design engineer with more than 25 years of
experience developing hardware and software for embedded systems.
He graduated from the University College of North Wales, Bangor,
with a degree in Electronic Engineering in 1979. Peter is currently
employed as a senior design engineer with Tyco Electronics. When he
is not tinkering with embedded systems, he likes hill walking and
enjoying folk music. Peter holds the ham radio call sign GW0PJA.
PROJECT FILES
To download code, go to ftp://ftp.circuitcellar.com/pub/Circuit_Cellar/2008/215.
RESOURCES
CML Microcircuits, "CMX589A GMSK Modem datasheet," D/589A/4,2002, www.cmlmicro.com/products/datasheets/Docs/cmx589ad.pdf.
International Electrotechnical Commission,"IEC Standard 61162-1:
Maritime Navigation and Radiocommunication Equipment and
Systems-Digital interfaces-Part 1: Single talker
and multiple listeners," 2007,
www.iec.ch.
International Maritime Organization,
www.imo.org.
National Marine Electronics Association,"NMEA 0183 Standard," 2002,
www.nmea.org/pub/0183/.
"ShipPlotter chart generator,"
http://emit.demon.co.uk/map2.php.
Universal Automatic Identification
System, www.uais.org.
SOURCES
CMX589A GMSK Modem
CML Microcircuits, Inc.
www.cmlmicro.com
ShipPlotter
COAA
www.coaa.co.uk/shipplotter.htm
FT2232C USB Device controller
Future Technology Devices International
www.ftdichip.com
IC-R7000 Communications receiver
Icom, Inc.
www.icomamerica.com
RealView MDK
Keil
www.keil.com
LM3S811 Microcontroller
Luminary Micro, Inc.
www.luminarymicro.com
Tera Term terminal program
Tera Term
http://hp.vector.co.jp/authors/VA002416/teraterm.html