2017-06-15 17:07:40 +00:00
|
|
|
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
|
|
|
|
|
//
|
|
|
|
|
// mode_s.h: Mode S message decoding (prototypes)
|
|
|
|
|
//
|
Overhaul of message scoring & error correction.
Major changes:
Try to error-correct all messages that potentially could be DF11/17/18
even if the original DF value is different. This allows messages with
correctable damage in the first 5 bits to be correctable.
Track recently-seen DF18 addresses separately to DF17 addresses.
DF18 does not imply Mode S support, so we don't want to treat it like
a known Mode S emitter, but once we've heard some DF18 for an aircraft
we can be more confident about future DF18 messages for the same
address.
Rework the scoring system so it's just a big enum that lists all the
possible outcomes in the order that we want. This makes the relative
ordering of different messages clearer, and makes it easier to move
messages above/below the accept thresholds as needed.
Don't accept 2-bit-error-corrected messages that are from aircraft we
have not previously seen. This greatly reduces the number of garbage
messages when using 2-bit error correction.
Overall results are:
* more CPU required for decoding (approx 30% increase in my tests)
as we're doing a lot more speculative CRC-checking work
* no significant change to message rates with error correction off
* about 5% more 1-bit-corrected DF17 decodes, with a
disproportionate increase in those messages contributing to
successful position decodes / unique aircraft counts
* _fewer_ decodes with 2-bit correction (versus old code with 2-bit
correction), but the message quality is substantially improved,
the rate of garbage decodes / phantom aircraft is greatly reduced
sample stats:
1-bit correction, old code:
141158 total usable messages
137852 accepted with correct CRC
3306 accepted with 1-bit error repaired
27446 DF17 messages
51 unique aircraft tracks
1-bit correction, new code:
141296 total usable messages
137854 accepted with correct CRC
3442 accepted with 1-bit error repaired
27528 DF17 messages
55 unique aircraft tracks
2-bit correction, old code:
142656 total usable messages
137809 accepted with correct CRC
3283 accepted with 1-bit error repaired
1564 accepted with 2-bit error repaired
28803 DF17 messages
349 unique aircraft tracks (<- note that most of these are garbage)
2-bit correction, new code:
142426 total usable messages
137822 accepted with correct CRC
3420 accepted with 1-bit error repaired
1184 accepted with 2-bit error repaired
28666 DF17 messages
55 unique aircraft tracks
2021-02-09 11:43:38 +00:00
|
|
|
// Copyright (c) 2017-2021 FlightAware, LLC
|
2017-06-15 17:07:40 +00:00
|
|
|
// Copyright (c) 2017 Oliver Jowett <oliver@mutability.co.uk>
|
|
|
|
|
//
|
|
|
|
|
// This file is free software: you may copy, redistribute and/or modify it
|
|
|
|
|
// under the terms of the GNU General Public License as published by the
|
|
|
|
|
// Free Software Foundation, either version 2 of the License, or (at your
|
|
|
|
|
// option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This file is distributed in the hope that it will be useful, but
|
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
// General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
#ifndef MODE_S_H
|
|
|
|
|
#define MODE_S_H
|
|
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Functions exported from mode_s.c
|
|
|
|
|
//
|
Overhaul of message scoring & error correction.
Major changes:
Try to error-correct all messages that potentially could be DF11/17/18
even if the original DF value is different. This allows messages with
correctable damage in the first 5 bits to be correctable.
Track recently-seen DF18 addresses separately to DF17 addresses.
DF18 does not imply Mode S support, so we don't want to treat it like
a known Mode S emitter, but once we've heard some DF18 for an aircraft
we can be more confident about future DF18 messages for the same
address.
Rework the scoring system so it's just a big enum that lists all the
possible outcomes in the order that we want. This makes the relative
ordering of different messages clearer, and makes it easier to move
messages above/below the accept thresholds as needed.
Don't accept 2-bit-error-corrected messages that are from aircraft we
have not previously seen. This greatly reduces the number of garbage
messages when using 2-bit error correction.
Overall results are:
* more CPU required for decoding (approx 30% increase in my tests)
as we're doing a lot more speculative CRC-checking work
* no significant change to message rates with error correction off
* about 5% more 1-bit-corrected DF17 decodes, with a
disproportionate increase in those messages contributing to
successful position decodes / unique aircraft counts
* _fewer_ decodes with 2-bit correction (versus old code with 2-bit
correction), but the message quality is substantially improved,
the rate of garbage decodes / phantom aircraft is greatly reduced
sample stats:
1-bit correction, old code:
141158 total usable messages
137852 accepted with correct CRC
3306 accepted with 1-bit error repaired
27446 DF17 messages
51 unique aircraft tracks
1-bit correction, new code:
141296 total usable messages
137854 accepted with correct CRC
3442 accepted with 1-bit error repaired
27528 DF17 messages
55 unique aircraft tracks
2-bit correction, old code:
142656 total usable messages
137809 accepted with correct CRC
3283 accepted with 1-bit error repaired
1564 accepted with 2-bit error repaired
28803 DF17 messages
349 unique aircraft tracks (<- note that most of these are garbage)
2-bit correction, new code:
142426 total usable messages
137822 accepted with correct CRC
3420 accepted with 1-bit error repaired
1184 accepted with 2-bit error repaired
28666 DF17 messages
55 unique aircraft tracks
2021-02-09 11:43:38 +00:00
|
|
|
|
|
|
|
|
// Possible return values of scoreModesMessage,
|
|
|
|
|
// ordered from worst to best
|
|
|
|
|
typedef enum {
|
|
|
|
|
SR_NOT_SET = 0, // message has not been scored yet
|
|
|
|
|
|
|
|
|
|
SR_ALL_ZEROS, // a message that's all zeros
|
|
|
|
|
SR_UNKNOWN_DF, // message with unrecognized DF
|
|
|
|
|
SR_UNCORRECTABLE, // message with uncorrectable errors
|
|
|
|
|
|
|
|
|
|
SR_UNKNOWN_THRESHOLD, // cutoff for message that might be valid, but don't match an existing aircraft
|
|
|
|
|
|
|
|
|
|
SR_UNRELIABLE_UNKNOWN, // Address/Parity, unknown aircraft
|
|
|
|
|
|
|
|
|
|
SR_DF11_IID_1ERROR_UNKNOWN, // DF11, non-zero IID, 1 error, unknown aircraft
|
|
|
|
|
SR_DF11_ACQ_1ERROR_UNKNOWN, // DF11, zero IID, 1 error, unknown aircraft
|
|
|
|
|
SR_DF11_IID_UNKNOWN, // DF11, non-zero IID, no errors, unknown aircraft
|
|
|
|
|
|
|
|
|
|
SR_DF18_2ERROR_UNKNOWN, // DF17, 2 errors, unknown aircraft
|
|
|
|
|
SR_DF17_2ERROR_UNKNOWN, // DF17, 2 errors, unknown aircraft
|
|
|
|
|
|
|
|
|
|
SR_ACCEPT_THRESHOLD, // cutoff for accepting messages
|
|
|
|
|
|
|
|
|
|
// Address/Parity is unreliable, prefer anything else but this
|
|
|
|
|
SR_UNRELIABLE_KNOWN, // Address/Parity, known aircraft
|
|
|
|
|
|
|
|
|
|
// 2-bit error correction is quite unreliable, put it low down the ranking even for known aircraft
|
|
|
|
|
SR_DF18_2ERROR_KNOWN, // DF18, 2 errors, known aircraft
|
|
|
|
|
SR_DF17_2ERROR_KNOWN, // DF17, 2 errors, known aircraft
|
|
|
|
|
|
|
|
|
|
// 1-bit error when we haven't previously seen anything from this address, low priority
|
|
|
|
|
SR_DF18_1ERROR_UNKNOWN, // DF18, 1 error, unknown aircraft
|
|
|
|
|
SR_DF17_1ERROR_UNKNOWN, // DF17, 1 error, unknown aircraft
|
|
|
|
|
|
|
|
|
|
// We need to accept at least one non-ES message type from unknown aircraft
|
|
|
|
|
// or else we'd never accept message from Mode-S only aircraft
|
|
|
|
|
SR_DF11_ACQ_UNKNOWN, // DF11, zero IID, no errors, unknown aircraft
|
|
|
|
|
|
|
|
|
|
SR_DF11_IID_1ERROR_KNOWN, // DF11, non-zero IID, 1 error, known aircraft
|
|
|
|
|
SR_DF11_ACQ_1ERROR_KNOWN, // DF11, zero IID, 1 error, known aircraft
|
|
|
|
|
SR_DF11_IID_KNOWN, // DF11, non-zero IID, no errors, known aircraft
|
|
|
|
|
|
|
|
|
|
SR_DF18_1ERROR_KNOWN, // DF18, 1 error, known aircraft
|
|
|
|
|
SR_DF17_1ERROR_KNOWN, // DF17, 1 error, known aircraft
|
|
|
|
|
|
|
|
|
|
SR_DF11_ACQ_KNOWN, // DF11, zero IID, no errors, known aircraft
|
|
|
|
|
|
|
|
|
|
SR_DF18_UNKNOWN, // DF18, no errors, unknown aircraft
|
|
|
|
|
SR_DF17_UNKNOWN, // DF17, no errors, unknown aircraft
|
|
|
|
|
SR_DF18_KNOWN, // DF18, no errors, known aircraft
|
|
|
|
|
SR_DF17_KNOWN, // DF17, no errors, known aircraft
|
|
|
|
|
} score_rank;
|
|
|
|
|
|
2017-06-15 17:07:40 +00:00
|
|
|
int modesMessageLenByType(int type);
|
Overhaul of message scoring & error correction.
Major changes:
Try to error-correct all messages that potentially could be DF11/17/18
even if the original DF value is different. This allows messages with
correctable damage in the first 5 bits to be correctable.
Track recently-seen DF18 addresses separately to DF17 addresses.
DF18 does not imply Mode S support, so we don't want to treat it like
a known Mode S emitter, but once we've heard some DF18 for an aircraft
we can be more confident about future DF18 messages for the same
address.
Rework the scoring system so it's just a big enum that lists all the
possible outcomes in the order that we want. This makes the relative
ordering of different messages clearer, and makes it easier to move
messages above/below the accept thresholds as needed.
Don't accept 2-bit-error-corrected messages that are from aircraft we
have not previously seen. This greatly reduces the number of garbage
messages when using 2-bit error correction.
Overall results are:
* more CPU required for decoding (approx 30% increase in my tests)
as we're doing a lot more speculative CRC-checking work
* no significant change to message rates with error correction off
* about 5% more 1-bit-corrected DF17 decodes, with a
disproportionate increase in those messages contributing to
successful position decodes / unique aircraft counts
* _fewer_ decodes with 2-bit correction (versus old code with 2-bit
correction), but the message quality is substantially improved,
the rate of garbage decodes / phantom aircraft is greatly reduced
sample stats:
1-bit correction, old code:
141158 total usable messages
137852 accepted with correct CRC
3306 accepted with 1-bit error repaired
27446 DF17 messages
51 unique aircraft tracks
1-bit correction, new code:
141296 total usable messages
137854 accepted with correct CRC
3442 accepted with 1-bit error repaired
27528 DF17 messages
55 unique aircraft tracks
2-bit correction, old code:
142656 total usable messages
137809 accepted with correct CRC
3283 accepted with 1-bit error repaired
1564 accepted with 2-bit error repaired
28803 DF17 messages
349 unique aircraft tracks (<- note that most of these are garbage)
2-bit correction, new code:
142426 total usable messages
137822 accepted with correct CRC
3420 accepted with 1-bit error repaired
1184 accepted with 2-bit error repaired
28666 DF17 messages
55 unique aircraft tracks
2021-02-09 11:43:38 +00:00
|
|
|
score_rank scoreModesMessage(const unsigned char *msg);
|
|
|
|
|
int decodeModesMessage (struct modesMessage *mm, const unsigned char *msg);
|
2017-06-15 17:07:40 +00:00
|
|
|
void displayModesMessage(struct modesMessage *mm);
|
|
|
|
|
void useModesMessage (struct modesMessage *mm);
|
|
|
|
|
|
|
|
|
|
// datafield extraction helpers
|
|
|
|
|
|
|
|
|
|
// The first bit (MSB of the first byte) is numbered 1, for consistency
|
|
|
|
|
// with how the specs number them.
|
|
|
|
|
|
|
|
|
|
// Extract one bit from a message.
|
Overhaul of message scoring & error correction.
Major changes:
Try to error-correct all messages that potentially could be DF11/17/18
even if the original DF value is different. This allows messages with
correctable damage in the first 5 bits to be correctable.
Track recently-seen DF18 addresses separately to DF17 addresses.
DF18 does not imply Mode S support, so we don't want to treat it like
a known Mode S emitter, but once we've heard some DF18 for an aircraft
we can be more confident about future DF18 messages for the same
address.
Rework the scoring system so it's just a big enum that lists all the
possible outcomes in the order that we want. This makes the relative
ordering of different messages clearer, and makes it easier to move
messages above/below the accept thresholds as needed.
Don't accept 2-bit-error-corrected messages that are from aircraft we
have not previously seen. This greatly reduces the number of garbage
messages when using 2-bit error correction.
Overall results are:
* more CPU required for decoding (approx 30% increase in my tests)
as we're doing a lot more speculative CRC-checking work
* no significant change to message rates with error correction off
* about 5% more 1-bit-corrected DF17 decodes, with a
disproportionate increase in those messages contributing to
successful position decodes / unique aircraft counts
* _fewer_ decodes with 2-bit correction (versus old code with 2-bit
correction), but the message quality is substantially improved,
the rate of garbage decodes / phantom aircraft is greatly reduced
sample stats:
1-bit correction, old code:
141158 total usable messages
137852 accepted with correct CRC
3306 accepted with 1-bit error repaired
27446 DF17 messages
51 unique aircraft tracks
1-bit correction, new code:
141296 total usable messages
137854 accepted with correct CRC
3442 accepted with 1-bit error repaired
27528 DF17 messages
55 unique aircraft tracks
2-bit correction, old code:
142656 total usable messages
137809 accepted with correct CRC
3283 accepted with 1-bit error repaired
1564 accepted with 2-bit error repaired
28803 DF17 messages
349 unique aircraft tracks (<- note that most of these are garbage)
2-bit correction, new code:
142426 total usable messages
137822 accepted with correct CRC
3420 accepted with 1-bit error repaired
1184 accepted with 2-bit error repaired
28666 DF17 messages
55 unique aircraft tracks
2021-02-09 11:43:38 +00:00
|
|
|
static inline __attribute__((always_inline)) unsigned getbit(const unsigned char *data, unsigned bitnum)
|
2017-06-15 17:07:40 +00:00
|
|
|
{
|
|
|
|
|
unsigned bi = bitnum - 1;
|
|
|
|
|
unsigned by = bi >> 3;
|
|
|
|
|
unsigned mask = 1 << (7 - (bi & 7));
|
|
|
|
|
|
|
|
|
|
return (data[by] & mask) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Extract some bits (firstbit .. lastbit inclusive) from a message.
|
Overhaul of message scoring & error correction.
Major changes:
Try to error-correct all messages that potentially could be DF11/17/18
even if the original DF value is different. This allows messages with
correctable damage in the first 5 bits to be correctable.
Track recently-seen DF18 addresses separately to DF17 addresses.
DF18 does not imply Mode S support, so we don't want to treat it like
a known Mode S emitter, but once we've heard some DF18 for an aircraft
we can be more confident about future DF18 messages for the same
address.
Rework the scoring system so it's just a big enum that lists all the
possible outcomes in the order that we want. This makes the relative
ordering of different messages clearer, and makes it easier to move
messages above/below the accept thresholds as needed.
Don't accept 2-bit-error-corrected messages that are from aircraft we
have not previously seen. This greatly reduces the number of garbage
messages when using 2-bit error correction.
Overall results are:
* more CPU required for decoding (approx 30% increase in my tests)
as we're doing a lot more speculative CRC-checking work
* no significant change to message rates with error correction off
* about 5% more 1-bit-corrected DF17 decodes, with a
disproportionate increase in those messages contributing to
successful position decodes / unique aircraft counts
* _fewer_ decodes with 2-bit correction (versus old code with 2-bit
correction), but the message quality is substantially improved,
the rate of garbage decodes / phantom aircraft is greatly reduced
sample stats:
1-bit correction, old code:
141158 total usable messages
137852 accepted with correct CRC
3306 accepted with 1-bit error repaired
27446 DF17 messages
51 unique aircraft tracks
1-bit correction, new code:
141296 total usable messages
137854 accepted with correct CRC
3442 accepted with 1-bit error repaired
27528 DF17 messages
55 unique aircraft tracks
2-bit correction, old code:
142656 total usable messages
137809 accepted with correct CRC
3283 accepted with 1-bit error repaired
1564 accepted with 2-bit error repaired
28803 DF17 messages
349 unique aircraft tracks (<- note that most of these are garbage)
2-bit correction, new code:
142426 total usable messages
137822 accepted with correct CRC
3420 accepted with 1-bit error repaired
1184 accepted with 2-bit error repaired
28666 DF17 messages
55 unique aircraft tracks
2021-02-09 11:43:38 +00:00
|
|
|
static inline __attribute__((always_inline)) unsigned getbits(const unsigned char *data, unsigned firstbit, unsigned lastbit)
|
2017-06-15 17:07:40 +00:00
|
|
|
{
|
|
|
|
|
unsigned fbi = firstbit - 1;
|
|
|
|
|
unsigned lbi = lastbit - 1;
|
|
|
|
|
unsigned nbi = (lastbit - firstbit + 1);
|
|
|
|
|
|
|
|
|
|
unsigned fby = fbi >> 3;
|
|
|
|
|
unsigned lby = lbi >> 3;
|
|
|
|
|
unsigned nby = (lby - fby) + 1;
|
|
|
|
|
|
|
|
|
|
unsigned shift = 7 - (lbi & 7);
|
|
|
|
|
unsigned topmask = 0xFF >> (fbi & 7);
|
|
|
|
|
|
|
|
|
|
assert (fbi <= lbi);
|
|
|
|
|
assert (nbi <= 32);
|
|
|
|
|
assert (nby <= 5);
|
|
|
|
|
|
|
|
|
|
if (nby == 5) {
|
|
|
|
|
return
|
|
|
|
|
((data[fby] & topmask) << (32 - shift)) |
|
|
|
|
|
(data[fby + 1] << (24 - shift)) |
|
|
|
|
|
(data[fby + 2] << (16 - shift)) |
|
|
|
|
|
(data[fby + 3] << (8 - shift)) |
|
|
|
|
|
(data[fby + 4] >> shift);
|
|
|
|
|
} else if (nby == 4) {
|
|
|
|
|
return
|
|
|
|
|
((data[fby] & topmask) << (24 - shift)) |
|
|
|
|
|
(data[fby + 1] << (16 - shift)) |
|
|
|
|
|
(data[fby + 2] << (8 - shift)) |
|
|
|
|
|
(data[fby + 3] >> shift);
|
|
|
|
|
} else if (nby == 3) {
|
|
|
|
|
return
|
|
|
|
|
((data[fby] & topmask) << (16 - shift)) |
|
|
|
|
|
(data[fby + 1] << (8 - shift)) |
|
|
|
|
|
(data[fby + 2] >> shift);
|
|
|
|
|
} else if (nby == 2) {
|
|
|
|
|
return
|
|
|
|
|
((data[fby] & topmask) << (8 - shift)) |
|
|
|
|
|
(data[fby + 1] >> shift);
|
|
|
|
|
} else if (nby == 1) {
|
|
|
|
|
return
|
|
|
|
|
(data[fby] & topmask) >> shift;
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|