📄 cdatams.cpp
字号:
///////////////////////////////////////////////////////////////////
// for Evaluation Project
// Mobile User Team
// BUPT Radio Research Center
///////////////////////////////////////////////////////////////////
//
// CDataMs.CPP
//
///////////////////////////////////////////////////////////////////
//
// 数据移动台类CDataMs的成员函数的定义
//
//
// Ref. documents:
// "1xEV-DV仿真程序类的初步定义"
// "CDataMs类成员函数"
//
// Written by: ZHANG Ding-ye
//
// Rev. date: 20010515 (yyyymmdd)
//
// What's NEW: 1 加入了若干用于本函数测试的语句,以///for test only///作为标识
// 测试完成后用//注释掉。
// 2 The value of m_fCurrentSlotC2I is in real value!
// 3 SG_EsNt数组存放的EsNt的值均是实际值,求得的SG_EsNt均值是实际值
// 的均值求dB后的值,而SG_EsNt的方差是实际值的dB的值的方差!
// 4 CLinkPrediction中返回的fDataRate是以kbps为单位的,所以用时要乘以1000!
// 5 EP生成函数加入m_iSgNumber=0;//重置记录SGEsNt数组中有效值的长度为零
// 6 修改了IsSubpacketEnd()函数,将里面的插入等效数据速率链表的功能取出,另外
// 增加一个成员函数InsertEffctiveCodeRate()来实现以上所说的功能。
// 7 将EP的生产函数中的条件 m_lDataQueueSize!=0 改为m_lDataQueueSize>0 ,以防产生非法操作
// 8 在清除SGEsNt数组和初始化此数组时加入 m_bIsSGEsNtArrayfull=false;
// //清除标志_用于指示SGEsNtArray是否已被有效数据填满-20010429
// 9 由于现在的Subpacket中的Symbol Group的数量N1和一个Subslot中的SG的个数N2有可能不是整数,
// 对PacketTransmission函数进行了修改-20010430
// Vision: 1.0版
// EP生成算法采用最简单的方法,无根据信道条件改变EP的算法和相应的拆包算法
//
//
///////////////////////////////////////////////////////////////////
#include "CServiceArea.h"
#include "CDataMs.h"
#include "CCell.h"
#include "CSector.h"
#include "CMsManager.h"
#include "CLinkPrediction.h"
#include "CChannelModel.h"
#include "systemsim.h"
#include "iostream.h"
/////////for test only//
//#include "fstream.h"
//#include "iomanip.h"
///////////////////////
char QuantizerMapSymbol[][5]={"0000","0001","0010","0011","0100","0101","0110","0111",
"1000","1001","1010","1011","1100","1101","1110","1111"};
double QuantizerMapC2I[16]={-14.5,-13.8,-12.35,-10.9,-9.5,-8.1,-6.65,-5.2,
-3.8,-2.35,-0.9,0.5,1.9,3.35,4.8,5.5};
double QuantizerMapC2ILimit[15]={-14.5,-13.1,-11.6,-10.2,-8.8,-7.4,-5.9,-4.5,
-3.1,-1.6,-0.2,1.2,2.6,4.1,5.5,};
//////////////////////////////////////////////////////////
//CDataMs
CDataMs::~CDataMs()
{
m_EffectiveCodeRateList.RemoveAll();
POSITION pos; //临时位置指针
// pos=m_CellSwitchMessageList.GetHeadPosition(); //取得链表的头指针
// while(pos!=NULL) //到链表尾则结束循环
// {
// delete m_CellSwitchMessageList.GetNext(pos); //释放内存
// }
// m_CellSwitchMessageList.RemoveAll(); //移去指针
pos=m_PacketArrivalMessageList.GetHeadPosition(); //取得链表的头指针
while(pos!=NULL) //到链表尾则结束循环
{
delete m_PacketArrivalMessageList.GetNext(pos); //释放内存
}
m_PacketArrivalMessageList.RemoveAll(); //移去指针
pos=m_PacketCallArrivalMessageList.GetHeadPosition();
while(pos!=NULL) //到链表尾则结束循环
{
delete m_PacketCallArrivalMessageList.GetNext(pos); //释放内存
}
m_PacketCallArrivalMessageList.RemoveAll(); //移去指针
pos=m_C2IFeedbackDelayList.GetHeadPosition();
while(pos!=NULL) //到链表尾则结束循环
{
delete m_C2IFeedbackDelayList.GetNext(pos); //释放内存
}
m_C2IFeedbackDelayList.RemoveAll();
}
void CDataMs::DataMsInitialization(CLinkPrediction* pLink)
//初始化函数, 参数为CLinkPrediction的指针
{
m_LinkPredictionPointer=pLink; //初始化LinkPrediction对象的指针
m_lDataQueueSize=0; //数据队列的数据量置零
m_iCurrentPacketSize=0; //当前Encoder packet的大小置零
m_stCurrentSector=m_stLocationSector; //当前传输数据分组的扇区初始化为最佳扇区
// m_iCurrentSectorIndex=m_iBestSectorIndex; //当前传输扇区在候选集数组中的下标初始化为最佳扇区在候选集数组中的下标
// m_aCandidateSector[m_iCurrentSectorIndex].iStatusTimer=0; //当前传输扇区的状态改变计数器置零
m_fCurrentSlotC2I=0.0; //当前分组数据信道(FPDCH)的C/I置零
m_iTransmissionNum=0; //当前Encoder packet的传输次数置零
m_pstRatePrediction=NULL; //当前C/I对应的传输信息的指针指向空
m_bIsTransmitingNow=false; //是否正在传输的标志初始化
m_bIsReTransmission=false; //是否为重传的标志初始化
m_bIsEPGood=false; //当前EP是否传输正确的标志初始化
m_iSlotNumRemained=0; //当前sub-packet剩余的时隙数置零
m_fMeanSNR=0.0; //平均SNR置零
m_fStdOfSNR=0.0; //SNR标准差置零
m_fCurrentEffectiveCodeRate=0.0;//当前等效编码速率置零
m_fEPErrorRate=0.0; //EP分组差错概率置零
m_iSuccessfulEPNum=0; //成功传输的EP分组数置零
m_iErrorEPNum=0; //出现差错的EP分组数置零
m_lTotalGoodBitsNum=0; //成功传输的数据量置零
m_fThroughputOfService=0.0; //数据吞吐量置零
// m_iCSMsgNum=0; //软切换消息队列长度置零
m_fPCThroughput=0.;
m_fAveragedPacketDelay=0.;
m_fAveragedPCDelay=0.;
m_iRealTotalSP=0;
m_iRealErrorSP=0;
m_fDelayedC2IValue=0.;
m_fFilterInputC2I=0.;
m_fFilterOutputC2I=0.;
m_fLastSlotC2I=0.;
m_iSlotCounter=0;
m_bIsSPDCCHOverEstimation=false;
m_fSPDCCHC2I=0.;
m_fPDCHPowerScale=0.;
m_iErrorSPDCCH=0;
m_bIsSPDCCHSuccess=false;
m_iDiscardedPacket=0;
m_iLengthOfArrayEsNt=0;
for(int i=0;i<SubslotNumber;i++) m_fC2I[i]=0.;
#ifdef PROPFAIRNESS
m_fAverageRate=1.0; //初始化平均传输速率
#else
m_fAverageRate=0.0;
#endif
for(int k=0 ; k<MaxTransmissionNum ; k++) m_fSaveOfC2IValue[k]=0.0;
m_lPacketCallDataBits=0;
//initialize new added attribute
m_fFudgetFactorOf8PSK=m_pMsManager->m_fFudgetFactorOf8PSK; //初始化高阶调制的修正因子,8PSK ,对应值为-2.4dB
m_fFudgetFactorOf16QAM=m_pMsManager->m_fFudgetFactorOf16QAM; //初始化高阶调制的修正因子,16QAM ,对应值为-3.2dB
m_pfSymbolEsNt=NULL; //指向 Symbol_Es/Nt 的数组的指针指向空
m_iSgNumber=0; //记录上面数组中有效值的长度置零
m_bIsSGEsNtArrayfull=false; //用于指示SGEsNtArray是否已被有效数据填满的bool变量初始化
m_fPacketDelay=0.; //用于记录累加的分组时延置零
m_iSuccessfulPacketNum=0; //记录成功传输过的分组的数目置零
m_iErrorPacketNum=0; //记录发生错误传输的分组数目置零
m_fPacketCallDelay=0.; //记录累加的PC的时延置零
m_iPacketCallNum=0; //记录传输过的PC的数目置零
m_bIsCurrentPacketOver=false; //初始化标识目前传输的packet是否结束,用于扇区的平均分组时延的计算
m_iCurrentPacketDelay=0; //初始化记录目前传输的packet的时延,用于扇区的平均分组时延的计算
m_lPacketCallDataBits=0;
m_iLabelOfDataTraffic=0; //对数据类型的类别的标志进行置零
}
void CDataMs::SGGenerator()
//根据Ep的大小生成Symbol Group的数组
{
m_iLengthOfArrayEsNt=m_iCurrentPacketSize*5/24;
m_pfSymbolEsNt=new float[m_iLengthOfArrayEsNt];
for(int i=0; i<m_iLengthOfArrayEsNt; i++)
{
m_pfSymbolEsNt[i]=0.0;
} //初始化数组值为零
//注意:应在EP传输完毕后用delete释放空间!
m_iSgNumber=0; //重置记录SGEsNt数组中有效值的长度为零
m_bIsSGEsNtArrayfull=false; //清除标志_用于指示SGEsNtArray是否已被有效数据填满
}
void CDataMs::C2ICalculate()
//当前时隙的C/I计算函数: 计算当前传输扇区的C/I
{
float fC[SubslotNumber];
float fI[SubslotNumber];
//扇区分配给数据业务的功率值(发送端),还需乘以到达移动台的损耗值
float fCFromSector;
CSector* pCurrentSector;
pCurrentSector=m_pServiceArea->GetSector(m_stCurrentSector);
fCFromSector=pCurrentSector->GetPacketPower();
//获得本扇区到达移动台的总损耗值(不考虑快衰)
int iCurrentSectorIndexInNeighborSector; //本扇区在相邻扇区数组(57)中的相对位置
for(int i=0 ; i<19*SectorNumber ; i++)
{
if( (m_stCurrentSector.stCellID.m==m_aNeighborSector[i].stSectorID.stCellID.m)
&& (m_stCurrentSector.stCellID.n==m_aNeighborSector[i].stSectorID.stCellID.n)
&& (m_stCurrentSector.s==m_aNeighborSector[i].stSectorID.s))
{
iCurrentSectorIndexInNeighborSector=i;
break;
}
}
float fLoss; //本扇区到达移动台的总损耗值
fLoss=m_aNeighborSector[iCurrentSectorIndexInNeighborSector].fPropagationLoss;
for(int j=0 ; j<SubslotNumber ; j++)
{
fC[j]=fCFromSector*fLoss*m_aNeighborSector[iCurrentSectorIndexInNeighborSector].fFastFading[j];
}
//至此得到四个子时隙对应的C
//计算四个子时隙对应的I
float fInterferenceOfSelfSector[SubslotNumber]; //本扇区的干扰
float fInterferenceOfOtherSector[SubslotNumber]; //其他扇区的干扰
float fThermonoise; //热噪声;以上三项之和等于fI
fThermonoise=float(pow(10,NoiseDensity/double(10))*BandWidth);
for(int k=0 ; k<SubslotNumber ; k++)
{
fInterferenceOfSelfSector[k]=m_pServiceArea->GetOrthogonalFactor()*(pCurrentSector->GetCommonPower()
+pCurrentSector->GetPilotPower()
+pCurrentSector->GetTotalVoicePower())*fLoss*m_aNeighborSector[iCurrentSectorIndexInNeighborSector].fFastFading[k];
}
//计算周围扇区对移动台的干扰
float fIFromOtherSector[19*SectorNumber][SubslotNumber]; //四个子时隙对应的56个相邻扇区的干扰
for(i=0;i<19;i++) //循环19次(相邻集小区的个数)
{
for(j=0;j<SectorNumber;j++)
{
for(k=0;k<SubslotNumber;k++)
fIFromOtherSector[i*SectorNumber+j][k]
=m_pServiceArea
->GetSector(m_aNeighborSector[i*SectorNumber+j].stSectorID)
->GetTxPower()
*m_aNeighborSector[i*SectorNumber+j].fPropagationLoss
*m_aNeighborSector[i*SectorNumber+j].fFastFading[k];
//扇区到达移动台的总功率为=发射功率*总的损耗
}
}
//计算周围扇区的干扰和最终的C/I
float fSumOfC2I=0;
for(int l=0 ; l<SubslotNumber ; l++)
{
fInterferenceOfOtherSector[l]=0.0;
fIFromOtherSector[iCurrentSectorIndexInNeighborSector][l]=0.0;
//对本扇区对应的对其他扇区的干扰值赋0,即只考虑其它扇区对本扇区的干扰。
for(int m=0 ; m<19*SectorNumber; m++)
{
fInterferenceOfOtherSector[l]+=fIFromOtherSector[m][l];
}
fI[l]=fInterferenceOfSelfSector[l]+fInterferenceOfOtherSector[l]+fThermonoise;
m_fC2I[l]=fC[l]/fI[l];
fSumOfC2I+=m_fC2I[l];
}
m_fCurrentSlotC2I=float(fSumOfC2I/SubslotNumber); //real value! not in dB!
}
void CDataMs::C2IFeedbackDelay()
//对C2I的值通过链表进行信道的时延模拟,对m_fDelayedC2IValue进行赋值
{
C2IFEEDBACKDELAY_TYPE *pC2IFeedbackDelay=new C2IFEEDBACKDELAY_TYPE;
pC2IFeedbackDelay->fDelayedC2IValue=m_fCurrentSlotC2I;
pC2IFeedbackDelay->iDelayTime=FEEDBACKDELAY;
m_C2IFeedbackDelayList.AddTail(pC2IFeedbackDelay);
POSITION pos;
pos=m_C2IFeedbackDelayList.GetHeadPosition();
C2IFEEDBACKDELAY_TYPE *pTempC2IFeedbackDelay=NULL;
while(pos!=NULL) //到链表尾则结束循环
{
pTempC2IFeedbackDelay=m_C2IFeedbackDelayList.GetNext(pos);
pTempC2IFeedbackDelay->iDelayTime--; //递减反馈时延计数器
if(pTempC2IFeedbackDelay->iDelayTime<0)
{
m_fDelayedC2IValue=pTempC2IFeedbackDelay->fDelayedC2IValue;
delete m_C2IFeedbackDelayList.GetHead();
m_C2IFeedbackDelayList.RemoveHead();
}
}
}
void CDataMs::RatePrediction()
//速率预测函数: 根据C/I数据,从LinkPrediction中得到对应的RATE2CI_TYPE指针
{
float fSumC2I=0.0;
// for (int i=0; i<m_iTransmissionNum ;i++) fSumC2I+=m_fSaveOfC2IValue[i];
float fC2IOfRatePrediction=float(fSumC2I+m_fFilterOutputC2I);
//当前时隙的C2I的值和记录重传的几次的c2i的值的数组中的值相加
if(fC2IOfRatePrediction==0)
{
m_pstRatePrediction=NULL;
return;
}
fC2IOfRatePrediction=float(10*log10((fC2IOfRatePrediction)));//转化为dB形式
/* if ((m_iTransmissionNum>=1)||(m_fCurrentEffectiveCodeRate>0.2))
fC2IOfRatePrediction+=1.0;
else
fC2IOfRatePrediction+=(float)0.5;*/
//继续对合并的fC2I进行修正
if(m_iTransmissionNum==0)
{
m_pstRatePrediction=m_LinkPredictionPointer-> GetEPDataRate(m_nChannelType,fC2IOfRatePrediction,m_lDataQueueSize);
m_iCurrentPacketSize=m_LinkPredictionPointer->m_iDeterminedPacketSize;
}
else
m_pstRatePrediction=m_LinkPredictionPointer-> GetSPDataRate(m_iCurrentPacketSize,m_nChannelType,fC2IOfRatePrediction);
m_fSPDCCHC2I=m_LinkPredictionPointer->m_fDeterminedSPDCHC2I;
}
void CDataMs::PacketTransmission()
//分组传输函数: 功能为,设置数据传输标志,递减当前sub-packet的时隙数,
//调用函数完成C/I的计算,完成SNR的转换并插入到SNR链表中。
//SNR的操作取消,改为对SymbolEsNt的操作,将其值插入到m_pfSymbolEsNt所指的数组
{
if(m_iSlotNumRemained<=0)
{
m_bIsTransmitingNow=false;
return;
}
//计算当前时隙的C/I
if(m_iSlotNumRemained!=m_pstRatePrediction->iSlotNumPerSubPacket)
{
C2ICalculate();
C2IFeedbackDelay();
C2IFeedback();
}
if(m_fCurrentSlotC2I>m_fSPDCCHC2I)
m_fPDCHPowerScale=1-m_fSPDCCHC2I/m_fCurrentSlotC2I;
else
{
m_bIsSPDCCHOverEstimation=true;
m_iSlotNumRemained--;
return;
}
if(m_iSlotCounter>=4)
m_fPDCHPowerScale=1.;
//在保存每次传输的C/I值时,在各时隙累加前乘以一个所占时隙的比例因子。
if(m_iTransmissionNum<MaxTransmissionNum)
{
if(m_iSlotNumRemained==m_pstRatePrediction->iSlotNumPerSubPacket)
m_fSaveOfC2IValue[m_iTransmissionNum]=(float)((1.0/m_pstRatePrediction->iSlotNumPerSubPacket)*m_fCurrentSlotC2I*m_fPDCHPowerScale);
else
m_fSaveOfC2IValue[m_iTransmissionNum]+=(float)((1.0/m_pstRatePrediction->iSlotNumPerSubPacket)*m_fCurrentSlotC2I*m_fPDCHPowerScale);
//用于对重传时的调度用C2I的计算,实际值!!
}
for(int j=0;j<SubslotNumber;j++)
{
m_fC2I[j]*=m_fPDCHPowerScale;
}
//将子时隙对应的C/I转化为等效的Es/Nt
float fEsNt[SubslotNumber]; //等效的Es/Nt数组
float fRateFactor; //由速率带来的修正因子
fRateFactor=float (ChipRate*m_pstRatePrediction->fEffectiveCodeRate/((m_pstRatePrediction->fDataRate*1000.0)));
//ChipRate 1.2288e6; m_pstRatePrediction->fEffectiveCodeRate 0.2-16/21 m_pstRatePrediction->fDataRate 单位是kb,因此要乘以1000
if(m_pstRatePrediction->iModulationOrder==2)
{
for(int i2=0 ; i2<SubslotNumber ; i2++)
{
fEsNt[i2]=m_fC2I[i2]*fRateFactor;
}
}
else if(m_pstRatePrediction->iModulationOrder==3)
{
for(int i3=0 ; i3<SubslotNumber ; i3++)
{
fEsNt[i3]=m_fC2I[i3]*fRateFactor*(float (pow(10,m_fFudgetFactorOf8PSK/double(10))));
}
}
else if(m_pstRatePrediction->iModulationOrder==4)
{
for(int i4=0 ; i4<SubslotNumber ; i4++)
{
fEsNt[i4]=m_fC2I[i4]*fRateFactor*(float (pow(10,m_fFudgetFactorOf16QAM/double(10))));
}
}
//计算各个Symbol Group的等效Es/Nt值
/////modify by zhdy in 20010430
//由于Subpacket中的Symbol Group的数量N1和一个Subslot中的SG的个数N2可能是小数,进行修改
//N1=m_pstRatePrediction->iSymbolNumber/24
//N2=N1/SubslotNumber;
bool bFlag=false; //false 表示NumberOfSG和NumberOfSGperSubslot均为整型
float fSGNumber=m_pstRatePrediction->iSymbolNumber/(float(24)*m_pstRatePrediction->iSlotNumPerSubPacket);
//当前Subpacket中的SG个数,可能是小数
float fdifference=fSGNumber-int(fSGNumber+1e-6); //用于看fSGNumber是否为小数
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -