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