#include <stdio.h>
#include <stdlib.h>
/************************
* Made by, YuriHan *
* Hamming Code Test. *
* 2007.08.01~ ver. 1.0 *
************************/
/*-----------------------
2007.08.03 ver 1.0
완성.
-----------------------*/
//Global/*{{{*/
// 테이블 초기화.
#define Clr_Hamming_Table {Hamming_Table.P0=1;Hamming_Table.P1=1;Hamming_Table.P2=1;Hamming_Table.P3=1;\
Hamming_Table.P4=1;Hamming_Table.P5=1;Hamming_Table.P6=1;}
unsigned char GetHammingCode(char* data,int Length);
unsigned char GetParityBit(char* data,int Length);
int VerifyData(char* data,unsigned char Code,unsigned char Parity,int Length);
static unsigned char Chk_ParityBit(char* data,unsigned char Parity,int Length);
static void Set_Table(int Num);
static struct _Hamming_Table // Bit Field. Table 이라기보다는
{ // Flag set에 가까움.
char P0 :1;
char P1 :1;
char P2 :1;
char P3 :1;
char P4 :1;
char P5 :1;
char P6 :1;
}Hamming_Table;
/*}}}*/
// 테스트를 위한 부분./*{{{*/
void Test_Menu(void);
void Test_Menu_Make(void);
void Test_Menu_verify(void);
void Test_Menu(void)/*{{{*/
{
int Select_Menu;
while(1)
{
system("cls");
printf( "\n\n\n\n\n\n"
"\t\t-----Select menu-----\n"
"\t\t 1. Make Code\n"
"\t\t 2. Verify Code\n"
"\t\t q. Quit Test Program\n"
"\t\t----------------------\n"
"\t\tSelect : ");
Select_Menu=getchar();
system("cls");
printf("\n\n\n\n\n\n");
switch(Select_Menu)
{
case '1' :
Test_Menu_Make();
break;
case '2' :
Test_Menu_verify();
break;
case 'q' :
return;
break;
}
}
}/*}}}*/
void Test_Menu_Make(void)/*{{{*/
{
char data_buf[17]={0};
unsigned char data[8]={0};
char buf;
printf( "Make Hamming & Pariey Code\n"
" |1234567890123456|\n"
"Data Input [8Byte] : 0x");
scanf("%s", data_buf);
sscanf(data_buf,"%02X%02X%02X%02X%02X%02X%02X%02X",&data[0],&data[1],&data[2],&data[3],&data[4],&data[5],&data[6],&data[7]);
fflush(stdin);
printf("\n\nParityBit[0x%02x]\t\tStrain Hamming Code[0x%02x]\n",
GetParityBit(data,8),GetHammingCode(data,8));
printf("\nWould you want to verify?(Y/N) ");
buf=getchar();
printf("\n\n");
switch(buf)
{
case 'Y' :
case 'y' :
Test_Menu_verify();
break;
}
system("PAUSE");
}/*}}}*/
void Test_Menu_verify(void)/*{{{*/
{
unsigned char buf[2];
char data_buf[17]={0};
unsigned char data[9]={0};
int i;
printf( "Verify Hamming & Pariey Code\n"
" |1234567890123456|\n"
"Data Input [8Byte] : 0x");
scanf("%s", data_buf);
sscanf(data_buf,"%02X%02X%02X%02X%02X%02X%02X%02X",&data[0],&data[1],&data[2],&data[3],&data[4],&data[5],&data[6],&data[7]);
printf("ParityBit : 0x");
scanf("%x",&buf[0]);
printf("Strain Hamming Code : 0x");
scanf("%x",&buf[1]);
switch(VerifyData(data,buf[1],buf[0],8))
{
case 0 :
printf("\n정상적인 코드입니다.\n");
break;
case -1 :
printf("\n잘못된 코드입니다.\n");
break;
case 1 :
printf( "\n\n수정 가능한 코드입니다."
"\n수정된 코드는 0x");
for(i=0;i<8;i++)printf("%02X",data[i]);
printf(" 입니다.\n");
break;
}
system("PAUSE");
}/*}}}*/
int main(void)/*{{{*/
{
Test_Menu();
printf("\n\nMade by, YuriHan's Dream Factory™\n\n");
system("PAUSE");
return 0;
}/*}}}*/
/*}}}*/
/*----------------------------------------------------
변형 해밍코드 관련 함수
기본 골격은 같지만 비트사이사이에 넣는 방식이 아닌
맨 끝에 몰아넣는 방식.
P0가 MSB측 P6으로 갈수록 LSB에 가까워지고
LSB측은 ChkSum의 Parity 포함.
----------------------------------------------------*/
unsigned char GetHammingCode(char* data,int Length)/*{{{*/
{
int i,j,k=0;
unsigned char buf=0;
unsigned char Code=0;
Clr_Hamming_Table;
for(i=0;i<Length;i++)
{
buf=data[i];
for(j=0;j<8;j++)
{
if(Hamming_Table.P0)
Code^=((buf&0x80));
if(Hamming_Table.P1)
Code^=((buf&0x80)>>1);
if(Hamming_Table.P2)
Code^=((buf&0x80)>>2);
if(Hamming_Table.P3)
Code^=((buf&0x80)>>3);
if(Hamming_Table.P4)
Code^=((buf&0x80)>>4);
if(Hamming_Table.P5)
Code^=((buf&0x80)>>5);
if(Hamming_Table.P6)
Code^=((buf&0x80)>>6);
Set_Table(++k);
buf<<=1;
}
}
// ChkSum의 ParityBit
buf=0;
for(i=1;i<8;i++)
{
buf+=((Code>>i)&0x01);
}
Code+=(buf&0x01);
return Code;
}/*}}}*/
static void Set_Table(int Num)/*{{{*/
{
//P0
if(!(Num%2)) // 홀
Hamming_Table.P0=1;
else // 짝
Hamming_Table.P0=0;
//P1
if(!(Num%2)) // 2 배수
Hamming_Table.P1=~Hamming_Table.P1;
//P2
if(!(Num%4)) // 4 배수
Hamming_Table.P2=~Hamming_Table.P2;
//P3
if(!(Num%8)) // 8 배수
Hamming_Table.P3=~Hamming_Table.P3;
//P4
if(!(Num%16)) // 16 배수
Hamming_Table.P4=~Hamming_Table.P4;
//P5
if(!(Num%32)) // 32 배수
Hamming_Table.P5=~Hamming_Table.P5;
//P6
if(!(Num%64)) // 64 배수
Hamming_Table.P6=~Hamming_Table.P6;
}/*}}}*/
/*----------------------------------------------------
변형 패리티비트 관련 함수
기본 골격은 같지만 바이트 끝에 넣는 방식이 아닌
맨 끝에 몰아넣는 방식.
MSB측이 Data[0] LSB측이 Data[Length]
----------------------------------------------------*/
unsigned char GetParityBit(char* data,int Length)/*{{{*/
{
unsigned char buf=0;
unsigned char Parity=0;
int i,j;
for(i=0;i<Length;i++)
{
for(j=0;j<8;j++)
{
buf+=((data[i]>>j)&0x01);
}
Parity<<=1;
Parity+=(buf&0x01);
buf=0;
}
return Parity;
}/*}}}*/
static unsigned char Chk_ParityBit(char* data,unsigned char Parity,int Length)/*{{{*/
{
unsigned char buf=GetParityBit(data,Length);
if(Parity==buf) // 같으면
return 0; // 정상종료
buf^=Parity;
return buf; // 다른부분만 리턴
}/*}}}*/
/*----------------------------------------------------
패킷 검증
해밍코드를 이용하여 잘못된 비트부분을 추출하고
패리티비트를 확인해서 그 위치의 바이트가
정상인지 비정상인지 판단후 수정한다.
2비트 이상 뻑났을때를 대비한 궁여지책.
----------------------------------------------------*/
int VerifyData(char* data,unsigned char Code,unsigned char Parity,int Length)/*{{{*/
{
unsigned char buf=0,buf_pos;
unsigned char buf_Parity;
unsigned char tmp=GetHammingCode(data,Length);
int i;
if(Code==tmp) // 코드 검증
return 0; // 같으면 success
else
{
// 해밍코드의 parity검사.
for(i=1;i<8;i++)
{
buf+=((Code>>i)&0x01);
}
if(!((buf&0x01)==(Code&0x01)))
return -1; // 다르면 Error.
else
{
buf=0; // 오류비트 위치 확인
if(Code&0x80) buf+=1;
if(Code&0x40) buf+=2;
if(Code&0x20) buf+=4;
if(Code&0x10) buf+=8;
if(Code&0x08) buf+=16;
if(Code&0x04) buf+=32;
if(Code&0x02) buf+=64;
buf_pos=buf/8; // 오류 데이터 바이트 위치
buf%=8; // 오류 데이터 비트 위치
buf_Parity=Chk_ParityBit(data,Parity,Length);
if(!buf_Parity) // 패리티는 정상 / 해밍은 오류일경우 에러처리
return -1;
else
{
{ // 지역변수 때문에..
int tmp=0;
for(i=0;i<8;i++)
if((buf_Parity)&(1<<i)) // buf_Parity내의 1의 갯수 파악.
tmp++;
if(tmp>=2) // 두개이상이면 에러
return -1; // 해밍 특성상 오류가 두개이상이면 흠좀무
}
if(buf_Parity!=(0x80>>buf_pos)) // 패리티 오류 위치와 해밍코드 오류 위치가 다르면
return -1; // 에러
else
{
data[buf_pos]^=(1>>buf); // 오류정정. 비트토글.
return 1;
}
}
}
}
return 0;
}/*}}}*/