漢明碼 (39,32)介紹

漢明碼 (39,32)是一個(gè)用于錯(cuò)誤檢測(cè)和糾正的編碼算法,特別適合于嵌入式領(lǐng)域的32bit CPU,數(shù)據(jù)位寬正好與總線位寬一致。

1. 基本結(jié)構(gòu)

數(shù)據(jù)位(k):32 位
編碼總長(zhǎng)(n):39 位
校驗(yàn)位(r):n - k = 7 位

數(shù)據(jù)位與校驗(yàn)位的排列規(guī)則:
1. 數(shù)據(jù)位和校驗(yàn)位一起組成 39 位編碼。
2. 索引為2的冪次方(1, 2, 4, 8, 16, 32)的位為各分組的奇偶校驗(yàn)位(p1,p2,p3,p4,p5,p6),39位為總的奇偶校驗(yàn)位(p7),其余位置為數(shù)據(jù)位(d0-d31),本文以偶校驗(yàn)為例。

2. 編碼過程

2.1 基本布局
索引: 1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39
排布: p1  p2  d0  p3  d1  d2  d3  p4  d4  d5  d6  d7  d8  d9  d10 p5  d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 p26 d26 d27 d28 d29 d30 d31 p7
2.2 校驗(yàn)碼計(jì)算

p1 校驗(yàn)的位是索引中二進(jìn)制bit0位為1的位置,全部列舉如下:
0b000001(1)->p1
0b000011(3)->d0
0b000101(5)->d1
0b000111(7)->d3
0b001001(9)->d4
0b001011(11)->d6
0b001101(13)->d8
0b001111(15)->d10
0b010001(17)->d11
0b010011(19)->d13
0b010101(21)->d15
0b010111(23)->d17
0b011001(25)->d19
0b011011(27)->d21
0b011101(29)->d23
0b011111(31)->d25
0b100001(33)->d26
0b100011(35)->d28
0b100101(37)->d30
0b100111(39)->p7
由此可得,p1 = d0 ^ d1 ^ d3 ^ d4 ^ d6 ^ d8 ^ d10 ^ d11 ^ d13 ^ d15 ^ d17 ^ d19 ^ d21 ^ d23 ^ d25 ^ d26 ^ d28 ^ d30

p2 校驗(yàn)的位是索引中二進(jìn)制bit1位為1的位置,全部列舉如下:
0b000001(2)->p2
0b000011(3)->d0
0b000110(6)->d2
0b000111(7)->d3
0b001010(10)->d5
0b001011(11)->d6
0b001110(14)->d9
0b001111(15)->d10
0b010010(18)->d12
0b010011(19)->d13
0b010110(22)->d16
0b010111(23)->d17
0b011010(26)->d20
0b011011(27)->d21
0b011110(30)->d24
0b011111(31)->d25
0b100010(34)->d27
0b100011(35)->d28
0b100110(38)->d31
0b100111(39)->p7

由此可得,p2 = d0 ^ d2 ^ d3 ^ d5 ^ d6 ^ d9 ^ d10 ^ d12 ^ d13 ^ d16 ^ d17 ^ d20 ^ d21 ^ d24 ^ d25 ^ d27 ^ d28 ^ d31

以此類推,
p3 校驗(yàn)的位是索引中二進(jìn)制bit2位為1的位置;
p4 校驗(yàn)的位是索引中二進(jìn)制bit3位為1的位置;
p5 校驗(yàn)的位是索引中二進(jìn)制bit4位為1的位置;
p6 校驗(yàn)的位是索引中二進(jìn)制bit5位為1的位置;
p7是可選校驗(yàn)位,主要用于檢測(cè)大于1bit的錯(cuò)誤,屬于漢明碼的拓展選項(xiàng),p7是所有位異或得到,如果只需要檢測(cè)1bit的錯(cuò)誤,p7位可以不用;

整理如下:

