2015-01-20 23:04:05 +00:00
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
2015-01-19 23:41:26 +00:00
//
2015-01-20 23:04:05 +00:00
// crc.h: Mode S CRC calculation and error correction.
2015-01-19 23:41:26 +00:00
//
2015-01-20 23:04:05 +00:00
// Copyright (c) 2014,2015 Oliver Jowett <oliver@mutability.co.uk>
2015-01-19 23:41:26 +00:00
//
2017-06-15 17:16:51 +00:00
// This file is free software: you may copy, redistribute and/or modify it
2015-01-20 23:04:05 +00:00
// under the terms of the GNU General Public License as published by the
2017-06-15 17:16:51 +00:00
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
2015-01-19 23:41:26 +00:00
//
2017-06-15 17:16:51 +00:00
// 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
2015-01-20 23:04:05 +00:00
// General Public License for more details.
2015-01-19 23:41:26 +00:00
//
2017-06-15 17:16:51 +00:00
// You should have received a copy of the GNU General Public License
2015-01-20 23:04:05 +00:00
// along with this program. If not, see <http://www.gnu.org/licenses/>.
2015-01-19 23:41:26 +00:00
# include "dump1090.h"
2015-01-20 23:04:05 +00:00
# include <assert.h>
2015-01-21 12:54:27 +00:00
// Errorinfo for "no errors"
static struct errorinfo NO_ERRORS ;
2015-01-20 23:04:05 +00:00
// Generator polynomial for the Mode S CRC:
# define MODES_GENERATOR_POLY 0xfff409U
// CRC values for all single-byte messages;
// used to speed up CRC calculation.
static uint32_t crc_table [ 256 ] ;
// Syndrome values for all single-bit errors;
// used to speed up construction of error-
// correction tables.
static uint32_t single_bit_syndrome [ 112 ] ;
static void initLookupTables ( )
{
int i ;
uint8_t msg [ 112 / 8 ] ;
2017-06-15 17:16:51 +00:00
2015-01-20 23:04:05 +00:00
for ( i = 0 ; i < 256 ; + + i ) {
uint32_t c = i < < 16 ;
int j ;
for ( j = 0 ; j < 8 ; + + j ) {
if ( c & 0x800000 )
c = ( c < < 1 ) ^ MODES_GENERATOR_POLY ;
else
c = ( c < < 1 ) ;
}
crc_table [ i ] = c & 0x00ffffff ;
}
memset ( msg , 0 , sizeof ( msg ) ) ;
for ( i = 0 ; i < 112 ; + + i ) {
msg [ i / 8 ] ^ = 1 < < ( 7 - ( i & 7 ) ) ;
single_bit_syndrome [ i ] = modesChecksum ( msg , 112 ) ;
msg [ i / 8 ] ^ = 1 < < ( 7 - ( i & 7 ) ) ;
}
2015-01-19 23:41:26 +00:00
}
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
uint32_t modesChecksum ( const uint8_t * message , int bits )
2015-01-20 23:04:05 +00:00
{
uint32_t rem = 0 ;
int i ;
int n = bits / 8 ;
assert ( bits % 8 = = 0 ) ;
assert ( n > = 3 ) ;
for ( i = 0 ; i < n - 3 ; + + i ) {
rem = ( rem < < 8 ) ^ crc_table [ message [ i ] ^ ( ( rem & 0xff0000 ) > > 16 ) ] ;
rem = rem & 0xffffff ;
}
rem = rem ^ ( message [ n - 3 ] < < 16 ) ^ ( message [ n - 2 ] < < 8 ) ^ ( message [ n - 1 ] ) ;
return rem ;
}
static struct errorinfo * bitErrorTable_short ;
static int bitErrorTableSize_short ;
static struct errorinfo * bitErrorTable_long ;
static int bitErrorTableSize_long ;
// compare two errorinfo structures
static int syndrome_compare ( const void * x , const void * y ) {
struct errorinfo * ex = ( struct errorinfo * ) x ;
struct errorinfo * ey = ( struct errorinfo * ) y ;
return ( int ) ex - > syndrome - ( int ) ey - > syndrome ;
}
// (n k), the number of ways of selecting k distinct items from a set of n items
static int combinations ( int n , int k )
{
int result = 1 , i ;
if ( k = = 0 | | k = = n )
2015-01-19 23:41:26 +00:00
return 1 ;
2015-01-20 23:04:05 +00:00
if ( k > n )
return 0 ;
for ( i = 1 ; i < = k ; + + i ) {
result = result * n / i ;
n = n - 1 ;
2015-01-19 23:41:26 +00:00
}
2015-01-20 23:04:05 +00:00
return result ;
2015-01-19 23:41:26 +00:00
}
2015-01-20 23:04:05 +00:00
// Recursively populates an errorinfo table with error syndromes
2015-01-19 23:41:26 +00:00
//
2015-01-20 23:04:05 +00:00
// in:
// table: the table to fill
// n: first entry to fill
// maxSize: max size of table
// offset: start bit offset for checksum calculation
// startbit: first bit to introduce errors into
// endbit: (one past) last bit to introduce errors info
// base_entry: template entry to start from
// error_bit: how many error bits have already been set
// max_errors: maximum total error bits to set
// out:
// returns: the next free entry in the table
// table: has been populated between [n, return value)
static int prepareSubtable ( struct errorinfo * table , int n , int maxsize , int offset , int startbit , int endbit , struct errorinfo * base_entry , int error_bit , int max_errors )
{
int i = 0 ;
if ( error_bit > = max_errors )
return n ;
for ( i = startbit ; i < endbit ; + + i ) {
assert ( n < maxsize ) ;
table [ n ] = * base_entry ;
table [ n ] . syndrome ^ = single_bit_syndrome [ i + offset ] ;
table [ n ] . errors = error_bit + 1 ;
table [ n ] . bit [ error_bit ] = i ;
2017-06-15 17:16:51 +00:00
2015-01-20 23:04:05 +00:00
+ + n ;
n = prepareSubtable ( table , n , maxsize , offset , i + 1 , endbit , & table [ n - 1 ] , error_bit + 1 , max_errors ) ;
}
return n ;
}
static int flagCollisions ( struct errorinfo * table , int tablesize , int offset , int startbit , int endbit , uint32_t base_syndrome , int error_bit , int first_error , int last_error )
{
int i = 0 ;
int count = 0 ;
if ( error_bit > last_error )
return 0 ;
for ( i = startbit ; i < endbit ; + + i ) {
struct errorinfo ei ;
ei . syndrome = base_syndrome ^ single_bit_syndrome [ i + offset ] ;
if ( error_bit > = first_error ) {
struct errorinfo * collision = bsearch ( & ei , table , tablesize , sizeof ( struct errorinfo ) , syndrome_compare ) ;
if ( collision ! = NULL & & collision - > errors ! = - 1 ) {
+ + count ;
collision - > errors = - 1 ;
2015-01-19 23:41:26 +00:00
}
}
2015-01-20 23:04:05 +00:00
count + = flagCollisions ( table , tablesize , offset , i + 1 , endbit , ei . syndrome , error_bit + 1 , first_error , last_error ) ;
}
return count ;
}
// Allocate and build an error table for messages of length "bits" (max 112)
// returns a pointer to the new table and sets *size_out to the table length
static struct errorinfo * prepareErrorTable ( int bits , int max_correct , int max_detect , int * size_out )
{
int maxsize , usedsize ;
struct errorinfo * table ;
struct errorinfo base_entry ;
int i , j ;
assert ( bits > = 0 & & bits < = 112 ) ;
assert ( max_correct > = 0 & & max_correct < = MODES_MAX_BITERRORS ) ;
assert ( max_detect > = max_correct ) ;
if ( ! max_correct ) {
* size_out = 0 ;
return NULL ;
}
maxsize = 0 ;
for ( i = 1 ; i < = max_correct ; + + i ) {
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
maxsize + = combinations ( bits , i ) ; // space needed for all i-bit errors
2015-01-20 23:04:05 +00:00
}
2017-06-15 17:16:51 +00:00
# ifdef CRCDEBUG
2015-01-20 23:04:05 +00:00
fprintf ( stderr , " Preparing syndrome table to correct up to %d-bit errors (detecting %d-bit errors) in a %d-bit message (max %d entries) \n " , max_correct , max_detect , bits , maxsize ) ;
# endif
table = malloc ( maxsize * sizeof ( struct errorinfo ) ) ;
base_entry . syndrome = 0 ;
base_entry . errors = 0 ;
for ( i = 0 ; i < MODES_MAX_BITERRORS ; + + i )
base_entry . bit [ i ] = - 1 ;
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
usedsize = prepareSubtable ( table , 0 , maxsize , 112 - bits , 0 , bits , & base_entry , 0 , max_correct ) ;
2017-06-15 17:16:51 +00:00
2015-01-20 23:04:05 +00:00
# ifdef CRCDEBUG
fprintf ( stderr , " %d syndromes (expected %d). \n " , usedsize , maxsize ) ;
fprintf ( stderr , " Sorting syndromes.. \n " ) ;
# endif
qsort ( table , usedsize , sizeof ( struct errorinfo ) , syndrome_compare ) ;
2017-06-15 17:16:51 +00:00
# ifdef CRCDEBUG
2015-01-20 23:04:05 +00:00
{
// Show the table stats
fprintf ( stderr , " Undetectable errors: \n " ) ;
for ( i = 1 ; i < = max_correct ; + + i ) {
int j , count ;
2017-06-15 17:16:51 +00:00
2015-01-20 23:04:05 +00:00
count = 0 ;
2017-06-15 17:16:51 +00:00
for ( j = 0 ; j < usedsize ; + + j )
2015-01-20 23:04:05 +00:00
if ( table [ j ] . errors = = i & & table [ j ] . syndrome = = 0 )
+ + count ;
fprintf ( stderr , " %d undetectable %d-bit errors \n " , count , i ) ;
2015-01-19 23:41:26 +00:00
}
}
2015-01-20 23:04:05 +00:00
# endif
2015-01-19 23:41:26 +00:00
2015-01-20 23:04:05 +00:00
// Handle ambiguous cases, where there is more than one possible error pattern
// that produces a given syndrome (this happens with >2 bit errors).
2017-06-15 17:16:51 +00:00
# ifdef CRCDEBUG
2015-01-20 23:04:05 +00:00
fprintf ( stderr , " Finding collisions.. \n " ) ;
# endif
for ( i = 0 , j = 0 ; i < usedsize ; + + i ) {
if ( i < usedsize - 1 & & table [ i + 1 ] . syndrome = = table [ i ] . syndrome ) {
// skip over this entry and all collisions
while ( i < usedsize & & table [ i + 1 ] . syndrome = = table [ i ] . syndrome )
+ + i ;
// now table[i] is the last duplicate
continue ;
}
if ( i ! = j )
table [ j ] = table [ i ] ;
+ + j ;
2015-01-19 23:41:26 +00:00
}
2015-01-20 23:04:05 +00:00
if ( j < usedsize ) {
# ifdef CRCDEBUG
fprintf ( stderr , " Discarded %d collisions. \n " , usedsize - j ) ;
# endif
usedsize = j ;
2015-01-19 23:41:26 +00:00
}
2017-06-15 17:16:51 +00:00
2015-01-20 23:04:05 +00:00
// Flag collisions we want to detect but not correct
if ( max_detect > max_correct ) {
int flagged ;
2015-01-19 23:41:26 +00:00
2015-01-20 23:04:05 +00:00
# ifdef CRCDEBUG
fprintf ( stderr , " Flagging collisions between %d - %d bits.. \n " , max_correct + 1 , max_detect ) ;
# endif
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
flagged = flagCollisions ( table , usedsize , 112 - bits , 0 , bits , 0 , 1 , max_correct + 1 , max_detect ) ;
2015-01-20 23:04:05 +00:00
# ifdef CRCDEBUG
fprintf ( stderr , " Flagged %d collisions for removal. \n " , flagged ) ;
# else
# endif
if ( flagged > 0 ) {
for ( i = 0 , j = 0 ; i < usedsize ; + + i ) {
if ( table [ i ] . errors ! = - 1 ) {
if ( i ! = j )
table [ j ] = table [ i ] ;
+ + j ;
}
}
# ifdef CRCDEBUG
fprintf ( stderr , " Discarded %d flagged collisions. \n " , usedsize - j ) ;
# endif
usedsize = j ;
}
2015-01-19 23:41:26 +00:00
}
2015-01-20 23:04:05 +00:00
if ( usedsize < maxsize ) {
# ifdef CRCDEBUG
fprintf ( stderr , " Shrinking table from %d to %d.. \n " , maxsize , usedsize ) ;
table = realloc ( table , usedsize * sizeof ( struct errorinfo ) ) ;
# endif
2015-01-19 23:41:26 +00:00
}
2017-06-15 17:16:51 +00:00
2015-01-20 23:04:05 +00:00
* size_out = usedsize ;
2017-06-15 17:16:51 +00:00
2015-01-20 23:04:05 +00:00
# ifdef CRCDEBUG
{
// Check the table.
unsigned char * msg = malloc ( bits / 8 ) ;
2015-01-19 23:41:26 +00:00
2015-01-20 23:04:05 +00:00
for ( i = 0 ; i < usedsize ; + + i ) {
int j ;
struct errorinfo * ei ;
uint32_t result ;
memset ( msg , 0 , bits / 8 ) ;
ei = & table [ i ] ;
for ( j = 0 ; j < ei - > errors ; + + j ) {
msg [ ei - > bit [ j ] > > 3 ] ^ = 1 < < ( 7 - ( ei - > bit [ j ] & 7 ) ) ;
}
result = modesChecksum ( msg , bits ) ;
if ( result ! = ei - > syndrome ) {
fprintf ( stderr , " PROBLEM: entry %6d/%6d syndrome %06x errors %d bits " , i , usedsize , ei - > syndrome , ei - > errors ) ;
for ( j = 0 ; j < ei - > errors ; + + j )
fprintf ( stderr , " %3d " , ei - > bit [ j ] ) ;
fprintf ( stderr , " checksum %06x \n " , result ) ;
}
}
free ( msg ) ;
// Show the table stats
fprintf ( stderr , " Syndrome table summary: \n " ) ;
for ( i = 1 ; i < = max_correct ; + + i ) {
int j , count , possible ;
2017-06-15 17:16:51 +00:00
2015-01-20 23:04:05 +00:00
count = 0 ;
2017-06-15 17:16:51 +00:00
for ( j = 0 ; j < usedsize ; + + j )
2015-01-20 23:04:05 +00:00
if ( table [ j ] . errors = = i )
+ + count ;
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 = combinations ( bits , i ) ;
2015-01-20 23:04:05 +00:00
fprintf ( stderr , " %d entries for %d-bit errors (%d possible, %d%% coverage) \n " , count , i , possible , 100 * count / possible ) ;
}
fprintf ( stderr , " %d entries total \n " , usedsize ) ;
}
# endif
return table ;
}
// Precompute syndrome tables for 56- and 112-bit messages.
void modesChecksumInit ( int fixBits )
{
initLookupTables ( ) ;
switch ( fixBits ) {
case 0 :
bitErrorTable_short = bitErrorTable_long = NULL ;
bitErrorTableSize_short = bitErrorTableSize_long = 0 ;
break ;
case 1 :
// For 1 bit correction, we have 100% coverage up to 4 bit detection, so don't bother
// with flagging collisions there.
bitErrorTable_short = prepareErrorTable ( MODES_SHORT_MSG_BITS , 1 , 1 , & bitErrorTableSize_short ) ;
bitErrorTable_long = prepareErrorTable ( MODES_LONG_MSG_BITS , 1 , 1 , & bitErrorTableSize_long ) ;
break ;
default :
// Detect out to 4 bit errors; this reduces our 2-bit coverage to about 65%.
// This can take a little while - tell the user.
fprintf ( stderr , " Preparing error correction tables.. " ) ;
bitErrorTable_short = prepareErrorTable ( MODES_SHORT_MSG_BITS , 2 , 4 , & bitErrorTableSize_short ) ;
bitErrorTable_long = prepareErrorTable ( MODES_LONG_MSG_BITS , 2 , 4 , & bitErrorTableSize_long ) ;
fprintf ( stderr , " done. \n " ) ;
break ;
}
}
// Given an error syndrome and message length, return
// an error-correction descriptor, or NULL if the
// syndrome is uncorrectable
struct errorinfo * modesChecksumDiagnose ( uint32_t syndrome , int bitlen )
{
struct errorinfo * table ;
int tablesize ;
struct errorinfo ei ;
if ( syndrome = = 0 )
2015-01-21 12:54:27 +00:00
return & NO_ERRORS ;
2015-01-20 23:04:05 +00:00
assert ( bitlen = = 56 | | bitlen = = 112 ) ;
if ( bitlen = = 56 ) { table = bitErrorTable_short ; tablesize = bitErrorTableSize_short ; }
else { table = bitErrorTable_long ; tablesize = bitErrorTableSize_long ; }
if ( ! table )
return NULL ;
ei . syndrome = syndrome ;
return bsearch ( & ei , table , tablesize , sizeof ( struct errorinfo ) , syndrome_compare ) ;
}
// Given a message and an error-correction descriptor,
// apply the error correction to the given message.
void modesChecksumFix ( uint8_t * msg , struct errorinfo * info )
{
int i ;
if ( ! info )
return ;
for ( i = 0 ; i < info - > errors ; + + i )
msg [ info - > bit [ i ] > > 3 ] ^ = 1 < < ( 7 - ( info - > bit [ i ] & 7 ) ) ;
}
# ifdef CRCDEBUG
int main ( int argc , char * * argv )
{
2015-01-23 21:59:31 +00:00
int shortlen , longlen ;
int i ;
struct errorinfo * shorttable , * longtable ;
2015-01-20 23:04:05 +00:00
if ( argc < 3 ) {
fprintf ( stderr , " syntax: crctests <ncorrect> <ndetect> \n " ) ;
return 1 ;
2015-01-19 23:41:26 +00:00
}
2015-01-20 23:04:05 +00:00
initLookupTables ( ) ;
2015-01-23 21:59:31 +00:00
shorttable = prepareErrorTable ( MODES_SHORT_MSG_BITS , atoi ( argv [ 1 ] ) , atoi ( argv [ 2 ] ) , & shortlen ) ;
longtable = prepareErrorTable ( MODES_LONG_MSG_BITS , atoi ( argv [ 1 ] ) , atoi ( argv [ 2 ] ) , & longlen ) ;
// check for DF11 correction syndromes where there is a syndrome with lower 7 bits all zero
// (which would be used for DF11 error correction), but there's also a syndrome which has
// the same upper 17 bits but nonzero lower 7 bits.
// empirically, with ncorrect=1 ndetect=2 we get no ambiguous syndromes;
// for ncorrect=2 ndetect=4 we get 11 ambiguous syndromes:
/*
syndrome 1 = 000 C00 bits = [ 44 45 ]
syndrome 2 = 000 C1B bits = [ 30 43 ]
syndrome 1 = 001400 bits = [ 43 45 ]
syndrome 2 = 00141 B bits = [ 30 44 ]
syndrome 1 = 001 800 bits = [ 43 44 ]
syndrome 2 = 001 81 B bits = [ 30 45 ]
syndrome 1 = 001 800 bits = [ 43 44 ]
syndrome 2 = 001 836 bits = [ 29 42 ]
syndrome 1 = 002400 bits = [ 42 45 ]
syndrome 2 = 00242 D bits = [ 29 30 ]
syndrome 1 = 002 800 bits = [ 42 44 ]
syndrome 2 = 002 836 bits = [ 29 43 ]
syndrome 1 = 003000 bits = [ 42 43 ]
syndrome 2 = 003036 bits = [ 29 44 ]
syndrome 1 = 003000 bits = [ 42 43 ]
syndrome 2 = 00306 C bits = [ 28 41 ]
syndrome 1 = 004 800 bits = [ 41 44 ]
syndrome 2 = 004 85 A bits = [ 28 29 ]
syndrome 1 = 005000 bits = [ 41 43 ]
syndrome 2 = 00506 C bits = [ 28 42 ]
syndrome 1 = 006000 bits = [ 41 42 ]
syndrome 2 = 00606 C bits = [ 28 43 ]
*/
// So in the DF11 correction logic, we just discard messages that require more than a 1 bit fix.
fprintf ( stderr , " checking %d syndromes for DF11 collisions.. \n " , shortlen ) ;
for ( i = 0 ; i < shortlen ; + + i ) {
if ( ( shorttable [ i ] . syndrome & 0xFF ) = = 0 ) {
int j ;
// all syndromes with the same first 17 bits should sort immediately after entry i,
// so this is fairly easy
for ( j = i + 1 ; j < shortlen ; + + j ) {
if ( ( shorttable [ i ] . syndrome & 0xFFFF80 ) = = ( shorttable [ j ] . syndrome & 0xFFFF80 ) ) {
int k ;
int mismatch = 0 ;
// we don't care if the only differences are in bits that lie in the checksum
for ( k = 0 ; k < shorttable [ i ] . errors ; + + k ) {
int l , matched = 0 ;
if ( shorttable [ i ] . bit [ k ] > = 49 )
continue ; // bit is in the final 7 bits, we don't care
for ( l = 0 ; l < shorttable [ j ] . errors ; + + l ) {
if ( shorttable [ i ] . bit [ k ] = = shorttable [ j ] . bit [ l ] ) {
matched = 1 ;
break ;
}
}
if ( ! matched )
mismatch = 1 ;
}
for ( k = 0 ; k < shorttable [ j ] . errors ; + + k ) {
int l , matched = 0 ;
if ( shorttable [ j ] . bit [ k ] > = 49 )
continue ; // bit is in the final 7 bits, we don't care
for ( l = 0 ; l < shorttable [ i ] . errors ; + + l ) {
if ( shorttable [ j ] . bit [ k ] = = shorttable [ i ] . bit [ l ] ) {
matched = 1 ;
break ;
}
}
if ( ! matched )
mismatch = 1 ;
}
if ( mismatch ) {
fprintf ( stderr ,
" DF11 correction collision: \n "
" syndrome 1 = %06X bits=[ " ,
shorttable [ i ] . syndrome ) ;
for ( k = 0 ; k < shorttable [ i ] . errors ; + + k )
fprintf ( stderr , " %d " , shorttable [ i ] . bit [ k ] ) ;
fprintf ( stderr , " ] \n " ) ;
fprintf ( stderr ,
" syndrome 2 = %06X bits=[ " ,
shorttable [ j ] . syndrome ) ;
for ( k = 0 ; k < shorttable [ j ] . errors ; + + k )
fprintf ( stderr , " %d " , shorttable [ j ] . bit [ k ] ) ;
fprintf ( stderr , " ] \n " ) ;
}
} else {
break ;
}
}
}
}
free ( shorttable ) ;
free ( longtable ) ;
2015-01-20 23:04:05 +00:00
return 0 ;
2015-01-19 23:41:26 +00:00
}
2015-01-20 23:04:05 +00:00
# endif