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 <math.h>
37 NS_LOG_COMPONENT_DEFINE ("SimpleOfdmWimaxPhy");
38 namespace ns3 {
39 
40 NS_OBJECT_ENSURE_REGISTERED (SimpleOfdmWimaxPhy);
41 
43 {
44  static TypeId
45  tid =
46  TypeId ("ns3::SimpleOfdmWimaxPhy").SetParent<WimaxPhy> ()
47 
48  .AddAttribute ("NoiseFigure",
49  "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver.",
50  DoubleValue (5),
52  MakeDoubleChecker<double> ())
53 
54  .AddAttribute ("TxPower",
55  "Transmission power (dB).",
56  DoubleValue (30),
58  MakeDoubleChecker<double> ())
59 
60  .AddAttribute ("G",
61  "This is the ratio of CP time to useful time.",
62  DoubleValue (0.25),
64  MakeDoubleChecker<double> ())
65 
66  .AddAttribute ("TxGain",
67  "Transmission gain (dB).",
68  DoubleValue (0),
70  MakeDoubleChecker<double> ())
71 
72  .AddAttribute ("RxGain",
73  "Reception gain (dB).",
74  DoubleValue (0),
76  MakeDoubleChecker<double> ())
77 
78  .AddAttribute ("Nfft",
79  "FFT size",
80  UintegerValue (256),
82  MakeUintegerChecker<uint16_t> (256, 1024))
83 
84  .AddAttribute ("TraceFilePath",
85  "Path to the directory containing SNR to block error rate files",
86  StringValue (""),
87  MakeStringAccessor (&SimpleOfdmWimaxPhy::GetTraceFilePath,
89  MakeStringChecker ())
90 
91  .AddTraceSource ("Rx", "Receive trace", MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_traceRx))
92 
93  .AddTraceSource ("Tx", "Transmit trace", MakeTraceSourceAccessor (&SimpleOfdmWimaxPhy::m_traceTx))
94 
95  .AddTraceSource ("PhyTxBegin",
96  "Trace source indicating a packet has begun transmitting over the channel medium",
98 
99  .AddTraceSource ("PhyTxEnd",
100  "Trace source indicating a packet has been completely transmitted over the channel",
102 
103  .AddTraceSource ("PhyTxDrop",
104  "Trace source indicating a packet has been dropped by the device during transmission",
106 
107  .AddTraceSource ("PhyRxBegin",
108  "Trace source indicating a packet has begun being received from the channel medium by the device",
110 
111  .AddTraceSource ("PhyRxEnd",
112  "Trace source indicating a packet has been completely received from the channel medium by the device",
114 
115  .AddTraceSource ("PhyRxDrop",
116  "Trace source indicating a packet has been dropped by the device during reception",
118  return tid;
119 }
120 
121 void
123 {
124  m_fecBlockSize = 0;
125  m_nrFecBlocksSent = 0;
126  m_dataRateBpsk12 = 0;
127  m_dataRateQpsk12 = 0;
128  m_dataRateQpsk34 = 0;
129  m_dataRateQam16_12 = 0;
130 
131  m_dataRateQam16_34 = 0;
132  m_dataRateQam64_23 = 0;
133  m_dataRateQam64_34 = 0;
134 
135  m_nrBlocks = 0;
136  m_blockSize = 0;
137  m_paddingBits = 0;
138  m_rxGain = 0;
139  m_txGain = 0;
140  m_nfft = 256;
141  m_g = (double) 1 / 4;
142  SetNrCarriers (192);
143  m_fecBlocks = new std::list<bvec>;
144  m_receivedFecBlocks = new std::list<bvec>;
145  m_currentBurstSize = 0;
146  m_noiseFigure = 5; // dB
147  m_txPower = 30; // dBm
148  SetBandwidth (10000000); // 10Mhz
149  m_nbErroneousBlock = 0;
152 }
153 
155 {
156  m_URNG = CreateObject<UniformRandomVariable> ();
157 
161 }
162 
164 {
168 }
169 
171 {
172 
173 }
174 
175 void
177 {
179 }
180 
181 void
183 {
186 }
187 
188 uint32_t
190 {
192 }
193 
194 void
196 {
198 }
199 
200 double
202 {
203  return m_txPower;
204 }
205 void
207 {
208  m_txPower = txPower;
209 }
210 
211 double
213 {
214  return m_noiseFigure;
215 }
216 void
218 {
219  m_noiseFigure = noiseFigure;
220 }
221 
222 void
224 {
225  delete m_receivedFecBlocks;
226  delete m_fecBlocks;
228  m_fecBlocks = 0;
231 }
232 
233 void
235 {
236  GetChannel ()->Attach (this);
237 }
238 
239 void
241 {
242  OfdmSendParams *o_params = dynamic_cast<OfdmSendParams*> (params);
243  Send (o_params->GetBurst (),
245  o_params->GetDirection ());
246 
247 }
248 
251 {
253 }
254 
255 void
257  WimaxPhy::ModulationType modulationType,
258  uint8_t direction)
259 {
260 
261  if (GetState () != PHY_STATE_TX)
262  {
263  m_currentBurstSize = burst->GetSize ();
264  m_nrFecBlocksSent = 0;
265  m_currentBurst = burst;
266  SetBlockParameters (burst->GetSize (), modulationType);
268  StartSendDummyFecBlock (true, modulationType, direction);
269  m_traceTx (burst);
270  }
271 }
272 
273 void
275  WimaxPhy::ModulationType modulationType,
276  uint8_t direction)
277 {
279  bool isLastFecBlock = 0;
280  if (isFirstBlock)
281  {
282  m_blockTime = GetBlockTransmissionTime (modulationType);
283  }
284 
285  SimpleOfdmWimaxChannel *channel = dynamic_cast<SimpleOfdmWimaxChannel*> (PeekPointer (GetChannel ()));
286 
288  {
289  isLastFecBlock = true;
290  }
291  else
292  {
293  isLastFecBlock = false;
294  }
295  channel->Send (m_blockTime,
297  this,
298  isFirstBlock,
299  isLastFecBlock,
300  GetTxFrequency (),
301  modulationType,
302  direction,
303  m_txPower,
305 
307  Simulator::Schedule (m_blockTime, &SimpleOfdmWimaxPhy::EndSendFecBlock, this, modulationType, direction);
308 }
309 
310 
311 void
313  uint8_t direction)
314 {
317 
319  {
320  // this is the last FEC block of the burst
321  NS_ASSERT_MSG (m_nrRemainingBlocksToSend == 0, "Error while sending a burst");
323  }
324  else
325  {
326  StartSendDummyFecBlock (false,modulationType,direction);
327  }
328 }
329 
330 void
332 {
334 }
335 
336 void
338  bool isFirstBlock,
339  uint64_t frequency,
340  WimaxPhy::ModulationType modulationType,
341  uint8_t direction,
342  double rxPower,
343  Ptr<PacketBurst> burst)
344 {
345 
346  uint8_t drop = 0;
347  double Nwb = -114 + m_noiseFigure + 10 * log (GetBandwidth () / 1000000000.0) / 2.303;
348  double SNR = rxPower - Nwb;
349 
351  double I1 = record->GetI1 ();
352  double I2 = record->GetI2 ();
353 
354  double blockErrorRate = m_URNG->GetValue (I1, I2);
355 
356  double rand = m_URNG->GetValue (0.0, 1.0);
357 
358  if (rand < blockErrorRate)
359  {
360  drop = 1;
361  }
362  if (rand > blockErrorRate)
363  {
364  drop = 0;
365  }
366 
367  if (blockErrorRate == 1.0)
368  {
369  drop = 1;
370  }
371  if (blockErrorRate == 0.0)
372  {
373  drop = 0;
374  }
375  delete record;
376 
377  NS_LOG_INFO ("PHY: Receive rxPower=" << rxPower << ", Nwb=" << Nwb << ", SNR=" << SNR << ", Modulation="
378  << modulationType << ", BlocErrorRate=" << blockErrorRate << ", drop=" << (int) drop);
379 
380  switch (GetState ())
381  {
382  case PHY_STATE_SCANNING:
383  if (frequency == GetScanningFrequency ())
384  {
387  SetSimplex (frequency);
389  }
390  break;
391  case PHY_STATE_IDLE:
392  if (frequency == GetRxFrequency ())
393  {
394  if (isFirstBlock)
395  {
396  NotifyRxBegin (burst);
397  m_receivedFecBlocks->clear ();
399  SetBlockParameters (burstSize, modulationType);
400  m_blockTime = GetBlockTransmissionTime (modulationType);
401  }
402 
405  this,
406  burstSize,
407  modulationType,
408  direction,
409  drop,
410  burst);
411 
413  }
414  break;
415  case PHY_STATE_RX:
416  // drop
417  break;
418  case PHY_STATE_TX:
419  if (IsDuplex () && frequency == GetRxFrequency ())
420  {
421 
422  }
423  break;
424  }
425 }
426 
427 void
429  WimaxPhy::ModulationType modulationType,
430  uint8_t direction,
431  uint8_t drop,
432  Ptr<PacketBurst> burst)
433 {
436 
437  if (drop == true)
438  {
440  }
441 
442  if ((uint32_t) m_nrRecivedFecBlocks * m_blockSize == burstSize * 8 + m_paddingBits)
443  {
444  NotifyRxEnd (burst);
445  if (m_nbErroneousBlock == 0)
446  {
449  this,
450  burst);
451  }
452  else
453  {
454  NotifyRxDrop (burst);
455  }
456  m_nbErroneousBlock = 0;
458  }
459 }
460 
461 void
463 {
464  Ptr<PacketBurst> b = burst->Copy ();
465  GetReceiveCallback () (b);
466  m_traceRx (burst);
467 }
468 
469 bvec
471 {
472  bvec buffer (burst->GetSize () * 8, 0);
473 
474  std::list<Ptr<Packet> > packets = burst->GetPackets ();
475 
476  uint32_t j = 0;
477  for (std::list<Ptr<Packet> >::iterator iter = packets.begin (); iter != packets.end (); ++iter)
478  {
479  Ptr<Packet> packet = *iter;
480  uint8_t *pstart = (uint8_t*) malloc (packet->GetSize ());
481  memset (pstart, 0, packet->GetSize ());
482  packet->CopyData (pstart, packet->GetSize ());
483  bvec temp (8);
484  temp.resize (0, 0);
485  temp.resize (8, 0);
486  for (uint32_t i = 0; i < packet->GetSize (); i++)
487  {
488  for (uint8_t l = 0; l < 8; l++)
489  {
490  temp[l] = (bool)((((uint8_t) pstart[i]) >> (7 - l)) & 0x01);
491  buffer.at (j * 8 + l) = temp[l];
492  }
493  j++;
494  }
495  free (pstart);
496  }
497 
498  return buffer;
499 }
500 
501 /*
502  Converts back the bit buffer (bvec) to the actual burst.
503  Actually creates byte buffer from the bvec and resets the buffer
504  of each packet in the copy of the orifinal burst stored before transmitting.
505  By doing this it preserves the metadata and tags in the packet.
506  Function could also be named DeserializeBurst because actually it
507  copying to the burst's byte buffer.
508  */
511 {
512  uint8_t init[buffer.size () / 8];
513  uint8_t *pstart = init;
514  uint8_t temp;
515  int32_t j = 0;
516  // recreating byte buffer from bit buffer (bvec)
517  for (uint32_t i = 0; i < buffer.size (); i += 8)
518  {
519 
520  temp = 0;
521  for (int l = 0; l < 8; l++)
522  {
523  bool bin = buffer.at (i + l);
524  temp += (uint8_t)(bin * pow (2, (7 - l)));
525  }
526 
527  *(pstart + j) = temp;
528  j++;
529  }
530  uint16_t bufferSize = buffer.size () / 8;
531  uint16_t pos = 0;
532  Ptr<PacketBurst> RecvBurst = Create<PacketBurst> ();
533  while (pos < bufferSize)
534  {
535  uint16_t packetSize = 0;
536  // Get the header type: first bit
537  uint8_t ht = (pstart[pos] >> 7) & 0x01;
538  if (ht == 1)
539  {
540  // BW request header. Size is always 8 bytes
541  packetSize = 6;
542  }
543  else
544  {
545  // Read the size
546  uint8_t Len_MSB = pstart[pos + 1] & 0x07;
547  packetSize = (uint16_t)((uint16_t)(Len_MSB << 8) | (uint16_t)(pstart[pos + 2]));
548  if (packetSize == 0)
549  {
550  break; // padding
551  }
552  }
553 
554  Ptr<Packet> p = Create<Packet> (&(pstart[pos]), packetSize);
555  RecvBurst->AddPacket (p);
556  pos += packetSize;
557  }
558  return RecvBurst;
559 }
560 
561 void
563 {
564 
565  bvec fecBlock (m_blockSize);
566  for (uint32_t i = 0, j = m_nrBlocks; j > 0; i += m_blockSize, j--)
567  {
568 
569  if (j == 1 && m_paddingBits > 0) // last block can be smaller than block size
570  {
571  fecBlock = bvec (buffer.begin () + i, buffer.end ());
572  fecBlock.resize (m_blockSize, 0);
573  }
574  else
575  {
576  fecBlock = bvec (buffer.begin () + i, buffer.begin () + i + m_blockSize);
577  }
578 
579  m_fecBlocks->push_back (fecBlock);
580  }
581 }
582 
583 bvec
585 {
586 
587  bvec buffer (m_blockSize * m_nrBlocks);
588  bvec block (m_blockSize);
589  uint32_t i = 0;
590  for (uint32_t j = 0; j < m_nrBlocks; j++)
591  {
592  bvec tmpRecFecBloc = m_receivedFecBlocks->front ();
593  buffer.insert (buffer.begin () + i, tmpRecFecBloc.begin (), tmpRecFecBloc.end ());
594  m_receivedFecBlocks->pop_front ();
595  i += m_blockSize;
596  }
597  return buffer;
598 }
599 
600 void
602 {
610 }
611 
612 void
614  uint8_t &bitsPerSymbol,
615  double &fecCode) const
616 {
617  switch (modulationType)
618  {
620  bitsPerSymbol = 1;
621  fecCode = (double) 1 / 2;
622  break;
624  bitsPerSymbol = 2;
625  fecCode = (double) 1 / 2;
626  break;
628  bitsPerSymbol = 2;
629  fecCode = (double) 3 / 4;
630  break;
632  bitsPerSymbol = 4;
633  fecCode = (double) 1 / 2;
634  break;
636  bitsPerSymbol = 4;
637  fecCode = (double) 3 / 4;
638  break;
640  bitsPerSymbol = 6;
641  fecCode = (double) 2 / 3;
642  break;
644  bitsPerSymbol = 6;
645  fecCode = 0.75;
646  break;
647  }
648 }
649 
650 uint32_t
652 {
653  uint8_t bitsPerSymbol = 0;
654  double fecCode = 0;
655  GetModulationFecParams (modulationType, bitsPerSymbol, fecCode);
656  double symbolsPerSecond = 1 / GetSymbolDuration ().GetSeconds ();
657  uint16_t bitsTransmittedPerSymbol = (uint16_t)(bitsPerSymbol * GetNrCarriers () * fecCode);
658  // 96, 192, 288, 384, 576, 767 and 864 bits per symbol for the seven modulations, respectively
659 
660  return (uint32_t) symbolsPerSecond * bitsTransmittedPerSymbol;
661 }
662 
663 uint32_t
665 {
666  switch (modulationType)
667  {
669  return m_dataRateBpsk12;
670  break;
672  return m_dataRateQpsk12;
673  break;
675  return m_dataRateQpsk34;
676  break;
678  return m_dataRateQam16_12;
679  break;
681  return m_dataRateQam16_34;
682  break;
684  return m_dataRateQam64_23;
685  break;
687  return m_dataRateQam64_34;
688  break;
689  }
690  NS_FATAL_ERROR ("Invalid modulation type");
691  return 0;
692 }
693 
694 Time
696 {
697  return Seconds ((double) GetFecBlockSize (modulationType) / DoGetDataRate (modulationType));
698 }
699 
700 Time
702 {
703  /*adding 3 extra nano second to cope with the loss of precision problem.
704  the time is internally stored in a 64 bit hence a floating-point time would loss
705  precision, e.g., 0.00001388888888888889 seconds will become 13888888888 femtoseconds.*/
706  return Seconds (DoGetNrSymbols (size, modulationType) * GetSymbolDuration ().GetSeconds ()) + NanoSeconds (3);
707 }
708 
709 uint64_t
711 {
712  Time transmissionTime = Seconds ((double)(GetNrBlocks (size, modulationType) * GetFecBlockSize (modulationType))
713  / DoGetDataRate (modulationType));
714  return (uint64_t) ceil (transmissionTime.GetSeconds () / GetSymbolDuration ().GetSeconds ());
715 }
716 
717 uint64_t
718 SimpleOfdmWimaxPhy::DoGetNrBytes (uint32_t symbols, WimaxPhy::ModulationType modulationType) const
719 {
720  Time transmissionTime = Seconds (symbols * GetSymbolDuration ().GetSeconds ());
721  return (uint64_t) floor ((transmissionTime.GetSeconds () * DoGetDataRate (modulationType)) / 8);
722 }
723 
724 uint32_t
726 {
727  uint32_t blockSize = 0;
728  switch (modulationType)
729  {
731  blockSize = 12;
732  break;
734  blockSize = 24;
735  break;
737  blockSize = 36;
738  break;
740  blockSize = 48;
741  break;
743  blockSize = 72;
744  break;
746  blockSize = 96;
747  break;
749  blockSize = 108;
750  break;
751  default:
752  NS_FATAL_ERROR ("Invalid modulation type");
753  break;
754  }
755  return blockSize * 8; // in bits
756 }
757 
758 // Channel coding block size, Table 215, page 434
759 uint32_t
761 {
762  uint32_t blockSize = 0;
763  switch (modulationType)
764  {
766  blockSize = 24;
767  break;
769  blockSize = 48;
770  break;
772  blockSize = 48;
773  break;
775  blockSize = 96;
776  break;
778  blockSize = 96;
779  break;
781  blockSize = 144;
782  break;
784  blockSize = 144;
785  break;
786  default:
787  NS_FATAL_ERROR ("Invalid modulation type");
788  break;
789  }
790  return blockSize * 8; // in bits
791 }
792 
793 void
795 {
796  m_blockSize = GetFecBlockSize (modulationType);
797  m_nrBlocks = GetNrBlocks (burstSize, modulationType);
798  m_paddingBits = (m_nrBlocks * m_blockSize) - (burstSize * 8);
800  NS_ASSERT_MSG (static_cast<uint32_t> (m_nrBlocks * m_blockSize) >= (burstSize * 8), "Size of padding bytes < 0");
801 }
802 
803 uint16_t
805 {
806  // assumed equal to 2 symbols
807  return 2 * GetPsPerSymbol ();
808 }
809 
810 uint16_t
812 {
813  // assumed equal to 2 symbols
814  return 2 * GetPsPerSymbol ();
815 }
816 
817 uint8_t
819 {
820  uint16_t duration = 0;
821  duration = (uint16_t)(GetFrameDuration ().GetSeconds () * 10000);
822  switch (duration)
823  {
824  case 25:
825  {
827  break;
828  }
829  case 40:
830  {
831  return FRAME_DURATION_4_MS;
832  break;
833  }
834  case 50:
835  {
836  return FRAME_DURATION_5_MS;
837  break;
838  }
839  case 80:
840  {
841  return FRAME_DURATION_8_MS;
842  break;
843  }
844  case 100:
845  {
846  return FRAME_DURATION_10_MS;
847  break;
848  }
849  case 125:
850  {
852  break;
853  }
854  case 200:
855  {
856  return FRAME_DURATION_20_MS;
857  break;
858  }
859  default:
860  {
861  NS_FATAL_ERROR ("Invalid frame duration = " << duration);
862  return 0;
863  }
864  }
865  NS_FATAL_ERROR ("Invalid frame duration = " << duration);
866  return 0;
867 }
868 
869 Time
870 SimpleOfdmWimaxPhy::DoGetFrameDuration (uint8_t frameDurationCode) const
871 {
872  switch (frameDurationCode)
873  {
875  return Seconds (2.5);
876  break;
877  case FRAME_DURATION_4_MS:
878  return Seconds (4);
879  break;
880  case FRAME_DURATION_5_MS:
881  return Seconds (5);
882  break;
883  case FRAME_DURATION_8_MS:
884  return Seconds (8);
885  break;
887  return Seconds (10);
888  break;
890  return Seconds (12.5);
891  break;
893  return Seconds (20);
894  break;
895  default:
896  NS_FATAL_ERROR ("Invalid modulation type");
897  }
898  return Seconds (0);
899 }
900 
901 /*
902  Retruns number of blocks (FEC blocks) the burst will be splitted in.
903  The size of the block is specific for each modulation type.
904  */
905 uint16_t
906 SimpleOfdmWimaxPhy::GetNrBlocks (uint32_t burstSize, WimaxPhy::ModulationType modulationType) const
907 {
908  uint32_t blockSize = GetFecBlockSize (modulationType);
909  uint16_t nrBlocks = (burstSize * 8) / blockSize;
910 
911  if ((burstSize * 8) % blockSize > 0)
912  {
913  nrBlocks += 1;
914  }
915 
916  return nrBlocks;
917 }
918 /*---------------------PHY parameters functions-----------------------*/
919 
920 void
922 {
923  /*Calculations as per section 8.3.2.
924  Currently assuming license-exempt 5 GHz band. For channel bandwidth 20 MHz (Table B.28, page 812) and frame duration 10 ms
925  (Table 232, page 460) i.e, 100 frames per second, sampling frequency is 23040000, symbol (OFDM symbol) duration is
926  1.388888888888889e-05 seconds, PS duration is 1.7361111111111112e-07 seconds. Hence PSs per frame is 57600, symbols per frame
927  is 720 and PSs per symbol is 80. Note that defining these parameters (symbol and PS duration) as Time may not result in exaclty
928  these values therefore lrint has been used (otherwise should be defined as double).
929  For licensed bands set channel bandwidth according to Table B.26, page 810.*/
930 
931  double samplingFrequency = DoGetSamplingFrequency ();
932  Time psDuration = Seconds ((double) 4 / samplingFrequency);
933 
934  SetPsDuration (psDuration);
935  uint16_t psPerFrame = (uint16_t)(GetFrameDuration ().GetSeconds () / psDuration.GetSeconds ());
936  SetPsPerFrame (psPerFrame);
937  double subcarrierSpacing = samplingFrequency / DoGetNfft ();
938  double tb = (double) 1 / subcarrierSpacing; // Tb (useful symbol time)
939  double tg = DoGetGValue () * tb; // Tg (cyclic prefix time)
940  Time symbolDuration = Seconds (tb + tg); // OFDM Symbol Time
941  SetSymbolDuration (symbolDuration);
942  uint16_t psPerSymbol = lrint (symbolDuration.GetSeconds () / psDuration.GetSeconds ());
943  SetPsPerSymbol (psPerSymbol);
944  uint32_t symbolsPerFrame = lrint (GetFrameDuration ().GetSeconds () / symbolDuration.GetSeconds ());
945  SetSymbolsPerFrame (symbolsPerFrame);
946 }
947 
948 void
950 {
951  m_nfft = nfft;
952 
953 }
954 
955 uint16_t
957 {
958  return m_nfft;
959 
960 }
961 
962 double
964 {
965  // sampling factor (n), see Table 213, page 429
966 
967  uint32_t channelBandwidth = GetChannelBandwidth ();
968 
969  if (channelBandwidth % 1750000 == 0)
970  {
971  return (double) 8 / 7;
972  }
973  else if (channelBandwidth % 1500000 == 0)
974  {
975  return (double) 86 / 75;
976  }
977  else if (channelBandwidth % 1250000 == 0)
978  {
979  return (double) 144 / 125;
980  }
981  else if (channelBandwidth % 2750000 == 0)
982  {
983  return (double) 316 / 275;
984  }
985  else if (channelBandwidth % 2000000 == 0)
986  {
987  return (double) 57 / 50;
988  }
989  else
990  {
991  NS_LOG_DEBUG ("Oops may be wrong channel bandwidth for OFDM PHY!");
992  NS_FATAL_ERROR ("wrong channel bandwidth for OFDM PHY");
993  }
994 
995  return (double) 8 / 7;
996 }
997 
998 double
1000 {
1001  // sampling frequency (Fs), see 8.3.2.2
1002 
1003  return (DoGetSamplingFactor () * GetChannelBandwidth () / 8000) * 8000;
1004 }
1005 
1006 double
1008 {
1009 
1010  return m_g;
1011 }
1012 
1013 void
1015 {
1016  m_g = g;
1017 
1018 }
1019 
1020 void
1022 {
1023  m_txGain = txGain;
1024 }
1025 
1026 void
1028 {
1029  m_rxGain = txRain;
1030 }
1031 
1032 double
1034 {
1035  return m_txGain;
1036 }
1037 
1038 double
1040 {
1041  return m_rxGain;
1042 }
1043 
1044 std::string
1046 {
1048 }
1049 
1050 void
1052 {
1053 
1054  m_snrToBlockErrorRateManager->SetTraceFilePath ((char*) path.c_str ());
1056 }
1057 
1058 void
1060 {
1061  m_phyTxBeginTrace (burst);
1062 }
1063 
1064 void
1066 {
1067  m_phyTxEndTrace (burst);
1068 }
1069 
1070 void
1072 {
1073  m_phyTxDropTrace (burst);
1074 }
1075 
1076 void
1078 {
1079  m_phyRxBeginTrace (burst);
1080 }
1081 
1082 void
1084 {
1085  m_phyRxEndTrace (burst);
1086 }
1087 
1088 void
1090 {
1091  m_phyRxDropTrace (burst);
1092 }
1093 
1094 int64_t
1096 {
1097  NS_LOG_FUNCTION (this << stream);
1098  m_URNG->SetStream (stream);
1099  return 1;
1100 }
1101 
1102 } // namespace ns3