p1 = d0 ^ d1 ^ d3 ^ d4 ^ d6 ^ d8 ^ d10 ^ d11 ^ d13 ^ d15 ^ d17 ^ d19 ^ d21 ^ d23 ^ d25 ^ d26 ^ d28 ^ d30
p2 = d0 ^ d2 ^ d3 ^ d5 ^ d6 ^ d9 ^ d10 ^ d12 ^ d13 ^ d16 ^ d17 ^ d20 ^ d21 ^ d24 ^ d25 ^ d27 ^ d28 ^ d31
p3 = d1 ^ d2 ^ d3 ^ d7 ^ d8 ^ d9 ^ d10 ^ d14 ^ d15 ^ d16 ^ d17 ^ d22 ^ d23 ^ d24 ^ d25 ^ d29 ^ d30 ^ d31
p4 = d4 ^ d5 ^ d6 ^ d7 ^ d8 ^ d9 ^ d10 ^ d18 ^ d19 ^ d20 ^ d21 ^ d22 ^ d23 ^ d24 ^ d25
p5 = d11 ^ d12 ^ d13 ^ d14 ^ d15 ^ d16 ^ d17 ^ d18 ^ d19 ^ d20 ^ d21 ^ d22 ^ d23 ^ d24 ^ d25
p6 = d26 ^ d27 ^ d28 ^ d29 ^ d30 ^ d31
p7 = p1 ^ p2 ^ p3 ^ p4 ^ p5 ^ p6 ^ d0 ^ d1 ^ d2 ^ d3 ^ d4 ^ d5 ^ d6 ^ d7 ^ d8 ^ d9 ^ d10 ^ d11 ^ d12 ^ d13 ^ d14 ^ d15 ^ d16 ^ d17 ^ d18 ^ d19 ^ d20 ^ d21 ^ d22 ^ d23 ^ d24 ^ d25 ^ d26 ^ d27 ^ d28 ^ d29 ^ d30 ^ d31

由此可得,漢明碼 (39,32)編碼后的7位校驗(yàn)碼p1-p7和32bit原始數(shù)據(jù)d0-d31。

3. 解碼過程

解碼過程需要用到編碼生成的7位校驗(yàn)碼和32bit原始數(shù)據(jù)組成的39bit的數(shù)據(jù),由于p1-p6都是各組數(shù)據(jù)異或而得的,故理論上在數(shù)據(jù)沒有出錯(cuò)的情況下,以下p1' p2' p3' p4' p5' p6' p7' (可選)的值應(yīng)該都等于0 :

p1' = p1  ^ d0 ^ d1 ^ d3 ^ d4 ^ d6 ^ d8 ^ d10 ^ d11 ^ d13 ^ d15 ^ d17 ^ d19 ^ d21 ^ d23 ^ d25 ^ d26 ^ d28 ^ d30 
p2' = p2 ^ d0 ^ d2 ^ d3 ^ d5 ^ d6 ^ d9 ^ d10 ^ d12 ^ d13 ^ d16 ^ d17 ^ d20 ^ d21 ^ d24 ^ d25 ^ d27 ^ d28 ^ d31
p3' = p3 ^ d1 ^ d2 ^ d3 ^ d7 ^ d8 ^ d9 ^ d10 ^ d14 ^ d15 ^ d16 ^ d17 ^ d22 ^ d23 ^ d24 ^ d25 ^ d29 ^ d30 ^ d31
p4' = p4 ^ d4 ^ d5 ^ d6 ^ d7 ^ d8 ^ d9 ^ d10 ^ d18 ^ d19 ^ d20 ^ d21 ^ d22 ^ d23 ^ d24 ^ d25
p5' = p5 ^ d11 ^ d12 ^ d13 ^ d14 ^ d15 ^ d16 ^ d17 ^ d18 ^ d19 ^ d20 ^ d21 ^ d22 ^ d23 ^ d24 ^ d25
p6' = p6 ^  d26 ^ d27 ^ d28 ^ d29 ^ d30 ^ d31
p7' = p7 ^ p1 ^ p2 ^ p3 ^ p4 ^ p5 ^ p6 ^ d0 ^ d1 ^ d2 ^ d3 ^ d4 ^ d5 ^ d6 ^ d7 ^ d8 ^ d9 ^ d10 ^ d11 ^ d12 ^ d13 ^ d14 ^ d15 ^ d16 ^ d17 ^ d18 ^ d19 ^ d20 ^ d21 ^ d22 ^ d23 ^ d24 ^ d25 ^ d26 ^ d27 ^ d28 ^ d29 ^ d30 ^ d31

如果有一個(gè)不等于0,說明必然發(fā)生了bit跳變,跳變位可能是校驗(yàn)位也可能是數(shù)據(jù)位。

  1. 如果只有一個(gè)bit發(fā)生了跳變,我們可以通過以下公式找到出錯(cuò)位置的索引號(hào),并將里面的bit位翻轉(zhuǎn)即可糾正該bit位的錯(cuò)誤:
    索引 = (p6'<<5) | (p5'<<4) | (p4'<<3) | (p3'<<2) | (p2'<<1) | p1'
    比如:算出來索引為3,我們根據(jù)前面的基本布局,知道索引為3的位置存的是d0的值,故只要把d0位翻轉(zhuǎn)即可;
  2. 如果存在大于1bit的位置發(fā)生跳變,則需要用到p7'和上面計(jì)算的索引共同來判斷。

4. 算法實(shí)現(xiàn)

def hamming_39_32_encode(data):
    # get data bits
    d = [(data >> i) & 1 for i in range(32)]

    # calculate parity
    p1 = d[0] ^ d[1] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[10] ^ d[11] ^ d[13] ^ d[15] ^ d[17] ^ d[19] ^ d[21] ^ d[23] ^ d[25] ^ d[26] ^ d[28] ^ d[30]
    p2 = d[0] ^ d[2] ^ d[3] ^ d[5] ^ d[6] ^ d[9] ^ d[10] ^ d[12] ^ d[13] ^ d[16] ^ d[17] ^ d[20] ^ d[21] ^ d[24] ^ d[25] ^ d[27] ^ d[28] ^ d[31]
    p3 = d[1] ^ d[2] ^ d[3] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[14] ^ d[15] ^ d[16] ^ d[17] ^ d[22] ^ d[23] ^ d[24] ^ d[25] ^ d[29] ^ d[30] ^ d[31]
    p4 = d[4] ^ d[5] ^ d[6] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[18] ^ d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25]
    p5 = d[11] ^ d[12] ^ d[13] ^ d[14] ^ d[15] ^ d[16] ^ d[17] ^ d[18] ^ d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25]
    p6 = d[26] ^ d[27] ^ d[28] ^ d[29] ^ d[30] ^ d[31]
    p7 = p1 ^ p2 ^ p3 ^ p4 ^ p5 ^ p6 ^ d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[11] ^ d[12] ^ d[13] ^ d[14] ^ d[15] ^ d[16] ^ d[17] ^ d[18] ^ d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25] ^ d[26] ^ d[27] ^ d[28] ^ d[29] ^ d[30] ^ d[31]

    parity = (p7<<6) | (p6<<5) | (p5<<4) | (p4<<3) | (p3<<2) | (p2<<1) | p1

    return parity

