UKUEHN : Various Improvements
Sorry Ulrich - I can't get Github to resolve the merge errors and preserve your commit notes, so I'll add them here. Improvements on bit error correction, doc update, preparation for program installation/package build Hi, I committed some further improvements on the bit error correction code, updated the readme, and implemented a way to install the program in the linux file system hierarchy (allows for package building). Regards, Ulrich
This commit is contained in:
parent
ee742cf8db
commit
9edba9332a
16
Makefile
16
Makefile
|
@ -1,12 +1,24 @@
|
|||
#
|
||||
# When building a package or installing otherwise in the system, make
|
||||
# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local
|
||||
#
|
||||
PROGNAME=dump1090
|
||||
|
||||
ifdef PREFIX
|
||||
BINDIR=$(PREFIX)/bin
|
||||
SHAREDIR=$(PREFIX)/share/$(PROGNAME)
|
||||
EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\"
|
||||
endif
|
||||
|
||||
CFLAGS=-O2 -g -Wall -W `pkg-config --cflags librtlsdr`
|
||||
LIBS=`pkg-config --libs librtlsdr` -lpthread -lm
|
||||
CC=gcc
|
||||
PROGNAME=dump1090
|
||||
|
||||
|
||||
all: dump1090
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
$(CC) $(CFLAGS) $(EXTRACFLAGS) -c $<
|
||||
|
||||
dump1090: dump1090.o anet.o
|
||||
$(CC) -g -o dump1090 dump1090.o anet.o $(LIBS)
|
||||
|
|
25
README.md
25
README.md
|
@ -86,9 +86,13 @@ it without arguments at all is the best thing to do.
|
|||
Reliability
|
||||
---
|
||||
|
||||
By default Dump1090 tries to fix single bit errors using the checksum.
|
||||
Basically the program will try to flip every bit of the message and check if
|
||||
the checksum of the resulting message matches.
|
||||
By default Dump1090 checks for decoding errors using the 24-bit CRC checksum,
|
||||
where available. Messages with errors are discarded.
|
||||
|
||||
The --fix command line switch enables fixing single bit error correction
|
||||
based on the CRC checksum. Technically, it uses a table of precomputed
|
||||
checksum differences resulting from single bit errors to look up the
|
||||
wrong bit position.
|
||||
|
||||
This is indeed able to fix errors and works reliably in my experience,
|
||||
however if you are interested in very reliable data I suggest to use
|
||||
|
@ -190,18 +194,19 @@ Aggressive mode
|
|||
|
||||
With --aggressive it is possible to activate the *aggressive mode* that is a
|
||||
modified version of the Mode S packet detection and decoding.
|
||||
THe aggresive mode uses more CPU usually (especially if there are many planes
|
||||
The aggresive mode uses more CPU usually (especially if there are many planes
|
||||
sending DF17 packets), but can detect a few more messages.
|
||||
|
||||
The algorithm in aggressive mode is modified in the following ways:
|
||||
|
||||
* Up to two demodulation errors are tolerated (adjacent entires in the magnitude
|
||||
vector with the same eight). Normally only messages without errors are
|
||||
checked.
|
||||
* It tries to fix DF17 messages trying every two bits combination.
|
||||
* Up to two demodulation errors are tolerated (adjacent entires in the
|
||||
magnitude vector with the same eight). Normally only messages without
|
||||
errors are checked.
|
||||
* It tries to fix DF17 messages with CRC errors resulting from any two bit
|
||||
errors.
|
||||
|
||||
The use of aggressive mdoe is only advised in places where there is low traffic
|
||||
in order to have a chance to capture some more messages.
|
||||
The use of aggressive mdoe is only advised in places where there is
|
||||
low traffic in order to have a chance to capture some more messages.
|
||||
|
||||
Debug mode
|
||||
---
|
||||
|
|
122
dump1090.c
122
dump1090.c
|
@ -72,6 +72,9 @@
|
|||
#define MODES_MSG_SQUELCH_LEVEL 0x02FF /* Average signal strength limit */
|
||||
#define MODES_MSG_ENCODER_ERRS 3 /* Maximum number of encoding errors */
|
||||
|
||||
/* When changing, change also fixBitErrors() and modesInitErrorTable() !! */
|
||||
#define MODES_MAX_BITERRORS 2 /* Global max for fixable bit erros */
|
||||
|
||||
#define MODEAC_MSG_SAMPLES (25 * 2) /* include up to the SPI bit */
|
||||
#define MODEAC_MSG_BYTES 2
|
||||
#define MODEAC_MSG_SQUELCH_LEVEL 0x07FF /* Average signal strength limit */
|
||||
|
@ -150,6 +153,10 @@
|
|||
#define MODES_CLIENT_BUF_SIZE 1024
|
||||
#define MODES_NET_SNDBUF_SIZE (1024*64)
|
||||
|
||||
#ifndef HTMLPATH
|
||||
#define HTMLPATH "./public_html" /* default path for gmap.html etc. */
|
||||
#endif
|
||||
|
||||
#define MODES_NOTUSED(V) ((void) V)
|
||||
|
||||
/* Structure used to describe a networking client. */
|
||||
|
@ -229,7 +236,7 @@ struct {
|
|||
/* Configuration */
|
||||
char *filename; /* Input form file, --ifile option. */
|
||||
int phase_enhance; /* Enable phase enhancement if true */
|
||||
int fix_errors; /* Single bit error correction if true. */
|
||||
int fix_errors; /* If > 0 no of bit errors to fix */
|
||||
int check_crc; /* Only display messages with good CRC. */
|
||||
int raw; /* Raw output format. */
|
||||
int beast; /* Beast binary format output. */
|
||||
|
@ -273,8 +280,12 @@ struct {
|
|||
unsigned int stat_goodcrc;
|
||||
unsigned int stat_badcrc;
|
||||
unsigned int stat_fixed;
|
||||
unsigned int stat_single_bit_fix;
|
||||
unsigned int stat_two_bits_fix;
|
||||
|
||||
/* Histogram of fixed bit errors: index 0 for single bit erros,
|
||||
* index 1 for double bit errors etc.
|
||||
*/
|
||||
unsigned int stat_bit_fix[MODES_MAX_BITERRORS];
|
||||
|
||||
unsigned int stat_http_requests;
|
||||
unsigned int stat_sbs_connections;
|
||||
unsigned int stat_out_of_phase;
|
||||
|
@ -301,6 +312,7 @@ struct modesMessage {
|
|||
int crcok; // True if CRC was valid
|
||||
uint32_t crc; // Message CRC
|
||||
int correctedbits; // No. of bits corrected
|
||||
int corrected[MODES_MAX_BITERRORS]; // corrected bit positions
|
||||
uint32_t addr; // ICAO Address from bytes 1 2 and 3
|
||||
int phase_corrected; // True if phase correction was applied
|
||||
uint64_t timestampMsg; // Timestamp of the message
|
||||
|
@ -341,7 +353,7 @@ void modesSendRawOutput(struct modesMessage *mm);
|
|||
void modesSendBeastOutput(struct modesMessage *mm);
|
||||
void modesSendSBSOutput(struct modesMessage *mm);
|
||||
void useModesMessage(struct modesMessage *mm);
|
||||
int fixBitErrors(unsigned char *msg, int bits);
|
||||
int fixBitErrors(unsigned char *msg, int bits, int maxfixable, int *bitpos);
|
||||
int fixSingleBitErrors(unsigned char *msg, int bits);
|
||||
int fixTwoBitsErrors(unsigned char *msg, int bits);
|
||||
void modesInitErrorInfo();
|
||||
|
@ -672,7 +684,7 @@ void dumpMagnitudeVector(uint16_t *m, uint32_t offset) {
|
|||
/* Produce a raw representation of the message as a Javascript file
|
||||
* loadable by debug.html. */
|
||||
void dumpRawMessageJS(char *descr, unsigned char *msg,
|
||||
uint16_t *m, uint32_t offset, int fixable)
|
||||
uint16_t *m, uint32_t offset, int fixable, int *bitpos)
|
||||
{
|
||||
int padding = 5; /* Show a few samples before the actual start. */
|
||||
int start = offset - padding;
|
||||
|
@ -680,6 +692,7 @@ void dumpRawMessageJS(char *descr, unsigned char *msg,
|
|||
FILE *fp;
|
||||
int j;
|
||||
|
||||
MODES_NOTUSED(fixable);
|
||||
if ((fp = fopen("frames.js","a")) == NULL) {
|
||||
fprintf(stderr, "Error opening frames.js: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
|
@ -690,8 +703,8 @@ void dumpRawMessageJS(char *descr, unsigned char *msg,
|
|||
fprintf(fp,"%d", j < 0 ? 0 : m[j]);
|
||||
if (j != end) fprintf(fp,",");
|
||||
}
|
||||
fprintf(fp,"], \"fixed\": %d, \"bits\": %d, \"hex\": \"",
|
||||
fixable, modesMessageLenByType(msg[0]>>3));
|
||||
fprintf(fp,"], \"fix1\": %d, \"fix2\": %d, \"bits\": %d, \"hex\": \"",
|
||||
bitpos[0], bitpos[1] , modesMessageLenByType(msg[0]>>3));
|
||||
for (j = 0; j < MODES_LONG_MSG_BYTES; j++)
|
||||
fprintf(fp,"\\x%02x",msg[j]);
|
||||
fprintf(fp,"\"});\n");
|
||||
|
@ -716,13 +729,18 @@ void dumpRawMessage(char *descr, unsigned char *msg,
|
|||
int j;
|
||||
int msgtype = msg[0] >> 3;
|
||||
int fixable = 0;
|
||||
int bitpos[MODES_MAX_BITERRORS];
|
||||
|
||||
for (j = 0; j < MODES_MAX_BITERRORS; j++) {
|
||||
bitpos[j] = -1;
|
||||
}
|
||||
if (msgtype == 17) {
|
||||
fixable = fixBitErrors(msg, MODES_LONG_MSG_BITS);
|
||||
fixable = fixBitErrors(msg, MODES_LONG_MSG_BITS,
|
||||
MODES_MAX_BITERRORS, bitpos);
|
||||
}
|
||||
|
||||
if (Modes.debug & MODES_DEBUG_JS) {
|
||||
dumpRawMessageJS(descr, msg, m, offset, fixable);
|
||||
dumpRawMessageJS(descr, msg, m, offset, fixable, bitpos);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1253,8 +1271,8 @@ int fixTwoBitsErrors(unsigned char *msg, int bits) {
|
|||
*/
|
||||
struct errorinfo {
|
||||
uint32_t syndrome; /* CRC syndrome */
|
||||
int pos0; /* bit position of first error */
|
||||
int pos1; /* bit position of second error, or -1 */
|
||||
int bits; /* No of bit positions to fix */
|
||||
int pos[MODES_MAX_BITERRORS]; /* bit positions */
|
||||
};
|
||||
|
||||
#define NERRORINFO \
|
||||
|
@ -1290,8 +1308,9 @@ void modesInitErrorInfo() {
|
|||
msg[bytepos0] ^= mask0; // create error0
|
||||
crc = modesChecksum(msg, MODES_LONG_MSG_BITS);
|
||||
bitErrorTable[n].syndrome = crc; // single bit error case
|
||||
bitErrorTable[n].pos0 = i;
|
||||
bitErrorTable[n].pos1 = -1;
|
||||
bitErrorTable[n].bits = 1;
|
||||
bitErrorTable[n].pos[0] = i;
|
||||
bitErrorTable[n].pos[1] = -1;
|
||||
n += 1;
|
||||
|
||||
if (Modes.aggressive) {
|
||||
|
@ -1308,9 +1327,10 @@ void modesInitErrorInfo() {
|
|||
*/
|
||||
break;
|
||||
}
|
||||
bitErrorTable[n].syndrome = crc; // two bit error case
|
||||
bitErrorTable[n].pos0 = i;
|
||||
bitErrorTable[n].pos1 = j;
|
||||
bitErrorTable[n].syndrome = crc; // two bit error case
|
||||
bitErrorTable[n].bits = 2;
|
||||
bitErrorTable[n].pos[0] = i;
|
||||
bitErrorTable[n].pos[1] = j;
|
||||
n += 1;
|
||||
msg[bytepos1] ^= mask1; // revert error1
|
||||
}
|
||||
|
@ -1362,35 +1382,43 @@ int flipBit(unsigned char *msg, int nbits, int bit) {
|
|||
// Search syndrome in table and, if an entry is found, flip the necessary
|
||||
// bits. Make sure the indices fit into the array, and for 2-bit errors,
|
||||
// are different.
|
||||
// Additional parameter: fix only less than maxcorrected bits, and record
|
||||
// fixed bit positions in corrected[]. This array can be NULL, otherwise
|
||||
// must be of length at least maxcorrected.
|
||||
// Return number of fixed bits.
|
||||
//
|
||||
int fixBitErrors(unsigned char *msg, int bits) {
|
||||
int fixBitErrors(unsigned char *msg, int bits,
|
||||
int maxfixable, int *fixedbitpos) {
|
||||
struct errorinfo *pei;
|
||||
struct errorinfo ei;
|
||||
int bitpos0, bitpos1, offset, res;
|
||||
int bitpos, offset, res, i;
|
||||
memset(&ei, 0, sizeof(struct errorinfo));
|
||||
ei.syndrome = modesChecksum(msg, bits);
|
||||
ei.pos0 = -1;
|
||||
ei.pos1 = -1;
|
||||
pei = bsearch(&ei, bitErrorTable, NERRORINFO,
|
||||
sizeof(struct errorinfo), cmpErrorInfo);
|
||||
if (pei == NULL) {
|
||||
return 0; // No syndrome found
|
||||
}
|
||||
if (maxfixable < pei->bits) {
|
||||
return 0;
|
||||
}
|
||||
res = 0;
|
||||
offset = MODES_LONG_MSG_BITS-bits;
|
||||
bitpos0 = pei->pos0 - offset;
|
||||
if ((bitpos0 < 0) || (bitpos0 >= bits)) {
|
||||
return 0;
|
||||
/* Check that all bit positions are inside message boundaries */
|
||||
for (i = 0; i < pei->bits; i++) {
|
||||
bitpos = pei->pos[i] - offset;
|
||||
if ((bitpos < 0) || (bitpos >= bits)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
msg[(bitpos0 >> 3)] ^= (1 << (7 - (bitpos0 & 7)));
|
||||
res++;
|
||||
if (pei->pos1 >= 0) { /* two-bit error pattern */
|
||||
bitpos1 = pei->pos1 - offset;
|
||||
if ((bitpos1 < 0) || (bitpos1 >= bits)) {
|
||||
return 0;
|
||||
}
|
||||
msg[(bitpos1 >> 3)] ^= (1 << (7 - (bitpos1 & 7)));
|
||||
res++;
|
||||
/* Fix the bits */
|
||||
for (i = 0; i < pei->bits; i++) {
|
||||
bitpos = pei->pos[i] - offset;
|
||||
msg[(bitpos >> 3)] ^= (1 << (7 - (bitpos & 7)));
|
||||
if (fixedbitpos != NULL) {
|
||||
fixedbitpos[res] = bitpos;
|
||||
}
|
||||
res++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -1492,7 +1520,8 @@ void testAndTimeBitCorrection() {
|
|||
inittmsg1();
|
||||
gettimeofday(&starttv, NULL);
|
||||
for (i = 0; i < MODES_LONG_MSG_BITS; i++) {
|
||||
fixBitErrors(&tmsg1[i][0], MODES_LONG_MSG_BITS);
|
||||
fixBitErrors(&tmsg1[i][0], MODES_LONG_MSG_BITS,
|
||||
MODES_MAX_BITERRORS, NULL);
|
||||
}
|
||||
gettimeofday(&endtv, NULL);
|
||||
printf(" New code: 1-bit errors on %d msgs: %ld usecs\n",
|
||||
|
@ -1511,7 +1540,8 @@ void testAndTimeBitCorrection() {
|
|||
inittmsg2();
|
||||
gettimeofday(&starttv, NULL);
|
||||
for (i = 0; i < NTWOBITS; i++) {
|
||||
fixBitErrors(&tmsg2[i][0], MODES_LONG_MSG_BITS);
|
||||
fixBitErrors(&tmsg2[i][0], MODES_LONG_MSG_BITS,
|
||||
MODES_MAX_BITERRORS, NULL);
|
||||
}
|
||||
gettimeofday(&endtv, NULL);
|
||||
printf(" New code: 2-bit errors on %d msgs: %ld usecs\n",
|
||||
|
@ -1745,7 +1775,8 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) {
|
|||
// using the results. Perhaps check the ICAO against known aircraft, and check
|
||||
// IID against known good IID's. That's a TODO.
|
||||
//
|
||||
mm->correctedbits = fixBitErrors(msg, mm->msgbits);
|
||||
mm->correctedbits = fixBitErrors(msg, mm->msgbits,
|
||||
Modes.fix_errors, mm->corrected);
|
||||
// If we correct, validate ICAO addr to help filter birthday paradox solutions.
|
||||
if (mm->correctedbits) {
|
||||
uint32_t addr = (msg[1] << 16) | (msg[2] << 8) | (msg[3]);
|
||||
|
@ -2601,11 +2632,10 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
|||
|
||||
} else {
|
||||
Modes.stat_badcrc++;
|
||||
Modes.stat_fixed++;
|
||||
if (mm.correctedbits == 1) {
|
||||
Modes.stat_single_bit_fix++;
|
||||
} else if (mm.correctedbits == 2) {
|
||||
Modes.stat_two_bits_fix++;
|
||||
Modes.stat_fixed += 1;
|
||||
if ((mm.correctedbits > 0) &&
|
||||
(mm.correctedbits <= MODES_MAX_BITERRORS)) {
|
||||
Modes.stat_bit_fix[mm.correctedbits-1] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3858,9 +3888,10 @@ int handleHTTPRequest(struct client *c) {
|
|||
}
|
||||
|
||||
if (strlen(url) < 2) {
|
||||
snprintf(getFile, sizeof getFile, "./public_html/gmap.html"); // Default file
|
||||
snprintf(getFile, sizeof getFile, "%s/%s",
|
||||
HTMLPATH, "gmap.html"); // Default file
|
||||
} else {
|
||||
snprintf(getFile, sizeof getFile, "./public_html%s", url);
|
||||
snprintf(getFile, sizeof getFile, "%s/%s", HTMLPATH, url);
|
||||
}
|
||||
|
||||
/* Select the content to send, we have just two so far:
|
||||
|
@ -4155,7 +4186,7 @@ int main(int argc, char **argv) {
|
|||
Modes.metric = 1;
|
||||
} else if (!strcmp(argv[j],"--aggressive")) {
|
||||
Modes.aggressive = 1;
|
||||
Modes.fix_errors = 1;
|
||||
Modes.fix_errors = MODES_MAX_BITERRORS;
|
||||
} else if (!strcmp(argv[j],"--interactive")) {
|
||||
Modes.interactive = 1;
|
||||
} else if (!strcmp(argv[j],"--interactive-rows") && more) {
|
||||
|
@ -4280,8 +4311,9 @@ int main(int argc, char **argv) {
|
|||
printf("%d with good crc\n", Modes.stat_goodcrc);
|
||||
printf("%d with bad crc\n", Modes.stat_badcrc);
|
||||
printf("%d errors corrected\n", Modes.stat_fixed);
|
||||
printf("%d single bit errors\n", Modes.stat_single_bit_fix);
|
||||
printf("%d two bits errors\n", Modes.stat_two_bits_fix);
|
||||
for (j = 0; j < MODES_MAX_BITERRORS; j++) {
|
||||
printf(" %d with %d bit %s\n", Modes.stat_bit_fix[j], j+1, (j==0)?"error":"errors");
|
||||
}
|
||||
printf("%d phase enhancement attempts\n", Modes.stat_out_of_phase);
|
||||
printf("%d phase enhanced demodulated with 0 errors\n", Modes.stat_ph_demodulated0);
|
||||
printf("%d phase enhanced demodulated with 1 error\n", Modes.stat_ph_demodulated1);
|
||||
|
|
Loading…
Reference in a new issue