Skip to content

Commit

Permalink
WIP big rewrite of message decoding / aircraft tracking.
Browse files Browse the repository at this point in the history
  • Loading branch information
mutability committed Aug 27, 2016
1 parent f152bf6 commit 54ca2c7
Show file tree
Hide file tree
Showing 9 changed files with 1,300 additions and 946 deletions.
1 change: 0 additions & 1 deletion demod_2400.c
Expand Up @@ -306,7 +306,6 @@ void demodulate2400(struct mag_buf *mag)
normalize_timespec(&mm.sysTimestampMsg);

mm.score = bestscore;
mm.bFlags = mm.correctedbits = 0;

// Decode the received message
{
Expand Down
2 changes: 1 addition & 1 deletion dump1090.c
Expand Up @@ -1019,7 +1019,7 @@ int main(int argc, char **argv) {
} else if (!strcmp(argv[j],"--metric")) {
Modes.metric = 1;
} else if (!strcmp(argv[j],"--hae") || !strcmp(argv[j],"--gnss")) {
Modes.use_hae = 1;
Modes.use_gnss = 1;
} else if (!strcmp(argv[j],"--aggressive")) {
#ifdef ALLOW_AGGRESSIVE
Modes.nfix_crc = MODES_MAX_BITERRORS;
Expand Down
182 changes: 117 additions & 65 deletions dump1090.h
Expand Up @@ -2,7 +2,7 @@
//
// dump1090.h: main program header
//
// Copyright (c) 2014,2015 Oliver Jowett <oliver@mutability.co.uk>
// Copyright (c) 2014-2016 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
Expand Down Expand Up @@ -135,40 +135,48 @@ typedef struct rtlsdr_dev rtlsdr_dev_t;
#define MODES_OUT_FLUSH_SIZE (MODES_OUT_BUF_SIZE - 256)
#define MODES_OUT_FLUSH_INTERVAL (60000)

#define MODES_UNIT_FEET 0
#define MODES_UNIT_METERS 1

#define MODES_USER_LATLON_VALID (1<<0)

#define MODES_ACFLAGS_LATLON_VALID (1<<0) // Aircraft Lat/Lon is decoded
#define MODES_ACFLAGS_ALTITUDE_VALID (1<<1) // Aircraft altitude is known
#define MODES_ACFLAGS_HEADING_VALID (1<<2) // Aircraft heading is known
#define MODES_ACFLAGS_SPEED_VALID (1<<3) // Aircraft speed is known
#define MODES_ACFLAGS_VERTRATE_VALID (1<<4) // Aircraft vertical rate is known
#define MODES_ACFLAGS_SQUAWK_VALID (1<<5) // Aircraft Mode A Squawk is known
#define MODES_ACFLAGS_CALLSIGN_VALID (1<<6) // Aircraft Callsign Identity
#define MODES_ACFLAGS_EWSPEED_VALID (1<<7) // Aircraft East West Speed is known
#define MODES_ACFLAGS_NSSPEED_VALID (1<<8) // Aircraft North South Speed is known
#define MODES_ACFLAGS_AOG (1<<9) // Aircraft is On the Ground
#define MODES_ACFLAGS_LLEVEN_VALID (1<<10) // Aircraft Even Lot/Lon is known
#define MODES_ACFLAGS_LLODD_VALID (1<<11) // Aircraft Odd Lot/Lon is known
#define MODES_ACFLAGS_AOG_VALID (1<<12) // MODES_ACFLAGS_AOG is valid
#define MODES_ACFLAGS_FS_VALID (1<<13) // Aircraft Flight Status is known
#define MODES_ACFLAGS_NSEWSPD_VALID (1<<14) // Aircraft EW and NS Speed is known
#define MODES_ACFLAGS_LATLON_REL_OK (1<<15) // Indicates it's OK to do a relative CPR
#define MODES_ACFLAGS_REL_CPR_USED (1<<16) // Lat/lon derived from relative CPR
#define MODES_ACFLAGS_CATEGORY_VALID (1<<17) // Aircraft category is known
#define MODES_ACFLAGS_FROM_MLAT (1<<18) // Data was derived from multilateration
#define MODES_ACFLAGS_ALTITUDE_HAE_VALID (1<<19) // altitude_hae is valid
#define MODES_ACFLAGS_HAE_DELTA_VALID (1<<20) // hae_delta is valid
#define MODES_ACFLAGS_FROM_TISB (1<<21) // Data was derived from TIS-B messages

#define MODES_ACFLAGS_LLEITHER_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID)
#define MODES_ACFLAGS_LLBOTH_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID)
#define MODES_ACFLAGS_AOG_GROUND (MODES_ACFLAGS_AOG_VALID | MODES_ACFLAGS_AOG)

#define INVALID_ALTITUDE (-9999)

/* Where did a bit of data arrive from? In order of increasing priority */
typedef enum {
SOURCE_INVALID, /* data is not valid */
SOURCE_MLAT, /* derived from mlat */
SOURCE_MODE_S, /* data from a Mode S message, no full CRC */
SOURCE_MODE_S_CHECKED, /* data from a Mode S message with full CRC */
SOURCE_TISB, /* data from a TIS-B extended squitter message */
SOURCE_ADSB, /* data from a ADS-B extended squitter message */
} datasource_t;

typedef enum {
UNIT_FEET,
UNIT_METERS
} altitude_unit_t;

typedef enum {
ALTITUDE_BARO,
ALTITUDE_GNSS
} altitude_source_t;

typedef enum {
AG_INVALID,
AG_GROUND,
AG_AIRBORNE,
AG_UNCERTAIN
} airground_t;

typedef enum {
SPEED_GROUNDSPEED,
SPEED_IAS,
SPEED_TAS
} speed_source_t;

typedef enum {
HEADING_TRUE,
HEADING_MAGNETIC
} heading_source_t;

#define MODES_NON_ICAO_ADDRESS (1<<24) // Set on addresses to indicate they are not ICAO addresses

#define MODES_DEBUG_DEMOD (1<<0)
Expand Down Expand Up @@ -310,7 +318,7 @@ struct { // Internal state
int stats_range_histo; // Collect/show a range histogram?
int onlyaddr; // Print only ICAO addresses
int metric; // Use metric units
int use_hae; // Use HAE altitudes with H suffix when available
int use_gnss; // Use GNSS altitudes with H suffix ("HAE", though it isn't always) when available
int mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...;
int interactive_rtl1090; // flight table in interactive mode is formatted like RTL1090
char *json_dir; // Path to json base directory, or NULL not to write json.
Expand Down Expand Up @@ -360,42 +368,86 @@ struct modesMessage {
double signalLevel; // RSSI, in the range [0..1], as a fraction of full-scale power
int score; // Scoring from scoreModesMessage, if used

// DF 11, DF 17
int ca; // Responder capabilities
int iid;

// DF 17, DF 18
int metype; // Extended squitter message type.
int mesub; // Extended squitter message subtype.
int heading; // Reported by aircraft, or computed from from EW and NS velocity
int raw_latitude; // Non decoded latitude.
int raw_longitude; // Non decoded longitude.
unsigned nuc_p; // NUCp value implied by message type
double fLat; // Coordinates obtained from CPR encoded data if/when decoded
double fLon; // Coordinates obtained from CPR encoded data if/when decoded
char flight[16]; // 8 chars flight number.
int ew_velocity; // E/W velocity.
int ns_velocity; // N/S velocity.
int vert_rate; // Vertical rate.
int velocity; // Reported by aircraft, or computed from from EW and NS velocity
datasource_t source; // Characterizes the overall message source

// Raw data, just extracted directly from the message
// The names reflect the field names in Annex 4
unsigned IID; // extracted from CRC of DF11s
unsigned AA;
unsigned AC;
unsigned CA;
unsigned CC;
unsigned CF;
unsigned DR;
unsigned FS;
unsigned ID;
unsigned KE;
unsigned ND;
unsigned RI;
unsigned SL;
unsigned UM;
unsigned VS;
unsigned char MB[7];
unsigned char MD[10];
unsigned char ME[7];
unsigned char MV[7];

// Decoded data
unsigned altitude_valid : 1;
unsigned heading_valid : 1;
unsigned speed_valid : 1;
unsigned vert_rate_valid : 1;
unsigned squawk_valid : 1;
unsigned callsign_valid : 1;
unsigned ew_velocity_valid : 1;
unsigned ns_velocity_valid : 1;
unsigned cpr_valid : 1;
unsigned cpr_odd : 1;
unsigned cpr_decoded : 1;
unsigned cpr_relative : 1;
unsigned category_valid : 1;
unsigned gnss_delta_valid : 1;
unsigned from_mlat : 1;
unsigned from_tisb : 1;
unsigned spi_valid : 1;
unsigned spi : 1;
unsigned alert_valid : 1;
unsigned alert : 1;

unsigned metype; // DF17/18 ME type
unsigned mesub; // DF17/18 ME subtype

// valid if altitude_valid:
int altitude; // Altitude in either feet or meters
altitude_unit_t altitude_unit; // the unit used for altitude
altitude_source_t altitude_source; // whether the altitude is a barometric altude or a GNSS height
// valid if gnss_delta_valid:
int gnss_delta; // difference between GNSS and baro alt
// valid if heading_valid:
unsigned heading; // Reported by aircraft, or computed from from EW and NS velocity
heading_source_t heading_source; // what "heading" is measuring (true or magnetic heading)
// valid if speed_valid:
unsigned speed; // in kts, reported by aircraft, or computed from from EW and NS velocity
speed_source_t speed_source; // what "speed" is measuring (groundspeed / IAS / TAS)
// valid if vert_rate_valid:
int vert_rate; // vertical rate in feet/minute
altitude_source_t vert_rate_source; // the altitude source used for vert_rate
// valid if squawk_valid:
unsigned squawk; // 13 bits identity (Squawk), encoded as 4 hex digits
// valid if callsign_valid
char callsign[9]; // 8 chars flight number
// valid if category_valid
unsigned category; // A0 - D7 encoded as a single hex byte
int altitude_hae; // altitude reported as GNSS HAE
int hae_delta; // difference between HAE and baro alt

// DF 18
int cf; // Control Field

// DF4, DF5, DF20, DF21
int fs; // Flight status for DF4,5,20,21
int modeA; // 13 bits identity (Squawk).
// valid if cpr_valid
unsigned cpr_lat; // Non decoded latitude.
unsigned cpr_lon; // Non decoded longitude.
unsigned cpr_nucp; // NUCp/NIC value implied by message type

// DF20, DF21
int bds; // BDS value implied if overlay control was used
airground_t airground; // air/ground state

// Fields used by multiple message types.
int altitude;
int unit;
int bFlags; // Flags related to fields in this structure
// valid if cpr_decoded:
double decoded_lat;
double decoded_lon;
};

// This one needs modesMessage:
Expand Down
37 changes: 20 additions & 17 deletions interactive.c
Expand Up @@ -122,25 +122,28 @@ void interactiveShowData(void) {
char strTt[5] = " ";
char strGs[5] = " ";

if (a->bFlags & MODES_ACFLAGS_SQUAWK_VALID) {
snprintf(strSquawk,5,"%04x", a->modeA);}
if (trackDataValid(&a->squawk_valid)) {
snprintf(strSquawk,5,"%04x", a->squawk);
}

if (a->bFlags & MODES_ACFLAGS_SPEED_VALID) {
snprintf (strGs, 5,"%3d", convert_speed(a->speed));}
if (trackDataValid(&a->speed_valid)) {
snprintf (strGs, 5,"%3d", convert_speed(a->speed));
}

if (a->bFlags & MODES_ACFLAGS_HEADING_VALID) {
snprintf (strTt, 5,"%03d", a->track);}
if (trackDataValid(&a->heading_valid)) {
snprintf (strTt, 5,"%03d", a->heading);
}

if (msgs > 99999) {
msgs = 99999;}
msgs = 99999;
}

if (Modes.interactive_rtl1090) { // RTL1090 display mode

if (a->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) {
snprintf(strFl,6,"F%03d",(a->altitude/100));
if (trackDataValid(&a->altitude_valid)) {
snprintf(strFl,6,"F%03d",((a->altitude+50)/100));
}
printf("%06x %-8s %-4s %-3s %-3s %4s %-6d %-2.0f\n",
a->addr, a->flight, strFl, strGs, strTt, strSquawk, msgs, (now - a->seen)/1000.0);
a->addr, a->callsign, strFl, strGs, strTt, strSquawk, msgs, (now - a->seen)/1000.0);

} else { // Dump1090 display mode
char strMode[5] = " ";
Expand All @@ -158,22 +161,22 @@ void interactiveShowData(void) {
if (flags & MODEAC_MSG_MODEA_HIT) {strMode[2] = 'a';}
if (flags & MODEAC_MSG_MODEC_HIT) {strMode[3] = 'c';}

if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) {
if (trackDataValid(&a->position_valid)) {
snprintf(strLat, 8,"%7.03f", a->lat);
snprintf(strLon, 9,"%8.03f", a->lon);
}

if (a->bFlags & MODES_ACFLAGS_AOG) {
if (trackDataValid(&a->airground_valid) && a->airground == AG_GROUND) {
snprintf(strFl, 7," grnd");
} else if (Modes.use_hae && (a->bFlags & MODES_ACFLAGS_ALTITUDE_HAE_VALID)) {
snprintf(strFl, 7, "%5dH", convert_altitude(a->altitude_hae));
} else if (a->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) {
} else if (Modes.use_gnss && trackDataValid(&a->altitude_gnss_valid)) {
snprintf(strFl, 7, "%5dH", convert_altitude(a->altitude_gnss));
} else if (trackDataValid(&a->altitude_valid)) {
snprintf(strFl, 7, "%5d ", convert_altitude(a->altitude));
}

printf("%s%06X %-4s %-4s %-8s %6s %3s %3s %7s %8s %5.1f %5d %2.0f\n",
(a->addr & MODES_NON_ICAO_ADDRESS) ? "~" : " ", (a->addr & 0xffffff),
strMode, strSquawk, a->flight, strFl, strGs, strTt,
strMode, strSquawk, a->callsign, strFl, strGs, strTt,
strLat, strLon, 10 * log10(signalAverage), msgs, (now - a->seen)/1000.0);
}
count++;
Expand Down
15 changes: 9 additions & 6 deletions mode_ac.c
Expand Up @@ -89,18 +89,21 @@ void decodeModeAMessage(struct modesMessage *mm, int ModeA)
mm->addr = (ModeA & 0x0000FF7F) | MODES_NON_ICAO_ADDRESS;

// Set the Identity field to ModeA
mm->modeA = ModeA & 0x7777;
mm->bFlags |= MODES_ACFLAGS_SQUAWK_VALID;
mm->squawk = ModeA & 0x7777;
mm->squawk_valid = 1;

// Flag ident in flight status
mm->fs = ModeA & 0x0080;
mm->spi = (ModeA & 0x0080) ? 1 : 0;
mm->spi_valid = 1;

// Decode an altitude if this looks like a possible mode C
if (!mm->fs) {
if (!mm->spi) {
int modeC = ModeAToModeC(ModeA);
if (modeC >= -12) {
if (modeC != INVALID_ALTITUDE) {
mm->altitude = modeC * 100;
mm->bFlags |= MODES_ACFLAGS_ALTITUDE_VALID;
mm->altitude_unit = UNIT_FEET;
mm->altitude_source = ALTITUDE_BARO;
mm->altitude_valid = 1;
}
}

Expand Down

0 comments on commit 54ca2c7

Please sign in to comment.