Try to correct single bit errors in the DF field

If noist/sampling/Nyquist errors cause bit detection errors in the DF
pare of the frame, then we may not be able to work out the correct
length of the message. We have to guess whether the bit should be a 0 or
a 1.

In such circumstances we assume the message length is long(112 bits)
However, if we start to get encoding errors after bit 56 the we attempt
to change our original guess at the bit, and invert it. If this change
of guess would have resulted in a short message, and if the short
message would have been error free then we can recover.
This commit is contained in:
Malcolm Robb 2013-04-12 20:45:12 +01:00
parent 63622355e3
commit 8c024d1736

View file

@ -202,6 +202,7 @@ struct {
int64_t stat_http_requests; int64_t stat_http_requests;
int64_t stat_sbs_connections; int64_t stat_sbs_connections;
int64_t stat_out_of_phase; int64_t stat_out_of_phase;
int64_t stat_DF_Corrected;
} Modes; } Modes;
/* The struct we use to store information about a decoded message. */ /* The struct we use to store information about a decoded message. */
@ -1396,10 +1397,10 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
* 9 ------------------- * 9 -------------------
*/ */
for (j = 0; j < mlen; j++) { for (j = 0; j < mlen; j++) {
int high, i, errors; int high, i, errors, errors56, errorsTy;
int good_message = 0; int good_message = 0;
uint16_t *pPreamble, *pPayload, *pPtr; uint16_t *pPreamble, *pPayload, *pPtr;
uint8_t theByte; uint8_t theByte, theErrs;
int msglen, sigStrength; int msglen, sigStrength;
pPreamble = &m[j]; pPreamble = &m[j];
@ -1471,11 +1472,18 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
/* Decode all the next 112 bits, regardless of the actual message /* Decode all the next 112 bits, regardless of the actual message
* size. We'll check the actual message type later. */ * size. We'll check the actual message type later. */
pMsg = &msg[0]; pMsg = &msg[0];
pPtr = pPayload; pPtr = pPayload;
theByte = 0; theByte = 0;
errors = 0; theErrs = 0; errorsTy = 0;
sigStrength = 0; errors = 0; errors56 = 0;
// We should have 4 'bits' of 0/1 and 1/0 samples in the preamble,
// so include these in the signal strength
sigStrength = (pPreamble[0]-pPreamble[1])
+ (pPreamble[2]-pPreamble[3])
+ (pPreamble[7]-pPreamble[6])
+ (pPreamble[9]-pPreamble[8]);
msglen = MODES_LONG_MSG_BITS; msglen = MODES_LONG_MSG_BITS;
for (i = 0; i < msglen; i++) { for (i = 0; i < msglen; i++) {
@ -1486,24 +1494,55 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
{sigStrength += (a-b); theByte |= 1;} {sigStrength += (a-b); theByte |= 1;}
else if (a < b) else if (a < b)
{sigStrength += (b-a); /*theByte |= 0;*/} {sigStrength += (b-a); /*theByte |= 0;*/}
else //a == b, 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
{errors56 = ++errors;/*theByte |= 0;*/}
else //(a == b), and we're in the message type part of a frame
{errorsTy = errors56 = ++errors; theErrs |= 1; /*theByte |= 0;*/}
if ((i & 7) == 7) if ((i & 7) == 7)
{*pMsg++ = theByte;} {*pMsg++ = theByte;}
else if ((i == 4) /*&& (errors == 0) */) else if ((i == 4) && (errors == 0))
{msglen = modesMessageLenByType(theByte);} {msglen = modesMessageLenByType(theByte);}
theByte = theByte << 1; theByte = theByte << 1;
if (i < 8)
{theErrs = theErrs << 1;}
// 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)
{break;} {
// If we're in the long frame when it went to pot, but it was still ok-ish when we
// were in the short part of the frame, then try for a mis-identified short frame
// we must believe that this should've been a long frame to get this far.
if (i >= MODES_SHORT_MSG_BITS)
{
// 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. If we only saw one error, we may
// be able to correct it by guessing the other way.
if (errorsTy == 1)
{
// See if inverting the bit we guessed at would change the message type from a
// long to a short. If it would, invert the bit, cross your fingers and carry on.
theByte = pMsg[0] ^ theErrs;
if (MODES_SHORT_MSG_BITS == modesMessageLenByType(theByte))
{
pMsg[0] = theByte; // write the modified type back to the msg buffer
errors = errors56; // revert to the number of errors prior to bit 56
msglen = MODES_SHORT_MSG_BITS;
i--; // this latest sample was zero, so we can ignore it.
Modes.stat_DF_Corrected++;
}
}
}
break;
}
} }
/* Filter for an average delta of three is small enough to let almost // Don't forget to add 4 for the preamble samples. This also removes any risk of dividing by zero.
* every kind of message to pass, but high enough to filter some sigStrength /= (msglen+4);
* random noise. */
sigStrength /= msglen;
/* 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
@ -2654,6 +2693,7 @@ int main(int argc, char **argv) {
/* If --ifile and --stats were given, print statistics. */ /* If --ifile and --stats were given, print statistics. */
if (Modes.stats && Modes.filename) { if (Modes.stats && Modes.filename) {
printf("%lld valid preambles\n", Modes.stat_valid_preamble); printf("%lld valid preambles\n", Modes.stat_valid_preamble);
printf("%lld DF-?? fields corrected for length\n", Modes.stat_DF_Corrected);
printf("%lld demodulated again after phase correction\n", Modes.stat_out_of_phase); printf("%lld demodulated again after phase correction\n", Modes.stat_out_of_phase);
printf("%lld demodulated with zero errors\n", Modes.stat_demodulated); printf("%lld demodulated with zero errors\n", Modes.stat_demodulated);
printf("%lld with good crc\n", Modes.stat_goodcrc); printf("%lld with good crc\n", Modes.stat_goodcrc);