A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
lte-ue-phy.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Giuseppe Piro <g.piro@poliba.it>
19  * Marco Miozzo <marco.miozzo@cttc.es>
20  * Nicola Baldo <nbaldo@cttc.es>
21  */
22 
23 #include <ns3/object-factory.h>
24 #include <ns3/log.h>
25 #include <cmath>
26 #include <ns3/simulator.h>
27 #include <ns3/double.h>
28 #include "lte-ue-phy.h"
29 #include "lte-enb-phy.h"
30 #include "lte-net-device.h"
31 #include "lte-ue-net-device.h"
32 #include "lte-enb-net-device.h"
34 #include "lte-amc.h"
35 #include "lte-ue-mac.h"
36 #include "ff-mac-common.h"
38 #include <ns3/lte-common.h>
39 
40 
41 NS_LOG_COMPONENT_DEFINE ("LteUePhy");
42 
43 namespace ns3 {
44 
45 
46 
47 
48 // duration of data portion of UL subframe
49 // = TTI - 1 symbol for SRS - 1ns as margin to avoid overlapping simulator events
50 // (symbol duration in nanoseconds = TTI / 14 (rounded))
51 // in other words, duration of data portion of UL subframe = TTI*(13/14) -1ns
52 static const Time UL_DATA_DURATION = NanoSeconds (1e6 - 71429 - 1);
53 
54 // delay from subframe start to transmission of SRS
55 // = TTI - 1 symbol for SRS
56 static const Time UL_SRS_DELAY_FROM_SUBFRAME_START = NanoSeconds (1e6 - 71429);
57 
58 
59 
60 
62 // member SAP forwarders
64 
65 
67 {
68 public:
70 
71  // inherited from LtePhySapProvider
72  virtual void SendMacPdu (Ptr<Packet> p);
73  virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
75  virtual void SetTransmissionMode (uint8_t txMode);
76  virtual void SetSrsConfigurationIndex (uint16_t srcCi);
77 
78 private:
80 };
81 
83 {
84 
85 }
86 
87 
88 void
90 {
91  m_phy->DoSendMacPdu (p);
92 }
93 
94 void
95 UeMemberLteUePhySapProvider::SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth)
96 {
97  m_phy->DoSetBandwidth (ulBandwidth, dlBandwidth);
98 }
99 
100 void
102 {
104 }
105 
106 void
108 {
109  m_phy->DoSetTransmissionMode (txMode);
110 }
111 
112 void
114 {
116 }
117 
118 
120 // generic LteUePhy methods
122 
123 
125 
126 
128 {
129  NS_LOG_FUNCTION (this);
130  NS_FATAL_ERROR ("This constructor should not be called");
131 }
132 
134  : LtePhy (dlPhy, ulPhy),
135  m_p10CqiPeriocity (MilliSeconds (1)),
136  // ideal behavior
137  m_p10CqiLast (MilliSeconds (0)),
138  m_a30CqiPeriocity (MilliSeconds (1)),
139  // ideal behavior
140  m_a30CqiLast (MilliSeconds (0)),
141  m_rnti (0),
142  m_srsPeriodicity (0)
143 {
144  m_amc = CreateObject <LteAmc> ();
147  for (int i = 0; i < m_macChTtiDelay; i++)
148  {
149  Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
150  m_packetBurstQueue.push_back (pb);
151  std::list<Ptr<LteControlMessage> > l;
152  m_controlMessagesQueue.push_back (l);
153  }
154  std::vector <int> ulRb;
155  m_subChannelsForTransmissionQueue.resize (m_macChTtiDelay, ulRb);
156 
157  NS_ASSERT_MSG (Simulator::Now ().GetNanoSeconds () == 0,
158  "Cannot create UE devices after simulation started");
160 }
161 
162 
164 {
165  m_txModeGain.clear ();
166 }
167 
168 void
170 {
171  NS_LOG_FUNCTION (this);
172  delete m_uePhySapProvider;
174 }
175 
176 
177 
178 TypeId
180 {
181  static TypeId tid = TypeId ("ns3::LteUePhy")
182  .SetParent<LtePhy> ()
183  .AddConstructor<LteUePhy> ()
184  .AddAttribute ("TxPower",
185  "Transmission power in dBm",
186  DoubleValue (10.0),
187  MakeDoubleAccessor (&LteUePhy::SetTxPower,
189  MakeDoubleChecker<double> ())
190  .AddAttribute ("NoiseFigure",
191  "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver."
192  " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is "
193  "\"the difference in decibels (dB) between"
194  " the noise output of the actual receiver to the noise output of an "
195  " ideal receiver with the same overall gain and bandwidth when the receivers "
196  " are connected to sources at the standard noise temperature T0.\" "
197  "In this model, we consider T0 = 290K.",
198  DoubleValue (9.0),
199  MakeDoubleAccessor (&LteUePhy::SetNoiseFigure,
201  MakeDoubleChecker<double> ())
202  .AddAttribute ("TxMode1Gain",
203  "Transmission mode 1 gain in dB",
204  DoubleValue (0.0),
205  MakeDoubleAccessor (&LteUePhy::SetTxMode1Gain ),
206  MakeDoubleChecker<double> ())
207  .AddAttribute ("TxMode2Gain",
208  "Transmission mode 2 gain in dB",
209  DoubleValue (4.2),
210  MakeDoubleAccessor (&LteUePhy::SetTxMode2Gain ),
211  MakeDoubleChecker<double> ())
212  .AddAttribute ("TxMode3Gain",
213  "Transmission mode 3 gain in dB",
214  DoubleValue (-2.8),
215  MakeDoubleAccessor (&LteUePhy::SetTxMode3Gain ),
216  MakeDoubleChecker<double> ())
217  .AddAttribute ("TxMode4Gain",
218  "Transmission mode 4 gain in dB",
219  DoubleValue (0.0),
220  MakeDoubleAccessor (&LteUePhy::SetTxMode4Gain ),
221  MakeDoubleChecker<double> ())
222  .AddAttribute ("TxMode5Gain",
223  "Transmission mode 5 gain in dB",
224  DoubleValue (0.0),
225  MakeDoubleAccessor (&LteUePhy::SetTxMode5Gain ),
226  MakeDoubleChecker<double> ())
227  .AddAttribute ("TxMode6Gain",
228  "Transmission mode 6 gain in dB",
229  DoubleValue (0.0),
230  MakeDoubleAccessor (&LteUePhy::SetTxMode6Gain ),
231  MakeDoubleChecker<double> ())
232  .AddAttribute ("TxMode7Gain",
233  "Transmission mode 7 gain in dB",
234  DoubleValue (0.0),
235  MakeDoubleAccessor (&LteUePhy::SetTxMode7Gain ),
236  MakeDoubleChecker<double> ())
237  ;
238  return tid;
239 }
240 
241 void
243 {
244  NS_LOG_FUNCTION (this);
247  LtePhy::DoStart ();
248 }
249 
250 void
252 {
253  NS_LOG_FUNCTION (this);
254  m_uePhySapUser = s;
255 }
256 
259 {
260  NS_LOG_FUNCTION (this);
261  return (m_uePhySapProvider);
262 }
263 
264 void
266 {
267  NS_LOG_FUNCTION (this << nf);
268  m_noiseFigure = nf;
269 }
270 
271 double
273 {
274  NS_LOG_FUNCTION (this);
275  return m_noiseFigure;
276 }
277 
278 void
280 {
281  NS_LOG_FUNCTION (this << pow);
282  m_txPower = pow;
283 }
284 
285 double
287 {
288  NS_LOG_FUNCTION (this);
289  return m_txPower;
290 }
291 
292 
293 uint8_t
295 {
296  return (m_macChTtiDelay);
297 }
298 
299 void
301 {
302  NS_LOG_FUNCTION (this);
303 
304  SetMacPdu (p);
305 }
306 
307 
308 void
310 {
312 }
313 
314 void
316 {
317  NS_LOG_FUNCTION (this);
318 
320 
323 }
324 
325 
326 void
327 LteUePhy::SetSubChannelsForReception (std::vector <int> mask)
328 {
329  NS_LOG_FUNCTION (this);
331 }
332 
333 
334 std::vector <int>
336 {
337  NS_LOG_FUNCTION (this);
339 }
340 
341 
342 std::vector <int>
344 {
345  NS_LOG_FUNCTION (this);
347 }
348 
349 
352 {
353  NS_LOG_FUNCTION (this);
354  LteSpectrumValueHelper psdHelper;
356 
357  return psd;
358 }
359 
360 void
362 {
363  NS_LOG_FUNCTION (this);
364  // check periodic wideband CQI
366  {
371  }
372  // check aperiodic high-layer configured subband CQI
374  {
379  }
380 }
381 
382 void
384 {
385  // Not used by UE, CQI are based only on RS
386 }
387 
388 
389 
392 {
393  NS_LOG_FUNCTION (this);
394 
395  // apply transmission mode gain
397  SpectrumValue newSinr = sinr;
398  newSinr *= m_txModeGain.at (m_transmissionMode);
399 // std::vector<int> cqi = m_amc->CreateCqiFeedbacks (newSinr);
400 
401 
402 
403  // CREATE DlCqiLteControlMessage
404  Ptr<DlCqiLteControlMessage> msg = Create<DlCqiLteControlMessage> ();
405  CqiListElement_s dlcqi;
406  std::vector<int> cqi;
408  {
409  cqi = m_amc->CreateCqiFeedbacks (newSinr, m_dlBandwidth);
410 
412  int nbSubChannels = cqi.size ();
413  double cqiSum = 0.0;
414  int activeSubChannels = 0;
415  // average the CQIs of the different RBs
416  for (int i = 0; i < nbSubChannels; i++)
417  {
418  if (cqi.at (i) != -1)
419  {
420  cqiSum += cqi.at (i);
421  activeSubChannels++;
422  }
423  NS_LOG_DEBUG (this << " subch " << i << " cqi " << cqi.at (i));
424  }
425  dlcqi.m_rnti = m_rnti;
426  dlcqi.m_ri = 1; // not yet used
427  dlcqi.m_cqiType = CqiListElement_s::P10; // Peridic CQI using PUCCH wideband
428  NS_ASSERT_MSG (nLayer > 0, " nLayer negative");
429  NS_ASSERT_MSG (nLayer < 3, " nLayer limit is 2s");
430  for (int i = 0; i < nLayer; i++)
431  {
432  if (activeSubChannels > 0)
433  {
434  dlcqi.m_wbCqi.push_back ((uint16_t) cqiSum / activeSubChannels);
435  }
436  else
437  {
438  // approximate with the worst case -> CQI = 1
439  dlcqi.m_wbCqi.push_back (1);
440  }
441  }
442  //NS_LOG_DEBUG (this << " Generate P10 CQI feedback " << (uint16_t) cqiSum / activeSubChannels);
443  dlcqi.m_wbPmi = 0; // not yet used
444  // dl.cqi.m_sbMeasResult others CQI report modes: not yet implemented
445  }
447  {
448  cqi = m_amc->CreateCqiFeedbacks (newSinr, GetRbgSize ());
450  int nbSubChannels = cqi.size ();
451  int rbgSize = GetRbgSize ();
452  double cqiSum = 0.0;
453  int cqiNum = 0;
454  SbMeasResult_s rbgMeas;
455  //NS_LOG_DEBUG (this << " Create A30 CQI feedback, RBG " << rbgSize << " cqiNum " << nbSubChannels << " band " << (uint16_t)m_dlBandwidth);
456  for (int i = 0; i < nbSubChannels; i++)
457  {
458  if (cqi.at (i) != -1)
459  {
460  cqiSum += cqi.at (i);
461  }
462  // else "nothing" no CQI is treated as CQI = 0 (worst case scenario)
463  cqiNum++;
464  if (cqiNum == rbgSize)
465  {
466  // average the CQIs of the different RBGs
467  //NS_LOG_DEBUG (this << " RBG CQI " << (uint16_t) cqiSum / rbgSize);
468  HigherLayerSelected_s hlCqi;
469  hlCqi.m_sbPmi = 0; // not yet used
470  for (int i = 0; i < nLayer; i++)
471  {
472  hlCqi.m_sbCqi.push_back ((uint16_t) cqiSum / rbgSize);
473  }
474  rbgMeas.m_higherLayerSelected.push_back (hlCqi);
475  cqiSum = 0.0;
476  cqiNum = 0;
477  }
478  }
479  dlcqi.m_rnti = m_rnti;
480  dlcqi.m_ri = 1; // not yet used
481  dlcqi.m_cqiType = CqiListElement_s::A30; // Aperidic CQI using PUSCH
482  //dlcqi.m_wbCqi.push_back ((uint16_t) cqiSum / nbSubChannels);
483  dlcqi.m_wbPmi = 0; // not yet used
484  dlcqi.m_sbMeasResult = rbgMeas;
485  }
486 
487  msg->SetDlCqi (dlcqi);
488  return msg;
489 }
490 
491 
492 
493 void
495 {
496  NS_LOG_FUNCTION (this << msg);
498  Ptr<LteEnbNetDevice> remoteDevice = thisDevice->GetTargetEnb ();
499  SetControlMessages (msg);
500 }
501 
502 
503 void
505 {
506  NS_LOG_FUNCTION (this);
507 
508  std::list<Ptr<LteControlMessage> >::iterator it;
509  for (it = msgList.begin (); it != msgList.end(); it++)
510  {
511  Ptr<LteControlMessage> msg = (*it);
512 
514  {
515  Ptr<DlDciLteControlMessage> msg2 = DynamicCast<DlDciLteControlMessage> (msg);
516 
517  DlDciListElement_s dci = msg2->GetDci ();
518  if (dci.m_rnti != m_rnti)
519  {
520  // DCI not for me
521  continue;
522  }
523 
524  if (dci.m_resAlloc != 0)
525  {
526  NS_FATAL_ERROR ("Resource Allocation type not implemented");
527  }
528 
529  std::vector <int> dlRb;
530 
531  // translate the DCI to Spectrum framework
532  uint32_t mask = 0x1;
533  for (int i = 0; i < 32; i++)
534  {
535  if (((dci.m_rbBitmap & mask) >> i) == 1)
536  {
537  for (int k = 0; k < GetRbgSize (); k++)
538  {
539  dlRb.push_back ((i * GetRbgSize ()) + k);
540  //NS_LOG_DEBUG(this << "DL-DCI allocated PRB " << (i*GetRbgSize()) + k);
541  }
542  }
543  mask = (mask << 1);
544  }
545 
546  // send TB info to LteSpectrumPhy
547  NS_LOG_DEBUG (this << " UE " << m_rnti << " DL-DCI " << dci.m_rnti << " bitmap " << dci.m_rbBitmap);
548  for (uint8_t i = 0; i < dci.m_tbsSize.size (); i++)
549  {
550  m_downlinkSpectrumPhy->AddExpectedTb (dci.m_rnti, dci.m_tbsSize.at (i), dci.m_mcs.at (i), dlRb, i);
551  }
552 
554 
555 
556  }
557  else if (msg->GetMessageType () == LteControlMessage::UL_DCI)
558  {
559  // set the uplink bandwidht according to the UL-CQI
560  NS_LOG_DEBUG (this << " UL DCI");
561  Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
562  UlDciListElement_s dci = msg2->GetDci ();
563  if (dci.m_rnti != m_rnti)
564  {
565  // DCI not for me
566  continue;
567  }
568  std::vector <int> ulRb;
569  for (int i = 0; i < dci.m_rbLen; i++)
570  {
571  ulRb.push_back (i + dci.m_rbStart);
572  //NS_LOG_DEBUG (this << " UE RB " << i + dci.m_rbStart);
573  }
574 
576  // pass the info to the MAC
578  }
579  else
580  {
581  // pass the message to UE-MAC
583  }
584 
585  }
586 
587 
588 }
589 
590 
591 void
593 {
595 }
596 
597 
598 void
599 LteUePhy::SubframeIndication (uint32_t frameNo, uint32_t subframeNo)
600 {
601  NS_LOG_LOGIC (this << frameNo << subframeNo);
602 
603  // update uplink transmission mask according to previous UL-CQIs
605  // shift the queue
606  for (uint8_t i = 1; i < m_macChTtiDelay; i++)
607  {
609  }
610  m_subChannelsForTransmissionQueue.at (m_macChTtiDelay-1).clear ();
611 
612  bool srs = false;
613  // check SRS periodicity
614  if (m_srsCounter==1)
615  {
616  srs = true;
618  }
619  else
620  {
621  m_srsCounter--;
622  }
623 
624  if (srs)
625  {
628  this);
629  }
630 
631 
632  std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
633  // send packets in queue
634  // send the current burts of packets
636  if (pb)
637  {
638  NS_LOG_LOGIC (this << " UE - start TX PUSCH + PUCCH");
640  }
641  else
642  {
643  // send only PUCCH (ideal: fake full bandwidth signal)
644  if (ctrlMsg.size ()>0)
645  {
646  NS_LOG_LOGIC (this << " UE - start TX PUCCH (NO PUSCH)");
647  std::vector <int> dlRb;
648  for (uint8_t i = 0; i < m_ulBandwidth; i++)
649  {
650  dlRb.push_back (i);
651  }
654  }
655  }
656 
657 
658  // trigger the MAC
659  m_uePhySapUser->SubframeIndication (frameNo, subframeNo);
660 
661 
662  ++subframeNo;
663  if (subframeNo > 10)
664  {
665  ++frameNo;
666  subframeNo = 1;
667  }
668 
669  // schedule next subframe indication
670  Simulator::Schedule (Seconds (GetTti ()), &LteUePhy::SubframeIndication, this, frameNo, subframeNo);
671 }
672 
673 void
675 {
676  NS_LOG_FUNCTION (this << " UE " << m_rnti << " start tx SRS, cell Id " << m_cellId);
677  // set the current tx power spectral density (full bandwidth)
678  std::vector <int> dlRb;
679  for (uint8_t i = 0; i < m_ulBandwidth; i++)
680  {
681  dlRb.push_back (i);
682  }
685 }
686 
687 
688 
689 void
690 LteUePhy::SetEnbCellId (uint16_t cellId)
691 {
692  m_enbCellId = cellId;
694  m_uplinkSpectrumPhy->SetCellId (cellId);
695 }
696 
697 
698 
699 void
700 LteUePhy::SetRnti (uint16_t rnti)
701 {
702  NS_LOG_FUNCTION (this << rnti);
703  m_rnti = rnti;
704 }
705 
706 
707 void
709 {
710  NS_LOG_FUNCTION (this << (uint16_t)txMode);
711  m_transmissionMode = txMode;
713 }
714 
715 void
717 {
718  NS_LOG_FUNCTION (this << srcCi);
720  m_srsCounter = GetSrsSubframeOffset (srcCi) + 1;
721  NS_LOG_DEBUG (this << " UE SRS P " << m_srsPeriodicity << " RNTI " << m_rnti << " offset " << GetSrsSubframeOffset (srcCi) << " cellId " << m_cellId << " CI " << srcCi);
722 }
723 
724 
725 void
727 {
728  SetTxModeGain (1, gain);
729 }
730 
731 void
733 {
734  SetTxModeGain (2, gain);
735 }
736 
737 void
739 {
740  SetTxModeGain (3, gain);
741 }
742 
743 void
745 {
746  SetTxModeGain (4, gain);
747 }
748 
749 void
751 {
752  SetTxModeGain (5, gain);
753 }
754 
755 void
757 {
758  SetTxModeGain (6, gain);
759 }
760 
761 void
763 {
764  SetTxModeGain (7, gain);
765 }
766 
767 
768 void
769 LteUePhy::SetTxModeGain (uint8_t txMode, double gain)
770 {
771  NS_LOG_FUNCTION (this << gain);
772  // convert to linear
773  double gainLin = std::pow (10.0, (gain / 10.0));
774  if (m_txModeGain.size () < txMode)
775  {
776  m_txModeGain.resize (txMode);
777  }
778  std::vector <double> temp;
779  temp = m_txModeGain;
780  m_txModeGain.clear ();
781  for (uint8_t i = 0; i < temp.size (); i++)
782  {
783  if (i==txMode-1)
784  {
785  m_txModeGain.push_back (gainLin);
786  }
787  else
788  {
789  m_txModeGain.push_back (temp.at (i));
790  }
791  }
792  // forward the info to DL LteSpectrumPhy
793  m_downlinkSpectrumPhy->SetTxModeGain (txMode, gain);
794 }
795 
796 
797 
798 
799 } // namespace ns3