[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