漢明碼 (39,32)介紹

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

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

數(shù)據(jù)位(k):32 位
編碼總長(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)位,主要用于檢測大于1bit的錯誤,屬于漢明碼的拓展選項(xiàng),p7是所有位異或得到,如果只需要檢測1bit的錯誤,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ù)沒有出錯的情況下,以下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

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

  1. 如果只有一個bit發(fā)生了跳變,我們可以通過以下公式找到出錯位置的索引號,并將里面的bit位翻轉(zhuǎn)即可糾正該bit位的錯誤:
    索引 = (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)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內(nèi)容