⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cvoicems.cpp

📁 这是cdma2000的一个分组调度算法实例
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//////////////////////////////////////////////////////////////////////////
//                        for Evaluation Project						//
//                          Mobile User Team							//
//                      BUPT Radio Research Center						//
//////////////////////////////////////////////////////////////////////////
//																		//
//                          CVoiceMs.CPP								//
//																		//
//////////////////////////////////////////////////////////////////////////
//																		//
// 话音移动台类CVoiceMs的成员函数的声明									//
//																		//
//																		//
// Ref. documents:														//
//          "1xEV-DV仿真程序类的初步定义"								//
//																		//
// Written by:    CAI Qi-ming											//
//																		//
// Rev. date:     20010320 (yyyymmdd)									//
//																		//
// What's NEW:															//
//																		//
//////////////////////////////////////////////////////////////////////////


#include "CVoiceMs.h"
#include "systemsim.h"
#include "iostream.h"
#include "sys_random.h"
#include "CMsManager.h"


//////////////////////////////////////////////////////////////////////////
//								  构造函数,							//
//                          将各属性赋予初始值							//
//////////////////////////////////////////////////////////////////////////
CVoiceMs::CVoiceMs()
{
}
//end of CVoiceMs()


//////////////////////////////////////////////////////////////////////////
//								 析构函数								//
//							   释放内存空间								//
//////////////////////////////////////////////////////////////////////////
CVoiceMs::~CVoiceMs()
{
	Clean();
}
//end of ~CVoiceMs()


//////////////////////////////////////////////////////////////////////////
//							话音MS初始化函数							//
//             初始化m_iServiceLength、m_bIsServiceActive				//
//             并调用最佳扇区选择函数,计算出最佳扇区,					//
//             调用激活集初始化函数,设定激活集							//
//             随机初始化激活集的业务信道功率							//
//////////////////////////////////////////////////////////////////////////
void   CVoiceMs::VoiceInitialization()
{
	Random R;
	float fRand;

	fRand=R.Next();
	m_fVoiceActiveFactor=m_pMsManager->m_fVoiceActiveFactor;
	//话音激活因子初始化
	m_iSHOMsgNum=0;                     //当前软切换消息队列长度初始化
	m_iDropTimer=0;                     //掉话计时器赋初值
	m_iUnsatisfiedTimer=0;              //不满意计时器赋初值
//	m_bIsServiceActive=true;            //设置话音激活标志为true
	m_iServiceTime=(int)(xExponent(MeanCallLength)*1000/(1.25*16)); 
	//服务时长一直不变(以帧为单位)
	m_iServiceLength=480000+INITIALSLOT;//m_iServiceTime*16; 
	//参数为平均呼叫时长120s(用slot数表示)
	m_fMeanC2I=0;
//	m_iFwdFrameRate=FULL_RATE;          //前向信道帧速率初始化为全速率
	m_cFwdMarkovState.initRan(m_iMsID); //Markov状态初始化(入口参数为移动台标号)
//	m_fFwdCurrentActiveFactor=1.0;      //本slot话音激活因子为1
//	m_fFwdLastActiveFactor=1.0;         //上一slot话音激活因子为1
	if(fRand<0.2921)
	{
		m_fFwdCurrentActiveFactor=1.0;      //本slot话音激活因子为1
		m_fFwdLastActiveFactor=1.0;         //上一slot话音激活因子为1
		m_iFwdFrameRate=FULL_RATE;
	}
	else if((0.2921<=fRand)&&(fRand<0.3303))
	{
		m_fFwdCurrentActiveFactor=0.5;      //本slot话音激活因子为0.5
		m_fFwdLastActiveFactor=0.5;         //上一slot话音激活因子为0.5
		m_iFwdFrameRate=HALF_RATE;
	}
	else if((0.3303<=fRand)&&(fRand<0.4029))
	{
		m_fFwdCurrentActiveFactor=0.25;      //本slot话音激活因子为0.25
		m_fFwdLastActiveFactor=0.25;         //上一slot话音激活因子为0.25
		m_iFwdFrameRate=QUARTER_RATE;
	}
	else
	{
		m_fFwdCurrentActiveFactor=0.125;      //本slot话音激活因子为0.125
		m_fFwdLastActiveFactor=0.125;         //上一slot话音激活因子为0.125
		m_iFwdFrameRate=EIGHTH_RATE;
	}
	m_bIsSHOOut=false;

	//...... added by cqm, Apr.9 .......//
	m_fMeanC2IofLastFrame=0;
	m_iBadFrameCounter=0;
	m_bIsFrameCorrect=true;
	bsFrameErrorFlagSet.set(); //初始化为帧全部正确
	m_iFERIndicator=0;
	m_pfC2IIndex=&(m_pMsManager->m_fC2IIndex[0]);      //前向链路C/I指针
	switch(int(m_fMsVelocity+1e-6))          //确定功控的目标
	{
		case 0 : 
			m_fC2ITarget=-(float)17.4;
			m_pfFER=&(m_pMsManager->m_fFER_0[0]); //前向链路FER指针
			break;
		case 3 : 
			m_fC2ITarget=-(float)16.45;
			m_pfFER=&(m_pMsManager->m_fFER_3[0]);
			break;
		case 10 :
			m_fC2ITarget=-(float)16.8;
			m_pfFER=&(m_pMsManager->m_fFER_30[0]);
			break; 
		case 30 : 
			m_fC2ITarget=-(float)16.8;
			m_pfFER=&(m_pMsManager->m_fFER_30[0]);
			break;
		case 120 : 
			m_fC2ITarget=-(float)17.;
			m_pfFER=&(m_pMsManager->m_fFER_100[0]);
			break;
	}
	//..................................//

	ObtainBestSector();                  //找出最佳扇区
	InitActiveSet();                     //初始化激活集
	ObtainC2I();                         //获得当前时隙的C/I
}
//end of VoiceInitialization()


