//////////////////////////////////////////////////////////////////////////
//
// CLinkPrediction.cpp
// implementation of the class CLinkPrediction
//
// Writer: Ouyang Hui
// March 27, 2001
//
// March 28, 2001
// Add Functions
// void CLinkPrediction::Initialization(int iChannelType)
// RATE2CI_TYPE* CLinkPrediction::GetDataRate(int iPacketSize,
// float fC2I)
// float CLinkPrediction::GetBLER(int iPacketSize, float fMeanSNR,
// float fStdSNR, float fEncodingRate)
//
// March 29, 2001
// test the functions OK
//
// The first half of April
// add the algorithms of interpolation
//
///////////////////////////////////////////////////////////////////////////
#include "CLinkPrediction.h"
CLinkPrediction::CLinkPrediction()
{
m_fTollerance=float(1e-6);
m_iDeterminedPacketSize=0;
m_fDeterminedSPDCHC2I=0.;
m_fDeterminedErrorRate=0.;
}
////////////////////////////////////////////////////////////////////////////
//
// TITLE: The destruction of the class CLinkPrediction
//
// PURPOSE:release the space occupied by the two tables in the class
//
// AUTHOR: Ouyang Hui
//
// DATE: 01/04/04
//
// MODIFICATIONS SINCE 01/04/04:
// 01/04/05 Ouyang Hui
// Add codes to delete the branches of the two tables
//
////////////////////////////////////////////////////////////////////////////
CLinkPrediction::~CLinkPrediction()
{
EPS2CI_TYPE* pEPS2CI_TYPE=m_pstRatePredictionTable;
RATE2CI_TYPE* pRATE2CI_TYPE;
EPS2BLER1_TYPE* pEPS2BLER1_TYPE=m_pstBLERPredictionTable;
RATE2BLER1_TYPE* pRATE2BLER1_TYPE;
SNR2BLER1_TYPE* pSNR2BLER1_TYPE;
int m,n,i,j;
m=m_iPacketSizeNum;
for (i=0;i<m;i++)
{
pRATE2CI_TYPE=pEPS2CI_TYPE[i].pstAddrOfRate2CI;
delete pRATE2CI_TYPE;
}
m=m_iPacketSizeNum;
for (i=0;i<m;i++)
{
n=pEPS2BLER1_TYPE[i].iRATE2BLER1Length;
pRATE2BLER1_TYPE=pEPS2BLER1_TYPE[i].pstAddrOfRate2BLER;
for (j=0;j<n;j++)
{
pSNR2BLER1_TYPE=pRATE2BLER1_TYPE[j].pstAddrOfSNR2BLER;
delete pSNR2BLER1_TYPE;
}
delete pRATE2BLER1_TYPE;
}
delete pEPS2CI_TYPE ;
delete pEPS2BLER1_TYPE ;
}
//////////////////////////////////////////////////////////////////////////
//
// TITLE: Function initializing the class CLinkPrediction
//
// PURPOSE:根據信道類型(參數),確定對應的數據文件,從文件中讀入參數,
// 確定數據表的大小,創建數據表,再從文件中讀入數據,寫入數據表,
// 完成數據表的創建。參數為信道類型。
//
// SAMPLE CALL:
// CLinkPrediction mylink;
// mylink.initialization();
//
// CALLED BY FUNCTIONS:
// CNetworkDrive::SystemInitialization()
//
// CALLING FUNCTIONS:
// CLinkPrediction::CheckTheInputs()
//
// AUTHOR: Ouyang Hui
//
// DATE: 01/04/04
//
// MODIFICATIONS SINCE 01/04/04:
//
//////////////////////////////////////////////////////////////////////////
void CLinkPrediction::Initialization()
{
CStdioFile f1; //定義一個I/O文件對象
CString s1,s2,s3;
bool bFlag=false;
double x;
int i,j,k;
char* q;
// m_iChannelType=iChannelType;
const char* cSpecificString1="速率估計部分";
const char* cSpecificString2="PER估計部分";
/* 打開數據文件準備讀*/
if(!f1.Open(m_sRate_BLERPredictionFileName,
CFile::modeRead))
{
#ifdef _DEBUG
afxDump<<"Unable to open file"<<"\n"; //異常處理
#endif
}
char buf[100]; //定義一個數據緩沖區,用于存放一行字符串
/////////////////////////////////////////////////////////////////////
// Construct the rate-prediction table
// The format of this part in the data file is:
// 字符標志(標識速率估計部分的數據) EP數據點的個數(整型)
// EP大小(整型) 數據點個數(整型)
// C/I(實型) 數據速率(實型) 等效編碼速率(實型) 調制方式(整型) 時隙數(整型)
// ........
// ........
// ........
// C/I(實型) 數據速率(實型) 等效編碼速率(實型) 調制方式(整型) 時隙數(整型)
// EP大小(整型) 數據點個數(整型)
// C/I(實型) 數據速率(實型) 等效編碼速率(實型) 調制方式(整型) 時隙數(整型)
// ........
// ........
// ........
// C/I(實型) 數據速率(實型) 等效編碼速率(實型) 調制方式(整型) 時隙數(整型)
// ........
// ........
// ........
while(f1.ReadString(buf,100)!=NULL)
{
s1=buf; //把這一行字符串內容賦給對象s1
if (s1.Find(cSpecificString1)>=0)
{
bFlag=TRUE;
break;
}
}
if (!bFlag)
{
cerr<<"Cannot find the string "<<cSpecificString1<<endl;
f1.Close();
exit(0);
}
s2=s1.Right(s1.GetLength()-s1.Find(' ')-1);
m_iPacketSizeNum=(int)strtod(s2,&q); //the number of encoder packet size
EPS2CI_TYPE* pEPS2CI=new EPS2CI_TYPE [m_iPacketSizeNum];
RATE2CI_TYPE* pRATE2CI;
for (i=0;i<m_iPacketSizeNum;i++)
{
f1.ReadString(buf,100);
x=strtod(buf,&q); //encoder packet size
pEPS2CI[i].iEncoderPacketSize=(int)x;
strcpy(buf,q);
x=strtod(buf,&q); //the number of data
pEPS2CI[i].iRATE2CILength=(int)x;
pRATE2CI=new RATE2CI_TYPE[pEPS2CI[i].iRATE2CILength];
for (j=0;j<pEPS2CI[i].iRATE2CILength;j++)
{
f1.ReadString(buf,100);
x=strtod(buf,&q); //C/I
pRATE2CI[j].fTargetC2I=(float)x;
strcpy(buf,q);
x=strtod(buf,&q); //data rate
pRATE2CI[j].fDataRate=(float)x;
strcpy(buf,q);
x=strtod(buf,&q); //effective code rate
pRATE2CI[j].fEffectiveCodeRate=(float)x;
strcpy(buf,q);
x=strtod(buf,&q); //modulation order
pRATE2CI[j].iModulationOrder=(int)x;
strcpy(buf,q);
x=strtod(buf,&q); //slot number per sub-packet
pRATE2CI[j].iSlotNumPerSubPacket=(int)x;
strcpy(buf,q);
x=strtod(buf,&q); //symbol number per sub-packet
pRATE2CI[j].iSymbolNumber=(int)x;
}
pEPS2CI[i].pstAddrOfRate2CI=pRATE2CI;
}
m_pstRatePredictionTable=pEPS2CI;
/////////////////////////////////////////////////////////////////////
// Construct the BLER-prediction table
// The format of this part in the data file is:
// 字符標志(標識PER估計部分的數據起始位置) EP數據點的個數(整型)
// EP大小(整型) 等效編碼速率的個數(整型)
// 等效編碼速率(實型) 數據點的個數(整型)
// Es/Nt的均值(實型) Es/Nt的標準差(實型) PER(實型)
// ......
// ......
// ......
// Es/Nt的均值(實型) Es/Nt的標準差(實型) PER(實型)
// 等效編碼速率(實型) 數據點的個數(整型)
// Es/Nt的均值(實型) Es/Nt的標準差(實型) PER(實型)
// ......
// ......
// ......
// Es/Nt的均值(實型) Es/Nt的標準差(實型) PER(實型)
// ......
// ......
// ......
// EP大小(整型) 等效編碼速率的個數(整型)
// ......
// ......
// ......
bFlag=false;
while(f1.ReadString(buf,100)!=NULL)
{
s1=buf; //把這一行字符串內容賦給對象s1
if (s1.Find(cSpecificString2)>=0)
{
bFlag=TRUE;
break;
}
}
if (!bFlag)
{
cerr<<"Cannot find the string "<<cSpecificString2<<endl;
f1.Close();
exit(0);
}
s2=s1.Right(s1.GetLength()-s1.Find(' ')-1);
EPS2BLER1_TYPE* pEPS2BLER1=new EPS2BLER1_TYPE[m_iPacketSizeNum];
RATE2BLER1_TYPE* pRATE2BLER1;
SNR2BLER1_TYPE* pSNR2BLER1;
float fRate;
for (i=0;i<m_iPacketSizeNum;i++)
{
f1.ReadString(buf,100);
x=strtod(buf,&q); //encoder packet size
pEPS2BLER1[i].iEncoderPacketSize=(int)x;
strcpy(buf,q);
x=strtod(buf,&q); //the number of data
pEPS2BLER1[i].iRATE2BLER1Length=(int)x;
pRATE2BLER1=new RATE2BLER1_TYPE[pEPS2BLER1[i].iRATE2BLER1Length];
for (j=0;j<pEPS2BLER1[i].iRATE2BLER1Length;j++)
{
f1.ReadString(buf,100);
x=strtod(buf,&q); //effective code rate
pRATE2BLER1[j].fEffectiveCodeRate=(float)x;
fRate=(float)x;
strcpy(buf,q);
x=strtod(buf,&q); //number of data
pRATE2BLER1[j].iSNR2BLER1Length=(int)x;
pSNR2BLER1=new SNR2BLER1_TYPE[pRATE2BLER1[j].iSNR2BLER1Length];
for (k=0;k<pRATE2BLER1[j].iSNR2BLER1Length;k++)
{
f1.ReadString(buf,100);
x=strtod(buf,&q); //mean of Es/Nt
pSNR2BLER1[k].fMeanSNR
=(float)(x+10*log10(fRate));
strcpy(buf,q);
x=strtod(buf,&q); //std of Es/Nt
pSNR2BLER1[k].fStdSNR=(float)x;
strcpy(buf,q);
x=strtod(buf,&q); //PER
pSNR2BLER1[k].fBLER=(float)x;
}
pRATE2BLER1[j].pstAddrOfSNR2BLER=pSNR2BLER1;
}
pEPS2BLER1[i].pstAddrOfRate2BLER=pRATE2BLER1;
}
m_pstBLERPredictionTable=pEPS2BLER1;
f1.Close();
CheckTheInputs();
}
////////////////////////////////////////////////////////////////////////////
//
// TITLE: Getting Data Rate from C/I
//
// PURPOSE:通過查速率估計表,獲得適合的數據速率、調制階數和等效編碼速率,
// 參數為分組長度和C/I值
//
// SAMPLE CALL
// CLinkPrediction* pLink;
// RATE2CI_TYPE* pRATE2CI;
// pRATE2CI=pLink->GetEPDataRate(1536,3);
//
// INPUTS: iPacketSize -- the length of the packet
// should be given precisely and only these 4
// values are legal:
// 3072, 1536, 768, 384
// fC2I -- the C/I
//
// OUTPUTS:pRATE2CI -- a structure body that contains the data rate,
// the effective coding rate, the modulation
// function, and the slot number.
//
// CALLED BY FUNCTIONS:
// CDataMs::RatePrediction()
//
// CALLING FUNCTIONS:
//
// AUTHOR: Ouyang Hui
//
// DATE: 01/04/04
//
// MODIFICATIONS SINCE 01/04/04:
// 01/04/05 Ouyang Hui
// Modify the process when the input C/I is too slow:
// If this happens, the function would return NULL.
//
// 01/04/06 Ouyang Hui
// Modify the process in the second level of the table
//
// 01/04/11 Ouyang Hui
// Modify a bug in the comparison of C/I
//
// 01/05/23 Ouyang Hui
// In the previous version, the function get the nearest point
// that must have LOWER C/I than the input. This may make the
// PER too low and reduce the throughput. So I modify the
// algorithm to find the nearest point that can have higher or
// lower C/I than the input.
// RESULT: the throughput is HIGHER!
//
////////////////////////////////////////////////////////////////////////////
RATE2CI_TYPE* CLinkPrediction::GetEPDataRate(int iChannelType,float fC2IdB,long lDataQueueSize)
{
EPS2CI_TYPE* tempEPS2CI;
RATE2CI_TYPE* tempRATE2CI;
int iEPSize,iPacketLength;
float fCIdB,fLastCIdB=(float)0.0;
double fC2INeededdB,fPowerMargindB,fSPDCCHSlotC2I,fPDCHSlotC2I,fPDCHSlotC2IdB;
int i,j,k,l;
bool bIsDataRateDetermined=false;
//find in the first level of the table