📄 codec.cpp
字号:
/**************************************************************************************/
/* */
/* force to zero */
/* for convolutional 1/2 code only */
/* */
/**************************************************************************************/
#include <iostream.h>
#include <string.h>
#include "Global.h"
#include "Codec.h"
#include <math.h>
#define MAX( a, b ) ( a > b ? a : b )
#define MIN( a, b ) ( a < b ? a : b )
extern IO IO;
/******************************************************************************************
function : Initialization and parameters check of the turbo-SPC CODEC
input : Nuser -- number of user
Datalen -- length of data
Codewordlen -- length of codeword
Enum -- number of recursive bit
Fnum -- number of non-recursive bit
Nestdim -- number of component code
Spctrellislen -- length of the trellis
Nodeorder -- node order of the trellis
Spcnpoly -- numerator polynome -- less significate bit represents 2^0
Spcdpoly -- denominator polynome
******************************************************************************************/
void SpcCoDec::Init( int Nuser, int Datalen, int Codewordlen, int Enum, int Fnum, int Nestdim, int Spctrellislen, int Nodeorder, int Spcnpoly, int Spcdpoly, int Spcinternum )
{
NUser = Nuser;
DataLen = Datalen;
CodewordLen = Codewordlen;
NestDim = Nestdim;
EfoldNum = Enum;
FfoldNum = Fnum;
FoldNum = EfoldNum + FfoldNum;
TrellisLen = Spctrellislen;
NodeOrder = Nodeorder;
NodeNum = 1 << Nodeorder;
Npoly = Spcnpoly;
Dpoly = Spcdpoly;
SpcInterNum = Spcinternum;
Rate = (float) DataLen / (float) CodewordLen;
SpcCoDec::Check( );
SpcCoDec::MemoryAllocation( );
ConvSpc.Init( NodeOrder, TrellisLen+NodeOrder, Npoly, Dpoly );// Initialization of the convolutional SPC
//set up the interleaver
if( FfoldNum == 0 ) EInterleaver( );
else FInterleaver( );
}
/******************************************************************************************
function : interleaver of the code with only recrsive component
******************************************************************************************/
void SpcCoDec::EInterleaver( )
{
int i, j;
for( j=0; j<DataLen; j++ ) ShaffleRule[0][j] = j;
for( i=0; i<NestDim; i++ )
{
for( j=0; j<DataLen; j++ ) ShaffleRule[i][j] = j;
Scramble( &ShaffleRule[i][0], DataLen, SpcInterNum );
}
}
/******************************************************************************************
function : interleaver of the code with both recrsive and non-recursive component
******************************************************************************************/
void SpcCoDec::FInterleaver( )
{
int i, j, k, m, n, kk;
int *temp = new int [DataLen];
int Length = TrellisLen;
int Elength = ( DataLen * EfoldNum ) / FoldNum;
int Flength = DataLen - Elength;
int SegLength = FoldNum / NestDim;
int a = Length * SegLength;
for( i=0; i<NestDim; i++)
{
for( n=0, k=0; k<FoldNum; k+=SegLength ) for( j=0; j<Length; j++ )
{
m = j * FoldNum + k;
for( kk=k; kk<k+SegLength; kk++ ) temp[n++] = m++;
}
CyclicShift( temp, DataLen, i*a );
Scramble( temp, Elength, SpcInterNum );
Scramble( &temp[Elength], Flength, SpcInterNum );
for( n=0, k=0; k<FoldNum; k+=SegLength ) for( j=0; j<Length; j++ )
{
m = j * FoldNum + k;
for( kk=k; kk<k+SegLength; kk++ ) ShaffleRule[i][m++] = temp[n++];
}
}
delete [] temp;
}
/******************************************************************************************
function : parameters check of the turbo-SPC
******************************************************************************************/
void SpcCoDec::Check( )
{
// if( _SpcNodeOrder != CODEORDER ) SystemIO.ErrorMessage( "_SpcNodeOrder != CODEORDER" );
if( DataLen % FoldNum != 0 ) IO.ErrorMessage( "turbo-SPC: DataLen % FoldNum != 0" );
if( EfoldNum == 0 ) IO.ErrorMessage( "EfoldNum=0 ==> SIMPLE parity check -- use another prog." );
if( FfoldNum != 0 )
{
if( FoldNum % NestDim != 0 ) IO.ErrorMessage( "turbo-SPC: FoldNum % NestDim != 0" ); // NOTE: there is something wrong here
if( DataLen % NestDim != 0 ) IO.ErrorMessage( "turbo-SPC: DataLen % NestDim != 0" );
}
}
/******************************************************************************************
function : memory allocation for the turbo-SPC
******************************************************************************************/
void SpcCoDec::MemoryAllocation( )
{
int i, j;
DataIn = new int [TrellisLen];
ParityOut = new int [TrellisLen];
Zin = new float [DataLen];
tmpbf = new float [DataLen];
Eparity = new float [TrellisLen]; Fparity = new float [TrellisLen];
EparityBf = new float* [TrellisLen]; FparityBf = new float* [TrellisLen];
for( i=0; i<TrellisLen; i++ )
{ EparityBf[i] = new float [EfoldNum]; FparityBf[i] = new float [FfoldNum]; }
Border = new float** [NUser];
for( i=0; i<NUser; i++ ) Border[i] = new float* [2];
for( i=0; i<NUser; i++ ) for( j=0; j<2; j++ ) Border[i][j] = new float [NodeNum];
ExInf = new float** [NUser];
for( i=0; i<NUser; i++ ) ExInf[i] = new float* [NestDim];
for( i=0; i<NUser; i++ ) for( j=0; j<NestDim; j++ ) ExInf[i][j] = new float [DataLen];
ShaffleRule = new int* [NestDim];
for( i=0; i<NestDim; i++ ) ShaffleRule[i] = new int [DataLen];
}
/******************************************************************************************
function : free the allocated memory used in turbo-SPC
******************************************************************************************/
void SpcCoDec::End( )
{
int i, j;
ConvSpc.End( );
delete [] DataIn;
delete [] ParityOut;
delete [] Zin;
delete [] tmpbf;
delete [] Eparity; delete [] Fparity;
for( i=0; i<TrellisLen; i++ )
{ delete [] EparityBf[i]; delete [] FparityBf[i]; }
delete [] EparityBf; delete [] FparityBf;
for( i=0; i<NUser; i++ ) for( j=0; j<2; j++ ) delete [] Border[i][j];
for( i=0; i<NUser; i++ ) delete [] Border[i];
delete [] Border;
for( i=0; i<NUser; i++ ) for( j=0; j<NestDim; j++ ) delete [] ExInf[i][j];
for( i=0; i<NUser; i++ ) delete [] ExInf[i];
delete [] ExInf;
}
/******************************************************************************************
function : encoder of turbo-SPC
input : rawData
output : *Codeword
******************************************************************************************/
void SpcCoDec::Encoder( int *Codeword , int *rawData )
{
int i, j, k, m, p;
int state;
int t = DataLen + NestDim * TrellisLen;
for( i=0; i<DataLen; i++ ) Codeword[i] = rawData[i];//_RawData[Nuser][i];
for( p=DataLen, i=0; i<NestDim; i++ )
{
state = 0;
for( m=0, j=0; j<TrellisLen; j++ )
{
DataIn[j] = rawData[ShaffleRule[i][m++]]; //_RawData[Nuser][ShaffleRule[i][m++]];
for( k=1; k<EfoldNum; k++ ) DataIn[j] ^= rawData[ShaffleRule[i][m++]]; //_RawData[Nuser][ShaffleRule[i][m++]];
m += FfoldNum;
}
ConvSpc.Encoder( &DataIn[0], &ParityOut[0], &state );
for( m=EfoldNum, j=0; j<TrellisLen; j++ )
{
Codeword[p] = ParityOut[j];
for( k=EfoldNum; k<FoldNum; k++ ) Codeword[p] ^= rawData[ShaffleRule[i][m++]];//_RawData[Nuser][ShaffleRule[i][m++]];
m += EfoldNum;
p++;
}
for( j=0; j<2*NodeOrder; j++ ) Codeword[t++] = ConvSpc.TermTable[state][j];
}
}
/******************************************************************************************
function : decoder of turbo-SPC
input : NUser, *Codeword -- LR value
output : *Codeword
******************************************************************************************/
/*
void SpcCoDec::Decoder( int Nuser, float *Codeword, char *Flag )
{
float buffer [DATALEN] , temp[DATALEN];
int i, j, p=DataLen+NestDim*TrellisLen;
for( i=0; i<NestDim; i++ )
{
BorderReSet( Nuser );
for( j=0; j<DataLen; j++ ) buffer[j]=Zin[j] = Codeword[ShaffleRule[i][j]] - ExInf[Nuser][i][j];
MapDecoding( &Codeword[DataLen+(i*TrellisLen)], &Codeword[p+(2*i*NodeOrder)], Nuser, i, Flag );// the major decoding step
for( j=0; j<DataLen; j++ ) Codeword[ShaffleRule[i][j]] = Zin[j];
}
}
*/
void SpcCoDec::Decoder( int Nuser, float *Codeword, char *Flag )
{
float buffer [DATALEN] ;
int i, j, p=DataLen+NestDim*TrellisLen;
for( j=0; j<DataLen; j++ ) Codeword[j] = Codeword[j] + Sum_Ex[j] ;
for( i=0; i<NestDim; i++ )
{
BorderReSet( Nuser );
for( j=0; j<DataLen; j++ ) buffer[j]=Zin[j] = Codeword[ShaffleRule[i][j]] - ExInf[Nuser][i][j];
MapDecoding( &Codeword[DataLen+(i*TrellisLen)], &Codeword[p+(2*i*NodeOrder)], Nuser, i, Flag );// the major decoding step
for( j=0; j<DataLen; j++ ) Codeword[ShaffleRule[i][j]] = Zin[j];
for( j=0; j<DataLen; j++ ) ExInf[Nuser][i][j] = Zin[j] - buffer[j] ;
}
for( j=0; j<DataLen; j++ ) Sum_Ex[j] = 0;
for( i=0; i<NestDim; i++ ) for( j=0; j<DataLen; j++ )Sum_Ex[ShaffleRule[i][j]] += ExInf[Nuser][i][j];
}
//*/
void SpcCoDec::BorderReSet( int Nuser )
{
int i;
for( i=1; i<NodeNum; i++ )
Border[Nuser][0][i] = Border[Nuser][1][i] = LS;;
Border[Nuser][0][0] = Border[Nuser][1][0] = 0;
}
/******************************************************************************************
function : decoder of convolutional-SPC
******************************************************************************************/
void SpcCoDec::MapDecoding( float *Parity, float *Tail, int Nuser, int dim, char *Flag )
{
Apriori( Parity, Tail );
ConvSpc.BCJR( &Border[Nuser][0][0], &Border[Nuser][1][0] );
Aposteriori( Nuser, dim, Parity, Tail, Flag );
}
/******************************************************************************************
function : handle the information output from the BCJR
******************************************************************************************/
void SpcCoDec::Aposteriori( int Nuser, int dim, float *Parity, float *Tail, char *Flag )
{
int i, m;
for( i=0; i<DataLen; i++ ) tmpbf[i] = Zin[i];
for( i=0; i<TrellisLen; i++ )
{
Eparity[i] = ConvSpc.LlrAdd(ConvSpc.aPP[i][0],ConvSpc.aPP[i][1])-ConvSpc.LlrAdd(ConvSpc.aPP[i][2],ConvSpc.aPP[i][3])-Eparity[i];
Fparity[i] = ConvSpc.LlrAdd(ConvSpc.aPP[i][0],ConvSpc.aPP[i][2])-ConvSpc.LlrAdd(ConvSpc.aPP[i][1],ConvSpc.aPP[i][3])-Fparity[i];
}
m = TrellisLen;
if( strcmp( Flag, "ParityRequire" ) == 0 ) for( i=0; i<NodeOrder; i++ )
{
Tail[2*i] = ConvSpc.LlrAdd(ConvSpc.aPP[m][0],ConvSpc.aPP[m][1])-ConvSpc.LlrAdd(ConvSpc.aPP[m][2],ConvSpc.aPP[m][3]);
Tail[2*i+1] = ConvSpc.LlrAdd(ConvSpc.aPP[m][0],ConvSpc.aPP[m][2])-ConvSpc.LlrAdd(ConvSpc.aPP[m][1],ConvSpc.aPP[m][3]);
m++;
}
for( m=0, i=0; i<TrellisLen; i++, m += FoldNum )
PostPreDec( &Zin[m], Eparity[i], &EparityBf[i][0], EfoldNum );
for( i=0; i<TrellisLen; i++ ) Eparity[i] = Parity[i];
// "ParityRequire" -- extrinstic information of parity are provided
// "ParityNotRequire" -- extrinstic information of parity are NOT provided
if( strcmp( Flag, "ParityRequire" ) == 0 )
{
if( FfoldNum == 0 ) for( i=0; i<TrellisLen; i++ ) Parity[i] = ( Parity[i] + Fparity[i] );
else if( FfoldNum == 1 ) for( m=EfoldNum, i=0; i<TrellisLen; i++, m+=FoldNum )
Parity[i] = ( Parity[i] + Plr( Fparity[i], Zin[m] ) );
else for( m=EfoldNum, i=0; i<TrellisLen; i++, m+=FoldNum )
Parity[i] = ( Parity[i] + Plr( Fparity[i], Plr( Zin[m], FparityBf[i][0] ) ) );
}
if( FfoldNum != 0 ) for( m=EfoldNum, i=0; i<TrellisLen; i++, m+=FoldNum )
PostPreDec( &Zin[m], Plr( Eparity[i], Fparity[i] ), &FparityBf[i][0], FfoldNum );
//for( i=0; i<DataLen; i++ ) ExInf[Nuser][dim][i] = Zin[i] - tmpbf[i];
}
/******************************************************************************************
function : sub-function of SpcCoDec::Aposteriori( int Nuser, int dim, float *Parity )
******************************************************************************************/
void SpcCoDec::PostPreDec( float *Zin, float Parity, float *bf, int blength )
{
int i;
for( i=0; i<blength; i++ ) Zin[i] = Zin[i] + Plr( Parity, bf[i] );
}
/******************************************************************************************
function : prepare the information for the BCJR
******************************************************************************************/
void SpcCoDec::Apriori( float *Parity, float *Tail )
{
int i, j, m;
for( m=0, i=0; i<TrellisLen; i++ )
{
PrePrtDec( &Zin[m], &Eparity[i], &EparityBf[i][0], EfoldNum );
m += EfoldNum;
PrePrtDec( &Zin[m], &Fparity[i], &FparityBf[i][0], FfoldNum );
m += FfoldNum;
}
if( FfoldNum == 0 ) for( i=0; i<TrellisLen; i++ ) Fparity[i] = Parity[i];
else for( i=0; i<TrellisLen; i++ ) Fparity[i] = Plr( Fparity[i], Parity[i] );
for( i=0; i<TrellisLen; i++ )
{
for( j=0; j<NodeNum; j++ )
{
if( ConvSpc.Bcode[j][0] == 0 ) ConvSpc.CodeInf[i][j][0] = Eparity[i] + Fparity[i];
else ConvSpc.CodeInf[i][j][0] = Eparity[i];
if( ConvSpc.Bcode[j][1] == 0 ) ConvSpc.CodeInf[i][j][1] = Fparity[i];
else ConvSpc.CodeInf[i][j][1] = 0;
}
}
m = TrellisLen;
for( i=0; i<NodeOrder; i++ )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -