📄 cvoicems.cpp
字号:
//所以在这里可以不调用该函数
}
//end of InitActiveSet()
//////////////////////////////////////////////////////////////////////////
// C/I计算函数, //
// 根据激活集情况,计算用户最终的C/I。 //
//////////////////////////////////////////////////////////////////////////
void CVoiceMs::ObtainC2I()
{ //定义必要的变量
float fTempC2I; //单个业务信道C/I(倍数)
float fSumofC2I=0; //C/I总和(倍数,初值为0)
float fThresholdC2I; //实际的门限C/I
POSITION posTemp; //用于链表循环的位置指针
ACTIVESECTOR_TYPE* pTempActiveSector=NULL; //临时激活扇区指针
if(m_ActiveSetList.IsEmpty()) //如果队列为空
return; //函数返回
else //否则,计算激活集中用户总的C/I
{
posTemp=m_ActiveSetList.GetHeadPosition();
//取得链表头,并令临时指针指向链表头
while(posTemp!=NULL) //到达链表尾则结束循环
{
pTempActiveSector=m_ActiveSetList.GetAt(posTemp);
//获得链表中的一个扇区
fTempC2I=(float)pow(10,(pTempActiveSector->fTrafficC2I/10));
//转换为倍数
fSumofC2I+=fTempC2I; //累加每一个扇区的C/I
m_ActiveSetList.GetNext(posTemp);//指向链表中下一个扇区
}
m_fC2I=(float)(10*log10(fSumofC2I)); //将属性中的C/I值赋值
if(m_iSlotCount%16!=0)
m_fMeanC2I+=(float)pow(10,(m_fC2I/10));
else
{
m_fMeanC2I=m_fMeanC2I+(float)pow(10,(m_fC2I/10));
m_fMeanC2I=(float)(10*log10(m_fMeanC2I/16));
// if(m_iMsID==100)
// cout<<m_fMeanC2I<<" ";
// switch(m_iFwdFrameRate)
// {
// case FULL_RATE : fThresholdC2I=m_pMsManager->m_fC2IThreshold;
// break;
// case HALF_RATE : fThresholdC2I=m_pMsManager->m_fC2IThreshold-(float)3.0;
// break;
// case QUARTER_RATE : fThresholdC2I=m_pMsManager->m_fC2IThreshold-(float)6.0;
// break;
// case EIGHTH_RATE : fThresholdC2I=m_pMsManager->m_fC2IThreshold-(float)9.0;
// break;
// }
if(m_fFwdLastActiveFactor==1.0)
fThresholdC2I=m_pMsManager->m_fC2IThreshold;
if(m_fFwdLastActiveFactor==0.5)
fThresholdC2I=m_pMsManager->m_fC2IThreshold-(float)3.0;
if(m_fFwdLastActiveFactor==0.25)
fThresholdC2I=m_pMsManager->m_fC2IThreshold-(float)6.0;
if(m_fFwdLastActiveFactor==0.125)
fThresholdC2I=m_pMsManager->m_fC2IThreshold-(float)9.0;
m_fMeanC2IofLastFrame=m_fMeanC2I;
if(m_fMeanC2I>=fThresholdC2I) //如果C/I大于门限
{
m_bIsC2IEnough=true;
//则C/I超过门限标志m_bIsC2IEnough置为true
if(m_pMsManager->m_iSlotCurrentNum>=INITIALSLOT)
{
m_iDropTimer=0; //掉话计时器清零
m_fMeanC2I=0;
}
else
m_fMeanC2I=0;
}
else
{
m_bIsC2IEnough=false; //否则置为false
if(m_pMsManager->m_iSlotCurrentNum>=INITIALSLOT)
{
m_iUnsatisfiedTimer++; //不满意数加一
m_iDropTimer++; //掉话计时器加一
m_fMeanC2I=0;
}
else
m_fMeanC2I=0;
}
}
}
}
//end of ObtainC2I()
//////////////////////////////////////////////////////////////////////////
// 软切换消息生成函数, //
// 根据候选集更新情况,生成加入、去掉或替换消息 //
// (替换体现为去掉和加入各一个消息) //
//////////////////////////////////////////////////////////////////////////
void CVoiceMs::SHOMsgGenerator()
{ //定义必要的变量
int i; //循环变量
int iLogicActiveSize=0; //逻辑激活集长度
int iBestSectorIndex,iWorstSectorIndex=-1,iTempIndex;
//最好基站下标,最差基站下标,临时基站下标(在候选集中的)
POSITION posTemp; //用于循环的位置指针
float fMaxPilotSNR=-1000.0; //初值设为一个很小的值,单位:dB
float fMinPilotSNR; //fMinC2I初值设为最大值
bool bIsSHOMsgIteration=false;
SOFTHANDOFFMESSAGE_TYPE* pTempSHOMsg=NULL;//临时软切换消息指针
// if(m_iMsID==4)
// cout<<"wait"<<endl;
if(m_ActiveSetList.IsEmpty()) //队列为空,返回
return;
else
{
posTemp=m_ActiveSetList.GetHeadPosition();
//取得链表头,并令临时指针指向链表头
while(posTemp!=NULL) //到达链表尾则结束循环
{
iTempIndex=m_ActiveSetList.GetAt(posTemp)->iIndexInCandidate;
//获得当前激活集扇区在候选集中的下标
if(m_aCandidateSector[iTempIndex].fPilotSNR>fMaxPilotSNR)
//找出最佳扇区(导频信噪比最大的那个)
{
fMaxPilotSNR=m_aCandidateSector[iTempIndex].fPilotSNR;
//记录下最大的导频信噪比
iBestSectorIndex=iTempIndex;
//记录下最佳扇区在候选集中的下标
}
m_ActiveSetList.GetNext(posTemp);
//指向链表中下一个扇区
}
m_aCandidateSector[iBestSectorIndex].bIsInActive=true;
//将最佳扇区的激活标志置为true
m_aCandidateSector[iBestSectorIndex].iStatusTimer=0;
//状态改变计数器置为0
fMinPilotSNR=fMaxPilotSNR;
//将最小导频信噪比初值设为最大导频信噪比
posTemp=m_ActiveSetList.GetHeadPosition();
//取得链表头,并令临时指针指向链表头
while(posTemp!=NULL)
//到达链表尾则结束循环
{
iTempIndex=m_ActiveSetList.GetAt(posTemp)->iIndexInCandidate;
//获得当前激活集扇区在候选集中的下标
if(iTempIndex!=iBestSectorIndex)
//找出不同于最佳扇区的扇区(导频信噪比最小的那个)
if(m_aCandidateSector[iTempIndex].bIsInActive==true)
//并且这个扇区的bIsInActive是true
if(m_aCandidateSector[iTempIndex].fPilotSNR<
fMinPilotSNR) //而且是最差扇区
{
iWorstSectorIndex=iTempIndex;
//记录最差扇区在候选集中的下标
fMinPilotSNR=
m_aCandidateSector[iTempIndex].fPilotSNR;
//记录下最小的导频信噪比
}
m_ActiveSetList.GetNext(posTemp);
//指向链表中下一个扇区
}
posTemp=m_SoftHandoffMessageList.GetHeadPosition();
//取得链表头,并令临时指针指向链表头
while(posTemp!=NULL)
//到达链表尾则结束循环
{
if(m_SoftHandoffMessageList.GetAt(posTemp)->bIsAdd)
//如果软切换消息是加入
iLogicActiveSize++;
//隐含的激活队列长度变化量加一
else //如果软切换消息是去掉
iLogicActiveSize--;
//隐含的激活队列长度变化量减一
m_SoftHandoffMessageList.GetNext(posTemp);
//指向链表中下一个软切换消息
}
iLogicActiveSize=iLogicActiveSize+m_iActiveSetSize;
//逻辑激活队列长度等于隐含的激活队列长度变化量加上原来的激活队列长度
for(i=0;i<6+SectorNumber;i++) //对候选扇区进行循环
{
if(i==iBestSectorIndex) //跳过最佳扇区
continue;
else
if(m_aCandidateSector[i].bIsInActive)
//如果是否在激活集中的标志为真
{
if(m_aCandidateSector[iBestSectorIndex].fPilotSNR
-m_aCandidateSector[i].fPilotSNR>
m_pMsManager->m_fSHODeleteThreshold)
//如果最佳扇区的导频信噪比与当前扇区的导频信噪比之差
//大于软切换去掉的门限值
{
m_aCandidateSector[i].iStatusTimer++;
//当前循环的候选扇区结构体中的状态改变计数器加一
if(m_aCandidateSector[i].iStatusTimer>
m_pMsManager->m_iSHODeleteTimer)
//如果状态改变计数器大于软切换去掉定时器
//(m_iSHODeleteTimer是以秒为单位的,要转换)
{
//...... modified by cqm, May.21 ......//
posTemp=m_SoftHandoffMessageList.GetHeadPosition();
while(posTemp!=NULL)
{
if((m_SoftHandoffMessageList.GetAt(posTemp)->iCandidateIndex==i)&&(m_SoftHandoffMessageList.GetAt(posTemp)->bIsAdd==false))
bIsSHOMsgIteration=true;
m_SoftHandoffMessageList.GetNext(posTemp);
}
if(!bIsSHOMsgIteration)
{
pTempSHOMsg=new SOFTHANDOFFMESSAGE_TYPE;
//产生一个新的软切换消息
pTempSHOMsg->iCandidateIndex=i;
//将当前扇区下标赋予iCandidateIndex
pTempSHOMsg->bIsAdd=false;
//bIsAdd置为false(实际上就是去掉)
pTempSHOMsg->iWaitTime=
m_pMsManager->m_iSoftHandoffDelay;
//软切换的时延为0.2s(转换为slot数)
pTempSHOMsg->stTargetSector=
m_aCandidateSector[i].stSectorID;
//目标扇区为当前扇区
m_SoftHandoffMessageList.AddTail(pTempSHOMsg);
//将生成的软切换消息加入软切换消息队列
m_iSHOMsgNum++;
//更新属性中的软切换消息队列长度
iLogicActiveSize--; //逻辑激活队列长度减一
m_aCandidateSector[i].bIsInActive=false;
//当前扇区的是否在激活集中的标志置为false
m_aCandidateSector[i].iStatusTimer=0;
//状态改变计数器清零
}
//.......................................//
}
}
else
//如果最佳扇区的导频信噪比与当前扇区的导频信噪比之差小于门限值
m_aCandidateSector[i].iStatusTimer=0;
//当前循环的候选扇区结构体中的状态改变计数器清零
}
else //如果是否在激活集中的标志为假
if(i!=iWorstSectorIndex)
//如果当前循环的扇区不是激活集中最差扇区
if((m_aCandidateSector[iBestSectorIndex].fPilotSNR
-m_aCandidateSector[i].fPilotSNR<
m_pMsManager->m_fSHOAddThreshold)&&(m_aCandidateSector[i].fPilotSNR>=-16)) //test by cqm
//如果最佳扇区的导频信噪比与当前扇区的导频信噪比之差小于软切换加入的门限值
{
m_aCandidateSector[i].iStatusTimer++;
//当前扇区的状态改变计数器加一
if(m_aCandidateSector[i].iStatusTimer>80) //test 0513
//如果状态改变计数器大于加入激活集的时间门限
//(取16个slot)
{
if(iLogicActiveSize>=
m_pMsManager->m_iActiveSetMaxSize)
//如果逻辑激活集扇区个数大于激活集扇区最大个数
if(m_aCandidateSector[i].fPilotSNR
-m_aCandidateSector[iWorstSectorIndex].fPilotSNR>
m_pMsManager->m_fSHOSubstitutionThreshold)
//如果当前扇区的导频信噪比与最差扇区的导频信噪比之差
//大于替换的门限(1dB)
if(m_aCandidateSector[iWorstSectorIndex].bIsInActive
==false)
//如果激活集中的最差扇区已经发生过去掉或替换操作
//(bIsInActive为false)
m_aCandidateSector[i].iStatusTimer--;
//状态改变计数器减一
else //如果还没有发生过去掉或替换操作,
//则产生替换操作(先去掉,再加入)
{
//...... modified by cqm, May.21 ......//
posTemp=m_SoftHandoffMessageList.GetHeadPosition();
while(posTemp!=NULL)
{
if(((m_SoftHandoffMessageList.GetAt(posTemp)->iCandidateIndex==iWorstSectorIndex)&&(m_SoftHandoffMessageList.GetAt(posTemp)->bIsAdd==false))||((m_SoftHandoffMessageList.GetAt(posTemp)->iCandidateIndex==i)&&(m_SoftHandoffMessageList.GetAt(posTemp)->bIsAdd==true)))
bIsSHOMsgIteration=true;
m_SoftHandoffMessageList.GetNext(posTemp);
}
if(!bIsSHOMsgIteration)
{
pTempSHOMsg=new SOFTHANDOFFMESSAGE_TYPE;
//产生一个新的软切换消息
pTempSHOMsg->bIsAdd=false;
//bIsAdd置为false(实际上就是去掉)
pTempSHOMsg->iCandidateIndex=iWorstSectorIndex;
//将最差扇区下标赋予iCandidateIndex
pTempSHOMsg->stTargetSector=
m_aCandidateSector[iWorstSectorIndex].stSectorID;
//需要去掉的目标扇区为最差扇区
pTempSHOMsg->iWaitTime=
m_pMsManager->m_iSoftHandoffDelay;
//软切换的时延为200ms(转换为slot数)
m_SoftHandoffMessageList.AddTail(pTempSHOMsg);
//将产生的软切换消息加入队列
m_iSHOMsgNum++;
//更新属性中的软切换消息队列长度
m_aCandidateSector[iWorstSectorIndex].iStatusTimer=0;
//状态改变计数器清零
m_aCandidateSector[iWorstSectorIndex].bIsInActive=false;
//是否在激活集中的标志置为false
pTempSHOMsg=new SOFTHANDOFFMESSAGE_TYPE;
//产生一个新的软切换消息
pTempSHOMsg->bIsAdd=true;
//bIsAdd置为true(实际上就是加入)
pTempSHOMsg->iCandidateIndex=i;
//将当前扇区下标赋予iCandidateIndex
pTempSHOMsg->stTargetSector=
m_aCandidateSector[i].stSectorID;
//需要加入的目标扇区为当前扇区
pTempSHOMsg->iWaitTime=
m_pMsManager->m_iSoftHandoffDelay;
//软切换的时延为200ms(转换为slot数)
m_SoftHandoffMessageList.AddTail(pTempSHOMsg);
//将产生的软切换消息加入队列
m_iSHOMsgNum++;
//更新属性中的软切换消息队列长度
m_aCandidateSector[i].iStatusTimer=0;
//状态改变计数器清零
m_aCandidateSector[i].bIsInActive=true;
//是否在激活集中的标志置为true
posTemp=m_ActiveSetList.GetHeadPosition();
//取得链表头,并令临时指针指向链表头
while(posTemp!=NULL)
//到达链表尾则结束循环
{
iTempIndex=
m_ActiveSetList.GetAt(posTemp)->iIndexInCandidate;
//获得当前激活集扇区在候选集中的下标
if(iTempIndex!=iBestSectorIndex)
//找出不同于最佳扇区的扇区(导频信噪比最小的那个)
if(m_aCandidateSector[iTempIndex].bIsInActive==true)
//并且这个扇区的bIsInActive是true
if(m_aCandidateSector[iTempIndex].fPilotSNR<
fMinPilotSNR)
//而且是最差扇区
{
iWorstSectorIndex=iTempIndex;
//记录下最差扇区在候选集中的下标
fMinPilotSNR=
m_aCandidateSector[iTempIndex].fPilotSNR;
//记录下最小的导频信噪比
}
m_ActiveSetList.GetNext(posTemp);
//指向链表中下一个扇区
}
}
//.......................................//
}
else
//如果当前扇区的导频信噪比与最差扇区的导频信噪比之差
//小于替换的门限(1dB)
m_aCandidateSector[i].iStatusTimer--;
//状态改变计数器减一
else //如果逻辑激活集扇区个数小于激活集扇区最大个数
{
//...... modified by cqm, May.21 ......//
posTemp=m_SoftHandoffMessageList.GetHeadPosition();
while(posTemp!=NULL)
{
if((m_SoftHandoffMessageList.GetAt(posTemp)->iCandidateIndex==i)&&(m_SoftHandoffMessageList.GetAt(posTemp)->bIsAdd==true))
bIsSHOMsgIteration=true;
m_SoftHandoffMessageList.GetNext(posTemp);
}
if(!bIsSHOMsgIteration)
{
pTempSHOMsg=new SOFTHANDOFFMESSAGE_TYPE;
//产生一个新的软切换消息
pTempSHOMsg->bIsAdd=true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -