Improved message detection and --stats option.

The demodulation algorithm now only skips the current message if the
CRC is valid, this improves the amount of messages detected with good
CRC by ~ 4% since sometimes we are just a few samples out of sync.

This also improves the amount of messages that can be fixed.

The --stats option was added in order to better evaluate how the
algorithm performs on the same input after some change. So if you run
the program with both --ifile and --stats no Mode S message is logged
at all, but at the end of the processing the program shows you the
amount of messages decoded with good, bad crc, bit corrections, valid
preambles and so forth.
This commit is contained in:
antirez 2013-01-06 15:13:40 +01:00
parent 3833673f3f
commit 417cab5fda

View file

@ -102,6 +102,7 @@ struct {
uint32_t icao_cache[MODES_ICAO_CACHE_LEN];/* Recently seen ICAO addresses */ uint32_t icao_cache[MODES_ICAO_CACHE_LEN];/* Recently seen ICAO addresses */
int icao_cache_idx; /* icao_cache circular buf idx. */ int icao_cache_idx; /* icao_cache circular buf idx. */
unsigned char *maglut; /* I/Q -> Magnitude lookup table. */ unsigned char *maglut; /* I/Q -> Magnitude lookup table. */
int exit; /* Exit from the main loop when true. */
/* RTLSDR */ /* RTLSDR */
int dev_index; int dev_index;
@ -118,10 +119,18 @@ struct {
int debug; /* Debugging mode */ int debug; /* Debugging mode */
int interactive; /* Interactive mode */ int interactive; /* Interactive mode */
int interactive_rows; /* Interactive mode: max number of rows */ int interactive_rows; /* Interactive mode: max number of rows */
int stats; /* Print stats at exit in --ifile mode. */
/* Interactive mode */ /* Interactive mode */
struct aircraft *aircrafts; struct aircraft *aircrafts;
long long interactive_last_update; /* Last screen update in milliseconds */ long long interactive_last_update; /* Last screen update in milliseconds */
/* Statistics */
long long stat_valid_preamble;
long long stat_demodulated;
long long stat_goodcrc;
long long stat_badcrc;
long long stat_fixed;
} Modes; } Modes;
/* The struct we use to store information about a decoded message. */ /* The struct we use to store information about a decoded message. */
@ -229,6 +238,14 @@ void modesInit(void) {
Modes.maglut[i*129+q] = round(sqrt(i*i+q*q)*1.408); Modes.maglut[i*129+q] = round(sqrt(i*i+q*q)*1.408);
} }
} }
/* Statistics */
Modes.stat_valid_preamble = 0;
Modes.stat_demodulated = 0;
Modes.stat_goodcrc = 0;
Modes.stat_badcrc = 0;
Modes.stat_fixed = 0;
Modes.exit = 0;
} }
/* =============================== RTLSDR handling ========================== */ /* =============================== RTLSDR handling ========================== */
@ -314,7 +331,10 @@ void readDataFromFile(void) {
p = Modes.data; p = Modes.data;
while(toread) { while(toread) {
nread = read(Modes.fd, p, toread); nread = read(Modes.fd, p, toread);
if (nread <= 0) exit(0); if (nread <= 0) {
Modes.exit = 1; /* Signal the other thread to exit. */
break;
}
p += nread; p += nread;
toread -= nread; toread -= nread;
} }
@ -1015,6 +1035,7 @@ void detectModeS(unsigned char *m, uint32_t mlen) {
msg, m, j); msg, m, j);
continue; continue;
} }
Modes.stat_valid_preamble++;
/* Decode all the next 112 bits, regardless of the actual message /* Decode all the next 112 bits, regardless of the actual message
* size. We'll check the actual message type later. */ * size. We'll check the actual message type later. */
@ -1072,8 +1093,20 @@ void detectModeS(unsigned char *m, uint32_t mlen) {
if (errors == 0) { if (errors == 0) {
struct modesMessage mm; struct modesMessage mm;
/* Decode the received message and update statistics */
decodeModesMessage(&mm,msg); decodeModesMessage(&mm,msg);
Modes.stat_demodulated++;
if (mm.errorbit == -1) {
if (mm.crcok)
Modes.stat_goodcrc++;
else
Modes.stat_badcrc++;
} else {
Modes.stat_badcrc++;
Modes.stat_fixed++;
}
/* Output debug mode info if needed. */
if (Modes.debug == MODES_DEBUG_DEMOD) if (Modes.debug == MODES_DEBUG_DEMOD)
dumpRawMessage("Demodulated with 0 errors", msg, m, j); dumpRawMessage("Demodulated with 0 errors", msg, m, j);
else if (Modes.debug == MODES_DEBUG_BADCRC && !mm.crcok) else if (Modes.debug == MODES_DEBUG_BADCRC && !mm.crcok)
@ -1082,7 +1115,8 @@ void detectModeS(unsigned char *m, uint32_t mlen) {
mm.errorbit == -1) mm.errorbit == -1)
dumpRawMessage("Decoded with good CRC", msg, m, j); dumpRawMessage("Decoded with good CRC", msg, m, j);
if (Modes.check_crc == 0 || mm.crcok) { /* Pass data to the next layer */
if (!Modes.stats && (Modes.check_crc == 0 || mm.crcok)) {
if (Modes.interactive) { if (Modes.interactive) {
interactiveReceiveData(&mm); interactiveReceiveData(&mm);
} else { } else {
@ -1091,8 +1125,8 @@ void detectModeS(unsigned char *m, uint32_t mlen) {
} }
} }
/* Skip this message. Inside it we can find only fake premables. */ /* Skip this message if we are sure it's fine. */
j += (MODES_PREAMBLE_US+(msglen*8))*2; if (mm.crcok) j += (MODES_PREAMBLE_US+(msglen*8))*2;
} else { } else {
if (Modes.debug == MODES_DEBUG_DEMODERR) { if (Modes.debug == MODES_DEBUG_DEMODERR) {
printf("The following message has %d demod errors\n", errors); printf("The following message has %d demod errors\n", errors);
@ -1240,6 +1274,7 @@ void showHelp(void) {
"--raw Show only messages hex values.\n" "--raw Show only messages hex values.\n"
"--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.\n" "--no-crc-check Disable messages with broken CRC.\n"
"--stats With --ifile print stats at exit. No other output.\n"
"--snip <level> Strip IQ file removing samples < level.\n" "--snip <level> Strip IQ file removing samples < level.\n"
"--help Show this help.\n" "--help Show this help.\n"
); );
@ -1277,6 +1312,8 @@ int main(int argc, char **argv) {
Modes.interactive_rows = atoi(argv[++j]); Modes.interactive_rows = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--debug") && more) { } else if (!strcmp(argv[j],"--debug") && more) {
Modes.debug = atoi(argv[++j]); Modes.debug = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--stats")) {
Modes.stats = 1;
} else if (!strcmp(argv[j],"--snip") && more) { } else if (!strcmp(argv[j],"--snip") && more) {
snipMode(atoi(argv[++j])); snipMode(atoi(argv[++j]));
exit(0); exit(0);
@ -1313,6 +1350,7 @@ int main(int argc, char **argv) {
pthread_cond_wait(&Modes.data_cond,&Modes.data_mutex); pthread_cond_wait(&Modes.data_cond,&Modes.data_mutex);
continue; continue;
} }
if (Modes.exit) break;
computeMagnitudeVector(); computeMagnitudeVector();
/* If we are reading data from the RTLSDR device, process data /* If we are reading data from the RTLSDR device, process data
@ -1342,6 +1380,15 @@ int main(int argc, char **argv) {
} }
} }
/* If --ifile and --stats were given, print statistics. */
if (Modes.stats && Modes.filename) {
printf("%lld valid preambles\n", Modes.stat_valid_preamble);
printf("%lld demodulated with zero errors\n", Modes.stat_demodulated);
printf("%lld with good crc\n", Modes.stat_goodcrc);
printf("%lld with bad crc\n", Modes.stat_badcrc);
printf("%lld single bit errors corrected\n", Modes.stat_fixed);
}
rtlsdr_close(Modes.dev); rtlsdr_close(Modes.dev);
return 0; return 0;
} }