A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
simple-ofdm-wimax-phy.cc
Go to the documentation of this file.
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"
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 
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),
65  MakeDoubleChecker<double> ())
66 
67  .AddAttribute ("TxGain",
68  "Transmission gain (dB).",
69  DoubleValue (0),
71  MakeDoubleChecker<double> ())
72 
73  .AddAttribute ("RxGain",
74  "Reception gain (dB).",
75  DoubleValue (0),
77  MakeDoubleChecker<double> ())
78 
79  .AddAttribute ("Nfft",
80  "FFT size",
81  UintegerValue (256),
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,
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
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;
153 }
154 
156 {
157  m_URNG = CreateObject<UniformRandomVariable> ();
158 
162 }
163 
165 {
169 }
170 
172 {
173 
174 }
175 
176 void
178 {
180 }
181 
182 void
184 {
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;
229  m_fecBlocks = 0;
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 (),
246  o_params->GetDirection ());
247 
248 }
249 
252 {
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);
269  StartSendDummyFecBlock (true, modulationType, direction);
270  m_traceTx (burst);
271  }
272 }
273 
274 void
276  WimaxPhy::ModulationType modulationType,
277  uint8_t direction)
278 {
280  bool isLastFecBlock = 0;
281  if (isFirstBlock)
282  {
283  m_blockTime = GetBlockTransmissionTime (modulationType);
284  }
285 
286  SimpleOfdmWimaxChannel *channel = dynamic_cast<SimpleOfdmWimaxChannel*> (PeekPointer (GetChannel ()));
287 
289  {
290  isLastFecBlock = true;
291  }
292  else
293  {
294  isLastFecBlock = false;
295  }
296  channel->Send (m_blockTime,
298  this,
299  isFirstBlock,
300  isLastFecBlock,
301  GetTxFrequency (),
302  modulationType,
303  direction,
304  m_txPower,
306 
308  Simulator::Schedule (m_blockTime, &SimpleOfdmWimaxPhy::EndSendFecBlock, this, modulationType, direction);
309 }
310 
311 
312 void
314  uint8_t direction)
315 {
318 
320  {
321  // this is the last FEC block of the burst
322  NS_ASSERT_MSG (m_nrRemainingBlocksToSend == 0, "Error while sending a burst");
324  }
325  else
326  {
327  StartSendDummyFecBlock (false,modulationType,direction);
328  }
329 }
330 
331 void
333 {
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 
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  {
388  SetSimplex (frequency);
390  }
391  break;
392  case PHY_STATE_IDLE:
393  if (frequency == GetRxFrequency ())
394  {
395  if (isFirstBlock)
396  {
397  NotifyRxBegin (burst);
398  m_receivedFecBlocks->clear ();
400  SetBlockParameters (burstSize, modulationType);
401  m_blockTime = GetBlockTransmissionTime (modulationType);
402  }
403 
406  this,
407  burstSize,
408  modulationType,
409  direction,
410  drop,
411  burst);
412 
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
430  WimaxPhy::ModulationType modulationType,
431  uint8_t direction,
432  uint8_t drop,
433  Ptr<PacketBurst> burst)
434 {
437 
438  if (drop == true)
439  {
441  }
442 
443  if ((uint32_t) m_nrRecivedFecBlocks * m_blockSize == burstSize * 8 + m_paddingBits)
444  {
445  NotifyRxEnd (burst);
446  if (m_nbErroneousBlock == 0)
447  {
450  this,
451  burst);
452  }
453  else
454  {
455  NotifyRxDrop (burst);
456  }
457  m_nbErroneousBlock = 0;
459  }
460 }
461 
462 void
464 {
465  Ptr<PacketBurst> b = burst->Copy ();
466  GetReceiveCallback () (b);
467  m_traceRx (burst);
468 }
469 
470 bvec
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  */
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
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
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
603 {
611 }
612 
613 void
615  uint8_t &bitsPerSymbol,
616  double &fecCode) const
617 {
618  switch (modulationType)
619  {
621  bitsPerSymbol = 1;
622  fecCode = (double) 1 / 2;
623  break;
625  bitsPerSymbol = 2;
626  fecCode = (double) 1 / 2;
627  break;
629  bitsPerSymbol = 2;
630  fecCode = (double) 3 / 4;
631  break;
633  bitsPerSymbol = 4;
634  fecCode = (double) 1 / 2;
635  break;
637  bitsPerSymbol = 4;
638  fecCode = (double) 3 / 4;
639  break;
641  bitsPerSymbol = 6;
642  fecCode = (double) 2 / 3;
643  break;
645  bitsPerSymbol = 6;
646  fecCode = 0.75;
647  break;
648  }
649 }
650 
651 uint32_t
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
666 {
667  switch (modulationType)
668  {
670  return m_dataRateBpsk12;
671  break;
673  return m_dataRateQpsk12;
674  break;
676  return m_dataRateQpsk34;
677  break;
679  return m_dataRateQam16_12;
680  break;
682  return m_dataRateQam16_34;
683  break;
685  return m_dataRateQam64_23;
686  break;
688  return m_dataRateQam64_34;
689  break;
690  }
691  NS_FATAL_ERROR ("Invalid modulation type");
692  return 0;
693 }
694 
695 Time
697 {
698  return Seconds ((double) GetFecBlockSize (modulationType) / DoGetDataRate (modulationType));
699 }
700 
701 Time
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
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
727 {
728  uint32_t blockSize = 0;
729  switch (modulationType)
730  {
732  blockSize = 12;
733  break;
735  blockSize = 24;
736  break;
738  blockSize = 36;
739  break;
741  blockSize = 48;
742  break;
744  blockSize = 72;
745  break;
747  blockSize = 96;
748  break;
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
762 {
763  uint32_t blockSize = 0;
764  switch (modulationType)
765  {
767  blockSize = 24;
768  break;
770  blockSize = 48;
771  break;
773  blockSize = 48;
774  break;
776  blockSize = 96;
777  break;
779  blockSize = 96;
780  break;
782  blockSize = 144;
783  break;
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
796 {
797  m_blockSize = GetFecBlockSize (modulationType);
798  m_nrBlocks = GetNrBlocks (burstSize, modulationType);
799  m_paddingBits = (m_nrBlocks * m_blockSize) - (burstSize * 8);
801  NS_ASSERT_MSG (static_cast<uint32_t> (m_nrBlocks * m_blockSize) >= (burstSize * 8), "Size of padding bytes < 0");
802 }
803 
804 uint16_t
806 {
807  // assumed equal to 2 symbols
808  return 2 * GetPsPerSymbol ();
809 }
810 
811 uint16_t
813 {
814  // assumed equal to 2 symbols
815  return 2 * GetPsPerSymbol ();
816 }
817 
818 uint8_t
820 {
821  uint16_t duration = 0;
822  duration = (uint16_t)(GetFrameDuration ().GetSeconds () * 10000);
823  switch (duration)
824  {
825  case 25:
826  {
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  {
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  {
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;
888  return Seconds (10);
889  break;
891  return Seconds (12.5);
892  break;
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
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
951 {
952  m_nfft = nfft;
953 
954 }
955 
956 uint16_t
958 {
959  return m_nfft;
960 
961 }
962 
963 double
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
1001 {
1002  // sampling frequency (Fs), see 8.3.2.2
1003 
1004  return (DoGetSamplingFactor () * GetChannelBandwidth () / 8000) * 8000;
1005 }
1006 
1007 double
1009 {
1010 
1011  return m_g;
1012 }
1013 
1014 void
1016 {
1017  m_g = g;
1018 
1019 }
1020 
1021 void
1023 {
1024  m_txGain = txGain;
1025 }
1026 
1027 void
1029 {
1030  m_rxGain = txRain;
1031 }
1032 
1033 double
1035 {
1036  return m_txGain;
1037 }
1038 
1039 double
1041 {
1042  return m_rxGain;
1043 }
1044 
1045 std::string
1047 {
1049 }
1050 
1051 void
1053 {
1054 
1055  m_snrToBlockErrorRateManager->SetTraceFilePath ((char*) path.c_str ());
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