From 63622355e31c4b230472fa6f89c9bf6d41a3e95d Mon Sep 17 00:00:00 2001 From: Malcolm Robb Date: Fri, 12 Apr 2013 10:53:46 +0100 Subject: [PATCH] Change the message bit decoder Change (and hopefully improve) the Message bit decoder. When decoding bits, a "0" is encoded as (m[j]m[j+1]) . However, there is a problem if mpj[ == m[j+1] because we can't decide what it's supposed to be. Antirez's original code defaults to a '1', and then lets the bit error detection code sort it out. I *think* it's better to default to '0' because it's more likely that noise added to the signal will produce a spurious '1' rathar than anything subtracting from the signal to produce a spurious '0' Also, Antirez''s code only looks for errors in the first bit of the message. I don't know why this is. There is a potential problem in deciding the message length if there are any errors in the first 5 bits decoded, because this defines the message type (the DF-??), and it's the DF that determines how many bits the message shall contain. If there is an error in the first 5 bits, then we could ignore the DF, and continue decoding a long format (112 bits). However, for weak signals, if the message is a short one (56 bits) this results in the sigStrength decaying to the point where it's level drops below squelch, so we discard a possibly decodeable 56bit However, if we assume it's a short message, and only decode 56 bits, and it's really a long message we won't have decoded all the bits. Not sure what to do about this --- dump1090.c | 59 +++++++++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/dump1090.c b/dump1090.c index c54dcf6..accf8ab 100644 --- a/dump1090.c +++ b/dump1090.c @@ -57,6 +57,8 @@ #define MODES_ASYNC_BUF_SAMPLES (MODES_ASYNC_BUF_SIZE / 2) /* Each sample is 2 bytes */ #define MODES_AUTO_GAIN -100 /* Use automatic gain. */ #define MODES_MAX_GAIN 999999 /* Use max available gain. */ +#define MODES_MSG_SQUELCH_LEVEL 0x02FF /* Average signal strength limit */ +#define MODES_MSG_ENCODER_ERRS 3 /* Maximum number of encoding errors */ #define MODES_PREAMBLE_US 8 /* microseconds = bits */ #define MODES_PREAMBLE_SAMPLES (MODES_PREAMBLE_US * 2) @@ -1394,10 +1396,10 @@ void detectModeS(uint16_t *m, uint32_t mlen) { * 9 ------------------- */ for (j = 0; j < mlen; j++) { - int low, high, delta, i, errors; + int high, i, errors; int good_message = 0; uint16_t *pPreamble, *pPayload, *pPtr; - uint8_t theByte; + uint8_t theByte; int msglen, sigStrength; pPreamble = &m[j]; @@ -1405,6 +1407,7 @@ void detectModeS(uint16_t *m, uint32_t mlen) { if (!use_correction) // This is not a re-try with phase correction { // so try to find a new preamble + /* First check of relations between the first 10 samples * representing a valid preamble. We don't even investigate further * if this simple test is not passed. */ @@ -1429,7 +1432,7 @@ void detectModeS(uint16_t *m, uint32_t mlen) { * of the high spikes level. We don't test bits too near to * the high levels as signals can be out of phase so part of the * energy can be in the near samples. */ - high = (pPreamble[0]+pPreamble[2]+pPreamble[7]+pPreamble[9])/6; + high = (pPreamble[0] + pPreamble[2] + pPreamble[7] + pPreamble[9]) / 6; if (pPreamble[4] >= high || pPreamble[5] >= high) { @@ -1473,52 +1476,40 @@ void detectModeS(uint16_t *m, uint32_t mlen) { theByte = 0; errors = 0; sigStrength = 0; - msglen = MODES_LONG_MSG_BITS; - for (i = 0; i < MODES_LONG_MSG_BITS; i++) { - low = *pPtr++; - high = *pPtr++; - delta = low-high; - if (delta < 0) delta = -delta; - if (i > 0 && delta < 256) { - if (theByte & 2) - {theByte |= 1;} - } else if (low == high) { - /* Checking if two adiacent samples have the same magnitude - * is an effective way to detect if it's just random noise - * that was detected as a valid preamble. */ - theByte |= 2; /* error */ - if (i < MODES_SHORT_MSG_BITS) errors++; - } else if (low > high) { - theByte |= 1; - } + msglen = MODES_LONG_MSG_BITS; + for (i = 0; i < msglen; i++) { + uint32_t a = *pPtr++; + uint32_t b = *pPtr++; - if (i < msglen) { - sigStrength += delta; - } + if (a > b) + {sigStrength += (a-b); theByte |= 1;} + else if (a < b) + {sigStrength += (b-a); /*theByte |= 0;*/} + else //a == b, + {errors++; /*theByte |= 0;*/} - if (i == 4) { - msglen = modesMessageLenByType(theByte); + if ((i & 7) == 7) + {*pMsg++ = theByte;} + else if ((i == 4) /*&& (errors == 0) */) + {msglen = modesMessageLenByType(theByte);} - } else if ((i & 7) == 7) { - *pMsg++ = theByte; - } theByte = theByte << 1; + + if (errors > MODES_MSG_ENCODER_ERRS) + {break;} } /* Filter for an average delta of three is small enough to let almost * every kind of message to pass, but high enough to filter some * random noise. */ sigStrength /= msglen; - if (sigStrength < (5*255)) { - use_correction = 0; - continue; - } /* 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 * and CRC may not be correct. This is handled by the next layer. */ - if (errors == 0 || (Modes.aggressive && errors < 3)) { + if ( (sigStrength > MODES_MSG_SQUELCH_LEVEL) && (errors <= MODES_MSG_ENCODER_ERRS) ) + { struct modesMessage mm; /* Decode the received message and update statistics */