--- a/src/lte/model/lte-ue-cphy-sap.h Thu Sep 04 22:55:05 2014 +0200 +++ a/src/lte/model/lte-ue-cphy-sap.h Thu Oct 09 22:25:28 2014 +0200 @@ -139,6 +139,11 @@ */ virtual void SetSrsConfigurationIndex (uint16_t srcCi) = 0; + /** + * \param pa the P_A value + */ + virtual void SetPa (double pa) = 0; + }; @@ -231,6 +236,7 @@ virtual void SetRnti (uint16_t rnti); virtual void SetTransmissionMode (uint8_t txMode); virtual void SetSrsConfigurationIndex (uint16_t srcCi); + virtual void SetPa (double pa); private: MemberLteUeCphySapProvider (); @@ -318,6 +324,12 @@ m_owner->DoSetSrsConfigurationIndex (srcCi); } +template +void +MemberLteUeCphySapProvider::SetPa (double pa) +{ + m_owner->DoSetPa (pa); +} /** --- a/src/lte/model/lte-ue-phy.cc Thu Sep 04 22:55:05 2014 +0200 +++ a/src/lte/model/lte-ue-phy.cc Thu Oct 09 22:25:28 2014 +0200 @@ -441,7 +441,26 @@ if (m_dataInterferencePowerUpdated) { - SpectrumValue mixedSinr = m_rsReceivedPower / m_dataInterferencePower; + SpectrumValue mixedSinr = (m_rsReceivedPower * m_paLinear) / m_dataInterferencePower; + + /* + * some RBs are not used in PDSCH and their SINR is very high + * for example with bandwidth 25, last RB is not used + * it can make avgSinr value very high, what is incorrect + */ + uint32_t rbgSize = GetRbgSize (); + uint32_t modulo = m_dlBandwidth % rbgSize; + double avgMixedSinr = 0; + uint32_t usedRbgNum = 0; + for(uint32_t i = 0; i < (m_dlBandwidth-1-modulo); i++) { + usedRbgNum++; + avgMixedSinr+=mixedSinr[i]; + } + avgMixedSinr = avgMixedSinr/usedRbgNum; + for(uint32_t i = 0; i < modulo; i++) { + mixedSinr[m_dlBandwidth-1-i] = avgMixedSinr; + } + GenerateMixedCqiReport (mixedSinr); m_dataInterferencePowerUpdated = false; return; @@ -1229,6 +1248,7 @@ m_rsrpSinrSampleCounter = 0; m_p10CqiLast = Simulator::Now (); m_a30CqiLast = Simulator::Now (); + m_paLinear = 1; m_packetBurstQueue.clear (); m_controlMessagesQueue.clear (); @@ -1367,6 +1387,12 @@ NS_LOG_DEBUG (this << " UE SRS P " << m_srsPeriodicity << " RNTI " << m_rnti << " offset " << m_srsSubframeOffset << " cellId " << m_cellId << " CI " << srcCi); } +void +LteUePhy::DoSetPa (double pa) +{ + NS_LOG_FUNCTION (this << pa); + m_paLinear = pow (10,(pa/10)); +} void LteUePhy::SetTxMode1Gain (double gain) --- a/src/lte/model/lte-ue-phy.h Thu Sep 04 22:55:05 2014 +0200 +++ a/src/lte/model/lte-ue-phy.h Thu Oct 09 22:25:28 2014 +0200 @@ -273,6 +273,7 @@ void DoSetRnti (uint16_t rnti); void DoSetTransmissionMode (uint8_t txMode); void DoSetSrsConfigurationIndex (uint16_t srcCi); + void DoSetPa (double pa); // UE PHY SAP methods virtual void DoSendMacPdu (Ptr p); @@ -314,6 +315,8 @@ uint16_t m_srsConfigured; Time m_srsStartTime; + double m_paLinear; + bool m_dlConfigured; bool m_ulConfigured; --- a/src/lte/model/lte-ue-rrc.cc Thu Sep 04 22:55:05 2014 +0200 +++ a/src/lte/model/lte-ue-rrc.cc Thu Oct 09 22:25:28 2014 +0200 @@ -1099,8 +1099,10 @@ if (pcd.havePdschConfigDedicated) { // update PdschConfigDedicated (i.e. P_A value) - m_pdschConfigDedicated = pcd.pdschConfigDedicated; - } + m_pdschConfigDedicated = pcd.pdschConfigDedicated; + double paDouble = LteRrcSap::ConvertPdschConfigDedicated2Double (m_pdschConfigDedicated); + m_cphySapProvider->SetPa (paDouble); + } std::list::const_iterator stamIt = rrcd.srbToAddModList.begin (); if (stamIt != rrcd.srbToAddModList.end ()) --- a/src/lte/test/lte-test-cqi-generation.cc Thu Sep 04 22:55:05 2014 +0200 +++ a/src/lte/test/lte-test-cqi-generation.cc Thu Oct 09 22:25:28 2014 +0200 @@ -32,6 +32,9 @@ #include "ns3/mobility-helper.h" #include "ns3/lte-helper.h" +#include "lte-ffr-simple.h" +#include "ns3/lte-rrc-sap.h" + #include "lte-test-cqi-generation.h" NS_LOG_COMPONENT_DEFINE ("LteCqiGenerationTest"); @@ -54,6 +57,22 @@ testcase->UlScheduling (frameNo, subframeNo, rnti, mcs, sizeTb); } +void +LteTestDlSchedulingCallback2 (LteCqiGenerationDlPowerControlTestCase *testcase, std::string path, + uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, + uint8_t mcsTb1, uint16_t sizeTb1, uint8_t mcsTb2, uint16_t sizeTb2) +{ + testcase->DlScheduling (frameNo, subframeNo, rnti, mcsTb1, sizeTb1, mcsTb2, sizeTb2); +} + +void +LteTestUlSchedulingCallback2 (LteCqiGenerationDlPowerControlTestCase *testcase, std::string path, + uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, + uint8_t mcs, uint16_t sizeTb) +{ + testcase->UlScheduling (frameNo, subframeNo, rnti, mcs, sizeTb); +} + /** * TestSuite @@ -69,6 +88,20 @@ AddTestCase (new LteCqiGenerationTestCase ("UsePdcchForCqiGeneration", false, 4, 2), TestCase::QUICK); AddTestCase (new LteCqiGenerationTestCase ("UsePdschForCqiGeneration", true, 28, 2), TestCase::QUICK); + AddTestCase (new LteCqiGenerationDlPowerControlTestCase ("CqiGenerationWithDlPowerControl", + LteRrcSap::PdschConfigDedicated::dB0, LteRrcSap::PdschConfigDedicated::dB0, 4, 2), TestCase::QUICK); + AddTestCase (new LteCqiGenerationDlPowerControlTestCase ("CqiGenerationWithDlPowerControl", + LteRrcSap::PdschConfigDedicated::dB0, LteRrcSap::PdschConfigDedicated::dB_3, 8, 2), TestCase::QUICK); + AddTestCase (new LteCqiGenerationDlPowerControlTestCase ("CqiGenerationWithDlPowerControl", + LteRrcSap::PdschConfigDedicated::dB0, LteRrcSap::PdschConfigDedicated::dB_6, 10, 2), TestCase::QUICK); + AddTestCase (new LteCqiGenerationDlPowerControlTestCase ("CqiGenerationWithDlPowerControl", + LteRrcSap::PdschConfigDedicated::dB1, LteRrcSap::PdschConfigDedicated::dB_6, 12, 2), TestCase::QUICK); + AddTestCase (new LteCqiGenerationDlPowerControlTestCase ("CqiGenerationWithDlPowerControl", + LteRrcSap::PdschConfigDedicated::dB2, LteRrcSap::PdschConfigDedicated::dB_6, 14, 2), TestCase::QUICK); + AddTestCase (new LteCqiGenerationDlPowerControlTestCase ("CqiGenerationWithDlPowerControl", + LteRrcSap::PdschConfigDedicated::dB3, LteRrcSap::PdschConfigDedicated::dB_6, 14, 2), TestCase::QUICK); + AddTestCase (new LteCqiGenerationDlPowerControlTestCase ("CqiGenerationWithDlPowerControl", + LteRrcSap::PdschConfigDedicated::dB3, LteRrcSap::PdschConfigDedicated::dB0, 8, 2), TestCase::QUICK); } static LteCqiGenerationTestSuite lteCqiGenerationTestSuite; @@ -206,3 +239,137 @@ Simulator::Destroy (); } + +LteCqiGenerationDlPowerControlTestCase::LteCqiGenerationDlPowerControlTestCase (std::string name, + uint8_t cell0Pa, uint8_t cell1Pa, uint16_t dlMcs, uint16_t ulMcs) + : TestCase ("Downlink Power Control: " + name), + m_cell0Pa (cell0Pa), + m_cell1Pa (cell1Pa), + m_dlMcs (dlMcs), + m_ulMcs (ulMcs) +{ + NS_LOG_INFO ("Creating LteCqiGenerationTestCase"); +} + +LteCqiGenerationDlPowerControlTestCase::~LteCqiGenerationDlPowerControlTestCase () +{ +} + +void +LteCqiGenerationDlPowerControlTestCase::DlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, + uint8_t mcsTb1, uint16_t sizeTb1, uint8_t mcsTb2, uint16_t sizeTb2) +{ + // need to allow for RRC connection establishment + CQI feedback reception + if (Simulator::Now () > MilliSeconds (500)) + { +// NS_LOG_UNCOND("DL MSC: " << (uint32_t)mcsTb1 << " expected DL MCS: " << (uint32_t)m_dlMcs); + NS_TEST_ASSERT_MSG_EQ ((uint32_t)mcsTb1, (uint32_t)m_dlMcs, "Wrong DL MCS "); + } +} + +void +LteCqiGenerationDlPowerControlTestCase::UlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, + uint8_t mcs, uint16_t sizeTb) +{ + // need to allow for RRC connection establishment + SRS transmission + if (Simulator::Now () > MilliSeconds (500)) + { +// NS_LOG_UNCOND("UL MSC: " << (uint32_t)mcs << " expected UL MCS: " << (uint32_t)m_ulMcs); + NS_TEST_ASSERT_MSG_EQ ((uint32_t)mcs, (uint32_t)m_ulMcs, "Wrong UL MCS"); + } +} + +void +LteCqiGenerationDlPowerControlTestCase::DoRun (void) +{ + NS_LOG_DEBUG ("LteCqiGenerationTestCase"); + + Config::Reset (); + Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true)); + Config::SetDefault ("ns3::LteHelper::UsePdschForCqiGeneration", BooleanValue (true)); + + Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (true)); + Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (true)); + + Ptr lteHelper = CreateObject (); + lteHelper->SetFfrAlgorithmType ("ns3::LteFfrSimple"); + + // Create Nodes: eNodeB and UE + NodeContainer enbNodes; + NodeContainer ueNodes1; + NodeContainer ueNodes2; + enbNodes.Create (2); + ueNodes1.Create (1); + ueNodes2.Create (1); + NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes1, ueNodes2); + + /* + * The topology is the following: + * + * eNB1 UE1 UE2 eNB2 + * | | | + * x -------------------------- x -------------------------- x + * 500 m 500 m + * + */ + + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector (0.0, 0.0, 0.0)); // eNB1 + positionAlloc->Add (Vector (1000, 0.0, 0.0)); // eNB2 + positionAlloc->Add (Vector (500.0, 0.0, 0.0)); // UE1 + positionAlloc->Add (Vector (500, 0.0, 0.0)); // UE2 + MobilityHelper mobility; + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.SetPositionAllocator (positionAlloc); + mobility.Install (allNodes); + + // Create Devices and install them in the Nodes (eNB and UE) + NetDeviceContainer enbDevs; + NetDeviceContainer ueDevs1; + NetDeviceContainer ueDevs2; + lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler"); + lteHelper->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI)); + enbDevs = lteHelper->InstallEnbDevice (enbNodes); + ueDevs1 = lteHelper->InstallUeDevice (ueNodes1); + ueDevs2 = lteHelper->InstallUeDevice (ueNodes2); + + // Attach a UE to a eNB + lteHelper->Attach (ueDevs1, enbDevs.Get (0)); + lteHelper->Attach (ueDevs2, enbDevs.Get (1)); + + // Activate an EPS bearer + enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE; + EpsBearer bearer (q); + lteHelper->ActivateDataRadioBearer (ueDevs1, bearer); + lteHelper->ActivateDataRadioBearer (ueDevs2, bearer); + + PointerValue tmp; + enbDevs.Get (0)->GetAttribute ("LteFfrAlgorithm", tmp); + Ptr simpleFfrAlgorithmEnb0 = DynamicCast(tmp.GetObject ()); + simpleFfrAlgorithmEnb0->ChangePdschConfigDedicated (true); + + LteRrcSap::PdschConfigDedicated pdschConfigDedicatedEnb0; + pdschConfigDedicatedEnb0.pa = m_cell0Pa; + simpleFfrAlgorithmEnb0->SetPdschConfigDedicated (pdschConfigDedicatedEnb0); + + enbDevs.Get (1)->GetAttribute ("LteFfrAlgorithm", tmp); + Ptr simpleFfrAlgorithmEnb1 = DynamicCast(tmp.GetObject ()); + simpleFfrAlgorithmEnb1->ChangePdschConfigDedicated (true); + + LteRrcSap::PdschConfigDedicated pdschConfigDedicatedEnb1; + pdschConfigDedicatedEnb1.pa = m_cell1Pa; + simpleFfrAlgorithmEnb1->SetPdschConfigDedicated (pdschConfigDedicatedEnb1); + + + Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling", + MakeBoundCallback (&LteTestDlSchedulingCallback2, this)); + + Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/UlScheduling", + MakeBoundCallback (&LteTestUlSchedulingCallback2, this)); + + Simulator::Stop (Seconds (1.100)); + Simulator::Run (); + + Simulator::Destroy (); +} + --- a/src/lte/test/lte-test-cqi-generation.h Thu Sep 04 22:55:05 2014 +0200 +++ a/src/lte/test/lte-test-cqi-generation.h Thu Oct 09 22:25:28 2014 +0200 @@ -54,4 +54,28 @@ }; +class LteCqiGenerationDlPowerControlTestCase : public TestCase +{ +public: + LteCqiGenerationDlPowerControlTestCase (std::string name, uint8_t cell0Pa, uint8_t cell1Pa, + uint16_t dlMcs, uint16_t ulMcs); + virtual ~LteCqiGenerationDlPowerControlTestCase (); + + void DlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, + uint8_t mcsTb1, uint16_t sizeTb1, uint8_t mcsTb2, uint16_t sizeTb2); + + void UlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti, + uint8_t mcs, uint16_t sizeTb); + +private: + virtual void DoRun (void); + + uint8_t m_cell0Pa; + uint8_t m_cell1Pa; + + uint16_t m_dlMcs; + uint16_t m_ulMcs; + +}; + #endif /* LTE_TEST_CQI_GENERATION_H */