When trying to correct a DF11 that had bits set in the top 17 bits of the

residual, use the full 24-bit syndrome.

Previously this would mask off the low 7 bits, which isn't particularly
great - it doesn't really make sense in that it implies a somewhat
random IID value, and it would actually only correct 20 possible bit
errors out of the 51 possible errors, 16 of which were errors in
the top 16 bits of the CRC itself. It is also risky as it will accept
a larger number of possible garbage messages as the lower 7 bits may take
any value.

Instead, use the full syndrome, assuming that the damaged message
had IID=0 - which seems more likely than assuming a random IID, since
IID=0 is used for acquisition squitters and should be arriving regularly.

The reduced rate of corrections for DF11 messages shouldn't have
much of an impact as DF11s carry very little data themselves - they
are mainly used to acquire the aircraft address. Once one good message
for an aircraft turns up (which would require IID=0 anyway before we'd
accept it) it doesn't really matter if we discard more damaged messages,
as they're not contributing to anything useful in the aircraft state
beyond air/ground status, which is also carried in many other messages.
This commit is contained in:
Oliver Jowett 2019-12-02 21:27:18 +08:00
parent ae29613d85
commit f7123c41e5
1 changed files with 32 additions and 22 deletions

View File

@ -259,12 +259,9 @@ static int correct_aa_field(uint32_t *addr, struct errorinfo *ei)
// 350: DF17/18 with 2-bit error and an address not matching a known aircraft // 350: DF17/18 with 2-bit error and an address not matching a known aircraft
// 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
// 750: DF11 with IID==0, good CRC and an address not matching a known aircraft
// 375: DF11 with IID==0, 1-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 // 800: DF11 with 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
// 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)
@ -310,31 +307,40 @@ int scoreModesMessage(unsigned char *msg, int validbits)
case 11: // All-call reply case 11: // All-call reply
iid = crc & 0x7f; iid = crc & 0x7f;
crc = crc & 0xffff80;
addr = getbits(msg, 9, 32); addr = getbits(msg, 9, 32);
ei = modesChecksumDiagnose(crc, msgbits); if (crc & 0xffff80) {
if (!ei) // Try to diagnose based on the _full_ CRC
return -2; // can't correct errors // i.e. under the assumption that IID = 0
ei = modesChecksumDiagnose(crc, msgbits);
if (!ei)
return -2; // can't correct errors
// see crc.c comments: we do not attempt to fix // see crc.c comments: we do not attempt to fix
// more than single-bit errors, as two-bit // more than single-bit errors, as two-bit
// errors are ambiguous in DF11. // errors are ambiguous in DF11.
if (ei->errors > 1) if (ei->errors > 1)
return -2; // can't correct errors 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);
// validate address // here, IID = 0 implicitly
if (icaoFilterTest(addr))
return 800;
else
return -1;
}
// CRC was correct (ish)
if (iid == 0) { if (iid == 0) {
if (icaoFilterTest(addr)) if (icaoFilterTest(addr))
return 1600 / (ei->errors + 1); return 1600;
else else
return 750 / (ei->errors + 1); return 750;
} else { } else { // iid != 0
if (icaoFilterTest(addr)) if (icaoFilterTest(addr))
return 1000 / (ei->errors + 1); return 1000;
else else
return -1; return -1;
} }
@ -439,8 +445,11 @@ int decodeModesMessage(struct modesMessage *mm, unsigned char *msg)
mm->IID = mm->crc & 0x7f; mm->IID = mm->crc & 0x7f;
if (mm->crc & 0xffff80) { if (mm->crc & 0xffff80) {
// Try to diagnose based on the _full_ CRC
// i.e. under the assumption that IID = 0
int addr; int addr;
struct errorinfo *ei = modesChecksumDiagnose(mm->crc & 0xffff80, mm->msgbits); struct errorinfo *ei = modesChecksumDiagnose(mm->crc, mm->msgbits);
if (!ei) { if (!ei) {
return -2; // couldn't fix it return -2; // couldn't fix it
} }
@ -452,6 +461,7 @@ int decodeModesMessage(struct modesMessage *mm, unsigned char *msg)
return -2; // can't correct errors return -2; // can't correct errors
mm->correctedbits = ei->errors; mm->correctedbits = ei->errors;
mm->IID = 0;
modesChecksumFix(msg, ei); modesChecksumFix(msg, ei);
// check whether the corrected message looks sensible // check whether the corrected message looks sensible