Aggressive mode implemented.
This commit is contained in:
parent
0bf65d8646
commit
dc91712741
19
README.md
19
README.md
|
@ -173,6 +173,25 @@ resources:
|
||||||
* http://www.lll.lu/~edward/edward/adsb/antenna/ADSBantenna.html
|
* http://www.lll.lu/~edward/edward/adsb/antenna/ADSBantenna.html
|
||||||
* http://modesbeast.com/pix/adsb-ant-drawing.gif
|
* http://modesbeast.com/pix/adsb-ant-drawing.gif
|
||||||
|
|
||||||
|
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
|
||||||
|
sending DF17 packets), but can detect a few more messages.
|
||||||
|
|
||||||
|
The algorithm in aggressive mode is modified in the following ways:
|
||||||
|
|
||||||
|
* Preamble detection is weakened to be more liberal in what is consdered valid.
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
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
|
Debug mode
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
90
dump1090.c
90
dump1090.c
|
@ -163,6 +163,7 @@ struct {
|
||||||
int stats; /* Print stats at exit in --ifile mode. */
|
int stats; /* Print stats at exit in --ifile mode. */
|
||||||
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. */
|
||||||
|
|
||||||
/* Interactive mode */
|
/* Interactive mode */
|
||||||
struct aircraft *aircrafts;
|
struct aircraft *aircrafts;
|
||||||
|
@ -174,6 +175,8 @@ struct {
|
||||||
long long stat_goodcrc;
|
long long stat_goodcrc;
|
||||||
long long stat_badcrc;
|
long long stat_badcrc;
|
||||||
long long stat_fixed;
|
long long stat_fixed;
|
||||||
|
long long stat_single_bit_fix;
|
||||||
|
long long stat_two_bits_fix;
|
||||||
long long stat_http_requests;
|
long long stat_http_requests;
|
||||||
} Modes;
|
} Modes;
|
||||||
|
|
||||||
|
@ -225,6 +228,8 @@ void interactiveShowData(void);
|
||||||
void interactiveReceiveData(struct modesMessage *mm);
|
void interactiveReceiveData(struct modesMessage *mm);
|
||||||
void modesSendRawOutput(struct modesMessage *mm);
|
void modesSendRawOutput(struct modesMessage *mm);
|
||||||
void useModesMessage(struct modesMessage *mm);
|
void useModesMessage(struct modesMessage *mm);
|
||||||
|
int fixSingleBitErrors(unsigned char *msg, int bits);
|
||||||
|
int fixTwoBitsErrors(unsigned char *msg, int bits);
|
||||||
|
|
||||||
/* ============================= Utility functions ========================== */
|
/* ============================= Utility functions ========================== */
|
||||||
|
|
||||||
|
@ -259,6 +264,7 @@ void modesInitConfig(void) {
|
||||||
Modes.interactive = 0;
|
Modes.interactive = 0;
|
||||||
Modes.interactive_rows = MODES_INTERACTIVE_ROWS;
|
Modes.interactive_rows = MODES_INTERACTIVE_ROWS;
|
||||||
Modes.interactive_ttl = MODES_INTERACTIVE_TTL;
|
Modes.interactive_ttl = MODES_INTERACTIVE_TTL;
|
||||||
|
Modes.aggressive = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void modesInit(void) {
|
void modesInit(void) {
|
||||||
|
@ -300,6 +306,8 @@ void modesInit(void) {
|
||||||
Modes.stat_goodcrc = 0;
|
Modes.stat_goodcrc = 0;
|
||||||
Modes.stat_badcrc = 0;
|
Modes.stat_badcrc = 0;
|
||||||
Modes.stat_fixed = 0;
|
Modes.stat_fixed = 0;
|
||||||
|
Modes.stat_single_bit_fix = 0;
|
||||||
|
Modes.stat_two_bits_fix = 0;
|
||||||
Modes.stat_http_requests = 0;
|
Modes.stat_http_requests = 0;
|
||||||
Modes.exit = 0;
|
Modes.exit = 0;
|
||||||
}
|
}
|
||||||
|
@ -496,13 +504,22 @@ void dumpRawMessage(char *descr, unsigned char *msg,
|
||||||
uint16_t *m, uint32_t offset)
|
uint16_t *m, uint32_t offset)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
|
int msgtype = msg[0]>>3;
|
||||||
|
int fixable = 0;
|
||||||
|
|
||||||
|
if (msgtype == 11 || msgtype == 17) {
|
||||||
|
int msgbits = (msgtype == 11) ? MODES_SHORT_MSG_BITS :
|
||||||
|
MODES_LONG_MSG_BITS;
|
||||||
|
if (fixSingleBitErrors(msg,msgbits) != -1) fixable = 1;
|
||||||
|
else if (fixTwoBitsErrors(msg,msgbits) != -1) fixable = 2;
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n--- %s\n ", descr);
|
printf("\n--- %s\n ", descr);
|
||||||
for (j = 0; j < MODES_LONG_MSG_BYTES; j++) {
|
for (j = 0; j < MODES_LONG_MSG_BYTES; j++) {
|
||||||
printf("%02x",msg[j]);
|
printf("%02x",msg[j]);
|
||||||
if (j == MODES_SHORT_MSG_BYTES-1) printf(" ... ");
|
if (j == MODES_SHORT_MSG_BYTES-1) printf(" ... ");
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf(" (DF %d, Fixable: %d)\n", msgtype, fixable);
|
||||||
dumpMagnitudeVector(m,offset);
|
dumpMagnitudeVector(m,offset);
|
||||||
printf("---\n\n");
|
printf("---\n\n");
|
||||||
}
|
}
|
||||||
|
@ -603,6 +620,44 @@ int fixSingleBitErrors(unsigned char *msg, int bits) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Similar to fixSingleBitErrors() but try every possible two bit combination.
|
||||||
|
* This is very slow and should be tried only against DF17 messages that
|
||||||
|
* don't pass the checksum, and only in Aggressive Mode. */
|
||||||
|
int fixTwoBitsErrors(unsigned char *msg, int bits) {
|
||||||
|
int j, i;
|
||||||
|
unsigned char aux[MODES_LONG_MSG_BITS/8];
|
||||||
|
|
||||||
|
for (j = 0; j < bits; j++) {
|
||||||
|
int byte1 = j/8;
|
||||||
|
int bitmask1 = 1 << (7-(j%8));
|
||||||
|
|
||||||
|
for (i = j+1; i < bits; i++) {
|
||||||
|
int byte2 = i/8;
|
||||||
|
int bitmask2 = 1 << (7-(i%8));
|
||||||
|
uint32_t crc1, crc2;
|
||||||
|
|
||||||
|
memcpy(aux,msg,bits/8);
|
||||||
|
|
||||||
|
aux[byte1] ^= bitmask1; /* Flip j-th bit. */
|
||||||
|
aux[byte2] ^= bitmask2; /* Flip i-th bit. */
|
||||||
|
|
||||||
|
crc1 = ((uint32_t)aux[(bits/8)-3] << 16) |
|
||||||
|
((uint32_t)aux[(bits/8)-2] << 8) |
|
||||||
|
(uint32_t)aux[(bits/8)-1];
|
||||||
|
crc2 = modesChecksum(aux,bits);
|
||||||
|
|
||||||
|
if (crc1 == crc2) {
|
||||||
|
/* The error is fixed. Overwrite the original buffer with
|
||||||
|
* the corrected sequence, and returns the error bit
|
||||||
|
* position. */
|
||||||
|
memcpy(msg,aux,bits/8);
|
||||||
|
return j | (i<<8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Hash the ICAO address to index our cache of MODES_ICAO_CACHE_LEN
|
/* Hash the ICAO address to index our cache of MODES_ICAO_CACHE_LEN
|
||||||
* elements, that is assumed to be a power of two. */
|
* elements, that is assumed to be a power of two. */
|
||||||
uint32_t ICAOCacheHashAddress(uint32_t a) {
|
uint32_t ICAOCacheHashAddress(uint32_t a) {
|
||||||
|
@ -823,6 +878,11 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) {
|
||||||
if ((mm->errorbit = fixSingleBitErrors(msg,mm->msgbits)) != -1) {
|
if ((mm->errorbit = fixSingleBitErrors(msg,mm->msgbits)) != -1) {
|
||||||
mm->crc = modesChecksum(msg,mm->msgbits);
|
mm->crc = modesChecksum(msg,mm->msgbits);
|
||||||
mm->crcok = 1;
|
mm->crcok = 1;
|
||||||
|
} else if (Modes.aggressive && mm->msgtype == 17 &&
|
||||||
|
(mm->errorbit = fixTwoBitsErrors(msg,mm->msgbits)) != -1)
|
||||||
|
{
|
||||||
|
mm->crc = modesChecksum(msg,mm->msgbits);
|
||||||
|
mm->crcok = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1133,6 +1193,7 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Modes.aggressive) {
|
||||||
/* The samples between the two spikes must be < than the average
|
/* The samples between the two spikes must be < than the average
|
||||||
* of the high spikes level. */
|
* of the high spikes level. */
|
||||||
high = (m[j]+m[j+2]+m[j+7]+m[j+9])/4;
|
high = (m[j]+m[j+2]+m[j+7]+m[j+9])/4;
|
||||||
|
@ -1143,7 +1204,8 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
||||||
{
|
{
|
||||||
if (Modes.debug == MODES_DEBUG_NOPREAMBLE &&
|
if (Modes.debug == MODES_DEBUG_NOPREAMBLE &&
|
||||||
m[j] > MODES_DEBUG_NOPREAMBLE_LEVEL)
|
m[j] > MODES_DEBUG_NOPREAMBLE_LEVEL)
|
||||||
dumpRawMessage("Too high level in samples between 3 and 6",
|
dumpRawMessage(
|
||||||
|
"Too high level in samples between 3 and 6",
|
||||||
msg, m, j);
|
msg, m, j);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1159,10 +1221,12 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
||||||
{
|
{
|
||||||
if (Modes.debug == MODES_DEBUG_NOPREAMBLE &&
|
if (Modes.debug == MODES_DEBUG_NOPREAMBLE &&
|
||||||
m[j] > MODES_DEBUG_NOPREAMBLE_LEVEL)
|
m[j] > MODES_DEBUG_NOPREAMBLE_LEVEL)
|
||||||
dumpRawMessage("Too high level in samples between 10 and 15",
|
dumpRawMessage(
|
||||||
|
"Too high level in samples between 10 and 15",
|
||||||
msg, m, j);
|
msg, m, j);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Modes.stat_valid_preamble++;
|
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
|
||||||
|
@ -1218,12 +1282,12 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
||||||
/* If we reached this point, and error is zero, we are very likely
|
/* If we reached this point, and error is zero, we are very likely
|
||||||
* with a Mode S message in our hands, but it may still be broken
|
* with a Mode S message in our hands, but it may still be broken
|
||||||
* and CRC may not be correct. This is handled by the next layer. */
|
* and CRC may not be correct. This is handled by the next layer. */
|
||||||
if (errors == 0) {
|
if (errors == 0 || (Modes.aggressive && errors < 3)) {
|
||||||
struct modesMessage mm;
|
struct modesMessage mm;
|
||||||
|
|
||||||
/* Decode the received message and update statistics */
|
/* Decode the received message and update statistics */
|
||||||
decodeModesMessage(&mm,msg);
|
decodeModesMessage(&mm,msg);
|
||||||
Modes.stat_demodulated++;
|
if (errors == 0) Modes.stat_demodulated++;
|
||||||
if (mm.errorbit == -1) {
|
if (mm.errorbit == -1) {
|
||||||
if (mm.crcok)
|
if (mm.crcok)
|
||||||
Modes.stat_goodcrc++;
|
Modes.stat_goodcrc++;
|
||||||
|
@ -1232,12 +1296,17 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
|
||||||
} else {
|
} else {
|
||||||
Modes.stat_badcrc++;
|
Modes.stat_badcrc++;
|
||||||
Modes.stat_fixed++;
|
Modes.stat_fixed++;
|
||||||
|
if (mm.errorbit < MODES_LONG_MSG_BITS)
|
||||||
|
Modes.stat_single_bit_fix++;
|
||||||
|
else
|
||||||
|
Modes.stat_two_bits_fix++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output debug mode info if needed. */
|
/* 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 || mm.errorbit != -1))
|
||||||
dumpRawMessage("Decoded with bad CRC", msg, m, j);
|
dumpRawMessage("Decoded with bad CRC", msg, m, j);
|
||||||
else if (Modes.debug == MODES_DEBUG_GOODCRC && mm.crcok &&
|
else if (Modes.debug == MODES_DEBUG_GOODCRC && mm.crcok &&
|
||||||
mm.errorbit == -1)
|
mm.errorbit == -1)
|
||||||
|
@ -2002,6 +2071,7 @@ void showHelp(void) {
|
||||||
"--net-http-port <port> HTTP server port (default: 8080).\n"
|
"--net-http-port <port> HTTP server port (default: 8080).\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 (discouraged).\n"
|
"--no-crc-check Disable messages with broken CRC (discouraged).\n"
|
||||||
|
"--aggressive More CPU for more messages (two bits fixes, ...).\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"
|
||||||
|
@ -2072,6 +2142,8 @@ int main(int argc, char **argv) {
|
||||||
Modes.onlyaddr = 1;
|
Modes.onlyaddr = 1;
|
||||||
} else if (!strcmp(argv[j],"--metric")) {
|
} else if (!strcmp(argv[j],"--metric")) {
|
||||||
Modes.metric = 1;
|
Modes.metric = 1;
|
||||||
|
} else if (!strcmp(argv[j],"--aggressive")) {
|
||||||
|
Modes.aggressive++;
|
||||||
} else if (!strcmp(argv[j],"--interactive")) {
|
} else if (!strcmp(argv[j],"--interactive")) {
|
||||||
Modes.interactive = 1;
|
Modes.interactive = 1;
|
||||||
} else if (!strcmp(argv[j],"--interactive-rows")) {
|
} else if (!strcmp(argv[j],"--interactive-rows")) {
|
||||||
|
@ -2153,7 +2225,11 @@ int main(int argc, char **argv) {
|
||||||
printf("%lld demodulated with zero errors\n", Modes.stat_demodulated);
|
printf("%lld demodulated with zero errors\n", Modes.stat_demodulated);
|
||||||
printf("%lld with good crc\n", Modes.stat_goodcrc);
|
printf("%lld with good crc\n", Modes.stat_goodcrc);
|
||||||
printf("%lld with bad crc\n", Modes.stat_badcrc);
|
printf("%lld with bad crc\n", Modes.stat_badcrc);
|
||||||
printf("%lld single bit errors corrected\n", Modes.stat_fixed);
|
printf("%lld errors corrected\n", 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