[hamradio-commits] [dump1090] 167/389: Added code for table based correction of bit errors. Code is not called yet except initialisation.

Matthew Ernisse mernisse-guest at moszumanska.debian.org
Wed Nov 5 00:19:51 UTC 2014


This is an automated email from the git hooks/post-receive script.

mernisse-guest pushed a commit to branch master
in repository dump1090.

commit 0a4fc6e98f23feecadd24cfac4a09a58ee0a7e2d
Author: Ulrich Kuehn <ukuehn at acm.org>
Date:   Sun May 12 17:33:44 2013 +0200

    Added code for table based correction of bit errors. Code is not called yet except initialisation.
---
 dump1090.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 183 insertions(+)

diff --git a/dump1090.c b/dump1090.c
index 80226fd..b3ff2a7 100644
--- a/dump1090.c
+++ b/dump1090.c
@@ -329,6 +329,7 @@ void modesSendSBSOutput(struct modesMessage *mm);
 void useModesMessage(struct modesMessage *mm);
 int fixSingleBitErrors(unsigned char *msg, int bits);
 int fixTwoBitsErrors(unsigned char *msg, int bits);
+void modesInitErrorInfo();
 int modesMessageLenByType(int type);
 
 /* ============================= Utility functions ========================== */
@@ -461,6 +462,9 @@ void modesInit(void) {
             Modes.maglut[(i*256)+q] = (uint16_t) ((mag < 65535) ? mag : 65535);
         }
     }
+
+    /* Prepare error correction tables */
+    modesInitErrorInfo();
 }
 
 /* =============================== RTLSDR handling ========================== */
@@ -1207,6 +1211,185 @@ int fixTwoBitsErrors(unsigned char *msg, int bits) {
     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 pos0;           /* bit position of first error */
+        int pos1;           /* bit position of second error, or -1 */
+};
+
+#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));
+        /* First, insert infos about all possible single bit errors */
+        for (i = 0;  i < MODES_LONG_MSG_BITS;  i++) {
+                int bytepos = (i >> 3);
+                int mask = 1 << (7 - (i & 7));
+                memset(msg, 0, MODES_LONG_MSG_BYTES);
+                msg[bytepos] ^= mask;
+                crc = modesChecksum(msg, MODES_LONG_MSG_BITS);
+                bitErrorTable[n].syndrome = crc;
+                bitErrorTable[n].pos0 = i;
+                bitErrorTable[n].pos1 = -1;
+                n += 1;
+        }
+        /* Add also all double bit errors */
+        for (i = 0;  i < MODES_LONG_MSG_BITS;  i++) {
+                int bytepos0 = (i >> 3);
+                int mask0 = 1 << (7 - (i & 7));
+                memset(msg, 0, MODES_LONG_MSG_BYTES);
+                msg[bytepos0] ^= mask0;
+                for (j = i+1;  j < MODES_LONG_MSG_BITS;  j++) {
+                        int bytepos1 = (j >> 3);
+                        int mask1 = 1 << (7 - (j & 7));
+                        msg[bytepos1] ^= mask1;
+                        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;
+                        bitErrorTable[n].pos0 = i;
+                        bitErrorTable[n].pos1 = j;
+                        n += 1;
+                }
+        }
+        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);
+        }
+        */
+}
+
+/* Flip a bit, but make sure that the DF field (first 5 bits)
+ * is never changed
+ */
+int flipBit(unsigned char *msg, int nbits, int bit) {
+        int bytepos, mask;
+        if ((bit < 0) || (bit >= nbits)) {
+                return 0;
+        }
+        if (bit < 5) {
+                return 0;
+        }
+        bytepos = (bit >> 3);
+        mask = 1 << (7 - (bit & 7));
+        msg[bytepos] ^= mask;
+        return 1;
+}
+
+/* Search syndrome in table and, if an entry is found, flip the necessary
+ * bits. Make sure the indices fit into the array, and for 2-bit errors,
+ * are different.
+ * Return number of fixed bits.
+ */
+int fixBitErrors(unsigned char *msg, int bits) {
+        struct errorinfo *pei;
+        struct errorinfo ei;
+        int bitpos0, bitpos1, offset, res;
+        ei.syndrome = modesChecksum(msg, bits);
+        ei.pos0 = -1;
+        ei.pos1 = -1;
+        pei = bsearch(&ei, bitErrorTable, NERRORINFO,
+                     sizeof(struct errorinfo), cmpErrorInfo);
+        if (pei == NULL) {
+                /* Nothing found */
+                return 0;
+        }
+        offset = MODES_LONG_MSG_BITS-bits;
+        bitpos0 = pei->pos0;
+        bitpos1 = pei->pos1;
+        res = 0;
+        if (bitpos1 >= 0) { /* two-bit error pattern */
+                bitpos0 -= offset;
+                bitpos1 -= offset;
+                if ((bitpos0 < 0) || (bitpos0 >= bits) ||
+                    (bitpos1 < 0) || (bitpos1 >= bits)) {
+                        return res;
+                }
+                res +=flipBit(msg, bits, bitpos0);
+                if (bitpos0 != bitpos1) {
+                        res += flipBit(msg, bits, bitpos1);
+                        return res;
+                }
+                return res;
+        } else {
+                bitpos0 -= offset;
+                if ((bitpos0 < 0) || (bitpos0 >= bits)) {
+                        return res;
+                }
+                res += flipBit(msg, bits, bitpos0);
+                return res;
+        }
+}
+
+
+
 /* Hash the ICAO address to index our cache of MODES_ICAO_CACHE_LEN
  * elements, that is assumed to be a power of two. */
 uint32_t ICAOCacheHashAddress(uint32_t a) {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/dump1090.git



More information about the pkg-hamradio-commits mailing list