📄 cvoicems.cpp
字号:
//bIsAdd置为true(实际上是加入)
pTempSHOMsg->iCandidateIndex=i;
//将当前扇区下标赋予iCandidateIndex
pTempSHOMsg->iWaitTime=
m_pMsManager->m_iSoftHandoffDelay;
//软切换的时延为0.2s(转换为slot数)
pTempSHOMsg->stTargetSector=
m_aCandidateSector[i].stSectorID;
//需要加入的目标扇区为当前扇区
m_SoftHandoffMessageList.AddTail(pTempSHOMsg);
//将产生的软切换消息加入队列
m_iSHOMsgNum++;
//更新属性中的软切换消息队列长度
m_aCandidateSector[i].bIsInActive=true;
//是否在激活集中的标志置为true
m_aCandidateSector[i].iStatusTimer=0;
//状态改变计数器清零
iLogicActiveSize++;
//逻辑激活集队列长度加一
}
//.......................................//
}
}
}
else
//如果最佳扇区的导频信噪比与当前扇区的导频信噪比之差
//大于软切换加入的门限值
m_aCandidateSector[i].iStatusTimer=0;
//当前扇区的状态改变计数器清零
}
}
}
//end of SHOMsgGenerator()
//////////////////////////////////////////////////////////////////////////
// 消息队列处理函数 //
// 完成每个时隙内消息等待时间递减的功能,并返回到时消息的数量。 //
//////////////////////////////////////////////////////////////////////////
int CVoiceMs::SHOMsgProcess()
{ //定义必要的变量
int iTimeoutSHOMsgNum=0; //超时的软切换消息数
POSITION posTemp; //临时位置指针
SOFTHANDOFFMESSAGE_TYPE* pSHOMsg=NULL; //软切换消息指针
if(m_SoftHandoffMessageList.IsEmpty()) //如果链表为空
return iTimeoutSHOMsgNum; //直接返回到时消息数量
else
{
posTemp=m_SoftHandoffMessageList.GetHeadPosition();
//取得链表头,并令临时指针指向链表头
while(posTemp!=NULL) //到达链表尾则结束循环
{
pSHOMsg=m_SoftHandoffMessageList.GetAt(posTemp);
//获得链表中的一个软切换消息结构
pSHOMsg->iWaitTime--; //等待时长减一(以时隙为单位)
if(pSHOMsg->iWaitTime<=0) //如果iWaitTime小于等于0
{
pSHOMsg->iWaitTime=0; //iWaitTime置为0
iTimeoutSHOMsgNum++; //到时的SHOMsg数量加一
}
m_SoftHandoffMessageList.GetNext(posTemp);
//获得链表的下一个软切换消息结构
}
return iTimeoutSHOMsgNum; //返回iTimeoutSHOMsgNum值
}
}
//end of SHOMsgProcess()
//////////////////////////////////////////////////////////////////////////
// 激活集变更函数 //
// 根据消息处理函数的返回值,读出相应的软切换消息, //
// 根据该消息完成相应的操作, //
// 去掉:直接从链表中删除,加入:加入新的激活信息结构体, //
// 并初始化各个变量。 //
//////////////////////////////////////////////////////////////////////////
void CVoiceMs::ChangeActiveSet()
{ //定义必要的变量
int iTargetSectorIndex; //目标扇区在候选集中的下标
int j; //循环变量
int iTempIndex; //临时下标
float fC2ITarget; //目标C/I
float fOrthogonalFactor; //正交因子
float fOtherChannelPower; //其他信道干扰,单位:mw
float fMaxTrafficPower; //最大业务信道功率,单位:mw
float fTempTrafficPower; //临时业务信道功率,单位:mw
float fMinTrafficPower; //最小业务信道功率,单位:mw
float fFastFading;
//...... added by cqm, Apr.25 ......//
Random R;
float fRand;
//..................................//
SOFTHANDOFFMESSAGE_TYPE* pSHOMsg=NULL; //软切换消息指针
POSITION posSHOMsg1,posSHOMsg2,posActive1,posActive2;
//所用到的位置指针
CSector* pTargetSector=NULL; //目标扇区指针
ACTIVESECTOR_TYPE* pTempActiveSector=NULL;//临时激活扇区指针
posSHOMsg1=posSHOMsg2=m_SoftHandoffMessageList.GetHeadPosition();
//两个位置变量同时指向链表头
while(posSHOMsg1!=NULL) //到链表尾则结束循环
{
pSHOMsg=m_SoftHandoffMessageList.GetAt(posSHOMsg1);
//获得一个软切换消息指针
pTargetSector=m_pServiceArea->GetSector(pSHOMsg->stTargetSector);
//得到目标扇区指针
iTargetSectorIndex=pSHOMsg->iCandidateIndex;
//获得目标扇区在候选集中的下标
m_SoftHandoffMessageList.GetNext(posSHOMsg2);
//posSHOMsg2指向链表中的下一个元素
if(pSHOMsg->iWaitTime==0) //如果软切换消息到时
{
if(pSHOMsg->bIsAdd) //如果消息类型是加入
{
//...... added by cqm, Apr.25 ......//
if((pSHOMsg->stTargetSector.stCellID.m!=3)||(pSHOMsg->stTargetSector.stCellID.n!=3))
{//如果切换到了周围小区
fRand=R.Next();
if(fRand>=0.05)
{
m_iServiceLength=16;//模拟软切换成功,认为服务时间到时(需要重新初始化一个话音用户)
m_bIsSHOOut=true;
}
delete m_SoftHandoffMessageList.GetAt(posSHOMsg1);
//删除当前的软切换消息
m_SoftHandoffMessageList.RemoveAt(posSHOMsg1);
//移去位置指针
posSHOMsg1=posSHOMsg2;
//指针指向链表中下一个软切换消息
m_iSHOMsgNum--;
//软切换消息队列长度减一
}
//.................................//
else//如果切换到了中心小区
{
if(!pTargetSector->IsTransmiting())
//如果目标扇区没有数据正在传输
{
fMaxTrafficPower
=m_pMsManager->m_fMaxFractionOfTrafficPower
*m_pServiceArea->GetSector(pSHOMsg->stTargetSector)->
GetMaxPower();
//计算业务信道最大功率
//(为最大发射功率乘以最大业务信道所占的最大比例)
for(j=0;j<19*SectorNumber;j++)
//对相邻集中的扇区进行循环
if((m_aNeighborSector[j].stSectorID.stCellID.m
==m_aCandidateSector[iTargetSectorIndex].stSectorID.stCellID.m)
&&(m_aNeighborSector[j].stSectorID.stCellID.n
==m_aCandidateSector[iTargetSectorIndex].stSectorID.stCellID.n)
&&(m_aNeighborSector[j].stSectorID.s
==m_aCandidateSector[iTargetSectorIndex].stSectorID.s))
//找到当前候选扇区在相邻集中的位置
{
switch(m_iFwdFrameRate)
{
case FULL_RATE : fC2ITarget=(float)pow(10,(/*m_pMsManager->*/m_fC2ITarget/10));
break;
case HALF_RATE : fC2ITarget=(float)pow(10,((/*m_pMsManager->*/m_fC2ITarget-(float)3)/10));
break;
case QUARTER_RATE : fC2ITarget=(float)pow(10,((/*m_pMsManager->*/m_fC2ITarget-(float)6)/10));
break;
case EIGHTH_RATE : fC2ITarget=(float)pow(10,((/*m_pMsManager->*/m_fC2ITarget-(float)9)/10));
break;
}
// fC2ITarget=(float)pow(10,(m_pMsManager->m_fC2ITarget/10));
fOrthogonalFactor=m_pServiceArea->GetOrthogonalFactor();
fFastFading=(m_aNeighborSector[j].fFastFading[0]
+m_aNeighborSector[j].fFastFading[1]
+m_aNeighborSector[j].fFastFading[2]
+m_aNeighborSector[j].fFastFading[3])/(float)4;
fOtherChannelPower=
m_pServiceArea->GetSector(pSHOMsg->stTargetSector)->
GetTxPower()*m_aNeighborSector[j].fPropagationLoss*fFastFading;
fTempTrafficPower=
(float)(fC2ITarget*
(m_aCandidateSector[iTargetSectorIndex].fInterferenceFromOtherSector
+fOtherChannelPower*fOrthogonalFactor
+NoisePower)
/(m_aNeighborSector[j].fPropagationLoss*fFastFading));
//业务信道功率赋初值,公式参考UpAndDown里的公式
if(fTempTrafficPower>fMaxTrafficPower)
//如果算出来的功率大于功率最大值
fTempTrafficPower=fMaxTrafficPower;
//则将业务信道功率赋最大值
fMinTrafficPower=
(float)(fMaxTrafficPower
/pow(10,(m_pMsManager->m_fDynamicRangeOfTrafficPower/10)));
//将dB转化为mw
if(fTempTrafficPower<fMinTrafficPower) //如果业务信道功率小于动态范围
fTempTrafficPower=fMinTrafficPower; //就将业务信道功率置为最小值(动态范围)
if(pTargetSector->GetMaxPower()
-pTargetSector->GetTxPower()>=
fTempTrafficPower)
//wgt
// if(pTargetSector->GetMaxPower()
// -pTargetSector->GetTxPower1()>=
// fTempTrafficPower)
//如果剩余的功率比所许要的业务信道功率大
{
pTempActiveSector=new ACTIVESECTOR_TYPE;
//产生一个新的软切换消息
pTempActiveSector->fTrafficPower=fTempTrafficPower;
//激活扇区业务信道功率赋初值
pTempActiveSector->fTrafficC2I=(float)(10*log10(fC2ITarget));
//激活扇区业务信道C/I先置为零
pTempActiveSector->iIndexInCandidate=iTargetSectorIndex;
//激活扇区在候选集中的下标赋初值
pTempActiveSector->stSectorID=pSHOMsg->stTargetSector;
//激活扇区的扇区标号赋初值
m_ActiveSetList.AddTail(pTempActiveSector);
//将生成的激活扇区加入激活集
//...... added by cqm, May.10 ......//
m_iActiveSetSize++;
//..................................//
//wgt
// pTargetSector->SetTxPower1(pTargetSector->GetTxPower1()+fTempTrafficPower);
//将该话音用户所需要的功率累加到m_fTxPower1
delete m_SoftHandoffMessageList.GetAt(posSHOMsg1);
//删除当前的软切换消息
m_SoftHandoffMessageList.RemoveAt(posSHOMsg1);
//移去位置指针
posSHOMsg1=posSHOMsg2;
//指针指向链表中下一个软切换消息
m_iSHOMsgNum--;
//软切换消息队列长度减一
}
else //如果剩余的功率比所许要的业务信道功率小
{
delete m_SoftHandoffMessageList.GetAt(posSHOMsg1);
//删除当前的软切换消息
m_SoftHandoffMessageList.RemoveAt(posSHOMsg1);
//移去位置指针
posSHOMsg1=posSHOMsg2;
//指针指向链表中下一个软切换消息
m_iSHOMsgNum--;
//软切换消息队列长度减一
}
break;
}
}
else//如果目标扇区有数据传输
posSHOMsg1=posSHOMsg2;//指针指向链表中下一个软切换消息
}
}
else //如果消息类型是去掉
{
posActive1=posActive2=m_ActiveSetList.GetHeadPosition();
//两个位置变量同时指向链表头
while(posActive1!=NULL) //到链表尾则结束循环
{
m_ActiveSetList.GetNext(posActive2);
//posActive2指向链表中的下一个元素
iTempIndex=m_ActiveSetList.GetAt(posActive1)->iIndexInCandidate;
//获得当前激活集在候选集中的下标
if(iTempIndex==iTargetSectorIndex)
//如果当前激活扇区是目标扇区
{
delete m_ActiveSetList.GetAt(posActive1);
//删除当前的激活扇区
m_ActiveSetList.RemoveAt(posActive1);
//移去指针
//...... added by cqm, May.10 ......//
m_iActiveSetSize--;
//..................................//
}
posActive1=posActive2;
//指针指向链表中下一个激活扇区
}
delete m_SoftHandoffMessageList.GetAt(posSHOMsg1);
//删除当前的软切换消息
m_SoftHandoffMessageList.RemoveAt(posSHOMsg1);
//移去指针
posSHOMsg1=posSHOMsg2;
//指针指向链表中下一个软切换消息
m_iSHOMsgNum--;
//软切换消息队列长度减一
}
}
else //如果软切换消息未到时
posSHOMsg1=posSHOMsg2; //指针指向链表中下一个软切换消息
}
}
//end of ChangeActiveSet()
//////////////////////////////////////////////////////////////////////////
// 激活集更新函数, //
// 根据候选集更新的情况,计算业务信道的信噪比 //
// 在每个时隙中均需调用,激活集初始化和变更之后也需调用 //
//////////////////////////////////////////////////////////////////////////
void CVoiceMs::UpdateActiveSet()
{ //定义必要的变量
int iTempIndex; //临时下标
int i; //循环变量
// bool bIsLastActive;
float fOtherSectorInterference; //从别的扇区来的干扰
float fOtherChannelInterference; //从别的信道来的干扰
float fTrafficPower; //业务信道功率
float fOrthogonalFactor; //正交因子
float fFastFading;
POSITION posTemp; //临时位置指针
ACTIVESECTOR_TYPE* pTempActiveSector=NULL; //临时激活扇区
// bIsLastActive=m_bIsServiceActive; //保存上一个时隙的激活标志
// SetVoiceActivity(); //设置本slot话音激活标志
posTemp=m_ActiveSetList.GetHeadPosition();
//取得链表头,并令临时指针指向链表头
while(posTemp!=NULL) //到达链表尾则结束循环
{
pTempActiveSector=m_ActiveSetList.GetAt(posTemp);
//获得当前的激活扇区
iTempIndex=pTempActiveSector->iIndexInCandidate;
if((m_aCandidateSector[iTempIndex].fPilotSNR<-16)&&(m_iActiveSetSize==1)&&(m_bIsSHOOut))//test by cqm
{
m_iServiceLength=80;//认为掉话
m_bIsSHOOut=true;
}
//获得该扇区在候选集中的下标
fOtherSectorInterference=
m_aCandidateSector[iTempIndex].fInterferenceFromOtherSector;
//获得从其他扇区来的干扰
fOrthogonalFactor=m_pServiceArea->GetOrthogonalFactor();
//获得正交因子
fOtherChannelInterference=m_pServiceArea->GetSector(pTempActiveSector->stSectorID)->GetTxPower()
-pTempActiveSector->fTrafficPower;
// if(m_iMsID==18)
// cout<<m_pServiceArea->GetSector(pTempActiveSector->stSectorID)->GetTxPower()<<endl;
for(i=0;i<19*SectorNumber;i++) //对相邻扇区集进行循环
{
if((pTempActiveSector->stSectorID.s
==m_aNeighborSector[i].stSectorID.s)
&&(pTempActiveSector->stSectorID.stCellID.m
==m_aNeighborSector[i].stSectorID.stCellID.m)
&&(pTempActiveSector->stSectorID.stCellID.n
==m_aNeighborSector[i].stSectorID.stCellID.n))
//找到当前扇区在相邻集中的位置
{
fFastFading=(m_aNeighborSector[i].fFastFading[0]
+m_aNeighborSector[i].fFastFading[1]
+m_aNeighborSector[i].fFastFading[2]
+m_aNeighborSector[i].fFastFading[3])/(float)4;
pTempActiveSector->fTrafficPower=pTempActiveSector->fTrafficPower
*m_fFwdCurrentActiveFactor/m_fFwdLastActiveFactor;
//...... added by cqm ......//
if(pTempActiveSector->fTrafficPower>m_pServiceArea->GetSector(pTempActiveSector->stSectorID)->GetMaxPower()*m_pMsManager->m_fMaxFractionOfTrafficPower)
pTempActiveSector->fTrafficPower=m_pServiceArea->GetSector(pTempActiveSector->stSectorID)->GetMaxPower()*m_pMsManager->m_fMaxFractionOfTrafficPower;
fTrafficPower=pTempActiveSector->fTrafficPower
*m_aNeighborSector[i].fPropagationLoss*fFastFading;
//............//
//计算MS接收到的业务信道功率
// fOtherChannelInterference=m_pServiceArea->GetSector(pTempActiveSector->stSectorID)->GetTxPower()
// -pTempActiveSector->fTrafficPower;
fOtherChannelInterference*=
m_aNeighborSector[i].fPropagationLoss*fFastFading;
//计算本扇区从其他信道来的干扰值
break;
}
}
pTempActiveSector->fTrafficC2I=
(float)(10*log10(fTrafficPower
/(fOtherChannelInterference*fOrthogonalFactor
+fOtherSectorInterference+NoisePower)));
//计算实际的C/I
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -