OLD | NEW |
(Empty) | |
| 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 * Modified by: NIST |
| 22 */ |
| 23 |
| 24 #include <ns3/object-factory.h> |
| 25 #include <ns3/log.h> |
| 26 #include <cfloat> |
| 27 #include <cmath> |
| 28 #include <ns3/simulator.h> |
| 29 #include <ns3/double.h> |
| 30 #include "nist-lte-ue-phy.h" |
| 31 #include "nist-lte-enb-phy.h" |
| 32 #include "nist-lte-net-device.h" |
| 33 #include "nist-lte-ue-net-device.h" |
| 34 #include "nist-lte-enb-net-device.h" |
| 35 #include "nist-lte-spectrum-value-helper.h" |
| 36 #include "nist-lte-amc.h" |
| 37 #include "nist-lte-ue-mac.h" |
| 38 #include "nist-ff-mac-common.h" |
| 39 #include "nist-lte-chunk-processor.h" |
| 40 #include <ns3/nist-lte-common.h> |
| 41 #include <ns3/pointer.h> |
| 42 #include <ns3/boolean.h> |
| 43 #include <ns3/nist-lte-ue-power-control.h> |
| 44 #include "nist-lte-radio-bearer-tag.h" |
| 45 #include <ns3/node.h> |
| 46 #include <fstream> |
| 47 namespace ns3 { |
| 48 |
| 49 NS_LOG_COMPONENT_DEFINE ("NistLteUePhy"); |
| 50 |
| 51 |
| 52 |
| 53 /** |
| 54 * Duration of the data portion of a UL subframe. |
| 55 * Equals to "TTI length - 1 symbol length for SRS - margin". |
| 56 * The margin is 1 nanosecond and is intended to avoid overlapping simulator |
| 57 * events. The duration of one symbol is TTI/14 (rounded). In other words, |
| 58 * duration of data portion of UL subframe = 1 ms * (13/14) - 1 ns. |
| 59 */ |
| 60 static const Time UL_DATA_DURATION = NanoSeconds (1e6 - 71429 - 1);· |
| 61 |
| 62 /** |
| 63 * Delay from subframe start to transmission of SRS. |
| 64 * Equals to "TTI length - 1 symbol for SRS". |
| 65 */ |
| 66 static const Time UL_SRS_DELAY_FROM_SUBFRAME_START = NanoSeconds (1e6 - 71429);· |
| 67 |
| 68 |
| 69 |
| 70 |
| 71 //////////////////////////////////////// |
| 72 // member SAP forwarders |
| 73 //////////////////////////////////////// |
| 74 |
| 75 |
| 76 class NistUeMemberLteUePhySapProvider : public NistLteUePhySapProvider |
| 77 { |
| 78 public: |
| 79 NistUeMemberLteUePhySapProvider (NistLteUePhy* phy); |
| 80 |
| 81 // inherited from NistLtePhySapProvider |
| 82 virtual void SendMacPdu (Ptr<Packet> p); |
| 83 virtual void SendNistLteControlMessage (Ptr<NistLteControlMessage> msg); |
| 84 virtual void SendRachPreamble (uint32_t prachId, uint32_t raRnti); |
| 85 |
| 86 private: |
| 87 NistLteUePhy* m_phy; |
| 88 }; |
| 89 |
| 90 NistUeMemberLteUePhySapProvider::NistUeMemberLteUePhySapProvider (NistLteUePhy*
phy) : m_phy (phy) |
| 91 { |
| 92 |
| 93 } |
| 94 |
| 95 void |
| 96 NistUeMemberLteUePhySapProvider::SendMacPdu (Ptr<Packet> p) |
| 97 { |
| 98 m_phy->DoSendMacPdu (p); |
| 99 } |
| 100 |
| 101 void |
| 102 NistUeMemberLteUePhySapProvider::SendNistLteControlMessage (Ptr<NistLteControlMe
ssage> msg) |
| 103 { |
| 104 m_phy->DoSendNistLteControlMessage (msg); |
| 105 } |
| 106 |
| 107 void |
| 108 NistUeMemberLteUePhySapProvider::SendRachPreamble (uint32_t prachId, uint32_t ra
Rnti) |
| 109 { |
| 110 m_phy->DoSendRachPreamble (prachId, raRnti); |
| 111 } |
| 112 ·· |
| 113 //////////////////////////////////////// |
| 114 // NistLteUePhy methods |
| 115 //////////////////////////////////////// |
| 116 |
| 117 /// Map each of UE PHY states to its string representation. |
| 118 static const std::string g_uePhyStateName[NistLteUePhy::NUM_STATES] = |
| 119 { |
| 120 "CELL_SEARCH", |
| 121 "SYNCHRONIZED" |
| 122 }; |
| 123 |
| 124 /** |
| 125 * \param s The UE PHY state. |
| 126 * \return The string representation of the given state. |
| 127 */ |
| 128 static inline const std::string & ToString (NistLteUePhy::State s) |
| 129 { |
| 130 return g_uePhyStateName[s]; |
| 131 } |
| 132 |
| 133 |
| 134 NS_OBJECT_ENSURE_REGISTERED (NistLteUePhy); |
| 135 |
| 136 |
| 137 NistLteUePhy::NistLteUePhy () |
| 138 { |
| 139 NS_LOG_FUNCTION (this); |
| 140 NS_FATAL_ERROR ("This constructor should not be called"); |
| 141 } |
| 142 |
| 143 NistLteUePhy::NistLteUePhy (Ptr<NistLteSpectrumPhy> dlPhy, Ptr<NistLteSpectrumPh
y> ulPhy) |
| 144 : NistLtePhy (dlPhy, ulPhy), |
| 145 m_p10CqiPeriocity (MilliSeconds (1)), // ideal behavior |
| 146 m_a30CqiPeriocity (MilliSeconds (1)), // ideal behavior |
| 147 m_uePhySapUser (0), |
| 148 m_ueCphySapUser (0), |
| 149 m_state (CELL_SEARCH), |
| 150 m_subframeNo (0), |
| 151 m_rsReceivedPowerUpdated (false), |
| 152 m_rsInterferencePowerUpdated (false), |
| 153 m_dataInterferencePowerUpdated (false), |
| 154 m_pssReceived (false), |
| 155 m_ueMeasurementsFilterPeriod (MilliSeconds (200)), |
| 156 m_ueMeasurementsFilterLast (MilliSeconds (0)), |
| 157 m_rsrpSinrSampleCounter (0), |
| 158 m_tFirstScanning(MilliSeconds (0)), |
| 159 m_ueSlssScanningInProgress(false), |
| 160 m_ueSlssMeasurementInProgress(false), |
| 161 m_currNMeasPeriods(0), |
| 162 m_currFrameNo(0), |
| 163 m_currSubframeNo(0), |
| 164 m_resyncRequested(false), |
| 165 m_waitingNextScPeriod(false) |
| 166 { |
| 167 m_amc = CreateObject <NistLteAmc> (); |
| 168 m_powerControl = CreateObject <NistLteUePowerControl> (); |
| 169 m_uePhySapProvider = new NistUeMemberLteUePhySapProvider (this); |
| 170 m_ueCphySapProvider = new NistMemberLteUeCphySapProvider<NistLteUePhy> (this); |
| 171 m_macChTtiDelay = UL_PUSCH_TTIS_DELAY; |
| 172 |
| 173 m_nextScanRdm = CreateObject<UniformRandomVariable> (); |
| 174 |
| 175 NS_ASSERT_MSG (Simulator::Now ().GetNanoSeconds () == 0, |
| 176 "Cannot create UE devices after simulation started"); |
| 177 |
| 178 //Simulator::ScheduleNow (&NistLteUePhy::SubframeIndication, this, 1, 1); //No
w it is done in the function SetInitialSubFrameIndication |
| 179 |
| 180 Simulator::Schedule (m_ueMeasurementsFilterPeriod, &NistLteUePhy::ReportNistUe
Measurements, this); |
| 181 |
| 182 m_slTxPoolInfo.m_pool = NULL; |
| 183 m_slTxPoolInfo.m_currentScPeriod.frameNo = 0; |
| 184 m_slTxPoolInfo.m_currentScPeriod.subframeNo = 0; |
| 185 m_slTxPoolInfo.m_nextScPeriod.frameNo = 0; |
| 186 m_slTxPoolInfo.m_nextScPeriod.subframeNo = 0; |
| 187 ·· |
| 188 m_discTxPools.m_pool = NULL; |
| 189 m_discTxPools.m_currentDiscPeriod.frameNo = 0; |
| 190 m_discTxPools.m_currentDiscPeriod.subframeNo = 0; |
| 191 m_discTxPools.m_nextDiscPeriod.frameNo = 0; |
| 192 m_discTxPools.m_nextDiscPeriod.subframeNo = 0; |
| 193 |
| 194 m_discRxApps.clear ();· |
| 195 m_discTxApps.clear ();· |
| 196 |
| 197 DoReset (); |
| 198 } |
| 199 |
| 200 NistLteUePhy::~NistLteUePhy () |
| 201 { |
| 202 m_txModeGain.clear (); |
| 203 } |
| 204 |
| 205 void |
| 206 NistLteUePhy::DoDispose () |
| 207 { |
| 208 NS_LOG_FUNCTION (this); |
| 209 delete m_uePhySapProvider; |
| 210 delete m_ueCphySapProvider; |
| 211 if (m_sidelinkSpectrumPhy) { |
| 212 m_sidelinkSpectrumPhy->Dispose (); |
| 213 m_sidelinkSpectrumPhy = 0; |
| 214 } |
| 215 NistLtePhy::DoDispose (); |
| 216 } |
| 217 |
| 218 |
| 219 |
| 220 TypeId |
| 221 NistLteUePhy::GetTypeId (void) |
| 222 { |
| 223 static TypeId tid = TypeId ("ns3::NistLteUePhy") |
| 224 .SetParent<NistLtePhy> () |
| 225 .AddConstructor<NistLteUePhy> () |
| 226 .AddAttribute ("TxPower", |
| 227 "Transmission power in dBm", |
| 228 DoubleValue (10.0), |
| 229 MakeDoubleAccessor (&NistLteUePhy::SetTxPower,· |
| 230 &NistLteUePhy::GetTxPower), |
| 231 MakeDoubleChecker<double> ()) |
| 232 .AddAttribute ("NoiseFigure", |
| 233 "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities
in the receiver." |
| 234 " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_
figure), this is " |
| 235 "\"the difference in decibels (dB) between" |
| 236 " the noise output of the actual receiver to the noise output
of an " |
| 237 " ideal receiver with the same overall gain and bandwidth whe
n the receivers " |
| 238 " are connected to sources at the standard noise temperature
T0.\" " |
| 239 "In this model, we consider T0 = 290K.", |
| 240 DoubleValue (9.0), |
| 241 MakeDoubleAccessor (&NistLteUePhy::SetNoiseFigure,· |
| 242 &NistLteUePhy::GetNoiseFigure), |
| 243 MakeDoubleChecker<double> ()) |
| 244 .AddAttribute ("TxMode1Gain", |
| 245 "Transmission mode 1 gain in dB", |
| 246 DoubleValue (0.0), |
| 247 MakeDoubleAccessor (&NistLteUePhy::SetTxMode1Gain), |
| 248 MakeDoubleChecker<double> ()) |
| 249 .AddAttribute ("TxMode2Gain", |
| 250 "Transmission mode 2 gain in dB", |
| 251 DoubleValue (4.2), |
| 252 MakeDoubleAccessor (&NistLteUePhy::SetTxMode2Gain), |
| 253 MakeDoubleChecker<double> ()) |
| 254 .AddAttribute ("TxMode3Gain", |
| 255 "Transmission mode 3 gain in dB", |
| 256 DoubleValue (-2.8), |
| 257 MakeDoubleAccessor (&NistLteUePhy::SetTxMode3Gain), |
| 258 MakeDoubleChecker<double> ()) |
| 259 .AddAttribute ("TxMode4Gain", |
| 260 "Transmission mode 4 gain in dB", |
| 261 DoubleValue (0.0), |
| 262 MakeDoubleAccessor (&NistLteUePhy::SetTxMode4Gain), |
| 263 MakeDoubleChecker<double> ()) |
| 264 .AddAttribute ("TxMode5Gain", |
| 265 "Transmission mode 5 gain in dB", |
| 266 DoubleValue (0.0), |
| 267 MakeDoubleAccessor (&NistLteUePhy::SetTxMode5Gain), |
| 268 MakeDoubleChecker<double> ()) |
| 269 .AddAttribute ("TxMode6Gain", |
| 270 "Transmission mode 6 gain in dB", |
| 271 DoubleValue (0.0), |
| 272 MakeDoubleAccessor (&NistLteUePhy::SetTxMode6Gain), |
| 273 MakeDoubleChecker<double> ()) |
| 274 .AddAttribute ("TxMode7Gain", |
| 275 "Transmission mode 7 gain in dB", |
| 276 DoubleValue (0.0), |
| 277 MakeDoubleAccessor (&NistLteUePhy::SetTxMode7Gain), |
| 278 MakeDoubleChecker<double> ()) |
| 279 .AddTraceSource ("ReportCurrentCellRsrpSinr", |
| 280 "RSRP and SINR statistics.", |
| 281 MakeTraceSourceAccessor (&NistLteUePhy::m_reportCurrentCell
RsrpSinrTrace), |
| 282 "ns3::NistLteUePhy::RsrpSinrTracedCallback") |
| 283 .AddAttribute ("RsrpSinrSamplePeriod", |
| 284 "The sampling period for reporting RSRP-SINR stats (default v
alue 1)", |
| 285 UintegerValue (1), |
| 286 MakeUintegerAccessor (&NistLteUePhy::m_rsrpSinrSamplePeriod), |
| 287 MakeUintegerChecker<uint16_t> ()) |
| 288 .AddTraceSource ("UlPhyTransmission", |
| 289 "DL transmission PHY layer statistics.", |
| 290 MakeTraceSourceAccessor (&NistLteUePhy::m_ulPhyTransmission
), |
| 291 "ns3::NistPhyTransmissionStatParameters::TracedCallback") |
| 292 .AddAttribute ("DlSpectrumPhy", |
| 293 "The downlink NistLteSpectrumPhy associated to this NistLtePh
y", |
| 294 TypeId::ATTR_GET, |
| 295 PointerValue (), |
| 296 MakePointerAccessor (&NistLteUePhy::GetDlSpectrumPhy), |
| 297 MakePointerChecker <NistLteSpectrumPhy> ()) |
| 298 .AddAttribute ("UlSpectrumPhy", |
| 299 "The uplink NistLteSpectrumPhy associated to this NistLtePhy"
, |
| 300 TypeId::ATTR_GET, |
| 301 PointerValue (), |
| 302 MakePointerAccessor (&NistLteUePhy::GetUlSpectrumPhy), |
| 303 MakePointerChecker <NistLteSpectrumPhy> ()) |
| 304 .AddAttribute ("SlSpectrumPhy", |
| 305 "The uplink NistLteSpectrumPhy associated to this NistLtePhy"
, |
| 306 TypeId::ATTR_GET, |
| 307 PointerValue (), |
| 308 MakePointerAccessor (&NistLteUePhy::GetSlSpectrumPhy), |
| 309 MakePointerChecker <NistLteSpectrumPhy> ()) |
| 310 .AddAttribute ("RsrqUeMeasThreshold", |
| 311 "Receive threshold for PSS on RSRQ [dB]", |
| 312 DoubleValue (-1000.0), |
| 313 MakeDoubleAccessor (&NistLteUePhy::m_pssReceptionThreshold), |
| 314 MakeDoubleChecker<double> ()) |
| 315 .AddAttribute ("RsrpUeMeasThreshold", |
| 316 "Receive threshold for RSRP [dB]", |
| 317 DoubleValue (-1000.0), //to avoid changing the default behavi
or, make it low so that it acts as if it was not used |
| 318 MakeDoubleAccessor (&NistLteUePhy::m_rsrpReceptionThreshold), |
| 319 MakeDoubleChecker<double> ()) |
| 320 .AddAttribute ("NistUeMeasurementsFilterPeriod", |
| 321 "Time period for reporting UE measurements, i.e., the" |
| 322 "length of layer-1 filtering.", |
| 323 TimeValue (MilliSeconds (200)), |
| 324 MakeTimeAccessor (&NistLteUePhy::m_ueMeasurementsFilterPeriod
), |
| 325 MakeTimeChecker ()) |
| 326 .AddTraceSource ("ReportNistUeMeasurements", |
| 327 "Report UE measurements RSRP (dBm) and RSRQ (dB).", |
| 328 MakeTraceSourceAccessor (&NistLteUePhy::m_reportNistUeMeasu
rements), |
| 329 "ns3::NistLteUePhy::RsrpRsrqTracedCallback") |
| 330 .AddTraceSource ("StateTransition", |
| 331 "Trace fired upon every UE PHY state transition", |
| 332 MakeTraceSourceAccessor (&NistLteUePhy::m_stateTransitionTr
ace), |
| 333 "ns3::NistLteUePhy::StateTracedCallback") |
| 334 .AddAttribute ("EnableUplinkPowerControl", |
| 335 "If true, Uplink Power Control will be enabled.", |
| 336 BooleanValue (true), |
| 337 MakeBooleanAccessor (&NistLteUePhy::m_enableUplinkPowerContro
l), |
| 338 MakeBooleanChecker ()) |
| 339 .AddAttribute ("UeSlssInterScanningPeriodMax", |
| 340 "The upper bound of the uniform random variable for the interv
al between SyncRef selection processes", |
| 341 TimeValue(MilliSeconds(2000)), |
| 342 MakeTimeAccessor(&NistLteUePhy::SetUeSlssInterScanningPeriodMa
x), |
| 343 MakeTimeChecker()) |
| 344 .AddAttribute ("UeSlssInterScanningPeriodMin", |
| 345 "The lower bound of the uniform random variable for the interv
al between SyncRef selection processes", |
| 346 TimeValue(MilliSeconds(2000)), |
| 347 MakeTimeAccessor(&NistLteUePhy::SetUeSlssInterScanningPeriodMi
n), |
| 348 MakeTimeChecker()) |
| 349 .AddAttribute("UeSlssScanningPeriod", |
| 350 "How long the UE will search for SyncRefs (scanning)", |
| 351 TimeValue(MilliSeconds(40)), |
| 352 MakeTimeAccessor(&NistLteUePhy::m_ueSlssScanningPeriod), |
| 353 MakeTimeChecker()) |
| 354 .AddAttribute("UeSlssMeasurementPeriod", |
| 355 "How long the UE will perform SLSS L1 measurements for SyncRef
selection (measurement)", |
| 356 TimeValue(MilliSeconds(400)), |
| 357 MakeTimeAccessor(&NistLteUePhy::m_ueSlssMeasurementPeriod), |
| 358 MakeTimeChecker()) |
| 359 .AddAttribute("UeSlssEvaluationPeriod", |
| 360 "How long the UE will perform SLSS L1 measurements to determine
cease/initiation of SLSS transmission (evaluation)", |
| 361 TimeValue(MilliSeconds(800)), |
| 362 MakeTimeAccessor(&NistLteUePhy::m_ueSlssEvaluationPeriod), |
| 363 MakeTimeChecker()) |
| 364 .AddAttribute ("NSamplesSrsrpMeas", |
| 365 "The maximum number of samples to take during SLSS L1 measurem
ents for each SyncRef", |
| 366 UintegerValue (4), |
| 367 MakeUintegerAccessor (&NistLteUePhy::m_nSamplesSrsrpMeas), |
| 368 MakeUintegerChecker<uint16_t> ()) |
| 369 .AddAttribute("UeRandomInitialSubframeIndication", |
| 370 "If True, the first frame and subframe values (beginning of the
simulation) are chosen randomly, if False they are fixed to 1,1 respectively", |
| 371 BooleanValue(false), |
| 372 MakeBooleanAccessor(&NistLteUePhy::SetInitialSubFrameIndication
), |
| 373 MakeBooleanChecker()) |
| 374 .AddAttribute ("MinSrsrp", |
| 375 "The minimum S-RSRP required to consider a SyncRef detectable"
, |
| 376 DoubleValue(-125), |
| 377 MakeDoubleAccessor (&NistLteUePhy::m_minSrsrp), |
| 378 MakeDoubleChecker<double>()) |
| 379 //discovery |
| 380 .AddTraceSource ("DiscoveryAnnouncement", |
| 381 "trace to track the announcement of discovery messages", |
| 382 MakeTraceSourceAccessor (&NistLteUePhy::m_discoveryAnnounce
mentTrace), |
| 383 "ns3::NistLteUePhy::DiscoveryAnnouncementTracedCallback") |
| 384 ; |
| 385 return tid; |
| 386 } |
| 387 |
| 388 void |
| 389 NistLteUePhy::DoInitialize () |
| 390 { |
| 391 NS_LOG_FUNCTION (this); |
| 392 NistLtePhy::DoInitialize (); |
| 393 } |
| 394 |
| 395 void |
| 396 NistLteUePhy::SetNistLteUePhySapUser (NistLteUePhySapUser* s) |
| 397 { |
| 398 NS_LOG_FUNCTION (this); |
| 399 m_uePhySapUser = s; |
| 400 } |
| 401 |
| 402 NistLteUePhySapProvider* |
| 403 NistLteUePhy::GetNistLteUePhySapProvider () |
| 404 { |
| 405 NS_LOG_FUNCTION (this); |
| 406 return (m_uePhySapProvider); |
| 407 } |
| 408 |
| 409 |
| 410 void |
| 411 NistLteUePhy::SetNistLteUeCphySapUser (NistLteUeCphySapUser* s) |
| 412 { |
| 413 NS_LOG_FUNCTION (this); |
| 414 m_ueCphySapUser = s; |
| 415 } |
| 416 |
| 417 NistLteUeCphySapProvider* |
| 418 NistLteUePhy::GetNistLteUeCphySapProvider () |
| 419 { |
| 420 NS_LOG_FUNCTION (this); |
| 421 return (m_ueCphySapProvider); |
| 422 } |
| 423 |
| 424 void |
| 425 NistLteUePhy::SetNoiseFigure (double nf) |
| 426 { |
| 427 NS_LOG_FUNCTION (this << nf); |
| 428 m_noiseFigure = nf; |
| 429 } |
| 430 |
| 431 double |
| 432 NistLteUePhy::GetNoiseFigure () const |
| 433 { |
| 434 NS_LOG_FUNCTION (this); |
| 435 return m_noiseFigure; |
| 436 } |
| 437 |
| 438 void |
| 439 NistLteUePhy::SetTxPower (double pow) |
| 440 { |
| 441 NS_LOG_FUNCTION (this << pow); |
| 442 m_txPower = pow; |
| 443 m_powerControl->SetTxPower (pow); |
| 444 } |
| 445 |
| 446 double |
| 447 NistLteUePhy::GetTxPower () const |
| 448 { |
| 449 NS_LOG_FUNCTION (this); |
| 450 return m_txPower; |
| 451 } |
| 452 |
| 453 Ptr<NistLteUePowerControl> |
| 454 NistLteUePhy::GetUplinkPowerControl () const |
| 455 { |
| 456 NS_LOG_FUNCTION (this); |
| 457 return m_powerControl; |
| 458 } |
| 459 |
| 460 uint8_t |
| 461 NistLteUePhy::GetMacChDelay (void) const |
| 462 { |
| 463 return (m_macChTtiDelay); |
| 464 } |
| 465 |
| 466 Ptr<NistLteSpectrumPhy> |
| 467 NistLteUePhy::GetDlSpectrumPhy () const |
| 468 { |
| 469 return m_downlinkSpectrumPhy; |
| 470 } |
| 471 |
| 472 Ptr<NistLteSpectrumPhy> |
| 473 NistLteUePhy::GetUlSpectrumPhy () const |
| 474 { |
| 475 return m_uplinkSpectrumPhy; |
| 476 } |
| 477 |
| 478 void |
| 479 NistLteUePhy::SetSlSpectrumPhy (Ptr<NistLteSpectrumPhy> phy)· |
| 480 { |
| 481 m_sidelinkSpectrumPhy = phy; |
| 482 } |
| 483 |
| 484 Ptr<NistLteSpectrumPhy> |
| 485 NistLteUePhy::GetSlSpectrumPhy () const |
| 486 { |
| 487 return m_sidelinkSpectrumPhy; |
| 488 } |
| 489 |
| 490 ·· |
| 491 void |
| 492 NistLteUePhy::DoSendMacPdu (Ptr<Packet> p) |
| 493 { |
| 494 NS_LOG_FUNCTION (this); |
| 495 |
| 496 SetMacPdu (p); |
| 497 } |
| 498 |
| 499 |
| 500 void |
| 501 NistLteUePhy::PhyPduReceived (Ptr<Packet> p) |
| 502 { |
| 503 m_uePhySapUser->ReceivePhyPdu (p); |
| 504 } |
| 505 |
| 506 void |
| 507 NistLteUePhy::SetSubChannelsForTransmission (std::vector <int> mask) |
| 508 { |
| 509 NS_LOG_FUNCTION (this); |
| 510 |
| 511 m_subChannelsForTransmission = mask; |
| 512 |
| 513 Ptr<SpectrumValue> txPsd = CreateTxPowerSpectralDensity (); |
| 514 m_uplinkSpectrumPhy->SetTxPowerSpectralDensity (txPsd); |
| 515 } |
| 516 |
| 517 |
| 518 void |
| 519 NistLteUePhy::SetSubChannelsForReception (std::vector <int> mask) |
| 520 { |
| 521 NS_LOG_FUNCTION (this); |
| 522 m_subChannelsForReception = mask; |
| 523 } |
| 524 |
| 525 |
| 526 std::vector <int> |
| 527 NistLteUePhy::GetSubChannelsForTransmission () |
| 528 { |
| 529 NS_LOG_FUNCTION (this); |
| 530 return m_subChannelsForTransmission; |
| 531 } |
| 532 |
| 533 |
| 534 std::vector <int> |
| 535 NistLteUePhy::GetSubChannelsForReception () |
| 536 { |
| 537 NS_LOG_FUNCTION (this); |
| 538 return m_subChannelsForReception; |
| 539 } |
| 540 |
| 541 |
| 542 Ptr<SpectrumValue> |
| 543 NistLteUePhy::CreateTxPowerSpectralDensity () |
| 544 { |
| 545 NS_LOG_FUNCTION (this); |
| 546 NistLteSpectrumValueHelper psdHelper; |
| 547 Ptr<SpectrumValue> psd = psdHelper.CreateUlTxPowerSpectralDensity (m_ulEarfcn,
m_ulBandwidth, m_txPower, GetSubChannelsForTransmission ()); |
| 548 |
| 549 return psd; |
| 550 } |
| 551 |
| 552 void |
| 553 NistLteUePhy::GenerateCtrlCqiReport (const SpectrumValue& sinr) |
| 554 { |
| 555 NS_LOG_FUNCTION (this); |
| 556 ·· |
| 557 GenerateCqiRsrpRsrq (sinr); |
| 558 } |
| 559 |
| 560 void |
| 561 NistLteUePhy::GenerateCqiRsrpRsrq (const SpectrumValue& sinr) |
| 562 { |
| 563 NS_LOG_FUNCTION (this << sinr); |
| 564 |
| 565 NS_ASSERT (m_state != CELL_SEARCH); |
| 566 NS_ASSERT (m_cellId > 0); |
| 567 |
| 568 if (m_dlConfigured && m_ulConfigured && (m_rnti > 0)) |
| 569 { |
| 570 // check periodic wideband CQI |
| 571 if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriocity) |
| 572 { |
| 573 Ptr<NistLteUeNetDevice> thisDevice = GetDevice ()->GetObject<NistLteUe
NetDevice> (); |
| 574 Ptr<NistDlCqiLteControlMessage> msg = CreateDlCqiFeedbackMessage (sinr
); |
| 575 if (msg) |
| 576 { |
| 577 DoSendNistLteControlMessage (msg); |
| 578 } |
| 579 m_p10CqiLast = Simulator::Now (); |
| 580 } |
| 581 // check aperiodic high-layer configured subband CQI |
| 582 if (Simulator::Now () > m_a30CqiLast + m_a30CqiPeriocity) |
| 583 { |
| 584 Ptr<NistLteUeNetDevice> thisDevice = GetDevice ()->GetObject<NistLteUe
NetDevice> (); |
| 585 Ptr<NistDlCqiLteControlMessage> msg = CreateDlCqiFeedbackMessage (sinr
); |
| 586 if (msg) |
| 587 { |
| 588 DoSendNistLteControlMessage (msg); |
| 589 } |
| 590 m_a30CqiLast = Simulator::Now (); |
| 591 } |
| 592 } |
| 593 |
| 594 // Generate PHY trace |
| 595 m_rsrpSinrSampleCounter++; |
| 596 if (m_rsrpSinrSampleCounter==m_rsrpSinrSamplePeriod) |
| 597 { |
| 598 NS_ASSERT_MSG (m_rsReceivedPowerUpdated, " RS received power info obsolete
"); |
| 599 // RSRP evaluated as averaged received power among RBs |
| 600 double sum = 0.0; |
| 601 uint8_t rbNum = 0; |
| 602 Values::const_iterator it; |
| 603 for (it = m_rsReceivedPower.ConstValuesBegin (); it != m_rsReceivedPower.C
onstValuesEnd (); it++) |
| 604 { |
| 605 // convert PSD [W/Hz] to linear power [W] for the single RE |
| 606 // we consider only one RE for the RS since the channel is· |
| 607 // flat within the same RB· |
| 608 double powerTxW = ((*it) * 180000.0) / 12.0; |
| 609 sum += powerTxW; |
| 610 rbNum++; |
| 611 } |
| 612 double rsrp = (rbNum > 0) ? (sum / rbNum) : DBL_MAX; |
| 613 // averaged SINR among RBs |
| 614 sum = 0.0; |
| 615 rbNum = 0; |
| 616 for (it = sinr.ConstValuesBegin (); it != sinr.ConstValuesEnd (); it++) |
| 617 { |
| 618 sum += (*it); |
| 619 rbNum++; |
| 620 } |
| 621 double avSinr = (rbNum > 0) ? (sum / rbNum) : DBL_MAX; |
| 622 NS_LOG_INFO (this << " cellId " << m_cellId << " rnti " << m_rnti << " RSR
P " << rsrp << " SINR " << avSinr); |
| 623 |
| 624 m_reportCurrentCellRsrpSinrTrace (m_cellId, m_rnti, rsrp, avSinr); |
| 625 m_rsrpSinrSampleCounter = 0; |
| 626 } |
| 627 |
| 628 if (m_pssReceived) |
| 629 { |
| 630 // measure instantaneous RSRQ now |
| 631 NS_ASSERT_MSG (m_rsInterferencePowerUpdated, " RS interference power info
obsolete"); |
| 632 |
| 633 std::list <NistPssElement>::iterator itPss = m_pssList.begin (); |
| 634 while (itPss != m_pssList.end ()) |
| 635 { |
| 636 uint16_t rbNum = 0; |
| 637 double rssiSum = 0.0; |
| 638 |
| 639 Values::const_iterator itIntN = m_rsInterferencePower.ConstValuesBegin
(); |
| 640 Values::const_iterator itPj = m_rsReceivedPower.ConstValuesBegin (); |
| 641 for (itPj = m_rsReceivedPower.ConstValuesBegin (); |
| 642 itPj != m_rsReceivedPower.ConstValuesEnd (); |
| 643 itIntN++, itPj++) |
| 644 { |
| 645 rbNum++; |
| 646 // convert PSD [W/Hz] to linear power [W] for the single RE |
| 647 double interfPlusNoisePowerTxW = ((*itIntN) * 180000.0) / 12.0; |
| 648 double signalPowerTxW = ((*itPj) * 180000.0) / 12.0; |
| 649 rssiSum += (2 * (interfPlusNoisePowerTxW + signalPowerTxW)); |
| 650 } |
| 651 |
| 652 NS_ASSERT (rbNum == (*itPss).nRB); |
| 653 double rsrq_dB = 10 * log10 ((*itPss).pssPsdSum / rssiSum); |
| 654 |
| 655 if (rsrq_dB > m_pssReceptionThreshold) |
| 656 { |
| 657 NS_LOG_INFO (this << " PSS RNTI " << m_rnti << " cellId " << m_cel
lId |
| 658 << " has RSRQ " << rsrq_dB << " and RBnum " << r
bNum); |
| 659 // store measurements |
| 660 std::map <uint16_t, NistUeMeasurementsElement>::iterator itMeasMap
; |
| 661 itMeasMap = m_ueMeasurementsMap.find ((*itPss).cellId); |
| 662 // Antonio: Included workaround for bug 2091 (code included in 3.2
3) |
| 663 //NS_ASSERT (itMeasMap != m_ueMeasurementsMap.end ()); |
| 664 if (itMeasMap != m_ueMeasurementsMap.end ()) |
| 665 { |
| 666 (*itMeasMap).second.rsrqSum += rsrq_dB; |
| 667 (*itMeasMap).second.rsrqNum++; |
| 668 } |
| 669 else |
| 670 { |
| 671 NS_LOG_WARN ("race condition of bug 2091 occurred"); |
| 672 } |
| 673 } |
| 674 |
| 675 itPss++; |
| 676 |
| 677 } // end of while (itPss != m_pssList.end ()) |
| 678 |
| 679 m_pssList.clear (); |
| 680 |
| 681 } // end of if (m_pssReceived) |
| 682 |
| 683 } // end of void NistLteUePhy::GenerateCtrlCqiReport (const SpectrumValue& sinr) |
| 684 |
| 685 void |
| 686 NistLteUePhy::GenerateDataCqiReport (const SpectrumValue& sinr) |
| 687 { |
| 688 // Not used by UE, CQI are based only on RS |
| 689 } |
| 690 |
| 691 void |
| 692 NistLteUePhy::GenerateMixedCqiReport (const SpectrumValue& sinr) |
| 693 { |
| 694 NS_LOG_FUNCTION (this); |
| 695 |
| 696 NS_ASSERT (m_state != CELL_SEARCH); |
| 697 NS_ASSERT (m_cellId > 0); |
| 698 ·· |
| 699 SpectrumValue mixedSinr = (m_rsReceivedPower * m_paLinear); |
| 700 if (m_dataInterferencePowerUpdated) |
| 701 { |
| 702 // we have a measurement of interf + noise for the denominator |
| 703 // of SINR = S/(I+N) |
| 704 mixedSinr /= m_dataInterferencePower; |
| 705 m_dataInterferencePowerUpdated = false; |
| 706 NS_LOG_LOGIC ("data interf measurement available, SINR = " << mixedSinr); |
| 707 } |
| 708 else |
| 709 { |
| 710 // we did not see any interference on data, so interference is |
| 711 // there and we have only noise at the denominator of SINR |
| 712 mixedSinr /= (*m_noisePsd); |
| 713 NS_LOG_LOGIC ("no data interf measurement available, SINR = " << mixedSinr
); |
| 714 } |
| 715 |
| 716 /* |
| 717 * some RBs are not used in PDSCH and their SINR is very high |
| 718 * for example with bandwidth 25, last RB is not used |
| 719 * it can make avgSinr value very high, what is incorrect |
| 720 */ |
| 721 uint32_t rbgSize = GetRbgSize (); |
| 722 uint32_t modulo = m_dlBandwidth % rbgSize; |
| 723 double avgMixedSinr = 0; |
| 724 uint32_t usedRbgNum = 0; |
| 725 for(uint32_t i = 0; i < (m_dlBandwidth-1-modulo); i++)· |
| 726 { |
| 727 usedRbgNum++; |
| 728 avgMixedSinr+=mixedSinr[i]; |
| 729 } |
| 730 avgMixedSinr = avgMixedSinr/usedRbgNum; |
| 731 for(uint32_t i = 0; i < modulo; i++)· |
| 732 { |
| 733 mixedSinr[m_dlBandwidth-1-i] = avgMixedSinr; |
| 734 } |
| 735 |
| 736 GenerateCqiRsrpRsrq (mixedSinr); |
| 737 } |
| 738 |
| 739 void |
| 740 NistLteUePhy::ReportInterference (const SpectrumValue& interf) |
| 741 { |
| 742 NS_LOG_FUNCTION (this << interf); |
| 743 m_rsInterferencePowerUpdated = true; |
| 744 m_rsInterferencePower = interf; |
| 745 } |
| 746 |
| 747 void |
| 748 NistLteUePhy::ReportDataInterference (const SpectrumValue& interf) |
| 749 { |
| 750 NS_LOG_FUNCTION (this << interf); |
| 751 |
| 752 m_dataInterferencePowerUpdated = true; |
| 753 m_dataInterferencePower = interf; |
| 754 } |
| 755 |
| 756 void |
| 757 NistLteUePhy::ReportRsReceivedPower (const SpectrumValue& power) |
| 758 { |
| 759 NS_LOG_FUNCTION (this << power); |
| 760 m_rsReceivedPowerUpdated = true; |
| 761 m_rsReceivedPower = power; |
| 762 |
| 763 if (m_enableUplinkPowerControl) |
| 764 { |
| 765 double sum = 0; |
| 766 uint32_t rbNum = 0; |
| 767 Values::const_iterator it; |
| 768 for (it = m_rsReceivedPower.ConstValuesBegin (); it != m_rsReceivedPower.C
onstValuesEnd (); it++) |
| 769 { |
| 770 double powerTxW = ((*it) * 180000); |
| 771 sum += powerTxW; |
| 772 rbNum++; |
| 773 } |
| 774 double rsrp = 10 * log10 (sum) + 30; |
| 775 |
| 776 NS_LOG_INFO ("RSRP: " << rsrp); |
| 777 m_powerControl->SetRsrp (rsrp); |
| 778 } |
| 779 } |
| 780 |
| 781 Ptr<NistDlCqiLteControlMessage> |
| 782 NistLteUePhy::CreateDlCqiFeedbackMessage (const SpectrumValue& sinr) |
| 783 { |
| 784 NS_LOG_FUNCTION (this); |
| 785 |
| 786 |
| 787 // apply transmission mode gain |
| 788 NS_ASSERT (m_transmissionMode < m_txModeGain.size ()); |
| 789 SpectrumValue newSinr = sinr; |
| 790 newSinr *= m_txModeGain.at (m_transmissionMode); |
| 791 |
| 792 // CREATE NistDlCqiLteControlMessage |
| 793 Ptr<NistDlCqiLteControlMessage> msg = Create<NistDlCqiLteControlMessage> (); |
| 794 NistCqiListElement_s dlcqi; |
| 795 std::vector<int> cqi; |
| 796 if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriocity) |
| 797 { |
| 798 cqi = m_amc->CreateCqiFeedbacks (newSinr, m_dlBandwidth); |
| 799 |
| 800 int nLayer = NistTransmissionModesLayers::TxMode2LayerNum (m_transmissionM
ode); |
| 801 int nbSubChannels = cqi.size (); |
| 802 double cqiSum = 0.0; |
| 803 int activeSubChannels = 0; |
| 804 // average the CQIs of the different RBs |
| 805 for (int i = 0; i < nbSubChannels; i++) |
| 806 { |
| 807 if (cqi.at (i) != -1) |
| 808 { |
| 809 cqiSum += cqi.at (i); |
| 810 activeSubChannels++; |
| 811 } |
| 812 NS_LOG_DEBUG (this << " subch " << i << " cqi " << cqi.at (i)); |
| 813 } |
| 814 dlcqi.m_rnti = m_rnti; |
| 815 dlcqi.m_ri = 1; // not yet used |
| 816 dlcqi.m_cqiType = NistCqiListElement_s::P10; // Peridic CQI using PUCCH wi
deband |
| 817 NS_ASSERT_MSG (nLayer > 0, " nLayer negative"); |
| 818 NS_ASSERT_MSG (nLayer < 3, " nLayer limit is 2s"); |
| 819 for (int i = 0; i < nLayer; i++) |
| 820 { |
| 821 if (activeSubChannels > 0) |
| 822 { |
| 823 dlcqi.m_wbCqi.push_back ((uint16_t) cqiSum / activeSubChannels); |
| 824 } |
| 825 else |
| 826 { |
| 827 // approximate with the worst case -> CQI = 1 |
| 828 dlcqi.m_wbCqi.push_back (1); |
| 829 } |
| 830 } |
| 831 //NS_LOG_DEBUG (this << " Generate P10 CQI feedback " << (uint16_t) cqiSum
/ activeSubChannels); |
| 832 dlcqi.m_wbPmi = 0; // not yet used |
| 833 // dl.cqi.m_sbMeasResult others CQI report modes: not yet implemented |
| 834 } |
| 835 else if (Simulator::Now () > m_a30CqiLast + m_a30CqiPeriocity) |
| 836 { |
| 837 cqi = m_amc->CreateCqiFeedbacks (newSinr, GetRbgSize ()); |
| 838 int nLayer = NistTransmissionModesLayers::TxMode2LayerNum (m_transmissionM
ode); |
| 839 int nbSubChannels = cqi.size (); |
| 840 int rbgSize = GetRbgSize (); |
| 841 double cqiSum = 0.0; |
| 842 int cqiNum = 0; |
| 843 NistSbMeasResult_s rbgMeas; |
| 844 //NS_LOG_DEBUG (this << " Create A30 CQI feedback, RBG " << rbgSize << " c
qiNum " << nbSubChannels << " band " << (uint16_t)m_dlBandwidth); |
| 845 for (int i = 0; i < nbSubChannels; i++) |
| 846 { |
| 847 if (cqi.at (i) != -1) |
| 848 { |
| 849 cqiSum += cqi.at (i); |
| 850 } |
| 851 // else "nothing" no CQI is treated as CQI = 0 (worst case scenario) |
| 852 cqiNum++; |
| 853 if (cqiNum == rbgSize) |
| 854 { |
| 855 // average the CQIs of the different RBGs |
| 856 //NS_LOG_DEBUG (this << " RBG CQI " << (uint16_t) cqiSum / rbgSiz
e); |
| 857 NistHigherLayerSelected_s hlCqi; |
| 858 hlCqi.m_sbPmi = 0; // not yet used |
| 859 for (int i = 0; i < nLayer; i++) |
| 860 { |
| 861 hlCqi.m_sbCqi.push_back ((uint16_t) cqiSum / rbgSize); |
| 862 } |
| 863 rbgMeas.m_higherLayerSelected.push_back (hlCqi); |
| 864 cqiSum = 0.0; |
| 865 cqiNum = 0; |
| 866 } |
| 867 } |
| 868 dlcqi.m_rnti = m_rnti; |
| 869 dlcqi.m_ri = 1; // not yet used |
| 870 dlcqi.m_cqiType = NistCqiListElement_s::A30; // Aperidic CQI using PUSCH |
| 871 //dlcqi.m_wbCqi.push_back ((uint16_t) cqiSum / nbSubChannels); |
| 872 dlcqi.m_wbPmi = 0; // not yet used |
| 873 dlcqi.m_sbMeasResult = rbgMeas; |
| 874 } |
| 875 |
| 876 msg->SetDlCqi (dlcqi); |
| 877 return msg; |
| 878 } |
| 879 |
| 880 |
| 881 void |
| 882 NistLteUePhy::ReportNistUeMeasurements () |
| 883 { |
| 884 NS_LOG_FUNCTION (this << Simulator::Now ()); |
| 885 NS_LOG_DEBUG (this << " Report UE Measurements "); |
| 886 |
| 887 NistLteUeCphySapUser::NistUeMeasurementsParameters ret; |
| 888 |
| 889 std::map <uint16_t, NistUeMeasurementsElement>::iterator it; |
| 890 for (it = m_ueMeasurementsMap.begin (); it != m_ueMeasurementsMap.end (); it++
) |
| 891 { |
| 892 double avg_rsrp = (*it).second.rsrpSum / (double)(*it).second.rsrpNum; |
| 893 double avg_rsrq = (*it).second.rsrqSum / (double)(*it).second.rsrqNum; |
| 894 /* |
| 895 * In CELL_SEARCH state, this may result in avg_rsrq = 0/0 = -nan. |
| 896 * UE RRC must take this into account when receiving measurement reports. |
| 897 * TODO remove this shortcoming by calculating RSRQ during CELL_SEARCH |
| 898 */ |
| 899 NS_LOG_DEBUG (this << " CellId " << (*it).first |
| 900 << " RSRP " << avg_rsrp |
| 901 << " (nSamples " << (uint16_t)(*it).second.rsrpNum << "
)" |
| 902 << " RSRQ " << avg_rsrq |
| 903 << " (nSamples " << (uint16_t)(*it).second.rsrqNum << "
)"); |
| 904 |
| 905 if (avg_rsrp >= m_rsrpReceptionThreshold) { |
| 906 NistLteUeCphySapUser::NistUeMeasurementsElement newEl; |
| 907 newEl.m_cellId = (*it).first; |
| 908 newEl.m_rsrp = avg_rsrp; |
| 909 newEl.m_rsrq = avg_rsrq; |
| 910 ret.m_ueMeasurementsList.push_back (newEl); |
| 911 } |
| 912 ······ |
| 913 // report to UE measurements trace |
| 914 m_reportNistUeMeasurements (m_rnti, (*it).first, avg_rsrp, avg_rsrq, ((*it
).first == m_cellId ? 1 : 0)); |
| 915 } |
| 916 |
| 917 // report to RRC |
| 918 m_ueCphySapUser->ReportNistUeMeasurements (ret); |
| 919 |
| 920 m_ueMeasurementsMap.clear (); |
| 921 Simulator::Schedule (m_ueMeasurementsFilterPeriod, &NistLteUePhy::ReportNistUe
Measurements, this); |
| 922 } |
| 923 |
| 924 void |
| 925 NistLteUePhy::DoSendNistLteControlMessage (Ptr<NistLteControlMessage> msg) |
| 926 { |
| 927 NS_LOG_FUNCTION (this << msg); |
| 928 |
| 929 SetControlMessages (msg); |
| 930 } |
| 931 |
| 932 void· |
| 933 NistLteUePhy::DoSendRachPreamble (uint32_t raPreambleId, uint32_t raRnti) |
| 934 { |
| 935 NS_LOG_FUNCTION (this << raPreambleId); |
| 936 |
| 937 // unlike other control messages, RACH preamble is sent ASAP |
| 938 Ptr<NistRachPreambleLteControlMessage> msg = Create<NistRachPreambleLteControl
Message> (); |
| 939 msg->SetRapId (raPreambleId); |
| 940 m_raPreambleId = raPreambleId; |
| 941 m_raRnti = raRnti; |
| 942 m_controlMessagesQueue.at (0).push_back (msg); |
| 943 } |
| 944 |
| 945 |
| 946 void |
| 947 NistLteUePhy::ReceiveNistLteControlMessageList (std::list<Ptr<NistLteControlMess
age> > msgList) |
| 948 { |
| 949 NS_LOG_FUNCTION (this); |
| 950 |
| 951 std::list<Ptr<NistLteControlMessage> >::iterator it; |
| 952 for (it = msgList.begin (); it != msgList.end (); it++) |
| 953 { |
| 954 Ptr<NistLteControlMessage> msg = (*it); |
| 955 NS_LOG_INFO ("Message type=" << msg->GetMessageType ()); |
| 956 ········ |
| 957 if (msg->GetMessageType () == NistLteControlMessage::DL_DCI) |
| 958 { |
| 959 Ptr<NistDlDciLteControlMessage> msg2 = DynamicCast<NistDlDciLteControl
Message> (msg); |
| 960 |
| 961 NistDlDciListElement_s dci = msg2->GetDci (); |
| 962 if (dci.m_rnti != m_rnti) |
| 963 { |
| 964 // DCI not for me |
| 965 continue; |
| 966 } |
| 967 |
| 968 if (dci.m_resAlloc != 0) |
| 969 { |
| 970 NS_FATAL_ERROR ("Resource Allocation type not implemented"); |
| 971 } |
| 972 |
| 973 std::vector <int> dlRb; |
| 974 |
| 975 // translate the DCI to Spectrum framework |
| 976 uint32_t mask = 0x1; |
| 977 for (int i = 0; i < 32; i++) |
| 978 { |
| 979 if (((dci.m_rbBitmap & mask) >> i) == 1) |
| 980 { |
| 981 for (int k = 0; k < GetRbgSize (); k++) |
| 982 { |
| 983 dlRb.push_back ((i * GetRbgSize ()) + k); |
| 984 // NS_LOG_DEBUG(this << " RNTI " << m_rnti << " RBG " << i << " DL-D
CI allocated PRB " << (i*GetRbgSize()) + k); |
| 985 } |
| 986 } |
| 987 mask = (mask << 1); |
| 988 } |
| 989 if (m_enableUplinkPowerControl) |
| 990 { |
| 991 m_powerControl->ReportTpc (dci.m_tpc); |
| 992 } |
| 993 |
| 994 |
| 995 // send TB info to NistLteSpectrumPhy |
| 996 NS_LOG_DEBUG (this << " UE " << m_rnti << " DL-DCI " << dci.m_rnti <<
" bitmap " << dci.m_rbBitmap); |
| 997 for (uint8_t i = 0; i < dci.m_tbsSize.size (); i++) |
| 998 { |
| 999 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.a
t (i), true /* DL */); |
| 1000 } |
| 1001 |
| 1002 SetSubChannelsForReception (dlRb); |
| 1003 |
| 1004 |
| 1005 } |
| 1006 else if (msg->GetMessageType () == NistLteControlMessage::UL_DCI) |
| 1007 { |
| 1008 // set the uplink bandwidth according to the UL-CQI |
| 1009 Ptr<NistUlDciLteControlMessage> msg2 = DynamicCast<NistUlDciLteControl
Message> (msg); |
| 1010 NistUlDciListElement_s dci = msg2->GetDci (); |
| 1011 if (dci.m_rnti != m_rnti) |
| 1012 { |
| 1013 // DCI not for me |
| 1014 continue; |
| 1015 } |
| 1016 NS_LOG_INFO (this << " UL DCI"); |
| 1017 std::vector <int> ulRb; |
| 1018 for (int i = 0; i < dci.m_rbLen; i++) |
| 1019 { |
| 1020 ulRb.push_back (i + dci.m_rbStart); |
| 1021 //NS_LOG_DEBUG (this << " UE RB " << i + dci.m_rbStart); |
| 1022 } |
| 1023 QueueSubChannelsForTransmission (ulRb); |
| 1024 // fire trace of UL Tx PHY stats |
| 1025 HarqProcessInfoList_t harqInfoList = m_harqPhyModule->GetHarqProcessIn
foUl (m_rnti, 0); |
| 1026 NistPhyTransmissionStatParameters params; |
| 1027 params.m_cellId = m_cellId; |
| 1028 params.m_imsi = 0; // it will be set by DlPhyTransmissionCallback in N
istLteHelper |
| 1029 params.m_timestamp = Simulator::Now ().GetMilliSeconds () + UL_PUSCH_T
TIS_DELAY; |
| 1030 params.m_rnti = m_rnti; |
| 1031 params.m_txMode = 0; // always SISO for UE |
| 1032 params.m_layer = 0; |
| 1033 params.m_mcs = dci.m_mcs; |
| 1034 params.m_size = dci.m_tbSize; |
| 1035 params.m_rv = harqInfoList.size (); |
| 1036 params.m_ndi = dci.m_ndi; |
| 1037 m_ulPhyTransmission (params); |
| 1038 // pass the info to the MAC |
| 1039 m_uePhySapUser->ReceiveNistLteControlMessage (msg); |
| 1040 } |
| 1041 else if (msg->GetMessageType () == NistLteControlMessage::RAR) |
| 1042 { |
| 1043 Ptr<NistRarLteControlMessage> rarMsg = DynamicCast<NistRarLteControlMe
ssage> (msg); |
| 1044 if (rarMsg->GetRaRnti () == m_raRnti) |
| 1045 { |
| 1046 for (std::list<NistRarLteControlMessage::NistRar>::const_iterator
it = rarMsg->NistRarListBegin (); it != rarMsg->NistRarListEnd (); ++it) |
| 1047 { |
| 1048 if (it->rapId != m_raPreambleId) |
| 1049 { |
| 1050 // UL grant not for me |
| 1051 continue; |
| 1052 } |
| 1053 else |
| 1054 { |
| 1055 NS_LOG_INFO ("received RAR RNTI " << m_raRnti); |
| 1056 // set the uplink bandwidht according to the UL grant |
| 1057 std::vector <int> ulRb; |
| 1058 for (int i = 0; i < it->rarPayload.m_grant.m_rbLen; i++) |
| 1059 { |
| 1060 ulRb.push_back (i + it->rarPayload.m_grant.m_rbStart); |
| 1061 } |
| 1062 |
| 1063 QueueSubChannelsForTransmission (ulRb); |
| 1064 // pass the info to the MAC |
| 1065 m_uePhySapUser->ReceiveNistLteControlMessage (msg); |
| 1066 // reset RACH variables with out of range values |
| 1067 m_raPreambleId = 255; |
| 1068 m_raRnti = 11; |
| 1069 } |
| 1070 } |
| 1071 } |
| 1072 } |
| 1073 else if (msg->GetMessageType () == NistLteControlMessage::MIB) |
| 1074 { |
| 1075 NS_LOG_INFO ("received MIB"); |
| 1076 NS_ASSERT (m_cellId > 0); |
| 1077 Ptr<NistMibLteControlMessage> msg2 = DynamicCast<NistMibLteControlMess
age> (msg); |
| 1078 m_ueCphySapUser->RecvNistMasterInformationBlock (m_cellId, msg2->GetMi
b ()); |
| 1079 } |
| 1080 else if (msg->GetMessageType () == NistLteControlMessage::SIB1) |
| 1081 { |
| 1082 NS_LOG_INFO ("received SIB1"); |
| 1083 NS_ASSERT (m_cellId > 0); |
| 1084 Ptr<NistSib1LteControlMessage> msg2 = DynamicCast<NistSib1LteControlMe
ssage> (msg); |
| 1085 m_ueCphySapUser->RecvNistSystemInformationBlockType1 (m_cellId, msg2->
GetSib1 ()); |
| 1086 } |
| 1087 else if (msg->GetMessageType () == NistLteControlMessage::SL_DCI) |
| 1088 { |
| 1089 Ptr<NistSlDciLteControlMessage> msg2 = DynamicCast<NistSlDciLteControl
Message> (msg); |
| 1090 NistSlDciListElement_s dci = msg2->GetDci (); |
| 1091 if (dci.m_rnti != m_rnti) |
| 1092 { |
| 1093 // DCI not for me |
| 1094 continue; |
| 1095 } |
| 1096 NS_LOG_INFO ("received SL_DCI"); |
| 1097 m_uePhySapUser->ReceiveNistLteControlMessage (msg); |
| 1098 } |
| 1099 else if (msg->GetMessageType () == NistLteControlMessage::SCI) |
| 1100 { |
| 1101 Ptr<SciNistLteControlMessage> msg2 = DynamicCast<SciNistLteControlMess
age> (msg); |
| 1102 NistSciListElement_s sci = msg2->GetSci (); |
| 1103 //must check if the destination is one to monitor |
| 1104 std::list <uint32_t>::iterator it; |
| 1105 bool for_me = false; |
| 1106 for (it = m_destinations.begin (); it != m_destinations.end () && !for
_me; it++) |
| 1107 { |
| 1108 if (sci.m_groupDstId == ((*it) & 0xFF)) |
| 1109 { |
| 1110 NS_LOG_INFO ("received SCI for group " << (uint32_t)((*it) & 0
xFF) << " from rnti " << sci.m_rnti); |
| 1111 |
| 1112 //todo, how to find the pool among the available ones? |
| 1113 //right now just use the first one |
| 1114 std::list <PoolInfo>::iterator poolIt = m_sidelinkRxPools.begi
n(); |
| 1115 if (poolIt == m_sidelinkRxPools.end()) |
| 1116 { |
| 1117 NS_LOG_INFO (this << " No Rx pool configured"); |
| 1118 } |
| 1119 else |
| 1120 { |
| 1121 //this is the first transmission of PSCCH |
| 1122 std::map<uint16_t, SidelinkGrantInfo>::iterator grantIt =
poolIt->m_currentGrants.find (sci.m_rnti); |
| 1123 if (grantIt == poolIt->m_currentGrants.end()) |
| 1124 { |
| 1125 SidelinkGrantInfo txInfo; |
| 1126 ······················ |
| 1127 txInfo.m_grant_received = true; |
| 1128 txInfo.m_grant.m_rnti = sci.m_rnti; |
| 1129 txInfo.m_grant.m_resPscch = sci.m_resPscch; |
| 1130 txInfo.m_grant.m_rbStart = sci.m_rbStart; |
| 1131 txInfo.m_grant.m_rbLen = sci.m_rbLen; |
| 1132 txInfo.m_grant.m_trp = sci.m_trp; |
| 1133 txInfo.m_grant.m_groupDstId = sci.m_groupDstId; |
| 1134 txInfo.m_grant.m_mcs = sci.m_mcs; |
| 1135 txInfo.m_grant.m_tbSize = sci.m_tbSize; |
| 1136 |
| 1137 //insert grant |
| 1138 poolIt->m_currentGrants.insert (std::pair <uint16_t, S
idelinkGrantInfo> (sci.m_rnti, txInfo)); |
| 1139 } //else it should be the retransmission and the data sh
ould be the same...add check |
| 1140 else |
| 1141 { |
| 1142 NS_LOG_DEBUG ("SCI Grant already present"); |
| 1143 } |
| 1144 } |
| 1145 ························ |
| 1146 //m_uePhySapUser->ReceiveNistLteControlMessage (msg); |
| 1147 ·················· |
| 1148 }············· |
| 1149 } |
| 1150 } |
| 1151 else if (msg->GetMessageType() == NistLteControlMessage::MIB_SL) |
| 1152 { |
| 1153 Ptr<MibSLNistLteControlMessage> msgMibSL = DynamicCast<MibSLNistLteCon
trolMessage> (msg); |
| 1154 NistLteRrcSap::MasterInformationBlockSL mibSL = msgMibSL->GetMibSL(); |
| 1155 |
| 1156 //Pass the message to the RRC |
| 1157 m_ueCphySapUser->ReceiveMibSL(mibSL); |
| 1158 |
| 1159 //Store the received MIB-SL during the SyncRef search |
| 1160 if (m_ueSlssScanningInProgress) |
| 1161 { |
| 1162 mibSL.rxOffset = Simulator::Now().GetMilliSeconds() % 40; |
| 1163 m_detectedMibSl.insert (std::pair <std::pair<uint16_t,uint16_t>, N
istLteRrcSap::MasterInformationBlockSL> (std::pair<uint16_t,uint16_t>(mibSL.slss
id, mibSL.rxOffset), mibSL)); |
| 1164 } |
| 1165 } |
| 1166 |
| 1167 //discovery |
| 1168 else if (msg->GetMessageType () == NistLteControlMessage::SL_DISC_MSG) |
| 1169 { |
| 1170 Ptr<NistSlDiscMessage> msg2 = DynamicCast<NistSlDiscMessage> (msg); |
| 1171 NistSlDiscMsg disc = msg2->GetSlDiscMessage (); |
| 1172 |
| 1173 NS_LOG_INFO ("received discovery from rnti " << disc.m_rnti << " with
resPsdch: " << disc.m_resPsdch); |
| 1174 m_uePhySapUser->ReceiveNistLteControlMessage (msg); |
| 1175 } |
| 1176 |
| 1177 else |
| 1178 { |
| 1179 // pass the message to UE-MAC |
| 1180 m_uePhySapUser->ReceiveNistLteControlMessage (msg); |
| 1181 } |
| 1182 |
| 1183 } |
| 1184 |
| 1185 |
| 1186 } |
| 1187 |
| 1188 |
| 1189 void |
| 1190 NistLteUePhy::ReceivePss (uint16_t cellId, Ptr<SpectrumValue> p) |
| 1191 { |
| 1192 NS_LOG_FUNCTION (this << cellId << (*p)); |
| 1193 |
| 1194 double sum = 0.0; |
| 1195 uint16_t nRB = 0; |
| 1196 Values::const_iterator itPi; |
| 1197 for (itPi = p->ConstValuesBegin (); itPi != p->ConstValuesEnd (); itPi++) |
| 1198 { |
| 1199 // convert PSD [W/Hz] to linear power [W] for the single RE |
| 1200 double powerTxW = ((*itPi) * 180000.0) / 12.0; |
| 1201 sum += powerTxW; |
| 1202 nRB++; |
| 1203 } |
| 1204 |
| 1205 // measure instantaneous RSRP now |
| 1206 double rsrp_dBm = 10 * log10 (1000 * (sum / (double)nRB)); |
| 1207 NS_LOG_INFO (this << " PSS RNTI " << m_rnti << " cellId " << m_cellId |
| 1208 << " has RSRP " << rsrp_dBm << " and RBnum " << nRB); |
| 1209 // note that m_pssReceptionThreshold does not apply here |
| 1210 |
| 1211 // store measurements |
| 1212 std::map <uint16_t, NistUeMeasurementsElement>::iterator itMeasMap = m_ueMeasu
rementsMap.find (cellId); |
| 1213 if (itMeasMap == m_ueMeasurementsMap.end ()) |
| 1214 { |
| 1215 // insert new entry |
| 1216 NistUeMeasurementsElement newEl; |
| 1217 newEl.rsrpSum = rsrp_dBm; |
| 1218 newEl.rsrpNum = 1; |
| 1219 newEl.rsrqSum = 0; |
| 1220 newEl.rsrqNum = 0; |
| 1221 m_ueMeasurementsMap.insert (std::pair <uint16_t, NistUeMeasurementsElement
> (cellId, newEl)); |
| 1222 } |
| 1223 else |
| 1224 { |
| 1225 (*itMeasMap).second.rsrpSum += rsrp_dBm; |
| 1226 (*itMeasMap).second.rsrpNum++; |
| 1227 } |
| 1228 |
| 1229 /* |
| 1230 * Collect the PSS for later processing in GenerateCtrlCqiReport() |
| 1231 * (to be called from ChunkProcessor after RX is finished). |
| 1232 */ |
| 1233 m_pssReceived = true; |
| 1234 NistPssElement el; |
| 1235 el.cellId = cellId; |
| 1236 el.pssPsdSum = sum; |
| 1237 el.nRB = nRB; |
| 1238 m_pssList.push_back (el); |
| 1239 |
| 1240 } // end of void NistLteUePhy::ReceivePss (uint16_t cellId, Ptr<SpectrumValue> p
) |
| 1241 |
| 1242 |
| 1243 void |
| 1244 NistLteUePhy::QueueSubChannelsForTransmission (std::vector <int> rbMap) |
| 1245 { |
| 1246 m_subChannelsForTransmissionQueue.at (m_macChTtiDelay - 1) = rbMap; |
| 1247 } |
| 1248 |
| 1249 |
| 1250 void |
| 1251 NistLteUePhy::SubframeIndication (uint32_t frameNo, uint32_t subframeNo) |
| 1252 { |
| 1253 NS_LOG_FUNCTION (this << " frame " << frameNo << " subframe " << subframeNo <<
" rnti " << m_rnti); |
| 1254 |
| 1255 NS_ASSERT_MSG (frameNo > 0, "the SRS index check code assumes that frameNo sta
rts at 1"); |
| 1256 |
| 1257 // refresh internal variables |
| 1258 m_rsReceivedPowerUpdated = false; |
| 1259 m_rsInterferencePowerUpdated = false; |
| 1260 m_pssReceived = false; |
| 1261 |
| 1262 // Clear expected TB not received in previous subframes |
| 1263 m_sidelinkSpectrumPhy->ClearExpectedSlTb(); |
| 1264 |
| 1265 //Notify RRC about the current Subframe indication |
| 1266 m_ueCphySapUser->ReportSubframeIndication(frameNo, subframeNo); |
| 1267 |
| 1268 //If a change of timing (resynchronization) was requested before, do the chang
e of frameNo and subframeNo if possible |
| 1269 // Do it here for avoiding miss alignments of subframe indications |
| 1270 if (m_resyncRequested) |
| 1271 { |
| 1272 NS_LOG_LOGIC(this <<" (re)synchronization requested "); |
| 1273 if(ChangeOfTiming(frameNo, subframeNo) ) |
| 1274 { |
| 1275 frameNo = m_currFrameNo; |
| 1276 subframeNo = m_currSubframeNo; |
| 1277 NS_LOG_LOGIC(this << " (re)synchronization successfully performed "); |
| 1278 } |
| 1279 else |
| 1280 { |
| 1281 NS_LOG_LOGIC(this <<" (re)synchronization postponed "); |
| 1282 } |
| 1283 } |
| 1284 |
| 1285 if (m_ulConfigured) |
| 1286 { |
| 1287 if (m_slTxPoolInfo.m_pool) |
| 1288 { |
| 1289 //Check if we need to initialize the Tx pool |
| 1290 if (m_slTxPoolInfo.m_nextScPeriod.frameNo == 0) { |
| 1291 //pool not initialized yet |
| 1292 m_slTxPoolInfo.m_nextScPeriod = m_slTxPoolInfo.m_pool->GetNextScPe
riod (frameNo, subframeNo); |
| 1293 //adjust because scheduler starts with frame/subframe = 1 |
| 1294 m_slTxPoolInfo.m_nextScPeriod.frameNo++; |
| 1295 m_slTxPoolInfo.m_nextScPeriod.subframeNo++; |
| 1296 NS_LOG_INFO (this << " Tx Pool initialized"); |
| 1297 } |
| 1298 |
| 1299 //Check if this is a new SC period |
| 1300 //NS_LOG_DEBUG (this << "Checking if beginning of next period " << m_s
lTxPoolInfo.m_nextScPeriod.frameNo << "/" << m_slTxPoolInfo.m_nextScPeriod.subfr
ameNo); |
| 1301 if (frameNo == m_slTxPoolInfo.m_nextScPeriod.frameNo && subframeNo ==
m_slTxPoolInfo.m_nextScPeriod.subframeNo) |
| 1302 { |
| 1303 m_slTxPoolInfo.m_currentScPeriod = m_slTxPoolInfo.m_nextScPeriod; |
| 1304 m_slTxPoolInfo.m_nextScPeriod = m_slTxPoolInfo.m_pool->GetNextScPe
riod (frameNo, subframeNo); |
| 1305 //adjust because scheduler starts with frame/subframe = 1 |
| 1306 m_slTxPoolInfo.m_nextScPeriod.frameNo++; |
| 1307 m_slTxPoolInfo.m_nextScPeriod.subframeNo++; |
| 1308 NS_LOG_INFO (this << " Starting new SC period for TX pool " << ".
Next period at " << m_slTxPoolInfo.m_nextScPeriod.frameNo << "/" << m_slTxPoolIn
fo.m_nextScPeriod.subframeNo); |
| 1309 |
| 1310 if (m_waitingNextScPeriod) |
| 1311 { |
| 1312 NS_LOG_LOGIC (this << " the UE was waiting for next SC period
and it just started"); |
| 1313 m_waitingNextScPeriod = false; |
| 1314 } |
| 1315 |
| 1316 //clear any previous grant |
| 1317 m_slTxPoolInfo.m_currentGrants.clear(); |
| 1318 } |
| 1319 } |
| 1320 ····· |
| 1321 if (m_discTxPools.m_pool) |
| 1322 { |
| 1323 //Check if we need to initialize the discovery Tx pool |
| 1324 if (m_discTxPools.m_nextDiscPeriod.frameNo == 0)· |
| 1325 { |
| 1326 //pool not initialized yet |
| 1327 m_discTxPools.m_nextDiscPeriod = m_discTxPools.m_pool->GetNextDiscPeri
od (frameNo, subframeNo); |
| 1328 //adjust because scheduler starts with frame/subframe = 1 |
| 1329 m_discTxPools.m_nextDiscPeriod.frameNo++; |
| 1330 m_discTxPools.m_nextDiscPeriod.subframeNo++; |
| 1331 NS_LOG_INFO (this << "Discovery Tx Pool initialized"); |
| 1332 } |
| 1333 //Check if this is a new discovery period |
| 1334 if (frameNo == m_discTxPools.m_nextDiscPeriod.frameNo && subframeNo == m
_discTxPools.m_nextDiscPeriod.subframeNo) |
| 1335 { |
| 1336 m_discTxPools.m_currentDiscPeriod = m_discTxPools.m_nextDiscPeriod; |
| 1337 m_discTxPools.m_nextDiscPeriod = m_discTxPools.m_pool->GetNextDiscPeri
od (frameNo, subframeNo); |
| 1338 //adjust because scheduler starts with frame/subframe = 1 |
| 1339 m_discTxPools.m_nextDiscPeriod.frameNo++; |
| 1340 m_discTxPools.m_nextDiscPeriod.subframeNo++; |
| 1341 NS_LOG_INFO (this << " Starting new discovery period for TX pool " <<
". Next period at " << m_discTxPools.m_nextDiscPeriod.frameNo << "/" << m_discTx
Pools.m_nextDiscPeriod.subframeNo); |
| 1342 ············· |
| 1343 //clear any previous grant |
| 1344 m_discTxPools.m_currentGrants.clear(); |
| 1345 ·· |
| 1346 } |
| 1347 } |
| 1348 |
| 1349 //check if we received grants for sidelink |
| 1350 //compute the reception slots for the PSSCH. Do this here because |
| 1351 //we did not have access to the frame/subframe no at the reception |
| 1352 std::list <PoolInfo>::iterator it; |
| 1353 for (it = m_sidelinkRxPools.begin() ; it != m_sidelinkRxPools.end () ; it+
+) |
| 1354 { |
| 1355 std::map <uint16_t, SidelinkGrantInfo>::iterator grantIt = it->m_curre
ntGrants.begin(); |
| 1356 while (grantIt != it->m_currentGrants.end()) |
| 1357 { |
| 1358 |
| 1359 std::list<SidelinkCommResourcePool::SidelinkTransmissionInfo>::ite
rator rxIt; |
| 1360 |
| 1361 if (grantIt->second.m_grant_received) |
| 1362 { |
| 1363 NS_LOG_INFO (this << " New grant received"); |
| 1364 //TODO: how to identify pool if multiple are presents?························· |
| 1365 SidelinkCommResourcePool::SubframeInfo tmp = it->m_pool->GetCu
rrentScPeriod(frameNo, subframeNo); |
| 1366 grantIt->second.m_psschTx = it->m_pool->GetPsschTransmissions
(tmp, grantIt->second.m_grant.m_trp, grantIt->second.m_grant.m_rbStart, grantIt-
>second.m_grant.m_rbLen); |
| 1367 |
| 1368 for (rxIt = grantIt->second.m_psschTx.begin (); rxIt != grantI
t->second.m_psschTx.end (); rxIt++) |
| 1369 { |
| 1370 //adjust for index starting at 1 |
| 1371 rxIt->subframe.frameNo++; |
| 1372 rxIt->subframe.subframeNo++; |
| 1373 NS_LOG_INFO (this << " Subframe Rx" << rxIt->subframe.fram
eNo << "/" << rxIt->subframe.subframeNo << ": rbStart=" << (uint32_t) rxIt->rbSt
art << ", rbLen=" << (uint32_t) rxIt->nbRb); |
| 1374 } |
| 1375 |
| 1376 grantIt->second.m_grant_received =false; |
| 1377 } |
| 1378 //now check if there is any grant for the current subframe and pas
s them to lower layer |
| 1379 rxIt = grantIt->second.m_psschTx.begin(); |
| 1380 if (rxIt != grantIt->second.m_psschTx.end()) |
| 1381 { |
| 1382 NS_LOG_DEBUG (frameNo << "/" << subframeNo << " RNTI=" << m_rn
ti << " next pssch at " << (*rxIt).subframe.frameNo << "/" << (*rxIt).subframe.s
ubframeNo); |
| 1383 |
| 1384 } |
| 1385 if (rxIt != grantIt->second.m_psschTx.end() && (*rxIt).subframe.fr
ameNo == frameNo && (*rxIt).subframe.subframeNo == subframeNo) |
| 1386 { |
| 1387 //reception |
| 1388 NS_LOG_INFO (this << " Expecting PSSCH reception RB " << (uint
16_t) grantIt->second.m_grant.m_rbStart << " to " << (uint16_t) (grantIt->second
.m_grant.m_rbStart + grantIt->second.m_grant.m_rbLen - 1)); |
| 1389 std::vector <int> rbMap; |
| 1390 for (int i = grantIt->second.m_grant.m_rbStart; i < grantIt->s
econd.m_grant.m_rbStart + grantIt->second.m_grant.m_rbLen; i++) |
| 1391 { |
| 1392 rbMap.push_back (i); |
| 1393 } |
| 1394 |
| 1395 m_sidelinkSpectrumPhy->AddExpectedTb (grantIt->second.m_grant.
m_rnti, grantIt->second.m_grant.m_groupDstId, grantIt->second.m_psschTx.size() %
4 == 0, grantIt->second.m_grant.m_tbSize, grantIt->second.m_grant.m_mcs, rbMap,
(4 - grantIt->second.m_psschTx.size () % 4)); |
| 1396 |
| 1397 //remove reception information |
| 1398 grantIt->second.m_psschTx.erase (rxIt); |
| 1399 |
| 1400 } |
| 1401 if (grantIt->second.m_psschTx.size() == 0) |
| 1402 { |
| 1403 //no more PSSCH transmission, clear the grant |
| 1404 it->m_currentGrants.erase (grantIt++); |
| 1405 } |
| 1406 else { |
| 1407 grantIt++; |
| 1408 } |
| 1409 } |
| 1410 } |
| 1411 |
| 1412 |
| 1413 // update uplink transmission mask according to previous UL-CQIs |
| 1414 std::vector <int> rbMask = m_subChannelsForTransmissionQueue.at (0); |
| 1415 SetSubChannelsForTransmission (m_subChannelsForTransmissionQueue.at (0)); |
| 1416 |
| 1417 // shift the queue |
| 1418 for (uint8_t i = 1; i < m_macChTtiDelay; i++) |
| 1419 { |
| 1420 m_subChannelsForTransmissionQueue.at (i-1) = m_subChannelsForTransmiss
ionQueue.at (i); |
| 1421 } |
| 1422 m_subChannelsForTransmissionQueue.at (m_macChTtiDelay-1).clear (); |
| 1423 |
| 1424 if (m_srsConfigured && (m_srsStartTime <= Simulator::Now ())) |
| 1425 { |
| 1426 |
| 1427 NS_ASSERT_MSG (subframeNo > 0 && subframeNo <= 10, "the SRS index chec
k code assumes that subframeNo starts at 1"); |
| 1428 if ((((frameNo-1)*10 + (subframeNo-1)) % m_srsPeriodicity) == m_srsSub
frameOffset) |
| 1429 { |
| 1430 NS_LOG_INFO (this << " frame " << frameNo << " subframe " << subfr
ameNo << " sending SRS (offset=" << m_srsSubframeOffset << ", period=" << m_srsP
eriodicity << ")"); |
| 1431 m_sendSrsEvent = Simulator::Schedule (UL_SRS_DELAY_FROM_SUBFRAME_S
TART,· |
| 1432 &NistLteUePhy::SendSrs, |
| 1433 this); |
| 1434 } |
| 1435 } |
| 1436 |
| 1437 |
| 1438 //If rbMask has non empty RBs, it means we are expected to send messages i
n the uplink |
| 1439 //otherwise we check if there are sidelink transmissions |
| 1440 //Is this true if there are only control messages? |
| 1441 std::list<Ptr<NistLteControlMessage> > ctrlMsg = GetControlMessages (); |
| 1442 // send the current burts of packets |
| 1443 Ptr<PacketBurst> pb = GetPacketBurst (); |
| 1444 |
| 1445 bool sciDiscfound = false; |
| 1446 bool mibslfound = false; |
| 1447 |
| 1448 if (rbMask.size () == 0) |
| 1449 { |
| 1450 //we do not have uplink data to send. Normally, uplink has priority ov
er sidelink but |
| 1451 //since we send UL CQI messages all the time, we can remove them if we
have a sidelink |
| 1452 //transmission |
| 1453 std::list<Ptr<NistLteControlMessage> >::iterator ctrlIt; |
| 1454 for (ctrlIt=ctrlMsg.begin() ; ctrlIt != ctrlMsg.end() && !sciDiscfound
; ctrlIt++) { |
| 1455 sciDiscfound = (*ctrlIt)->GetMessageType () == NistLteControlMessa
ge::SCI || (*ctrlIt)->GetMessageType () == NistLteControlMessage::SL_DISC_MSG; |
| 1456 mibslfound = (*ctrlIt)->GetMessageType() == NistLteControlMessage:
:MIB_SL; |
| 1457 } |
| 1458 if (pb || sciDiscfound || mibslfound) |
| 1459 { |
| 1460 //we have sidelink to send, purge the control messages |
| 1461 ctrlIt=ctrlMsg.begin(); |
| 1462 while (ctrlIt != ctrlMsg.end()) |
| 1463 { |
| 1464 NS_LOG_INFO ("Message type = " << (*ctrlIt)->GetMessageType ()
); |
| 1465 if ((*ctrlIt)->GetMessageType () == NistLteControlMessage::DL_
CQI |
| 1466 || (*ctrlIt)->GetMessageType () == NistLteControlMessage::
BSR) |
| 1467 { |
| 1468 ctrlIt = ctrlMsg.erase (ctrlIt); |
| 1469 } |
| 1470 else |
| 1471 { |
| 1472 NS_ASSERT ((*ctrlIt)->GetMessageType () == NistLteControlM
essage::SCI |
| 1473 || (*ctrlIt)->GetMessageType() == NistLteContro
lMessage::MIB_SL |
| 1474 || (*ctrlIt)->GetMessageType () == NistLteContr
olMessage::SL_DISC_MSG |
| 1475 ); |
| 1476 ctrlIt++; |
| 1477 } |
| 1478 |
| 1479 } |
| 1480 } |
| 1481 } |
| 1482 if (rbMask.size() != 0 || (ctrlMsg.size () > 0 && (*ctrlMsg.begin())->GetM
essageType () != NistLteControlMessage::SCI |
| 1483 && (*ctrlMsg.begin())->GetMessageType () != NistLteControlMessage::MIB
_SL |
| 1484 && (*ctrlMsg.begin())->GetMessageType () != NistLteControlMessage::SL_
DISC_MSG |
| 1485 )) |
| 1486 { |
| 1487 |
| 1488 // send packets in queue |
| 1489 NS_LOG_LOGIC (this << " UE - start slot for PUSCH + PUCCH - RNTI " <<
m_rnti << " CELLID " << m_cellId); |
| 1490 if (pb) |
| 1491 { |
| 1492 //sanity check if this is a sidelink |
| 1493 Ptr<Packet> packet = (*(pb->Begin()))->Copy (); |
| 1494 NistLteRadioBearerTag tag; |
| 1495 packet->RemovePacketTag (tag); |
| 1496 NS_ASSERT (tag.GetDestinationL2Id () == 0); |
| 1497 |
| 1498 if (m_enableUplinkPowerControl) |
| 1499 { |
| 1500 m_txPower = m_powerControl->GetPuschTxPower (rbMask); |
| 1501 SetSubChannelsForTransmission (rbMask); |
| 1502 } |
| 1503 m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATI
ON); |
| 1504 } |
| 1505 else |
| 1506 { |
| 1507 // send only PUCCH (ideal: fake null bandwidth signal) |
| 1508 if (ctrlMsg.size ()>0) |
| 1509 { |
| 1510 NS_LOG_LOGIC (this << " UE - start TX PUCCH (NO PUSCH)"); |
| 1511 std::vector <int> dlRb; |
| 1512 |
| 1513 if (m_enableUplinkPowerControl) |
| 1514 { |
| 1515 m_txPower = m_powerControl->GetPucchTxPower (dlRb); |
| 1516 } |
| 1517 |
| 1518 SetSubChannelsForTransmission (dlRb); |
| 1519 m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DU
RATION); |
| 1520 } |
| 1521 else |
| 1522 { |
| 1523 NS_LOG_LOGIC (this << " UE - UL NOTHING TO SEND"); |
| 1524 } |
| 1525 } |
| 1526 } |
| 1527 else |
| 1528 { |
| 1529 //check sidelink |
| 1530 |
| 1531 //check if there is a SLSS message to be transmitted |
| 1532 bool mibSLfound = false; |
| 1533 std::list<Ptr<NistLteControlMessage> >::iterator ctrlIt; |
| 1534 for (ctrlIt = ctrlMsg.begin(); ctrlIt != ctrlMsg.end(); ctrlIt++) |
| 1535 { |
| 1536 if ((*ctrlIt)->GetMessageType() == NistLteControlMessage::MIB_SL) |
| 1537 { |
| 1538 mibSLfound = true; |
| 1539 } |
| 1540 } |
| 1541 |
| 1542 if (!m_waitingNextScPeriod) |
| 1543 { |
| 1544 |
| 1545 //since we only have 1 Tx pool we can either send PSCCH or PSSCH b
ut not both |
| 1546 // send packets in queue |
| 1547 NS_LOG_LOGIC (this << " UE - start slot for PSSCH + PSCCH - RNTI "
<< m_rnti << " CELLID " << m_cellId); |
| 1548 // send the current burts of packets |
| 1549 //Ptr<PacketBurst> pb = GetPacketBurst (); |
| 1550 if (pb) |
| 1551 { |
| 1552 //NS_ASSERT (ctrlMsg.size () == 0); //(In the future we can ha
ve PSSCH and MIB-SL in the same subframe) |
| 1553 NS_LOG_LOGIC (this << " UE - start TX PSSCH"); |
| 1554 NS_LOG_DEBUG (this << " TX Burst containing " << pb->GetNPacke
ts() << " packets"); |
| 1555 |
| 1556 //tx pool only has 1 grant so we can go straight to the first
element |
| 1557 //find the matching transmission opportunity. This is needed i
n case some opportunities |
| 1558 //were skipped because the queue was empty |
| 1559 std::list<SidelinkCommResourcePool::SidelinkTransmissionInfo>:
:iterator txIt = m_slTxPoolInfo.m_currentGrants.begin()->second.m_psschTx.begin
(); |
| 1560 while (txIt->subframe.frameNo < frameNo || (txIt->subframe.fra
meNo == frameNo && txIt->subframe.subframeNo < subframeNo)) |
| 1561 { |
| 1562 txIt = m_slTxPoolInfo.m_currentGrants.begin()->second.m_ps
schTx.erase (txIt); |
| 1563 if (txIt == m_slTxPoolInfo.m_currentGrants.begin()->second
.m_psschTx.end()) { |
| 1564 NS_LOG_ERROR ("Reached end of transmission list"); |
| 1565 } |
| 1566 } |
| 1567 NS_ASSERT (txIt != m_slTxPoolInfo.m_currentGrants.begin()->sec
ond.m_psschTx.end()); //must be at least one element |
| 1568 NS_ASSERT_MSG (txIt->subframe.frameNo == frameNo && txIt->subf
rame.subframeNo == subframeNo, "Found " << txIt->subframe.frameNo << "/" << txIt
->subframe.subframeNo); //there must be an opportunity in this subframe |
| 1569 NS_ASSERT (rbMask.size() == 0); |
| 1570 for (int i = txIt->rbStart ; i < txIt->rbStart + txIt->nbRb ;
i++) |
| 1571 { |
| 1572 NS_LOG_LOGIC (this << " Transmitting PSSCH on RB " << i); |
| 1573 rbMask.push_back (i); |
| 1574 } |
| 1575 m_slTxPoolInfo.m_currentGrants.begin()->second.m_psschTx.erase
(txIt); |
| 1576 |
| 1577 // if (m_slTxPoolInfo.m_currentGrants.begin()->second.m_psschT
x.size() == 0) { |
| 1578 // //no more PSSCH transmission, clear the grant |
| 1579 // m_slTxPoolInfo.m_currentGrants.clear (); |
| 1580 // } |
| 1581 |
| 1582 if (m_enableUplinkPowerControl) |
| 1583 { |
| 1584 m_txPower = m_powerControl->GetPsschTxPower (rbMask); |
| 1585 } |
| 1586 |
| 1587 //SetSubChannelsForTransmission (rbMask); |
| 1588 //m_uplinkSpectrumPhy->StartTxSlDataFrame (pb, ctrlMsg, UL_DAT
A_DURATION, m_slTxPoolInfo.m_currentGrants.begin()->second.m_grant.m_groupDstId)
; |
| 1589 |
| 1590 //Synchronization has priority over communication |
| 1591 //The PSSCH is transmitted only if no synchronization operatio
ns are being performed |
| 1592 if (!mibSLfound) |
| 1593 { |
| 1594 if(m_ueSlssScanningInProgress) |
| 1595 { |
| 1596 NS_LOG_LOGIC(this <<" trying to do a PSSCH transmissio
n while there is a scanning in progress... Ignoring transmission"); |
| 1597 } |
| 1598 else if(m_ueSlssMeasurementsSched.find(Simulator::Now().Ge
tMilliSeconds()) != m_ueSlssMeasurementsSched.end()) |
| 1599 { |
| 1600 NS_LOG_LOGIC(this << " trying to do a PSSCH transmissi
on while measuring S-RSRP in the same subframe... Ignoring transmission"); |
| 1601 } |
| 1602 else |
| 1603 { |
| 1604 SetSubChannelsForTransmission (rbMask); |
| 1605 m_uplinkSpectrumPhy->StartTxSlDataFrame (pb, ctrlMsg,
UL_DATA_DURATION, m_slTxPoolInfo.m_currentGrants.begin()->second.m_grant.m_group
DstId); |
| 1606 } |
| 1607 } |
| 1608 else |
| 1609 { |
| 1610 //TODO: Make the transmission possible if using different
RBs than MIB-SL |
| 1611 NS_LOG_LOGIC(this << " trying to do a PSSCH transmission w
hile there is a PSBCH (SLSS) transmission scheduled... Ignoring transmission "); |
| 1612 } |
| 1613 } |
| 1614 else |
| 1615 { |
| 1616 // send only PSCCH (ideal: fake null bandwidth signal) |
| 1617 if (ctrlMsg.size ()>0 && sciDiscfound) |
| 1618 { |
| 1619 ······················ |
| 1620 std::list<Ptr<NistLteControlMessage> >::iterator msgIt = c
trlMsg.begin(); |
| 1621 //skiping the MIB-SL if it is the first in the list |
| 1622 if((*msgIt)->GetMessageType () != NistLteControlMessage::S
CI && (*msgIt)->GetMessageType () != NistLteControlMessage::SL_DISC_MSG) |
| 1623 { |
| 1624 msgIt++; |
| 1625 } |
| 1626 · |
| 1627 else if ((*msgIt)->GetMessageType () == NistLteControlMess
age::SCI) |
| 1628 { |
| 1629 NS_LOG_LOGIC (this << " UE - start TX PSCCH"); |
| 1630 //access the control message to store the PSSCH grant an
d be able to |
| 1631 //determine the subframes/RBs for PSSCH transmissions/ d
iscovery |
| 1632 |
| 1633 NS_ASSERT_MSG ((*msgIt)->GetMessageType () == NistLteCon
trolMessage::SCI, "Received " << (*msgIt)->GetMessageType ()); |
| 1634 |
| 1635 Ptr<SciNistLteControlMessage> msg2 = DynamicCast<SciNist
LteControlMessage> (*msgIt); |
| 1636 NistSciListElement_s sci = msg2->GetSci (); |
| 1637 |
| 1638 std::map<uint16_t, SidelinkGrantInfo>::iterator grantIt
= m_slTxPoolInfo.m_currentGrants.find (sci.m_rnti); |
| 1639 if (grantIt == m_slTxPoolInfo.m_currentGrants.end ()) |
| 1640 { |
| 1641 SidelinkGrantInfo grantInfo; |
| 1642 //this is the first transmission of PSCCH |
| 1643 grantInfo.m_grant_received = true; |
| 1644 grantInfo.m_grant.m_rnti = sci.m_rnti; |
| 1645 grantInfo.m_grant.m_resPscch = sci.m_resPscch; |
| 1646 grantInfo.m_grant.m_rbStart = sci.m_rbStart; |
| 1647 grantInfo.m_grant.m_rbLen = sci.m_rbLen; |
| 1648 grantInfo.m_grant.m_trp = sci.m_trp; |
| 1649 grantInfo.m_grant.m_groupDstId = sci.m_groupDstId; |
| 1650 grantInfo.m_grant.m_mcs = sci.m_mcs; |
| 1651 grantInfo.m_grant.m_tbSize = sci.m_tbSize; |
| 1652 |
| 1653 grantInfo.m_grant.frameNo = frameNo; |
| 1654 grantInfo.m_grant.subframeNo = subframeNo; |
| 1655 |
| 1656 grantInfo.m_pscchTx = m_slTxPoolInfo.m_pool->GetPscc
hTransmissions (sci.m_resPscch); |
| 1657 SidelinkCommResourcePool::SubframeInfo tmp = m_slTxP
oolInfo.m_pool->GetCurrentScPeriod(frameNo, subframeNo); |
| 1658 grantInfo.m_psschTx = m_slTxPoolInfo.m_pool->GetPssc
hTransmissions (tmp, grantInfo.m_grant.m_trp, grantInfo.m_grant.m_rbStart, grant
Info.m_grant.m_rbLen); |
| 1659 |
| 1660 std::list<SidelinkCommResourcePool::SidelinkTransmis
sionInfo>::iterator txIt; |
| 1661 for (txIt = grantInfo.m_psschTx.begin (); txIt != gr
antInfo.m_psschTx.end (); txIt++) |
| 1662 { |
| 1663 //adjust for index starting at 1 |
| 1664 txIt->subframe.frameNo++; |
| 1665 txIt->subframe.subframeNo++; |
| 1666 NS_LOG_INFO (this << " Subframe Tx" << txIt->sub
frame.frameNo << "/" << txIt->subframe.subframeNo << ": rbStart=" << (uint32_t)
txIt->rbStart << ", rbLen=" << (uint32_t) txIt->nbRb); |
| 1667 } |
| 1668 |
| 1669 //insert grant |
| 1670 m_slTxPoolInfo.m_currentGrants.insert (std::pair <ui
nt16_t, SidelinkGrantInfo> (sci.m_rnti, grantInfo)); |
| 1671 NS_LOG_DEBUG (this << " Creating grant at " << gran
tInfo.m_grant.frameNo << "/" << grantInfo.m_grant.subframeNo); |
| 1672 } |
| 1673 else |
| 1674 { |
| 1675 NS_LOG_DEBUG (this << " Grant created at " << grant
It->second.m_grant.frameNo << "/" << grantIt->second.m_grant.subframeNo); |
| 1676 } |
| 1677 std::list<SidelinkCommResourcePool::SidelinkTransmission
Info>::iterator txIt = m_slTxPoolInfo.m_currentGrants.begin()->second.m_pscchTx.
begin (); |
| 1678 NS_ASSERT (txIt != m_slTxPoolInfo.m_currentGrants.begin(
)->second.m_pscchTx.end()); //must be at least one element |
| 1679 std::vector <int> slRb; |
| 1680 for (int i = txIt->rbStart ; i < txIt->rbStart + txIt->n
bRb ; i++) |
| 1681 { |
| 1682 NS_LOG_LOGIC (this << " Transmitting PSCCH on RB " <
< i); |
| 1683 slRb.push_back (i); |
| 1684 } |
| 1685 m_slTxPoolInfo.m_currentGrants.begin()->second.m_pscchTx
.erase (txIt); |
| 1686 |
| 1687 //in some cases (when frames reached 1024), there can be
a period with no |
| 1688 //slots for PSSCH. This causes the grant to not be clear
ed during the transmission |
| 1689 //of PSSCH frames. We check and clear here after the tra
nsmission of the second PSCCH |
| 1690 // if (m_slTxPoolInfo.m_currentGrants.begin()->second.m_
pscchTx.size() == 0 && m_slTxPoolInfo.m_currentGrants.begin()->second.m_psschTx.
size() == 0) { |
| 1691 // m_slTxPoolInfo.m_currentGrants.clear (); |
| 1692 // } |
| 1693 |
| 1694 if (m_enableUplinkPowerControl) |
| 1695 { |
| 1696 m_txPower = m_powerControl->GetPscchTxPower (slRb); |
| 1697 } |
| 1698 |
| 1699 //SetSubChannelsForTransmission (slRb); |
| 1700 //m_uplinkSpectrumPhy->StartTxSlDataFrame (pb, ctrlMsg,
UL_DATA_DURATION, sci.m_groupDstId); |
| 1701 |
| 1702 //Synchronization has priority over communication |
| 1703 //The PSCCH is transmitted only if no synchronization op
erations are being performed |
| 1704 if (!mibSLfound) |
| 1705 { |
| 1706 if(m_ueSlssScanningInProgress) |
| 1707 { |
| 1708 NS_LOG_LOGIC(this << "trying to do a PSCCH trans
mission while there is a scanning in progress... Ignoring transmission"); |
| 1709 |
| 1710 } |
| 1711 else if(m_ueSlssMeasurementsSched.find(Simulator::No
w().GetMilliSeconds()) != m_ueSlssMeasurementsSched.end()) //Measurement in this
subframe |
| 1712 { |
| 1713 NS_LOG_LOGIC(this << " trying to do a PSCCH tran
smission while measuring S-RSRP in the same subframe... Ignoring transmission"); |
| 1714 } |
| 1715 else |
| 1716 { |
| 1717 SetSubChannelsForTransmission (slRb); |
| 1718 m_uplinkSpectrumPhy->StartTxSlDataFrame (pb, ctr
lMsg, UL_DATA_DURATION, sci.m_groupDstId); |
| 1719 } |
| 1720 } |
| 1721 else |
| 1722 { |
| 1723 //TODO: Make the transmission possible if using diff
erent RBs than MIB-SL |
| 1724 NS_LOG_LOGIC(this << " trying to do a PSCCH transmis
sion while there is a PSBCH (SLSS) transmission scheduled... Ignoring transmissi
on "); |
| 1725 } |
| 1726 } |
| 1727 |
| 1728 ·················· |
| 1729 else if ((*msgIt)->GetMessageType () == NistLteControlMessag
e::SL_DISC_MSG) |
| 1730 { |
| 1731 NS_LOG_LOGIC (this << " UE - start Tx PSDCH"); |
| 1732 NS_ASSERT_MSG ((*msgIt)->GetMessageType () == NistLteContr
olMessage::SL_DISC_MSG, "Received " << (*msgIt)->GetMessageType ()); |
| 1733 ······················· |
| 1734 std::map<uint16_t, DiscGrantInfo>::iterator grantIt = m_di
scTxPools.m_currentGrants.find (m_rnti); |
| 1735 if (grantIt == m_discTxPools.m_currentGrants.end ())· |
| 1736 { |
| 1737 DiscGrantInfo grantInfo; |
| 1738 grantInfo.m_grant_received = true; |
| 1739 grantInfo.m_grant.m_rnti = m_rnti; |
| 1740 grantInfo.m_grant.m_resPsdch = m_discResPsdch; |
| 1741 |
| 1742 grantInfo.m_psdchTx = m_discTxPools.m_pool->GetPsdchTr
ansmissions (grantInfo.m_grant.m_resPsdch); |
| 1743 ·························· |
| 1744 uint8_t retx = m_discTxPools.m_pool->GetNumRetx (); |
| 1745 m_uplinkSpectrumPhy->SetDiscNumRetx (retx); |
| 1746 ·························· |
| 1747 std::list<SidelinkDiscResourcePool::SidelinkTransmi
ssionInfo>::iterator txIt; |
| 1748 for (txIt = grantInfo.m_psdchTx.begin (); txIt != gran
tInfo.m_psdchTx.end (); txIt++) |
| 1749 { |
| 1750 //adjust for index starting at 1 |
| 1751 txIt->subframe.frameNo++; |
| 1752 txIt->subframe.subframeNo++; |
| 1753 } |
| 1754 |
| 1755 NS_LOG_DEBUG (this << " Creating grant"); |
| 1756 m_discTxPools.m_currentGrants.insert (std::pair<uint16
_t,DiscGrantInfo> (m_rnti, grantInfo)); |
| 1757 } |
| 1758 else· |
| 1759 { |
| 1760 NS_LOG_DEBUG (this << " Grant already created"); |
| 1761 } |
| 1762 |
| 1763 ························ |
| 1764 std::list<SidelinkDiscResourcePool::SidelinkTransmission
Info>::iterator txIt = m_discTxPools.m_currentGrants.begin()->second.m_psdchTx.b
egin (); |
| 1765 NS_ASSERT (txIt != m_discTxPools.m_currentGrants.begin()
->second.m_psdchTx.end());· |
| 1766 std::vector <int> slRb; |
| 1767 for (int i = txIt->rbStart ; i < txIt->rbStart + txIt->n
bRb ; i++) |
| 1768 { |
| 1769 NS_LOG_LOGIC (this << " Transmitting PSDCH on RB " <<
i); |
| 1770 slRb.push_back (i); |
| 1771 } |
| 1772 ························· |
| 1773 m_discTxPools.m_currentGrants.begin()->second.m_psdchTx.
erase (txIt); |
| 1774 ························· |
| 1775 //TODO: UL power control for discovery |
| 1776 if (m_enableUplinkPowerControl) |
| 1777 { |
| 1778 m_txPower = m_powerControl->GetPsdchTxPower (slRb); |
| 1779 } |
| 1780 ················ |
| 1781 SetSubChannelsForTransmission (slRb); |
| 1782 |
| 1783 |
| 1784 ·························· |
| 1785 //0 added to passby the group Id |
| 1786 //to be double checked |
| 1787 // |
| 1788 m_uplinkSpectrumPhy->StartTxSlDataFrame (pb, ctrlMsg, UL
_DATA_DURATION,0); |
| 1789 ······················· |
| 1790 for (std::list<Ptr<NistLteControlMessage> >::iterator ms
g = ctrlMsg.begin(); msg != ctrlMsg.end(); ++msg) |
| 1791 { |
| 1792 NS_LOG_LOGIC (this << ((*msg)->GetMessageType ()) << "
discovery msg"); |
| 1793 Ptr<NistSlDiscMessage> msg2 = DynamicCast<NistSlDiscMe
ssage> ((*msg)); |
| 1794 if (msg2) |
| 1795 { |
| 1796 NistSlDiscMsg disc = msg2->GetSlDiscMessage (); |
| 1797 m_discoveryAnnouncementTrace (m_cellId, m_rnti,(uint
32_t)disc.m_proSeAppCode.to_ulong()); |
| 1798 } |
| 1799 } |
| 1800 ························ |
| 1801 } |
| 1802 |
| 1803 else |
| 1804 { |
| 1805 NS_LOG_LOGIC (this << " UE - SL/UL NOTHING TO SEND"); |
| 1806 } |
| 1807 } |
| 1808 }····· |
| 1809 }//end if !m_waitingNextScPeriod |
| 1810 else |
| 1811 { |
| 1812 NS_LOG_LOGIC (this << " the UE changed of timing and it is waiting
for the start of a new SC period using the new timing... Delaying transmissions
"); |
| 1813 } |
| 1814 |
| 1815 //Transmit the SLSS |
| 1816 if (mibSLfound) |
| 1817 { |
| 1818 //Remove all other control packets (i.e., SCI) |
| 1819 ctrlIt=ctrlMsg.begin(); |
| 1820 while (ctrlIt != ctrlMsg.end()) |
| 1821 { |
| 1822 if ((*ctrlIt)->GetMessageType () != NistLteControlMessage::MIB
_SL) |
| 1823 { |
| 1824 ctrlIt = ctrlMsg.erase (ctrlIt); |
| 1825 } |
| 1826 else |
| 1827 { |
| 1828 ctrlIt++; |
| 1829 } |
| 1830 } |
| 1831 |
| 1832 ctrlIt=ctrlMsg.begin(); |
| 1833 |
| 1834 //We assume the SyncRef selection has priority over SLSS transmiss
ion |
| 1835 //The SLSS is sent only if no scanning or measurement is performed
in this subframe |
| 1836 if(m_ueSlssScanningInProgress) |
| 1837 { |
| 1838 NS_LOG_LOGIC(this << " trying to do a PSBCH transmission while
there is a scanning in progress... Ignoring transmission"); |
| 1839 } |
| 1840 else if(m_ueSlssMeasurementsSched.find(Simulator::Now().GetMilliSe
conds()) != m_ueSlssMeasurementsSched.end()) //Measurement in this subframe |
| 1841 { |
| 1842 NS_LOG_LOGIC(this << " trying to do a PSBCH transmission while
measuring S-RSRP in the same subframe... Ignoring transmission"); |
| 1843 } |
| 1844 else |
| 1845 { |
| 1846 std::vector<int> dlRb; |
| 1847 for (uint8_t i = 22; i < 28; i++) |
| 1848 { |
| 1849 dlRb.push_back(i); |
| 1850 } |
| 1851 if (m_enableUplinkPowerControl) |
| 1852 { |
| 1853 //TODO: Set the transmission power corresponding to PSBCH |
| 1854 m_txPower = m_powerControl->GetPscchTxPower(dlRb); |
| 1855 } |
| 1856 SetSubChannelsForTransmission(dlRb); |
| 1857 m_uplinkSpectrumPhy->StartTxSlDataFrame(pb, ctrlMsg, UL_DATA_D
URATION,m_slTxPoolInfo.m_currentGrants.begin()->second.m_grant.m_groupDstId); |
| 1858 } |
| 1859 } |
| 1860 } |
| 1861 |
| 1862 } // m_configured |
| 1863 |
| 1864 // trigger the MAC |
| 1865 m_uePhySapUser->SubframeIndication (frameNo, subframeNo); |
| 1866 |
| 1867 m_subframeNo = subframeNo; |
| 1868 ++subframeNo; |
| 1869 if (subframeNo > 10) |
| 1870 { |
| 1871 ++frameNo; |
| 1872 if (frameNo > 1024) { |
| 1873 frameNo = 1; |
| 1874 } |
| 1875 subframeNo = 1; |
| 1876 } |
| 1877 |
| 1878 // schedule next subframe indication |
| 1879 Simulator::Schedule (Seconds (GetTti ()), &NistLteUePhy::SubframeIndication, t
his, frameNo, subframeNo); |
| 1880 } |
| 1881 |
| 1882 |
| 1883 void |
| 1884 NistLteUePhy::SendSrs () |
| 1885 { |
| 1886 NS_LOG_FUNCTION (this << " UE " << m_rnti << " start tx SRS, cell Id " << (uin
t32_t) m_cellId); |
| 1887 NS_ASSERT (m_cellId > 0); |
| 1888 // set the current tx power spectral density (full bandwidth) |
| 1889 std::vector <int> dlRb; |
| 1890 for (uint8_t i = 0; i < m_ulBandwidth; i++) |
| 1891 { |
| 1892 dlRb.push_back (i); |
| 1893 } |
| 1894 |
| 1895 if (m_enableUplinkPowerControl) |
| 1896 { |
| 1897 m_txPower = m_powerControl->GetSrsTxPower (dlRb); |
| 1898 } |
| 1899 |
| 1900 SetSubChannelsForTransmission (dlRb); |
| 1901 m_uplinkSpectrumPhy->StartTxUlSrsFrame (); |
| 1902 } |
| 1903 |
| 1904 |
| 1905 void |
| 1906 NistLteUePhy::DoReset () |
| 1907 { |
| 1908 NS_LOG_FUNCTION (this); |
| 1909 |
| 1910 m_rnti = 0; |
| 1911 m_transmissionMode = 0; |
| 1912 m_srsPeriodicity = 0; |
| 1913 m_srsConfigured = false; |
| 1914 m_dlConfigured = false; |
| 1915 m_ulConfigured = false; |
| 1916 m_raPreambleId = 255; // value out of range |
| 1917 m_raRnti = 11; // value out of range |
| 1918 m_rsrpSinrSampleCounter = 0; |
| 1919 m_p10CqiLast = Simulator::Now (); |
| 1920 m_a30CqiLast = Simulator::Now (); |
| 1921 m_paLinear = 1; |
| 1922 |
| 1923 m_packetBurstQueue.clear (); |
| 1924 m_controlMessagesQueue.clear (); |
| 1925 m_subChannelsForTransmissionQueue.clear (); |
| 1926 for (int i = 0; i < m_macChTtiDelay; i++) |
| 1927 { |
| 1928 Ptr<PacketBurst> pb = CreateObject <PacketBurst> (); |
| 1929 m_packetBurstQueue.push_back (pb); |
| 1930 std::list<Ptr<NistLteControlMessage> > l; |
| 1931 m_controlMessagesQueue.push_back (l); |
| 1932 } |
| 1933 std::vector <int> ulRb; |
| 1934 m_subChannelsForTransmissionQueue.resize (m_macChTtiDelay, ulRb); |
| 1935 |
| 1936 m_sendSrsEvent.Cancel (); |
| 1937 m_downlinkSpectrumPhy->Reset (); |
| 1938 m_uplinkSpectrumPhy->Reset (); |
| 1939 |
| 1940 } // end of void NistLteUePhy::DoReset () |
| 1941 |
| 1942 void |
| 1943 NistLteUePhy::DoStartCellSearch (uint16_t dlEarfcn) |
| 1944 { |
| 1945 NS_LOG_FUNCTION (this << dlEarfcn); |
| 1946 m_dlEarfcn = dlEarfcn; |
| 1947 DoSetDlBandwidth (6); // configure DL for receiving PSS |
| 1948 SwitchToState (CELL_SEARCH); |
| 1949 } |
| 1950 |
| 1951 void |
| 1952 NistLteUePhy::DoSynchronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn) |
| 1953 { |
| 1954 NS_LOG_FUNCTION (this << cellId << dlEarfcn); |
| 1955 m_dlEarfcn = dlEarfcn; |
| 1956 DoSynchronizeWithEnb (cellId); |
| 1957 } |
| 1958 |
| 1959 void |
| 1960 NistLteUePhy::DoSynchronizeWithEnb (uint16_t cellId) |
| 1961 { |
| 1962 NS_LOG_FUNCTION (this << cellId); |
| 1963 |
| 1964 if (cellId == 0) |
| 1965 { |
| 1966 NS_FATAL_ERROR ("Cell ID shall not be zero"); |
| 1967 } |
| 1968 |
| 1969 m_cellId = cellId; |
| 1970 m_downlinkSpectrumPhy->SetCellId (cellId); |
| 1971 m_uplinkSpectrumPhy->SetCellId (cellId); |
| 1972 |
| 1973 // configure DL for receiving the BCH with the minimum bandwidth |
| 1974 DoSetDlBandwidth (6); |
| 1975 |
| 1976 m_dlConfigured = false; |
| 1977 m_ulConfigured = false; |
| 1978 |
| 1979 SwitchToState (SYNCHRONIZED); |
| 1980 } |
| 1981 |
| 1982 void |
| 1983 NistLteUePhy::DoSetDlBandwidth (uint8_t dlBandwidth) |
| 1984 { |
| 1985 NS_LOG_FUNCTION (this << (uint32_t) dlBandwidth); |
| 1986 if (m_dlBandwidth != dlBandwidth or !m_dlConfigured) |
| 1987 { |
| 1988 m_dlBandwidth = dlBandwidth; |
| 1989 |
| 1990 static const int Type0AllocationRbg[4] = { |
| 1991 10, // RGB size 1 |
| 1992 26, // RGB size 2 |
| 1993 63, // RGB size 3 |
| 1994 110 // RGB size 4 |
| 1995 }; // see table 7.1.6.1-1 of 36.213 |
| 1996 for (int i = 0; i < 4; i++) |
| 1997 { |
| 1998 if (dlBandwidth < Type0AllocationRbg[i]) |
| 1999 { |
| 2000 m_rbgSize = i + 1; |
| 2001 break; |
| 2002 } |
| 2003 } |
| 2004 |
| 2005 m_noisePsd = NistLteSpectrumValueHelper::CreateNoisePowerSpectralDensity (
m_dlEarfcn, m_dlBandwidth, m_noiseFigure); |
| 2006 m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (m_noisePsd); |
| 2007 m_downlinkSpectrumPhy->GetChannel ()->AddRx (m_downlinkSpectrumPhy); |
| 2008 } |
| 2009 m_dlConfigured = true; |
| 2010 } |
| 2011 |
| 2012 |
| 2013 void· |
| 2014 NistLteUePhy::DoConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth) |
| 2015 { |
| 2016 NS_LOG_FUNCTION (this << ulEarfcn << (uint16_t) ulBandwidth); |
| 2017 m_ulEarfcn = ulEarfcn; |
| 2018 m_ulBandwidth = ulBandwidth; |
| 2019 m_ulConfigured = true; |
| 2020 |
| 2021 //configure sidelink with UL |
| 2022 if (m_sidelinkSpectrumPhy) { |
| 2023 m_slNoisePsd = NistLteSpectrumValueHelper::CreateNoisePowerSpectralDensity (
m_ulEarfcn, m_ulBandwidth, m_noiseFigure); |
| 2024 m_sidelinkSpectrumPhy->SetNoisePowerSpectralDensity (m_slNoisePsd); |
| 2025 m_sidelinkSpectrumPhy->GetChannel ()->AddRx (m_sidelinkSpectrumPhy); |
| 2026 } |
| 2027 } |
| 2028 |
| 2029 void |
| 2030 NistLteUePhy::DoConfigureReferenceSignalPower (int8_t referenceSignalPower) |
| 2031 { |
| 2032 NS_LOG_FUNCTION (this); |
| 2033 m_powerControl->ConfigureReferenceSignalPower (referenceSignalPower); |
| 2034 } |
| 2035 · |
| 2036 void |
| 2037 NistLteUePhy::DoSetRnti (uint16_t rnti) |
| 2038 { |
| 2039 NS_LOG_FUNCTION (this << " ID:" << m_uplinkSpectrumPhy->GetDevice()->GetNode()
->GetId() << " RNTI: " << rnti); |
| 2040 m_rnti = rnti; |
| 2041 |
| 2042 m_powerControl->SetCellId (m_cellId); |
| 2043 m_powerControl->SetRnti (m_rnti); |
| 2044 } |
| 2045 · |
| 2046 void |
| 2047 NistLteUePhy::DoSetTransmissionMode (uint8_t txMode) |
| 2048 { |
| 2049 NS_LOG_FUNCTION (this << (uint16_t)txMode); |
| 2050 m_transmissionMode = txMode; |
| 2051 m_downlinkSpectrumPhy->SetTransmissionMode (txMode); |
| 2052 } |
| 2053 |
| 2054 void |
| 2055 NistLteUePhy::DoSetSrsConfigurationIndex (uint16_t srcCi) |
| 2056 { |
| 2057 NS_LOG_FUNCTION (this << srcCi); |
| 2058 m_srsPeriodicity = GetSrsPeriodicity (srcCi); |
| 2059 m_srsSubframeOffset = GetSrsSubframeOffset (srcCi); |
| 2060 m_srsConfigured = true; |
| 2061 |
| 2062 // a guard time is needed for the case where the SRS periodicity is changed dy
namically at run time |
| 2063 // if we use a static one, we can have a 0ms guard time |
| 2064 m_srsStartTime = Simulator::Now () + MilliSeconds (0); |
| 2065 NS_LOG_DEBUG (this << " UE SRS P " << m_srsPeriodicity << " RNTI " << m_rnti <
< " offset " << m_srsSubframeOffset << " cellId " << m_cellId << " CI " << srcCi
); |
| 2066 } |
| 2067 |
| 2068 void |
| 2069 NistLteUePhy::DoSetPa (double pa) |
| 2070 { |
| 2071 NS_LOG_FUNCTION (this << pa); |
| 2072 m_paLinear = pow (10,(pa/10)); |
| 2073 } |
| 2074 ·· |
| 2075 void |
| 2076 NistLteUePhy::DoSetSlTxPool (Ptr<SidelinkTxDiscResourcePool> pool) |
| 2077 { |
| 2078 m_discTxPools.m_pool = pool; |
| 2079 m_discTxPools.m_npsdch = pool->GetNPsdch (); |
| 2080 m_discTxPools.m_currentGrants.clear ();·· |
| 2081 m_discTxPools.m_nextDiscPeriod.frameNo = 0; |
| 2082 m_discTxPools.m_nextDiscPeriod.subframeNo = 0; |
| 2083 |
| 2084 } |
| 2085 |
| 2086 |
| 2087 void |
| 2088 NistLteUePhy::DoRemoveSlTxPool (bool disc) |
| 2089 { |
| 2090 m_discTxPools.m_pool = NULL; |
| 2091 m_discTxPools.m_npsdch = 0; |
| 2092 m_discTxPools.m_currentGrants.clear (); |
| 2093 } |
| 2094 |
| 2095 |
| 2096 void |
| 2097 NistLteUePhy::DoSetSlRxPools (std::list<Ptr<SidelinkRxDiscResourcePool> > pools) |
| 2098 { |
| 2099 ·· |
| 2100 std::list<Ptr<SidelinkRxDiscResourcePool> >::iterator poolIt; |
| 2101 for (poolIt = pools.begin (); poolIt != pools.end(); poolIt++) |
| 2102 { |
| 2103 bool found = false; |
| 2104 std::list<DiscPoolInfo >::iterator currentPoolIt; |
| 2105 for (currentPoolIt = m_discRxPools.begin (); currentPoolIt != m_discRxPool
s.end() && !found; currentPoolIt++) |
| 2106 { |
| 2107 if (*poolIt == currentPoolIt->m_pool) |
| 2108 { |
| 2109 found = true; |
| 2110 } |
| 2111 } |
| 2112 if (!found) |
| 2113 { |
| 2114 DiscPoolInfo newpool; |
| 2115 newpool.m_pool = *poolIt; |
| 2116 newpool.m_npsdch = (*poolIt)->GetNPsdch (); |
| 2117 newpool.m_currentGrants.clear (); |
| 2118 m_discRxPools.push_back (newpool); |
| 2119 // |
| 2120 m_sidelinkSpectrumPhy->SetRxPool (newpool.m_pool); |
| 2121 // |
| 2122 } |
| 2123 } |
| 2124 } |
| 2125 |
| 2126 void |
| 2127 NistLteUePhy::DoSetDiscGrantInfo (uint8_t resPsdch) |
| 2128 { |
| 2129 m_discResPsdch = resPsdch; |
| 2130 } |
| 2131 |
| 2132 void· |
| 2133 NistLteUePhy::DoAddDiscTxApps (std::list<uint32_t> apps) |
| 2134 { |
| 2135 m_discTxApps = apps; |
| 2136 m_sidelinkSpectrumPhy->AddDiscTxApps (apps); |
| 2137 } |
| 2138 |
| 2139 void· |
| 2140 NistLteUePhy::DoAddDiscRxApps (std::list<uint32_t> apps) |
| 2141 { |
| 2142 m_discRxApps = apps; |
| 2143 m_sidelinkSpectrumPhy->AddDiscRxApps (apps); |
| 2144 } |
| 2145 |
| 2146 void |
| 2147 NistLteUePhy::DoSetSlTxPool (Ptr<SidelinkTxCommResourcePool> pool) |
| 2148 { |
| 2149 m_slTxPoolInfo.m_pool = pool; |
| 2150 m_slTxPoolInfo.m_npscch = pool->GetNPscch(); |
| 2151 m_slTxPoolInfo.m_currentGrants.clear(); |
| 2152 m_slTxPoolInfo.m_nextScPeriod.frameNo = 0; //init to 0 to make it invalid |
| 2153 m_slTxPoolInfo.m_nextScPeriod.subframeNo = 0; //init to 0 to make it invalid |
| 2154 } |
| 2155 |
| 2156 void |
| 2157 NistLteUePhy::DoRemoveSlTxPool () |
| 2158 { |
| 2159 m_slTxPoolInfo.m_pool = NULL; |
| 2160 m_slTxPoolInfo.m_npscch = 0; |
| 2161 m_slTxPoolInfo.m_currentGrants.clear(); |
| 2162 } |
| 2163 ·· |
| 2164 void |
| 2165 NistLteUePhy::DoSetSlRxPools (std::list<Ptr<SidelinkRxCommResourcePool> > pools) |
| 2166 { |
| 2167 //update the pools that have changed |
| 2168 std::list<Ptr<SidelinkRxCommResourcePool> >::iterator poolIt; |
| 2169 for (poolIt = pools.begin (); poolIt != pools.end(); poolIt++) |
| 2170 { |
| 2171 bool found = false; |
| 2172 std::list<PoolInfo >::iterator currentPoolIt; |
| 2173 for (currentPoolIt = m_sidelinkRxPools.begin (); currentPoolIt != m_sideli
nkRxPools.end() && !found; currentPoolIt++) |
| 2174 { |
| 2175 if (*poolIt == currentPoolIt->m_pool) |
| 2176 { |
| 2177 found = true; |
| 2178 } |
| 2179 } |
| 2180 if (!found) |
| 2181 { |
| 2182 PoolInfo newpool; |
| 2183 newpool.m_pool = *poolIt; |
| 2184 newpool.m_npscch = (*poolIt)->GetNPscch(); |
| 2185 newpool.m_currentGrants.clear(); |
| 2186 m_sidelinkRxPools.push_back (newpool); |
| 2187 } |
| 2188 } |
| 2189 //TODO: should remove the ones no longer needed. |
| 2190 //Find a clean way to handle updates |
| 2191 //m_sidelinkRxPools.clear (); |
| 2192 ·· |
| 2193 } |
| 2194 |
| 2195 void |
| 2196 NistLteUePhy::DoAddSlDestination (uint32_t destination) |
| 2197 { |
| 2198 std::list <uint32_t>::iterator it; |
| 2199 for (it = m_destinations.begin (); it != m_destinations.end ();it++) { |
| 2200 if ((*it) == destination) { |
| 2201 break; |
| 2202 } |
| 2203 } |
| 2204 if (it == m_destinations.end ()) { |
| 2205 //did not find it, so insert |
| 2206 m_destinations.push_back (destination); |
| 2207 |
| 2208 if (m_sidelinkSpectrumPhy) { |
| 2209 m_sidelinkSpectrumPhy->AddL1GroupId (destination); |
| 2210 } |
| 2211 } |
| 2212 } |
| 2213 |
| 2214 ·· |
| 2215 void |
| 2216 NistLteUePhy::DoRemoveSlDestination (uint32_t destination) |
| 2217 { |
| 2218 std::list <uint32_t>::iterator it = m_destinations.begin (); |
| 2219 while (it != m_destinations.end ()) { |
| 2220 if ((*it) == destination) { |
| 2221 m_destinations.erase (it); |
| 2222 if (m_sidelinkSpectrumPhy) { |
| 2223 m_sidelinkSpectrumPhy->RemoveL1GroupId (destination); |
| 2224 } |
| 2225 break;//leave the loop |
| 2226 } |
| 2227 it++; |
| 2228 } |
| 2229 } |
| 2230 ·· |
| 2231 |
| 2232 void· |
| 2233 NistLteUePhy::SetTxMode1Gain (double gain) |
| 2234 { |
| 2235 SetTxModeGain (1, gain); |
| 2236 } |
| 2237 |
| 2238 void· |
| 2239 NistLteUePhy::SetTxMode2Gain (double gain) |
| 2240 { |
| 2241 SetTxModeGain (2, gain); |
| 2242 } |
| 2243 |
| 2244 void· |
| 2245 NistLteUePhy::SetTxMode3Gain (double gain) |
| 2246 { |
| 2247 SetTxModeGain (3, gain); |
| 2248 } |
| 2249 |
| 2250 void· |
| 2251 NistLteUePhy::SetTxMode4Gain (double gain) |
| 2252 { |
| 2253 SetTxModeGain (4, gain); |
| 2254 } |
| 2255 |
| 2256 void· |
| 2257 NistLteUePhy::SetTxMode5Gain (double gain) |
| 2258 { |
| 2259 SetTxModeGain (5, gain); |
| 2260 } |
| 2261 |
| 2262 void· |
| 2263 NistLteUePhy::SetTxMode6Gain (double gain) |
| 2264 { |
| 2265 SetTxModeGain (6, gain); |
| 2266 } |
| 2267 |
| 2268 void· |
| 2269 NistLteUePhy::SetTxMode7Gain (double gain) |
| 2270 { |
| 2271 SetTxModeGain (7, gain); |
| 2272 } |
| 2273 |
| 2274 |
| 2275 void |
| 2276 NistLteUePhy::SetTxModeGain (uint8_t txMode, double gain) |
| 2277 { |
| 2278 NS_LOG_FUNCTION (this << gain); |
| 2279 // convert to linear |
| 2280 double gainLin = std::pow (10.0, (gain / 10.0)); |
| 2281 if (m_txModeGain.size () < txMode) |
| 2282 { |
| 2283 m_txModeGain.resize (txMode); |
| 2284 } |
| 2285 std::vector <double> temp; |
| 2286 temp = m_txModeGain; |
| 2287 m_txModeGain.clear (); |
| 2288 for (uint8_t i = 0; i < temp.size (); i++) |
| 2289 { |
| 2290 if (i==txMode-1) |
| 2291 { |
| 2292 m_txModeGain.push_back (gainLin); |
| 2293 } |
| 2294 else |
| 2295 { |
| 2296 m_txModeGain.push_back (temp.at (i)); |
| 2297 } |
| 2298 } |
| 2299 // forward the info to DL NistLteSpectrumPhy |
| 2300 m_downlinkSpectrumPhy->SetTxModeGain (txMode, gain); |
| 2301 } |
| 2302 |
| 2303 |
| 2304 |
| 2305 void |
| 2306 NistLteUePhy::ReceiveLteDlHarqFeedback (NistDlInfoListElement_s m) |
| 2307 { |
| 2308 NS_LOG_FUNCTION (this); |
| 2309 // generate feedback to eNB and send it through ideal PUCCH |
| 2310 Ptr<NistDlHarqFeedbackLteControlMessage> msg = Create<NistDlHarqFeedbackLteCon
trolMessage> (); |
| 2311 msg->SetDlHarqFeedback (m); |
| 2312 SetControlMessages (msg); |
| 2313 } |
| 2314 |
| 2315 void |
| 2316 NistLteUePhy::SetHarqPhyModule (Ptr<NistLteHarqPhy> harq) |
| 2317 { |
| 2318 m_harqPhyModule = harq; |
| 2319 } |
| 2320 |
| 2321 |
| 2322 NistLteUePhy::State |
| 2323 NistLteUePhy::GetState () const |
| 2324 { |
| 2325 NS_LOG_FUNCTION (this); |
| 2326 return m_state; |
| 2327 } |
| 2328 |
| 2329 |
| 2330 void |
| 2331 NistLteUePhy::SwitchToState (State newState) |
| 2332 { |
| 2333 NS_LOG_FUNCTION (this << newState); |
| 2334 State oldState = m_state; |
| 2335 m_state = newState; |
| 2336 NS_LOG_INFO (this << " cellId=" << m_cellId << " rnti=" << m_rnti |
| 2337 << " UePhy " << ToString (oldState) |
| 2338 << " --> " << ToString (newState)); |
| 2339 m_stateTransitionTrace (m_cellId, m_rnti, oldState, newState); |
| 2340 } |
| 2341 |
| 2342 void NistLteUePhy::SetFirstScanningTime(Time t){ |
| 2343 NS_LOG_FUNCTION (this); |
| 2344 m_tFirstScanning = t; |
| 2345 Simulator::Schedule(m_tFirstScanning,&NistLteUePhy::StartSlssScanning, this); |
| 2346 } |
| 2347 |
| 2348 Time NistLteUePhy::GetFirstScanningTime(){ |
| 2349 NS_LOG_FUNCTION (this); |
| 2350 return m_tFirstScanning; |
| 2351 } |
| 2352 |
| 2353 void NistLteUePhy::ReceiveSlss(uint16_t slssid, Ptr<SpectrumValue> p) |
| 2354 { |
| 2355 NS_LOG_FUNCTION(this << slssid); |
| 2356 |
| 2357 if (m_ueSlssScanningInProgress || m_ueSlssMeasurementInProgress) |
| 2358 { |
| 2359 NS_LOG_LOGIC (this << " The UE is currently performing the SyncRef scannin
g or S-RSRP measurement"); |
| 2360 |
| 2361 //Measure instantaneous S-RSRP... |
| 2362 double sum = 0.0; |
| 2363 uint16_t nRB = 0; |
| 2364 Values::const_iterator itPi; |
| 2365 for (itPi = p->ConstValuesBegin(); itPi != p->ConstValuesEnd(); itPi++) |
| 2366 { |
| 2367 if((*itPi)) |
| 2368 { |
| 2369 double powerTxW = ((*itPi) * 180000.0) / 12.0; // convert PSD [W/H
z] to linear power [W] |
| 2370 sum += powerTxW; |
| 2371 nRB++; |
| 2372 } |
| 2373 } |
| 2374 double s_rsrp_W = (sum / (double) nRB); |
| 2375 double s_rsrp_dBm = 10 * log10(1000 * (s_rsrp_W)); |
| 2376 uint16_t offset = Simulator::Now().GetMilliSeconds() % 40; |
| 2377 |
| 2378 NS_LOG_INFO(this << " UE RNTI " << m_rnti << " received SLSS from SyncRef
with SLSSID " << slssid |
| 2379 << " offset "<< offset << " with S-RSRP " << s_rsrp_dBm << " d
Bm" ); |
| 2380 |
| 2381 //If it is not detectable, ignore |
| 2382 if (s_rsrp_dBm < m_minSrsrp) |
| 2383 { |
| 2384 NS_LOG_LOGIC (this << " The S-RSRP is below the minimum required... Ig
noring"); |
| 2385 return; |
| 2386 } |
| 2387 |
| 2388 //Store the SLSS and S-RSRP |
| 2389 //Note that a SyncRef is identified by SLSSID and reception offset. |
| 2390 //SLSSs coming from different UEs, but having the same SyncRef info (same
SLSSID and reception offset) |
| 2391 //are considered as different S-RSRP samples of the same SyncRef |
| 2392 std::map <std::pair<uint16_t,uint16_t>, NistUeSlssMeasurementsElement>::it
erator |
| 2393 itMeasMap = m_ueSlssMeasurementsMap.find(std::pair<uint16_t,uint16_t>(slss
id,offset)); |
| 2394 |
| 2395 if (itMeasMap == m_ueSlssMeasurementsMap.end()) //First entry |
| 2396 { |
| 2397 NistUeSlssMeasurementsElement newEl; |
| 2398 newEl.srsrpSum = s_rsrp_W; |
| 2399 newEl.srsrpNum = 1; |
| 2400 |
| 2401 if(m_ueSlssScanningInProgress) |
| 2402 { |
| 2403 NS_LOG_LOGIC (this << " SyncRef scan in progress, first detected e
ntry"); |
| 2404 m_ueSlssDetectionMap.insert(std::pair< std::pair<uint16_t,uint16_t
>, |
| 2405 NistUeSlssMeasurementsElement>(std::pa
ir<uint16_t,uint16_t>(slssid,offset), newEl)); |
| 2406 } |
| 2407 else if(m_ueSlssMeasurementInProgress) |
| 2408 { |
| 2409 NS_LOG_LOGIC (this << " S-RSRP measurement in progress, first meas
urement entry"); |
| 2410 //Insert new measurement only if it was already detected |
| 2411 std::map <std::pair<uint16_t,uint16_t>, NistUeSlssMeasurementsElem
ent>::iterator |
| 2412 itDetectionMap = m_ueSlssDetectionMap.find(std::pair<uint16_t,uint
16_t>(slssid,offset)); |
| 2413 if (itDetectionMap != m_ueSlssDetectionMap.end()) |
| 2414 { |
| 2415 NS_LOG_LOGIC (this << " SyncRef already detected, storing meas
urement"); |
| 2416 m_ueSlssMeasurementsMap.insert(std::pair< std::pair<uint16_t,u
int16_t>, |
| 2417 NistUeSlssMeasurementsElement>(
std::pair<uint16_t,uint16_t>(slssid,offset), newEl)); |
| 2418 } |
| 2419 else |
| 2420 { |
| 2421 NS_LOG_LOGIC (this << " SyncRef was not detected during SyncRe
f search/scanning... Ignoring"); |
| 2422 } |
| 2423 } |
| 2424 } |
| 2425 else |
| 2426 { |
| 2427 NS_LOG_LOGIC (this << " Measurement entry found... Adding values"); |
| 2428 |
| 2429 (*itMeasMap).second.srsrpSum += s_rsrp_W; |
| 2430 (*itMeasMap).second.srsrpNum++; |
| 2431 } |
| 2432 } |
| 2433 else |
| 2434 { |
| 2435 NS_LOG_LOGIC (this << " The UE is not currently performing SyncRef scannin
g or S-RSRP measurement... Ignoring"); |
| 2436 } |
| 2437 } |
| 2438 |
| 2439 |
| 2440 |
| 2441 void NistLteUePhy::SetInitialSubFrameIndication(bool rdm) |
| 2442 { |
| 2443 NS_LOG_FUNCTION (this << rdm); |
| 2444 |
| 2445 if (rdm) |
| 2446 { |
| 2447 NS_LOG_LOGIC (this << " Random initial frame/subframe indication"); |
| 2448 |
| 2449 Ptr<UniformRandomVariable> frameRdm = CreateObject<UniformRandomVariable>
(); |
| 2450 Ptr<UniformRandomVariable> subframeRdm = CreateObject<UniformRandomVariabl
e> (); |
| 2451 frameRdm->SetAttribute("Min", DoubleValue(1)); |
| 2452 frameRdm->SetAttribute("Max", DoubleValue(1024)); |
| 2453 subframeRdm->SetAttribute("Min", DoubleValue(1)); |
| 2454 subframeRdm->SetAttribute("Max", DoubleValue(10)); |
| 2455 Simulator::ScheduleNow(&NistLteUePhy::SubframeIndication, this, |
| 2456 frameRdm->GetInteger(), subframeRdm->GetInteger()); |
| 2457 } |
| 2458 else |
| 2459 { |
| 2460 NS_LOG_LOGIC (this << " Standard initial frame/subframe indication (frameN
o=1, subframeNo=1"); |
| 2461 Simulator::ScheduleNow(&NistLteUePhy::SubframeIndication, this, 1, 1); |
| 2462 } |
| 2463 } |
| 2464 |
| 2465 void NistLteUePhy::SetUeSlssInterScanningPeriodMax(Time t) |
| 2466 { |
| 2467 NS_LOG_FUNCTION (this); |
| 2468 m_nextScanRdm->SetAttribute("Max",DoubleValue(t.GetMilliSeconds()) ); |
| 2469 } |
| 2470 |
| 2471 void NistLteUePhy::SetUeSlssInterScanningPeriodMin(Time t) |
| 2472 { |
| 2473 NS_LOG_FUNCTION (this); |
| 2474 m_nextScanRdm->SetAttribute("Min",DoubleValue(t.GetMilliSeconds()) ); |
| 2475 } |
| 2476 |
| 2477 void NistLteUePhy::StartSlssScanning() |
| 2478 { |
| 2479 NS_LOG_FUNCTION (this); |
| 2480 m_ueSlssScanningInProgress = true; |
| 2481 m_detectedMibSl.clear(); |
| 2482 Simulator::Schedule(m_ueSlssScanningPeriod, &NistLteUePhy::EndSlssScanning, th
is); |
| 2483 |
| 2484 } |
| 2485 |
| 2486 void NistLteUePhy::EndSlssScanning() |
| 2487 { |
| 2488 NS_LOG_FUNCTION (this); |
| 2489 m_ueSlssScanningInProgress = false; |
| 2490 |
| 2491 //Filter to keep only the SyncRefs with received MIB-SL |
| 2492 std::map <std::pair<uint16_t,uint16_t>, NistUeSlssMeasurementsElement>::iterat
or itDetectionMap; |
| 2493 for (itDetectionMap = m_ueSlssDetectionMap.begin(); itDetectionMap != m_ueSlss
DetectionMap.end();itDetectionMap++ ) |
| 2494 { |
| 2495 NS_LOG_LOGIC(this <<" UE RNTI "<<m_rnti<<" detected SyncRef with SLSSID "<
<itDetectionMap->first.first <<" offset " << itDetectionMap->first.second <<" S-
RSRP "<< itDetectionMap->second.srsrpSum / itDetectionMap->second.srsrpNum); |
| 2496 std::map <std::pair<uint16_t,uint16_t>, NistLteRrcSap::MasterInformationBl
ockSL>::iterator itMap = |
| 2497 m_detectedMibSl.find (std::pair<uint16_t,uint16_t>(itDetectionMap->fir
st.first, itDetectionMap->first.second)); |
| 2498 //If the MIB-SL wasn't received, erase it from the detection map |
| 2499 if (itMap == m_detectedMibSl.end ()) |
| 2500 { |
| 2501 NS_LOG_LOGIC(this << " MIB-SL was not found... Removing from detection
list"); |
| 2502 m_ueSlssDetectionMap.erase(itDetectionMap); |
| 2503 } |
| 2504 } |
| 2505 |
| 2506 //Select the 6 SyncRefs with higher S-RSRP. Remove the others form the detecte
d list |
| 2507 std::map <double, std::pair<uint16_t,uint16_t> > tmp; |
| 2508 for (itDetectionMap = m_ueSlssDetectionMap.begin(); itDetectionMap != m_ueSlss
DetectionMap.end();itDetectionMap++ ) |
| 2509 { |
| 2510 tmp.insert(std::pair<double, std::pair<uint16_t,uint16_t> >(itDetectionMap
->second.srsrpSum / itDetectionMap->second.srsrpNum, itDetectionMap->first)); |
| 2511 } |
| 2512 while (tmp.size() > 6) |
| 2513 { |
| 2514 NS_LOG_LOGIC(this << " The UE detected more than 6 SyncRefs... Removing lo
west S-RSRP SyncRef: SLSSID"<< tmp.begin()->second.first <<"ofset "<<tmp.begin()
->second.second<< "S-RSRP " <<tmp.begin()->first); |
| 2515 tmp.erase(tmp.begin()->first); |
| 2516 } |
| 2517 std::map <std::pair<uint16_t,uint16_t>, NistUeSlssMeasurementsElement> ret; |
| 2518 std::map <double, std::pair<uint16_t,uint16_t> >::iterator itTmp; |
| 2519 for (itTmp = tmp.begin(); itTmp != tmp.end();itTmp++ ) |
| 2520 { |
| 2521 std::map<std::pair<uint16_t,uint16_t>, NistUeSlssMeasurementsElement>::ite
rator |
| 2522 itDetectionMapTwo = m_ueSlssDetectionMap.find(itTmp->second); |
| 2523 if (itDetectionMapTwo != m_ueSlssDetectionMap.end()) |
| 2524 { |
| 2525 ret.insert(std::pair<std::pair<uint16_t,uint16_t>,NistUeSlssMeasuremen
tsElement>(itDetectionMapTwo->first, itDetectionMapTwo->second)); |
| 2526 } |
| 2527 } |
| 2528 |
| 2529 m_ueSlssDetectionMap = ret; // It contains now only the 6 SyncRefs with higher
S-RSRP |
| 2530 m_ueSlssMeasurementsMap= ret;// It contains now only the 6 SyncRefs with highe
r S-RSRP (we use the S-RSRP measurements during scanning as first measurements) |
| 2531 |
| 2532 uint32_t nDetectedSyncRef = m_ueSlssDetectionMap.size(); |
| 2533 |
| 2534 if (nDetectedSyncRef > 0) |
| 2535 { |
| 2536 NS_LOG_LOGIC(this << " At least one SyncRef detected, creating measurement
schedule and starting measurement sub-process"); |
| 2537 //Create measurement schedule |
| 2538 std::map <std::pair<uint16_t,uint16_t>, NistUeSlssMeasurementsElement>::it
erator itMeasMap; |
| 2539 for (itMeasMap = m_ueSlssMeasurementsMap.begin(); itMeasMap != m_ueSlssMea
surementsMap.end();itMeasMap++ ) |
| 2540 { |
| 2541 uint16_t currOffset = Simulator::Now().GetMilliSeconds()%40; |
| 2542 int64_t t; |
| 2543 if ( currOffset < itMeasMap->first.second) |
| 2544 { |
| 2545 t = Simulator::Now().GetMilliSeconds() + (itMeasMap->first.second
- currOffset); |
| 2546 } |
| 2547 else |
| 2548 { |
| 2549 t = Simulator::Now().GetMilliSeconds() + (40 - currOffset + itMeas
Map->first.second); |
| 2550 } |
| 2551 uint16_t count = 1; |
| 2552 while (t < (Simulator::Now().GetMilliSeconds()+ m_ueSlssMeasurementPer
iod.GetMilliSeconds() - 40)) |
| 2553 { |
| 2554 NS_LOG_INFO(this << " UE RNTI "<<m_rnti<<" will measure S-RSRP of
SyncRef SLSSID "<< itMeasMap->first.first<<" offset "<< itMeasMap->first.second<
<" at t:"<< t<<" ms"); |
| 2555 m_ueSlssMeasurementsSched.insert(std::pair<int64_t, std::pair<uint
16_t,uint16_t> >(t,itMeasMap->first)); |
| 2556 count ++; |
| 2557 if (count > m_nSamplesSrsrpMeas){ |
| 2558 break; |
| 2559 } |
| 2560 t = t + 40; |
| 2561 } |
| 2562 } |
| 2563 //Start measurement process of the 6 SyncRefs with higher S-RSRP |
| 2564 StartSlssMeasurements(0,0); |
| 2565 } |
| 2566 else |
| 2567 { |
| 2568 NS_LOG_LOGIC(this << " No SyncRef detected... Ending SyncRef selection pro
cess"); |
| 2569 ScheduleNextSyncRefReselection(0); //The process ended after scanning |
| 2570 } |
| 2571 } |
| 2572 |
| 2573 void NistLteUePhy::StartSlssMeasurements(uint64_t slssid, uint16_t offset) |
| 2574 { |
| 2575 NS_LOG_FUNCTION (this); |
| 2576 |
| 2577 m_ueSlssMeasurementInProgress = true; |
| 2578 Time t; |
| 2579 if (slssid == 0) //Measurement |
| 2580 { |
| 2581 t = m_ueSlssMeasurementPeriod; |
| 2582 NS_LOG_LOGIC(this << " Starting S-RSRP measurement corresponding to the me
asurement sub-process... Report happening in "<<t<<" ms"); |
| 2583 } |
| 2584 else{ //Evaluation |
| 2585 t = m_ueSlssEvaluationPeriod; |
| 2586 NS_LOG_LOGIC(this << " Starting S-RSRP measurement corresponding to the ev
aluation sub-process... Report happening in "<<t<<" ms"); |
| 2587 } |
| 2588 Simulator::Schedule(t,&NistLteUePhy::ReportSlssMeasurements, this, slssid, off
set); |
| 2589 } |
| 2590 |
| 2591 |
| 2592 void NistLteUePhy::ReportSlssMeasurements(uint64_t slssid, uint16_t offset) |
| 2593 { |
| 2594 NS_LOG_FUNCTION (this); |
| 2595 |
| 2596 NistLteUeCphySapUser::NistUeSlssMeasurementsParameters ret; |
| 2597 std::map<std::pair<uint16_t,uint16_t>, NistUeSlssMeasurementsElement>::iterato
r it; |
| 2598 |
| 2599 if(slssid == 0) //Report all |
| 2600 { |
| 2601 NS_LOG_LOGIC(this << " End of S-RSRP measurement corresponding to the meas
urement sub-process... Reporting L1 filtered S-RSRP values of detected SyncRefs"
); |
| 2602 |
| 2603 for (it = m_ueSlssMeasurementsMap.begin(); it != m_ueSlssMeasurementsMap.e
nd(); it++) |
| 2604 { |
| 2605 //L1 filtering: linear average |
| 2606 double avg_s_rsrp_W = (*it).second.srsrpSum/ (double) (*it).second.srs
rpNum; |
| 2607 //The stored values are in W, the report to the RRC should be in dBm |
| 2608 double avg_s_rsrp_dBm = 10 * log10(1000 * (avg_s_rsrp_W)); |
| 2609 |
| 2610 NS_LOG_INFO(this <<" UE RNTI "<<m_rnti<< " report SyncRef with SLSSID
" |
| 2611 << (*it).first.first << " offset "<< (*it).first.second <<
" L1 filtered S-RSRP " << avg_s_rsrp_dBm |
| 2612 << " from " << (double) (*it).second.srsrpNum <<" samples"
); |
| 2613 |
| 2614 NistLteUeCphySapUser::NistUeSlssMeasurementReportElement newEl; |
| 2615 newEl.m_slssid = (*it).first.first; |
| 2616 newEl.m_srsrp = avg_s_rsrp_dBm; |
| 2617 newEl.m_offset = (*it).first.second; |
| 2618 ret.m_ueSlssMeasurementsList.push_back(newEl); |
| 2619 } |
| 2620 |
| 2621 } |
| 2622 else // Report only of the selected SyncRef |
| 2623 { |
| 2624 NS_LOG_LOGIC(this << " End of S-RSRP measurement corresponding to the eval
uation sub-process"); |
| 2625 NS_LOG_LOGIC(this << " Reporting L1 filtered S-RSRP values of the SyncRef
SLSSID " << slssid <<" offset "<<offset); |
| 2626 |
| 2627 it = m_ueSlssMeasurementsMap.find (std::pair<uint16_t,uint16_t>(slssid,off
set)); |
| 2628 if (it != m_ueSlssMeasurementsMap.end ()) |
| 2629 { |
| 2630 //L1 filtering: linear average |
| 2631 double avg_s_rsrp_W = (*it).second.srsrpSum/ (double) (*it).second.srs
rpNum; |
| 2632 //The stored values are in W, the report to the RRC should be in dBm |
| 2633 double avg_s_rsrp_dBm = 10 * log10(1000 * (avg_s_rsrp_W)); |
| 2634 |
| 2635 NS_LOG_INFO(this << Simulator::Now().GetMilliSeconds()<< " UE RNTI "<<
m_rnti<< " Report SyncRef with SLSSID " |
| 2636 << (*it).first.first << " offset "<< (*it).first.second <<
" L1 filtered S-RSRP " << avg_s_rsrp_dBm |
| 2637 << " from " << (double) (*it).second.srsrpNum <<" samples"
); |
| 2638 |
| 2639 NistLteUeCphySapUser::NistUeSlssMeasurementReportElement newEl; |
| 2640 newEl.m_slssid = (*it).first.first; |
| 2641 newEl.m_srsrp = avg_s_rsrp_dBm; |
| 2642 newEl.m_offset = (*it).first.second; |
| 2643 ret.m_ueSlssMeasurementsList.push_back(newEl); |
| 2644 } |
| 2645 } |
| 2646 |
| 2647 //Report to RRC |
| 2648 m_ueCphySapUser->ReportSlssMeasurements(ret,slssid,offset); |
| 2649 |
| 2650 //Cleaning for next process |
| 2651 m_ueSlssMeasurementsMap.clear(); |
| 2652 m_ueSlssMeasurementsSched.clear(); |
| 2653 m_ueSlssMeasurementInProgress = false; |
| 2654 |
| 2655 //Schedule the start of the measurement period for evaluation of selected Sync
Ref if appropriated |
| 2656 m_currNMeasPeriods ++; |
| 2657 if (m_currNMeasPeriods == 1 && m_resyncRequested) |
| 2658 { |
| 2659 NS_LOG_LOGIC(this << " The measurement sub-process ended and RRC selected
a SyncRef for (re)synchronization"); |
| 2660 |
| 2661 //Schedule the measurement for evaluation of the selected SyncRef for init
iation/cease of SlSS transmission |
| 2662 NS_LOG_INFO(this <<" UE RNTI "<<m_rnti<< " will start evaluation of select
ed SyncRef with SLSSID " <<m_resyncParams.syncRefMib.slssid <<" offset" << m_res
yncParams.syncRefMib.rxOffset ); |
| 2663 Simulator::ScheduleNow(&NistLteUePhy::StartSlssMeasurements, this, m_resyn
cParams.syncRefMib.slssid, m_resyncParams.syncRefMib.rxOffset); |
| 2664 |
| 2665 //Create measurement schedule for the evaluation |
| 2666 uint16_t currOffset = Simulator::Now().GetMilliSeconds()%40; |
| 2667 int64_t t; |
| 2668 if ( currOffset < m_resyncParams.syncRefMib.rxOffset) |
| 2669 { |
| 2670 t = Simulator::Now().GetMilliSeconds() + (m_resyncParams.syncRefMib.rx
Offset - currOffset); |
| 2671 } |
| 2672 else |
| 2673 { |
| 2674 t = Simulator::Now().GetMilliSeconds() + (40 - currOffset + m_resyncPa
rams.syncRefMib.rxOffset); |
| 2675 } |
| 2676 uint16_t count = 1; |
| 2677 while (t < (Simulator::Now().GetMilliSeconds()+ m_ueSlssMeasurementPeriod.
GetMilliSeconds() - 40)) |
| 2678 { |
| 2679 NS_LOG_INFO(this <<" UE RNTI "<<m_rnti<< " will measure SyncRef with S
LSSID"<< m_resyncParams.syncRefMib.slssid<<" offset "<< m_resyncParams.syncRefM
ib.rxOffset<<" at t:"<< t<<" ms"); |
| 2680 m_ueSlssMeasurementsSched.insert(std::pair<int64_t, std::pair<uint16_t
,uint16_t> >(t, std::pair<uint16_t,uint16_t>(m_resyncParams.syncRefMib.slssid ,
m_resyncParams.syncRefMib.rxOffset))); |
| 2681 count ++; |
| 2682 if (count > m_nSamplesSrsrpMeas) |
| 2683 { |
| 2684 break; |
| 2685 } |
| 2686 t = t + 40; |
| 2687 } |
| 2688 } |
| 2689 else |
| 2690 { //m_currNMeasPeriods == 2 (after evaluation) || !m_resyncRequested (after
measurement without selecting a SyncRef) |
| 2691 |
| 2692 //End of the selection+evaluation process, reinitialize variables for next
process and schedule it |
| 2693 m_ueSlssDetectionMap.clear(); |
| 2694 |
| 2695 if (m_currNMeasPeriods ==1) |
| 2696 { |
| 2697 NS_LOG_LOGIC(this << " The measurement sub-process ended and RRC did n
ot selected a SyncRef... Ending SyncRef selection process"); |
| 2698 ScheduleNextSyncRefReselection(1); //The process ended after measureme
nt |
| 2699 } |
| 2700 if (m_currNMeasPeriods == 2) |
| 2701 { |
| 2702 NS_LOG_LOGIC(this << " The evaluation sub-process ended... Ending Sync
Ref selection process"); |
| 2703 ScheduleNextSyncRefReselection(2); // The process ended after evaluati
on |
| 2704 } |
| 2705 m_currNMeasPeriods = 0; |
| 2706 } |
| 2707 } |
| 2708 |
| 2709 void NistLteUePhy::ScheduleNextSyncRefReselection(uint16_t endOfPrevious ){ |
| 2710 NS_LOG_FUNCTION (this); |
| 2711 |
| 2712 int32_t t_nextProcess = m_nextScanRdm->GetInteger(); |
| 2713 |
| 2714 switch(endOfPrevious) |
| 2715 { |
| 2716 case 0: |
| 2717 NS_LOG_LOGIC(this << " SyncRef selection process ended after scanning sub-
process"); |
| 2718 t_nextProcess = t_nextProcess - m_ueSlssScanningPeriod.GetMilliSeconds(); |
| 2719 break; |
| 2720 case 1: |
| 2721 NS_LOG_LOGIC(this << " SyncRef selection process ended after measurement s
ub-process"); |
| 2722 t_nextProcess = t_nextProcess - (m_ueSlssScanningPeriod.GetMilliSeconds()
+ m_ueSlssMeasurementPeriod.GetMilliSeconds()); |
| 2723 break; |
| 2724 case 2: |
| 2725 NS_LOG_LOGIC(this << " SyncRef selection process ended after evaluation su
b-process"); |
| 2726 t_nextProcess = t_nextProcess - (m_ueSlssScanningPeriod.GetMilliSeconds()
+ m_ueSlssMeasurementPeriod.GetMilliSeconds()+ m_ueSlssEvaluationPeriod.GetMilli
Seconds()); |
| 2727 break; |
| 2728 } |
| 2729 |
| 2730 //The standard requires at least one SyncRef selection process within 20s |
| 2731 if (t_nextProcess > 20000) |
| 2732 { |
| 2733 NS_LOG_LOGIC(this << " Attempted to schedule the next SyncRef selection pr
ocess for a period larger than 20 s... Scheduling it for 20 s"); |
| 2734 t_nextProcess = 20000; |
| 2735 } |
| 2736 |
| 2737 //Do not travel to the past |
| 2738 if (t_nextProcess <= 0) |
| 2739 { |
| 2740 NS_LOG_LOGIC(this << " Attempted to schedule the next SyncRef selection pr
ocess for the past... Scheduling it for next subframe"); |
| 2741 t_nextProcess = 1; |
| 2742 } |
| 2743 NS_LOG_INFO(this <<" UE RNTI "<<m_rnti<< " will start the next SyncRef selecti
on process in t: "<<t_nextProcess<<" ms"); |
| 2744 Simulator::Schedule(MilliSeconds(t_nextProcess), &NistLteUePhy::StartSlssScann
ing,this); |
| 2745 } |
| 2746 |
| 2747 bool |
| 2748 NistLteUePhy::ChangeOfTiming(uint32_t frameNo, uint32_t subframeNo) |
| 2749 { |
| 2750 NS_LOG_FUNCTION (this); |
| 2751 |
| 2752 if (m_slTxPoolInfo.m_pool) |
| 2753 { |
| 2754 NS_LOG_LOGIC(this << " The UE is currently transmitting sidelink communica
tion"); |
| 2755 |
| 2756 //Is it the start of a new period? |
| 2757 if (((frameNo == m_slTxPoolInfo.m_nextScPeriod.frameNo && subframeNo |
| 2758 == m_slTxPoolInfo.m_nextScPeriod.subframeNo) |
| 2759 || m_slTxPoolInfo.m_nextScPeriod.frameNo == 0)) |
| 2760 { |
| 2761 NS_LOG_LOGIC(this << " The current subframe corresponds to the start o
f a new sidelink communication period... Applying the change of timing"); |
| 2762 |
| 2763 //Apply the change of Timing |
| 2764 frameNo = m_resyncParams.newFrameNo; |
| 2765 subframeNo = m_resyncParams.newSubframeNo; |
| 2766 m_resyncRequested = false; |
| 2767 NS_LOG_INFO(this <<" UE RNTI " << m_rnti |
| 2768 << " has a TxPool and changed the Subframe Indication from
:" |
| 2769 << " frame " << m_slTxPoolInfo.m_nextScPeriod.frameNo |
| 2770 << " subframe " << m_slTxPoolInfo.m_nextScPeriod.subframeN
o |
| 2771 << " to: frame " << frameNo << " subframe " << subframeNo)
; |
| 2772 |
| 2773 //Notify RRC about the successful change of SyncRef and timing |
| 2774 m_ueCphySapUser->ReportChangeOfSyncRef(m_resyncParams.syncRefMib,frame
No, subframeNo); |
| 2775 |
| 2776 //Notify MAC about the successful change of SyncRef and timing. Some a
djustments first |
| 2777 |
| 2778 //Adjusting MAC subframe indication: |
| 2779 //There is a delay between the MAC scheduling and the PHY: the MAC is
4 subframes ahead |
| 2780 uint32_t macSubframeNo = subframeNo; |
| 2781 uint32_t macFrameNo = frameNo; |
| 2782 macSubframeNo += 4; |
| 2783 if (macSubframeNo > 10) |
| 2784 { |
| 2785 ++macFrameNo; |
| 2786 if (macFrameNo > 1024) |
| 2787 macFrameNo = 1; |
| 2788 macSubframeNo -= 10; |
| 2789 } |
| 2790 //Adjusting the sidelink communication parameters |
| 2791 //We calculate the next period using the frameNo/subframeNo of the MAC
. |
| 2792 //Thus we avoid miss alignment due to the delay |
| 2793 m_slTxPoolInfo.m_currentScPeriod |
| 2794 = m_slTxPoolInfo.m_pool->GetCurrentScPeriod(macFrameNo,macSubframeNo); |
| 2795 m_slTxPoolInfo.m_nextScPeriod |
| 2796 = m_slTxPoolInfo.m_pool->GetNextScPeriod( |
| 2797 m_slTxPoolInfo.m_currentScPeriod.frameNo, |
| 2798 m_slTxPoolInfo.m_currentScPeriod.subframeNo); |
| 2799 //adjust because scheduler starts with frame/subframe = 1 |
| 2800 m_slTxPoolInfo.m_nextScPeriod.frameNo++; |
| 2801 m_slTxPoolInfo.m_nextScPeriod.subframeNo++; |
| 2802 NS_LOG_INFO(this << " UE RNTI " << m_rnti << " Next sidelink communica
tion Tx period at frame/subframe: " |
| 2803 << m_slTxPoolInfo.m_nextScPeriod.frameNo << "/" |
| 2804 << m_slTxPoolInfo.m_nextScPeriod.subframeNo); |
| 2805 //clear any previous grant |
| 2806 m_slTxPoolInfo.m_currentGrants.clear(); |
| 2807 |
| 2808 //Don't try to send sidelink communication until the start of the next
period |
| 2809 m_waitingNextScPeriod = true; |
| 2810 |
| 2811 //Finally, notify the MAC (Note the parameters are the PHY frameNo and
subframeNo) |
| 2812 m_uePhySapUser->NotifyChangeOfTiming(frameNo, subframeNo); |
| 2813 |
| 2814 //Store the new values |
| 2815 m_currFrameNo = frameNo; |
| 2816 m_currSubframeNo = subframeNo; |
| 2817 |
| 2818 //Notify the SpectrumPhy about the change of SLSSID |
| 2819 m_uplinkSpectrumPhy->SetSlssid(m_resyncParams.syncRefMib.slssid); |
| 2820 m_sidelinkSpectrumPhy->SetSlssid(m_resyncParams.syncRefMib.slssid); |
| 2821 |
| 2822 return true; |
| 2823 } |
| 2824 else |
| 2825 {//Delay the change of Timing |
| 2826 NS_LOG_LOGIC(this << " The current subframe does not correspond to the
start of a new sidelink communication period... Delaying the change of timing")
; |
| 2827 |
| 2828 //Adjusting subframe indication to still match the SyncRef when the ch
ange of timing will be performed |
| 2829 ++m_resyncParams.newSubframeNo; |
| 2830 if (m_resyncParams.newSubframeNo > 10) |
| 2831 { |
| 2832 ++m_resyncParams.newFrameNo; |
| 2833 if (m_resyncParams.newFrameNo > 1024) |
| 2834 { |
| 2835 m_resyncParams.newFrameNo = 1; |
| 2836 } |
| 2837 m_resyncParams.newSubframeNo = 1; |
| 2838 } |
| 2839 return false; |
| 2840 } |
| 2841 } |
| 2842 else |
| 2843 { |
| 2844 //No pool, apply directly the change of Timing |
| 2845 NS_LOG_LOGIC(this << " The UE is not currently transmitting sidelink commu
nication... Applying the change of timing"); |
| 2846 |
| 2847 frameNo = m_resyncParams.newFrameNo; |
| 2848 subframeNo = m_resyncParams.newSubframeNo; |
| 2849 m_resyncRequested = false; |
| 2850 NS_LOG_INFO(this << " UE RNTI " << m_rnti << "did not have a Tx pool and" |
| 2851 << " changed the Subframe Indication from: " |
| 2852 << " frame "<<m_currFrameNo<< "subframe "<<m_currSubframeNo |
| 2853 << " to: frame "<< frameNo << " subframe " << subframeNo); |
| 2854 |
| 2855 //Notify RRC about the successful change of SyncRef and timing |
| 2856 m_ueCphySapUser->ReportChangeOfSyncRef(m_resyncParams.syncRefMib, frameNo,
subframeNo); |
| 2857 |
| 2858 m_currFrameNo = frameNo; |
| 2859 m_currSubframeNo = subframeNo; |
| 2860 |
| 2861 //Notify the SpectrumPhy about the change of SLSSID |
| 2862 m_uplinkSpectrumPhy->SetSlssid(m_resyncParams.syncRefMib.slssid); |
| 2863 m_sidelinkSpectrumPhy->SetSlssid(m_resyncParams.syncRefMib.slssid); |
| 2864 |
| 2865 return true; |
| 2866 } |
| 2867 } |
| 2868 |
| 2869 void NistLteUePhy::DoSetSlssId(uint64_t slssid) |
| 2870 { |
| 2871 NS_LOG_FUNCTION (this); |
| 2872 m_uplinkSpectrumPhy->SetSlssid(slssid); |
| 2873 m_sidelinkSpectrumPhy->SetSlssid(slssid); |
| 2874 } |
| 2875 |
| 2876 void NistLteUePhy::DoSendSlss(NistLteRrcSap::MasterInformationBlockSL mibSl) |
| 2877 { |
| 2878 NS_LOG_FUNCTION (this); |
| 2879 Ptr<MibSLNistLteControlMessage> msg = Create<MibSLNistLteControlMessage> (); |
| 2880 msg->SetMibSL(mibSl); |
| 2881 NS_LOG_LOGIC(this << " Adding a MIB-SL to the queue of control messages to be
send "); |
| 2882 DoSendNistLteControlMessage(msg); |
| 2883 //Notify the SpectrumPhy about the SLSSID used for transmitting |
| 2884 //Do it here to have the correct SLSSID in the SpectrumPhy and cover the case
in which |
| 2885 //the UE reselects a random SLSSID without change of timing, i.e., out-of-cove
rage and without SyncRef |
| 2886 m_uplinkSpectrumPhy->SetSlssid(mibSl.slssid); |
| 2887 m_sidelinkSpectrumPhy->SetSlssid(mibSl.slssid); |
| 2888 |
| 2889 } |
| 2890 |
| 2891 void NistLteUePhy::DoSynchronizeToSyncRef(NistLteRrcSap::MasterInformationBlockS
L mibSl) |
| 2892 { |
| 2893 NS_LOG_FUNCTION (this); |
| 2894 |
| 2895 //Estimate the current timing (frame/subframe indication) of the SyncRef |
| 2896 //using the information in the MIB-SL and the creation and reception timestamp
s |
| 2897 uint32_t mibCreationAge = Simulator::Now().GetMilliSeconds() - mibSl.creationT
imestamp.GetMilliSeconds(); |
| 2898 uint32_t mibRxAge = Simulator::Now().GetMilliSeconds() - mibSl.rxTimestamp.Get
MilliSeconds(); |
| 2899 |
| 2900 uint32_t frameOffsetSyncRef = 0; |
| 2901 if (mibCreationAge >= 10) |
| 2902 { |
| 2903 frameOffsetSyncRef = uint32_t(mibCreationAge / 10); |
| 2904 } |
| 2905 uint32_t frameSyncRef = mibSl.directFrameNo + frameOffsetSyncRef; |
| 2906 if (frameSyncRef > 1024) |
| 2907 { |
| 2908 frameSyncRef = frameSyncRef - 1024; |
| 2909 } |
| 2910 uint32_t subframeOffsetSyncRef = mibCreationAge % 10; |
| 2911 uint32_t subframeSyncRef = mibSl.directSubframeNo + subframeOffsetSyncRef; |
| 2912 if (subframeSyncRef > 10) |
| 2913 { |
| 2914 subframeSyncRef = subframeSyncRef % 10; |
| 2915 frameSyncRef++; |
| 2916 if (frameSyncRef > 1024) |
| 2917 { |
| 2918 frameSyncRef = 1; |
| 2919 } |
| 2920 } |
| 2921 NS_LOG_INFO(this << " Synchronizing to SyncRef SLSSSID " << mibSl.slssid <<" o
ffset " << mibSl.rxOffset); |
| 2922 NS_LOG_INFO(this << " Its last mib was received " << mibRxAge << " ms ago, and
it was created by the SyncRef "<<mibCreationAge<<" ms ago"); |
| 2923 NS_LOG_INFO(this << " The subframe indication in the MIB-SL, i.e., when create
d (frame/subframe):" << mibSl.directFrameNo <<"/"<< mibSl.directSubframeNo); |
| 2924 NS_LOG_INFO(this << " The estimated CURRENT subframe indication of the SyncRef
(frame/subframe): "<< frameSyncRef << "/"<< subframeSyncRef); |
| 2925 NS_LOG_INFO(this << " The CURRENT subframe indication of this UE (frame/subfra
me): "<< m_currFrameNo << "/"<< m_currSubframeNo); |
| 2926 |
| 2927 //Request the synchronization (change of timing) for the next subframe |
| 2928 m_resyncRequested = true; |
| 2929 ++subframeSyncRef; //Update frame/subframe number to be used (in the next subf
rame) |
| 2930 if (subframeSyncRef > 10) |
| 2931 { |
| 2932 ++frameSyncRef; |
| 2933 if (frameSyncRef > 1024) |
| 2934 { |
| 2935 frameSyncRef = 1; |
| 2936 } |
| 2937 subframeSyncRef = 1; |
| 2938 } |
| 2939 m_resyncParams.newFrameNo = frameSyncRef; |
| 2940 m_resyncParams.newSubframeNo = subframeSyncRef; |
| 2941 m_resyncParams.syncRefMib = mibSl; |
| 2942 } |
| 2943 |
| 2944 } // namespace ns3 |
OLD | NEW |