A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
simple-ofdm-wimax-phy.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007,2008, 2009 INRIA, UDcast
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: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
19  * <amine.ismail@udcast.com>
20  */
21 
22 #include "ns3/simulator.h"
23 #include "ns3/packet.h"
24 #include "ns3/node.h"
25 #include "ns3/uinteger.h"
26 #include "ns3/double.h"
27 #include "ns3/string.h"
28 #include "wimax-net-device.h"
29 #include "simple-ofdm-wimax-phy.h"
30 #include "wimax-channel.h"
31 #include "ns3/packet-burst.h"
32 #include "wimax-mac-header.h"
33 #include "simple-ofdm-wimax-channel.h"
34 #include "ns3/trace-source-accessor.h"
35 #include <string>
36 #include <cmath>
37 
38 NS_LOG_COMPONENT_DEFINE ("SimpleOfdmWimaxPhy");
39 namespace ns3 {
40 
41 NS_OBJECT_ENSURE_REGISTERED (SimpleOfdmWimaxPhy);
42 
43 TypeId SimpleOfdmWimaxPhy::GetTypeId (void)
44 {
45  static TypeId
46  tid =
47  TypeId ("ns3::SimpleOfdmWimaxPhy").SetParent<WimaxPhy> ()
48 
49  .AddAttribute ("NoiseFigure",
50  "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver.",
51  DoubleValue (5),
53  MakeDoubleChecker<double> ())
54 
55  .AddAttribute ("TxPower",
56  "Transmission power (dB).",
57  DoubleValue (30),
59  MakeDoubleChecker<double> ())
60 
61  .AddAttribute ("G",
62  "This is the ratio of CP time to useful time.",
63  DoubleValue (0.25),
64  MakeDoubleAccessor (&SimpleOfdmWimaxPhy::DoSetGValue, &SimpleOfdmWimaxPhy::DoGetGValue),
65  MakeDoubleChecker<double> ())
66 
67  .AddAttribute ("TxGain",
68  "Transmission gain (dB).",
69  DoubleValue (0),
70  MakeDoubleAccessor (&SimpleOfdmWimaxPhy::SetTxGain, &SimpleOfdmWimaxPhy::GetTxGain),
71  MakeDoubleChecker<double> ())
72 
73  .AddAttribute ("RxGain",
74  "Reception gain (dB).",
75  DoubleValue (0),
76  MakeDoubleAccessor (&SimpleOfdmWimaxPhy::SetRxGain, &SimpleOfdmWimaxPhy::GetRxGain),
77  MakeDoubleChecker<double> ())
78 
79  .AddAttribute ("Nfft",
80  "FFT size",
81  UintegerValue (256),
82  MakeUintegerAccessor (&SimpleOfdmWimaxPhy::DoSetNfft, &SimpleOfdmWimaxPhy::DoGetNfft),
83  MakeUintegerChecker<uint16_t> (256, 1024))
84 
85  .AddAttribute ("TraceFilePath",
86  "Path to the directory containing SNR to block error rate files",
87  StringValue (""),
88  MakeStringAccessor (&SimpleOfdmWimaxPhy::GetTraceFilePath,
89  &SimpleOfdmWimaxPhy::SetTraceFilePath),
90  MakeStringChecker ())
91 
92  .AddTraceSource ("Rx", "Receive trace", MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_traceRx))
93 
94  .AddTraceSource ("Tx", "Transmit trace", MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_traceTx))
95 
96  .AddTraceSource ("PhyTxBegin",
97  "Trace source indicating a packet has begun transmitting over the channel medium",
99 
100  .AddTraceSource ("PhyTxEnd",
101  "Trace source indicating a packet has been completely transmitted over the channel",
103 
104  .AddTraceSource ("PhyTxDrop",
105  "Trace source indicating a packet has been dropped by the device during transmission",
107 
108  .AddTraceSource ("PhyRxBegin",
109  "Trace source indicating a packet has begun being received from the channel medium by the device",
111 
112  .AddTraceSource ("PhyRxEnd",
113  "Trace source indicating a packet has been completely received from the channel medium by the device",
115 
116  .AddTraceSource ("PhyRxDrop",
117  "Trace source indicating a packet has been dropped by the device during reception",
119  return tid;
120 }
121 
122 void
123 SimpleOfdmWimaxPhy::InitSimpleOfdmWimaxPhy (void)
124 {
125  m_fecBlockSize = 0;
126  m_nrFecBlocksSent = 0;
127  m_dataRateBpsk12 = 0;
128  m_dataRateQpsk12 = 0;
129  m_dataRateQpsk34 = 0;
130  m_dataRateQam16_12 = 0;
131 
132  m_dataRateQam16_34 = 0;
133  m_dataRateQam64_23 = 0;
134  m_dataRateQam64_34 = 0;
135 
136  m_nrBlocks = 0;
137  m_blockSize = 0;
138  m_paddingBits = 0;
139  m_rxGain = 0;
140  m_txGain = 0;
141  m_nfft = 256;
142  m_g = (double) 1 / 4;
143  SetNrCarriers (192);
144  m_fecBlocks = new std::list<bvec>;
145  m_receivedFecBlocks = new std::list<bvec>;
146  m_currentBurstSize = 0;
147  m_noiseFigure = 5; // dB
148  m_txPower = 30; // dBm
149  SetBandwidth (10000000); // 10Mhz
150  m_nbErroneousBlock = 0;
151  m_nrRecivedFecBlocks = 0;
152  m_snrToBlockErrorRateManager = new SNRToBlockErrorRateManager ();
153 }
154 
155 SimpleOfdmWimaxPhy::SimpleOfdmWimaxPhy (void)
156 {
157  m_URNG = CreateObject<UniformRandomVariable> ();
158 
159  InitSimpleOfdmWimaxPhy ();
160  m_snrToBlockErrorRateManager->SetTraceFilePath ((char*) "");
161  m_snrToBlockErrorRateManager->LoadTraces ();
162 }
163 
164 SimpleOfdmWimaxPhy::SimpleOfdmWimaxPhy (char * tracesPath)
165 {
166  InitSimpleOfdmWimaxPhy ();
167  m_snrToBlockErrorRateManager->SetTraceFilePath (tracesPath);
168  m_snrToBlockErrorRateManager->LoadTraces ();
169 }
170 
171 SimpleOfdmWimaxPhy::~SimpleOfdmWimaxPhy (void)
172 {
173 
174 }
175 
176 void
178 {
179  m_snrToBlockErrorRateManager->ActivateLoss (loss);
180 }
181 
182 void
184 {
185  m_snrToBlockErrorRateManager->SetTraceFilePath (tracesPath);
186  m_snrToBlockErrorRateManager->ReLoadTraces ();
187 }
188 
189 uint32_t
191 {
193 }
194 
195 void
197 {
199 }
200 
201 double
203 {
204  return m_txPower;
205 }
206 void
208 {
209  m_txPower = txPower;
210 }
211 
212 double
214 {
215  return m_noiseFigure;
216 }
217 void
219 {
220  m_noiseFigure = noiseFigure;
221 }
222 
223 void
225 {
226  delete m_receivedFecBlocks;
227  delete m_fecBlocks;
228  m_receivedFecBlocks = 0;
229  m_fecBlocks = 0;
230  delete m_snrToBlockErrorRateManager;
232 }
233 
234 void
236 {
237  GetChannel ()->Attach (this);
238 }
239 
240 void
242 {
243  OfdmSendParams *o_params = dynamic_cast<OfdmSendParams*> (params);
244  Send (o_params->GetBurst (),
245  (WimaxPhy::ModulationType) o_params->GetModulationType (),
246  o_params->GetDirection ());
247 
248 }
249 
250 WimaxPhy::PhyType
252 {
253  return WimaxPhy::simpleOfdmWimaxPhy;
254 }
255 
256 void
258  WimaxPhy::ModulationType modulationType,
259  uint8_t direction)
260 {
261 
262  if (GetState () != PHY_STATE_TX)
263  {
264  m_currentBurstSize = burst->GetSize ();
265  m_nrFecBlocksSent = 0;
266  m_currentBurst = burst;
267  SetBlockParameters (burst->GetSize (), modulationType);
268  NotifyTxBegin (m_currentBurst);
269  StartSendDummyFecBlock (true, modulationType, direction);
270  m_traceTx (burst);
271  }
272 }
273 
274 void
275 SimpleOfdmWimaxPhy::StartSendDummyFecBlock (bool isFirstBlock,
276  WimaxPhy::ModulationType modulationType,
277  uint8_t direction)
278 {
279  SetState (PHY_STATE_TX);
280  bool isLastFecBlock = 0;
281  if (isFirstBlock)
282  {
283  m_blockTime = GetBlockTransmissionTime (modulationType);
284  }
285 
286  SimpleOfdmWimaxChannel *channel = dynamic_cast<SimpleOfdmWimaxChannel*> (PeekPointer (GetChannel ()));
287 
288  if (m_nrRemainingBlocksToSend==1)
289  {
290  isLastFecBlock = true;
291  }
292  else
293  {
294  isLastFecBlock = false;
295  }
296  channel->Send (m_blockTime,
297  m_currentBurstSize,
298  this,
299  isFirstBlock,
300  isLastFecBlock,
301  GetTxFrequency (),
302  modulationType,
303  direction,
304  m_txPower,
305  m_currentBurst);
306 
307  m_nrRemainingBlocksToSend--;
308  Simulator::Schedule (m_blockTime, &SimpleOfdmWimaxPhy::EndSendFecBlock, this, modulationType, direction);
309 }
310 
311 
312 void
313 SimpleOfdmWimaxPhy::EndSendFecBlock (WimaxPhy::ModulationType modulationType,
314  uint8_t direction)
315 {
316  m_nrFecBlocksSent++;
317  SetState (PHY_STATE_IDLE);
318 
319  if (m_nrFecBlocksSent * m_blockSize == m_currentBurstSize * 8 + m_paddingBits)
320  {
321  // this is the last FEC block of the burst
322  NS_ASSERT_MSG (m_nrRemainingBlocksToSend == 0, "Error while sending a burst");
323  NotifyTxEnd (m_currentBurst);
324  }
325  else
326  {
327  StartSendDummyFecBlock (false,modulationType,direction);
328  }
329 }
330 
331 void
332 SimpleOfdmWimaxPhy::EndSend (void)
333 {
334  SetState (PHY_STATE_IDLE);
335 }
336 
337 void
339  bool isFirstBlock,
340  uint64_t frequency,
341  WimaxPhy::ModulationType modulationType,
342  uint8_t direction,
343  double rxPower,
344  Ptr<PacketBurst> burst)
345 {
346 
347  uint8_t drop = 0;
348  double Nwb = -114 + m_noiseFigure + 10 * std::log (GetBandwidth () / 1000000000.0) / 2.303;
349  double SNR = rxPower - Nwb;
350 
351  SNRToBlockErrorRateRecord * record = m_snrToBlockErrorRateManager->GetSNRToBlockErrorRateRecord (SNR, modulationType);
352  double I1 = record->GetI1 ();
353  double I2 = record->GetI2 ();
354 
355  double blockErrorRate = m_URNG->GetValue (I1, I2);
356 
357  double rand = m_URNG->GetValue (0.0, 1.0);
358 
359  if (rand < blockErrorRate)
360  {
361  drop = 1;
362  }
363  if (rand > blockErrorRate)
364  {
365  drop = 0;
366  }
367 
368  if (blockErrorRate == 1.0)
369  {
370  drop = 1;
371  }
372  if (blockErrorRate == 0.0)
373  {
374  drop = 0;
375  }
376  delete record;
377 
378  NS_LOG_INFO ("PHY: Receive rxPower=" << rxPower << ", Nwb=" << Nwb << ", SNR=" << SNR << ", Modulation="
379  << modulationType << ", BlocErrorRate=" << blockErrorRate << ", drop=" << (int) drop);
380 
381  switch (GetState ())
382  {
383  case PHY_STATE_SCANNING:
384  if (frequency == GetScanningFrequency ())
385  {
386  Simulator::Cancel (GetChnlSrchTimeoutEvent ());
388  SetSimplex (frequency);
389  SetState (PHY_STATE_IDLE);
390  }
391  break;
392  case PHY_STATE_IDLE:
393  if (frequency == GetRxFrequency ())
394  {
395  if (isFirstBlock)
396  {
397  NotifyRxBegin (burst);
398  m_receivedFecBlocks->clear ();
399  m_nrRecivedFecBlocks=0;
400  SetBlockParameters (burstSize, modulationType);
401  m_blockTime = GetBlockTransmissionTime (modulationType);
402  }
403 
404  Simulator::Schedule (m_blockTime,
405  &SimpleOfdmWimaxPhy::EndReceiveFecBlock,
406  this,
407  burstSize,
408  modulationType,
409  direction,
410  drop,
411  burst);
412 
413  SetState (PHY_STATE_RX);
414  }
415  break;
416  case PHY_STATE_RX:
417  // drop
418  break;
419  case PHY_STATE_TX:
420  if (IsDuplex () && frequency == GetRxFrequency ())
421  {
422 
423  }
424  break;
425  }
426 }
427 
428 void
429 SimpleOfdmWimaxPhy::EndReceiveFecBlock (uint32_t burstSize,
430  WimaxPhy::ModulationType modulationType,
431  uint8_t direction,
432  uint8_t drop,
433  Ptr<PacketBurst> burst)
434 {
435  SetState (PHY_STATE_IDLE);
436  m_nrRecivedFecBlocks++;
437 
438  if (drop == true)
439  {
440  m_nbErroneousBlock++;
441  }
442 
443  if ((uint32_t) m_nrRecivedFecBlocks * m_blockSize == burstSize * 8 + m_paddingBits)
444  {
445  NotifyRxEnd (burst);
446  if (m_nbErroneousBlock == 0)
447  {
449  &SimpleOfdmWimaxPhy::EndReceive,
450  this,
451  burst);
452  }
453  else
454  {
455  NotifyRxDrop (burst);
456  }
457  m_nbErroneousBlock = 0;
458  m_nrRecivedFecBlocks = 0;
459  }
460 }
461 
462 void
463 SimpleOfdmWimaxPhy::EndReceive (Ptr<const PacketBurst> burst)
464 {
465  Ptr<PacketBurst> b = burst->Copy ();
466  GetReceiveCallback () (b);
467  m_traceRx (burst);
468 }
469 
470 bvec
471 SimpleOfdmWimaxPhy::ConvertBurstToBits (Ptr<const PacketBurst> burst)
472 {
473  bvec buffer (burst->GetSize () * 8, 0);
474 
475  std::list<Ptr<Packet> > packets = burst->GetPackets ();
476 
477  uint32_t j = 0;
478  for (std::list<Ptr<Packet> >::iterator iter = packets.begin (); iter != packets.end (); ++iter)
479  {
480  Ptr<Packet> packet = *iter;
481  uint8_t *pstart = (uint8_t*) std::malloc (packet->GetSize ());
482  std::memset (pstart, 0, packet->GetSize ());
483  packet->CopyData (pstart, packet->GetSize ());
484  bvec temp (8);
485  temp.resize (0, 0);
486  temp.resize (8, 0);
487  for (uint32_t i = 0; i < packet->GetSize (); i++)
488  {
489  for (uint8_t l = 0; l < 8; l++)
490  {
491  temp[l] = (bool)((((uint8_t) pstart[i]) >> (7 - l)) & 0x01);
492  buffer.at (j * 8 + l) = temp[l];
493  }
494  j++;
495  }
496  std::free (pstart);
497  }
498 
499  return buffer;
500 }
501 
502 /*
503  Converts back the bit buffer (bvec) to the actual burst.
504  Actually creates byte buffer from the bvec and resets the buffer
505  of each packet in the copy of the orifinal burst stored before transmitting.
506  By doing this it preserves the metadata and tags in the packet.
507  Function could also be named DeserializeBurst because actually it
508  copying to the burst's byte buffer.
509  */
510 Ptr<PacketBurst>
511 SimpleOfdmWimaxPhy::ConvertBitsToBurst (bvec buffer)
512 {
513  uint8_t init[buffer.size () / 8];
514  uint8_t *pstart = init;
515  uint8_t temp;
516  int32_t j = 0;
517  // recreating byte buffer from bit buffer (bvec)
518  for (uint32_t i = 0; i < buffer.size (); i += 8)
519  {
520 
521  temp = 0;
522  for (int l = 0; l < 8; l++)
523  {
524  bool bin = buffer.at (i + l);
525  temp += (uint8_t)(bin * std::pow (2.0, (7 - l)));
526  }
527 
528  *(pstart + j) = temp;
529  j++;
530  }
531  uint16_t bufferSize = buffer.size () / 8;
532  uint16_t pos = 0;
533  Ptr<PacketBurst> RecvBurst = Create<PacketBurst> ();
534  while (pos < bufferSize)
535  {
536  uint16_t packetSize = 0;
537  // Get the header type: first bit
538  uint8_t ht = (pstart[pos] >> 7) & 0x01;
539  if (ht == 1)
540  {
541  // BW request header. Size is always 8 bytes
542  packetSize = 6;
543  }
544  else
545  {
546  // Read the size
547  uint8_t Len_MSB = pstart[pos + 1] & 0x07;
548  packetSize = (uint16_t)((uint16_t)(Len_MSB << 8) | (uint16_t)(pstart[pos + 2]));
549  if (packetSize == 0)
550  {
551  break; // padding
552  }
553  }
554 
555  Ptr<Packet> p = Create<Packet> (&(pstart[pos]), packetSize);
556  RecvBurst->AddPacket (p);
557  pos += packetSize;
558  }
559  return RecvBurst;
560 }
561 
562 void
563 SimpleOfdmWimaxPhy::CreateFecBlocks (const bvec &buffer, WimaxPhy::ModulationType modulationType)
564 {
565 
566  bvec fecBlock (m_blockSize);
567  for (uint32_t i = 0, j = m_nrBlocks; j > 0; i += m_blockSize, j--)
568  {
569 
570  if (j == 1 && m_paddingBits > 0) // last block can be smaller than block size
571  {
572  fecBlock = bvec (buffer.begin () + i, buffer.end ());
573  fecBlock.resize (m_blockSize, 0);
574  }
575  else
576  {
577  fecBlock = bvec (buffer.begin () + i, buffer.begin () + i + m_blockSize);
578  }
579 
580  m_fecBlocks->push_back (fecBlock);
581  }
582 }
583 
584 bvec
585 SimpleOfdmWimaxPhy::RecreateBuffer ()
586 {
587 
588  bvec buffer (m_blockSize * m_nrBlocks);
589  bvec block (m_blockSize);
590  uint32_t i = 0;
591  for (uint32_t j = 0; j < m_nrBlocks; j++)
592  {
593  bvec tmpRecFecBloc = m_receivedFecBlocks->front ();
594  buffer.insert (buffer.begin () + i, tmpRecFecBloc.begin (), tmpRecFecBloc.end ());
595  m_receivedFecBlocks->pop_front ();
596  i += m_blockSize;
597  }
598  return buffer;
599 }
600 
601 void
602 SimpleOfdmWimaxPhy::DoSetDataRates (void)
603 {
604  m_dataRateBpsk12 = CalculateDataRate (MODULATION_TYPE_BPSK_12); // 6912000 bps
605  m_dataRateQpsk12 = CalculateDataRate (MODULATION_TYPE_QPSK_12); // 13824000
606  m_dataRateQpsk34 = CalculateDataRate (MODULATION_TYPE_QPSK_34); // 20736000
607  m_dataRateQam16_12 = CalculateDataRate (MODULATION_TYPE_QAM16_12); // 27648000
608  m_dataRateQam16_34 = CalculateDataRate (MODULATION_TYPE_QAM16_34); // 41472000
609  m_dataRateQam64_23 = CalculateDataRate (MODULATION_TYPE_QAM64_23); // 55224000
610  m_dataRateQam64_34 = CalculateDataRate (MODULATION_TYPE_QAM64_34); // 62208000
611 }
612 
613 void
614 SimpleOfdmWimaxPhy::GetModulationFecParams (WimaxPhy::ModulationType modulationType,
615  uint8_t &bitsPerSymbol,
616  double &fecCode) const
617 {
618  switch (modulationType)
619  {
620  case MODULATION_TYPE_BPSK_12:
621  bitsPerSymbol = 1;
622  fecCode = (double) 1 / 2;
623  break;
624  case MODULATION_TYPE_QPSK_12:
625  bitsPerSymbol = 2;
626  fecCode = (double) 1 / 2;
627  break;
628  case MODULATION_TYPE_QPSK_34:
629  bitsPerSymbol = 2;
630  fecCode = (double) 3 / 4;
631  break;
632  case MODULATION_TYPE_QAM16_12:
633  bitsPerSymbol = 4;
634  fecCode = (double) 1 / 2;
635  break;
636  case MODULATION_TYPE_QAM16_34:
637  bitsPerSymbol = 4;
638  fecCode = (double) 3 / 4;
639  break;
640  case MODULATION_TYPE_QAM64_23:
641  bitsPerSymbol = 6;
642  fecCode = (double) 2 / 3;
643  break;
644  case MODULATION_TYPE_QAM64_34:
645  bitsPerSymbol = 6;
646  fecCode = 0.75;
647  break;
648  }
649 }
650 
651 uint32_t
652 SimpleOfdmWimaxPhy::CalculateDataRate (WimaxPhy::ModulationType modulationType) const
653 {
654  uint8_t bitsPerSymbol = 0;
655  double fecCode = 0;
656  GetModulationFecParams (modulationType, bitsPerSymbol, fecCode);
657  double symbolsPerSecond = 1 / GetSymbolDuration ().GetSeconds ();
658  uint16_t bitsTransmittedPerSymbol = (uint16_t)(bitsPerSymbol * GetNrCarriers () * fecCode);
659  // 96, 192, 288, 384, 576, 767 and 864 bits per symbol for the seven modulations, respectively
660 
661  return (uint32_t) symbolsPerSecond * bitsTransmittedPerSymbol;
662 }
663 
664 uint32_t
665 SimpleOfdmWimaxPhy::DoGetDataRate (WimaxPhy::ModulationType modulationType) const
666 {
667  switch (modulationType)
668  {
669  case MODULATION_TYPE_BPSK_12:
670  return m_dataRateBpsk12;
671  break;
672  case MODULATION_TYPE_QPSK_12:
673  return m_dataRateQpsk12;
674  break;
675  case MODULATION_TYPE_QPSK_34:
676  return m_dataRateQpsk34;
677  break;
678  case MODULATION_TYPE_QAM16_12:
679  return m_dataRateQam16_12;
680  break;
681  case MODULATION_TYPE_QAM16_34:
682  return m_dataRateQam16_34;
683  break;
684  case MODULATION_TYPE_QAM64_23:
685  return m_dataRateQam64_23;
686  break;
687  case MODULATION_TYPE_QAM64_34:
688  return m_dataRateQam64_34;
689  break;
690  }
691  NS_FATAL_ERROR ("Invalid modulation type");
692  return 0;
693 }
694 
695 Time
696 SimpleOfdmWimaxPhy::GetBlockTransmissionTime (WimaxPhy::ModulationType modulationType) const
697 {
698  return Seconds ((double) GetFecBlockSize (modulationType) / DoGetDataRate (modulationType));
699 }
700 
701 Time
702 SimpleOfdmWimaxPhy::DoGetTransmissionTime (uint32_t size, WimaxPhy::ModulationType modulationType) const
703 {
704  /*adding 3 extra nano second to cope with the loss of precision problem.
705  the time is internally stored in a 64 bit hence a floating-point time would loss
706  precision, e.g., 0.00001388888888888889 seconds will become 13888888888 femtoseconds.*/
707  return Seconds (DoGetNrSymbols (size, modulationType) * GetSymbolDuration ().GetSeconds ()) + NanoSeconds (3);
708 }
709 
710 uint64_t
711 SimpleOfdmWimaxPhy::DoGetNrSymbols (uint32_t size, WimaxPhy::ModulationType modulationType) const
712 {
713  Time transmissionTime = Seconds ((double)(GetNrBlocks (size, modulationType) * GetFecBlockSize (modulationType))
714  / DoGetDataRate (modulationType));
715  return (uint64_t) std::ceil (transmissionTime.GetSeconds () / GetSymbolDuration ().GetSeconds ());
716 }
717 
718 uint64_t
719 SimpleOfdmWimaxPhy::DoGetNrBytes (uint32_t symbols, WimaxPhy::ModulationType modulationType) const
720 {
721  Time transmissionTime = Seconds (symbols * GetSymbolDuration ().GetSeconds ());
722  return (uint64_t) std::floor ((transmissionTime.GetSeconds () * DoGetDataRate (modulationType)) / 8);
723 }
724 
725 uint32_t
726 SimpleOfdmWimaxPhy::GetFecBlockSize (WimaxPhy::ModulationType modulationType) const
727 {
728  uint32_t blockSize = 0;
729  switch (modulationType)
730  {
731  case MODULATION_TYPE_BPSK_12:
732  blockSize = 12;
733  break;
734  case MODULATION_TYPE_QPSK_12:
735  blockSize = 24;
736  break;
737  case MODULATION_TYPE_QPSK_34:
738  blockSize = 36;
739  break;
740  case MODULATION_TYPE_QAM16_12:
741  blockSize = 48;
742  break;
743  case MODULATION_TYPE_QAM16_34:
744  blockSize = 72;
745  break;
746  case MODULATION_TYPE_QAM64_23:
747  blockSize = 96;
748  break;
749  case MODULATION_TYPE_QAM64_34:
750  blockSize = 108;
751  break;
752  default:
753  NS_FATAL_ERROR ("Invalid modulation type");
754  break;
755  }
756  return blockSize * 8; // in bits
757 }
758 
759 // Channel coding block size, Table 215, page 434
760 uint32_t
761 SimpleOfdmWimaxPhy::GetCodedFecBlockSize (WimaxPhy::ModulationType modulationType) const
762 {
763  uint32_t blockSize = 0;
764  switch (modulationType)
765  {
766  case MODULATION_TYPE_BPSK_12:
767  blockSize = 24;
768  break;
769  case MODULATION_TYPE_QPSK_12:
770  blockSize = 48;
771  break;
772  case MODULATION_TYPE_QPSK_34:
773  blockSize = 48;
774  break;
775  case MODULATION_TYPE_QAM16_12:
776  blockSize = 96;
777  break;
778  case MODULATION_TYPE_QAM16_34:
779  blockSize = 96;
780  break;
781  case MODULATION_TYPE_QAM64_23:
782  blockSize = 144;
783  break;
784  case MODULATION_TYPE_QAM64_34:
785  blockSize = 144;
786  break;
787  default:
788  NS_FATAL_ERROR ("Invalid modulation type");
789  break;
790  }
791  return blockSize * 8; // in bits
792 }
793 
794 void
795 SimpleOfdmWimaxPhy::SetBlockParameters (uint32_t burstSize, WimaxPhy::ModulationType modulationType)
796 {
797  m_blockSize = GetFecBlockSize (modulationType);
798  m_nrBlocks = GetNrBlocks (burstSize, modulationType);
799  m_paddingBits = (m_nrBlocks * m_blockSize) - (burstSize * 8);
800  m_nrRemainingBlocksToSend = m_nrBlocks;
801  NS_ASSERT_MSG (static_cast<uint32_t> (m_nrBlocks * m_blockSize) >= (burstSize * 8), "Size of padding bytes < 0");
802 }
803 
804 uint16_t
805 SimpleOfdmWimaxPhy::DoGetTtg (void) const
806 {
807  // assumed equal to 2 symbols
808  return 2 * GetPsPerSymbol ();
809 }
810 
811 uint16_t
812 SimpleOfdmWimaxPhy::DoGetRtg (void) const
813 {
814  // assumed equal to 2 symbols
815  return 2 * GetPsPerSymbol ();
816 }
817 
818 uint8_t
819 SimpleOfdmWimaxPhy::DoGetFrameDurationCode (void) const
820 {
821  uint16_t duration = 0;
822  duration = (uint16_t)(GetFrameDuration ().GetSeconds () * 10000);
823  switch (duration)
824  {
825  case 25:
826  {
827  return FRAME_DURATION_2_POINT_5_MS;
828  break;
829  }
830  case 40:
831  {
832  return FRAME_DURATION_4_MS;
833  break;
834  }
835  case 50:
836  {
837  return FRAME_DURATION_5_MS;
838  break;
839  }
840  case 80:
841  {
842  return FRAME_DURATION_8_MS;
843  break;
844  }
845  case 100:
846  {
847  return FRAME_DURATION_10_MS;
848  break;
849  }
850  case 125:
851  {
852  return FRAME_DURATION_12_POINT_5_MS;
853  break;
854  }
855  case 200:
856  {
857  return FRAME_DURATION_20_MS;
858  break;
859  }
860  default:
861  {
862  NS_FATAL_ERROR ("Invalid frame duration = " << duration);
863  return 0;
864  }
865  }
866  NS_FATAL_ERROR ("Invalid frame duration = " << duration);
867  return 0;
868 }
869 
870 Time
871 SimpleOfdmWimaxPhy::DoGetFrameDuration (uint8_t frameDurationCode) const
872 {
873  switch (frameDurationCode)
874  {
875  case FRAME_DURATION_2_POINT_5_MS:
876  return Seconds (2.5);
877  break;
878  case FRAME_DURATION_4_MS:
879  return Seconds (4);
880  break;
881  case FRAME_DURATION_5_MS:
882  return Seconds (5);
883  break;
884  case FRAME_DURATION_8_MS:
885  return Seconds (8);
886  break;
887  case FRAME_DURATION_10_MS:
888  return Seconds (10);
889  break;
890  case FRAME_DURATION_12_POINT_5_MS:
891  return Seconds (12.5);
892  break;
893  case FRAME_DURATION_20_MS:
894  return Seconds (20);
895  break;
896  default:
897  NS_FATAL_ERROR ("Invalid modulation type");
898  }
899  return Seconds (0);
900 }
901 
902 /*
903  Retruns number of blocks (FEC blocks) the burst will be splitted in.
904  The size of the block is specific for each modulation type.
905  */
906 uint16_t
907 SimpleOfdmWimaxPhy::GetNrBlocks (uint32_t burstSize, WimaxPhy::ModulationType modulationType) const
908 {
909  uint32_t blockSize = GetFecBlockSize (modulationType);
910  uint16_t nrBlocks = (burstSize * 8) / blockSize;
911 
912  if ((burstSize * 8) % blockSize > 0)
913  {
914  nrBlocks += 1;
915  }
916 
917  return nrBlocks;
918 }
919 /*---------------------PHY parameters functions-----------------------*/
920 
921 void
922 SimpleOfdmWimaxPhy::DoSetPhyParameters (void)
923 {
924  /*Calculations as per section 8.3.2.
925  Currently assuming license-exempt 5 GHz band. For channel bandwidth 20 MHz (Table B.28, page 812) and frame duration 10 ms
926  (Table 232, page 460) i.e, 100 frames per second, sampling frequency is 23040000, symbol (OFDM symbol) duration is
927  1.388888888888889e-05 seconds, PS duration is 1.7361111111111112e-07 seconds. Hence PSs per frame is 57600, symbols per frame
928  is 720 and PSs per symbol is 80. Note that defining these parameters (symbol and PS duration) as Time may not result in exaclty
929  these values therefore lrint has been used (otherwise should be defined as double).
930  For licensed bands set channel bandwidth according to Table B.26, page 810.*/
931 
932  double samplingFrequency = DoGetSamplingFrequency ();
933  Time psDuration = Seconds ((double) 4 / samplingFrequency);
934 
935  SetPsDuration (psDuration);
936  uint16_t psPerFrame = (uint16_t)(GetFrameDuration ().GetSeconds () / psDuration.GetSeconds ());
937  SetPsPerFrame (psPerFrame);
938  double subcarrierSpacing = samplingFrequency / DoGetNfft ();
939  double tb = (double) 1 / subcarrierSpacing; // Tb (useful symbol time)
940  double tg = DoGetGValue () * tb; // Tg (cyclic prefix time)
941  Time symbolDuration = Seconds (tb + tg); // OFDM Symbol Time
942  SetSymbolDuration (symbolDuration);
943  uint16_t psPerSymbol = lrint (symbolDuration.GetSeconds () / psDuration.GetSeconds ());
944  SetPsPerSymbol (psPerSymbol);
945  uint32_t symbolsPerFrame = lrint (GetFrameDuration ().GetSeconds () / symbolDuration.GetSeconds ());
946  SetSymbolsPerFrame (symbolsPerFrame);
947 }
948 
949 void
950 SimpleOfdmWimaxPhy::DoSetNfft (uint16_t nfft)
951 {
952  m_nfft = nfft;
953 
954 }
955 
956 uint16_t
957 SimpleOfdmWimaxPhy::DoGetNfft (void) const
958 {
959  return m_nfft;
960 
961 }
962 
963 double
964 SimpleOfdmWimaxPhy::DoGetSamplingFactor (void) const
965 {
966  // sampling factor (n), see Table 213, page 429
967 
968  uint32_t channelBandwidth = GetChannelBandwidth ();
969 
970  if (channelBandwidth % 1750000 == 0)
971  {
972  return (double) 8 / 7;
973  }
974  else if (channelBandwidth % 1500000 == 0)
975  {
976  return (double) 86 / 75;
977  }
978  else if (channelBandwidth % 1250000 == 0)
979  {
980  return (double) 144 / 125;
981  }
982  else if (channelBandwidth % 2750000 == 0)
983  {
984  return (double) 316 / 275;
985  }
986  else if (channelBandwidth % 2000000 == 0)
987  {
988  return (double) 57 / 50;
989  }
990  else
991  {
992  NS_LOG_DEBUG ("Oops may be wrong channel bandwidth for OFDM PHY!");
993  NS_FATAL_ERROR ("wrong channel bandwidth for OFDM PHY");
994  }
995 
996  return (double) 8 / 7;
997 }
998 
999 double
1000 SimpleOfdmWimaxPhy::DoGetSamplingFrequency (void) const
1001 {
1002  // sampling frequency (Fs), see 8.3.2.2
1003 
1004  return (DoGetSamplingFactor () * GetChannelBandwidth () / 8000) * 8000;
1005 }
1006 
1007 double
1008 SimpleOfdmWimaxPhy::DoGetGValue (void) const
1009 {
1010 
1011  return m_g;
1012 }
1013 
1014 void
1015 SimpleOfdmWimaxPhy::DoSetGValue (double g)
1016 {
1017  m_g = g;
1018 
1019 }
1020 
1021 void
1022 SimpleOfdmWimaxPhy::SetTxGain (double txGain)
1023 {
1024  m_txGain = txGain;
1025 }
1026 
1027 void
1028 SimpleOfdmWimaxPhy::SetRxGain (double txRain)
1029 {
1030  m_rxGain = txRain;
1031 }
1032 
1033 double
1034 SimpleOfdmWimaxPhy::GetTxGain (void) const
1035 {
1036  return m_txGain;
1037 }
1038 
1039 double
1040 SimpleOfdmWimaxPhy::GetRxGain (void) const
1041 {
1042  return m_rxGain;
1043 }
1044 
1045 std::string
1046 SimpleOfdmWimaxPhy::GetTraceFilePath (void) const
1047 {
1048  return (m_snrToBlockErrorRateManager->GetTraceFilePath ());
1049 }
1050 
1051 void
1052 SimpleOfdmWimaxPhy::SetTraceFilePath (std::string path)
1053 {
1054 
1055  m_snrToBlockErrorRateManager->SetTraceFilePath ((char*) path.c_str ());
1056  m_snrToBlockErrorRateManager->LoadTraces ();
1057 }
1058 
1059 void
1061 {
1062  m_phyTxBeginTrace (burst);
1063 }
1064 
1065 void
1067 {
1068  m_phyTxEndTrace (burst);
1069 }
1070 
1071 void
1073 {
1074  m_phyTxDropTrace (burst);
1075 }
1076 
1077 void
1079 {
1080  m_phyRxBeginTrace (burst);
1081 }
1082 
1083 void
1085 {
1086  m_phyRxEndTrace (burst);
1087 }
1088 
1089 void
1091 {
1092  m_phyRxDropTrace (burst);
1093 }
1094 
1095 int64_t
1097 {
1098  NS_LOG_FUNCTION (this << stream);
1099  m_URNG->SetStream (stream);
1100  return 1;
1101 }
1102 
1103 } // namespace ns3
void SetNoiseFigure(double nf)
set the noise figure of the device
Time NanoSeconds(uint64_t ns)
create ns3::Time instances in units of nanoseconds.
Definition: nstime.h:629
void StartReceive(uint32_t burstSize, bool isFirstBlock, uint64_t frequency, WimaxPhy::ModulationType modulationType, uint8_t direction, double rxPower, Ptr< PacketBurst > burst)
start the reception of a fec block
Callback< void, Ptr< const PacketBurst > > GetReceiveCallback(void) const
Definition: wimax-phy.cc:151
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
void SetSNRToBlockErrorRateTracesPath(char *tracesPath)
Set the path of the repository containing the traces.
TracedCallback< Ptr< PacketBurst > > m_phyRxEndTrace
void Send(Ptr< PacketBurst > burst, WimaxPhy::ModulationType modulationType, uint8_t direction)
Sends a burst on the channel.
void NotifyRxDrop(Ptr< PacketBurst > burst)
virtual void DoDispose(void)
Definition: wimax-phy.cc:95
void NotifyRxBegin(Ptr< PacketBurst > burst)
int64_t AssignStreams(int64_t stream)
bool IsDuplex(void) const
Definition: wimax-phy.cc:200
uint32_t GetChannelBandwidth(void) const
Definition: wimax-phy.cc:328
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
void SetSimplex(uint64_t frequency)
configure the physical layer in simplex mode
Definition: wimax-phy.cc:164
void NotifyTxDrop(Ptr< PacketBurst > burst)
#define NS_LOG_INFO(msg)
Definition: log.h:264
uint64_t GetRxFrequency(void) const
Definition: wimax-phy.cc:171
static void Cancel(const EventId &id)
Definition: simulator.cc:267
Time GetSymbolDuration(void) const
Definition: wimax-phy.cc:370
void NotifyTxBegin(Ptr< PacketBurst > burst)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
void SetSymbolsPerFrame(uint32_t symbolsPerFrame)
set the number of symbols per frame
Definition: wimax-phy.cc:406
TracedCallback< Ptr< PacketBurst > > m_phyTxDropTrace
void SetPsDuration(Time psDuration)
set the physical slot duration in seconds
Definition: wimax-phy.cc:352
Time GetFrameDuration(void) const
Definition: wimax-phy.cc:298
void SetBandwidth(uint32_t BW)
Set the bandwidth.
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
This class represents a record (handled by SnrToBlockErrorRate manager) that keeps a mapping between ...
TracedCallback< Ptr< PacketBurst > > m_phyTxBeginTrace
SNRToBlockErrorRateRecord * GetSNRToBlockErrorRateRecord(double SNR, uint8_t modulation)
returns a record of type SNRToBlockErrorRateRecord corresponding to a given modulation and SNR value ...
Ptr< UniformRandomVariable > m_URNG
Provides uniform random variables.
double GetSeconds(void) const
Definition: nstime.h:262
The SendParams class defines the parameters with which Send() function of a particular PHY is called...
Definition: send-params.h:43
void SetScanningCallback(void) const
calls the scanning call back function
Definition: wimax-phy.cc:212
void ActivateLoss(bool loss)
If activate loss is called with false, all the returned BlcER will be 0 (no losses) ...
void SetPsPerSymbol(uint16_t psPerSymbol)
set the number of physical slots per symbol
Definition: wimax-phy.cc:382
void SetTraceFilePath(char *traceFilePath)
Set the path of the repository containing the traces.
Ptr< WimaxChannel > GetChannel(void) const
Definition: wimax-phy.cc:109
uint8_t GetNrCarriers(void) const
Definition: wimax-phy.cc:286
void LoadTraces(void)
Loads the traces form the repository specified in the constructor or setted by SetTraceFilePath funct...
void NotifyRxEnd(Ptr< PacketBurst > burst)
void SetChannelBandwidth(uint32_t channelBandwidth)
Set the channel bandwidth.
Definition: wimax-phy.cc:322
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
double GetTxPower(void) const
double GetNoiseFigure(void) const
double GetValue(double min, double max)
Returns a random double from the uniform distribution with the specified range.
uint16_t GetPsPerSymbol(void) const
Definition: wimax-phy.cc:388
void DoAttach(Ptr< WimaxChannel > channel)
void ActivateLoss(bool loss)
if called with true it will enable the loss model
void NotifyTxEnd(Ptr< PacketBurst > burst)
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
TracedCallback< Ptr< PacketBurst > > m_phyRxBeginTrace
void SetTxPower(double txPower)
set the transmission power
TracedCallback< Ptr< PacketBurst > > m_phyTxEndTrace
void SetSymbolDuration(Time symbolDuration)
set the OFMD symbol duration in second
Definition: wimax-phy.cc:364
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
uint32_t GetBandwidth(void) const
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
void SetState(PhyState state)
set the state of the device
Definition: wimax-phy.cc:189
WimaxPhy::PhyType GetPhyType(void) const
returns the type this physical layer
void SetNrCarriers(uint8_t nrCarriers)
Set the number of carriers in the physical frame.
Definition: wimax-phy.cc:280
uint64_t GetTxFrequency(void) const
Definition: wimax-phy.cc:177
void SetPsPerFrame(uint16_t psPerFrame)
set the number of physical slot per frame
Definition: wimax-phy.cc:394
PhyState GetState(void) const
Definition: wimax-phy.cc:194
uint64_t GetScanningFrequency(void) const
Definition: wimax-phy.cc:183
TracedCallback< Ptr< PacketBurst > > m_phyRxDropTrace