Trong viễn thông, mã Hamming là một mã sửa lỗi tuyến tắnh (linear error-correcting code), ựược ựặt theo tên của người sáng tạo ra nó, ông Richard Hamming. Mã Hamming có thể phát hiện một bit hoặc hai bit bị lỗi. Mã Hamming còn có thể sửa các lỗi do một bit bị sai gây ra. Mã Hamming
ựược công bố vào năm 1950, mã này có ựặc ựiểm là sơ ựồ tạo mã và giải mã
ựơn giản, giả sử số bit kiểm tra r và số bit mang thông tin k thì k phải thoả
mãn hệ thức k ≤ 2r - 1 - r, khi số bit mang tin tăng thì số bit kiểm tra cũng tăng, tuy nhiên tốc ựộ tăng của số bit mang tin nhanh hơn nhiều so với tốc ựộ
tăng của số bit kiểm tra nên khi số bit mang tin lớn thì tắnh kinh tế càng cao, vì những ưu ựiểm này nên hiện nay mã Hamming ựược sử dụng khá rộng rãi.
Thực ra trước khi mã Hamming ra ựời ựã có nhiều mã phát hiện lỗi ựơn giản ựược sử dụng, tuy nhiên không mã nào có hiệu quả bằng mã Hamming với một chi phắ tương ựương. Chẳng hạn mã chẵn lẻ (thêm một bit cho biết số
lượng bit có giá trị 1 của ựoạn dữ liệu nằm trước là số chẵn hay số lẻ, tuy nhiên mã này không biết ựược bit nào là bit bị lỗi khi phát hiện có lỗi xảy ra); mã hai trong năm (two out of five code) (ựảm bảo mỗi một khối 5 bit có chắnh xác 2 bit có giá trị bằng 1, mã này cũng không xác ựịnh ựược vị trắ gây lỗi)Ầ
Hình 4.1. Sự liên quan giữa các bit dữ liệu với các bit chẵn lẻ
Mô hình này mô tả một mã 7 bit, bao gồm 4 bit dữ liệu (3, 5, 6, 7) và bit chẵn lẻ (1,2,4). Sự liên quan của các bit dữ liệu với bit chẵn lẻựược biểu hiện bằng các phần của hình tròn gối lên nhau. Bit thứ 1 kiểm tra bit thứ (3, 5, 7), trong khi bit 2 kiểm tra bit (3, 6, 7). Lưu ý, các vị trị (1,2,4Ầ) thực ra là vị trắ 20, 21, 22Ầ
Hình 4.2. Các bit dữ liệu và các bit kiểm tra
Các bit dữ liệu và bit chẵn lẻ trong mối quan hệ chồng gối với nhau. Các bit chẵn lẻựược tắnh dùng quy luật Ộsố chẵnỢ (nếu số lượng bit có giá trị bằng 1 là một số lẻ, thì bit chẵn lẻ bằng 1, và do ựó cộng thêm một bit có giá trị 1 này vào dữ liệu, tổng số bit 1 sẽ là một số chẵn - bao gồm cả bit chẵn lẻ, còn không thì bit chẵn lẻ có giá trị 0). Giá trị của nhóm dữ liệu là 1100110 - các bit chẵn lẻựược in ựậm và ựọc từ phải sang trái. Càng nhiều bit sửa lỗi thêm vào trong thông ựiệp, và các bit ấy ựược bố trắ theo một cách là mỗi bỗ trắ của nhóm các bit bị lỗi tạo nên một hình thái lỗi riêng biệt, thì chúng ta có thể xác
ựịnh ựược những bit bị sai. Trong một thông ựiệp dài 7 bit, chúng ta có 7 khả
có thể không những chỉ xác ựịnh ựược là lỗi trong truyền thông có xảy ra hay không mà còn có thể xác ựịnh ựược bit nào là bit bị lỗi.
Thuật toán tạo mã Hamming
Bước 1: Tất cả các bit ở vị trị là luỹ thừa của 2 ựược dùng làm bit kiểm tra (các vị trắ như 1, 2, 4, 8, 16, 32, 64,Ầ hay nói cách khác 20, 21, 22, 23, 24, 25, 26,Ầ )
Bước 2: Tất cả các vị trắ bit khác ựược dùng cho dữ liệu sẽựược mã hóa. (các vị trắ 3, 5, 6, 7, 9, 10Ầ).
Bước 3: Mỗi bit kiểm tra tắnh giá trị chẵn lẻ cho một số bit từ mã. Vị trắ của bit kiểm tra quyết ựịnh chuỗi các bit mà nó luân phiên kiểm tra và bỏ qua: Vị trắ 1 (n=1): bỏ qua 0 bit (n-1), kiểm tra 1 bit (n), bỏ qua 1 bit (n), kiểm tra 1 bit (n)Ầ
Vị trắ 2 (n=2): bỏ qua 1 bit (n-1), kiểm tra 2 bit (n), bỏ qua 2 bit (n), kiểm tra 2 bit (n)Ầ
Vị trắ 4 (n=4): bỏ qua 3 bit (n-1), kiểm tra 4 bit (n), bỏ qua 4 bit (n), kiểm tra 4 bit (n)Ầ
Và cứ tiếp tục như trên.
Nói cách khác, bit kiểm tra tại vị trắ 2k kiểm tra các bit ở các vị trắ bit k có giá trị bằng 1. Ngược lại, vắ dụ bit 13 chẳng hạn 11012 ựược kiểm bởi các bit 10002 = 8, 01002 = 4 và 00012 =1.
Vắ dụ:
Chẳng hạn, chúng ta có một từ dữ liệu dài 7 bit với các giá trị là Ộ0110101Ợ, và chúng ta muốn sử dụng mã Hamming ựể kiểm soát lỗi, khi ựó ta cần dùng ựến 4 bit ựể kiểm tra, do ựó ựộ dài của mã sau khi ựã thêm bit kiểm tra là 11 (vì vậy, ta còn gọi là (11,7)).
Việc thành lập mã ựược thể hiện ở bảng dưới ựây, chữ d (data) ựược dùng ựể biểu diễn dữ liệu, chữ p (parity) ựể biểu thị các bit chẵn lẻựược dùng
ựể kiểm tra. đầu tiên, các bit của dữ liệu ựược ựặt vào vị trắ thắch hợp của chúng, sau ựó các bit chẵn lẻựược tắnh toán dùng quy luật số chẵn.
Thứ tự bit 1 2 3 4 5 6 7 8 9 10 11 Vị trắ bit chẵn lẻ và các bit dữ liệu p1 p2 d1 p3 d2 d3 d4 p4 d5 d6 d7 Nhóm dữ liệu (không có bit chẵn lẻ): 0 1 1 0 1 0 1 p1 1 0 1 0 1 1 p2 0 0 1 0 0 1 p3 0 1 1 0 p4 0 1 0 1 Nhóm dữ liệu (với bit chẵn lẻ): 1 0 0 0 1 1 0 0 1 0 1
Bảng 4.1. Cách tắnh các bit chẵn lẻ trong mã Hamming (từ trái sang phải)
Từ mã khi ựã thêm các bit kiểm tra là Ộ10001100101Ợ.
Thuật toán giải mã và kiểm tra của mã Hamming
Giả sử ta nhận ựược một bản tin ựã ựược mã hoá bằng thuật toán mã Hamming và muốn kiểm tra xem bản tin có lỗi hay không.
Bước 1: Dùng quy luật số chẵn tương tự như khi tạo mã ựể kiểm tra, khi
ựó tại các bit kiểm tra, nếu là 0 thì là sai, là 1 là ựúng.
Bước 2: Cộng các vị trắ sai ta sẽựược vị trắ của bit ựã bị sai và tiến hành sửa sai.
Bước 3: Bằng việc bỏ ựi phần mã Hamming, ta lấy ựược phần dữ liệu gốc trước khi mã hoá.
Lưu ý là các bit chẵn lẻ không kiểm tra ựược lẫn nhau, nếu chỉ một bit chẵn lẻ bị sai thôi, trong khi tất cả các bit khác là ựúng, thì chỉ có bit chẵn lẻ
nói ựến là sai mà thôi và không phải là các bit nó kiểm tra.
Bảng 4.2 dưới ựây cho thấy quy luật tạo mã Hamming kiểm tra bản tin Ộ10001100100Ợ bằng cách cho bit chẵn lẻ giá trị 1 khi kết quả kiểm tra dùng quy luật số chẵn bị sai.
Thứ tự bit 1 2 3 4 5 6 7 8 9 10 11 Vị trắ bit chẵn lẻ và các bit dữ liệu p1 p2 d1 p3 d2 d3 D4 p4 d5 d6 d7 Kiểm chẵn lẻ Bit chẵn lẻ Nhóm dữ liệu nhận ựược: 1 0 0 0 1 1 0 0 1 0 0 1 p1 1 0 1 0 1 0 Sai 1 p2 0 0 1 0 0 0 Sai 1 p3 0 1 1 0 đúng 0 p4 0 1 0 0 Sai 1
Bảng 4.2. Kiểm tra các bit chẵn lẻ (bit bịựảo lộn có nền thẫm)
Cuối cùng, theo thuật toán, ta tắnh giá trị các bit chẵn lẻ (bit nằm dưới cùng ựược viết về bên phải - viết ngược từ dưới lên). Giá trị nguyên của các bit chẵn lẻ là 11, như vậy có nghĩa là bit thứ 11 trong bản tin là bit có giá trị
không ựúng và bit này cần ựược ựổi ngược lại. Bảng dưới ựây cho thấy cách tắnh giá trị này:
p4 p3 p2 p1 Nhị phân 1 0 1 1
Thập phân 8 2 1 Σ = 11
Bảng 4.3. Tắnh giá trị các bit kiểm tra
Việc ựổi ngược lại giá trị của bit 11 làm cho bản tin nhận ựược 10001100100 trở lại thành 10001100101. Bằng việc bỏựi phần mã Hamming, chúng ta lấy ựược phần dữ liệu gốc với giá trị là: 0110101
Giả sử, có hai bit bị biến ựổi tại các vị trắ là x và y, nếu x và y có cùng một bit tại vị trắ 2k trong ựại diện của chúng, thì bit chẵn lẻ tương ứng với vị
trắ bit ựấy kiểm tra cả hai bit, và do ựó sẽ giữ nguyên giá trị, không thay ựổi. Song một số bit chẵn lẻ nào ựấy nhất ựịnh phải thay ựổi, vì x ≠ y, và do ựó hai bit tương ứng nào ựó có giá trị x và y khác nhau. Do vậy, mã Hamming phát hiện tất cả các lỗi do hai bit bị thay ựổi - song nó không phân biệt ựược chúng với các lỗi do 1 bit bị thay ựổi.
Hiện thời, khi nói ựến mã Hamming, chúng ta thực ra muốn nói ựến mã (7,4) mà Hamming công bố năm 1950, với mỗi nhóm 4 bit dữ liệu, mã
Hamming thêm 3 bit kiểm tra. Thuật toán (7,4) của Hamming có thể sửa chữa bất cứ một bit lỗi nào, và phát hiện tất cả các lỗi của 1 bit và các lỗi của 2 bit gây ra. điều này có nghĩa là ựối với tất cả các phương tiện truyền thông không có chùm lỗi ựột phá (burst errors) xảy ra, mã (7,4) của Hamming rất hiệu quả (trừ khi phương tiện truyền thông có ựộ nhiễu rất cao thì nó mới có thể gây cho 2 bit trong số 7 bit truyền bịựảo lộn.
Cài ựặt mô phỏng mã Hamming
Trong chương trình này, chúng tôi sử dụng mã Hamming (12,8) - mã hoá mỗi 8 bit (tức một kắ tự) thì thêm 4 bit nữa ựể tạo thành mã 12 bit. Tiếp ựó, tiến hành ghi 12 bit ựó vào trong 2 byte. Như vậy, với phương pháp này, thì cứ mỗi một kắ tự sẽ ựược mã hoá thành 2. để mã hoá thêm mã Hamming thì ta phải trả giá bằng dung lượng, bởi cứ mỗi file ựầu vào thì file kết quả sẽ có kắch thước gấp ựôi. Tất nhiên, phương pháp này chưa phải là tối ưu, nhưng cũng là chấp nhận ựược.
Như vậy sơựồ làm việc của chương trình như sau;
Mã hoá file dữ liệu:
- đọc từng byte của file.
- Tắnh toán các vị trắ ựặt bit chẵn lẻ.
- Tắnh giá trị của các bit chẵn lẻ và ghi vào bộựệm.
- Chuyển các bit từ bộựệm thành kắ tự và ghi ra file kết quả. đoạn chương trình như sau:
// Tắnh toán vị trắ các parity parity[1] = 1;
for (i=2; i<=4; i++)
parity[i] = (parity[i-1]<<1) & 0xfffffffe; //Thực hiện mã hoá
if (strcmp(command,"e")==0) {
//Mở file ựể ựọc và chuẩn bị ghi dữ liệu while ((ch=getc(filein))!=EOF)
{
for(i=1;i<=12;i++) code[i]=0; for (j=7;j>=0;j--)
info[7-j+1]=getbit(ch,j);
for (j=1; j<=4; j++) {
red[j] = 0; l = 0;
for (i=1; i<=12; i++) {
//Kiểm tra bit "i" không phải là luỹ thừa của 2 result = 0;
test = 1;
for (index=1; index<=4; index++) { if (i==test) result = 1; test *= 2; } if (!result) { l++; if ( (i>>(j-1)) & 0x01 ) red[j] ^= info[l]; } } } // Tạo từ mã code[1]=red[1];code[2]=red[2]; code[4]=red[3];code[8]=red[4];
//Thực hiện lưu lại từ mã vào trong file out buff=0; for (i=1;i<=8;i++) buff+=code[i]*pow(2,8-i); fputc(buff,fileout); buff=0; for (i=9;i<=16;i++) buff+=code[i]*pow(2,16-i); fputc(buff,fileout); } }
Trong ựó, hàm int getbit(int x, int k) ựược dùng ựể lấy bit thứ k trong số x.
Giải mã file ựã mã hoá:
Quá trình thực hiện giải mã ựược thực hiện như sau: - đọc mỗi 2 byte trong file mã hoá.
- Chuyển ra một dãy bit.
- Kiểm tra dãy bit xem có lỗi hay không? Nếu có thì tìm vị trắ lỗi và sửa. - Loại bỏ các mã Hamming ra khỏi dãy bit và ghi 8 bit vào file kết quả.
(Ghi chú: File kết quả này có thể giống hệt với file gốc ban ựầu - nếu không có lỗi, hoặc lỗi ựã ựược sửa, và sẽ khác với file gốc ban ựầu - nếu có lỗi nhưng không sửa ựược).
đoạn chương trình như sau:
//Thực hiện giải mã
if (strcmp(command,"d")==0) {
//Mở file ựể ựọc và chuẩn bị ghi dữ liệu
//Thực hiện ựọc file và ghi vào code
while (((ch1=getc(filein))!=EOF)&&((ch2=getc(filein))!=EOF)) { for(i=1;i<=16;i++) code[i]=0; for(j=7;j>=0;j--) code[7-j+1]=getbit(ch1,j); for(j=7;j>=0;j--) code[15-j+1]=getbit(ch2,j); // Kiểm tra xem có lỗi hay không? syn = 0;
for (i=1; i<=12; i++) if (code[i]) syn ^= i; // Sửa lỗi nếu bị sai if (syn) { code[syn] ^= 1; fal=1; }
//Thực hiện ghi lại nội dung vào file out info[1]=code[3]; info[2]=code[5]; info[3]=code[6]; info[4]=code[7]; info[5]=code[9]; info[6]=code[10]; info[7]=code[11]; info[8]=code[12]; buff=0; for (i=1;i<=8;i++) buff+=info[i]*pow(2,8-i); fputc(buff,fileout); }
if (fal==0) printf("Bản tin nhận không có lỗi !"); else printf("Bản tin nhận bị lỗi ! đã sửa !"); }
Khi phát hiện lỗi, mã Hamming chỉ có thể sửa ựược một lỗi, hơn nữa chi phắ dành cho việc kiểm soát và sửa lỗi này khá lớn. Vì vậy, người ta ựã cải tiến và giới thiệu nhiều phương pháp khác hiệu quả và tốn ắt chi phắ hơn, trong các phương pháp ấy là phương pháp kiểm tra CRC.