📄 cvoicems.cpp
字号:
///////////////////////////////////////////////////////////////////
// WCDMA TEAM //
// BUPT Radio Research Center //
///////////////////////////////////////////////////////////////////
//
// CVoiceMs.cpp
//
//////////////////////////////////////////////////////////////////////
// //
// 话音移动台CVoiceMs的成员函数的声明 //
// //
// Written by: 李晶 //
// Date: 200404 //
// //
//////////////////////////////////////////////////////////////////////
#include "CVoiceMs.h"
#include "systemsim.h"
#include "iostream.h"
#include "sys_random.h"
#include "CMsManager.h"
#include "CLinkPrediction.h"
//////////////////////////////////////////////////////////////////////////
// 构造函数
// 将各属性赋予初始值
//////////////////////////////////////////////////////////////////////////
CVoiceMs::CVoiceMs()
{
}
//end of CVoiceMs()
//////////////////////////////////////////////////////////////////////////
// 析构函数
// 释放内存空间
//////////////////////////////////////////////////////////////////////////
CVoiceMs::~CVoiceMs()
{
Clean();
}
//end of ~CVoiceMs()
//////////////////////////////////////////////////////////////////////////
//TITLE: VoiceInitialization(话音移动台初始化函数)
//
//PARAMETERS:NULL
//
//PURPOSE AND ALGORITHMS:
// 初始化m_iServiceLength、m_eUsertype、m_iUnsatisfiedTimer、
// m_iDropTimer等参数
// 实际上,每一次初始化话音移动台的时候,都是先调用基类的
// MobileInitialization函数,再调用此函数进行初始化
//
//AUTHOR: Li Jing
//
//CALLING FUNCTIONS:
// CMarkovVoice::initRan()
// CMobile::ObtainBestSector()
// CMobile::InitActiveSet()
// CMobile::ObtainC2I()
//
//////////////////////////////////////////////////////////////////////////
void CVoiceMs::VoiceInitialization(CLinkPrediction *pLinkPrediction)
{
//Modified by Li Jing,20040713
m_pLinkPrediction = pLinkPrediction;//指向链路预测对象
POSITION pos;
pos=m_pLinkPrediction->m_pstRateTable.GetHeadPosition();
RATE2CI_TYPE *pRate = new RATE2CI_TYPE;
pRate=m_pLinkPrediction->m_pstRateTable.GetNext(pos);
while ((pos!=NULL)&&(pRate->fDataRate!=(float)12.2||pRate->iChannelType!=m_iChannelType))
{
pRate=m_pLinkPrediction->m_pstRateTable.GetNext(pos);
}
m_pstTFI=pRate->pTFI;
m_fC2ITarget=pRate->fTargetC2I;
m_eUsertype=voice; //初始化m_eUsertype为voice,表示为话音用户
m_bIsDropped=false;
m_iDropTimer=0;
m_fVoiceActiveFactor=m_pMsManager->m_fVoiceActiveFactor;
//话音激活因子初始化
m_iServiceTime=0; //已经服务的时长清0
m_iServiceLength=0; //用slot数表示的已经服务的时长
m_iTotalOutageWindow=0; //中断的窗口数清为0
m_iTotalWindow=0; //总的通话窗口清为0
m_fOutageRatio=0; //中断率清为0
m_fC2IThreshold=m_pMsManager->m_fC2IThreshold;
//at present,consider full_rate only
m_fFwdCurrentActiveFactor=1.0; //本slot话音激活因子为1
m_fFwdLastActiveFactor=1.0; //上一slot话音激活因子为1
m_iFwdFrameRate=FULL_RATE;
m_pfC2IIndex=&(m_pMsManager->m_fC2IIndex[0]); //C/I指针
switch(m_iChannelType) //determine the C/I target
{
case 1 :
//MsVelocity=3
m_pfBLER=&(m_pMsManager->m_fBLER_1[0]);
break;
case 2 :
//MsVelocity=10
m_pfBLER=&(m_pMsManager->m_fBLER_2[0]);
break;
case 3 :
//MsVelocity=30
m_pfBLER=&(m_pMsManager->m_fBLER_3[0]);
break;
case 4 :
//MsVelocity=120
m_pfBLER=&(m_pMsManager->m_fBLER_4[0]);
break;
case 5 :
//MsVelocity=0
m_pfBLER=&(m_pMsManager->m_fBLER_5[0]);
break;
}
ObtainBestSector(); //在移动台的监测集中根据导频情况找出最佳扇区
InitActiveSet(); //初始化激活集。话音移动台与数据DCH状态的移动台的激活集初始化过程是相同的,而
//DSCH状态的移动台则不要初始化激活集。所以这个函数在实现时要加以区分!
//另外,初始化激活集与2000中有较大的区别:现在初始化时移动台只是与最佳扇区进行
//接纳控制,也就是说初始化时最多只有最佳扇区可能进入激活集
ObtainC2I(); //获得当前时隙的C/I
}
//////////////////////////////////////////////////////////////////////////
//TITLE: PowerControl(功率控制函数)
//
//PARAMETERS:NULL
//
//PURPOSE AND ALGORITHMS:
// 功率控制函数,根据计算得到的C/I与功率控制目标C/I的关系,调整
// 激活集内各个扇区的发射功率。需要考虑功控误差,暂时不考虑功控时延
// (在基类中用的是纯虚函数,此处给出实现)
//
//AUTHOR: Li Jing
//
//CALLING FUNCTIONS:
//
//////////////////////////////////////////////////////////////////////////
void CVoiceMs::PowerControl()
{
/* CStdioFile f;
char buf[50];
char FileName[40];
CString sp;
sp="Exception.txt";
strcpy(FileName,sp);*/
//Modified by Li Jing,20041012
float fPowerDelta_T;
float fPowerDelta_R;
float fPowerIncrement;
float fMinTrafficPower; //业务信道最小值,单位:mw
float fTotalC2I=0; //总的C/I,初值为零
float frv; //(0,1)分布的随机数
float fOldTrafficPower; //功控前业务信道功率,单位:mW
float fTempTrafficPower; //业务信道功率,单位:dBm
float fTargetC2I;
POSITION posTemp; //临时位置指针
CSector* pTempSector=NULL; //临时扇区指针
bool bDecision;
fPowerDelta_T=(float)(-1*m_pMsManager->m_fPowerControlStep);
fTotalC2I=m_fC2I; //当前时隙的C/I
fTargetC2I=m_fC2ITarget;
if(fTotalC2I<=fTargetC2I)
//如果当前时隙的C/I小于目标C/I
fPowerDelta_T*=(-1);//调整步长为正(增加)
/* if(m_iMsID==90)
{
if(!f.Open(FileName,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite))
{
#ifdef _DEBUG
afxDump<<"Unable to open file"<<"\n"; //exception handling
#endif
}
f.SeekToEnd();
//使文件指针指向文件尾部,输出数据可以在文件尾部接着写
f.WriteString("\nthe mobile has done one power control");
}*/
posTemp=m_ActiveSetList.GetHeadPosition();
//取得链表头,并令临时指针指向链表头
while(posTemp!=NULL) //到达链表尾则结束循环
{
pTempSector=
m_pServiceArea->GetSector(m_ActiveSetList.GetAt(posTemp)->stSectorID);
//获得激活扇区的指针
fOldTrafficPower=m_ActiveSetList.GetAt(posTemp)->fTrafficPower;
//retrieve the transmit power before the power control
fTempTrafficPower=(float)(10*log10(fOldTrafficPower));
frv=xUniform(0.0,1.0);//产生一个(0,1)分布的随机数,用来模拟功控误差
if(frv<m_pMsManager->m_fBEROfPC)
//如果随机数小于功控比特差错概率
fPowerDelta_R=fPowerDelta_T*(-1);//功控出错,原来的加变成了减
else
fPowerDelta_R=fPowerDelta_T;
fTempTrafficPower+=fPowerDelta_R; //调整此目标扇区对此移动台业务信道功率值
fTempTrafficPower=(float)(pow(10,(fTempTrafficPower/10)));
if(fTempTrafficPower>pTempSector->GetMaxPower()
*m_pMsManager->m_fMaxFractionOfTrafficPower)
//如果业务信道功率大于最大值
fTempTrafficPower=
pTempSector->GetMaxPower()*m_pMsManager->
m_fMaxFractionOfTrafficPower;
//就将业务信道功率置为最大值
fMinTrafficPower=
(float)((pTempSector->GetMaxPower()*
m_pMsManager->m_fMaxFractionOfTrafficPower)
/pow(10,(m_pMsManager->m_fDynamicRangeOfTrafficPower/10)));
//将dB转化为mw
if(fTempTrafficPower<fMinTrafficPower)
//如果业务信道功率小于动态范围
fTempTrafficPower=fMinTrafficPower;
//就将业务信道功率置为最小值(动态范围)
fPowerIncrement=fTempTrafficPower-fOldTrafficPower;
//retrieve the power increment of the power control
bDecision=pTempSector->PowerControlDecision(fPowerIncrement);
if(bDecision)
{
m_ActiveSetList.GetAt(posTemp)->fTrafficPower=fTempTrafficPower;
pTempSector->VoicePowerCumulate(fPowerIncrement);
//add the voice power increment to the active sector
pTempSector->TxPowerUpdate();
//update the total power of the sector
}
/* if(m_iMsID==90)
{
f.WriteString("\nthe active sector's index in monitor is:");
_gcvt(m_ActiveSetList.GetAt(posTemp)->iIndexInMonitor,8,buf);
f.WriteString(buf);
f.WriteString("\nthe active sector's transmission power is:");
_gcvt(m_ActiveSetList.GetAt(posTemp)->fTrafficPower,8,buf);
f.WriteString(buf);
}*/
m_ActiveSetList.GetNext(posTemp);
//获得链表的下一个激活扇区结构
}
/* if(m_iMsID==90)
{
f.Close();
}*/
}
//////////////////////////////////////////////////////////////////////////
//TITLE: SetVoiceActivity(话音激活特性设置函数)
//
//PARAMETERS:NULL
//
//PURPOSE AND ALGORITHMS:
// 根据话音激活因子,设置话音激活标志
//
//AUTHOR: Li Jing
//
//CALLING FUNCTIONS:
//
//////////////////////////////////////////////////////////////////////////
/*void CVoiceMs::SetVoiceActivity()
{
float fDif;
m_fFwdLastActiveFactor=m_fFwdCurrentActiveFactor;
if(m_iSlotCount%15==1)
//每一个帧,更新一次激活因子
{
m_iFwdFrameRate=m_cFwdMarkovState.GetNextState()%4;
switch(m_iFwdFrameRate)
{
case FULL_RATE : m_fFwdCurrentActiveFactor=1.0;
fDif=0.0;
break;
case HALF_RATE : m_fFwdCurrentActiveFactor=0.5;
fDif=3.0;
break;
case QUARTER_RATE : m_fFwdCurrentActiveFactor=0.25;
fDif=6.0;
break;
case EIGHTH_RATE : m_fFwdCurrentActiveFactor=0.125;
fDif=9.0;
break;
}
m_fC2IThreshold=m_pMsManager->m_fC2IThreshold-fDif;
switch(m_iChannelType)
{
case 1 : m_fC2ITarget=(float)C2ITargetForVoice1-fDif;
break;
case 2 : m_fC2ITarget=(float)C2ITargetForVoice2-fDif;
break;
case 3 : m_fC2ITarget=(float)C2ITargetForVoice3-fDif;
break;
case 4 : m_fC2ITarget=(float)C2ITargetForVoice4-fDif;
break;
case 5 : m_fC2ITarget=(float)C2ITargetForVoice5-fDif;
break;
}
}
}
*/
//////////////////////////////////////////////////////////////////////////
//TITLE: IsServiceOver(服务时长到时的判断函数)
//
//PARAMETERS:NULL
//
//PURPOSE AND ALGORITHMS:
// 判断服务时长是否到时,到时返回TRUE
//
//AUTHOR: Li Jing
//
//CALLING FUNCTIONS:
//
//////////////////////////////////////////////////////////////////////////
bool CVoiceMs::IsServiceOver()
{
if(m_iServiceLength>=MeanCallTime*1500) //如果服务到时
return true; //返回true
else
return false; //返回false
}
//////////////////////////////////////////////////////////////////////////
//TITLE: UpdateActiveSetPower(更新激活集中激活扇区的功率函数)
//
//PARAMETERS:NULL
//
//PURPOSE AND ALGORITHMS:
// 将移动台激活集中的各个扇区各自的话音功率进行累加,调用函数:
// CMsManager::UpdateSectorVoicePower()将所有的话音移动台
// 进行循环一次后,实际上就将每一个扇区发射的话音总功率累加起来了
//
//AUTHOR: Li Jing
//
//CALLING FUNCTIONS:
// CServiceArea::GetSector()
// CSector::VoicePowerCumulate()
//
//CALLED FUNCTIONS:
// CMsManager::UpdateSectorVoicePower()
//
//NOTES: 这个函数还是放在话音移动台中实现,因为数据移动台不调用这个函数
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -