#include <stdio.h>
#include <math.h> // для time
static const unsigned int golay_encode_matrix[12] =
{
0xC75, 0x49F, 0xD4B, 0x6E3, 0x9B3, 0xB66, 0xECC, 0x1ED, 0x3DA, 0x7B4, 0xB1D, 0xE3A,
};
static const unsigned int golay_decode_matrix[12] =
{
0x49F, 0x93E, 0x6E3, 0xDC6, 0xF13, 0xAB9, 0x1ED, 0x3DA, 0x7B4, 0xF68, 0xA4F, 0xC75,
};
/// Функция для вычисления веса Хэмминга 12-разрядного целого числа
static unsigned int weight12(unsigned int vector)
{
unsigned int w=0;
for(char i=0; i<12; i++ )
{
if( vector & 1 ) w++;
vector>>=1;
}
return w;
}
/// возвращает Golay-код данного 12-битного слова
unsigned int golay_coding(unsigned int w)
{
unsigned int out=0;
for(char i = 0; i<12; i++ )
{
if( w & 1 ) out ^= golay_encode_matrix[i];
w>>=1;
}
return out;
}
/// возвращает декодированный Golay-код данного 12-битного слова
unsigned int golay_decoding(unsigned int w)
{
unsigned int out=0;
for(char i = 0; i<12; i++ )
{
if( w & 1 ) out ^= golay_decode_matrix[i];
w>>=1;
}
return out;
}
/// Вернуть маску ошибочных битов в received_data или 0xFFFF если ошибок слишком много
unsigned int golay_errors(unsigned int received_data,unsigned int received_parity)//(unsigned long codeword)
{
unsigned int syndrome;
unsigned int w,i;
unsigned int inv_syndrome = 0;
// received_parity = (unsigned int)(codeword>>12);
// received_data = (unsigned int)codeword & 0xfff;
/* We use the C notation ^ for XOR to represent addition modulo 2.
*
* Model the received codeword (r) as the transmitted codeword (u)
* plus an error vector (e).
*
* r = e ^ u
*
* Then we calculate a syndrome (s):
*
* s = r * H, where H = [ P ], where I12 is the identity matrix
* [ I12 ]
*
* (In other words, we calculate the parity check for the received
* data bits, and add them to the received parity bits)
*/
syndrome = received_parity ^ (golay_coding(received_data));
w = weight12(syndrome);
/*
Свойства кода Галея таковы, что расстояние Хемминга (то есть, минимальное расстояние между кодовыми словами) 8;
что означает, что один бит ошибки в битах данных, вызовет 7 ошибок в битах четности.
В частности, если мы находим, 3 или меньше ошибок в битах четности, либо:
- Нет ошибки в битах данных, или
- Есть по крайней мере 5 ошибок в битах данных, мы надеемся, что в первом случае (мы не исповедуем иметь дело с последним).
*/
if( w <= 3 )
{
// return ((long) syndrome)<<12;
return 0; // в данных ошибок нет (или больше 5)
}
/*
the next thing to try is one error in the data bits.
we try each bit in turn and see if an error in that bit would have given
us anything like the parity bits we got. At this point, we tolerate two
errors in the parity bits, but three or more errors would give a total
error weight of 4 or more, which means it's actually uncorrectable or
closer to another codeword.
следующая вещь, чтобы попытаться это одна ошибка в биты данных.
мы стараемся каждый бит, в свою очередь, и увидеть, если ошибка в том,
что бит дал бы нам что-нибудь, как биты четности, которые мы получили.
На данный момент, мы терпим две ошибки в битах четности,
но три или больше ошибок будет давать общую массу ошибок 4 или более,
что означает, что на самом деле неисправимая или ближе к другому кодовому слову.
*/
for( i = 0; i<12; i++ )
{
unsigned int error = 1<<i;
unsigned int coding_error = golay_encode_matrix[i];
if( weight12(syndrome^coding_error) <= 2 )
{
//return (long)((((unsigned long)(syndrome^coding_error))<<12) | (unsigned long)error) ;
return error ; // возвращаю только ошибку в данных
}
}
/*
okay then, let's see whether the parity bits are error free, and all the
errors are in the data bits. model this as follows:
Хорошо, давайте посмотрим, биты четности, являются ли ошибок, и все ошибки в битах данных.
эта модель выглядит следующим образом:
* [r | pr] = [u | pu] + [e | 0]
*
* pr = pu
* pu = H * u => u = H' * pu = H' * pr , where H' is inverse of H
*
* we already have s = H*r + pr, so pr = s - H*r = s ^ H*r
* e = u ^ r
* = (H' * ( s ^ H*r )) ^ r
* = H'*s ^ r ^ r
* = H'*s
*
* Опять же, мы принимаем до трех ошибочных битов...
*/
inv_syndrome = golay_decoding(syndrome);
w = weight12(inv_syndrome);
if( w <=3 ) {
return inv_syndrome;
}
/*
Final shot: try with 2 errors in the data bits, and 1 in the parity
bits; as before we try each of the bits in the parity in turn
Заключительный выстрел: попробуйте 2 ошибки в битах данных, и 1 в биты четности;
как и прежде мы стараемся каждый из битов в четности в свою очередь,
*/
for( i = 0; i<12; i++ )
{
unsigned int error = 1<<i;
unsigned int coding_error = golay_decode_matrix[i];
if( weight12(inv_syndrome^coding_error) <= 2 )
{
// unsigned long error_word = ((unsigned long)(inv_syndrome^coding_error)) | ((unsigned long)error)<<12;
// return (long)error_word;
unsigned int error_word = inv_syndrome^coding_error;
return error_word;
}
}
/* uncorrectable error */
return 0xFFFF;
}
/// возвращает 12-битный Golay-паритет от слова данных
unsigned int golay_encode(unsigned int w)
{
return golay_coding(w);
}
/* decode a received codeword. Up to 3 errors are corrected for; 4
errors are detected as uncorrectable (return 0xFFFF); 5 or more errors
cause an incorrect correction.
*/
unsigned int golay_decode(unsigned int data,unsigned int parity)
{
unsigned int data_errors= golay_errors(data,parity);
if( data_errors == 0xFFFF )
return 0xFFFF;
// data_errors = (unsigned int)errors & 0xfff;
return (data ^ data_errors);
}
int main(void)
{ // test
unsigned int Codeword; // Codeword composed of 12-bit info and 12-bit parity
unsigned int Paritet; // Received vector in two halfs of 12 bits each
unsigned int Syndrome;
int modified_syndrome;
int Codeword_out; // Расчетное кодовое слово
long seed;
///
srandom(seed);
Codeword = random()&0xfff;
printf("c =%03X\n", Codeword
);
///
Paritet=golay_encode(Codeword);
printf("t =%03X%03X\n", Codeword
,Paritet
);
///
unsigned int error_Codeword=(random()&0x030);
unsigned int error_Paritet=(random()&0x101);
printf("e =%03X%03X, w(e) = %d\n", error_Codeword
,error_Paritet
, weight12
(error_Codeword
)+weight12
(error_Paritet
));
///
Codeword^=error_Codeword;
Paritet^=error_Paritet;
printf("r =%03X%03X\n",Codeword
,Paritet
);
///
printf("E =%03X\n", golay_errors
(Codeword
,Paritet
));
printf("c =%03X\n", golay_decode
(Codeword
,Paritet
));
return 0;
}