//////////////////////////////////////////////////////////////////////////
//						 激活集初始化函数								//
//     根据最佳基站的导频信噪比,扫描候选集中其他扇区的导频信噪比		//
//            确定激活集扇区、业务信道功率和信噪比						//
//////////////////////////////////////////////////////////////////////////
void   CVoiceMs::InitActiveSet()
{                                   //定义必要的变量
	int i,j;                        //循环所需变量
//	int iVoiceNumInSys;             //系统中的用户数,单位:个
	int iBestSectorIndex;			//激活集中最佳基站
	float fOrthogonalFactor;        //正交因子
	float fFastFading;
//	float fTempTxPower;             //临时发射功率,单位:mw
	float fOtherChannelPower;       //本扇区其他信道的干扰,单位:mw
	float fMaxTrafficPower;         //最大业务信道功率,单位:mw
	float fMinTrafficPower;         //业务信道功率动态范围(最小值)
	float fC2ITarget;               //目标C/I
	//...... added by cqm, Apr.9 ......//
	bool bFlag=false;
	//.................................//
	ACTIVESECTOR_TYPE* pTempActiveSector=NULL;   //临时激活扇区指针


	m_iActiveSetSize=0;             //激活集链表初值是零
	//test by cqm
	if(m_fBestPilotSNR<-16)
	{
		m_iServiceLength=16;//等效为服务到时,重新初始化一个(即认为软切换出去了)
		m_bIsSHOOut=true;
	}


	switch(m_iFwdFrameRate)
	{
		case FULL_RATE : fC2ITarget=/*m_pMsManager->*/m_fC2ITarget;
			break;
		case HALF_RATE : fC2ITarget=/*m_pMsManager->*/m_fC2ITarget-(float)3.0;
			break;
		case QUARTER_RATE : fC2ITarget=/*m_pMsManager->*/m_fC2ITarget-(float)6.0;
			break;
		case EIGHTH_RATE : fC2ITarget=/*m_pMsManager->*/m_fC2ITarget-(float)9.0;
			break; 
	}
//	if(m_iMsID==10)
//		cout<<"wait"<<endl;
	//...... added by cqm, May.22 ......//
	for(i=0;i<6+SectorNumber;i++)   //对候选扇区进行循环(共九个)
	{
		if(m_fBestPilotSNR-m_aCandidateSector[i].fPilotSNR==0)   
		//最佳扇区的导频信噪比和当前扇区的导频信噪比之差小于门限3dB?
		{
			iBestSectorIndex=i;
			if(m_iActiveSetSize<m_pMsManager->m_iActiveSetMaxSize) 
			//如果激活集未满
			{
				pTempActiveSector=new ACTIVESECTOR_TYPE;      
				//产生一个新的激活集结构体
				pTempActiveSector->stSectorID=
					m_aCandidateSector[i].stSectorID; //扇区标号赋初值
				pTempActiveSector->iIndexInCandidate=i;
				//在候选集中的标号赋初值
				fMaxTrafficPower=
					m_pMsManager->m_fMaxFractionOfTrafficPower
					*m_pServiceArea->
					GetSector(pTempActiveSector->stSectorID)->
					GetMaxPower();     //业务信道最大发射功率
				for(j=0;j<19*SectorNumber;j++)
					if((m_aNeighborSector[j].stSectorID.stCellID.m
						==m_aCandidateSector[i].stSectorID.stCellID.m)
						&&(m_aNeighborSector[j].stSectorID.stCellID.n
						==m_aCandidateSector[i].stSectorID.stCellID.n)
						&&(m_aNeighborSector[j].stSectorID.s
						==m_aCandidateSector[i].stSectorID.s))  
						//找到当前候选扇区在相邻集中的位置
					{
						fC2ITarget=
							(float)pow(10,(/*m_pMsManager->*/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(pTempActiveSector->stSectorID)->
							GetTxPower()
							*m_aNeighborSector[j].fPropagationLoss*fFastFading;
						pTempActiveSector->fTrafficPower=
							(float)(fC2ITarget*
							(m_aCandidateSector[i].fInterferenceFromOtherSector
							+fOtherChannelPower*fOrthogonalFactor
							+NoisePower)/(m_aNeighborSector[j].fPropagationLoss*fFastFading));
						//业务信道发射功率赋初值,公式参考UpAndDown里的公式
						if(pTempActiveSector->fTrafficPower>fMaxTrafficPower)    
						//如果算出来的功率大于功率最大值
							pTempActiveSector->fTrafficPower=fMaxTrafficPower;    
						//则将业务信道功率赋最大值
						fMinTrafficPower=
							(float)(fMaxTrafficPower
							/pow(10,(m_pMsManager->m_fDynamicRangeOfTrafficPower/10)));  
						//将dB转化为mw
						if(pTempActiveSector->fTrafficPower<fMinTrafficPower)    
						//如果业务信道功率小于最小值
							pTempActiveSector->fTrafficPower=fMinTrafficPower;
						//就将业务信道功率置为最小值


						m_pServiceArea->
							GetSector(m_aCandidateSector[i].stSectorID)->
							VoicePowerCumulate(pTempActiveSector->fTrafficPower);
						//将功率累加进去
						break;            //计算完后跳出循环
					}
				pTempActiveSector->fTrafficC2I=/*m_pMsManager->*/10*log10(fC2ITarget);///////////
				//下行业务信道C/I赋初值,单位:dB
				//(等执行UpdateActiveSet时再计算C/I)

				m_ActiveSetList.AddTail(pTempActiveSector);       
				//将该扇区加入激活集链表
				m_aCandidateSector[i].bIsInActive=true;          
				//该候选扇区是在激活集中
				m_iActiveSetSize++;                               
				//更新激活集链表长度
				if((pTempActiveSector->stSectorID.stCellID.m!=3)||(pTempActiveSector->stSectorID.stCellID.n!=3))
					bFlag=true;
			} 
			else                           //如果激活集已满
				break;                     //结束循环
		}	
	}
	//................................//


	for(i=0;i<6+SectorNumber;i++)   //对候选扇区进行循环(共九个)
	{
		if((m_fBestPilotSNR-m_aCandidateSector[i].fPilotSNR<6)&&(iBestSectorIndex!=i)&&(m_aCandidateSector[i].fPilotSNR>-16))   
		//最佳扇区的导频信噪比和当前扇区的导频信噪比之差小于门限3dB?
		{
			if(m_iActiveSetSize<m_pMsManager->m_iActiveSetMaxSize)
			//如果激活集未满
			{
				pTempActiveSector=new ACTIVESECTOR_TYPE;      
				//产生一个新的激活集结构体
				pTempActiveSector->stSectorID=
					m_aCandidateSector[i].stSectorID; //扇区标号赋初值
				pTempActiveSector->iIndexInCandidate=i;
				//在候选集中的标号赋初值
				fMaxTrafficPower=
					m_pMsManager->m_fMaxFractionOfTrafficPower
					*m_pServiceArea->
					GetSector(pTempActiveSector->stSectorID)->
					GetMaxPower();     //业务信道最大发射功率
				for(j=0;j<19*SectorNumber;j++)
					if((m_aNeighborSector[j].stSectorID.stCellID.m
						==m_aCandidateSector[i].stSectorID.stCellID.m)
						&&(m_aNeighborSector[j].stSectorID.stCellID.n
						==m_aCandidateSector[i].stSectorID.stCellID.n)
						&&(m_aNeighborSector[j].stSectorID.s
						==m_aCandidateSector[i].stSectorID.s))  
						//找到当前候选扇区在相邻集中的位置
					{
//						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(pTempActiveSector->stSectorID)->
							GetTxPower()
							*m_aNeighborSector[j].fPropagationLoss*fFastFading;
						pTempActiveSector->fTrafficPower=
							(float)(fC2ITarget*
							(m_aCandidateSector[i].fInterferenceFromOtherSector
							+fOtherChannelPower*fOrthogonalFactor
							+NoisePower)/(m_aNeighborSector[j].fPropagationLoss*fFastFading));
						//业务信道发射功率赋初值,公式参考UpAndDown里的公式
						if(pTempActiveSector->fTrafficPower>fMaxTrafficPower)    
						//如果算出来的功率大于功率最大值
							pTempActiveSector->fTrafficPower=fMaxTrafficPower;    
						//则将业务信道功率赋最大值
						fMinTrafficPower=
							(float)(fMaxTrafficPower
							/pow(10,(m_pMsManager->m_fDynamicRangeOfTrafficPower/10)));  
						//将dB转化为mw
						if(pTempActiveSector->fTrafficPower<fMinTrafficPower)    
						//如果业务信道功率小于最小值
							pTempActiveSector->fTrafficPower=fMinTrafficPower;
						//就将业务信道功率置为最小值


						m_pServiceArea->
							GetSector(m_aCandidateSector[i].stSectorID)->
							VoicePowerCumulate(pTempActiveSector->fTrafficPower);
						//将功率累加进去
						break;            //计算完后跳出循环
					}
				pTempActiveSector->fTrafficC2I=/*m_pMsManager->*/10*log10(fC2ITarget);/////////////
				//下行业务信道C/I赋初值,单位:dB
				//(等执行UpdateActiveSet时再计算C/I)

				m_ActiveSetList.AddTail(pTempActiveSector);       
				//将该扇区加入激活集链表
				m_aCandidateSector[i].bIsInActive=true;          
				//该候选扇区是在激活集中
				m_iActiveSetSize++;                               
				//更新激活集链表长度
				//...... added by cqm, Apr.9 ......//
				if((pTempActiveSector->stSectorID.stCellID.m!=3)||(pTempActiveSector->stSectorID.stCellID.n!=3))
					bFlag=true;
				//.................................//
			} 
			else                           //如果激活集已满
				break;                     //结束循环
		}	
	}
	//...... added by cqm, Apr.9 ......//
	if((bFlag==true)&&(m_iActiveSetSize==1))//如果激活集里面只有一个扇区而且不是(3,3)扇区
	{
		m_iServiceLength=16;//等效为服务到时,重新初始化一个(即认为软切换出去了)
		m_bIsSHOOut=true;
	}
		//.................................//
//	UpdateActiveSet();                     //更新激活集(计算C/I)
//由于函数UpdateActiveSet()考虑了话音激活的影响,
//在这里调用会引起程序的错误,而程序现在也引入了初始化的一段时间

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -