]> git.sesse.net Git - hamming/blobdiff - hamming.c
Add an implementation of the (72,64) Hamming codes.
[hamming] / hamming.c
index 03714582b4ac5018e95551d86798f4d8dbf6fc50..33376f31993bd4b1ed25cd45355984b7ed1bcb4f 100644 (file)
--- a/hamming.c
+++ b/hamming.c
@@ -2,6 +2,7 @@
 
 #define DATA_BITS    11
 #define PARITY_BITS  5
+#define EXTRA_BIT_POSITION (PARITY_BITS - 1)
 #define CODE_BITS    (DATA_BITS + PARITY_BITS)
 #define NUM_DATA_WORDS (1 << DATA_BITS)
 
@@ -9,7 +10,8 @@ unsigned char hamming_lookup[NUM_DATA_WORDS];
 
 /* 
  * Needed since we store all the parity at the end of the word, not at the expected
- * power-of-two bit positions.
+ * power-of-two bit positions. This is the inverse of the mapping
+ * (0..15) -> (0, 8, 4, 2, 1, the rest in ascending order)
  */
 unsigned char permutation_table[CODE_BITS] = {
        0, 4, 3, 5, 2, 6, 7, 8, 1, 9, 10, 11, 12, 13, 14, 15
@@ -21,20 +23,20 @@ unsigned generate_parity(unsigned data)
        unsigned parity[PARITY_BITS];
        unsigned i;
 
-       parity[4] = 0;
+       parity[EXTRA_BIT_POSITION] = 0;
        
        for (i = 0; i < DATA_BITS; ++i) {
                bits[i] = (data & (1 << i)) ? 1 : 0;
-               parity[4] ^= bits[i];
+               parity[EXTRA_BIT_POSITION] ^= bits[i];
        }
 
        parity[0] = bits[0] ^ bits[1] ^ bits[3] ^ bits[4] ^ bits[6] ^ bits[8] ^ bits[10];
        parity[1] = bits[0] ^ bits[2] ^ bits[3] ^ bits[5] ^ bits[6] ^ bits[9] ^ bits[10];
        parity[2] = bits[1] ^ bits[2] ^ bits[3] ^ bits[7] ^ bits[8] ^ bits[9] ^ bits[10];
        parity[3] = bits[4] ^ bits[5] ^ bits[6] ^ bits[7] ^ bits[8] ^ bits[9] ^ bits[10];
-       parity[4] ^= parity[0] ^ parity[1] ^ parity[2] ^ parity[3];
+       parity[EXTRA_BIT_POSITION] ^= parity[0] ^ parity[1] ^ parity[2] ^ parity[3];
 
-       return parity[4] | (parity[3] << 1) | (parity[2] << 2) | (parity[1] << 3) | (parity[0] << 4);
+       return parity[EXTRA_BIT_POSITION] | (parity[3] << 1) | (parity[2] << 2) | (parity[1] << 3) | (parity[0] << 4);
 }
 
 unsigned make_codeword(unsigned data)
@@ -102,13 +104,13 @@ unsigned correct_single_bit_error(unsigned code)
        unsigned parity[PARITY_BITS];
        unsigned i, bp = 0;
 
-       parity[4] = 0;
+       parity[EXTRA_BIT_POSITION] = 0;
 
        for (i = 0; i < CODE_BITS; ++i) {
                bits[i] = (code & (1 << i)) ? 1 : 0;
        }
        for (i = 1; i < CODE_BITS; ++i) {
-               parity[4] ^= bits[i];
+               parity[EXTRA_BIT_POSITION] ^= bits[i];
        }
 
        parity[0] = bits[PARITY_BITS+0] ^ bits[PARITY_BITS+1] ^ bits[PARITY_BITS+3] ^ bits[PARITY_BITS+4] ^ bits[PARITY_BITS+6] ^ bits[PARITY_BITS+8] ^ bits[PARITY_BITS+10];
@@ -125,11 +127,11 @@ unsigned correct_single_bit_error(unsigned code)
        if (bp != 0) {
                /* flip the wrong bit */
                code ^= (1 << permutation_table[bp]);
-               parity[4] ^= 1;
+               parity[EXTRA_BIT_POSITION] ^= 1;
        }
 
        /* recompute the lower parity */
-       return (code & ~1) | parity[4];
+       return (code & ~1) | parity[EXTRA_BIT_POSITION];
 }
 
 void check_zero_bit_detection()