This project is in an early stage of development. Its objective is to simulate and decode the Automatic Identification System (AIS) used in maritime traffic.
Much like my F-14 CADC simulation, this project aims to model complex hardware systems in software to understand telemetry flow, low-level memory management, and navigation data architecture.
The system is designed with an embedded systems mindset (low-level C). Dynamic memory allocation is avoided during iterative processing to ensure predictable, safe performance, emulating real-world hardware constraints.
The project is written in standard C and does not rely on complex external libraries. You can compile it using gcc or the included Makefile (recommended).
- GCC with C11 support.
- GNU Make.
- A shell capable of redirecting standard input, such as Bash, MSYS2, or Git Bash on Windows.
The project uses only the C standard library and links against the standard math library (libm).
common/
ais_types.h Shared status codes and decoded AIS data types
nmea_checksum.* NMEA checksum calculation and validation
sixbit.* AIS 6-bit ASCII unarmoring
bitstream.* MSB-first bit packing and field extraction
decoder/
nmea_assemble.* NMEA fragment validation and reassembly
position_report.* AIS message types 1, 2, and 3 decoding
main.c Command-line decoder and output formatting
tests/
test_nmea_layer.c
test_sixbit_layer.c
test_position_report.c
sentences.nmea Sample AIVDM input
Makefile Build and test targets
From the project root, run:
make allThis creates the main executable and the test executables in build/:
build/ais_decoder
build/test_nmea_layer
build/test_sixbit_layer
build/test_position_report
On Windows with MinGW, the files may appear with the .exe extension.
Run the complete test suite with:
make testThe tests cover:
- NMEA checksum validation and fragment reassembly.
- AIS 6-bit unarmoring and MSB-first bit extraction.
- AIS type 1, 2, and 3 position report decoding.
- Invalid checksums, malformed payloads, unsupported message types, and unavailable field values.
To remove generated files:
make cleanThe main program reads NMEA/AIVDM sentences from standard input. To decode the included sample file:
./build/ais_decoder < sentences.nmeaOn Windows or MinGW, use this form if necessary:
./build/ais_decoder.exe < sentences.nmeaThe program prints a table containing:
- MMSI.
- Latitude and longitude.
- Speed over ground (SOG).
- Course over ground (COG).
- True heading.
- Navigational status.
- UTC time when the message was decoded.
Invalid sentences are reported on standard error and do not stop the processing of later input lines. The final summary reports the number of input lines, decoded messages, checksum errors, unsupported message types, malformed sentences, invalid 6-bit payloads, and malformed payloads.
The executable supports two optional arguments:
./build/ais_decoder [--csv output.csv] [--quiet]
--csv output.csv writes decoded messages to a CSV file with these columns:
mmsi,latitude,longitude,sog_knots,cog_deg,heading_deg,nav_status,timestamp_utc
Unavailable numeric values are written as empty CSV fields.
--quiet suppresses diagnostic messages and the final summary on standard error. The decoded table, or CSV file when requested, is still produced.
Examples:
./build/ais_decoder --quiet < sentences.nmea
./build/ais_decoder --csv output.csv < sentences.nmea
./build/ais_decoder --quiet --csv output.csv < sentences.nmeaEach input line should be a complete NMEA AIS sentence, for example:
!AIVDM,1,1,,A,15M67FC000G?ufbE`FepT@3n00Sa,0*5F
The decoder validates the NMEA checksum before processing the payload. Multi-fragment messages are accumulated using their sequence identifier and channel until all fragments arrive. At the current stage, only AIS message types 1, 2, and 3 are decoded as Class A position reports. Other valid AIS message types are counted as unsupported.
NMEA line
-> checksum validation
-> fragment reassembly
-> AIS 6-bit unarmoring
-> MSB-first bit extraction
-> type 1/2/3 position report decoding
-> table or CSV output
The project is currently focused on Class A position reports. It does not yet decode static/voyage data or other AIS message types. The timestamp in the output is the local system's UTC conversion time when the message is processed, not a timestamp transmitted inside the AIS position report.
[1] E. S. Raymond, "AIVDM/AIVDO protocol decoding," GPSD. [En línea]. Disponible en: https://gpsd.gitlab.io/gpsd/AIVDM.html. [Accedido: 12-sep-2026].
[2] E. S. Raymond, "GPSD - Put your GPS on the net!," GPSD. [En línea]. Disponible en: https://gpsd.gitlab.io/gpsd/. [Accedido: 12-sep-2026].
[3] OpenCPN, "NMEA 0183," OpenCPN Manuals. [En línea]. Disponible en: https://opencpn.org/wiki/dokuwiki/doku.php?id=opencpn:manual_basic:nmea0183. [Accedido: 12-sep-2026].
[4] International Telecommunication Union, "Technical characteristics for an automatic identification system using time division multiple access in the VHF maritime mobile band," Recommendation ITU-R M.1371-6, feb. 2026. [En línea]. Disponible en: https://www.itu.int/dms_pubrec/itu-r/rec/m/R-REC-M.1371-6-202602-I!!PDF-E.pdf.
Conceptual research support (understanding the ITU-R M.1371 field structure and general
AIS/NMEA protocol concepts) was aided by AI assistants during development. All implementation
is original, with the exception of the CSV export helper in main.c, noted in its own comment.