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

📄 cvoicems.cpp

📁 这是cdma2000的一个分组调度算法实例
💻 CPP
📖 第 1 页 / 共 4 页
字号:
			//(本扇区的业务信道接受功率
			///(本扇区其他信道的干扰值*正交因子+其他扇区的干扰值+热噪声))
			//并转化为dB
		m_ActiveSetList.GetNext(posTemp);   //获得链表中的下一个激活扇区
	}
}
//end of UpdateActiveSet()


///////////////////////////////////////////////////
//               功率控制函数,
//根据计算得到的C/I与功率控制目标C/I的关系,
//调整激活集内各个扇区的发射功率。需要考虑功控误差。
///////////////////////////////////////////////////
void   CVoiceMs::PowerControl()
{                                 //定义必要的变量        
	float fPowerDelta=(float)(-1*m_pMsManager->m_fPowerControlStep);  
	//业务信道功率增量,单位:dB
	float fMinTrafficPower;       //业务信道最小值,单位:mw
	float fTotalC2I=0;            //总的C/I,初值为零
	float frv;                    //(0,1)分布的随机数
	float fTempTrafficPower;      //业务信道功率,单位:dBm
	float fTargetC2I;
	POSITION posTemp;             //临时位置指针
	CSector* pTempSector=NULL;    //临时扇区指针


	fTotalC2I=m_fC2I;                            //获得当前时隙的C/I
	switch(m_iFwdFrameRate)
	{
		case FULL_RATE : fTargetC2I=/*m_pMsManager->*/m_fC2ITarget;
			break;
		case HALF_RATE : fTargetC2I=/*m_pMsManager->*/m_fC2ITarget-(float)3.0;
			break;
		case QUARTER_RATE : fTargetC2I=/*m_pMsManager->*/m_fC2ITarget-(float)6.0;
			break;
		case EIGHTH_RATE : fTargetC2I=/*m_pMsManager->*/m_fC2ITarget-(float)9.0;
			break;
	}

	if(fTotalC2I<=fTargetC2I) 
	//如果当前时隙的C/I小于目标C/I
		fPowerDelta*=(-1);//调整步长为正(增加)
	frv=xUniform(0.0,1.0);//产生一个(0,1)分布的随机数,用来模拟功控误差
	if(frv<m_pMsManager->m_fBEROfPC)
	//如果随机数小于功控比特差错概率
		fPowerDelta*=(-1);//功控出错,原来的加变成了减

	posTemp=m_ActiveSetList.GetHeadPosition();    
	//取得链表头,并令临时指针指向链表头
	while(posTemp!=NULL)           //到达链表尾则结束循环
	{
		pTempSector=
			m_pServiceArea->GetSector(m_ActiveSetList.GetAt(posTemp)->stSectorID);   
		//获得激活扇区的指针
		fTempTrafficPower=
			(float)(10*log10(m_ActiveSetList.GetAt(posTemp)->
			fTrafficPower));

		fTempTrafficPower+=fPowerDelta;   //调整业务信道功率值
		m_ActiveSetList.GetAt(posTemp)->fTrafficPower=
			(float)(pow(10,(fTempTrafficPower/10)));
		if(m_ActiveSetList.GetAt(posTemp)->fTrafficPower>
			pTempSector->GetMaxPower()
		    *m_pMsManager->m_fMaxFractionOfTrafficPower)       
		//如果业务信道功率大于最大值
			m_ActiveSetList.GetAt(posTemp)->fTrafficPower=
				pTempSector->GetMaxPower()*m_pMsManager->
				m_fMaxFractionOfTrafficPower;       
			//就将业务信道功率置为最大值
		fMinTrafficPower=
			(float)((pTempSector->GetMaxPower()*
			m_pMsManager->m_fMaxFractionOfTrafficPower)
			/pow(10,(m_pMsManager->m_fDynamicRangeOfTrafficPower/10)));  
		//将dB转化为mw
		if(m_ActiveSetList.GetAt(posTemp)->fTrafficPower<
			fMinTrafficPower)         
		//如果业务信道功率小于动态范围
			m_ActiveSetList.GetAt(posTemp)->fTrafficPower=
				fMinTrafficPower;       
			//就将业务信道功率置为最小值(动态范围)
		m_ActiveSetList.GetNext(posTemp); 
		//获得链表的下一个激活扇区结构
	}
}
//end of PowerControl()


