1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
4  * Copyright (c) 2018 Fraunhofer ESK : RLF extensions
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Author: Giuseppe Piro  <g.piro@poliba.it>
20  *         Marco Miozzo <marco.miozzo@cttc.es>
21  *         Nicola Baldo <nbaldo@cttc.es>
22  * Modified by:
23  *          Vignesh Babu <ns3-dev@esk.fraunhofer.de> (RLF extensions)
24  */
25 
26 #include <ns3/object-factory.h>
27 #include <ns3/log.h>
28 #include <ns3/node.h>
29 #include <cfloat>
30 #include <cmath>
31 #include <ns3/simulator.h>
32 #include <ns3/double.h>
33 #include "lte-ue-phy.h"
34 #include "lte-enb-phy.h"
35 #include "lte-net-device.h"
36 #include "lte-ue-net-device.h"
37 #include "lte-enb-net-device.h"
38 #include "lte-spectrum-value-helper.h"
39 #include "lte-amc.h"
40 #include "lte-ue-mac.h"
41 #include "ff-mac-common.h"
42 #include "lte-chunk-processor.h"
43 #include <ns3/lte-common.h>
44 #include <ns3/pointer.h>
45 #include <ns3/boolean.h>
46 #include <ns3/lte-ue-power-control.h>
47 
48 namespace ns3 {
49 
50 NS_LOG_COMPONENT_DEFINE ("LteUePhy");
51 
52 
53 
54 /**
55  * Duration of the data portion of a UL subframe.
56  * Equals to "TTI length - 1 symbol length for SRS - margin".
57  * The margin is 1 nanosecond and is intended to avoid overlapping simulator
58  * events. The duration of one symbol is TTI/14 (rounded). In other words,
59  * duration of data portion of UL subframe = 1 ms * (13/14) - 1 ns.
60  */
61 static const Time UL_DATA_DURATION = NanoSeconds (1e6 - 71429 - 1);
62 
63 /**
64  * Delay from subframe start to transmission of SRS.
65  * Equals to "TTI length - 1 symbol for SRS".
66  */
67 static const Time UL_SRS_DELAY_FROM_SUBFRAME_START = NanoSeconds (1e6 - 71429);
68 
69 
70 
71 
72 ////////////////////////////////////////
73 // member SAP forwarders
74 ////////////////////////////////////////
75 
76 /// UeMemberLteUePhySapProvider class
77 class UeMemberLteUePhySapProvider : public LteUePhySapProvider
78 {
79 public:
80   /**
81    * Constructor
82    *
83    * \param phy the LTE UE Phy
84    */
85   UeMemberLteUePhySapProvider (LteUePhy* phy);
86 
87   // inherited from LtePhySapProvider
88   virtual void SendMacPdu (Ptr<Packet> p);
89   virtual void SendLteControlMessage (Ptr<LteControlMessage> msg);
90   virtual void SendRachPreamble (uint32_t prachId, uint32_t raRnti);
91   virtual void NotifyConnectionSuccessful ();
92 
93 private:
94   LteUePhy* m_phy; ///< the Phy
95 };
96 
UeMemberLteUePhySapProvider(LteUePhy * phy)97 UeMemberLteUePhySapProvider::UeMemberLteUePhySapProvider (LteUePhy* phy) : m_phy (phy)
98 {}
99 
100 void
SendMacPdu(Ptr<Packet> p)101 UeMemberLteUePhySapProvider::SendMacPdu (Ptr<Packet> p)
102 {
103   m_phy->DoSendMacPdu (p);
104 }
105 
106 void
SendLteControlMessage(Ptr<LteControlMessage> msg)107 UeMemberLteUePhySapProvider::SendLteControlMessage (Ptr<LteControlMessage> msg)
108 {
109   m_phy->DoSendLteControlMessage (msg);
110 }
111 
112 void
SendRachPreamble(uint32_t prachId,uint32_t raRnti)113 UeMemberLteUePhySapProvider::SendRachPreamble (uint32_t prachId, uint32_t raRnti)
114 {
115   m_phy->DoSendRachPreamble (prachId, raRnti);
116 }
117 
118 void
NotifyConnectionSuccessful()119 UeMemberLteUePhySapProvider::NotifyConnectionSuccessful ()
120 {
121   m_phy->DoNotifyConnectionSuccessful ();
122 }
123 
124 
125 ////////////////////////////////////////
126 // LteUePhy methods
127 ////////////////////////////////////////
128 
129 /// Map each of UE PHY states to its string representation.
130 static const std::string g_uePhyStateName[LteUePhy::NUM_STATES] =
131 {
132   "CELL_SEARCH",
133   "SYNCHRONIZED"
134 };
135 
136 /**
137  * \param s The UE PHY state.
138  * \return The string representation of the given state.
139  */
ToString(LteUePhy::State s)140 static inline const std::string & ToString (LteUePhy::State s)
141 {
142   return g_uePhyStateName[s];
143 }
144 
145 
146 NS_OBJECT_ENSURE_REGISTERED (LteUePhy);
147 
148 
LteUePhy()149 LteUePhy::LteUePhy ()
150 {
151   NS_LOG_FUNCTION (this);
152   NS_FATAL_ERROR ("This constructor should not be called");
153 }
154 
LteUePhy(Ptr<LteSpectrumPhy> dlPhy,Ptr<LteSpectrumPhy> ulPhy)155 LteUePhy::LteUePhy (Ptr<LteSpectrumPhy> dlPhy, Ptr<LteSpectrumPhy> ulPhy)
156   : LtePhy (dlPhy, ulPhy),
157     m_uePhySapUser (0),
158     m_ueCphySapUser (0),
159     m_state (CELL_SEARCH),
160     m_subframeNo (0),
161     m_rsReceivedPowerUpdated (false),
162     m_rsInterferencePowerUpdated (false),
163     m_dataInterferencePowerUpdated (false),
164     m_pssReceived (false),
165     m_ueMeasurementsFilterPeriod (MilliSeconds (200)),
166     m_ueMeasurementsFilterLast (MilliSeconds (0)),
167     m_rsrpSinrSampleCounter (0),
168     m_imsi (0)
169 {
170   m_amc = CreateObject <LteAmc> ();
171   m_powerControl = CreateObject <LteUePowerControl> ();
172   m_uePhySapProvider = new UeMemberLteUePhySapProvider (this);
173   m_ueCphySapProvider = new MemberLteUeCphySapProvider<LteUePhy> (this);
174   m_macChTtiDelay = UL_PUSCH_TTIS_DELAY;
175 
176   NS_ASSERT_MSG (Simulator::Now ().GetNanoSeconds () == 0,
177                  "Cannot create UE devices after simulation started");
178   Simulator::Schedule (m_ueMeasurementsFilterPeriod, &LteUePhy::ReportUeMeasurements, this);
179 
180   DoReset ();
181 }
182 
183 
~LteUePhy()184 LteUePhy::~LteUePhy ()
185 {
186   m_txModeGain.clear ();
187 }
188 
189 void
DoDispose()190 LteUePhy::DoDispose ()
191 {
192   NS_LOG_FUNCTION (this);
193   delete m_uePhySapProvider;
194   delete m_ueCphySapProvider;
195   LtePhy::DoDispose ();
196 }
197 
198 
199 
200 TypeId
GetTypeId(void)201 LteUePhy::GetTypeId (void)
202 {
203   static TypeId tid = TypeId ("ns3::LteUePhy")
204     .SetParent<LtePhy> ()
205     .SetGroupName ("Lte")
206     .AddConstructor<LteUePhy> ()
207     .AddAttribute ("TxPower",
208                    "Transmission power in dBm",
209                    DoubleValue (10.0),
210                    MakeDoubleAccessor (&LteUePhy::SetTxPower,
211                                        &LteUePhy::GetTxPower),
212                    MakeDoubleChecker<double> ())
213     .AddAttribute ("NoiseFigure",
214                    "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver."
215                    " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is "
216                    "\"the difference in decibels (dB) between"
217                    " the noise output of the actual receiver to the noise output of an "
218                    " ideal receiver with the same overall gain and bandwidth when the receivers "
219                    " are connected to sources at the standard noise temperature T0.\" "
220                    "In this model, we consider T0 = 290K.",
221                    DoubleValue (9.0),
222                    MakeDoubleAccessor (&LteUePhy::SetNoiseFigure,
223                                        &LteUePhy::GetNoiseFigure),
224                    MakeDoubleChecker<double> ())
225     .AddAttribute ("TxMode1Gain",
226                    "Transmission mode 1 gain in dB",
227                    DoubleValue (0.0),
228                    MakeDoubleAccessor (&LteUePhy::SetTxMode1Gain),
229                    MakeDoubleChecker<double> ())
230     .AddAttribute ("TxMode2Gain",
231                    "Transmission mode 2 gain in dB",
232                    DoubleValue (4.2),
233                    MakeDoubleAccessor (&LteUePhy::SetTxMode2Gain),
234                    MakeDoubleChecker<double> ())
235     .AddAttribute ("TxMode3Gain",
236                    "Transmission mode 3 gain in dB",
237                    DoubleValue (-2.8),
238                    MakeDoubleAccessor (&LteUePhy::SetTxMode3Gain),
239                    MakeDoubleChecker<double> ())
240     .AddAttribute ("TxMode4Gain",
241                    "Transmission mode 4 gain in dB",
242                    DoubleValue (0.0),
243                    MakeDoubleAccessor (&LteUePhy::SetTxMode4Gain),
244                    MakeDoubleChecker<double> ())
245     .AddAttribute ("TxMode5Gain",
246                    "Transmission mode 5 gain in dB",
247                    DoubleValue (0.0),
248                    MakeDoubleAccessor (&LteUePhy::SetTxMode5Gain),
249                    MakeDoubleChecker<double> ())
250     .AddAttribute ("TxMode6Gain",
251                    "Transmission mode 6 gain in dB",
252                    DoubleValue (0.0),
253                    MakeDoubleAccessor (&LteUePhy::SetTxMode6Gain),
254                    MakeDoubleChecker<double> ())
255     .AddAttribute ("TxMode7Gain",
256                    "Transmission mode 7 gain in dB",
257                    DoubleValue (0.0),
258                    MakeDoubleAccessor (&LteUePhy::SetTxMode7Gain),
259                    MakeDoubleChecker<double> ())
260     .AddTraceSource ("ReportCurrentCellRsrpSinr",
261                      "RSRP and SINR statistics.",
262                      MakeTraceSourceAccessor (&LteUePhy::m_reportCurrentCellRsrpSinrTrace),
263                      "ns3::LteUePhy::RsrpSinrTracedCallback")
264     .AddAttribute ("RsrpSinrSamplePeriod",
265                    "The sampling period for reporting RSRP-SINR stats (default value 1)",
266                    UintegerValue (1),
267                    MakeUintegerAccessor (&LteUePhy::m_rsrpSinrSamplePeriod),
268                    MakeUintegerChecker<uint16_t> ())
269     .AddTraceSource ("ReportUlPhyResourceBlocks",
270                      "UL transmission PHY layer resource blocks.",
271                      MakeTraceSourceAccessor (&LteUePhy::m_reportUlPhyResourceBlocks),
272                      "ns3::LteUePhy::UlPhyResourceBlocksTracedCallback")
273     .AddTraceSource ("ReportPowerSpectralDensity",
274                      "Power Spectral Density data.",
275                      MakeTraceSourceAccessor (&LteUePhy::m_reportPowerSpectralDensity),
276                      "ns3::LteUePhy::PowerSpectralDensityTracedCallback")
277     .AddTraceSource ("UlPhyTransmission",
278                      "DL transmission PHY layer statistics.",
279                      MakeTraceSourceAccessor (&LteUePhy::m_ulPhyTransmission),
280                      "ns3::PhyTransmissionStatParameters::TracedCallback")
281     .AddAttribute ("DlSpectrumPhy",
282                    "The downlink LteSpectrumPhy associated to this LtePhy",
283                    TypeId::ATTR_GET,
284                    PointerValue (),
285                    MakePointerAccessor (&LteUePhy::GetDlSpectrumPhy),
286                    MakePointerChecker <LteSpectrumPhy> ())
287     .AddAttribute ("UlSpectrumPhy",
288                    "The uplink LteSpectrumPhy associated to this LtePhy",
289                    TypeId::ATTR_GET,
290                    PointerValue (),
291                    MakePointerAccessor (&LteUePhy::GetUlSpectrumPhy),
292                    MakePointerChecker <LteSpectrumPhy> ())
293     .AddAttribute ("RsrqUeMeasThreshold",
294                    "Receive threshold for PSS on RSRQ [dB]",
295                    DoubleValue (-1000.0),
296                    MakeDoubleAccessor (&LteUePhy::m_pssReceptionThreshold),
297                    MakeDoubleChecker<double> ())
298     .AddAttribute ("UeMeasurementsFilterPeriod",
299                    "Time period for reporting UE measurements, i.e., the"
300                    "length of layer-1 filtering.",
301                    TimeValue (MilliSeconds (200)),
302                    MakeTimeAccessor (&LteUePhy::m_ueMeasurementsFilterPeriod),
303                    MakeTimeChecker ())
304     .AddAttribute ("DownlinkCqiPeriodicity",
305                    "Periodicity in milliseconds for reporting the"
306                    "wideband and subband downlink CQIs to the eNB",
307                    TimeValue (MilliSeconds (1)),
308                    MakeTimeAccessor (&LteUePhy::SetDownlinkCqiPeriodicity),
309                    MakeTimeChecker ())
310     .AddTraceSource ("ReportUeMeasurements",
311                      "Report UE measurements RSRP (dBm) and RSRQ (dB).",
312                      MakeTraceSourceAccessor (&LteUePhy::m_reportUeMeasurements),
313                      "ns3::LteUePhy::RsrpRsrqTracedCallback")
314     .AddTraceSource ("StateTransition",
315                      "Trace fired upon every UE PHY state transition",
316                      MakeTraceSourceAccessor (&LteUePhy::m_stateTransitionTrace),
317                      "ns3::LteUePhy::StateTracedCallback")
318     .AddAttribute ("EnableUplinkPowerControl",
319                    "If true, Uplink Power Control will be enabled.",
320                    BooleanValue (true),
321                    MakeBooleanAccessor (&LteUePhy::m_enableUplinkPowerControl),
322                    MakeBooleanChecker ())
323     .AddAttribute ("Qout",
324                    "corresponds to 10% block error rate of a hypothetical PDCCH transmission"
325                    "taking into account the PCFICH errors with transmission parameters."
326                    "see 3GPP TS 36.213 4.2.1 and TS 36.133 7.6",
327                    DoubleValue (-5),
328                    MakeDoubleAccessor (&LteUePhy::m_qOut),
329                    MakeDoubleChecker<double> ())
330     .AddAttribute ("Qin",
331                    "corresponds to 2% block error rate of a hypothetical PDCCH transmission"
332                    "taking into account the PCFICH errors with transmission parameters."
333                    "see 3GPP TS 36.213 4.2.1 and TS 36.133 7.6",
334                    DoubleValue (-3.9),
335                    MakeDoubleAccessor (&LteUePhy::m_qIn),
336                    MakeDoubleChecker<double> ())
337     .AddAttribute ("NumQoutEvalSf",
338                    "This specifies the total number of consecutive subframes"
339                    "which corresponds to the Qout evaluation period",
340                    UintegerValue (200), //see 3GPP 3GPP TS 36.133 7.6.2.1
341                    MakeUintegerAccessor (&LteUePhy::SetNumQoutEvalSf,
342                                          &LteUePhy::GetNumQoutEvalSf),
343                    MakeUintegerChecker<uint16_t> ())
344     .AddAttribute ("NumQinEvalSf",
345                    "This specifies the total number of consecutive subframes"
346                    "which corresponds to the Qin evaluation period",
347                    UintegerValue (100), //see 3GPP 3GPP TS 36.133 7.6.2.1
348                    MakeUintegerAccessor (&LteUePhy::SetNumQinEvalSf,
349                                          &LteUePhy::GetNumQinEvalSf),
350                    MakeUintegerChecker<uint16_t> ())
351     .AddAttribute ("EnableRlfDetection",
352                    "If true, RLF detection will be enabled.",
353                    BooleanValue (true),
354                    MakeBooleanAccessor (&LteUePhy::m_enableRlfDetection),
355                    MakeBooleanChecker ())
356   ;
357   return tid;
358 }
359 
360 void
DoInitialize()361 LteUePhy::DoInitialize ()
362 {
363   NS_LOG_FUNCTION (this);
364 
365   NS_ABORT_MSG_IF (m_netDevice == nullptr, "LteNetDevice is not available in LteUePhy");
366   Ptr<Node> node = m_netDevice->GetNode ();
367   NS_ABORT_MSG_IF (node == nullptr, "Node is not available in the LteNetDevice of LteUePhy");
368   uint32_t nodeId = node->GetId ();
369 
370   //ScheduleWithContext() is needed here to set context for logs,
371   //because Initialize() is called outside of Node::AddDevice().
372 
373   Simulator::ScheduleWithContext (nodeId, Seconds (0), &LteUePhy::SubframeIndication, this, 1, 1);
374 
375   LtePhy::DoInitialize ();
376 }
377 
378 void
SetLteUePhySapUser(LteUePhySapUser * s)379 LteUePhy::SetLteUePhySapUser (LteUePhySapUser* s)
380 {
381   NS_LOG_FUNCTION (this);
382   m_uePhySapUser = s;
383 }
384 
385 LteUePhySapProvider*
GetLteUePhySapProvider()386 LteUePhy::GetLteUePhySapProvider ()
387 {
388   NS_LOG_FUNCTION (this);
389   return (m_uePhySapProvider);
390 }
391 
392 
393 void
SetLteUeCphySapUser(LteUeCphySapUser * s)394 LteUePhy::SetLteUeCphySapUser (LteUeCphySapUser* s)
395 {
396   NS_LOG_FUNCTION (this);
397   m_ueCphySapUser = s;
398 }
399 
400 LteUeCphySapProvider*
GetLteUeCphySapProvider()401 LteUePhy::GetLteUeCphySapProvider ()
402 {
403   NS_LOG_FUNCTION (this);
404   return (m_ueCphySapProvider);
405 }
406 
407 void
SetNoiseFigure(double nf)408 LteUePhy::SetNoiseFigure (double nf)
409 {
410   NS_LOG_FUNCTION (this << nf);
411   m_noiseFigure = nf;
412 }
413 
414 double
GetNoiseFigure() const415 LteUePhy::GetNoiseFigure () const
416 {
417   NS_LOG_FUNCTION (this);
418   return m_noiseFigure;
419 }
420 
421 void
SetTxPower(double pow)422 LteUePhy::SetTxPower (double pow)
423 {
424   NS_LOG_FUNCTION (this << pow);
425   m_txPower = pow;
426   m_powerControl->SetTxPower (pow);
427 }
428 
429 double
GetTxPower() const430 LteUePhy::GetTxPower () const
431 {
432   NS_LOG_FUNCTION (this);
433   return m_txPower;
434 }
435 
436 Ptr<LteUePowerControl>
GetUplinkPowerControl() const437 LteUePhy::GetUplinkPowerControl () const
438 {
439   NS_LOG_FUNCTION (this);
440   return m_powerControl;
441 }
442 
443 uint8_t
GetMacChDelay(void) const444 LteUePhy::GetMacChDelay (void) const
445 {
446   return (m_macChTtiDelay);
447 }
448 
449 Ptr<LteSpectrumPhy>
GetDlSpectrumPhy() const450 LteUePhy::GetDlSpectrumPhy () const
451 {
452   return m_downlinkSpectrumPhy;
453 }
454 
455 Ptr<LteSpectrumPhy>
GetUlSpectrumPhy() const456 LteUePhy::GetUlSpectrumPhy () const
457 {
458   return m_uplinkSpectrumPhy;
459 }
460 
461 void
SetNumQoutEvalSf(uint16_t numSubframes)462 LteUePhy::SetNumQoutEvalSf (uint16_t numSubframes)
463 {
464   NS_LOG_FUNCTION (this << numSubframes);
465   NS_ABORT_MSG_IF (numSubframes % 10 != 0, "Number of subframes used for Qout "
466                    "evaluation must be multiple of 10");
467   m_numOfQoutEvalSf = numSubframes;
468 }
469 
470 void
SetNumQinEvalSf(uint16_t numSubframes)471 LteUePhy::SetNumQinEvalSf (uint16_t numSubframes)
472 {
473   NS_LOG_FUNCTION (this << numSubframes);
474   NS_ABORT_MSG_IF (numSubframes % 10 != 0, "Number of subframes used for Qin "
475                    "evaluation must be multiple of 10");
476   m_numOfQinEvalSf = numSubframes;
477 }
478 
479 uint16_t
GetNumQoutEvalSf(void) const480 LteUePhy::GetNumQoutEvalSf (void) const
481 {
482   NS_LOG_FUNCTION (this);
483   return m_numOfQoutEvalSf;
484 }
485 
486 uint16_t
GetNumQinEvalSf(void) const487 LteUePhy::GetNumQinEvalSf (void) const
488 {
489   NS_LOG_FUNCTION (this);
490   return m_numOfQinEvalSf;
491 }
492 
493 void
DoSendMacPdu(Ptr<Packet> p)494 LteUePhy::DoSendMacPdu (Ptr<Packet> p)
495 {
496   NS_LOG_FUNCTION (this);
497 
498   SetMacPdu (p);
499 }
500 
501 
502 void
PhyPduReceived(Ptr<Packet> p)503 LteUePhy::PhyPduReceived (Ptr<Packet> p)
504 {
505   m_uePhySapUser->ReceivePhyPdu (p);
506 }
507 
508 void
SetSubChannelsForTransmission(std::vector<int> mask)509 LteUePhy::SetSubChannelsForTransmission (std::vector <int> mask)
510 {
511   NS_LOG_FUNCTION (this);
512 
513   m_subChannelsForTransmission = mask;
514 
515   Ptr<SpectrumValue> txPsd = CreateTxPowerSpectralDensity ();
516   m_uplinkSpectrumPhy->SetTxPowerSpectralDensity (txPsd);
517 }
518 
519 
520 void
SetSubChannelsForReception(std::vector<int> mask)521 LteUePhy::SetSubChannelsForReception (std::vector <int> mask)
522 {
523   NS_LOG_FUNCTION (this);
524   m_subChannelsForReception = mask;
525 }
526 
527 
528 std::vector <int>
GetSubChannelsForTransmission()529 LteUePhy::GetSubChannelsForTransmission ()
530 {
531   NS_LOG_FUNCTION (this);
532   return m_subChannelsForTransmission;
533 }
534 
535 
536 std::vector <int>
GetSubChannelsForReception()537 LteUePhy::GetSubChannelsForReception ()
538 {
539   NS_LOG_FUNCTION (this);
540   return m_subChannelsForReception;
541 }
542 
543 
544 Ptr<SpectrumValue>
CreateTxPowerSpectralDensity()545 LteUePhy::CreateTxPowerSpectralDensity ()
546 {
547   NS_LOG_FUNCTION (this);
548   LteSpectrumValueHelper psdHelper;
549   Ptr<SpectrumValue> psd = psdHelper.CreateUlTxPowerSpectralDensity (m_ulEarfcn, m_ulBandwidth, m_txPower, GetSubChannelsForTransmission ());
550   m_reportPowerSpectralDensity (m_rnti, psd);
551 
552   return psd;
553 }
554 
555 void
GenerateCtrlCqiReport(const SpectrumValue & sinr)556 LteUePhy::GenerateCtrlCqiReport (const SpectrumValue& sinr)
557 {
558   NS_LOG_FUNCTION (this);
559   /**
560    * We do not generate the CQI report
561    * when the UE is not synchronized to any cell.
562    *
563    * Also, the RLF is detected after the DL CTRL
564    * is received by the UE,therefore, we do not need
565    * to generate the CQI reports and the UE measurements
566    * for a CTRL for which the RLF has been detected.
567    */
568   if (m_cellId == 0)
569     {
570       return;
571     }
572   m_ctrlSinrForRlf = sinr;
573   GenerateCqiRsrpRsrq (sinr);
574 }
575 
576 void
GenerateCqiRsrpRsrq(const SpectrumValue & sinr)577 LteUePhy::GenerateCqiRsrpRsrq (const SpectrumValue& sinr)
578 {
579   NS_LOG_FUNCTION (this << sinr);
580 
581   NS_ASSERT (m_state != CELL_SEARCH);
582   NS_ASSERT (m_cellId > 0);
583 
584   if (m_dlConfigured && m_ulConfigured && (m_rnti > 0))
585     {
586       // check periodic wideband CQI
587       if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriodicity)
588         {
589           NS_LOG_DEBUG ("Reporting P10 CQI at : " << Simulator::Now ().As (Time::MS)
590                                                   << ". Last reported at : " << m_p10CqiLast.As (Time::MS));
591           Ptr<LteUeNetDevice> thisDevice = GetDevice ()->GetObject<LteUeNetDevice> ();
592           Ptr<DlCqiLteControlMessage> msg = CreateDlCqiFeedbackMessage (sinr);
593           if (msg)
594             {
595               DoSendLteControlMessage (msg);
596             }
597           m_p10CqiLast = Simulator::Now ();
598         }
599       // check aperiodic high-layer configured subband CQI
600       if  (Simulator::Now () > m_a30CqiLast + m_a30CqiPeriodicity)
601         {
602           NS_LOG_DEBUG ("Reporting A30 CQI at : " << Simulator::Now ().As (Time::MS)
603                                                   << ". Last reported at : " << m_a30CqiLast.As (Time::MS));
604           Ptr<LteUeNetDevice> thisDevice = GetDevice ()->GetObject<LteUeNetDevice> ();
605           Ptr<DlCqiLteControlMessage> msg = CreateDlCqiFeedbackMessage (sinr);
606           if (msg)
607             {
608               DoSendLteControlMessage (msg);
609             }
610           m_a30CqiLast = Simulator::Now ();
611         }
612     }
613 
614   // Generate PHY trace
615   m_rsrpSinrSampleCounter++;
616   if (m_rsrpSinrSampleCounter == m_rsrpSinrSamplePeriod)
617     {
618       NS_ASSERT_MSG (m_rsReceivedPowerUpdated, " RS received power info obsolete");
619       // RSRP evaluated as averaged received power among RBs
620       double sum = 0.0;
621       uint8_t rbNum = 0;
622       Values::const_iterator it;
623       for (it = m_rsReceivedPower.ConstValuesBegin (); it != m_rsReceivedPower.ConstValuesEnd (); it++)
624         {
625           // convert PSD [W/Hz] to linear power [W] for the single RE
626           // we consider only one RE for the RS since the channel is
627           // flat within the same RB
628           double powerTxW = ((*it) * 180000.0) / 12.0;
629           sum += powerTxW;
630           rbNum++;
631         }
632       double rsrp = (rbNum > 0) ? (sum / rbNum) : DBL_MAX;
633       // averaged SINR among RBs
634       double avSinr = ComputeAvgSinr (sinr);
635 
636       NS_LOG_INFO (this << " cellId " << m_cellId << " rnti " << m_rnti << " RSRP " << rsrp << " SINR " << avSinr << " ComponentCarrierId " << (uint16_t) m_componentCarrierId);
637       //trigger RLF detection only when UE has an active RRC connection
638       //and RLF detection attribute is set to true
639       if (m_isConnected && m_enableRlfDetection)
640         {
641           double avrgSinrForRlf = ComputeAvgSinr (m_ctrlSinrForRlf);
642           RlfDetection (10 * log10 (avrgSinrForRlf));
643         }
644 
645       m_reportCurrentCellRsrpSinrTrace (m_cellId, m_rnti, rsrp, avSinr, (uint16_t) m_componentCarrierId);
646       m_rsrpSinrSampleCounter = 0;
647     }
648 
649   if (m_pssReceived)
650     {
651       // measure instantaneous RSRQ now
652       NS_ASSERT_MSG (m_rsInterferencePowerUpdated, " RS interference power info obsolete");
653 
654       std::list <PssElement>::iterator itPss = m_pssList.begin ();
655       while (itPss != m_pssList.end ())
656         {
657           uint16_t rbNum = 0;
658           double rssiSum = 0.0;
659 
660           Values::const_iterator itIntN = m_rsInterferencePower.ConstValuesBegin ();
661           Values::const_iterator itPj = m_rsReceivedPower.ConstValuesBegin ();
662           for (itPj = m_rsReceivedPower.ConstValuesBegin ();
663                itPj != m_rsReceivedPower.ConstValuesEnd ();
664                itIntN++, itPj++)
665             {
666               rbNum++;
667               // convert PSD [W/Hz] to linear power [W] for the single RE
668               double interfPlusNoisePowerTxW = ((*itIntN) * 180000.0) / 12.0;
669               double signalPowerTxW = ((*itPj) * 180000.0) / 12.0;
670               rssiSum += (2 * (interfPlusNoisePowerTxW + signalPowerTxW));
671             }
672 
673           NS_ASSERT (rbNum == (*itPss).nRB);
674           double rsrq_dB = 10 * log10 ((*itPss).pssPsdSum / rssiSum);
675 
676           if (rsrq_dB > m_pssReceptionThreshold)
677             {
678               NS_LOG_INFO (this << " PSS RNTI " << m_rnti << " cellId " << m_cellId
679                                 << " has RSRQ " << rsrq_dB << " and RBnum " << rbNum);
680               // store measurements
681               std::map <uint16_t, UeMeasurementsElement>::iterator itMeasMap;
682               itMeasMap = m_ueMeasurementsMap.find ((*itPss).cellId);
683               if (itMeasMap != m_ueMeasurementsMap.end ())
684                 {
685                   (*itMeasMap).second.rsrqSum += rsrq_dB;
686                   (*itMeasMap).second.rsrqNum++;
687                 }
688               else
689                 {
690                   NS_LOG_WARN ("race condition of bug 2091 occurred");
691                 }
692             }
693 
694           itPss++;
695 
696         } // end of while (itPss != m_pssList.end ())
697 
698       m_pssList.clear ();
699 
700     } // end of if (m_pssReceived)
701 
702 } // end of void LteUePhy::GenerateCtrlCqiReport (const SpectrumValue& sinr)
703 
704 double
ComputeAvgSinr(const SpectrumValue & sinr)705 LteUePhy::ComputeAvgSinr (const SpectrumValue& sinr)
706 {
707   NS_LOG_FUNCTION (this);
708 
709   // averaged SINR among RBs
710   double sum = 0.0;
711   uint8_t rbNum = 0;
712   Values::const_iterator it;
713 
714   for (it = sinr.ConstValuesBegin (); it != sinr.ConstValuesEnd (); it++)
715     {
716       sum += (*it);
717       rbNum++;
718     }
719 
720   double avrgSinr = (rbNum > 0) ? (sum / rbNum) : DBL_MAX;
721 
722   return avrgSinr;
723 }
724 
725 void
GenerateDataCqiReport(const SpectrumValue & sinr)726 LteUePhy::GenerateDataCqiReport (const SpectrumValue& sinr)
727 {
728   // Not used by UE, CQI are based only on RS
729 }
730 
731 void
GenerateMixedCqiReport(const SpectrumValue & sinr)732 LteUePhy::GenerateMixedCqiReport (const SpectrumValue& sinr)
733 {
734   NS_LOG_FUNCTION (this);
735 
736   /**
737    * We do not generate the CQI report
738    * when the UE is not synchronized to any cell.
739    *
740    * Also, the RLF is detected after the DL CTRL
741    * is received by the UE,therefore, we do not need
742    * to generate the CQI reports and the UE measurements
743    * for a CTRL for which the RLF has been detected.
744    */
745   if (m_cellId == 0)
746     {
747       return;
748     }
749 
750   NS_ASSERT (m_state != CELL_SEARCH);
751   //NOTE: The SINR received by this method is
752   //based on CTRL, which is not used to compute
753   //PDSCH (i.e., data) based SINR. It is used
754   //for RLF detection.
755   m_ctrlSinrForRlf = sinr;
756 
757   SpectrumValue mixedSinr = (m_rsReceivedPower * m_paLinear);
758   if (m_dataInterferencePowerUpdated)
759     {
760       // we have a measurement of interf + noise for the denominator
761       // of SINR = S/(I+N)
762       mixedSinr /= m_dataInterferencePower;
763       m_dataInterferencePowerUpdated = false;
764       NS_LOG_LOGIC ("data interf measurement available, SINR = " << mixedSinr);
765     }
766   else
767     {
768       // we did not see any interference on data, so interference is
769       // there and we have only noise at the denominator of SINR
770       mixedSinr /= (*m_noisePsd);
771       NS_LOG_LOGIC ("no data interf measurement available, SINR = " << mixedSinr);
772     }
773 
774   /*
775    * some RBs are not used in PDSCH and their SINR is very high
776    * for example with bandwidth 25, last RB is not used
777    * it can make avgSinr value very high, what is incorrect
778    */
779   uint32_t rbgSize = GetRbgSize ();
780   uint32_t modulo = m_dlBandwidth % rbgSize;
781   double avgMixedSinr = 0;
782   uint32_t usedRbgNum = 0;
783   for (uint32_t i = 0; i < (m_dlBandwidth - 1 - modulo); i++)
784     {
785       usedRbgNum++;
786       avgMixedSinr += mixedSinr[i];
787     }
788   avgMixedSinr = avgMixedSinr / usedRbgNum;
789   for (uint32_t i = 0; i < modulo; i++)
790     {
791       mixedSinr[m_dlBandwidth - 1 - i] = avgMixedSinr;
792     }
793 
794   GenerateCqiRsrpRsrq (mixedSinr);
795 }
796 
797 void
ReportInterference(const SpectrumValue & interf)798 LteUePhy::ReportInterference (const SpectrumValue& interf)
799 {
800   NS_LOG_FUNCTION (this << interf);
801   m_rsInterferencePowerUpdated = true;
802   m_rsInterferencePower = interf;
803 }
804 
805 void
ReportDataInterference(const SpectrumValue & interf)806 LteUePhy::ReportDataInterference (const SpectrumValue& interf)
807 {
808   NS_LOG_FUNCTION (this << interf);
809 
810   m_dataInterferencePowerUpdated = true;
811   m_dataInterferencePower = interf;
812 }
813 
814 void
ReportRsReceivedPower(const SpectrumValue & power)815 LteUePhy::ReportRsReceivedPower (const SpectrumValue& power)
816 {
817   NS_LOG_FUNCTION (this << power);
818   m_rsReceivedPowerUpdated = true;
819   m_rsReceivedPower = power;
820 
821   if (m_enableUplinkPowerControl)
822     {
823       double sum = 0;
824       uint32_t rbNum = 0;
825       Values::const_iterator it;
826       for (it = m_rsReceivedPower.ConstValuesBegin (); it != m_rsReceivedPower.ConstValuesEnd (); it++)
827         {
828           double powerTxW = ((*it) * 180000);
829           sum += powerTxW;
830           rbNum++;
831         }
832       double rsrp = 10 * log10 (sum) + 30;
833 
834       NS_LOG_INFO ("RSRP: " << rsrp);
835       m_powerControl->SetRsrp (rsrp);
836     }
837 }
838 
839 Ptr<DlCqiLteControlMessage>
CreateDlCqiFeedbackMessage(const SpectrumValue & sinr)840 LteUePhy::CreateDlCqiFeedbackMessage (const SpectrumValue& sinr)
841 {
842   NS_LOG_FUNCTION (this);
843 
844 
845   // apply transmission mode gain
846   NS_ASSERT (m_transmissionMode < m_txModeGain.size ());
847   SpectrumValue newSinr = sinr;
848   newSinr *= m_txModeGain.at (m_transmissionMode);
849 
850   // CREATE DlCqiLteControlMessage
851   Ptr<DlCqiLteControlMessage> msg = Create<DlCqiLteControlMessage> ();
852   CqiListElement_s dlcqi;
853   std::vector<int> cqi;
854   if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriodicity)
855     {
856       cqi = m_amc->CreateCqiFeedbacks (newSinr, m_dlBandwidth);
857 
858       int nLayer = TransmissionModesLayers::TxMode2LayerNum (m_transmissionMode);
859       int nbSubChannels = cqi.size ();
860       double cqiSum = 0.0;
861       int activeSubChannels = 0;
862       // average the CQIs of the different RBs
863       for (int i = 0; i < nbSubChannels; i++)
864         {
865           if (cqi.at (i) != -1)
866             {
867               cqiSum += cqi.at (i);
868               activeSubChannels++;
869             }
870           NS_LOG_DEBUG (this << " subch " << i << " cqi " <<  cqi.at (i));
871         }
872       dlcqi.m_rnti = m_rnti;
873       dlcqi.m_ri = 1; // not yet used
874       dlcqi.m_cqiType = CqiListElement_s::P10; // Peridic CQI using PUCCH wideband
875       NS_ASSERT_MSG (nLayer > 0, " nLayer negative");
876       NS_ASSERT_MSG (nLayer < 3, " nLayer limit is 2s");
877       for (int i = 0; i < nLayer; i++)
878         {
879           if (activeSubChannels > 0)
880             {
881               dlcqi.m_wbCqi.push_back ((uint16_t) cqiSum / activeSubChannels);
882             }
883           else
884             {
885               // approximate with the worst case -> CQI = 1
886               dlcqi.m_wbCqi.push_back (1);
887             }
888         }
889       //NS_LOG_DEBUG (this << " Generate P10 CQI feedback " << (uint16_t) cqiSum / activeSubChannels);
890       dlcqi.m_wbPmi = 0; // not yet used
891       // dl.cqi.m_sbMeasResult others CQI report modes: not yet implemented
892     }
893   else if (Simulator::Now () > m_a30CqiLast + m_a30CqiPeriodicity)
894     {
895       cqi = m_amc->CreateCqiFeedbacks (newSinr, GetRbgSize ());
896       int nLayer = TransmissionModesLayers::TxMode2LayerNum (m_transmissionMode);
897       int nbSubChannels = cqi.size ();
898       int rbgSize = GetRbgSize ();
899       double cqiSum = 0.0;
900       int cqiNum = 0;
901       SbMeasResult_s rbgMeas;
902       //NS_LOG_DEBUG (this << " Create A30 CQI feedback, RBG " << rbgSize << " cqiNum " << nbSubChannels << " band "  << (uint16_t)m_dlBandwidth);
903       for (int i = 0; i < nbSubChannels; i++)
904         {
905           if (cqi.at (i) != -1)
906             {
907               cqiSum += cqi.at (i);
908             }
909           // else "nothing" no CQI is treated as CQI = 0 (worst case scenario)
910           cqiNum++;
911           if (cqiNum == rbgSize)
912             {
913               // average the CQIs of the different RBGs
914               //NS_LOG_DEBUG (this << " RBG CQI "  << (uint16_t) cqiSum / rbgSize);
915               HigherLayerSelected_s hlCqi;
916               hlCqi.m_sbPmi = 0; // not yet used
917               for (int i = 0; i < nLayer; i++)
918                 {
919                   hlCqi.m_sbCqi.push_back ((uint16_t) cqiSum / rbgSize);
920                 }
921               rbgMeas.m_higherLayerSelected.push_back (hlCqi);
922               cqiSum = 0.0;
923               cqiNum = 0;
924             }
925         }
926       dlcqi.m_rnti = m_rnti;
927       dlcqi.m_ri = 1; // not yet used
928       dlcqi.m_cqiType = CqiListElement_s::A30; // Aperidic CQI using PUSCH
929       //dlcqi.m_wbCqi.push_back ((uint16_t) cqiSum / nbSubChannels);
930       dlcqi.m_wbPmi = 0; // not yet used
931       dlcqi.m_sbMeasResult = rbgMeas;
932     }
933 
934   msg->SetDlCqi (dlcqi);
935   return msg;
936 }
937 
938 
939 void
ReportUeMeasurements()940 LteUePhy::ReportUeMeasurements ()
941 {
942   NS_LOG_FUNCTION (this << Simulator::Now ());
943   NS_LOG_DEBUG (this << " Report UE Measurements ");
944 
945   LteUeCphySapUser::UeMeasurementsParameters ret;
946 
947   std::map <uint16_t, UeMeasurementsElement>::iterator it;
948   for (it = m_ueMeasurementsMap.begin (); it != m_ueMeasurementsMap.end (); it++)
949     {
950       double avg_rsrp = (*it).second.rsrpSum / (double)(*it).second.rsrpNum;
951       double avg_rsrq = (*it).second.rsrqSum / (double)(*it).second.rsrqNum;
952       /*
953        * In CELL_SEARCH state, this may result in avg_rsrq = 0/0 = -nan.
954        * UE RRC must take this into account when receiving measurement reports.
955        * TODO remove this shortcoming by calculating RSRQ during CELL_SEARCH
956        */
957       NS_LOG_DEBUG (this << " CellId " << (*it).first
958                          << " RSRP " << avg_rsrp
959                          << " (nSamples " << (uint16_t)(*it).second.rsrpNum << ")"
960                          << " RSRQ " << avg_rsrq
961                          << " (nSamples " << (uint16_t)(*it).second.rsrqNum << ")"
962                          << " ComponentCarrierID " << (uint16_t)m_componentCarrierId);
963 
964       LteUeCphySapUser::UeMeasurementsElement newEl;
965       newEl.m_cellId = (*it).first;
966       newEl.m_rsrp = avg_rsrp;
967       newEl.m_rsrq = avg_rsrq;
968       ret.m_ueMeasurementsList.push_back (newEl);
969       ret.m_componentCarrierId = m_componentCarrierId;
970 
971       // report to UE measurements trace
972       m_reportUeMeasurements (m_rnti, (*it).first, avg_rsrp, avg_rsrq, ((*it).first == m_cellId ? 1 : 0), m_componentCarrierId);
973     }
974 
975   // report to RRC
976   m_ueCphySapUser->ReportUeMeasurements (ret);
977 
978   m_ueMeasurementsMap.clear ();
979   Simulator::Schedule (m_ueMeasurementsFilterPeriod, &LteUePhy::ReportUeMeasurements, this);
980 }
981 
982 void
SetDownlinkCqiPeriodicity(Time cqiPeriodicity)983 LteUePhy::SetDownlinkCqiPeriodicity (Time cqiPeriodicity)
984 {
985   NS_LOG_FUNCTION (this << cqiPeriodicity);
986   m_a30CqiPeriodicity = cqiPeriodicity;
987   m_p10CqiPeriodicity = cqiPeriodicity;
988 }
989 
990 void
DoSendLteControlMessage(Ptr<LteControlMessage> msg)991 LteUePhy::DoSendLteControlMessage (Ptr<LteControlMessage> msg)
992 {
993   NS_LOG_FUNCTION (this << msg);
994 
995   SetControlMessages (msg);
996 }
997 
998 void
DoSendRachPreamble(uint32_t raPreambleId,uint32_t raRnti)999 LteUePhy::DoSendRachPreamble (uint32_t raPreambleId, uint32_t raRnti)
1000 {
1001   NS_LOG_FUNCTION (this << raPreambleId);
1002 
1003   // unlike other control messages, RACH preamble is sent ASAP
1004   Ptr<RachPreambleLteControlMessage> msg = Create<RachPreambleLteControlMessage> ();
1005   msg->SetRapId (raPreambleId);
1006   m_raPreambleId = raPreambleId;
1007   m_raRnti = raRnti;
1008   m_controlMessagesQueue.at (0).push_back (msg);
1009 }
1010 
1011 void
DoNotifyConnectionSuccessful()1012 LteUePhy::DoNotifyConnectionSuccessful ()
1013 {
1014   /**
1015    * Radio link failure detection should take place only on the
1016    * primary carrier to avoid errors due to multiple calls to the
1017    * same methods at the RRC layer
1018    */
1019   if (m_componentCarrierId == 0)
1020     {
1021       m_isConnected = true;
1022       // Initialize the parameters for radio link failure detection
1023       InitializeRlfParams ();
1024     }
1025 }
1026 
1027 
1028 
1029 void
ReceiveLteControlMessageList(std::list<Ptr<LteControlMessage>> msgList)1030 LteUePhy::ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> > msgList)
1031 {
1032   NS_LOG_FUNCTION (this);
1033 
1034   std::list<Ptr<LteControlMessage> >::iterator it;
1035   NS_LOG_DEBUG (this << " I am rnti = " << m_rnti << " and I received msgs " << (uint16_t) msgList.size ());
1036   for (it = msgList.begin (); it != msgList.end (); it++)
1037     {
1038       Ptr<LteControlMessage> msg = (*it);
1039 
1040       if (msg->GetMessageType () == LteControlMessage::DL_DCI)
1041         {
1042           Ptr<DlDciLteControlMessage> msg2 = DynamicCast<DlDciLteControlMessage> (msg);
1043 
1044           DlDciListElement_s dci = msg2->GetDci ();
1045           if (dci.m_rnti != m_rnti)
1046             {
1047               // DCI not for me
1048               continue;
1049             }
1050 
1051           if (dci.m_resAlloc != 0)
1052             {
1053               NS_FATAL_ERROR ("Resource Allocation type not implemented");
1054             }
1055 
1056           std::vector <int> dlRb;
1057 
1058           // translate the DCI to Spectrum framework
1059           uint32_t mask = 0x1;
1060           for (int i = 0; i < 32; i++)
1061             {
1062               if (((dci.m_rbBitmap & mask) >> i) == 1)
1063                 {
1064                   for (int k = 0; k < GetRbgSize (); k++)
1065                     {
1066                       dlRb.push_back ((i * GetRbgSize ()) + k);
1067 //             NS_LOG_DEBUG(this << " RNTI " << m_rnti << " RBG " << i << " DL-DCI allocated PRB " << (i*GetRbgSize()) + k);
1068                     }
1069                 }
1070               mask = (mask << 1);
1071             }
1072           if (m_enableUplinkPowerControl)
1073             {
1074               m_powerControl->ReportTpc (dci.m_tpc);
1075             }
1076 
1077 
1078           // send TB info to LteSpectrumPhy
1079           NS_LOG_DEBUG (this << " UE " << m_rnti << " DL-DCI " << dci.m_rnti << " bitmap "  << dci.m_rbBitmap);
1080           for (uint8_t i = 0; i < dci.m_tbsSize.size (); i++)
1081             {
1082               m_downlinkSpectrumPhy->AddExpectedTb (dci.m_rnti, dci.m_ndi.at (i), dci.m_tbsSize.at (i), dci.m_mcs.at (i), dlRb, i, dci.m_harqProcess, dci.m_rv.at (i), true /* DL */);
1083             }
1084 
1085           SetSubChannelsForReception (dlRb);
1086 
1087 
1088         }
1089       else if (msg->GetMessageType () == LteControlMessage::UL_DCI)
1090         {
1091           // set the uplink bandwidth according to the UL-CQI
1092           Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
1093           UlDciListElement_s dci = msg2->GetDci ();
1094           if (dci.m_rnti != m_rnti)
1095             {
1096               // DCI not for me
1097               continue;
1098             }
1099           NS_LOG_INFO (this << " UL DCI");
1100           std::vector <int> ulRb;
1101           for (int i = 0; i < dci.m_rbLen; i++)
1102             {
1103               ulRb.push_back (i + dci.m_rbStart);
1104               //NS_LOG_DEBUG (this << " UE RB " << i + dci.m_rbStart);
1105             }
1106           m_reportUlPhyResourceBlocks (m_rnti, ulRb);
1107           QueueSubChannelsForTransmission (ulRb);
1108           // fire trace of UL Tx PHY stats
1109           HarqProcessInfoList_t harqInfoList = m_harqPhyModule->GetHarqProcessInfoUl (m_rnti, 0);
1110           PhyTransmissionStatParameters params;
1111           params.m_cellId = m_cellId;
1112           params.m_imsi = 0; // it will be set by DlPhyTransmissionCallback in LteHelper
1113           params.m_timestamp = Simulator::Now ().GetMilliSeconds () + UL_PUSCH_TTIS_DELAY;
1114           params.m_rnti = m_rnti;
1115           params.m_txMode = 0; // always SISO for UE
1116           params.m_layer = 0;
1117           params.m_mcs = dci.m_mcs;
1118           params.m_size = dci.m_tbSize;
1119           params.m_rv = harqInfoList.size ();
1120           params.m_ndi = dci.m_ndi;
1121           params.m_ccId = m_componentCarrierId;
1122           m_ulPhyTransmission (params);
1123           // pass the info to the MAC
1124           m_uePhySapUser->ReceiveLteControlMessage (msg);
1125         }
1126       else if (msg->GetMessageType () == LteControlMessage::RAR)
1127         {
1128           Ptr<RarLteControlMessage> rarMsg = DynamicCast<RarLteControlMessage> (msg);
1129           if (rarMsg->GetRaRnti () == m_raRnti)
1130             {
1131               for (std::list<RarLteControlMessage::Rar>::const_iterator it = rarMsg->RarListBegin (); it != rarMsg->RarListEnd (); ++it)
1132                 {
1133                   if (it->rapId != m_raPreambleId)
1134                     {
1135                       // UL grant not for me
1136                       continue;
1137                     }
1138                   else
1139                     {
1140                       NS_LOG_INFO ("received RAR RNTI " << m_raRnti);
1141                       // set the uplink bandwidth according to the UL grant
1142                       std::vector <int> ulRb;
1143                       for (int i = 0; i < it->rarPayload.m_grant.m_rbLen; i++)
1144                         {
1145                           ulRb.push_back (i + it->rarPayload.m_grant.m_rbStart);
1146                         }
1147 
1148                       QueueSubChannelsForTransmission (ulRb);
1149                       // pass the info to the MAC
1150                       m_uePhySapUser->ReceiveLteControlMessage (msg);
1151                       // reset RACH variables with out of range values
1152                       m_raPreambleId = 255;
1153                       m_raRnti = 11;
1154                     }
1155                 }
1156             }
1157         }
1158       else if (msg->GetMessageType () == LteControlMessage::MIB)
1159         {
1160           NS_LOG_INFO ("received MIB");
1161           NS_ASSERT (m_cellId > 0);
1162           Ptr<MibLteControlMessage> msg2 = DynamicCast<MibLteControlMessage> (msg);
1163           m_ueCphySapUser->RecvMasterInformationBlock (m_cellId, msg2->GetMib ());
1164         }
1165       else if (msg->GetMessageType () == LteControlMessage::SIB1)
1166         {
1167           NS_LOG_INFO ("received SIB1");
1168           NS_ASSERT (m_cellId > 0);
1169           Ptr<Sib1LteControlMessage> msg2 = DynamicCast<Sib1LteControlMessage> (msg);
1170           m_ueCphySapUser->RecvSystemInformationBlockType1 (m_cellId, msg2->GetSib1 ());
1171         }
1172       else
1173         {
1174           // pass the message to UE-MAC
1175           m_uePhySapUser->ReceiveLteControlMessage (msg);
1176         }
1177 
1178     }
1179 
1180 
1181 }
1182 
1183 
1184 void
ReceivePss(uint16_t cellId,Ptr<SpectrumValue> p)1185 LteUePhy::ReceivePss (uint16_t cellId, Ptr<SpectrumValue> p)
1186 {
1187   NS_LOG_FUNCTION (this << cellId << (*p));
1188 
1189   double sum = 0.0;
1190   uint16_t nRB = 0;
1191   Values::const_iterator itPi;
1192   for (itPi = p->ConstValuesBegin (); itPi != p->ConstValuesEnd (); itPi++)
1193     {
1194       // convert PSD [W/Hz] to linear power [W] for the single RE
1195       double powerTxW = ((*itPi) * 180000.0) / 12.0;
1196       sum += powerTxW;
1197       nRB++;
1198     }
1199 
1200   // measure instantaneous RSRP now
1201   double rsrp_dBm = 10 * log10 (1000 * (sum / (double)nRB));
1202   NS_LOG_INFO (this << " PSS RNTI " << m_rnti << " cellId " << m_cellId
1203                     << " has RSRP " << rsrp_dBm << " and RBnum " << nRB);
1204   // note that m_pssReceptionThreshold does not apply here
1205 
1206   // store measurements
1207   std::map <uint16_t, UeMeasurementsElement>::iterator itMeasMap = m_ueMeasurementsMap.find (cellId);
1208   if (itMeasMap == m_ueMeasurementsMap.end ())
1209     {
1210       // insert new entry
1211       UeMeasurementsElement newEl;
1212       newEl.rsrpSum = rsrp_dBm;
1213       newEl.rsrpNum = 1;
1214       newEl.rsrqSum = 0;
1215       newEl.rsrqNum = 0;
1216       m_ueMeasurementsMap.insert (std::pair <uint16_t, UeMeasurementsElement> (cellId, newEl));
1217     }
1218   else
1219     {
1220       (*itMeasMap).second.rsrpSum += rsrp_dBm;
1221       (*itMeasMap).second.rsrpNum++;
1222     }
1223 
1224   /*
1225    * Collect the PSS for later processing in GenerateCtrlCqiReport()
1226    * (to be called from ChunkProcessor after RX is finished).
1227    */
1228   m_pssReceived = true;
1229   PssElement el;
1230   el.cellId = cellId;
1231   el.pssPsdSum = sum;
1232   el.nRB = nRB;
1233   m_pssList.push_back (el);
1234 
1235 } // end of void LteUePhy::ReceivePss (uint16_t cellId, Ptr<SpectrumValue> p)
1236 
1237 
1238 void
QueueSubChannelsForTransmission(std::vector<int> rbMap)1239 LteUePhy::QueueSubChannelsForTransmission (std::vector <int> rbMap)
1240 {
1241   m_subChannelsForTransmissionQueue.at (m_macChTtiDelay - 1) = rbMap;
1242 }
1243 
1244 
1245 void
SubframeIndication(uint32_t frameNo,uint32_t subframeNo)1246 LteUePhy::SubframeIndication (uint32_t frameNo, uint32_t subframeNo)
1247 {
1248   NS_LOG_FUNCTION (this << frameNo << subframeNo);
1249 
1250   NS_ASSERT_MSG (frameNo > 0, "the SRS index check code assumes that frameNo starts at 1");
1251 
1252   // refresh internal variables
1253   m_rsReceivedPowerUpdated = false;
1254   m_rsInterferencePowerUpdated = false;
1255   m_pssReceived = false;
1256 
1257   if (m_ulConfigured)
1258     {
1259       // update uplink transmission mask according to previous UL-CQIs
1260       std::vector <int> rbMask = m_subChannelsForTransmissionQueue.at (0);
1261       SetSubChannelsForTransmission (m_subChannelsForTransmissionQueue.at (0));
1262 
1263       // shift the queue
1264       for (uint8_t i = 1; i < m_macChTtiDelay; i++)
1265         {
1266           m_subChannelsForTransmissionQueue.at (i - 1) = m_subChannelsForTransmissionQueue.at (i);
1267         }
1268       m_subChannelsForTransmissionQueue.at (m_macChTtiDelay - 1).clear ();
1269 
1270       if (m_srsConfigured && (m_srsStartTime <= Simulator::Now ()))
1271         {
1272 
1273           NS_ASSERT_MSG (subframeNo > 0 && subframeNo <= 10, "the SRS index check code assumes that subframeNo starts at 1");
1274           if ((((frameNo - 1) * 10 + (subframeNo - 1)) % m_srsPeriodicity) == m_srsSubframeOffset)
1275             {
1276               NS_LOG_INFO ("frame " << frameNo << " subframe " << subframeNo << " sending SRS (offset=" << m_srsSubframeOffset << ", period=" << m_srsPeriodicity << ")");
1277               m_sendSrsEvent = Simulator::Schedule (UL_SRS_DELAY_FROM_SUBFRAME_START,
1278                                                     &LteUePhy::SendSrs,
1279                                                     this);
1280             }
1281         }
1282 
1283       std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
1284       // send packets in queue
1285       NS_LOG_LOGIC (this << " UE - start slot for PUSCH + PUCCH - RNTI " << m_rnti << " CELLID " << m_cellId);
1286       // send the current burts of packets
1287       Ptr<PacketBurst> pb = GetPacketBurst ();
1288       if (pb)
1289         {
1290           if (m_enableUplinkPowerControl)
1291             {
1292               m_txPower = m_powerControl->GetPuschTxPower (rbMask);
1293               SetSubChannelsForTransmission (rbMask);
1294             }
1295           m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
1296         }
1297       else
1298         {
1299           // send only PUCCH (ideal: fake null bandwidth signal)
1300           if (ctrlMsg.size () > 0)
1301             {
1302               NS_LOG_LOGIC (this << " UE - start TX PUCCH (NO PUSCH)");
1303               std::vector <int> dlRb;
1304 
1305               if (m_enableUplinkPowerControl)
1306                 {
1307                   m_txPower = m_powerControl->GetPucchTxPower (dlRb);
1308                 }
1309 
1310               SetSubChannelsForTransmission (dlRb);
1311               m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
1312             }
1313           else
1314             {
1315               NS_LOG_LOGIC (this << " UE - UL NOTHING TO SEND");
1316             }
1317         }
1318     }  // m_configured
1319 
1320   // trigger the MAC
1321   m_uePhySapUser->SubframeIndication (frameNo, subframeNo);
1322 
1323   m_subframeNo = subframeNo;
1324   ++subframeNo;
1325   if (subframeNo > 10)
1326     {
1327       ++frameNo;
1328       subframeNo = 1;
1329     }
1330 
1331   // schedule next subframe indication
1332   Simulator::Schedule (Seconds (GetTti ()), &LteUePhy::SubframeIndication, this, frameNo, subframeNo);
1333 }
1334 
1335 
1336 void
SendSrs()1337 LteUePhy::SendSrs ()
1338 {
1339   NS_LOG_FUNCTION (this << " UE " << m_rnti << " start tx SRS, cell Id " << (uint32_t) m_cellId);
1340   NS_ASSERT (m_cellId > 0);
1341   // set the current tx power spectral density (full bandwidth)
1342   std::vector <int> dlRb;
1343   for (uint8_t i = 0; i < m_ulBandwidth; i++)
1344     {
1345       dlRb.push_back (i);
1346     }
1347 
1348   if (m_enableUplinkPowerControl)
1349     {
1350       m_txPower = m_powerControl->GetSrsTxPower (dlRb);
1351     }
1352 
1353   SetSubChannelsForTransmission (dlRb);
1354   m_uplinkSpectrumPhy->StartTxUlSrsFrame ();
1355 }
1356 
1357 
1358 void
DoReset()1359 LteUePhy::DoReset ()
1360 {
1361   NS_LOG_FUNCTION (this);
1362 
1363   m_rnti = 0;
1364   m_cellId = 0;
1365   m_isConnected = false;
1366   m_transmissionMode = 0;
1367   m_srsPeriodicity = 0;
1368   m_srsConfigured = false;
1369   m_dlConfigured = false;
1370   m_ulConfigured = false;
1371   m_raPreambleId = 255; // value out of range
1372   m_raRnti = 11; // value out of range
1373   m_rsrpSinrSampleCounter = 0;
1374   m_p10CqiLast = Simulator::Now ();
1375   m_a30CqiLast = Simulator::Now ();
1376   m_paLinear = 1;
1377 
1378   m_packetBurstQueue.clear ();
1379   m_controlMessagesQueue.clear ();
1380   m_subChannelsForTransmissionQueue.clear ();
1381   for (int i = 0; i < m_macChTtiDelay; i++)
1382     {
1383       Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
1384       m_packetBurstQueue.push_back (pb);
1385       std::list<Ptr<LteControlMessage> > l;
1386       m_controlMessagesQueue.push_back (l);
1387     }
1388   std::vector <int> ulRb;
1389   m_subChannelsForTransmissionQueue.resize (m_macChTtiDelay, ulRb);
1390 
1391   m_sendSrsEvent.Cancel ();
1392   m_downlinkSpectrumPhy->Reset ();
1393   m_uplinkSpectrumPhy->Reset ();
1394   m_pssList.clear ();
1395   /**
1396    * Call the EndRx() method of the interference model for DL control and data
1397    * to cancel any ongoing downlink reception of control and data info.
1398    */
1399   m_downlinkSpectrumPhy->m_interferenceCtrl->EndRx ();
1400   m_downlinkSpectrumPhy->m_interferenceData->EndRx ();
1401 
1402 } // end of void LteUePhy::DoReset ()
1403 
1404 void
DoStartCellSearch(uint32_t dlEarfcn)1405 LteUePhy::DoStartCellSearch (uint32_t dlEarfcn)
1406 {
1407   NS_LOG_FUNCTION (this << dlEarfcn);
1408   m_dlEarfcn = dlEarfcn;
1409   DoSetDlBandwidth (6); // configure DL for receiving PSS
1410   SwitchToState (CELL_SEARCH);
1411 }
1412 
1413 void
DoSynchronizeWithEnb(uint16_t cellId,uint32_t dlEarfcn)1414 LteUePhy::DoSynchronizeWithEnb (uint16_t cellId, uint32_t dlEarfcn)
1415 {
1416   NS_LOG_FUNCTION (this << cellId << dlEarfcn);
1417   m_dlEarfcn = dlEarfcn;
1418   DoSynchronizeWithEnb (cellId);
1419 }
1420 
1421 void
DoSynchronizeWithEnb(uint16_t cellId)1422 LteUePhy::DoSynchronizeWithEnb (uint16_t cellId)
1423 {
1424   NS_LOG_FUNCTION (this << cellId);
1425 
1426   if (cellId == 0)
1427     {
1428       NS_FATAL_ERROR ("Cell ID shall not be zero");
1429     }
1430 
1431   m_cellId = cellId;
1432   m_downlinkSpectrumPhy->SetCellId (cellId);
1433   m_uplinkSpectrumPhy->SetCellId (cellId);
1434 
1435   // configure DL for receiving the BCH with the minimum bandwidth
1436   DoSetDlBandwidth (6);
1437 
1438   m_dlConfigured = false;
1439   m_ulConfigured = false;
1440 
1441   SwitchToState (SYNCHRONIZED);
1442 }
1443 
1444 void
DoSetDlBandwidth(uint16_t dlBandwidth)1445 LteUePhy::DoSetDlBandwidth (uint16_t dlBandwidth)
1446 {
1447   NS_LOG_FUNCTION (this << (uint32_t) dlBandwidth);
1448   if (m_dlBandwidth != dlBandwidth or !m_dlConfigured)
1449     {
1450       m_dlBandwidth = dlBandwidth;
1451 
1452       static const int Type0AllocationRbg[4] = {
1453         10,     // RGB size 1
1454         26,     // RGB size 2
1455         63,     // RGB size 3
1456         110     // RGB size 4
1457       };  // see table 7.1.6.1-1 of 36.213
1458       for (int i = 0; i < 4; i++)
1459         {
1460           if (dlBandwidth < Type0AllocationRbg[i])
1461             {
1462               m_rbgSize = i + 1;
1463               break;
1464             }
1465         }
1466 
1467       m_noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (m_dlEarfcn, m_dlBandwidth, m_noiseFigure);
1468       m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (m_noisePsd);
1469       m_downlinkSpectrumPhy->GetChannel ()->AddRx (m_downlinkSpectrumPhy);
1470     }
1471   m_dlConfigured = true;
1472 }
1473 
1474 
1475 void
DoConfigureUplink(uint32_t ulEarfcn,uint16_t ulBandwidth)1476 LteUePhy::DoConfigureUplink (uint32_t ulEarfcn, uint16_t ulBandwidth)
1477 {
1478   m_ulEarfcn = ulEarfcn;
1479   m_ulBandwidth = ulBandwidth;
1480   m_ulConfigured = true;
1481 }
1482 
1483 void
DoConfigureReferenceSignalPower(int8_t referenceSignalPower)1484 LteUePhy::DoConfigureReferenceSignalPower (int8_t referenceSignalPower)
1485 {
1486   NS_LOG_FUNCTION (this);
1487   m_powerControl->ConfigureReferenceSignalPower (referenceSignalPower);
1488 }
1489 
1490 void
DoSetRnti(uint16_t rnti)1491 LteUePhy::DoSetRnti (uint16_t rnti)
1492 {
1493   NS_LOG_FUNCTION (this << rnti);
1494   m_rnti = rnti;
1495 
1496   m_powerControl->SetCellId (m_cellId);
1497   m_powerControl->SetRnti (m_rnti);
1498 }
1499 
1500 void
DoSetTransmissionMode(uint8_t txMode)1501 LteUePhy::DoSetTransmissionMode (uint8_t txMode)
1502 {
1503   NS_LOG_FUNCTION (this << (uint16_t)txMode);
1504   m_transmissionMode = txMode;
1505   m_downlinkSpectrumPhy->SetTransmissionMode (txMode);
1506 }
1507 
1508 void
DoSetSrsConfigurationIndex(uint16_t srcCi)1509 LteUePhy::DoSetSrsConfigurationIndex (uint16_t srcCi)
1510 {
1511   NS_LOG_FUNCTION (this << srcCi);
1512   m_srsPeriodicity = GetSrsPeriodicity (srcCi);
1513   m_srsSubframeOffset = GetSrsSubframeOffset (srcCi);
1514   m_srsConfigured = true;
1515 
1516   // a guard time is needed for the case where the SRS periodicity is changed dynamically at run time
1517   // if we use a static one, we can have a 0ms guard time
1518   m_srsStartTime = Simulator::Now () + MilliSeconds (0);
1519   NS_LOG_DEBUG (this << " UE SRS P " << m_srsPeriodicity << " RNTI " << m_rnti << " offset " << m_srsSubframeOffset << " cellId " << m_cellId << " CI " << srcCi);
1520 }
1521 
1522 void
DoSetPa(double pa)1523 LteUePhy::DoSetPa (double pa)
1524 {
1525   NS_LOG_FUNCTION (this << pa);
1526   m_paLinear = pow (10,(pa / 10));
1527 }
1528 
1529 void
DoSetRsrpFilterCoefficient(uint8_t rsrpFilterCoefficient)1530 LteUePhy::DoSetRsrpFilterCoefficient (uint8_t rsrpFilterCoefficient)
1531 {
1532   NS_LOG_FUNCTION (this << (uint16_t) (rsrpFilterCoefficient));
1533   m_powerControl->SetRsrpFilterCoefficient (rsrpFilterCoefficient);
1534 }
1535 
1536 void
DoResetPhyAfterRlf()1537 LteUePhy::DoResetPhyAfterRlf ()
1538 {
1539   NS_LOG_FUNCTION (this);
1540   m_downlinkSpectrumPhy->m_harqPhyModule->ClearDlHarqBuffer (m_rnti); //flush HARQ buffers
1541   m_dataInterferencePowerUpdated = false;
1542   m_rsInterferencePowerUpdated = false;
1543   m_pssReceived = false;
1544   DoReset ();
1545 }
1546 
1547 void
DoResetRlfParams()1548 LteUePhy::DoResetRlfParams ()
1549 {
1550   NS_LOG_FUNCTION (this);
1551 
1552   InitializeRlfParams ();
1553 }
1554 
1555 void
DoStartInSnycDetection()1556 LteUePhy::DoStartInSnycDetection ()
1557 {
1558   NS_LOG_FUNCTION (this);
1559   // indicates that the downlink radio link quality has to be monitored for in-sync indications
1560   m_downlinkInSync = false;
1561 }
1562 
1563 void
DoSetImsi(uint64_t imsi)1564 LteUePhy::DoSetImsi (uint64_t imsi)
1565 {
1566   NS_LOG_FUNCTION (this);
1567   m_imsi = imsi;
1568 }
1569 
1570 void
InitializeRlfParams()1571 LteUePhy::InitializeRlfParams ()
1572 {
1573   NS_LOG_FUNCTION (this);
1574   m_numOfSubframes = 0;
1575   m_sinrDbFrame = 0;
1576   m_numOfFrames = 0;
1577   m_downlinkInSync = true;
1578 }
1579 
1580 void
RlfDetection(double sinrDb)1581 LteUePhy::RlfDetection (double sinrDb)
1582 {
1583   NS_LOG_FUNCTION (this << sinrDb);
1584   m_sinrDbFrame += sinrDb;
1585   m_numOfSubframes++;
1586   NS_LOG_LOGIC ("No of Subframes: " << m_numOfSubframes << " UE synchronized: " << m_downlinkInSync);
1587   //check for out_of_snyc indications first when UE is both DL and UL synchronized
1588   //m_downlinkInSync=true indicates that the evaluation is for out-of-sync indications
1589   if (m_downlinkInSync && m_numOfSubframes == 10)
1590     {
1591       /**
1592        * For every frame, if the downlink radio link quality(avg SINR)
1593        * is less than the threshold Qout, then the frame cannot be decoded
1594        */
1595       if ((m_sinrDbFrame / m_numOfSubframes) < m_qOut)
1596         {
1597           m_numOfFrames++; //increment the counter if a frame cannot be decoded
1598           NS_LOG_LOGIC ("No of Frames which cannot be decoded: " << m_numOfFrames);
1599         }
1600       else
1601         {
1602           /**
1603            * If the downlink radio link quality(avg SINR) is greater
1604            * than the threshold Qout, then the frame counter is reset
1605            * since only consecutive frames should be considered.
1606            */
1607           NS_LOG_INFO ("Resetting frame counter at phy. Current value = " << m_numOfFrames);
1608           m_numOfFrames = 0;
1609           // Also reset the sync indicator counter at RRC
1610           m_ueCphySapUser->ResetSyncIndicationCounter ();
1611         }
1612       m_numOfSubframes = 0;
1613       m_sinrDbFrame = 0;
1614     }
1615   /**
1616    * Once the number of consecutive frames which cannot be decoded equals
1617    * the Qout evaluation period (i.e 200ms), then an out-of-sync indication
1618    * is sent to the RRC layer
1619    */
1620   if (m_downlinkInSync && (m_numOfFrames * 10) == m_numOfQoutEvalSf)
1621     {
1622       NS_LOG_LOGIC ("At " << Simulator::Now ().As (Time::MS)
1623                           << " ms UE PHY sending out of snyc indication to UE RRC layer");
1624       m_ueCphySapUser->NotifyOutOfSync ();
1625       m_numOfFrames = 0;
1626     }
1627   //check for in_snyc indications when T310 timer is started
1628   //m_downlinkInSync=false indicates that the evaluation is for in-sync indications
1629   if (!m_downlinkInSync && m_numOfSubframes == 10)
1630     {
1631       /**
1632        * For every frame, if the downlink radio link quality(avg SINR)
1633        * is greater than the threshold Qin, then the frame can be
1634        * successfully decoded.
1635        */
1636       if ((m_sinrDbFrame / m_numOfSubframes) > m_qIn)
1637         {
1638           m_numOfFrames++; //increment the counter if a frame can be decoded
1639           NS_LOG_LOGIC ("No of Frames successfully decoded: " << m_numOfFrames);
1640         }
1641       else
1642         {
1643           /**
1644            * If the downlink radio link quality(avg SINR) is less
1645            * than the threshold Qin, then the frame counter is reset
1646            * since only consecutive frames should be considered
1647            */
1648           m_numOfFrames = 0;
1649           // Also reset the sync indicator counter at RRC
1650           m_ueCphySapUser->ResetSyncIndicationCounter ();
1651         }
1652       m_numOfSubframes = 0;
1653       m_sinrDbFrame = 0;
1654     }
1655   /**
1656    * Once the number of consecutive frames which can be decoded equals the Qin evaluation period (i.e 100ms),
1657    * then an in-sync indication is sent to the RRC layer
1658    */
1659   if (!m_downlinkInSync && (m_numOfFrames * 10) == m_numOfQinEvalSf)
1660     {
1661       NS_LOG_LOGIC ("At " << Simulator::Now ().As (Time::MS)
1662                           << " ms UE PHY sending in snyc indication to UE RRC layer");
1663       m_ueCphySapUser->NotifyInSync ();
1664       m_numOfFrames = 0;
1665     }
1666 }
1667 
1668 
1669 void
SetTxMode1Gain(double gain)1670 LteUePhy::SetTxMode1Gain (double gain)
1671 {
1672   SetTxModeGain (1, gain);
1673 }
1674 
1675 void
SetTxMode2Gain(double gain)1676 LteUePhy::SetTxMode2Gain (double gain)
1677 {
1678   SetTxModeGain (2, gain);
1679 }
1680 
1681 void
SetTxMode3Gain(double gain)1682 LteUePhy::SetTxMode3Gain (double gain)
1683 {
1684   SetTxModeGain (3, gain);
1685 }
1686 
1687 void
SetTxMode4Gain(double gain)1688 LteUePhy::SetTxMode4Gain (double gain)
1689 {
1690   SetTxModeGain (4, gain);
1691 }
1692 
1693 void
SetTxMode5Gain(double gain)1694 LteUePhy::SetTxMode5Gain (double gain)
1695 {
1696   SetTxModeGain (5, gain);
1697 }
1698 
1699 void
SetTxMode6Gain(double gain)1700 LteUePhy::SetTxMode6Gain (double gain)
1701 {
1702   SetTxModeGain (6, gain);
1703 }
1704 
1705 void
SetTxMode7Gain(double gain)1706 LteUePhy::SetTxMode7Gain (double gain)
1707 {
1708   SetTxModeGain (7, gain);
1709 }
1710 
1711 
1712 void
SetTxModeGain(uint8_t txMode,double gain)1713 LteUePhy::SetTxModeGain (uint8_t txMode, double gain)
1714 {
1715   NS_LOG_FUNCTION (this << gain);
1716   // convert to linear
1717   double gainLin = std::pow (10.0, (gain / 10.0));
1718   if (m_txModeGain.size () < txMode)
1719     {
1720       m_txModeGain.resize (txMode);
1721     }
1722   std::vector <double> temp;
1723   temp = m_txModeGain;
1724   m_txModeGain.clear ();
1725   for (uint8_t i = 0; i < temp.size (); i++)
1726     {
1727       if (i == txMode - 1)
1728         {
1729           m_txModeGain.push_back (gainLin);
1730         }
1731       else
1732         {
1733           m_txModeGain.push_back (temp.at (i));
1734         }
1735     }
1736   // forward the info to DL LteSpectrumPhy
1737   m_downlinkSpectrumPhy->SetTxModeGain (txMode, gain);
1738 }
1739 
1740 
1741 
1742 void
EnqueueDlHarqFeedback(DlInfoListElement_s m)1743 LteUePhy::EnqueueDlHarqFeedback (DlInfoListElement_s m)
1744 {
1745   NS_LOG_FUNCTION (this);
1746   // get the feedback from LteSpectrumPhy and send it through ideal PUCCH to eNB
1747   Ptr<DlHarqFeedbackLteControlMessage> msg = Create<DlHarqFeedbackLteControlMessage> ();
1748   msg->SetDlHarqFeedback (m);
1749   SetControlMessages (msg);
1750 }
1751 
1752 void
SetHarqPhyModule(Ptr<LteHarqPhy> harq)1753 LteUePhy::SetHarqPhyModule (Ptr<LteHarqPhy> harq)
1754 {
1755   m_harqPhyModule = harq;
1756 }
1757 
1758 
1759 LteUePhy::State
GetState() const1760 LteUePhy::GetState () const
1761 {
1762   NS_LOG_FUNCTION (this);
1763   return m_state;
1764 }
1765 
1766 
1767 void
SwitchToState(State newState)1768 LteUePhy::SwitchToState (State newState)
1769 {
1770   NS_LOG_FUNCTION (this << newState);
1771   State oldState = m_state;
1772   m_state = newState;
1773   NS_LOG_INFO (this << " cellId=" << m_cellId << " rnti=" << m_rnti
1774                     << " UePhy " << ToString (oldState)
1775                     << " --> " << ToString (newState));
1776   m_stateTransitionTrace (m_cellId, m_rnti, oldState, newState);
1777 }
1778 
1779 
1780 } // namespace ns3
1781