commit
0c91c5f61f
166
dump1090.c
166
dump1090.c
|
@ -184,22 +184,24 @@ struct {
|
||||||
int onlyaddr; /* Print only ICAO addresses. */
|
int onlyaddr; /* Print only ICAO addresses. */
|
||||||
int metric; /* Use metric units. */
|
int metric; /* Use metric units. */
|
||||||
int aggressive; /* Aggressive detection algorithm. */
|
int aggressive; /* Aggressive detection algorithm. */
|
||||||
|
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 */ //&&&
|
||||||
|
|
||||||
/* Interactive mode */
|
/* Interactive mode */
|
||||||
struct aircraft *aircrafts;
|
struct aircraft *aircrafts;
|
||||||
uint64_t interactive_last_update; /* Last screen update in milliseconds */
|
uint64_t interactive_last_update; /* Last screen update in milliseconds */
|
||||||
|
|
||||||
/* Statistics */
|
/* Statistics */
|
||||||
int64_t stat_valid_preamble;
|
uint64_t stat_valid_preamble;
|
||||||
int64_t stat_demodulated;
|
uint64_t stat_demodulated;
|
||||||
int64_t stat_goodcrc;
|
uint64_t stat_goodcrc;
|
||||||
int64_t stat_badcrc;
|
uint64_t stat_badcrc;
|
||||||
int64_t stat_fixed;
|
uint64_t stat_fixed;
|
||||||
int64_t stat_single_bit_fix;
|
uint64_t stat_single_bit_fix;
|
||||||
int64_t stat_two_bits_fix;
|
uint64_t stat_two_bits_fix;
|
||||||
int64_t stat_http_requests;
|
uint64_t stat_http_requests;
|
||||||
int64_t stat_sbs_connections;
|
uint64_t stat_sbs_connections;
|
||||||
int64_t stat_out_of_phase;
|
uint64_t stat_out_of_phase;
|
||||||
} Modes;
|
} Modes;
|
||||||
|
|
||||||
/* The struct we use to store information about a decoded message. */
|
/* The struct we use to store information about a decoded message. */
|
||||||
|
@ -218,7 +220,6 @@ struct modesMessage {
|
||||||
|
|
||||||
/* DF 11 */
|
/* DF 11 */
|
||||||
int ca; /* Responder capabilities. */
|
int ca; /* Responder capabilities. */
|
||||||
int iid;
|
|
||||||
|
|
||||||
/* DF 17 */
|
/* DF 17 */
|
||||||
int metype; /* Extended squitter message type. */
|
int metype; /* Extended squitter message type. */
|
||||||
|
@ -298,6 +299,8 @@ void modesInitConfig(void) {
|
||||||
Modes.interactive_ttl = MODES_INTERACTIVE_TTL;
|
Modes.interactive_ttl = MODES_INTERACTIVE_TTL;
|
||||||
Modes.quiet = 0;
|
Modes.quiet = 0;
|
||||||
Modes.aggressive = 0;
|
Modes.aggressive = 0;
|
||||||
|
Modes.mlat = 0; //&&&
|
||||||
|
Modes.interactive_rtl1090 = 0; //&&&
|
||||||
}
|
}
|
||||||
|
|
||||||
void modesInit(void) {
|
void modesInit(void) {
|
||||||
|
@ -697,22 +700,20 @@ uint32_t modes_checksum_table[112] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t modesChecksum(unsigned char *msg, int bits) {
|
uint32_t modesChecksum(unsigned char *msg, int bits) {
|
||||||
uint32_t crc = 0;
|
uint32_t crc = 0;
|
||||||
int offset = (bits == 112) ? 0 : (112-56);
|
int offset = (bits == 112) ? 0 : (112-56);
|
||||||
uint8_t theByte = *msg;
|
|
||||||
uint32_t * pCRCTable = &modes_checksum_table[offset];
|
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for(j = 0; j < bits; j++) {
|
for(j = 0; j < bits; j++) {
|
||||||
if ((j & 7) == 0)
|
int byte = j/8;
|
||||||
{theByte = *msg++;}
|
int bit = j%8;
|
||||||
|
int bitmask = 1 << (7-bit);
|
||||||
|
|
||||||
// If bit is set, xor with corresponding table entry.
|
/* If bit is set, xor with corresponding table entry. */
|
||||||
if (theByte & 0x80) {crc ^= *pCRCTable;}
|
if (msg[byte] & bitmask)
|
||||||
pCRCTable++;
|
crc ^= modes_checksum_table[j+offset];
|
||||||
theByte = theByte << 1;
|
|
||||||
}
|
}
|
||||||
return crc; // 24 bit checksum.
|
return crc; /* 24 bit checksum. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given the Downlink Format (DF) of the message, return the message length
|
/* Given the Downlink Format (DF) of the message, return the message length
|
||||||
|
@ -994,27 +995,23 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) {
|
||||||
char *ais_charset = "?ABCDEFGHIJKLMNOPQRSTUVWXYZ????? ???????????????0123456789??????";
|
char *ais_charset = "?ABCDEFGHIJKLMNOPQRSTUVWXYZ????? ???????????????0123456789??????";
|
||||||
|
|
||||||
/* Work on our local copy */
|
/* Work on our local copy */
|
||||||
memcpy(mm->msg, msg, MODES_LONG_MSG_BYTES);
|
memcpy(mm->msg,msg,MODES_LONG_MSG_BYTES);
|
||||||
msg = mm->msg;
|
msg = mm->msg;
|
||||||
|
|
||||||
/* Get the message type ASAP as other operations depend on this */
|
/* Get the message type ASAP as other operations depend on this */
|
||||||
mm->msgtype = msg[0] >> 3; /* Downlink Format */
|
mm->msgtype = msg[0]>>3; /* Downlink Format */
|
||||||
mm->msgbits = modesMessageLenByType(mm->msgtype);
|
mm->msgbits = modesMessageLenByType(mm->msgtype);
|
||||||
|
|
||||||
/* CRC is always the last three bytes. */
|
/* CRC is always the last three bytes. */
|
||||||
mm->crc = ((uint32_t)msg[(mm->msgbits/8)-3] << 16) |
|
mm->crc = ((uint32_t)msg[(mm->msgbits/8)-3] << 16) |
|
||||||
((uint32_t)msg[(mm->msgbits/8)-2] << 8) |
|
((uint32_t)msg[(mm->msgbits/8)-2] << 8) |
|
||||||
(uint32_t)msg[(mm->msgbits/8)-1];
|
(uint32_t)msg[(mm->msgbits/8)-1];
|
||||||
crc2 = modesChecksum(msg, mm->msgbits);
|
crc2 = modesChecksum(msg,mm->msgbits);
|
||||||
mm->iid = (mm->crc ^ crc2);
|
|
||||||
|
|
||||||
/* Check CRC and fix single bit errors using the CRC when
|
/* Check CRC and fix single bit errors using the CRC when
|
||||||
* possible (DF 11 and 17). */
|
* possible (DF 11 and 17). */
|
||||||
mm->errorbit = -1; /* No error */
|
mm->errorbit = -1; /* No error */
|
||||||
if (mm->msgtype == 11)
|
mm->crcok = (mm->crc == crc2);
|
||||||
{mm->crcok = (mm->iid < 80);}
|
|
||||||
else
|
|
||||||
{mm->crcok = (mm->iid == 0);}
|
|
||||||
|
|
||||||
if (!mm->crcok && Modes.fix_errors &&
|
if (!mm->crcok && Modes.fix_errors &&
|
||||||
(mm->msgtype == 11 || mm->msgtype == 17))
|
(mm->msgtype == 11 || mm->msgtype == 17))
|
||||||
|
@ -1180,6 +1177,7 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) {
|
||||||
* in a human readable format. */
|
* in a human readable format. */
|
||||||
void displayModesMessage(struct modesMessage *mm) {
|
void displayModesMessage(struct modesMessage *mm) {
|
||||||
int j;
|
int j;
|
||||||
|
char * pTimeStamp; //&&&
|
||||||
|
|
||||||
/* Handle only addresses mode first. */
|
/* Handle only addresses mode first. */
|
||||||
if (Modes.onlyaddr) {
|
if (Modes.onlyaddr) {
|
||||||
|
@ -1188,10 +1186,19 @@ void displayModesMessage(struct modesMessage *mm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show the raw message. */
|
/* Show the raw message. */
|
||||||
printf("*");
|
if (Modes.mlat) { //&&&
|
||||||
|
printf("@"); //&&&
|
||||||
|
pTimeStamp = (char *) &mm->timestampMsg;
|
||||||
|
for (j=5; j>=0;j--) {
|
||||||
|
printf("%02X",pTimeStamp[j]);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
printf("*");
|
||||||
|
|
||||||
for (j = 0; j < mm->msgbits/8; j++) printf("%02x", mm->msg[j]);
|
for (j = 0; j < mm->msgbits/8; j++) printf("%02x", mm->msg[j]);
|
||||||
printf(";\n");
|
printf(";\n");
|
||||||
|
|
||||||
|
|
||||||
if (Modes.raw) {
|
if (Modes.raw) {
|
||||||
fflush(stdout); /* Provide data to the reader ASAP. */
|
fflush(stdout); /* Provide data to the reader ASAP. */
|
||||||
return; /* Enough for --raw mode */
|
return; /* Enough for --raw mode */
|
||||||
|
@ -1568,7 +1575,6 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
||||||
|
|
||||||
/* Pass data to the next layer */
|
/* Pass data to the next layer */
|
||||||
useModesMessage(&mm);
|
useModesMessage(&mm);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (Modes.debug & MODES_DEBUG_DEMODERR && use_correction) {
|
if (Modes.debug & MODES_DEBUG_DEMODERR && use_correction) {
|
||||||
printf("The following message has %d demod errors\n", errors);
|
printf("The following message has %d demod errors\n", errors);
|
||||||
|
@ -1576,9 +1582,10 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retry with phase correction if possible.
|
/* Retry with phase correction if possible. */
|
||||||
if (!good_message && !use_correction && j && detectOutOfPhase(pPreamble)) {
|
if (!good_message && !use_correction && j && detectOutOfPhase(pPreamble)) {
|
||||||
use_correction = 1; j--;
|
j--;
|
||||||
|
use_correction = 1;
|
||||||
} else {
|
} else {
|
||||||
use_correction = 0;
|
use_correction = 0;
|
||||||
}
|
}
|
||||||
|
@ -1623,7 +1630,11 @@ struct aircraft *interactiveCreateAircraft(uint32_t addr) {
|
||||||
struct aircraft *a = (struct aircraft *) malloc(sizeof(*a));
|
struct aircraft *a = (struct aircraft *) malloc(sizeof(*a));
|
||||||
|
|
||||||
a->addr = addr;
|
a->addr = addr;
|
||||||
snprintf(a->hexaddr,sizeof(a->hexaddr),"%06x",(int)addr);
|
if (Modes.interactive_rtl1090 == 0) {
|
||||||
|
snprintf(a->hexaddr,sizeof(a->hexaddr),"%06x",(int)addr);
|
||||||
|
} else {
|
||||||
|
snprintf(a->hexaddr,sizeof(a->hexaddr),"%06X",(int)addr); //&&&
|
||||||
|
}
|
||||||
a->flight[0] = '\0';
|
a->flight[0] = '\0';
|
||||||
a->altitude = 0;
|
a->altitude = 0;
|
||||||
a->speed = 0;
|
a->speed = 0;
|
||||||
|
@ -1863,14 +1874,23 @@ void interactiveShowData(void) {
|
||||||
progress = spinner[time(NULL)%4];
|
progress = spinner[time(NULL)%4];
|
||||||
|
|
||||||
printf("\x1b[H\x1b[2J"); /* Clear the screen */
|
printf("\x1b[H\x1b[2J"); /* Clear the screen */
|
||||||
printf(
|
|
||||||
"Hex ModeA Flight Alt Speed Lat Lon Track Msgs Seen %c\n"
|
//&&&
|
||||||
"--------------------------------------------------------------------------------\n",
|
if (Modes.interactive_rtl1090 ==0) {
|
||||||
progress);
|
printf (
|
||||||
|
"Hex ModeA Flight Alt Speed Lat Lon Track Msgs Seen %c\n",progress);
|
||||||
|
} else {
|
||||||
|
printf (
|
||||||
|
"Hex Flight Alt V/S GS TT SSR G*456^ Msgs Seen %c\n",progress);
|
||||||
|
}
|
||||||
|
printf("--------------------------------------------------------------------------------\n");
|
||||||
|
|
||||||
while(a && count < Modes.interactive_rows) {
|
while(a && count < Modes.interactive_rows) {
|
||||||
int altitude = a->altitude, speed = a->speed, msgs = a->messages;
|
int altitude = a->altitude, speed = a->speed, msgs = a->messages;
|
||||||
char squawk[5] = "0";
|
char squawk[5] = " ";
|
||||||
|
char fl[5] = " ";
|
||||||
|
char tt[5] = " ";
|
||||||
|
char gs[5] = " ";
|
||||||
char spacer = '\0';
|
char spacer = '\0';
|
||||||
|
|
||||||
/* Convert units to metric if --metric was specified. */
|
/* Convert units to metric if --metric was specified. */
|
||||||
|
@ -1897,10 +1917,26 @@ void interactiveShowData(void) {
|
||||||
spacer = ' ';
|
spacer = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%-6s %-4s %-8s %-7d %-7d %-7.03f %-7.03f %-3d %-6d %d%c sec\n",
|
//&&&
|
||||||
a->hexaddr, squawk, a->flight, altitude, speed,
|
if (Modes.interactive_rtl1090 != 0) {
|
||||||
a->lat, a->lon, a->track, msgs, (int)(now - a->seen), spacer);
|
if (altitude>0) {
|
||||||
a = a->next;
|
altitude=altitude/100;
|
||||||
|
sprintf(fl,"F%03d",altitude);
|
||||||
|
}
|
||||||
|
if (speed > 0) {
|
||||||
|
sprintf (gs,"%3d",speed);
|
||||||
|
}
|
||||||
|
if (a->track > 0) {
|
||||||
|
sprintf (tt,"%03d",a->track);
|
||||||
|
}
|
||||||
|
printf("%-6s %-8s %-4s %-3s %-3s %4s %6d %d %c \n",
|
||||||
|
a->hexaddr, a->flight, fl, gs, tt, squawk, msgs, (int)(now - a->seen), spacer);
|
||||||
|
} else {
|
||||||
|
printf("%-6s %-4s %-8s %-7d %-7d %-7.03f %-7.03f %-3d %-6d %d%c sec\n",
|
||||||
|
a->hexaddr, squawk, a->flight, altitude, speed,
|
||||||
|
a->lat, a->lon, a->track, msgs, (int)(now - a->seen), spacer);
|
||||||
|
}
|
||||||
|
a = a->next;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2101,18 +2137,28 @@ void modesSendBeastOutput(struct modesMessage *mm) {
|
||||||
void modesSendRawOutput(struct modesMessage *mm) {
|
void modesSendRawOutput(struct modesMessage *mm) {
|
||||||
char msg[128], *p = msg;
|
char msg[128], *p = msg;
|
||||||
int j;
|
int j;
|
||||||
|
char * pTimeStamp;
|
||||||
|
|
||||||
|
if (Modes.mlat) { //&&&
|
||||||
|
*p++ = '@';
|
||||||
|
pTimeStamp = (char *) &mm->timestampMsg;
|
||||||
|
for (j = 5; j >= 0; j--) {
|
||||||
|
sprintf(p, "%02X", pTimeStamp[j]);
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
*p++ = '*';
|
||||||
|
|
||||||
*p++ = '*';
|
|
||||||
for (j = 0; j < mm->msgbits/8; j++) {
|
for (j = 0; j < mm->msgbits/8; j++) {
|
||||||
sprintf(p, "%02X", mm->msg[j]);
|
sprintf(p, "%02X", mm->msg[j]);
|
||||||
p += 2;
|
p += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
*p++ = ';';
|
*p++ = ';';
|
||||||
*p++ = '\n';
|
*p++ = '\n';
|
||||||
modesSendAllClients(Modes.ros, msg, p-msg);
|
modesSendAllClients(Modes.ros, msg, p-msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Write SBS output to TCP clients. */
|
/* Write SBS output to TCP clients. */
|
||||||
void modesSendSBSOutput(struct modesMessage *mm, struct aircraft *a) {
|
void modesSendSBSOutput(struct modesMessage *mm, struct aircraft *a) {
|
||||||
char msg[256], *p = msg;
|
char msg[256], *p = msg;
|
||||||
|
@ -2466,6 +2512,7 @@ void showHelp(void) {
|
||||||
"--interactive Interactive mode refreshing data on screen.\n"
|
"--interactive Interactive mode refreshing data on screen.\n"
|
||||||
"--interactive-rows <num> Max number of rows in interactive mode (default: 15).\n"
|
"--interactive-rows <num> Max number of rows in interactive mode (default: 15).\n"
|
||||||
"--interactive-ttl <sec> Remove from list if idle for <sec> (default: 60).\n"
|
"--interactive-ttl <sec> Remove from list if idle for <sec> (default: 60).\n"
|
||||||
|
"--interactive-rtl1090 Display flight table in RTL1090 format.\n" //&&&
|
||||||
"--raw Show only messages hex values.\n"
|
"--raw Show only messages hex values.\n"
|
||||||
"--net Enable networking.\n"
|
"--net Enable networking.\n"
|
||||||
"--net-beast TCP raw output in Beast binary format.\n"
|
"--net-beast TCP raw output in Beast binary format.\n"
|
||||||
|
@ -2477,6 +2524,7 @@ void showHelp(void) {
|
||||||
"--no-fix Disable single-bits error correction using CRC.\n"
|
"--no-fix Disable single-bits error correction using CRC.\n"
|
||||||
"--no-crc-check Disable messages with broken CRC (discouraged).\n"
|
"--no-crc-check Disable messages with broken CRC (discouraged).\n"
|
||||||
"--aggressive More CPU for more messages (two bits fixes, ...).\n"
|
"--aggressive More CPU for more messages (two bits fixes, ...).\n"
|
||||||
|
"--mlat display raw messages in Beast ascii mode.\n" //&&&
|
||||||
"--stats With --ifile print stats at exit. No other output.\n"
|
"--stats With --ifile print stats at exit. No other output.\n"
|
||||||
"--onlyaddr Show only ICAO addresses (testing purposes).\n"
|
"--onlyaddr Show only ICAO addresses (testing purposes).\n"
|
||||||
"--metric Use metric units (meters, km/h, ...).\n"
|
"--metric Use metric units (meters, km/h, ...).\n"
|
||||||
|
@ -2600,6 +2648,11 @@ int main(int argc, char **argv) {
|
||||||
Modes.ppm_error = atoi(argv[++j]);
|
Modes.ppm_error = atoi(argv[++j]);
|
||||||
} else if (!strcmp(argv[j],"--quiet")) {
|
} else if (!strcmp(argv[j],"--quiet")) {
|
||||||
Modes.quiet = 1;
|
Modes.quiet = 1;
|
||||||
|
} else if (!strcmp(argv[j],"--mlat")) {
|
||||||
|
Modes.mlat = 1; //&&&
|
||||||
|
} else if (!strcmp(argv[j],"--interactive-rtl1090")) {
|
||||||
|
Modes.interactive = 1; //&&&
|
||||||
|
Modes.interactive_rtl1090 = 1; //&&&
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Unknown or not enough arguments for option '%s'.\n\n",
|
"Unknown or not enough arguments for option '%s'.\n\n",
|
||||||
|
@ -2662,15 +2715,18 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
/* If --ifile and --stats were given, print statistics. */
|
/* If --ifile and --stats were given, print statistics. */
|
||||||
if (Modes.stats && Modes.filename) {
|
if (Modes.stats && Modes.filename) {
|
||||||
printf("%lld valid preambles\n", Modes.stat_valid_preamble);
|
printf("%lld valid preambles\n", Modes.stat_valid_preamble);
|
||||||
printf("%lld demodulated again after phase correction\n", Modes.stat_out_of_phase);
|
printf("%lld demodulated again after phase correction\n",
|
||||||
printf("%lld demodulated with zero errors\n", Modes.stat_demodulated);
|
Modes.stat_out_of_phase);
|
||||||
printf("%lld with good crc\n", Modes.stat_goodcrc);
|
printf("%lld demodulated with zero errors\n",
|
||||||
printf("%lld with bad crc\n", Modes.stat_badcrc);
|
Modes.stat_demodulated);
|
||||||
printf("%lld errors corrected\n", Modes.stat_fixed);
|
printf("%lld with good crc\n", Modes.stat_goodcrc);
|
||||||
printf("%lld single bit errors\n", Modes.stat_single_bit_fix);
|
printf("%lld with bad crc\n", Modes.stat_badcrc);
|
||||||
printf("%lld two bits errors\n", Modes.stat_two_bits_fix);
|
printf("%lld errors corrected\n", Modes.stat_fixed);
|
||||||
printf("%lld total usable messages\n", Modes.stat_goodcrc + Modes.stat_fixed);
|
printf("%lld single bit errors\n", Modes.stat_single_bit_fix);
|
||||||
|
printf("%lld two bits errors\n", Modes.stat_two_bits_fix);
|
||||||
|
printf("%lld total usable messages\n",
|
||||||
|
Modes.stat_goodcrc + Modes.stat_fixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
rtlsdr_close(Modes.dev);
|
rtlsdr_close(Modes.dev);
|
||||||
|
|
Loading…
Reference in a new issue