//////////////////////////////////////////////////////////////////////////
//						 话音激活特性设置函数,							//						
//				根据话音激活因子,设置话音激活标志。					//
//////////////////////////////////////////////////////////////////////////
void   CVoiceMs::SetVoiceActivity()
{                                    //定义必要的变量
	m_fFwdLastActiveFactor=m_fFwdCurrentActiveFactor;
	if(m_iSlotCount%16==1)//modified by cqm, May.14
	{
		m_iFwdFrameRate=m_cFwdMarkovState.GetNextState()%4;
		switch(m_iFwdFrameRate)
		{
			case FULL_RATE : m_fFwdCurrentActiveFactor=1.0;
				 break;
			case HALF_RATE : m_fFwdCurrentActiveFactor=0.5;
				 break;
			case QUARTER_RATE : m_fFwdCurrentActiveFactor=0.25;
				 break;
			case EIGHTH_RATE : m_fFwdCurrentActiveFactor=0.125;
				 break;
		}
	}
}
//end of SetVoiceActivity()


//////////////////////////////////////////////////////////////////////////
//					服务时长到时的判断函数,							//
//				判断服务时长是否到时,到时返回TRUE。					//
//////////////////////////////////////////////////////////////////////////
bool   CVoiceMs::IsServiceOver()
{
	if(m_iServiceLength<=0)      //如果服务到时
		return true;             //返回true
	else 
		return false;            //返回false
}
//end of IsServiceOver()


//////////////////////////////////////////////////////////////////////////
//						更新激活集功率函数,							//
//						得到激活集的总功率								//
//////////////////////////////////////////////////////////////////////////
void CVoiceMs::UpdateActiveSetPower()
{                           //定义必要的变量
	POSITION posTemp;       //位置变量
	ACTIVESECTOR_TYPE* pTempActiveSector=NULL;//临时激活扇区结构体
	CSector* pSector=NULL;  //扇区指针
	float fTempPower;       //临时功率,单位:mw

	posTemp=m_ActiveSetList.GetHeadPosition();//获得链表头指针
	while(posTemp!=NULL)                //到达链表尾则结束循环
	{
		pTempActiveSector=m_ActiveSetList.GetNext(posTemp);
		//获得当前激活扇区
		fTempPower=pTempActiveSector->fTrafficPower;//获得功率值
		pSector=
			m_pServiceArea->GetSector(pTempActiveSector->stSectorID);
		//得到扇区指针
		pSector->VoicePowerCumulate(fTempPower);  //累加话音业务总功率
	}
}
//end of UpdateActiveSetPower()


void CVoiceMs::Clean()
{
	POSITION posTemp;                    //临时位置指针
	
	
	posTemp=m_ActiveSetList.GetHeadPosition();      //取得链表的头指针
	while(posTemp!=NULL)                            //到链表尾则结束循环
	{
		delete m_ActiveSetList.GetNext(posTemp);    //释放内存
	}
	m_ActiveSetList.RemoveAll();                    //移去指针

	posTemp=m_SoftHandoffMessageList.GetHeadPosition(); //取得链表的头指针
	while(posTemp!=NULL)                            //到链表尾则结束循环
	{
		delete m_SoftHandoffMessageList.GetNext(posTemp);//释放内存
	}
	m_SoftHandoffMessageList.RemoveAll();           //移去指针	
}
//end of Clean()


//...... added by cqm, Apr.9 ......//
//FER预测函数,根据接收到的Eb/Nt值,查短期FER vs Eb/Nt表得到当前用户的FER
void CVoiceMs::FERPrediction()
{
	float x1,x2,y1,y2,x,y;


	switch(m_iFwdFrameRate)
	{
		case HALF_RATE : m_fMeanC2IofLastFrame+=3.;
			break;
		case QUARTER_RATE : m_fMeanC2IofLastFrame+=6.;
			break;
		case EIGHTH_RATE : m_fMeanC2IofLastFrame+=9.;
			break;
		default : break;
	}
	for (int ii=1;ii<26;ii++)
	{
		if (m_fMeanC2IofLastFrame<m_pfC2IIndex[ii])
			break;
	}
	if (ii==26)
	{
		x2=m_pfC2IIndex[25];
		y2=(float)log(m_pfFER[25]);
		x1=m_pfC2IIndex[24];
		y1=(float)log(m_pfFER[24]);
	}
	else
	{
		x2=m_pfC2IIndex[ii];
		y2=(float)log(m_pfFER[ii]);
		x1=m_pfC2IIndex[ii-1];
		y1=(float)log(m_pfFER[ii-1]);
	}
	
	x=m_fMeanC2IofLastFrame;
	
	y=((x2-x)*y1+(x-x1)*y2)/(x2-x1);
	m_fFER=(float)exp(y);
}	
//end of FERPrediction()


