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.
This commit is contained in:
Oliver Jowett 2015-01-23 21:59:31 +00:00
parent 5ac90e30a8
commit 26feb1d078
2 changed files with 127 additions and 6 deletions

124
crc.c
View file

@ -421,7 +421,9 @@ void modesChecksumFix(uint8_t *msg, struct errorinfo *info)
#ifdef CRCDEBUG #ifdef CRCDEBUG
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int len; int shortlen, longlen;
int i;
struct errorinfo *shorttable, *longtable;
if (argc < 3) { if (argc < 3) {
fprintf(stderr, "syntax: crctests <ncorrect> <ndetect>\n"); fprintf(stderr, "syntax: crctests <ncorrect> <ndetect>\n");
@ -429,8 +431,124 @@ int main(int argc, char **argv)
} }
initLookupTables(); initLookupTables();
prepareErrorTable(MODES_SHORT_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &len); shorttable = prepareErrorTable(MODES_SHORT_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &shortlen);
prepareErrorTable(MODES_LONG_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &len); 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; return 0;
} }

View file

@ -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 // 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 // 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 // 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 // 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 // 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 // 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 // 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) // 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) if (!ei)
return -2; // can't correct errors 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 // fix any errors in the address field
correct_aa_field(&addr, ei); correct_aa_field(&addr, ei);