From 26feb1d0782a0da86e2ff5eff5b7631c8d7e50b2 Mon Sep 17 00:00:00 2001 From: Oliver Jowett Date: Fri, 23 Jan 2015 21:59:31 +0000 Subject: [PATCH] Add some testing code that looks for ambiguous syndromes that could confuse the partial correction used in DF11. That code shows that yes, there are ambiguous syndromes in the 2-bit correction case only, so disable corrections of more than 1 bit in DF11. --- crc.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- mode_s.c | 9 ++-- 2 files changed, 127 insertions(+), 6 deletions(-) diff --git a/crc.c b/crc.c index f7459a3..ad7d020 100644 --- a/crc.c +++ b/crc.c @@ -421,7 +421,9 @@ void modesChecksumFix(uint8_t *msg, struct errorinfo *info) #ifdef CRCDEBUG int main(int argc, char **argv) { - int len; + int shortlen, longlen; + int i; + struct errorinfo *shorttable, *longtable; if (argc < 3) { fprintf(stderr, "syntax: crctests \n"); @@ -429,8 +431,124 @@ int main(int argc, char **argv) } initLookupTables(); - prepareErrorTable(MODES_SHORT_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &len); - prepareErrorTable(MODES_LONG_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &len); + shorttable = prepareErrorTable(MODES_SHORT_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &shortlen); + longtable = prepareErrorTable(MODES_LONG_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &longlen); + + // check for DF11 correction syndromes where there is a syndrome with lower 7 bits all zero + // (which would be used for DF11 error correction), but there's also a syndrome which has + // the same upper 17 bits but nonzero lower 7 bits. + + // empirically, with ncorrect=1 ndetect=2 we get no ambiguous syndromes; + // for ncorrect=2 ndetect=4 we get 11 ambiguous syndromes: + + /* + syndrome 1 = 000C00 bits=[ 44 45 ] + syndrome 2 = 000C1B bits=[ 30 43 ] + + syndrome 1 = 001400 bits=[ 43 45 ] + syndrome 2 = 00141B bits=[ 30 44 ] + + syndrome 1 = 001800 bits=[ 43 44 ] + syndrome 2 = 00181B bits=[ 30 45 ] + + syndrome 1 = 001800 bits=[ 43 44 ] + syndrome 2 = 001836 bits=[ 29 42 ] + + syndrome 1 = 002400 bits=[ 42 45 ] + syndrome 2 = 00242D bits=[ 29 30 ] + + syndrome 1 = 002800 bits=[ 42 44 ] + syndrome 2 = 002836 bits=[ 29 43 ] + + syndrome 1 = 003000 bits=[ 42 43 ] + syndrome 2 = 003036 bits=[ 29 44 ] + + syndrome 1 = 003000 bits=[ 42 43 ] + syndrome 2 = 00306C bits=[ 28 41 ] + + syndrome 1 = 004800 bits=[ 41 44 ] + syndrome 2 = 00485A bits=[ 28 29 ] + + syndrome 1 = 005000 bits=[ 41 43 ] + syndrome 2 = 00506C bits=[ 28 42 ] + + syndrome 1 = 006000 bits=[ 41 42 ] + syndrome 2 = 00606C bits=[ 28 43 ] + */ + + // So in the DF11 correction logic, we just discard messages that require more than a 1 bit fix. + + fprintf(stderr, "checking %d syndromes for DF11 collisions..\n", shortlen); + for (i = 0; i < shortlen; ++i) { + if ((shorttable[i].syndrome & 0xFF) == 0) { + int j; + // all syndromes with the same first 17 bits should sort immediately after entry i, + // so this is fairly easy + for (j = i+1; j < shortlen; ++j) { + if ((shorttable[i].syndrome & 0xFFFF80) == (shorttable[j].syndrome & 0xFFFF80)) { + int k; + int mismatch = 0; + + // we don't care if the only differences are in bits that lie in the checksum + for (k = 0; k < shorttable[i].errors; ++k) { + int l, matched = 0; + + if (shorttable[i].bit[k] >= 49) + continue; // bit is in the final 7 bits, we don't care + + for (l = 0; l < shorttable[j].errors; ++l) { + if (shorttable[i].bit[k] == shorttable[j].bit[l]) { + matched = 1; + break; + } + } + + if (!matched) + mismatch = 1; + } + + for (k = 0; k < shorttable[j].errors; ++k) { + int l, matched = 0; + + if (shorttable[j].bit[k] >= 49) + continue; // bit is in the final 7 bits, we don't care + + for (l = 0; l < shorttable[i].errors; ++l) { + if (shorttable[j].bit[k] == shorttable[i].bit[l]) { + matched = 1; + break; + } + } + + if (!matched) + mismatch = 1; + } + + if (mismatch) { + fprintf(stderr, + "DF11 correction collision: \n" + " syndrome 1 = %06X bits=[", + shorttable[i].syndrome); + for (k = 0; k < shorttable[i].errors; ++k) + fprintf(stderr, " %d", shorttable[i].bit[k]); + fprintf(stderr, " ]\n"); + + fprintf(stderr, + " syndrome 2 = %06X bits=[", + shorttable[j].syndrome); + for (k = 0; k < shorttable[j].errors; ++k) + fprintf(stderr, " %d", shorttable[j].bit[k]); + fprintf(stderr, " ]\n"); + } + } else { + break; + } + } + } + } + + free(shorttable); + free(longtable); return 0; } diff --git a/mode_s.c b/mode_s.c index 28f66c3..dbacfc6 100644 --- a/mode_s.c +++ b/mode_s.c @@ -301,13 +301,10 @@ static int correct_aa_field(uint32_t *addr, struct errorinfo *ei) // 1600: DF11 with IID==0, good CRC and an address matching a known aircraft // 800: DF11 with IID==0, 1-bit error and an address matching a known aircraft // 750: DF11 with IID==0, good CRC and an address not matching a known aircraft -// 400: DF11 with IID==0, 2-bit error and an address matching a known aircraft // 375: DF11 with IID==0, 1-bit error and an address not matching a known aircraft -// 187: DF11 with IID==0, 2-bit error and an address not matching a known aircraft // 1000: DF11 with IID!=0, good CRC and an address matching a known aircraft // 500: DF11 with IID!=0, 1-bit error and an address matching a known aircraft -// 250: DF11 with IID!=0, 2-bit error and an address matching a known aircraft // 1000: DF20/21 with a CRC-derived address matching a known aircraft // 500: DF20/21 with a CRC-derived address matching a known aircraft (bottom 16 bits only - overlay control in use) @@ -349,6 +346,12 @@ int scoreModesMessage(unsigned char *msg, int validbits) if (!ei) return -2; // can't correct errors + // see crc.c comments: we do not attempt to fix + // more than single-bit errors, as two-bit + // errors are ambiguous in DF11. + if (ei->errors > 1) + return -2; // can't correct errors + // fix any errors in the address field correct_aa_field(&addr, ei);