//帧质量判断函数,判断当前slot话音帧是否正确	
void CVoiceMs::FrameQualityDecision()
{
	Random R;
	float fRand;

	fRand=(float)R.Next();
	if(fRand>m_fFER)
		m_bIsFrameCorrect=true;
	else
		m_bIsFrameCorrect=false;
}
//end of FrameQualityDecision()


//服务质量判断函数,如果短期FER大于15%,m_iFERIndicator加一	
void CVoiceMs::GOSDecision()
{
	float fFER;
//	bsFrameErrorFlagSet <<= 1; //标志位全部左移1位(好像是左移),末位补0
//	if(m_bIsFrameCorrect)    //如果当前帧正确
//		bsFrameErrorFlagSet.flip(0);//末位补1(即代表帧正确)
	
//	uiCountErrorFrame=WindowSize - bsFrameErrorFlagSet.count();//计算窗口中0的个数
//	m_fFER = (float)uiCountErrorFrame/WindowSize;//计算短期误码率
	//for test(cqm)
//	if(m_iMsID==10)
//		cout<<uiCountErrorFrame<<"  "<<WindowSize<<"   "<<m_fFER<<endl;
	//////////////
	if(!m_bIsFrameCorrect)
		m_iBadFrameCounter++;
	if(m_iSlotCount%320==0)
	{
//		if(!m_bIsFrameCorrect)
//			m_iBadFrameCounter++;
		fFER=(float)m_iBadFrameCounter/WindowSize;
		if(fFER>=0.15)
			m_iFERIndicator++;
		m_iBadFrameCounter=0;
	}
}
//end of GOSDecision()


//判断用户是否中断函数,在用户通话结束或drop结束时由CMsManager调用			
//void CVoiceMs::IsUserOutage()
//{
//}
//.................................//


//////////////////////////////////////////////////////////////////////////
//							get(),set()								//
//////////////////////////////////////////////////////////////////////////
//...... added by cqm, Apr.9 ......//
int CVoiceMs::GetFERIndicator()
{
	return m_iFERIndicator;
}
void CVoiceMs::SetFERIndicator(int i_inputFERIndicator)
{
	m_iFERIndicator=i_inputFERIndicator;
}

int CVoiceMs::GetActiveSetSize()
{
	return m_iActiveSetSize;
}

void CVoiceMs::SetActiveSetSize(int i_inputActiveSetSize)       
{
	m_iActiveSetSize=i_inputActiveSetSize;
}

int CVoiceMs::GetServiceLength()
{
	return m_iServiceLength;
}

void CVoiceMs::SetServiceLength(int i_inputServiceLength)       
{
	m_iServiceLength=i_inputServiceLength;
}

int  CVoiceMs::GetServiceTime()
{
	return m_iServiceTime;
}

void  CVoiceMs::SetServiceTime(int i_inputServiceTime)
{
	m_iServiceTime=i_inputServiceTime;
}

int CVoiceMs::GetSHOMsgNum()
{
	return m_iSHOMsgNum;
}

void CVoiceMs::SetSHOMsgNum(int i_inputSHOMsgNum)      
{
	m_iSHOMsgNum=i_inputSHOMsgNum;
}

int CVoiceMs::GetDropTimer()
{
	return m_iDropTimer;
}

void CVoiceMs::SetDropTimer(int i_inputDropTimer)
{
	m_iDropTimer=i_inputDropTimer;
}

int CVoiceMs::GetUnsatisfiedTimer()
{
	return m_iUnsatisfiedTimer;
}
	
void  CVoiceMs::SetUnsatisfiedTimer(int i_inputUnsatisfiedTimer)
{
	m_iUnsatisfiedTimer=i_inputUnsatisfiedTimer;
}

float CVoiceMs::GetVoiceActiveFactor()
{
	return m_fVoiceActiveFactor;
}

void CVoiceMs::SetVoiceActiveFactor(float i_inputVoiceActiveFactor)     
{
	m_fVoiceActiveFactor=i_inputVoiceActiveFactor;
}

float CVoiceMs::GetC2I()
{
	return m_fC2I;
}

void CVoiceMs::SetC2I(float f_inputC2I)       
{
	m_fC2I=f_inputC2I;
}

//bool   CVoiceMs::IsServiceActive()
//得到当前时隙的话音激活标志,TRUE激活
//{
//	return m_bIsServiceActive;
//}

bool   CVoiceMs::IsC2IEnough()
//得到当前C/I是否超过门限值,TRUE为超过
{
	return m_bIsC2IEnough;
}
//end of get and set 
//end of CVoiceMs

⌨️ 快捷键说明

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