blob: 605244caa14924580573bff7be578e2cad551ded [file] [log] [blame]
/* ____________________________________________________________________________
*
* Filename : bch.c
*______________________________________________________________________________
*
* History:
* 24 Apr 2008 : Creation
*____________________________________________________________________________*/
/*_______________________________ Include Files _____________________________*/
#include <common.h>
#include <asm/arch/omap4_hal.h>
/*________________________________ Local Types ______________________________*/
/*______________________________ Local Constants ____________________________*/
#define mm_max 8 /* Dimension of Galois Field */
#define nn_max 256 /* Length of codeword, n = 2**m - 1 */
#define tt_max 2 /* Number of errors that can be corrected */
#define kk_max 256 /* Length of information bit, kk = nn - rr */
#define rr_max 32 /* Number of parity checks, rr = deg[g(x)] */
#define parallel_max 8 /* Number of parallel encoding/syndrome computations */
/*______________________________ Local Variables ____________________________*/
int i, j;
int gen_roots[nn_max + 1], gen_roots_true[nn_max + 1] ; // Roots of generator polynomial
int iii, jjj, Temp ;
int bb_temp[rr_max] ;
int loop_count ;
int mask ; // Register states
int mm, nn, kk, tt, rr; // BCH code parameters
int nn_shorten, kk_shorten; // Shortened BCH code
int Parallel ; // Parallel processing
int p[mm_max + 1], alpha_to[nn_max], index_of[nn_max] ; // Galois field
int gg[rr_max] ; // Generator polynomial
int bb[rr_max] ; // Parity checks
int T_G[rr_max][rr_max], T_G_R[rr_max][rr_max]; // Parallel lookahead table
int T_G_R_Temp[rr_max][rr_max] ;
int data[kk_max], data_p[parallel_max][kk_max]; // Information data and received data
/*______________________________ Local Functions Declarations _______________*/
/*______________________________ Global Functions ___________________________*/
U32 hexStringtoInteger(const char* hexString, U32* result)
{
int iL;
int temp;
int factor;
int length;
length = strlen(hexString);
if ((length == 0) || (length>8))
return 1;
*result = 0;
factor = 1;
/* Convert the characters to hex number */
for(iL=length-1; iL>=0 ;iL--)
{
if (*(hexString+iL)>=97){
temp = ( *(hexString+iL) - 97) + 10;
}else if ( *(hexString+iL) >= 65){
temp = (*(hexString+iL) - 65) + 10;
}else{
temp = *(hexString+iL) - 48;
}
*result += (temp * factor);
factor *= 16;
}
return 0;
}
U32 cpfrom_bit_reverse32(U32 value)
{
U32 value_i;
U32 value_o;
U32 itr;
value_i=value;
value_o=value_i & 1;
for(itr=0; itr<31; itr++)
{
value_o = value_o<<1;
value_i = value_i>>1;
value_o = value_o | (value_i & 1);
}
return value_o;
}
U32 cpfrom_byte_reverse32(U32 value)
{
U32 value_i;
U32 value_o;
U32 itr;
value_i=value;
value_o=value_i & 0xFF;
for(itr=0; itr<3; itr++)
{
value_o = value_o<<8;
value_i = value_i>>8;
value_o = value_o | (value_i & 0xFF);
}
return value_o;
}
U32 bch_enc(U8 index, U32 in_v[])
{
U32 out_v;
if (index == 1){
kk_shorten = 32;
mm = 6;
}
else if (index == 4){
kk_shorten = 128;
mm = 8;
}
else
return 0xFFFFFFFF;
tt = 2;
Parallel = 8;
// nn = (int)pow(2, mm) - 1 ;
nn = 1; /* nn = (int)pow(2, mm) - 1 ; */
for (j = 0 ; j < mm ; j++) /* nn = (int)pow(2, mm) - 1 ; */
nn = nn * 2; /* nn = (int)pow(2, mm) - 1 ; */
nn = nn - 1; /* nn = (int)pow(2, mm) - 1 ; */
// INPUT
for (j = 0 ; j < index ; j++)
{ for (i = 0 ; i < 32 ; i++)
{ if (0x1 & (in_v[j] >> i))
data[32*(j+1)-i-1] = 1 ;
else
data[32*(j+1)-i-1] = 0 ;
}
}
// generate the Galois Field GF(2**mm)
// Primitive polynomials
for (i = 1; i < mm; i++)
p[i] = 0;
p[0] = p[mm] = 1;
if (mm == 6) p[1] = 1;
else if (mm == 8) p[4] = p[5] = p[6] = 1;
// Galois field implementation with shift registers
mask = 1 ;
alpha_to[mm] = 0 ;
for (i = 0; i < mm; i++)
{ alpha_to[i] = mask ;
index_of[alpha_to[i]] = i ;
if (p[i] != 0)
alpha_to[mm] ^= mask ;
mask <<= 1 ;
}
index_of[alpha_to[mm]] = mm ;
mask >>= 1 ;
for (i = mm + 1; i < nn; i++)
{ if (alpha_to[i-1] >= mask)
alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i-1] ^ mask) << 1) ;
else alpha_to[i] = alpha_to[i-1] << 1 ;
index_of[alpha_to[i]] = i ;
}
index_of[0] = -1 ;
// Compute the generator polynomial and lookahead matrix for BCH code
// Initialization of gen_roots
for (i = 0; i <= nn; i++)
{ gen_roots_true[i] = 0;
gen_roots[i] = 0;
}
// Cyclotomic cosets of gen_roots
for (i = 1; i <= 2*tt ; i++)
{
for (j = 0; j < mm; j++)
{
// Temp = ((int)pow(2, j) * i) % nn;
Temp = 1; /* Temp = ((int)pow(2, j) * i); */
for(jjj=0; jjj<j; jjj++) /* Temp = ((int)pow(2, j) * i); */
Temp = Temp * 2; /* Temp = ((int)pow(2, j) * i); */
// Temp = fmod((double)(Temp * i), (double)nn);
Temp = (Temp * i) % nn; /* Temp = ((int)pow(2, j) * i) % nn; */
gen_roots_true[Temp] = 1;
}
}
rr = 0; // Count the number of parity check bits
for (i = 0; i < nn; i++)
{ if (gen_roots_true[i] == 1)
{ rr++;
gen_roots[rr] = i;
}
}
kk = nn - rr;
// Compute generator polynomial based on its roots
gg[0] = 2 ; // g(x) = (X + alpha) initially
gg[1] = 1 ;
for (i = 2; i <= rr; i++)
{ gg[i] = 1 ;
for (j = i - 1; j > 0; j--)
{
if (gg[j] != 0)
// gg[j] = gg[j-1]^ alpha_to[fmod((double)(index_of[gg[j]] + index_of[alpha_to[gen_roots[i]]]), (double)nn)] ;
gg[j] = gg[j-1]^ alpha_to[(index_of[gg[j]] + index_of[alpha_to[gen_roots[i]]]) % nn] ;
else
gg[j] = gg[j-1] ;
}
// gg[0] = alpha_to[fmod((double)(index_of[gg[0]] + index_of[alpha_to[gen_roots[i]]]), (double)nn)] ;
gg[0] = alpha_to[(index_of[gg[0]] + index_of[alpha_to[gen_roots[i]]]) % nn] ;
}
// for parallel encoding and syndrome computation
// Max parallalism is rr
if (Parallel > rr)
Parallel = rr ;
// Construct parallel lookahead matrix T_g, and T_g**r from gg(x)
for (i = 0; i < rr; i++)
{ for (j = 0; j < rr; j++)
T_G[i][j] = 0;
}
for (i = 1; i < rr; i++)
T_G[i][i-1] = 1 ;
for (i = 0; i < rr; i++)
T_G[i][rr - 1] = gg[i] ;
for (i = 0; i < rr; i++)
{ for (j = 0; j < rr; j++)
T_G_R[i][j] = T_G[i][j];
}
// Compute T_G**R Matrix
for (iii = 1; iii < Parallel; iii++)
{ for (i = 0; i < rr; i++)
{ for (j = 0; j < rr; j++)
{ Temp = 0;
for (jjj = 0; jjj < rr; jjj++)
Temp = Temp ^ T_G_R[i][jjj] * T_G[jjj][j];
T_G_R_Temp[i][j] = Temp;
}
}
for (i = 0; i < rr; i++)
{ for (j = 0; j < rr; j++)
T_G_R[i][j] = T_G_R_Temp[i][j];
}
}
nn_shorten = kk_shorten + rr ;
// Parallel BCH Encode
// Determine the number of loops required for parallelism.
// loop_count = ceil(kk_shorten / (double)Parallel) ;
loop_count = kk_shorten / Parallel ;
// Serial to parallel data conversion
for (i = 0; i < Parallel; i++)
{ for (j = 0; j < loop_count; j++)
{ if (i + j * Parallel < kk_shorten)
data_p[i][j] = data[i + j * Parallel];
else
data_p[i][j] = 0;
}
}
// Initialize the parity bits.
for (i = 0; i < rr; i++)
bb[i] = 0;
// Compute parity checks
// S(t) = T_G_R [ S(t-1) + M(t) ]
for (iii = loop_count - 1; iii >= 0; iii--)
{
for (i = 0; i < rr; i++)
bb_temp[i] = bb[i] ;
for (i = Parallel - 1; i >= 0; i--)
bb_temp[rr - Parallel + i] = bb_temp[rr - Parallel + i] ^ data_p[i][iii];
for (i = 0; i < rr; i++)
{ Temp = 0;
for (j = 0; j < rr; j++)
Temp = Temp ^ (bb_temp[j] * T_G_R[i][j]);
bb[i] = Temp;
}
}
// OUTPUT
out_v = 0;
for (i = 0 ; i < rr ; i++)
out_v = ( out_v << 1) | bb[i] ;
return out_v;
}
/*------------------------------- End OF File --------------------------------*/