diff --git a/src/lte/model/lte-amc.h b/src/lte/model/lte-amc.h index 01a4453c9..3c01fdcdb 100644 --- a/src/lte/model/lte-amc.h +++ b/src/lte/model/lte-amc.h @@ -83,7 +83,6 @@ public: */ static std::vector CreateCqiFeedbacks (const SpectrumValue& sinr); -private: /** * \brief Get a proper CQI for the spectrale efficiency value. * In order to assure a fewer block error rate, the AMC chooses the lower CQI value diff --git a/src/lte/model/lte-common.cc b/src/lte/model/lte-common.cc index 6199186ac..0e830a7f2 100644 --- a/src/lte/model/lte-common.cc +++ b/src/lte/model/lte-common.cc @@ -16,10 +16,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Manuel Requena + * Author: Marco Miozzo */ #include "lte-common.h" +#include +NS_LOG_COMPONENT_DEFINE ("LteFfConverter"); namespace ns3 { @@ -47,5 +50,31 @@ operator < (const lteFlowId_t& a, const lteFlowId_t& b) } +uint16_t +LteFfConverter::double2fpS11dot3(double val) +{ + // convert from double to fixed point notation Sxxxxxxxxxxx.xxx + int16_t valFp = (int16_t)(val * pow (2, 3)); + return (valFp); +} + +double +LteFfConverter::fpS11dot3toDouble(uint16_t val) +{ + // convert from fixed point notation Sxxxxxxxxxxx.xxx to double + double valD = ((int16_t)val) / pow (2, 3); + return (valD); +} + +double +LteFfConverter::getMinFpS11dot3Value () +{ + return (-4096); // -4096 = 0x8000 = 1000 0000 0000 0000 b +} + +//static double g_lowestFpS11dot3Value = -4096; // 0x8001 (1000 0000 0000 0000) + + + }; // namespace ns3 diff --git a/src/lte/model/lte-common.h b/src/lte/model/lte-common.h index 18149f54f..ab675d5bd 100644 --- a/src/lte/model/lte-common.h +++ b/src/lte/model/lte-common.h @@ -16,11 +16,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Manuel Requena + * Author: Marco Miozzo */ #ifndef LTE_COMMON_H #define LTE_COMMON_H #include "ns3/uinteger.h" +#include namespace ns3 { @@ -38,6 +40,19 @@ public: friend bool operator < (const lteFlowId_t &a, const lteFlowId_t &b); }; +class LteFfConverter +{ + +public: + static uint16_t double2fpS11dot3 (double val); + static double fpS11dot3toDouble (uint16_t val); + static double getMinFpS11dot3Value (); + + //static const double MIN_FP_S11DOT3_VALUE = -4096; + + +}; + }; // namespace ns3 diff --git a/src/lte/model/lte-enb-phy.cc b/src/lte/model/lte-enb-phy.cc index 6ce1b2fef..e01eb346c 100644 --- a/src/lte/model/lte-enb-phy.cc +++ b/src/lte/model/lte-enb-phy.cc @@ -30,6 +30,7 @@ #include "ideal-control-messages.h" #include "lte-enb-net-device.h" #include "lte-enb-mac.h" +#include NS_LOG_COMPONENT_DEFINE ("LteEnbPhy"); @@ -398,8 +399,11 @@ LteEnbPhy::CreateUlCqiReport (const SpectrumValue& sinr) int i = 0; for (it = sinr.ConstValuesBegin (); it != sinr.ConstValuesEnd (); it++) { - ulcqi.m_sinr.push_back ((*it)); - //NS_LOG_DEBUG(this << " RB " << i << " SINR " << (*it)); + double sinrdb = 10*log10 ((*it)); + // convert from double to fixed point notation Sxxxxxxxxxxx.xxx + int16_t sinrFp = LteFfConverter::double2fpS11dot3 (sinrdb); + ulcqi.m_sinr.push_back (sinrFp); + //NS_LOG_DEBUG(this << " RB " << i << " SINR FP " << sinrFp << " orig " << sinrdb); i++; } return (ulcqi); diff --git a/src/lte/model/pf-ff-mac-scheduler.cc b/src/lte/model/pf-ff-mac-scheduler.cc index 113547105..ea3380758 100644 --- a/src/lte/model/pf-ff-mac-scheduler.cc +++ b/src/lte/model/pf-ff-mac-scheduler.cc @@ -698,8 +698,36 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched uldci.m_rbStart = rbAllocated; uldci.m_rbLen = rbPerFlow; rbAllocated += rbPerFlow; - uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD - uldci.m_tbSize = (LteAmc::GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); // MCS 0 -> UL-AMC TBD + std::map >::iterator itCqi = m_ueCqi.find ((*it).first); + if (itCqi == m_ueCqi.end ()) + { + // no cqi info about this UE + uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD + //NS_LOG_DEBUG (this << " UE does not have ULCQI " << (*it).first ); + } + else + { + // take the lowest CQI value (worst RB) + double minSinr = (*itCqi).second.at(uldci.m_rbStart); + for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++) + { + //NS_LOG_DEBUG (this << " UE " << (*it).first << " has CQI " << (*itCqi).second.at(i)); + if ((*itCqi).second.at(i) < minSinr) + { + minSinr = (*itCqi).second.at(i); + } + } + + // translate SINR -> cqi: WILD ACK: same as DL + double s = log2 ( 1 + ( + pow (10, minSinr / 10 ) / + ( (-log (5.0 * 0.00005 )) / 1.5) )); + int cqi = LteAmc::GetCqiFromSpectralEfficiency (s); + uldci.m_mcs = LteAmc::GetMcsFromCqi (cqi); + //NS_LOG_DEBUG (this << " UE " << (*it).first << " minsinr " << minSinr << " -> mcs " << (uint16_t)uldci.m_mcs); + + } + uldci.m_tbSize = (LteAmc::GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); uldci.m_ndi = 1; uldci.m_cceIndex = 0; uldci.m_aggrLevel = 1; @@ -784,7 +812,7 @@ PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched uint16_t sfnSf = ((0xFF & frameNo) << 4) | (0xF & subframeNo); // retrieve the allocation for this subframe std::map >::iterator itMap; - std::map >::iterator itCqi; + std::map >::iterator itCqi; itMap = m_allocationMaps.find (sfnSf); if (itMap == m_allocationMaps.end()) { @@ -793,30 +821,33 @@ PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched } for (uint32_t i = 0; i < (*itMap).second.size (); i++) { - //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINR " << params.m_ulCqi.m_sinr.at (i)); - // fixed point notation Sxxxxxxxxxxx.xxx + // convert from fixed point notation Sxxxxxxxxxxx.xxx to double + double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i)); + //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr); itCqi = m_ueCqi.find ((*itMap).second.at (i)); if (itCqi == m_ueCqi.end ()) { // create a new entry - std::vector newCqi; + std::vector newCqi; for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++) { if (i==j) { - newCqi.push_back (params.m_ulCqi.m_sinr.at (i)); + newCqi.push_back (sinr); } else { - newCqi.push_back (0); // TBD : put the lower possible value + // initialize with minumum values according to the fixed point notation + newCqi.push_back (LteFfConverter::getMinFpS11dot3Value ()); } } + m_ueCqi.insert (std::pair > ((*itMap).second.at (i), newCqi)); } else { // update the value - (*itCqi).second.at (i) = params.m_ulCqi.m_sinr.at (i); + (*itCqi).second.at (i) = sinr; } } diff --git a/src/lte/model/pf-ff-mac-scheduler.h b/src/lte/model/pf-ff-mac-scheduler.h index 4bd021651..8cbe9ef83 100644 --- a/src/lte/model/pf-ff-mac-scheduler.h +++ b/src/lte/model/pf-ff-mac-scheduler.h @@ -160,7 +160,7 @@ private: /* * Map of UEs' UL-CQI per RBG */ - std::map > m_ueCqi; + std::map > m_ueCqi; /* * Map of UE's buffer status reports received