Skip to content

Commit 26feb1d

Browse files
committed
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.
1 parent 5ac90e3 commit 26feb1d

File tree

2 files changed

+127
-6
lines changed

2 files changed

+127
-6
lines changed

crc.c

+121-3
Original file line numberDiff line numberDiff line change
@@ -421,16 +421,134 @@ void modesChecksumFix(uint8_t *msg, struct errorinfo *info)
421421
#ifdef CRCDEBUG
422422
int main(int argc, char **argv)
423423
{
424-
int len;
424+
int shortlen, longlen;
425+
int i;
426+
struct errorinfo *shorttable, *longtable;
425427

426428
if (argc < 3) {
427429
fprintf(stderr, "syntax: crctests <ncorrect> <ndetect>\n");
428430
return 1;
429431
}
430432

431433
initLookupTables();
432-
prepareErrorTable(MODES_SHORT_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &len);
433-
prepareErrorTable(MODES_LONG_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &len);
434+
shorttable = prepareErrorTable(MODES_SHORT_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &shortlen);
435+
longtable = prepareErrorTable(MODES_LONG_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &longlen);
436+
437+
// check for DF11 correction syndromes where there is a syndrome with lower 7 bits all zero
438+
// (which would be used for DF11 error correction), but there's also a syndrome which has
439+
// the same upper 17 bits but nonzero lower 7 bits.
440+
441+
// empirically, with ncorrect=1 ndetect=2 we get no ambiguous syndromes;
442+
// for ncorrect=2 ndetect=4 we get 11 ambiguous syndromes:
443+
444+
/*
445+
syndrome 1 = 000C00 bits=[ 44 45 ]
446+
syndrome 2 = 000C1B bits=[ 30 43 ]
447+
448+
syndrome 1 = 001400 bits=[ 43 45 ]
449+
syndrome 2 = 00141B bits=[ 30 44 ]
450+
451+
syndrome 1 = 001800 bits=[ 43 44 ]
452+
syndrome 2 = 00181B bits=[ 30 45 ]
453+
454+
syndrome 1 = 001800 bits=[ 43 44 ]
455+
syndrome 2 = 001836 bits=[ 29 42 ]
456+
457+
syndrome 1 = 002400 bits=[ 42 45 ]
458+
syndrome 2 = 00242D bits=[ 29 30 ]
459+
460+
syndrome 1 = 002800 bits=[ 42 44 ]
461+
syndrome 2 = 002836 bits=[ 29 43 ]
462+
463+
syndrome 1 = 003000 bits=[ 42 43 ]
464+
syndrome 2 = 003036 bits=[ 29 44 ]
465+
466+
syndrome 1 = 003000 bits=[ 42 43 ]
467+
syndrome 2 = 00306C bits=[ 28 41 ]
468+
469+
syndrome 1 = 004800 bits=[ 41 44 ]
470+
syndrome 2 = 00485A bits=[ 28 29 ]
471+
472+
syndrome 1 = 005000 bits=[ 41 43 ]
473+
syndrome 2 = 00506C bits=[ 28 42 ]
474+
475+
syndrome 1 = 006000 bits=[ 41 42 ]
476+
syndrome 2 = 00606C bits=[ 28 43 ]
477+
*/
478+
479+
// So in the DF11 correction logic, we just discard messages that require more than a 1 bit fix.
480+
481+
fprintf(stderr, "checking %d syndromes for DF11 collisions..\n", shortlen);
482+
for (i = 0; i < shortlen; ++i) {
483+
if ((shorttable[i].syndrome & 0xFF) == 0) {
484+
int j;
485+
// all syndromes with the same first 17 bits should sort immediately after entry i,
486+
// so this is fairly easy
487+
for (j = i+1; j < shortlen; ++j) {
488+
if ((shorttable[i].syndrome & 0xFFFF80) == (shorttable[j].syndrome & 0xFFFF80)) {
489+
int k;
490+
int mismatch = 0;
491+
492+
// we don't care if the only differences are in bits that lie in the checksum
493+
for (k = 0; k < shorttable[i].errors; ++k) {
494+
int l, matched = 0;
495+
496+
if (shorttable[i].bit[k] >= 49)
497+
continue; // bit is in the final 7 bits, we don't care
498+
499+
for (l = 0; l < shorttable[j].errors; ++l) {
500+
if (shorttable[i].bit[k] == shorttable[j].bit[l]) {
501+
matched = 1;
502+
break;
503+
}
504+
}
505+
506+
if (!matched)
507+
mismatch = 1;
508+
}
509+
510+
for (k = 0; k < shorttable[j].errors; ++k) {
511+
int l, matched = 0;
512+
513+
if (shorttable[j].bit[k] >= 49)
514+
continue; // bit is in the final 7 bits, we don't care
515+
516+
for (l = 0; l < shorttable[i].errors; ++l) {
517+
if (shorttable[j].bit[k] == shorttable[i].bit[l]) {
518+
matched = 1;
519+
break;
520+
}
521+
}
522+
523+
if (!matched)
524+
mismatch = 1;
525+
}
526+
527+
if (mismatch) {
528+
fprintf(stderr,
529+
"DF11 correction collision: \n"
530+
" syndrome 1 = %06X bits=[",
531+
shorttable[i].syndrome);
532+
for (k = 0; k < shorttable[i].errors; ++k)
533+
fprintf(stderr, " %d", shorttable[i].bit[k]);
534+
fprintf(stderr, " ]\n");
535+
536+
fprintf(stderr,
537+
" syndrome 2 = %06X bits=[",
538+
shorttable[j].syndrome);
539+
for (k = 0; k < shorttable[j].errors; ++k)
540+
fprintf(stderr, " %d", shorttable[j].bit[k]);
541+
fprintf(stderr, " ]\n");
542+
}
543+
} else {
544+
break;
545+
}
546+
}
547+
}
548+
}
549+
550+
free(shorttable);
551+
free(longtable);
434552

435553
return 0;
436554
}

mode_s.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -301,13 +301,10 @@ static int correct_aa_field(uint32_t *addr, struct errorinfo *ei)
301301
// 1600: DF11 with IID==0, good CRC and an address matching a known aircraft
302302
// 800: DF11 with IID==0, 1-bit error and an address matching a known aircraft
303303
// 750: DF11 with IID==0, good CRC and an address not matching a known aircraft
304-
// 400: DF11 with IID==0, 2-bit error and an address matching a known aircraft
305304
// 375: DF11 with IID==0, 1-bit error and an address not matching a known aircraft
306-
// 187: DF11 with IID==0, 2-bit error and an address not matching a known aircraft
307305

308306
// 1000: DF11 with IID!=0, good CRC and an address matching a known aircraft
309307
// 500: DF11 with IID!=0, 1-bit error and an address matching a known aircraft
310-
// 250: DF11 with IID!=0, 2-bit error and an address matching a known aircraft
311308

312309
// 1000: DF20/21 with a CRC-derived address matching a known aircraft
313310
// 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)
349346
if (!ei)
350347
return -2; // can't correct errors
351348

349+
// see crc.c comments: we do not attempt to fix
350+
// more than single-bit errors, as two-bit
351+
// errors are ambiguous in DF11.
352+
if (ei->errors > 1)
353+
return -2; // can't correct errors
354+
352355
// fix any errors in the address field
353356
correct_aa_field(&addr, ei);
354357

0 commit comments

Comments
 (0)