def hamming_39_32_decode(parity, data):
    # get data bits
    d = [(data >> i) & 1 for i in range(32)]
    # get parity bits
    p = [(parity >> i) & 1 for i in range(7)]

    # calculate syndrome
    p1 = p[0] ^ d[0] ^ d[1] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[10] ^ d[11] ^ d[13] ^ d[15] ^ d[17] ^ d[19] ^ d[21] ^ d[23] ^ d[25] ^ d[26] ^ d[28] ^ d[30]
    p2 = p[1] ^ d[0] ^ d[2] ^ d[3] ^ d[5] ^ d[6] ^ d[9] ^ d[10] ^ d[12] ^ d[13] ^ d[16] ^ d[17] ^ d[20] ^ d[21] ^ d[24] ^ d[25] ^ d[27] ^ d[28] ^ d[31]
    p3 = p[2] ^ d[1] ^ d[2] ^ d[3] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[14] ^ d[15] ^ d[16] ^ d[17] ^ d[22] ^ d[23] ^ d[24] ^ d[25] ^ d[29] ^ d[30] ^ d[31]
    p4 = p[3] ^ d[4] ^ d[5] ^ d[6] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[18] ^ d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25]
    p5 = p[4] ^ d[11] ^ d[12] ^ d[13] ^ d[14] ^ d[15] ^ d[16] ^ d[17] ^ d[18] ^ d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25]
    p6 = p[5] ^ d[26] ^ d[27] ^ d[28] ^ d[29] ^ d[30] ^ d[31]
    p7 = p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4] ^ p[5] ^ p[6] ^ d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6] ^ d[7] ^ d[8] ^ d[9] ^ d[10] ^ d[11] ^ d[12] ^ d[13] ^ d[14] ^ d[15] ^ d[16] ^ d[17] ^ d[18] ^ d[19] ^ d[20] ^ d[21] ^ d[22] ^ d[23] ^ d[24] ^ d[25] ^ d[26] ^ d[27] ^ d[28] ^ d[29] ^ d[30] ^ d[31]
    
    syndrome = (p6<<5) | (p5<<4) | (p4<<3) | (p3<<2) | (p2<<1) | p1
    
    if syndrome == 0 and p7 == 0 :
        print("hamming decode success")
        return data
    else:
        if syndrome !=0 and p7 != 0:
            print(f"1 bit error at positon {syndrome}")
            # correct 1bit error
            index = 0
            decode = data
            for i in range(39):
                if (i & (i + 1)) == 0:
                    continue
                if i == 38:
                    continue
                if (i == syndrome-1):
                    decode  &= (~(1 << index))
                    decode |= ((d[index] ^ 1) << index) #flip
                index += 1
            print("correct success decode origin data is 0x%x" %decode)
            return decode
        else:
            print("more than 1 bit error")
            return -1

##test code
data = 0x0ff0000e
parity = hamming_39_32_encode(data)
print(f"parity:{parity:07b}")

decode = hamming_39_32_decode(parity, 0x0ff0000e)
print("decode:%x"%decode)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 Google Play應(yīng)用市場(chǎng)對(duì)于應(yīng)用的targetSdkVersion有了更為嚴(yán)格的要求。從 2018 年...
    申國(guó)駿閱讀 65,800評(píng)論 15 98
  • """1.個(gè)性化消息: 將用戶的姓名存到一個(gè)變量中,并向該用戶顯示一條消息。顯示的消息應(yīng)非常簡(jiǎn)單,如“Hello ...
    她即我命閱讀 5,023評(píng)論 0 6
  • 我們都是軟弱的人,所以才會(huì)說謊。我們都是膽小的人,所以才要武裝。我們都是一群笨蛋,所以才會(huì)互相傷害。
    所羅門的偽證_dc0a閱讀 3,567評(píng)論 1 3
  • 為了讓我有一個(gè)更快速、更精彩、更輝煌的成長(zhǎng),我將開始這段刻骨銘心的自我蛻變之旅!從今天開始,我將每天堅(jiān)持閱...
    李薇帆閱讀 2,244評(píng)論 1 4
  • 似乎最近一直都在路上,每次出來走的時(shí)候感受都會(huì)很不一樣。 1、感恩一直遇到好心人,很幸運(yùn)。在路上總是...
    時(shí)間里的花Lily閱讀 1,739評(píng)論 1 3

友情鏈接更多精彩內(nèi)容