📄 cdatams.cpp
字号:
//
////////////////////////////////////////////////////////////////////////////
void CDataMs::DCHPowerControl(void)
{
/* //for compile
CStdioFile f;
char buf[50];
// 打开数据文件准备写
if(!f.Open("DCHPowerControlFile.txt",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite))
{
#ifdef _DEBUG
afxDump<<"Unable to open file"<<"\n"; //异常处理
#endif
}
f.SeekToEnd();
f.WriteString("DCH信道功率控制函数: 当前时隙为:");
_itoa(m_pMsManager->m_iSlotCurrentNum,buf,10);
f.WriteString(buf);
f.WriteString("移动台标号为:");
_itoa(m_iMsID,buf,10);
f.WriteString(buf);
f.WriteString("\n扇区 移动台C2I 功控前DCH功率 功率变化量 功控后DCH功率 \n");
*/
////获取当前时隙业务信道C2I
float fCurrentC2IindB = m_fSlotC2IindB[ m_pstTFI-> iTTISlotNum - m_iSlotNumRemained];
//获取功率控制步长
//notice 这里暂时没有考虑功率控制的误差
float fPowerDelta = POWERCONTROLSTEP;
if( fCurrentC2IindB > m_pstRate->fTargetC2I )
{
fPowerDelta *= (-1);
}
float frv=xUniform(0.0,1.0); //产生一个(0,1)分布的随机数,用来模拟功控误差
if( frv<BEROfPC )
{
fPowerDelta*=(-1); //功控出错
}
//设定判断当前TTI内功率控制是否成功的标志
bool bIsPCEffective = true;
////对激活集中导频进行功率控制
POSITION postemp;
postemp = m_ActiveSetList.GetHeadPosition();
ACTIVESECTOR_TYPE *ptempActiveSector = NULL;
float ftempActiveSecPowerindB = 0.0;
float ftempActiveSecPower = 0.0; //记录DCH信道可能发射功率的变量
while( postemp != NULL )
{
//获取激活集中扇区指针
ptempActiveSector = m_ActiveSetList.GetNext( postemp );
//修改功控失败标志,判断标准是上一时隙下行链路有扇区达到满功率发射的时候仍未达到功率控制目标值
if( ( ptempActiveSector->fTrafficPower == MAXDCHPOWER )
&& ( fCurrentC2IindB < m_pstRate->fTargetC2I )
&& ( m_pMsManager->m_iSlotCurrentNum > INITIALSLOT ) )
bIsPCEffective = false;
//计算功率控制后DCH信道可能的发射功率
ftempActiveSecPowerindB = ( float ) ( 10*( log10( ptempActiveSector->fTrafficPower ) ) );
ftempActiveSecPowerindB += fPowerDelta;
ftempActiveSecPower = ( float ) pow( 10, ftempActiveSecPowerindB/10 );
//获取当前激活扇区能够提供的功率余量
float ftempDCHPowerMargin = 0.0; //保存功率余量的临时变量
SECTORID_TYPE sttempSectorID = m_aMonitorSector[ ptempActiveSector-> iIndexInMonitor ].stSectorID;
CSector *ptempSector = m_pServiceArea->GetSector( sttempSectorID ); //获取当前扇区指针
ftempDCHPowerMargin = ptempSector->GetDCHAvailablePower();
/* //for compile
f.WriteString("(");
_gcvt(ptempSector->GetParentCellID().m,8,buf);
f.WriteString(buf);
f.WriteString(",");
_gcvt(ptempSector->GetParentCellID().n,8,buf);
f.WriteString(buf);
f.WriteString(",");
_gcvt(ptempSector->GetSectorIndex(),8,buf);
f.WriteString(buf);
f.WriteString(")\t");
_gcvt(fCurrentC2IindB,8,buf);
f.WriteString(buf);
f.WriteString("\t");
_gcvt(ptempActiveSector->fTrafficPower,8,buf);
f.WriteString(buf);
f.WriteString("\t");
//end of for compile
*/
//增加对DCH信道最大可用功率的限制
if( ftempActiveSecPower > MAXDCHPOWER)
ftempActiveSecPower = MAXDCHPOWER;
//判断当前激活集中扇区是否能够提供功控所需功率
float ftempDCHPowerDelta = ftempActiveSecPower - ptempActiveSector->fTrafficPower; //需要改变的功率增量
if( ftempDCHPowerMargin > ftempDCHPowerDelta )
{
/* _gcvt(ftempDCHPowerDelta,8,buf);
f.WriteString(buf);
f.WriteString("\t");
_gcvt(ftempActiveSecPower,8,buf);
f.WriteString(buf);
f.WriteString("\n");
*/
////扇区的发射功率允许功率控制的余量
//修改激活集业务信道的功率,实现功率控制
ptempActiveSector->fTrafficPower = ftempActiveSecPower;
//notice 这里实现了对扇区发射功率的动态修改
//修改激活集中扇区DCH信道功率和扇区总的发射功率
float fSectorDCHPower = ptempSector->GetTotalDCHPower() + ftempDCHPowerDelta;
ptempSector->SetTotalDCHPower(fSectorDCHPower);
//修改扇区DCH信道可用的发射功率
float fSectorAvailableDCHPower = ptempSector->GetDCHAvailablePower() - ftempDCHPowerDelta;
ptempSector->SetDCHAvailablePower(fSectorAvailableDCHPower);
//修改扇区发射功率
ptempSector->TxPowerUpdate();
}
else
{
/* _gcvt(0.0,8,buf);
f.WriteString(buf);
f.WriteString("\t");
_gcvt(ptempActiveSector->fTrafficPower,8,buf);
f.WriteString(buf);
f.WriteString("\n");
*/
////扇区的发射功率不能够提供功率控制的余量
}
//notice 这里是否需要有DCH信道功率的最大值、最小值
}
//在初始化时间之后增加功控失败计时器
if( (bIsPCEffective == false) && (m_pMsManager->m_iSlotCurrentNum > INITIALSLOT) )
m_iPowCrtlFailedTimer++;
}
/////////////////////////////////////////////////////////////////////////
//
// TITLE: 释放DCH信道功率函数
//
// PURPOSE: HTTP移动台下行DCH数据量为空的时候需要释放DCH信道
//
// SAMPLE CALL: pHttpDataMs->ReleaseDCHPower(void)
//
// CALLED BY FUNCTIONS: CMsManager::DCHMsListProcess()
//
// CALLING FUNCTIONS:
//
// AUTHOR: Chen Meiya
//
// DATE: 09/04(MM/YY)
//
// MODIFICATIONS SINCE
//
////////////////////////////////////////////////////////////////////////////
void CDataMs::ReleaseDCHPower(void)
{
POSITION postemp;
postemp = m_ActiveSetList.GetHeadPosition();
ACTIVESECTOR_TYPE *ptempActiveSector = NULL;
CSector *pSector = NULL;
float ftempActiveSecPowerindB = 0.0;
float ftempActiveSecPower = 0.0;
float fSectorDCHPower;
float fSecDCHAvailablePower;
while( postemp != NULL )
{
//获取当前激活扇区的DCH信道功率
ptempActiveSector = m_ActiveSetList.GetNext( postemp );
ftempActiveSecPowerindB = ( float ) ( 10*( log10( ptempActiveSector->fTrafficPower ) ) );
ftempActiveSecPower = ( float ) pow( 10, ftempActiveSecPowerindB/10 );
//释放当前激活扇区的DCH信道功率
pSector = m_pServiceArea->GetSector(ptempActiveSector->stSectorID);
fSectorDCHPower = pSector->GetTotalDCHPower();
fSectorDCHPower -= ftempActiveSecPower;
pSector->SetTotalDCHPower(fSectorDCHPower);
//New added
pSector->TxPowerUpdate();
fSecDCHAvailablePower = pSector->GetDCHAvailablePower();
fSecDCHAvailablePower += ftempActiveSecPower;
pSector->SetDCHAvailablePower(fSecDCHAvailablePower);
delete ptempActiveSector;
}
m_ActiveSetList.RemoveAll();
}
//e数据统计相关方法
/////////////////////////////////////////////////////////////////////////
//
// TITLE: 服务相关统计量计算函数
//
// PURPOSE: 对数据移动台要计算其业务相关的统计量
//
// SAMPLE CALL: pDataMs->ServiceStatistics(void)
//
// CALLED BY FUNCTIONS:
//
// CALLING FUNCTIONS:
//
// AUTHOR: Chen Meiya
//
// DATE: 09/04(MM/YY)
//
//
/////////////////////////////////////////////////////////////////////////
void CDataMs::SerivceStatisticsCalculate()
{
////计算移动台吞吐量
//对于FTP移动台和HTTP移动台要分别计算
//FTP没有分组到达过程,吞吐量=(成功接收比特数)/仿真时间;
//HTTP有分组到达过程,吞吐量即是分组呼叫的吞吐量 = (成功接收比特数)/分组呼叫累计时延。
if( m_enTrafficType == FTP)
{
//by zl 20050426
//m_fServiceThrput = float(m_lTotalSucfulBitNum/(m_pMsManager->m_fDropTime - INITIALSLOT*SlotSize));
m_fServiceThrput = float(m_lTotalSucfulBitNum/m_pMsManager->m_fDropTime);
}
else if( (m_enTrafficType == HTTP) && (m_lTotalSucfulBitNum > 0) )
{
m_fPacketCallThrput =float (m_lTotalSucfulPCBitNum/(m_iPacketCallDelay*m_pMsManager->m_fSlotTime - INITIALSLOT*SlotSize));
m_fServiceThrput = m_fPacketCallThrput;
//计算HTTP移动台Active Session Throughput
m_fAST = float((double)m_lTotalSucfulBitNum/(double)(m_iASTTimer * SlotSize));
//计算HTTP移动台平均分组时延
m_fAveragePacketDelay = (m_iTotalPacketDelay*m_pMsManager->m_fSlotTime)/(m_iTotalSucfulPacketNum+m_iTotalFailedPacketNum);
//计算HTTP移动台平均分组呼叫时延
m_fAveragePCDelay = (m_iPacketCallDelay*m_pMsManager->m_fSlotTime) / m_iPacketCallNum;
}
else if( m_enTrafficType == VIDEO) //20060116
{
m_fServiceThrput = float(m_lTotalSucfulBitNum/(m_pMsManager->m_fDropTime - INITIALSLOT*SlotSize));
//m_fServiceThrput = float(m_lTotalSucfulBitNum/m_pMsManager->m_fDropTime);
}
}
/////////////////////////////////////////////////////////////////////////
//
// TITLE: 最近服务扇区距离计算函数
//
// PURPOSE: 计算移动台和当前服务扇区中最近扇区的距离
//
// SAMPLE CALL: pDataMs->CloestSectorDistance(void)
//
// CALLED BY FUNCTIONS:
//
// CALLING FUNCTIONS:
//
// AUTHOR: Chen Meiya
//
// DATE: 09/04(MM/YY)
//
//
////////////////////////////////////////////////////////////////////////////
void CDataMs::ClosestSectorDistance(void)
{
float fDistance;
//计算移动台和服务扇区之间的最短距离
if( m_enTrafficType == DCHData )
{
if( m_bIsAdmitted == true )
{
POSITION pos;
ACTIVESECTOR_TYPE *pActiveSec;
SECTORID_TYPE tempSecID;
m_fClosestServingSecDistance = 10000.0;
pos = m_ActiveSetList.GetHeadPosition();
while( pos != NULL )
{
pActiveSec = m_ActiveSetList.GetNext(pos);
tempSecID = pActiveSec->stSectorID;
fDistance = m_pMsManager->DistanceCaculte(m_stMsLocation,tempSecID);
if( fDistance < m_fClosestServingSecDistance )
m_fClosestServingSecDistance = fDistance;
}
}
else
{
m_fClosestServingSecDistance = m_pMsManager->DistanceCaculte(m_stMsLocation,m_stBestSector);
}
}
else //HSDSCHData by zl
{
fDistance = m_pMsManager->DistanceCaculte(m_stMsLocation,m_stLocationSector);
m_fClosestServingSecDistance = fDistance;
}
}
/////////////////////////////////////////////////////////////////////////
//
// TITLE: 分组呼叫吞吐量计算函数
//
// PURPOSE: 对HTTP移动台要计算其业务吞吐量
//
// SAMPLE CALL: pHttpDataMs->PCThrputCalculate(void)
//
// CALLED BY FUNCTIONS: CMsManager::DCHMsListProcess()
//
// CALLING FUNCTIONS:
//
// AUTHOR: Chen Meiya
//
// DATE: 04/04(MM/YY)
//
// MODIFICATIONS SINCE 04/04(MM/YY)
//
////////////////////////////////////////////////////////////////////////////
void CDataMs::PCThrputCalculate(void)
{
//计算HTTP移动台的吞吐量
if( m_enTrafficType == HTTP )
{
m_fPacketCallThrput = m_lTotalSucfulPCBitNum/(m_iPacketCallDelay*m_pMsManager->m_fSlotTime);
}
}
/////////////////////////////////////////////////////////////////////////
//
// TITLE: 平均分组时延计算函数
//
// PURPOSE: 计算平均分组时延
//
// SAMPLE CALL: pHttpDataMs->AveragePDelayCalculate(void)
//
// CALLED BY FUNCTIONS: CMsManager::DCHMsListProcess()
//
// CALLING FUNCTIONS:
//
// AUTHOR: Chen Meiya
//
// DATE: 04/04(MM/YY)
//
// MODIFICATIONS SINCE 04/04(MM/YY)
//
////////////////////////////////////////////////////////////////////////////
void CDataMs::AveragePDelayCalculate(void)
{ //计算HTTP移动台平均分组时延
if( m_enTrafficType == HTTP )
{
m_fAveragePacketDelay = (m_iTotalPacketDelay*m_pMsManager->m_fSlotTime)/(m_iTotalSucfulPacketNum+m_iTotalFailedPacketNum);
}
}
/////////////////////////////////////////////////////////////////////////
//
// TITLE: 平均分组呼叫时延计算函数
//
// PURPOSE: 计算平均分组呼叫时延
//
// SAMPLE CALL: pHttpDataMs->AveragePCDelayCalculate(void)
//
// CALLED BY FUNCTIONS: CMsManager::DCHMsListProcess()
//
// CALLING FUNCTIONS:
//
// AUTHOR: Chen Meiya
//
// DATE: 04/04(MM/YY)
//
// MODIFICATIONS SINCE 04/04(MM/YY)
//
////////////////////////////////////////////////////////////////////////////
void CDataMs::AveragePCDelayCalculate(void)
{ //计算HTTP移动台平均分组呼叫时延
if( m_enTrafficType == HTTP )
{
m_fAveragePCDelay = (m_iPacketCallDelay*m_pMsManager->m_fSlotTime) / m_iPacketCallNum;
}
}
/////////////////////////////////////////////////////////////////////////
//
// TITLE: 数据移动台业务吞吐量计算函数
//
// PURPOSE: 计算数据移动台业务吞吐量
//
// SAMPLE CALL: pHttpDataMs->ServiceThrputCalculate(void)
//
// CALLED BY FUNCTIONS: CMsManager::DCHMsListProcess()
//
// CALLING FUNCTIONS:
//
// AUTHOR: Chen Meiya
//
// DATE: 04/04(MM/YY)
//
// MODIFICATIONS SINCE 04/04(MM/YY)
//
////////////////////////////////////////////////////////////////////////////
void CDataMs::ServiceThrputCalculate(void)
{
//计算移动台吞吐量
m_fServiceThrput = m_lTotalSucfulBitNum/m_pMsManager->m_fDropTime;
}
///////////////////////////////////////////////////////////////////////////////
//接口函数的实现
//////////////////////////////////////////////////////////////////////////////
////设置导频强度门限
void CDataMs::SetPilotStrenThreshold(float fThreshold)
{
m_fPilotStrenThreshold = fThreshold;
}
////设置导频强度门限滞后
void CDataMs::SetPilotStrenHyst(float fHyst)
{
m_fPilotStrenHyst = fHyst;
}
////返回最佳扇区计时器取值
int CDataMs::GetBestSecTimer(void)
{
return m_iBestSecTimer;
}
////设置最佳扇区计时器取值
void CDataMs::SetBestSecTimer(int iTimer)
{
m_iBestSecTimer = iTimer;
}
////获取移动台是否被block的标志
bool CDataMs::IsBlocked(void)
{
return m_bIsBlocked;
}
////设定移动台是否被block的标志
void CDataMs::SetIsBlocked( bool pIsBlocked )
{
m_bIsBlocked = pIsBlocked;
}
//在基类中已经定义
////设定移动台是否成功接纳的标志
void CDataMs::SetIsAdmitted(bool btemp)
{
m_bIsAdmitted = btemp;
}
////获取移动台是否已经加入成功接纳DCH移动台队列的标志
bool CDataMs::IsInAdmittedList(void)
{
return m_bIsInAdmittedList;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -