A Discrete-Event Network Simulator
API
wifi-spectrum-value-helper.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 CTTC
4  * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
5  * Copyright (c) 2017 Orange Labs
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation;
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * Authors: Nicola Baldo <nbaldo@cttc.es>
21  * Giuseppe Piro <g.piro@poliba.it>
22  * Rediet <getachew.redieteab@orange.com>
23  */
24 
25 #include <map>
26 #include <cmath>
28 #include "ns3/log.h"
29 #include "ns3/fatal-error.h"
30 #include "ns3/assert.h"
31 
32 namespace ns3 {
33 
34 NS_LOG_COMPONENT_DEFINE ("WifiSpectrumValueHelper");
35 
38 {
46  WifiSpectrumModelId (uint32_t f, uint16_t w, double b, uint16_t g);
47  uint32_t m_centerFrequency;
48  uint16_t m_channelWidth;
49  double m_bandBandwidth;
50  uint16_t m_guardBandwidth;
51 };
52 
53 WifiSpectrumModelId::WifiSpectrumModelId (uint32_t f, uint16_t w, double b, uint16_t g)
54  : m_centerFrequency (f),
55  m_channelWidth (w),
56  m_bandBandwidth (b),
57  m_guardBandwidth (g)
58 {
59  NS_LOG_FUNCTION (this << f << w << b << g);
60 }
61 
68 bool
70 {
71  return ( (a.m_centerFrequency < b.m_centerFrequency)
73  && (a.m_channelWidth < b.m_channelWidth))
75  && (a.m_channelWidth == b.m_channelWidth)
76  && (a.m_bandBandwidth < b.m_bandBandwidth)) // to cover coexistence of 11ax with legacy case
78  && (a.m_channelWidth == b.m_channelWidth)
80  && (a.m_guardBandwidth < b.m_guardBandwidth))); // to cover 2.4 GHz case, where DSSS coexists with OFDM
81 }
82 
83 static std::map<WifiSpectrumModelId, Ptr<SpectrumModel> > g_wifiSpectrumModelMap;
84 
86 WifiSpectrumValueHelper::GetSpectrumModel (uint32_t centerFrequency, uint16_t channelWidth, uint32_t bandBandwidth, uint16_t guardBandwidth)
87 {
88  NS_LOG_FUNCTION (centerFrequency << channelWidth << bandBandwidth << guardBandwidth);
90  WifiSpectrumModelId key (centerFrequency, channelWidth, bandBandwidth, guardBandwidth);
91  std::map<WifiSpectrumModelId, Ptr<SpectrumModel> >::iterator it = g_wifiSpectrumModelMap.find (key);
92  if (it != g_wifiSpectrumModelMap.end ())
93  {
94  ret = it->second;
95  }
96  else
97  {
98  Bands bands;
99  double centerFrequencyHz = centerFrequency * 1e6;
100  double bandwidth = (channelWidth + (2.0 * guardBandwidth)) * 1e6;
101  // For OFDM, the center subcarrier is null (at center frequency)
102  uint32_t numBands = static_cast<uint32_t> ((bandwidth / bandBandwidth) + 0.5);
103  NS_ASSERT (numBands > 0);
104  if (numBands % 2 == 0)
105  {
106  // round up to the nearest odd number of subbands so that bands
107  // are symmetric around center frequency
108  numBands += 1;
109  }
110  NS_ASSERT_MSG (numBands % 2 == 1, "Number of bands should be odd");
111  NS_LOG_DEBUG ("Num bands " << numBands << " band bandwidth " << bandBandwidth);
112  // lay down numBands/2 bands symmetrically around center frequency
113  // and place an additional band at center frequency
114  double startingFrequencyHz = centerFrequencyHz - (numBands / 2 * bandBandwidth) - bandBandwidth / 2;
115  for (size_t i = 0; i < numBands; i++)
116  {
117  BandInfo info;
118  double f = startingFrequencyHz + (i * bandBandwidth);
119  info.fl = f;
120  f += bandBandwidth / 2;
121  info.fc = f;
122  f += bandBandwidth / 2;
123  info.fh = f;
124  NS_LOG_DEBUG ("creating band " << i << " (" << info.fl << ":" << info.fc << ":" << info.fh << ")");
125  bands.push_back (info);
126  }
127  ret = Create<SpectrumModel> (bands);
128  g_wifiSpectrumModelMap.insert (std::pair<WifiSpectrumModelId, Ptr<SpectrumModel> > (key, ret));
129  }
130  NS_LOG_LOGIC ("returning SpectrumModel::GetUid () == " << ret->GetUid ());
131  return ret;
132 }
133 
134 // Power allocated to 71 center subbands out of 135 total subbands in the band
136 WifiSpectrumValueHelper::CreateDsssTxPowerSpectralDensity (uint32_t centerFrequency, double txPowerW, uint16_t guardBandwidth)
137 {
138  NS_LOG_FUNCTION (centerFrequency << txPowerW << +guardBandwidth);
139  uint16_t channelWidth = 22; // DSSS channels are 22 MHz wide
140  uint32_t bandBandwidth = 312500;
141  Ptr<SpectrumValue> c = Create<SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
142  Values::iterator vit = c->ValuesBegin ();
143  Bands::const_iterator bit = c->ConstBandsBegin ();
144  uint32_t nGuardBands = static_cast<uint32_t> (((2 * guardBandwidth * 1e6) / bandBandwidth) + 0.5);
145  uint32_t nAllocatedBands = static_cast<uint32_t> (((channelWidth * 1e6) / bandBandwidth) + 0.5);
146  NS_ASSERT (c->GetSpectrumModel ()->GetNumBands () == (nAllocatedBands + nGuardBands + 1));
147  // Evenly spread power across 22 MHz
148  double txPowerPerBand = txPowerW / nAllocatedBands;
149  for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++, bit++)
150  {
151  if ((i >= (nGuardBands / 2)) && (i <= ((nGuardBands / 2) + nAllocatedBands - 1)))
152  {
153  *vit = txPowerPerBand / (bit->fh - bit->fl);
154  }
155  }
156  return c;
157 }
158 
160 WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity (uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth)
161 {
162  NS_LOG_FUNCTION (centerFrequency << channelWidth << txPowerW << guardBandwidth);
163  uint32_t bandBandwidth = 0;
164  uint32_t innerSlopeWidth = 0;
165  switch (channelWidth)
166  {
167  case 20:
168  bandBandwidth = 312500;
169  innerSlopeWidth = static_cast<uint32_t> ((2e6 / bandBandwidth) + 0.5); // [-11;-9] & [9;11]
170  break;
171  case 10:
172  bandBandwidth = 156250;
173  innerSlopeWidth = static_cast<uint32_t> ((1e6 / bandBandwidth) + 0.5); // [-5.5;-4.5] & [4.5;5.5]
174  break;
175  case 5:
176  bandBandwidth = 78125;
177  innerSlopeWidth = static_cast<uint32_t> ((5e5 / bandBandwidth) + 0.5); // [-2.75;-2.5] & [2.5;2.75]
178  break;
179  default:
180  NS_FATAL_ERROR ("Channel width " << channelWidth << " should be correctly set.");
181  return 0;
182  }
183 
184  Ptr<SpectrumValue> c = Create<SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
185  uint32_t nGuardBands = static_cast<uint32_t> (((2 * guardBandwidth * 1e6) / bandBandwidth) + 0.5);
186  uint32_t nAllocatedBands = static_cast<uint32_t> (((channelWidth * 1e6) / bandBandwidth) + 0.5);
187  NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == (nAllocatedBands + nGuardBands + 1), "Unexpected number of bands " << c->GetSpectrumModel ()->GetNumBands ());
188  // 52 subcarriers (48 data + 4 pilot)
189  // skip guard band and 6 subbands, then place power in 26 subbands, then
190  // skip the center subband, then place power in 26 subbands, then skip
191  // the final 6 subbands and the guard band.
192  double txPowerPerBandW = txPowerW / 52;
193  NS_LOG_DEBUG ("Power per band " << txPowerPerBandW << "W");
194  uint32_t start1 = (nGuardBands / 2) + 6;
195  uint32_t stop1 = start1 + 26 - 1;
196  uint32_t start2 = stop1 + 2;
197  uint32_t stop2 = start2 + 26 - 1;
198 
199  //Build transmit spectrum mask
200  std::vector <StartStop> subBands;
201  subBands.push_back (std::make_pair (start1, stop1));
202  subBands.push_back (std::make_pair (start2, stop2));
203  StartStop maskBand (0, nAllocatedBands + nGuardBands);
204  CreateSpectrumMaskForOfdm (c, subBands, maskBand,
205  txPowerPerBandW, nGuardBands,
206  innerSlopeWidth, -40.0); // -40 dBr for the outermost points of the standard defined mask for 11a, 11g and downclocked versions of 11a for 11p
207  NormalizeSpectrumMask (c, txPowerW);
208  NS_ASSERT_MSG (std::abs (txPowerW - Integral (*c)) < 1e-6, "Power allocation failed");
209  return c;
210 }
211 
213 WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity (uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth)
214 {
215  NS_LOG_FUNCTION (centerFrequency << channelWidth << txPowerW << guardBandwidth);
216  uint32_t bandBandwidth = 312500;
217  Ptr<SpectrumValue> c = Create<SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
218  uint32_t nGuardBands = static_cast<uint32_t> (((2 * guardBandwidth * 1e6) / bandBandwidth) + 0.5);
219  uint32_t nAllocatedBands = static_cast<uint32_t> (((channelWidth * 1e6) / bandBandwidth) + 0.5);
220  NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == (nAllocatedBands + nGuardBands + 1), "Unexpected number of bands " << c->GetSpectrumModel ()->GetNumBands ());
221  double txPowerPerBandW = 0.0;
222  // skip the guard band and 4 subbands, then place power in 28 subbands, then
223  // skip the center subband, then place power in 28 subbands, then skip
224  // the final 4 subbands and the guard band.
225  // Repeat for each 20 MHz band.
226  uint32_t start1 = (nGuardBands / 2) + 4;
227  uint32_t stop1 = start1 + 28 - 1;
228  uint32_t start2 = stop1 + 2;
229  uint32_t stop2 = start2 + 28 - 1;
230  uint32_t start3 = stop2 + (2 * 4);
231  uint32_t stop3 = start3 + 28 - 1;
232  uint32_t start4 = stop3 + 2;
233  uint32_t stop4 = start4 + 28 - 1;
234  uint32_t start5 = stop4 + (2 * 4);
235  uint32_t stop5 = start5 + 28 - 1;
236  uint32_t start6 = stop5 + 2;
237  uint32_t stop6 = start6 + 28 - 1;
238  uint32_t start7 = stop6 + (2 * 4);
239  uint32_t stop7 = start7 + 28 - 1;
240  uint32_t start8 = stop7 + 2;
241  uint32_t stop8 = start8 + 28 - 1;
242  uint32_t start9 = stop8 + (2 * 4);
243  uint32_t stop9 = start9 + 28 - 1;
244  uint32_t start10 = stop9 + 2;
245  uint32_t stop10 = start10 + 28 - 1;
246  uint32_t start11 = stop10 + (2 * 4);
247  uint32_t stop11 = start11 + 28 - 1;
248  uint32_t start12 = stop11 + 2;
249  uint32_t stop12 = start12 + 28 - 1;
250  uint32_t start13 = stop12 + (2 * 4);
251  uint32_t stop13 = start13 + 28 - 1;
252  uint32_t start14 = stop13 + 2;
253  uint32_t stop14 = start14 + 28 - 1;
254  uint32_t start15 = stop14 + (2 * 4);
255  uint32_t stop15 = start15 + 28 - 1;
256  uint32_t start16 = stop15 + 2;
257  uint32_t stop16 = start16 + 28 - 1;
258  //Prepare spectrum mask specific variables
259  uint32_t innerSlopeWidth = static_cast<uint32_t> ((2e6 / bandBandwidth) + 0.5); //size in number of subcarriers of the 0dBr<->20dBr slope (2MHz for HT/VHT)
260  double lowestPointDbr = (centerFrequency >= 5000) ?
261  -40.0 : //if 5 GHz band
262  -45.0; //if 2.4 GHz band
263  std::vector <StartStop> subBands; //list of data/pilot-containing subBands (sent at 0dBr)
264  StartStop maskBand (0, nAllocatedBands + nGuardBands);
265  switch (channelWidth)
266  {
267  case 20:
268  // 56 subcarriers (52 data + 4 pilot)
269  txPowerPerBandW = txPowerW / 56;
270  subBands.push_back (std::make_pair (start1, stop1));
271  subBands.push_back (std::make_pair (start2, stop2));
272  break;
273  case 40:
274  // 112 subcarriers (104 data + 8 pilot)
275  // possible alternative: 114 subcarriers (108 data + 6 pilot)
276  txPowerPerBandW = txPowerW / 112;
277  subBands.push_back (std::make_pair (start1, stop1));
278  subBands.push_back (std::make_pair (start2, stop2));
279  subBands.push_back (std::make_pair (start3, stop3));
280  subBands.push_back (std::make_pair (start4, stop4));
281  break;
282  case 80:
283  // 224 subcarriers (208 data + 16 pilot)
284  // possible alternative: 242 subcarriers (234 data + 8 pilot)
285  txPowerPerBandW = txPowerW / 224;
286  NS_ASSERT (lowestPointDbr == -40.0);
287  subBands.push_back (std::make_pair (start1, stop1));
288  subBands.push_back (std::make_pair (start2, stop2));
289  subBands.push_back (std::make_pair (start3, stop3));
290  subBands.push_back (std::make_pair (start4, stop4));
291  subBands.push_back (std::make_pair (start5, stop5));
292  subBands.push_back (std::make_pair (start6, stop6));
293  subBands.push_back (std::make_pair (start7, stop7));
294  subBands.push_back (std::make_pair (start8, stop8));
295  break;
296  case 160:
297  // 448 subcarriers (416 data + 32 pilot)
298  // possible alternative: 484 subcarriers (468 data + 16 pilot)
299  txPowerPerBandW = txPowerW / 448;
300  NS_ASSERT (lowestPointDbr == -40.0);
301  subBands.push_back (std::make_pair (start1, stop1));
302  subBands.push_back (std::make_pair (start2, stop2));
303  subBands.push_back (std::make_pair (start3, stop3));
304  subBands.push_back (std::make_pair (start4, stop4));
305  subBands.push_back (std::make_pair (start5, stop5));
306  subBands.push_back (std::make_pair (start6, stop6));
307  subBands.push_back (std::make_pair (start7, stop7));
308  subBands.push_back (std::make_pair (start8, stop8));
309  subBands.push_back (std::make_pair (start9, stop9));
310  subBands.push_back (std::make_pair (start10, stop10));
311  subBands.push_back (std::make_pair (start11, stop11));
312  subBands.push_back (std::make_pair (start12, stop12));
313  subBands.push_back (std::make_pair (start13, stop13));
314  subBands.push_back (std::make_pair (start14, stop14));
315  subBands.push_back (std::make_pair (start15, stop15));
316  subBands.push_back (std::make_pair (start16, stop16));
317  break;
318  }
319 
320  //Build transmit spectrum mask
321  CreateSpectrumMaskForOfdm (c, subBands, maskBand,
322  txPowerPerBandW, nGuardBands,
323  innerSlopeWidth, lowestPointDbr);
324  NormalizeSpectrumMask (c, txPowerW);
325  NS_ASSERT_MSG (std::abs (txPowerW - Integral (*c)) < 1e-6, "Power allocation failed");
326  return c;
327 }
328 
330 WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth)
331 {
332  NS_LOG_FUNCTION (centerFrequency << channelWidth << txPowerW << guardBandwidth);
333  uint32_t bandBandwidth = 78125;
334  Ptr<SpectrumValue> c = Create<SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
335  uint32_t nGuardBands = static_cast<uint32_t> (((2 * guardBandwidth * 1e6) / bandBandwidth) + 0.5);
336  uint32_t nAllocatedBands = static_cast<uint32_t> (((channelWidth * 1e6) / bandBandwidth) + 0.5);
337  NS_ASSERT_MSG (c->GetSpectrumModel ()->GetNumBands () == (nAllocatedBands + nGuardBands + 1), "Unexpected number of bands " << c->GetSpectrumModel ()->GetNumBands ());
338  double txPowerPerBandW = 0.0;
339  uint32_t start1;
340  uint32_t stop1;
341  uint32_t start2;
342  uint32_t stop2;
343  uint32_t start3;
344  uint32_t stop3;
345  uint32_t start4;
346  uint32_t stop4;
347  //Prepare spectrum mask specific variables
348  uint32_t innerSlopeWidth = static_cast<uint32_t> ((1e6 / bandBandwidth) + 0.5); //size in number of subcarriers of the 0dBr<->20dBr slope
349  double lowestPointDbr = (centerFrequency >= 5000) ?
350  -40.0 : //if 5 GHz band
351  -45.0; //if 2.4 GHz band
352  std::vector <StartStop> subBands; //list of data/pilot-containing subBands (sent at 0dBr)
353  StartStop maskBand (0, nAllocatedBands + nGuardBands);
354  switch (channelWidth)
355  {
356  case 20:
357  // 242 subcarriers (234 data + 8 pilot)
358  txPowerPerBandW = txPowerW / 242;
359  innerSlopeWidth = static_cast<uint32_t> ((5e5 / bandBandwidth) + 0.5); // [-10.25;-9.75] & [9.75;10.25]
360  // skip the guard band and 6 subbands, then place power in 121 subbands, then
361  // skip 3 DC, then place power in 121 subbands, then skip
362  // the final 5 subbands and the guard band.
363  start1 = (nGuardBands / 2) + 6;
364  stop1 = start1 + 121 - 1;
365  start2 = stop1 + 4;
366  stop2 = start2 + 121 - 1;
367  subBands.push_back (std::make_pair (start1, stop1));
368  subBands.push_back (std::make_pair (start2, stop2));
369  break;
370  case 40:
371  // 484 subcarriers (468 data + 16 pilot)
372  txPowerPerBandW = txPowerW / 484;
373  // skip the guard band and 12 subbands, then place power in 242 subbands, then
374  // skip 5 DC, then place power in 242 subbands, then skip
375  // the final 11 subbands and the guard band.
376  start1 = (nGuardBands / 2) + 12;
377  stop1 = start1 + 242 - 1;
378  start2 = stop1 + 6;
379  stop2 = start2 + 242 - 1;
380  subBands.push_back (std::make_pair (start1, stop1));
381  subBands.push_back (std::make_pair (start2, stop2));
382  break;
383  case 80:
384  // 996 subcarriers (980 data + 16 pilot)
385  txPowerPerBandW = txPowerW / 996;
386  // skip the guard band and 12 subbands, then place power in 498 subbands, then
387  // skip 5 DC, then place power in 498 subbands, then skip
388  // the final 11 subbands and the guard band.
389  start1 = (nGuardBands / 2) + 12;
390  stop1 = start1 + 498 - 1;
391  start2 = stop1 + 6;
392  stop2 = start2 + 498 - 1;
393  subBands.push_back (std::make_pair (start1, stop1));
394  subBands.push_back (std::make_pair (start2, stop2));
395  break;
396  case 160:
397  // 2 x 996 subcarriers (2 x 80 MHZ bands)
398  txPowerPerBandW = txPowerW / (2 * 996);
399  start1 = (nGuardBands / 2) + 12;
400  stop1 = start1 + 498 - 1;
401  start2 = stop1 + 6;
402  stop2 = start2 + 498 - 1;
403  start3 = stop2 + (2 * 12);
404  stop3 = start3 + 498 - 1;
405  start4 = stop3 + 6;
406  stop4 = start4 + 498 - 1;
407  subBands.push_back (std::make_pair (start1, stop1));
408  subBands.push_back (std::make_pair (start2, stop2));
409  subBands.push_back (std::make_pair (start3, stop3));
410  subBands.push_back (std::make_pair (start4, stop4));
411  break;
412  default:
413  NS_FATAL_ERROR ("ChannelWidth " << channelWidth << " unsupported");
414  break;
415  }
416 
417  //Build transmit spectrum mask
418  CreateSpectrumMaskForOfdm (c, subBands, maskBand,
419  txPowerPerBandW, nGuardBands,
420  innerSlopeWidth, lowestPointDbr);
421  NormalizeSpectrumMask (c, txPowerW);
422  NS_ASSERT_MSG (std::abs (txPowerW - Integral (*c)) < 1e-6, "Power allocation failed");
423  return c;
424 }
425 
427 WifiSpectrumValueHelper::CreateNoisePowerSpectralDensity (uint32_t centerFrequency, uint16_t channelWidth, uint32_t bandBandwidth, double noiseFigure, uint16_t guardBandwidth)
428 {
429  Ptr<SpectrumModel> model = GetSpectrumModel (centerFrequency, channelWidth, bandBandwidth, guardBandwidth);
430  return CreateNoisePowerSpectralDensity (noiseFigure, model);
431 }
432 
435 {
436  NS_LOG_FUNCTION (noiseFigureDb << spectrumModel);
437 
438  // see "LTE - From theory to practice"
439  // Section 22.4.4.2 Thermal Noise and Receiver Noise Figure
440  const double kT_dBm_Hz = -174.0; // dBm/Hz
441  double kT_W_Hz = DbmToW (kT_dBm_Hz);
442  double noiseFigureLinear = std::pow (10.0, noiseFigureDb / 10.0);
443  double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
444 
445  Ptr<SpectrumValue> noisePsd = Create <SpectrumValue> (spectrumModel);
446  (*noisePsd) = noisePowerSpectralDensity;
447  NS_LOG_INFO ("NoisePowerSpectralDensity has integrated power of " << Integral (*noisePsd));
448  return noisePsd;
449 }
450 
452 WifiSpectrumValueHelper::CreateRfFilter (uint32_t centerFrequency, uint16_t channelWidth, uint32_t bandBandwidth, uint16_t guardBandwidth)
453 {
454  NS_LOG_FUNCTION (centerFrequency << channelWidth << bandBandwidth << guardBandwidth);
455  Ptr<SpectrumValue> c = Create <SpectrumValue> (GetSpectrumModel (centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
456  size_t numBands = c->GetSpectrumModel ()->GetNumBands ();
457  Bands::const_iterator bit = c->ConstBandsBegin ();
458  Values::iterator vit = c->ValuesBegin ();
459  size_t numBandsInFilter = static_cast<size_t> (channelWidth * 1e6 / bandBandwidth);
460  if (channelWidth % bandBandwidth != 0)
461  {
462  numBandsInFilter += 1;
463  }
464  NS_LOG_INFO ("Num bands in filter: " << numBandsInFilter);
465  // Set the value of the filter to 1 for the center-most numBandsInFilter
466  NS_ASSERT_MSG ((numBandsInFilter % 2 == 1) && (numBands % 2 == 1), "Should have odd number of bands");
467  size_t startIndex = (numBands - numBandsInFilter) / 2;
468  vit += startIndex;
469  bit += startIndex;
470  for (size_t i = startIndex; i < startIndex + numBandsInFilter; i++, vit++, bit++)
471  {
472  *vit = 1;
473  }
474  NS_LOG_LOGIC ("Added subbands " << startIndex << " to " << startIndex + numBandsInFilter << " to filter");
475  return c;
476 }
477 
478 void
479 WifiSpectrumValueHelper::CreateSpectrumMaskForOfdm (Ptr<SpectrumValue> c, std::vector <StartStop> allocatedSubBands, StartStop maskBand,
480  double txPowerPerBandW, uint32_t nGuardBands,
481  uint32_t innerSlopeWidth, double lowestPointDbr)
482 {
483  NS_LOG_FUNCTION (c << allocatedSubBands.front ().first << allocatedSubBands.back ().second << maskBand.first << maskBand.second << txPowerPerBandW << nGuardBands << innerSlopeWidth << lowestPointDbr);
484  uint32_t numSubBands = allocatedSubBands.size ();
485  uint32_t numBands = c->GetSpectrumModel ()->GetNumBands ();
486  uint32_t numMaskBands = maskBand.second - maskBand.first + 1;
487  NS_ASSERT (numSubBands && numBands && numMaskBands);
488  NS_LOG_LOGIC ("Power per band " << txPowerPerBandW << "W");
489 
490  //Different power levels
491  double txPowerRefDbm = (10.0 * std::log10 (txPowerPerBandW * 1000.0));
492  double txPowerInnerBandMinDbm = txPowerRefDbm - 20;
493  double txPowerMiddleBandMinDbm = txPowerRefDbm - 28;
494  double txPowerOuterBandMinDbm = txPowerRefDbm + lowestPointDbr; //TODO also take into account dBm/MHz constraints
495 
496  //Different widths (in number of bands)
497  uint32_t outerSlopeWidth = nGuardBands / 4; // nGuardBands is the total left+right guard band. The left/right outer part is half of the left/right guard band.
498  uint32_t middleSlopeWidth = outerSlopeWidth - (innerSlopeWidth / 2);
499  StartStop outerBandLeft (maskBand.first, //to handle cases where allocated channel is under WifiPhy configured channel width.
500  maskBand.first + outerSlopeWidth - 1);
501  StartStop middleBandLeft (outerBandLeft.second + 1,
502  outerBandLeft.second + middleSlopeWidth);
503  StartStop innerBandLeft (allocatedSubBands.front ().first - innerSlopeWidth,
504  allocatedSubBands.front ().first - 1); //better to place slope based on allocated subcarriers
505  StartStop flatJunctionLeft (middleBandLeft.second + 1,
506  innerBandLeft.first - 1); //in order to handle shift due to guard subcarriers
507  StartStop outerBandRight (maskBand.second - outerSlopeWidth + 1,
508  maskBand.second); //start from outer edge to be able to compute flat junction width
509  StartStop middleBandRight (outerBandRight.first - middleSlopeWidth,
510  outerBandRight.first - 1);
511  StartStop innerBandRight (allocatedSubBands.back ().second + 1,
512  allocatedSubBands.back ().second + innerSlopeWidth);
513  StartStop flatJunctionRight (innerBandRight.second + 1,
514  middleBandRight.first - 1);
515  NS_LOG_DEBUG ("outerBandLeft=[" << outerBandLeft.first << ";" << outerBandLeft.second << "] " <<
516  "middleBandLeft=[" << middleBandLeft.first << ";" << middleBandLeft.second << "] " <<
517  "flatJunctionLeft=[" << flatJunctionLeft.first << ";" << flatJunctionLeft.second << "] " <<
518  "innerBandLeft=[" << innerBandLeft.first << ";" << innerBandLeft.second << "] " <<
519  "subBands=[" << allocatedSubBands.front ().first << ";" << allocatedSubBands.back ().second << "] " <<
520  "innerBandRight=[" << innerBandRight.first << ";" << innerBandRight.second << "] " <<
521  "flatJunctionRight=[" << flatJunctionRight.first << ";" << flatJunctionRight.second << "] " <<
522  "middleBandRight=[" << middleBandRight.first << ";" << middleBandRight.second << "] " <<
523  "outerBandRight=[" << outerBandRight.first << ";" << outerBandRight.second << "] ");
524  NS_ASSERT (numMaskBands == ((allocatedSubBands.back ().second - allocatedSubBands.front ().first + 1) //equivalent to allocatedBand (includes notches and DC)
525  + 2 * (innerSlopeWidth + middleSlopeWidth + outerSlopeWidth)
526  + (flatJunctionLeft.second - flatJunctionLeft.first + 1) //flat junctions
527  + (flatJunctionRight.second - flatJunctionRight.first + 1)));
528 
529  //Different slopes
530  double innerSlope = 20.0 / innerSlopeWidth; //0 to 20dBr
531  double middleSlope = 8.0 / middleSlopeWidth; //20 to 28dBr
532  double outerSlope = (txPowerMiddleBandMinDbm - txPowerOuterBandMinDbm) / outerSlopeWidth;
533 
534  //Build spectrum mask
535  Values::iterator vit = c->ValuesBegin ();
536  Bands::const_iterator bit = c->ConstBandsBegin ();
537  double txPowerW = 0.0;
538  for (size_t i = 0; i < numBands; i++, vit++, bit++)
539  {
540  if (i < maskBand.first || i > maskBand.second) //outside the spectrum mask
541  {
542  txPowerW = 0.0;
543  }
544  else if (i <= outerBandLeft.second && i >= outerBandLeft.first) //better to put greater first (less computation)
545  {
546  txPowerW = DbmToW (txPowerOuterBandMinDbm + ((i - outerBandLeft.first) * outerSlope));
547  }
548  else if (i <= middleBandLeft.second && i >= middleBandLeft.first)
549  {
550  txPowerW = DbmToW (txPowerMiddleBandMinDbm + ((i - middleBandLeft.first) * middleSlope));
551  }
552  else if (i <= flatJunctionLeft.second && i >= flatJunctionLeft.first)
553  {
554  txPowerW = DbmToW (txPowerInnerBandMinDbm);
555  }
556  else if (i <= innerBandLeft.second && i >= innerBandLeft.first)
557  {
558  txPowerW = DbmToW (txPowerInnerBandMinDbm + ((i - innerBandLeft.first) * innerSlope));
559  }
560  else if (i <= allocatedSubBands.back ().second && i >= allocatedSubBands.front ().first) //roughly in allocated band
561  {
562  bool insideSubBand = false;
563  for (uint32_t j = 0; !insideSubBand && j < numSubBands; j++) //continue until inside a sub-band
564  {
565  insideSubBand = (i <= allocatedSubBands[j].second) && (i >= allocatedSubBands[j].first);
566  }
567  if (insideSubBand)
568  {
569  txPowerW = txPowerPerBandW;
570  }
571  else
572  {
573  txPowerW = DbmToW (txPowerInnerBandMinDbm); //consider that nulled as much as possible inband but power leakage -> -20dBr
574  }
575  }
576  else if (i <= innerBandRight.second && i >= innerBandRight.first)
577  {
578  txPowerW = DbmToW (txPowerRefDbm - ((i - innerBandRight.first + 1) * innerSlope)); // +1 so as to be symmetric with left slope
579  }
580  else if (i <= flatJunctionRight.second && i >= flatJunctionRight.first)
581  {
582  txPowerW = DbmToW (txPowerInnerBandMinDbm);
583  }
584  else if (i <= middleBandRight.second && i >= middleBandRight.first)
585  {
586  txPowerW = DbmToW (txPowerInnerBandMinDbm - ((i - middleBandRight.first + 1) * middleSlope)); // +1 so as to be symmetric with left slope
587  }
588  else if (i <= outerBandRight.second && i >= outerBandRight.first)
589  {
590  txPowerW = DbmToW (txPowerMiddleBandMinDbm - ((i - outerBandRight.first + 1) * outerSlope)); // +1 so as to be symmetric with left slope
591  }
592  else
593  {
594  NS_FATAL_ERROR ("Should have handled all cases");
595  }
596  double txPowerDbr = 10 * std::log10 (txPowerW / txPowerPerBandW);
597  NS_LOG_LOGIC (uint32_t (i) << " -> " << txPowerDbr);
598  *vit = txPowerW / (bit->fh - bit->fl);
599  }
600  NS_LOG_INFO ("Added signal power to subbands " << allocatedSubBands.front ().first << "-" << allocatedSubBands.back ().second);
601 }
602 
603 void
605 {
606  NS_LOG_FUNCTION (c << txPowerW);
607  //Normalize power so that total signal power equals transmit power
608  double currentTxPowerW = Integral (*c);
609  double normalizationRatio = currentTxPowerW / txPowerW;
610  NS_LOG_LOGIC ("Current power: " << currentTxPowerW << "W vs expected power: " << txPowerW << "W" <<
611  " -> ratio (C/E) = " << normalizationRatio);
612  Values::iterator vit = c->ValuesBegin ();
613  for (size_t i = 0; i < c->GetSpectrumModel ()->GetNumBands (); i++, vit++)
614  {
615  *vit = (*vit) / normalizationRatio;
616  }
617 }
618 
619 double
621 {
622  return std::pow (10.0, 0.1 * (dBm - 30.0));
623 }
624 
626 
628 {
629 }
630 
632 {
633 }
634 
639 {
640 public:
642  {
643  Bands bands;
644  for (int i = -4; i < 13 + 7; i++)
645  {
646  BandInfo bi;
647  bi.fl = 2407.0e6 + i * 5.0e6;
648  bi.fh = 2407.0e6 + (i + 1) * 5.0e6;
649  bi.fc = (bi.fl + bi.fh) / 2;
650  bands.push_back (bi);
651  }
652  g_WifiSpectrumModel5Mhz = Create<SpectrumModel> (bands);
653  }
655 
656 
657 
658 Ptr<SpectrumValue>
660 {
661  Ptr<SpectrumValue> c = Create <SpectrumValue> (g_WifiSpectrumModel5Mhz);
662  (*c) = v;
663  return c;
664 }
665 
666 
669 {
670  Ptr<SpectrumValue> txPsd = Create <SpectrumValue> (g_WifiSpectrumModel5Mhz);
671 
672  // since the spectrum model has a resolution of 5 MHz, we model
673  // the transmitted signal with a constant density over a 20MHz
674  // bandwidth centered on the center frequency of the channel. The
675  // transmission power outside the transmission power density is
676  // calculated considering the transmit spectrum mask, see IEEE
677  // Std. 802.11-2007, Annex I
678 
679  double txPowerDensity = txPower / 20e6;
680 
681  NS_ASSERT (channel >= 1);
682  NS_ASSERT (channel <= 13);
683 
684  (*txPsd)[channel - 1] = txPowerDensity * 1e-4; // -40dB
685  (*txPsd)[channel] = txPowerDensity * 1e-4; // -40dB
686  (*txPsd)[channel + 1] = txPowerDensity * 0.0015849; // -28dB
687  (*txPsd)[channel + 2] = txPowerDensity * 0.0015849; // -28dB
688  (*txPsd)[channel + 3] = txPowerDensity;
689  (*txPsd)[channel + 4] = txPowerDensity;
690  (*txPsd)[channel + 5] = txPowerDensity;
691  (*txPsd)[channel + 6] = txPowerDensity;
692  (*txPsd)[channel + 7] = txPowerDensity * 0.0015849; // -28dB
693  (*txPsd)[channel + 8] = txPowerDensity * 0.0015849; // -28dB
694  (*txPsd)[channel + 9] = txPowerDensity * 1e-4; // -40dB
695  (*txPsd)[channel + 10] = txPowerDensity * 1e-4; // -40dB
696 
697  return txPsd;
698 }
699 
700 
703 {
704  Ptr<SpectrumValue> rf = Create <SpectrumValue> (g_WifiSpectrumModel5Mhz);
705 
706  NS_ASSERT (channel >= 1);
707  NS_ASSERT (channel <= 13);
708 
709  (*rf)[channel + 3] = 1;
710  (*rf)[channel + 4] = 1;
711  (*rf)[channel + 5] = 1;
712  (*rf)[channel + 6] = 1;
713 
714  return rf;
715 }
716 
717 
718 } // namespace ns3
size_t GetNumBands() const
static std::map< WifiSpectrumModelId, Ptr< SpectrumModel > > g_wifiSpectrumModelMap
static initializer for the class
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
static class ns3::WifiSpectrumModel5MhzInitializer g_WifiSpectrumModel5MhzInitializerInstance
initialization instance for WifiSpectrumModel5Mhz
double Integral(const SpectrumValue &arg)
static Ptr< SpectrumValue > CreateHtOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth)
Create a transmit power spectral density corresponding to OFDM High Throughput (HT) (802...
WifiSpectrumModelId(uint32_t f, uint16_t w, double b, uint16_t g)
Constructor.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
static Ptr< SpectrumValue > CreateRfFilter(uint32_t centerFrequency, uint16_t channelWidth, uint32_t bandBandwidth, uint16_t guardBandwidth)
Create a spectral density corresponding to the RF filter.
static Ptr< SpectrumValue > CreateDsssTxPowerSpectralDensity(uint32_t centerFrequency, double txPowerW, uint16_t guardBandwidth)
Create a transmit power spectral density corresponding to DSSS.
std::vector< BandInfo > Bands
Container of BandInfo.
SpectrumModelUid_t GetUid() const
channel
Definition: third.py:92
bool operator<(const EventId &a, const EventId &b)
Definition: event-id.h:160
std::pair< uint32_t, uint32_t > StartStop
typedef for a pair of start and stop sub-band indexes
static void CreateSpectrumMaskForOfdm(Ptr< SpectrumValue > c, std::vector< StartStop > allocatedSubBands, StartStop maskBand, double txPowerPerBandW, uint32_t nGuardBands, uint32_t innerSlopeWidth, double lowestPointDbr)
Create a transmit power spectral density corresponding to OFDM transmit spectrum mask requirements fo...
uint32_t m_centerFrequency
center frequency (in MHz)
static Ptr< SpectrumValue > CreateNoisePowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, uint32_t bandBandwidth, double noiseFigure, uint16_t guardBandwidth)
Create a power spectral density corresponding to the noise.
double fc
center frequency
static void NormalizeSpectrumMask(Ptr< SpectrumValue > c, double txPowerW)
Normalize the transmit spectrum mask generated by CreateSpectrumMaskForOfdm so that the total transmi...
uint16_t m_guardBandwidth
guard band width (in MHz)
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
static Ptr< SpectrumValue > CreateHeOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth)
Create a transmit power spectral density corresponding to OFDM High Efficiency (HE) (802...
static Ptr< SpectrumModel > GetSpectrumModel(uint32_t centerFrequency, uint16_t channelWidth, uint32_t bandBandwidth, uint16_t guardBandwidth)
Return a SpectrumModel instance corresponding to the center frequency and channel width...
double f(double x, void *params)
Definition: 80211b.c:70
virtual Ptr< SpectrumValue > CreateTxPowerSpectralDensity(double txPower, uint8_t channel)
Creates a SpectrumValue instance that represents the TX Power Spectral Density of a wifi device corre...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double fl
lower limit of subband
virtual Ptr< SpectrumValue > CreateConstant(double psd)
Creates a SpectrumValue instance with a constant value for all frequencies.
Wifi Spectrum Model structure.
Ptr< const SpectrumModel > GetSpectrumModel() const
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
static double DbmToW(double dbm)
Convert from dBm to Watts.
virtual ~WifiSpectrumValueHelper()
Destructor.
double m_bandBandwidth
width of each band (in Hz)
Values::iterator ValuesBegin()
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
Static class to initialize the values for the 2.4 GHz Wi-Fi spectrum model.
virtual Ptr< SpectrumValue > CreateRfFilter(uint8_t channel)
Creates a SpectrumValue instance which represents the frequency response of the RF filter which is us...
static Ptr< SpectrumValue > CreateOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth)
Create a transmit power spectral density corresponding to OFDM (802.11a/g).
uint16_t m_channelWidth
channel width (in MHz)
double fh
upper limit of subband
Definition: first.py:1
static Ptr< SpectrumModel > g_WifiSpectrumModel5Mhz
static initializer for the class
The building block of a SpectrumModel.
Bands::const_iterator ConstBandsBegin() const