Changed algorithm to speed up fixSingleBitErrors() and fixTwoBitsErrors().
Old: Modify mesage, recalculate CRC, compare until a valid solution is found. New: Calculate CRC, identify incorrect bits bits, correct message. No recalculation if CRC is needed. Allows fixing of two bit errors on "slow" systems like RaspberryPi.
This commit is contained in:
parent
fccf6e2e9e
commit
05c068ce9b
130
dump1090.c
130
dump1090.c
@ -657,72 +657,104 @@ int modesMessageLenByType(int type) {
|
|||||||
return MODES_SHORT_MSG_BITS;
|
return MODES_SHORT_MSG_BITS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parity table for MODE S Messages. Same as above but with bits set for
|
||||||
|
* message bits containing the actual CRC.
|
||||||
|
*
|
||||||
|
* By xoring all the elements in this table for which the corresponding bit on
|
||||||
|
* the message is set to 1 the result is zero for messages with a valid crc.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static const uint32_t modes_checksum_fix_table[112] = {
|
||||||
|
0x3935ea, 0x1c9af5, 0xf1b77e, 0x78dbbf, 0xc397db, 0x9e31e9, 0xb0e2f0, 0x587178,
|
||||||
|
0x2c38bc, 0x161c5e, 0x0b0e2f, 0xfa7d13, 0x82c48d, 0xbe9842, 0x5f4c21, 0xd05c14,
|
||||||
|
0x682e0a, 0x341705, 0xe5f186, 0x72f8c3, 0xc68665, 0x9cb936, 0x4e5c9b, 0xd8d449,
|
||||||
|
0x939020, 0x49c810, 0x24e408, 0x127204, 0x093902, 0x049c81, 0xfdb444, 0x7eda22,
|
||||||
|
0x3f6d11, 0xe04c8c, 0x702646, 0x381323, 0xe3f395, 0x8e03ce, 0x4701e7, 0xdc7af7,
|
||||||
|
0x91c77f, 0xb719bb, 0xa476d9, 0xadc168, 0x56e0b4, 0x2b705a, 0x15b82d, 0xf52612,
|
||||||
|
0x7a9309, 0xc2b380, 0x6159c0, 0x30ace0, 0x185670, 0x0c2b38, 0x06159c, 0x030ace,
|
||||||
|
0x018567, 0xff38b7, 0x80665f, 0xbfc92b, 0xa01e91, 0xaff54c, 0x57faa6, 0x2bfd53,
|
||||||
|
0xea04ad, 0x8af852, 0x457c29, 0xdd4410, 0x6ea208, 0x375104, 0x1ba882, 0x0dd441,
|
||||||
|
0xf91024, 0x7c8812, 0x3e4409, 0xe0d800, 0x706c00, 0x383600, 0x1c1b00, 0x0e0d80,
|
||||||
|
0x0706c0, 0x038360, 0x01c1b0, 0x00e0d8, 0x00706c, 0x003836, 0x001c1b, 0xfff409,
|
||||||
|
0x800000, 0x400000, 0x200000, 0x100000, 0x080000, 0x040000, 0x020000, 0x010000,
|
||||||
|
0x008000, 0x004000, 0x002000, 0x001000, 0x000800, 0x000400, 0x000200, 0x000100,
|
||||||
|
0x000080, 0x000040, 0x000020, 0x000010, 0x000008, 0x000004, 0x000002, 0x000001
|
||||||
|
};
|
||||||
|
|
||||||
/* Try to fix single bit errors using the checksum. On success modifies
|
/* Try to fix single bit errors using the checksum. On success modifies
|
||||||
* the original buffer with the fixed version, and returns the position
|
* the original buffer with the fixed version, and returns the position
|
||||||
* of the error bit. Otherwise if fixing failed -1 is returned. */
|
* of the error bit. Otherwise if fixing failed -1 is returned. */
|
||||||
int fixSingleBitErrors(unsigned char *msg, int bits) {
|
int fixSingleBitErrors(unsigned char *msg, int bits) {
|
||||||
|
uint32_t crc_zero = 0;
|
||||||
|
int offset = (bits == 112) ? 0 : (112-56);
|
||||||
int j;
|
int j;
|
||||||
unsigned char aux[MODES_LONG_MSG_BITS/8];
|
/* Calculate CRC for given message. Xoring elements of table above if
|
||||||
|
* corresponding bit of message is set. An error free message will give
|
||||||
for (j = 0; j < bits; j++) {
|
* zero in crc_zero after this procedure.
|
||||||
|
*/
|
||||||
|
for(j = 0; j < bits; j++) {
|
||||||
int byte = j/8;
|
int byte = j/8;
|
||||||
int bitmask = 1 << (7-(j%8));
|
int bit = j%8;
|
||||||
uint32_t crc1, crc2;
|
int bitmask = 1 << (7-bit);
|
||||||
|
|
||||||
memcpy(aux,msg,bits/8);
|
/* If bit is set, xor with corresponding table entry. */
|
||||||
aux[byte] ^= bitmask; /* Flip j-th bit. */
|
if (msg[byte] & bitmask)
|
||||||
|
crc_zero ^= modes_checksum_fix_table[j+offset];
|
||||||
|
}
|
||||||
|
|
||||||
crc1 = ((uint32_t)aux[(bits/8)-3] << 16) |
|
/* If message contains a single bit error, the position in the table above
|
||||||
((uint32_t)aux[(bits/8)-2] << 8) |
|
* corresponds to the erroneous bit position */
|
||||||
(uint32_t)aux[(bits/8)-1];
|
for (j = 0; j < bits; j++) {
|
||||||
crc2 = modesChecksum(aux,bits);
|
if(crc_zero == modes_checksum_fix_table[j+offset]){
|
||||||
|
int byte = j/8;
|
||||||
if (crc1 == crc2) {
|
int bitmask = 1 << (7-(j%8));
|
||||||
/* The error is fixed. Overwrite the original buffer with
|
msg[byte] ^= bitmask; /* Flip j-th bit in original buffer. */
|
||||||
* the corrected sequence, and returns the error bit
|
/* The error is fixed. Return the error bit position. */
|
||||||
* position. */
|
|
||||||
memcpy(msg,aux,bits/8);
|
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Similar to fixSingleBitErrors() but try every possible two bit combination.
|
/* Similar to fixSingleBitErrors() but try every possible two bit combination.*/
|
||||||
* This is very slow and should be tried only against DF17 messages that
|
|
||||||
* don't pass the checksum, and only in Aggressive Mode. */
|
|
||||||
int fixTwoBitsErrors(unsigned char *msg, int bits) {
|
int fixTwoBitsErrors(unsigned char *msg, int bits) {
|
||||||
int j, i;
|
uint32_t crc_zero = 0;
|
||||||
unsigned char aux[MODES_LONG_MSG_BITS/8];
|
int offset = (bits == 112) ? 0 : (112-56);
|
||||||
|
int i, j;
|
||||||
|
/* Calculate CRC for given message. Xoring elements of table above if
|
||||||
|
* corresponding bit of message is set. An error free message will give
|
||||||
|
* zero in crc_zero after this procedure.
|
||||||
|
*/
|
||||||
|
for(j = 0; j < bits; j++) {
|
||||||
|
int byte = j/8;
|
||||||
|
int bit = j%8;
|
||||||
|
int bitmask = 1 << (7-bit);
|
||||||
|
|
||||||
|
/* If bit is set, xor with corresponding table entry. */
|
||||||
|
if (msg[byte] & bitmask)
|
||||||
|
crc_zero ^= modes_checksum_fix_table[j+offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If message contains two and exactly two bit errors, crc_zero is the XOR
|
||||||
|
* of two elements of the table above which correspond to the erroneous bit
|
||||||
|
* positions
|
||||||
|
* Iterate over all two bit combinations. */
|
||||||
for (j = 0; j < bits; j++) {
|
for (j = 0; j < bits; j++) {
|
||||||
int byte1 = j/8;
|
|
||||||
int bitmask1 = 1 << (7-(j%8));
|
|
||||||
|
|
||||||
/* Don't check the same pairs multiple times, so i starts from j+1 */
|
|
||||||
for (i = j+1; i < bits; i++) {
|
for (i = j+1; i < bits; i++) {
|
||||||
int byte2 = i/8;
|
/* Try to flip bit j and i.
|
||||||
int bitmask2 = 1 << (7-(i%8));
|
* Again, we do not actually flip these bits in the message buffer
|
||||||
uint32_t crc1, crc2;
|
* but we check if crc_zero would be zero if these bits where
|
||||||
|
* flipped. */
|
||||||
memcpy(aux,msg,bits/8);
|
uint32_t crc_fixed = crc_zero ^ modes_checksum_fix_table[j + offset] ^ modes_checksum_fix_table[i + offset];
|
||||||
|
if(crc_fixed == 0){
|
||||||
aux[byte1] ^= bitmask1; /* Flip j-th bit. */
|
/* We found the two bits which need to be flipped in order to
|
||||||
aux[byte2] ^= bitmask2; /* Flip i-th bit. */
|
* get an CRC error free message.*/
|
||||||
|
int byte1 = j/8;
|
||||||
crc1 = ((uint32_t)aux[(bits/8)-3] << 16) |
|
int bitmask1 = 1 << (7-(j%8));
|
||||||
((uint32_t)aux[(bits/8)-2] << 8) |
|
int byte2 = i/8;
|
||||||
(uint32_t)aux[(bits/8)-1];
|
int bitmask2 = 1 << (7-(i%8));
|
||||||
crc2 = modesChecksum(aux,bits);
|
msg[byte1] ^= bitmask1; /* Flip j-th bit. */
|
||||||
|
msg[byte2] ^= bitmask2; /* Flip i-th bit. */
|
||||||
if (crc1 == crc2) {
|
|
||||||
/* The error is fixed. Overwrite the original buffer with
|
|
||||||
* the corrected sequence, and returns the error bit
|
|
||||||
* position. */
|
|
||||||
memcpy(msg,aux,bits/8);
|
|
||||||
/* We return the two bits as a 16 bit integer by shifting
|
|
||||||
* 'i' on the left. This is possible since 'i' will always
|
|
||||||
* be non-zero because i starts from j+1. */
|
|
||||||
return j | (i<<8);
|
return j | (i<<8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -953,7 +985,7 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) {
|
|||||||
if ((mm->errorbit = fixSingleBitErrors(msg,mm->msgbits)) != -1) {
|
if ((mm->errorbit = fixSingleBitErrors(msg,mm->msgbits)) != -1) {
|
||||||
mm->crc = modesChecksum(msg,mm->msgbits);
|
mm->crc = modesChecksum(msg,mm->msgbits);
|
||||||
mm->crcok = 1;
|
mm->crcok = 1;
|
||||||
} else if (Modes.aggressive && mm->msgtype == 17 &&
|
} else if (Modes.aggressive &&
|
||||||
(mm->errorbit = fixTwoBitsErrors(msg,mm->msgbits)) != -1)
|
(mm->errorbit = fixTwoBitsErrors(msg,mm->msgbits)) != -1)
|
||||||
{
|
{
|
||||||
mm->crc = modesChecksum(msg,mm->msgbits);
|
mm->crc = modesChecksum(msg,mm->msgbits);
|
||||||
|
Loading…
Reference in New Issue
Block a user