From 07df054590712e90a9d9eb10b0907c30dbd65349 Mon Sep 17 00:00:00 2001 From: Oliver Jowett Date: Mon, 19 Jan 2015 23:41:26 +0000 Subject: [PATCH] Move CRC code to a separate file. --- Makefile | 8 +- crc.c | 245 ++++++++++++++++++++++++++++++++++++++++++++ crc.h | 40 ++++++++ dump1090.h | 8 +- mode_s.c | 290 ----------------------------------------------------- 5 files changed, 293 insertions(+), 298 deletions(-) create mode 100644 crc.c create mode 100644 crc.h diff --git a/Makefile b/Makefile index 2f068d4..4f54027 100644 --- a/Makefile +++ b/Makefile @@ -21,11 +21,11 @@ all: dump1090 view1090 %.o: %.c dump1090.h $(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRACFLAGS) -c $< -dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o - $(CC) -g -o dump1090 dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS) $(LIBS_RTL) $(LDFLAGS) +dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o crc.o + $(CC) -g -o dump1090 $^ $(LIBS) $(LIBS_RTL) $(LDFLAGS) -view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o - $(CC) -g -o view1090 view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS) $(LDFLAGS) +view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o crc.o + $(CC) -g -o view1090 $^ $(LIBS) $(LDFLAGS) clean: rm -f *.o dump1090 view1090 diff --git a/crc.c b/crc.c new file mode 100644 index 0000000..316f5c2 --- /dev/null +++ b/crc.c @@ -0,0 +1,245 @@ +// dump1090, a Mode S messages decoder for RTLSDR devices. +// +// Copyright (C) 2012 by Salvatore Sanfilippo +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "dump1090.h" + +// Parity table for MODE S Messages. +// The table contains 112 elements, every element corresponds to a bit set +// in the message, starting from the first bit of actual data after the +// preamble. +// +// For messages of 112 bit, the whole table is used. +// For messages of 56 bits only the last 56 elements are used. +// +// The algorithm is as simple as xoring all the elements in this table +// for which the corresponding bit on the message is set to 1. +// +// The latest 24 elements in this table are set to 0 as the checksum at the +// end of the message should not affect the computation. +// +// Note: this function can be used with DF11 and DF17, other modes have +// the CRC xored with the sender address as they are reply to interrogations, +// but a casual listener can't split the address from the checksum. +// +uint32_t modes_checksum_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, +0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, +0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, +0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 +}; + +uint32_t modesChecksum(unsigned char *msg, int bits) { + uint32_t crc = 0; + uint32_t rem = 0; + int offset = (bits == 112) ? 0 : (112-56); + uint8_t theByte = *msg; + uint32_t * pCRCTable = &modes_checksum_table[offset]; + int j; + + // We don't really need to include the checksum itself + bits -= 24; + for(j = 0; j < bits; j++) { + if ((j & 7) == 0) + theByte = *msg++; + + // If bit is set, xor with corresponding table entry. + if (theByte & 0x80) {crc ^= *pCRCTable;} + pCRCTable++; + theByte = theByte << 1; + } + + rem = (msg[0] << 16) | (msg[1] << 8) | msg[2]; // message checksum + return ((crc ^ rem) & 0x00FFFFFF); // 24 bit checksum syndrome. +} + +//========================================================================= +// +// Code for introducing a less CPU-intensive method of correcting +// single bit errors. +// +// Makes use of the fact that the crc checksum is linear with respect to +// the bitwise xor operation, i.e. +// crc(m^e) = (crc(m)^crc(e) +// where m and e are the message resp. error bit vectors. +// +// Call crc(e) the syndrome. +// +// The code below works by precomputing a table of (crc(e), e) for all +// possible error vectors e (here only single bit and double bit errors), +// search for the syndrome in the table, and correct the then known error. +// The error vector e is represented by one or two bit positions that are +// changed. If a second bit position is not used, it is -1. +// +// Run-time is binary search in a sorted table, plus some constant overhead, +// instead of running through all possible bit positions (resp. pairs of +// bit positions). +// +struct errorinfo { + uint32_t syndrome; // CRC syndrome + int bits; // Number of bit positions to fix + int pos[MODES_MAX_BITERRORS]; // Bit positions corrected by this syndrome +}; + +#define NERRORINFO \ + (MODES_LONG_MSG_BITS+MODES_LONG_MSG_BITS*(MODES_LONG_MSG_BITS-1)/2) +struct errorinfo bitErrorTable[NERRORINFO]; + +// Compare function as needed for stdlib's qsort and bsearch functions +static int cmpErrorInfo(const void *p0, const void *p1) { + struct errorinfo *e0 = (struct errorinfo*)p0; + struct errorinfo *e1 = (struct errorinfo*)p1; + if (e0->syndrome == e1->syndrome) { + return 0; + } else if (e0->syndrome < e1->syndrome) { + return -1; + } else { + return 1; + } +} +// +//========================================================================= +// +// Compute the table of all syndromes for 1-bit and 2-bit error vectors +void modesInitErrorInfo() { + unsigned char msg[MODES_LONG_MSG_BYTES]; + int i, j, n; + uint32_t crc; + n = 0; + memset(bitErrorTable, 0, sizeof(bitErrorTable)); + memset(msg, 0, MODES_LONG_MSG_BYTES); + // Add all possible single and double bit errors + // don't include errors in first 5 bits (DF type) + for (i = 5; i < MODES_LONG_MSG_BITS; i++) { + int bytepos0 = (i >> 3); + int mask0 = 1 << (7 - (i & 7)); + msg[bytepos0] ^= mask0; // create error0 + crc = modesChecksum(msg, MODES_LONG_MSG_BITS); + bitErrorTable[n].syndrome = crc; // single bit error case + bitErrorTable[n].bits = 1; + bitErrorTable[n].pos[0] = i; + bitErrorTable[n].pos[1] = -1; + n += 1; + + if (Modes.nfix_crc > 1) { + for (j = i+1; j < MODES_LONG_MSG_BITS; j++) { + int bytepos1 = (j >> 3); + int mask1 = 1 << (7 - (j & 7)); + msg[bytepos1] ^= mask1; // create error1 + crc = modesChecksum(msg, MODES_LONG_MSG_BITS); + if (n >= NERRORINFO) { + //fprintf(stderr, "Internal error, too many entries, fix NERRORINFO\n"); + break; + } + bitErrorTable[n].syndrome = crc; // two bit error case + bitErrorTable[n].bits = 2; + bitErrorTable[n].pos[0] = i; + bitErrorTable[n].pos[1] = j; + n += 1; + msg[bytepos1] ^= mask1; // revert error1 + } + } + msg[bytepos0] ^= mask0; // revert error0 + } + qsort(bitErrorTable, NERRORINFO, sizeof(struct errorinfo), cmpErrorInfo); + + // Test code: report if any syndrome appears at least twice. In this + // case the correction cannot be done without ambiguity. + // Tried it, does not happen for 1- and 2-bit errors. + /* + for (i = 1; i < NERRORINFO; i++) { + if (bitErrorTable[i-1].syndrome == bitErrorTable[i].syndrome) { + fprintf(stderr, "modesInitErrorInfo: Collision for syndrome %06x\n", + (int)bitErrorTable[i].syndrome); + } + } + + for (i = 0; i < NERRORINFO; i++) { + printf("syndrome %06x bit0 %3d bit1 %3d\n", + bitErrorTable[i].syndrome, + bitErrorTable[i].pos0, bitErrorTable[i].pos1); + } + */ +} +// +//========================================================================= +// +// Search for syndrome in table and if an entry is found, flip the necessary +// bits. Make sure the indices fit into the array +// Additional parameter: fix only less than maxcorrected bits, and record +// fixed bit positions in corrected[]. This array can be NULL, otherwise +// must be of length at least maxcorrected. +// Return number of fixed bits. +// +int fixBitErrors(unsigned char *msg, int bits, int maxfix, char *fixedbits) { + struct errorinfo *pei; + struct errorinfo ei; + int bitpos, offset, res, i; + memset(&ei, 0, sizeof(struct errorinfo)); + ei.syndrome = modesChecksum(msg, bits); + pei = bsearch(&ei, bitErrorTable, NERRORINFO, + sizeof(struct errorinfo), cmpErrorInfo); + if (pei == NULL) { + return 0; // No syndrome found + } + + // Check if the syndrome fixes more bits than we allow + if (maxfix < pei->bits) { + return 0; + } + + // Check that all bit positions lie inside the message length + offset = MODES_LONG_MSG_BITS-bits; + for (i = 0; i < pei->bits; i++) { + bitpos = pei->pos[i] - offset; + if ((bitpos < 0) || (bitpos >= bits)) { + return 0; + } + } + + // Fix the bits + for (i = res = 0; i < pei->bits; i++) { + bitpos = pei->pos[i] - offset; + msg[bitpos >> 3] ^= (1 << (7 - (bitpos & 7))); + if (fixedbits) { + fixedbits[res++] = bitpos; + } + } + return res; +} diff --git a/crc.h b/crc.h new file mode 100644 index 0000000..d116860 --- /dev/null +++ b/crc.h @@ -0,0 +1,40 @@ +// dump1090, a Mode S messages decoder for RTLSDR devices. +// +// Copyright (C) 2012 by Salvatore Sanfilippo +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef DUMP1090_CRC_H +#define DUMP1090_CRC_H + +#include + +void modesInitErrorInfo(); +uint32_t modesChecksum(unsigned char *msg, int bits); +int fixBitErrors(unsigned char *msg, int bits, int maxfix, char *fixedbits); + +#endif diff --git a/dump1090.h b/dump1090.h index 0bec186..dc444a8 100644 --- a/dump1090.h +++ b/dump1090.h @@ -65,14 +65,14 @@ #include #include #include - #include "rtl-sdr.h" - #include "anet.h" #else #include "winstubs.h" //Put everything Windows specific in here - #include "rtl-sdr.h" - #include "anet.h" #endif +#include "rtl-sdr.h" +#include "anet.h" +#include "crc.h" + // ============================= #defines =============================== // // If you have a valid coaa.h, these values will come from it. If not, diff --git a/mode_s.c b/mode_s.c index ee569fc..4c5a6b7 100644 --- a/mode_s.c +++ b/mode_s.c @@ -32,65 +32,9 @@ // // ===================== Mode S detection and decoding =================== // -// Parity table for MODE S Messages. -// The table contains 112 elements, every element corresponds to a bit set -// in the message, starting from the first bit of actual data after the -// preamble. // -// For messages of 112 bit, the whole table is used. -// For messages of 56 bits only the last 56 elements are used. // -// The algorithm is as simple as xoring all the elements in this table -// for which the corresponding bit on the message is set to 1. -// -// The latest 24 elements in this table are set to 0 as the checksum at the -// end of the message should not affect the computation. -// -// Note: this function can be used with DF11 and DF17, other modes have -// the CRC xored with the sender address as they are reply to interrogations, -// but a casual listener can't split the address from the checksum. -// -uint32_t modes_checksum_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, -0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, -0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, -0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 -}; -uint32_t modesChecksum(unsigned char *msg, int bits) { - uint32_t crc = 0; - uint32_t rem = 0; - int offset = (bits == 112) ? 0 : (112-56); - uint8_t theByte = *msg; - uint32_t * pCRCTable = &modes_checksum_table[offset]; - int j; - - // We don't really need to include the checksum itself - bits -= 24; - for(j = 0; j < bits; j++) { - if ((j & 7) == 0) - theByte = *msg++; - - // If bit is set, xor with corresponding table entry. - if (theByte & 0x80) {crc ^= *pCRCTable;} - pCRCTable++; - theByte = theByte << 1; - } - - rem = (msg[0] << 16) | (msg[1] << 8) | msg[2]; // message checksum - return ((crc ^ rem) & 0x00FFFFFF); // 24 bit checksum syndrome. -} -// //========================================================================= // // Given the Downlink Format (DF) of the message, return the message length in bits. @@ -102,241 +46,7 @@ uint32_t modesChecksum(unsigned char *msg, int bits) { int modesMessageLenByType(int type) { return (type & 0x10) ? MODES_LONG_MSG_BITS : MODES_SHORT_MSG_BITS ; } -// -//========================================================================= -// -// Try to fix single bit errors using the checksum. On success modifies -// the original buffer with the fixed version, and returns the position -// of the error bit. Otherwise if fixing failed -1 is returned. -/* -int fixSingleBitErrors(unsigned char *msg, int bits) { - int j; - unsigned char aux[MODES_LONG_MSG_BYTES]; - memcpy(aux, msg, bits/8); - - // Do not attempt to error correct Bits 0-4. These contain the DF, and must - // be correct because we can only error correct DF17 - for (j = 5; j < bits; j++) { - int byte = j/8; - int bitmask = 1 << (7 - (j & 7)); - - aux[byte] ^= bitmask; // Flip j-th bit - - if (0 == modesChecksum(aux, bits)) { - // The error is fixed. Overwrite the original buffer with the - // corrected sequence, and returns the error bit position - msg[byte] = aux[byte]; - return (j); - } - - aux[byte] ^= bitmask; // Flip j-th bit back again - } - return (-1); -} -*/ -//========================================================================= -// -// 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 j, i; - unsigned char aux[MODES_LONG_MSG_BYTES]; - - memcpy(aux, msg, bits/8); - - // Do not attempt to error correct Bits 0-4. These contain the DF, and must - // be correct because we can only error correct DF17 - for (j = 5; j < bits; j++) { - int byte1 = j/8; - int bitmask1 = 1 << (7 - (j & 7)); - aux[byte1] ^= bitmask1; // Flip j-th bit - - // Don't check the same pairs multiple times, so i starts from j+1 - for (i = j+1; i < bits; i++) { - int byte2 = i/8; - int bitmask2 = 1 << (7 - (i & 7)); - - aux[byte2] ^= bitmask2; // Flip i-th bit - - if (0 == modesChecksum(aux, bits)) { - // The error is fixed. Overwrite the original buffer with - // the corrected sequence, and returns the error bit position - msg[byte1] = aux[byte1]; - msg[byte2] = aux[byte2]; - - // 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)); - - aux[byte2] ^= bitmask2; // Flip i-th bit back - } - - aux[byte1] ^= bitmask1; // Flip j-th bit back - } - } - return (-1); -} -*/ -// -//========================================================================= -// -// Code for introducing a less CPU-intensive method of correcting -// single bit errors. -// -// Makes use of the fact that the crc checksum is linear with respect to -// the bitwise xor operation, i.e. -// crc(m^e) = (crc(m)^crc(e) -// where m and e are the message resp. error bit vectors. -// -// Call crc(e) the syndrome. -// -// The code below works by precomputing a table of (crc(e), e) for all -// possible error vectors e (here only single bit and double bit errors), -// search for the syndrome in the table, and correct the then known error. -// The error vector e is represented by one or two bit positions that are -// changed. If a second bit position is not used, it is -1. -// -// Run-time is binary search in a sorted table, plus some constant overhead, -// instead of running through all possible bit positions (resp. pairs of -// bit positions). -// -struct errorinfo { - uint32_t syndrome; // CRC syndrome - int bits; // Number of bit positions to fix - int pos[MODES_MAX_BITERRORS]; // Bit positions corrected by this syndrome -}; - -#define NERRORINFO \ - (MODES_LONG_MSG_BITS+MODES_LONG_MSG_BITS*(MODES_LONG_MSG_BITS-1)/2) -struct errorinfo bitErrorTable[NERRORINFO]; - -// Compare function as needed for stdlib's qsort and bsearch functions -int cmpErrorInfo(const void *p0, const void *p1) { - struct errorinfo *e0 = (struct errorinfo*)p0; - struct errorinfo *e1 = (struct errorinfo*)p1; - if (e0->syndrome == e1->syndrome) { - return 0; - } else if (e0->syndrome < e1->syndrome) { - return -1; - } else { - return 1; - } -} -// -//========================================================================= -// -// Compute the table of all syndromes for 1-bit and 2-bit error vectors -void modesInitErrorInfo() { - unsigned char msg[MODES_LONG_MSG_BYTES]; - int i, j, n; - uint32_t crc; - n = 0; - memset(bitErrorTable, 0, sizeof(bitErrorTable)); - memset(msg, 0, MODES_LONG_MSG_BYTES); - // Add all possible single and double bit errors - // don't include errors in first 5 bits (DF type) - for (i = 5; i < MODES_LONG_MSG_BITS; i++) { - int bytepos0 = (i >> 3); - int mask0 = 1 << (7 - (i & 7)); - msg[bytepos0] ^= mask0; // create error0 - crc = modesChecksum(msg, MODES_LONG_MSG_BITS); - bitErrorTable[n].syndrome = crc; // single bit error case - bitErrorTable[n].bits = 1; - bitErrorTable[n].pos[0] = i; - bitErrorTable[n].pos[1] = -1; - n += 1; - - if (Modes.nfix_crc > 1) { - for (j = i+1; j < MODES_LONG_MSG_BITS; j++) { - int bytepos1 = (j >> 3); - int mask1 = 1 << (7 - (j & 7)); - msg[bytepos1] ^= mask1; // create error1 - crc = modesChecksum(msg, MODES_LONG_MSG_BITS); - if (n >= NERRORINFO) { - //fprintf(stderr, "Internal error, too many entries, fix NERRORINFO\n"); - break; - } - bitErrorTable[n].syndrome = crc; // two bit error case - bitErrorTable[n].bits = 2; - bitErrorTable[n].pos[0] = i; - bitErrorTable[n].pos[1] = j; - n += 1; - msg[bytepos1] ^= mask1; // revert error1 - } - } - msg[bytepos0] ^= mask0; // revert error0 - } - qsort(bitErrorTable, NERRORINFO, sizeof(struct errorinfo), cmpErrorInfo); - - // Test code: report if any syndrome appears at least twice. In this - // case the correction cannot be done without ambiguity. - // Tried it, does not happen for 1- and 2-bit errors. - /* - for (i = 1; i < NERRORINFO; i++) { - if (bitErrorTable[i-1].syndrome == bitErrorTable[i].syndrome) { - fprintf(stderr, "modesInitErrorInfo: Collision for syndrome %06x\n", - (int)bitErrorTable[i].syndrome); - } - } - - for (i = 0; i < NERRORINFO; i++) { - printf("syndrome %06x bit0 %3d bit1 %3d\n", - bitErrorTable[i].syndrome, - bitErrorTable[i].pos0, bitErrorTable[i].pos1); - } - */ -} -// -//========================================================================= -// -// Search for syndrome in table and if an entry is found, flip the necessary -// bits. Make sure the indices fit into the array -// Additional parameter: fix only less than maxcorrected bits, and record -// fixed bit positions in corrected[]. This array can be NULL, otherwise -// must be of length at least maxcorrected. -// Return number of fixed bits. -// -int fixBitErrors(unsigned char *msg, int bits, int maxfix, char *fixedbits) { - struct errorinfo *pei; - struct errorinfo ei; - int bitpos, offset, res, i; - memset(&ei, 0, sizeof(struct errorinfo)); - ei.syndrome = modesChecksum(msg, bits); - pei = bsearch(&ei, bitErrorTable, NERRORINFO, - sizeof(struct errorinfo), cmpErrorInfo); - if (pei == NULL) { - return 0; // No syndrome found - } - - // Check if the syndrome fixes more bits than we allow - if (maxfix < pei->bits) { - return 0; - } - - // Check that all bit positions lie inside the message length - offset = MODES_LONG_MSG_BITS-bits; - for (i = 0; i < pei->bits; i++) { - bitpos = pei->pos[i] - offset; - if ((bitpos < 0) || (bitpos >= bits)) { - return 0; - } - } - - // Fix the bits - for (i = res = 0; i < pei->bits; i++) { - bitpos = pei->pos[i] - offset; - msg[bitpos >> 3] ^= (1 << (7 - (bitpos & 7))); - if (fixedbits) { - fixedbits[res++] = bitpos; - } - } - return res; -} -// // ============================== Debugging ================================= // // Helper function for dumpMagnitudeVector().