diff --git a/dump1090.c b/dump1090.c index 0fb1fa6..e3bd9ef 100644 --- a/dump1090.c +++ b/dump1090.c @@ -494,6 +494,44 @@ void showCopyright(void) { #endif +static void display_demod_stats(const char *prefix, struct demod_stats *dstats) { + int j; + + printf("%d %sdemodulated with 0 errors\n", dstats->demodulated0, prefix); + printf("%d %sdemodulated with 1 error\n", dstats->demodulated1, prefix); + printf("%d %sdemodulated with 2 errors\n", dstats->demodulated2, prefix); + printf("%d %sdemodulated with > 2 errors\n", dstats->demodulated3, prefix); + printf("%d %swith good crc\n", dstats->goodcrc, prefix); + for (j = 0; j < MODES_MAX_PHASE_STATS; ++j) + if (dstats->goodcrc_byphase[j] > 0) + printf(" %d %swith phase offset %d\n", dstats->goodcrc_byphase[j], prefix, j); + printf("%d %swith bad crc\n", dstats->badcrc, prefix); + printf("%d %serrors corrected\n", dstats->fixed, prefix); + + for (j = 0; j < MODES_MAX_BITERRORS; j++) { + printf(" %d %swith %d bit %s\n", dstats->bit_fix[j], prefix, j+1, (j==0)?"error":"errors"); + } +} + +static void reset_demod_stats(struct demod_stats *dstats) { + int j; + + dstats->demodulated0 = + dstats->demodulated1 = + dstats->demodulated2 = + dstats->goodcrc = + dstats->badcrc = + dstats->fixed = 0; + + for (j = 0; j < MODES_MAX_BITERRORS; j++) { + dstats->bit_fix[j] = 0; + } + + for (j = 0; j < MODES_MAX_PHASE_STATS; j++) { + dstats->goodcrc_byphase[j] = 0; + } +} + static void display_stats(void) { int j; time_t now = time(NULL); @@ -523,37 +561,16 @@ static void display_stats(void) { printf(" %d with phase offset %d\n", Modes.stat_preamble_phase[j], j); printf("%d DF-?? fields corrected for length\n", Modes.stat_DF_Len_Corrected); printf("%d DF-?? fields corrected for type\n", Modes.stat_DF_Type_Corrected); - printf("%d demodulated with 0 errors\n", Modes.stat_demodulated0); - printf("%d demodulated with 1 error\n", Modes.stat_demodulated1); - printf("%d demodulated with 2 errors\n", Modes.stat_demodulated2); - printf("%d demodulated with > 2 errors\n", Modes.stat_demodulated3); - printf("%d with good crc\n", Modes.stat_goodcrc); - for (j = 0; j < MODES_MAX_PHASE_STATS; ++j) - if (Modes.stat_goodcrc_phase[j] > 0) - printf(" %d with phase offset %d\n", Modes.stat_goodcrc_phase[j], j); - printf("%d with bad crc\n", Modes.stat_badcrc); - printf("%d errors corrected\n", Modes.stat_fixed); - - 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"); - } + display_demod_stats("", &Modes.stat_demod); if (Modes.phase_enhance) { 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); - printf("%d phase enhanced demodulated with 2 errors\n", Modes.stat_ph_demodulated2); - printf("%d phase enhanced demodulated with > 2 errors\n", Modes.stat_ph_demodulated3); - printf("%d phase enhanced with good crc\n", Modes.stat_ph_goodcrc); - printf("%d phase enhanced with bad crc\n", Modes.stat_ph_badcrc); - printf("%d phase enhanced errors corrected\n", Modes.stat_ph_fixed); - - for (j = 0; j < MODES_MAX_BITERRORS; j++) { - printf(" %d with %d bit %s\n", Modes.stat_ph_bit_fix[j], j+1, (j==0)?"error":"errors"); - } + display_demod_stats("phase enhanced ", &Modes.stat_demod_phasecorrected); } - printf("%d total usable messages\n", Modes.stat_goodcrc + Modes.stat_ph_goodcrc + Modes.stat_fixed + Modes.stat_ph_fixed); + printf("%d total usable messages\n", + Modes.stat_demod.goodcrc + Modes.stat_demod_phasecorrected.goodcrc + + Modes.stat_demod.fixed + Modes.stat_demod_phasecorrected.fixed); fflush(stdout); Modes.stat_cputime.tv_sec = 0; @@ -567,33 +584,15 @@ static void display_stats(void) { Modes.stat_preamble_not_quiet = Modes.stat_valid_preamble = Modes.stat_DF_Len_Corrected = - Modes.stat_DF_Type_Corrected = - Modes.stat_demodulated0 = - Modes.stat_demodulated1 = - Modes.stat_demodulated2 = - Modes.stat_demodulated3 = - Modes.stat_goodcrc = - Modes.stat_badcrc = - Modes.stat_fixed = 0; - - Modes.stat_out_of_phase = - Modes.stat_ph_demodulated0 = - Modes.stat_ph_demodulated1 = - Modes.stat_ph_demodulated2 = - Modes.stat_ph_demodulated3 = - Modes.stat_ph_goodcrc = - Modes.stat_ph_badcrc = - Modes.stat_ph_fixed = 0; - - for (j = 0; j < MODES_MAX_BITERRORS; j++) { - Modes.stat_ph_bit_fix[j] = 0; - Modes.stat_bit_fix[j] = 0; - } + Modes.stat_DF_Type_Corrected = + Modes.stat_out_of_phase = 0; for (j = 0; j < MODES_MAX_PHASE_STATS; j++) { Modes.stat_preamble_phase[j] = 0; - Modes.stat_goodcrc_phase[j] = 0; } + + reset_demod_stats(&Modes.stat_demod); + reset_demod_stats(&Modes.stat_demod_phasecorrected); } diff --git a/dump1090.h b/dump1090.h index 7b9deba..b545eca 100644 --- a/dump1090.h +++ b/dump1090.h @@ -96,6 +96,8 @@ // When changing, change also fixBitErrors() and modesInitErrorTable() !! #define MODES_MAX_BITERRORS 2 // Global max for fixable bit erros +#define MODES_MAX_PHASE_STATS 10 + #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 @@ -246,6 +248,22 @@ struct stDF { unsigned char msg[MODES_LONG_MSG_BYTES]; // the binary } tDF; +// Common stats for non-phase-corrected vs phase-corrected cases +struct demod_stats { + unsigned int demodulated0; + unsigned int demodulated1; + unsigned int demodulated2; + unsigned int demodulated3; + unsigned int goodcrc; + unsigned int goodcrc_byphase[MODES_MAX_PHASE_STATS]; + unsigned int badcrc; + unsigned int fixed; + + // Histogram of fixed bit errors: index 0 for single bit erros, + // index 1 for double bit errors etc. + unsigned int bit_fix[MODES_MAX_BITERRORS]; +}; + // Program global state struct { // Internal state pthread_t reader_thread; @@ -348,39 +366,19 @@ struct { // Internal state struct stDF *pDF; // Pointer to DF list // Statistics -#define MODES_MAX_PHASE_STATS 12 unsigned int stat_preamble_no_correlation; unsigned int stat_preamble_not_quiet; unsigned int stat_valid_preamble; unsigned int stat_preamble_phase[MODES_MAX_PHASE_STATS]; - unsigned int stat_demodulated0; - unsigned int stat_demodulated1; - unsigned int stat_demodulated2; - unsigned int stat_demodulated3; - unsigned int stat_goodcrc; - unsigned int stat_goodcrc_phase[MODES_MAX_PHASE_STATS]; - unsigned int stat_badcrc; - unsigned int stat_fixed; - // 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]; + struct demod_stats stat_demod; + struct demod_stats stat_demod_phasecorrected; unsigned int stat_http_requests; unsigned int stat_sbs_connections; unsigned int stat_raw_connections; unsigned int stat_beast_connections; unsigned int stat_out_of_phase; - unsigned int stat_ph_demodulated0; - unsigned int stat_ph_demodulated1; - unsigned int stat_ph_demodulated2; - unsigned int stat_ph_demodulated3; - unsigned int stat_ph_goodcrc; - unsigned int stat_ph_badcrc; - unsigned int stat_ph_fixed; - // Histogram of fixed bit errors: index 0 for single bit erros, - // index 1 for double bit errors etc. - unsigned int stat_ph_bit_fix[MODES_MAX_BITERRORS]; unsigned int stat_DF_Len_Corrected; unsigned int stat_DF_Type_Corrected; diff --git a/mode_s.c b/mode_s.c index 88053c5..ded2b2b 100644 --- a/mode_s.c +++ b/mode_s.c @@ -1818,49 +1818,25 @@ void detectModeS(uint16_t *m, uint32_t mlen) { // Update statistics if (Modes.stats) { - if (mm.crcok || use_correction || mm.correctedbits) { + struct demod_stats *dstats = (use_correction ? &Modes.stat_demod_phasecorrected : &Modes.stat_demod); - if (use_correction) { - switch (errors) { - case 0: {Modes.stat_ph_demodulated0++; break;} - case 1: {Modes.stat_ph_demodulated1++; break;} - case 2: {Modes.stat_ph_demodulated2++; break;} - default:{Modes.stat_ph_demodulated3++; break;} - } - } else { - switch (errors) { - case 0: {Modes.stat_demodulated0++; break;} - case 1: {Modes.stat_demodulated1++; break;} - case 2: {Modes.stat_demodulated2++; break;} - default:{Modes.stat_demodulated3++; break;} - } - } - - if (mm.correctedbits == 0) { - if (use_correction) { - if (mm.crcok) {Modes.stat_ph_goodcrc++;} - else {Modes.stat_ph_badcrc++;} - } else { - if (mm.crcok) {Modes.stat_goodcrc++;} - else {Modes.stat_badcrc++;} - } - - } else if (use_correction) { - Modes.stat_ph_badcrc++; - Modes.stat_ph_fixed++; - if ( (mm.correctedbits) - && (mm.correctedbits <= MODES_MAX_BITERRORS) ) { - Modes.stat_ph_bit_fix[mm.correctedbits-1] += 1; - } - - } else { - Modes.stat_badcrc++; - Modes.stat_fixed++; - if ( (mm.correctedbits) - && (mm.correctedbits <= MODES_MAX_BITERRORS) ) { - Modes.stat_bit_fix[mm.correctedbits-1] += 1; - } - } + switch (errors) { + case 0: dstats->demodulated0++; break; + case 1: dstats->demodulated1++; break; + case 2: dstats->demodulated2++; break; + default: dstats->demodulated3++; break; + } + + if (mm.crcok) { + dstats->goodcrc++; + dstats->goodcrc_byphase[0]++; + } else if (mm.correctedbits > 0) { + dstats->badcrc++; + dstats->fixed++; + if (mm.correctedbits <= MODES_MAX_BITERRORS) + dstats->bit_fix[mm.correctedbits-1] += 1; + } else { + dstats->badcrc++; } } @@ -1878,7 +1854,7 @@ void detectModeS(uint16_t *m, uint32_t mlen) { } // Skip this message if we are sure it's fine - if (mm.crcok) { + if (mm.crcok || mm.correctedbits) { j += (MODES_PREAMBLE_US+msglen)*2 - 1; } @@ -1972,19 +1948,19 @@ static inline int slice_phase4(uint16_t *m) { } static inline int correlate_phase0(uint16_t *m) { - return slice_phase0(m) * 3; + return slice_phase0(m) * 26; } static inline int correlate_phase1(uint16_t *m) { - return slice_phase1(m) * 4; + return slice_phase1(m) * 38; } static inline int correlate_phase2(uint16_t *m) { - return slice_phase2(m) * 4; + return slice_phase2(m) * 38; } static inline int correlate_phase3(uint16_t *m) { - return slice_phase3(m) * 3; + return slice_phase3(m) * 26; } static inline int correlate_phase4(uint16_t *m) { - return slice_phase4(m) * 2; + return slice_phase4(m) * 19; } // @@ -2092,6 +2068,7 @@ void detectModeS_oversample(uint16_t *m, uint32_t mlen) { uint8_t theByte, theErrs; uint32_t sigLevel, noiseLevel; uint16_t snr; + int try_phase; // Look for a message starting at around sample 0 with phase offset 3..7 @@ -2183,6 +2160,9 @@ void detectModeS_oversample(uint16_t *m, uint32_t mlen) { Modes.stat_valid_preamble++; Modes.stat_preamble_phase[initial_phase%MODES_MAX_PHASE_STATS]++; + try_phase = initial_phase; + + retry: // Rather than clear the whole mm structure, just clear the parts which are required. The clear // is required for every possible preamble, and we don't want to be memset-ing the whole // modesMessage structure if we don't have to.. @@ -2192,10 +2172,10 @@ void detectModeS_oversample(uint16_t *m, uint32_t mlen) { // Decode all the next 112 bits, regardless of the actual message // size. We'll check the actual message type later - + pMsg = &msg[0]; - pPtr = &m[j+19] + (initial_phase/5); - phase = initial_phase % 5; + pPtr = &m[j+19] + (try_phase/5); + phase = try_phase % 5; theByte = 0; theErrs = 0; errorsTy = 0; errors = 0; errors56 = 0; @@ -2369,46 +2349,59 @@ void detectModeS_oversample(uint16_t *m, uint32_t mlen) { // && ((2 * snr) > (int) (MODES_MSG_SQUELCH_DB * 10)) && (errors <= MODES_MSG_ENCODER_ERRS) ) { // Set initial mm structure details - mm.timestampMsg = Modes.timestampBlk + (j*5) + initial_phase; + mm.timestampMsg = Modes.timestampBlk + (j*5) + try_phase; mm.signalLevel = (snr > 255 ? 255 : (uint8_t)snr); - mm.phase_corrected = 0; - - //dumpRawMessage("decoded with oversampling", msg, m, j); + mm.phase_corrected = (initial_phase != try_phase); // Decode the received message decodeModesMessage(&mm, msg); - + // Update statistics if (Modes.stats) { + struct demod_stats *dstats = (mm.phase_corrected ? &Modes.stat_demod_phasecorrected : &Modes.stat_demod); + switch (errors) { - case 0: {Modes.stat_demodulated0++; break;} - case 1: {Modes.stat_demodulated1++; break;} - case 2: {Modes.stat_demodulated2++; break;} - default:{Modes.stat_demodulated3++; break;} + case 0: dstats->demodulated0++; break; + case 1: dstats->demodulated1++; break; + case 2: dstats->demodulated2++; break; + default: dstats->demodulated3++; break; } - if (mm.correctedbits == 0) { - if (mm.crcok) { - Modes.stat_goodcrc++; - Modes.stat_goodcrc_phase[initial_phase%MODES_MAX_PHASE_STATS]++; - } else {Modes.stat_badcrc++;} + if (mm.crcok) { + dstats->goodcrc++; + dstats->goodcrc_byphase[try_phase%MODES_MAX_PHASE_STATS]++; + } else if (mm.correctedbits > 0) { + dstats->badcrc++; + dstats->fixed++; + if (mm.correctedbits <= MODES_MAX_BITERRORS) + dstats->bit_fix[mm.correctedbits-1] += 1; } else { - Modes.stat_badcrc++; - Modes.stat_fixed++; - if ( (mm.correctedbits) - && (mm.correctedbits <= MODES_MAX_BITERRORS) ) { - Modes.stat_bit_fix[mm.correctedbits-1] += 1; - } + dstats->badcrc++; } } // Skip this message if we are sure it's fine - if (mm.crcok) { + if (mm.crcok || mm.correctedbits) { j += (16+msglen)*6/5 - 1; } // Pass data to the next layer useModesMessage(&mm); + + // Only try with different phases if we mostly demodulated OK, + // but the CRC failed. This seems to catch most of the cases + // where trying different phases actually helps, and is much + // cheaper than trying it on every single candidate that passes + // peak detection + if (Modes.phase_enhance && !mm.crcok && !mm.correctedbits) { + if (try_phase == initial_phase) + ++Modes.stat_out_of_phase; + try_phase++; + if (try_phase == 9) + try_phase = 4; + if (try_phase != initial_phase) + goto retry; + } } }