DF Error detection and Correction

Added additional error detection and correction to the DF field of the
first byte in every ModeS frame.
This commit is contained in:
Malcolm Robb 2013-04-29 01:30:12 +01:00
parent 7cf79580a4
commit e161b7662c

View file

@ -243,7 +243,8 @@ struct {
unsigned int stat_http_requests; unsigned int stat_http_requests;
unsigned int stat_sbs_connections; unsigned int stat_sbs_connections;
unsigned int stat_out_of_phase; unsigned int stat_out_of_phase;
unsigned int stat_DF_Corrected; unsigned int stat_DF_Len_Corrected;
unsigned int stat_DF_Type_Corrected;
unsigned int stat_ModeAC; unsigned int stat_ModeAC;
} Modes; } Modes;
@ -462,7 +463,8 @@ void modesInit(void) {
Modes.stat_http_requests = 0; Modes.stat_http_requests = 0;
Modes.stat_sbs_connections = 0; Modes.stat_sbs_connections = 0;
Modes.stat_out_of_phase = 0; Modes.stat_out_of_phase = 0;
Modes.stat_DF_Corrected = 0; Modes.stat_DF_Len_Corrected = 0;
Modes.stat_DF_Type_Corrected = 0;
Modes.stat_ModeAC = 0; Modes.stat_ModeAC = 0;
Modes.exit = 0; Modes.exit = 0;
} }
@ -1892,7 +1894,7 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
int good_message = 0; int good_message = 0;
uint16_t *pPreamble, *pPayload, *pPtr; uint16_t *pPreamble, *pPayload, *pPtr;
uint8_t theByte, theErrs; uint8_t theByte, theErrs;
int msglen, sigStrength; int msglen, scanlen, sigStrength;
pPreamble = &m[j]; pPreamble = &m[j];
pPayload = &m[j+MODES_PREAMBLE_SAMPLES]; pPayload = &m[j+MODES_PREAMBLE_SAMPLES];
@ -1997,69 +1999,97 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
+ (pPreamble[7]-pPreamble[6]) + (pPreamble[7]-pPreamble[6])
+ (pPreamble[9]-pPreamble[8]); + (pPreamble[9]-pPreamble[8]);
msglen = MODES_LONG_MSG_BITS; msglen = scanlen = MODES_LONG_MSG_BITS;
for (i = 0; i < msglen; i++) { for (i = 0; i < scanlen; i++) {
uint32_t a = *pPtr++; uint32_t a = *pPtr++;
uint32_t b = *pPtr++; uint32_t b = *pPtr++;
if (a > b) if (a > b)
{sigStrength += (a-b); theByte |= 1;} {theByte |= 1; if (i < 56) {sigStrength += (a-b);}}
else if (a < b) else if (a < b)
{sigStrength += (b-a); /*theByte |= 0;*/} {/*theByte |= 0;*/ if (i < 56) {sigStrength += (b-a);}}
else if (i >= MODES_SHORT_MSG_BITS) //(a == b), and we're in the long part of a frame else if (i >= MODES_SHORT_MSG_BITS) //(a == b), and we're in the long part of a frame
{errors++; /*theByte |= 0;*/} {errors++; /*theByte |= 0;*/}
else if (i >= 5) //(a == b), and we're in the short part of a frame else if (i >= 5) //(a == b), and we're in the short part of a frame
{errors56 = ++errors;/*theByte |= 0;*/} {scanlen = MODES_LONG_MSG_BITS; errors56 = ++errors;/*theByte |= 0;*/}
else //(a == b), and we're in the message type part of a frame else if (i) //(a == b), and we're in the message type part of a frame
{errorsTy = errors56 = ++errors; theErrs |= 1; /*theByte |= 0;*/} {errorsTy = errors56 = ++errors; theErrs |= 1; /*theByte |= 0;*/}
else //(a == b), and we're in the first bit of the message type part of a frame
{errorsTy = errors56 = ++errors; theErrs |= 1; theByte |= 1;}
if ((i & 7) == 7) if ((i & 7) == 7)
{*pMsg++ = theByte;} {*pMsg++ = theByte;}
else if ((i == 4) && (errors == 0)) else if (i == 4) {
{msglen = modesMessageLenByType(theByte);} msglen = modesMessageLenByType(theByte);
if (errors == 0)
{scanlen = msglen;}
}
theByte = theByte << 1; theByte = theByte << 1;
if (i < 8) if (i < 7)
{theErrs = theErrs << 1;} {theErrs = theErrs << 1;}
// If we've exceeded the permissible number of encoding errors, abandon ship now // If we've exceeded the permissible number of encoding errors, abandon ship now
if (errors > MODES_MSG_ENCODER_ERRS) if (errors > MODES_MSG_ENCODER_ERRS) {
{
// If we're in the long frame when it went to pot, but it was still ok-ish when we if (i < MODES_SHORT_MSG_BITS) {
// were in the short part of the frame, then try for a mis-identified short frame msglen = 0;
// we must believe that this should've been a long frame to get this far.
if (i >= MODES_SHORT_MSG_BITS) } else if ((errorsTy == 1) && (theErrs == 0x80)) {
{ // If we only saw one error in the first bit of the byte of the frame, then it's possible
// If we did see some errors in the first byte of the frame, then it's possible // we guessed wrongly about the value of the bit. We may be able to correct it by guessing
// we guessed wrongly about the value of the bit. If we only saw one error, we may // the other way.
// be able to correct it by guessing the other way. //
if (errorsTy == 1) // We guessed a '1' at bit 7, which is the DF length bit == 112 Bits.
{ // Inverting bit 7 will change the message type from a long to a short.
// See if inverting the bit we guessed at would change the message type from a // Invert the bit, cross your fingers and carry on.
// long to a short. If it would, invert the bit, cross your fingers and carry on. msglen = MODES_SHORT_MSG_BITS;
theByte = pMsg[0] ^ theErrs; msg[0] ^= theErrs; errorsTy = 0;
if (MODES_SHORT_MSG_BITS == modesMessageLenByType(theByte)) errors = errors56; // revert to the number of errors prior to bit 56
{ Modes.stat_DF_Len_Corrected++;
pMsg[0] = theByte; // write the modified type back to the msg buffer
errors = errors56; // revert to the number of errors prior to bit 56 } else if (i < MODES_LONG_MSG_BITS) {
msglen = MODES_SHORT_MSG_BITS; msglen = MODES_SHORT_MSG_BITS;
i--; // this latest sample was zero, so we can ignore it. errors = errors56;
Modes.stat_DF_Corrected++;
} } else {
} msglen = MODES_LONG_MSG_BITS;
}
break;
} }
break;
}
}
if (msglen == modesMessageLenByType(theByte = msg[0])) {
// The msglen is consistent with the DF type
if ((errorsTy == 1) && (theErrs & 0x78)) {
// We guessed at one of the message type bits. See if our guess is "likely"
// to be correct by comparing the DF against a list of known good DF's
int DF = ((theByte = msg[0]) >> 3) & 0x1f;
if ( (DF != 0) && (DF != 4) && (DF != 5) && (DF != 11)
&& (DF != 16) && (DF != 17) && (DF != 18) && (DF != 19) && (DF != 20) && (DF != 21) && (DF != 22) && (DF != 24) ) {
// Other DF values are probably errors. Toggle the bit we guessed at and see if the resultant DF is more likely
theByte ^= theErrs;
DF = (theByte >> 3) & 0x1f;
// if this DF any more likely??
if ( (DF == 0) || (DF == 4) || (DF == 5) || (DF == 11)
|| (DF == 16) || (DF == 17) || (DF == 18) || (DF == 19) || (DF == 20) || (DF == 21) || (DF == 22) || (DF == 24) ) {
// Yep, more likely, so update the main message
msg[0] = theByte;
Modes.stat_DF_Type_Corrected++;
errors--; // decrease the error count so we attempt to use the modified DF.
}
}
}
} }
// Don't forget to add 4 for the preamble samples. This also removes any risk of dividing by zero. // Don't forget to add 4 for the preamble samples. This also removes any risk of dividing by zero.
sigStrength /= (msglen+4); sigStrength /= 60;
/* If we reached this point, and error is zero, we are very likely /* If we reached this point, and error is zero, we are very likely
* with a Mode S message in our hands, but it may still be broken * with a Mode S message in our hands, but it may still be broken
* and CRC may not be correct. This is handled by the next layer. */ * and CRC may not be correct. This is handled by the next layer. */
if ( (sigStrength > MODES_MSG_SQUELCH_LEVEL) && (errors <= MODES_MSG_ENCODER_ERRS) ) if ((msglen) && (sigStrength > MODES_MSG_SQUELCH_LEVEL) && (errors <= MODES_MSG_ENCODER_ERRS) )
{ {
struct modesMessage mm; struct modesMessage mm;
@ -3580,7 +3610,8 @@ int main(int argc, char **argv) {
if (Modes.stats && Modes.filename) { if (Modes.stats && Modes.filename) {
printf("%d ModeA/C detected\n", Modes.stat_ModeAC); printf("%d ModeA/C detected\n", Modes.stat_ModeAC);
printf("%d valid preambles\n", Modes.stat_valid_preamble); printf("%d valid preambles\n", Modes.stat_valid_preamble);
printf("%d DF-?? fields corrected for length\n", Modes.stat_DF_Corrected); 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 again after phase correction\n", Modes.stat_out_of_phase); printf("%d demodulated again after phase correction\n", Modes.stat_out_of_phase);
printf("%d demodulated with zero errors\n", Modes.stat_demodulated); printf("%d demodulated with zero errors\n", Modes.stat_demodulated);
printf("%d with good crc\n", Modes.stat_goodcrc); printf("%d with good crc\n", Modes.stat_goodcrc);