A Discrete-Event Network Simulator
API
wifi-spectrum-value-helper.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 CTTC
3  * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
4  * Copyright (c) 2017 Orange Labs
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Authors: Nicola Baldo <nbaldo@cttc.es>
20  * Giuseppe Piro <g.piro@poliba.it>
21  * Rediet <getachew.redieteab@orange.com>
22  */
23 
25 
26 #include "ns3/assert.h"
27 #include "ns3/fatal-error.h"
28 #include "ns3/log.h"
29 
30 #include <cmath>
31 #include <map>
32 #include <sstream>
33 
34 namespace ns3
35 {
36 
37 NS_LOG_COMPONENT_DEFINE("WifiSpectrumValueHelper");
38 
41 {
49  WifiSpectrumModelId(uint32_t f, uint16_t w, double b, uint16_t g);
50  uint32_t m_centerFrequency;
51  uint16_t m_channelWidth;
52  double m_bandBandwidth;
53  uint16_t m_guardBandwidth;
54 };
55 
56 WifiSpectrumModelId::WifiSpectrumModelId(uint32_t f, uint16_t w, double b, uint16_t g)
57  : m_centerFrequency(f),
58  m_channelWidth(w),
59  m_bandBandwidth(b),
60  m_guardBandwidth(g)
61 {
62  NS_LOG_FUNCTION(this << f << w << b << g);
63 }
64 
71 bool
73 {
74  return (
78  (a.m_bandBandwidth < b.m_bandBandwidth)) // to cover coexistence of 11ax with legacy case
79  || ((a.m_centerFrequency == b.m_centerFrequency) &&
81  (a.m_guardBandwidth <
82  b.m_guardBandwidth))); // to cover 2.4 GHz case, where DSSS coexists with OFDM
83 }
84 
85 static std::map<WifiSpectrumModelId, Ptr<SpectrumModel>>
87 
90  uint16_t channelWidth,
91  uint32_t bandBandwidth,
92  uint16_t guardBandwidth)
93 {
94  NS_LOG_FUNCTION(centerFrequency << channelWidth << bandBandwidth << guardBandwidth);
96  WifiSpectrumModelId key(centerFrequency, channelWidth, bandBandwidth, guardBandwidth);
97  std::map<WifiSpectrumModelId, Ptr<SpectrumModel>>::iterator it =
98  g_wifiSpectrumModelMap.find(key);
99  if (it != g_wifiSpectrumModelMap.end())
100  {
101  ret = it->second;
102  }
103  else
104  {
105  Bands bands;
106  double centerFrequencyHz = centerFrequency * 1e6;
107  double bandwidth = (channelWidth + (2.0 * guardBandwidth)) * 1e6;
108  // For OFDM, the center subcarrier is null (at center frequency)
109  uint32_t numBands = static_cast<uint32_t>((bandwidth / bandBandwidth) + 0.5);
110  NS_ASSERT(numBands > 0);
111  if (numBands % 2 == 0)
112  {
113  // round up to the nearest odd number of subbands so that bands
114  // are symmetric around center frequency
115  numBands += 1;
116  }
117  NS_ASSERT_MSG(numBands % 2 == 1, "Number of bands should be odd");
118  NS_LOG_DEBUG("Num bands " << numBands << " band bandwidth " << bandBandwidth);
119  // lay down numBands/2 bands symmetrically around center frequency
120  // and place an additional band at center frequency
121  double startingFrequencyHz =
122  centerFrequencyHz - (numBands / 2 * bandBandwidth) - bandBandwidth / 2;
123  for (size_t i = 0; i < numBands; i++)
124  {
125  BandInfo info;
126  double f = startingFrequencyHz + (i * bandBandwidth);
127  info.fl = f;
128  f += bandBandwidth / 2;
129  info.fc = f;
130  f += bandBandwidth / 2;
131  info.fh = f;
132  NS_LOG_DEBUG("creating band " << i << " (" << info.fl << ":" << info.fc << ":"
133  << info.fh << ")");
134  bands.push_back(info);
135  }
136  ret = Create<SpectrumModel>(std::move(bands));
137  g_wifiSpectrumModelMap.insert(std::pair<WifiSpectrumModelId, Ptr<SpectrumModel>>(key, ret));
138  }
139  NS_LOG_LOGIC("returning SpectrumModel::GetUid () == " << ret->GetUid());
140  return ret;
141 }
142 
143 // Power allocated to 71 center subbands out of 135 total subbands in the band
146  double txPowerW,
147  uint16_t guardBandwidth)
148 {
149  NS_LOG_FUNCTION(centerFrequency << txPowerW << +guardBandwidth);
150  uint16_t channelWidth = 22; // DSSS channels are 22 MHz wide
151  uint32_t bandBandwidth = 312500;
152  Ptr<SpectrumValue> c = Create<SpectrumValue>(
153  GetSpectrumModel(centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
154  Values::iterator vit = c->ValuesBegin();
155  Bands::const_iterator bit = c->ConstBandsBegin();
156  uint32_t nGuardBands =
157  static_cast<uint32_t>(((2 * guardBandwidth * 1e6) / bandBandwidth) + 0.5);
158  uint32_t nAllocatedBands = static_cast<uint32_t>(((channelWidth * 1e6) / bandBandwidth) + 0.5);
159  NS_ASSERT(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1));
160  // Evenly spread power across 22 MHz
161  double txPowerPerBand = txPowerW / nAllocatedBands;
162  for (size_t i = 0; i < c->GetSpectrumModel()->GetNumBands(); i++, vit++, bit++)
163  {
164  if ((i >= (nGuardBands / 2)) && (i <= ((nGuardBands / 2) + nAllocatedBands - 1)))
165  {
166  *vit = txPowerPerBand / (bit->fh - bit->fl);
167  }
168  }
169  return c;
170 }
171 
174  uint16_t channelWidth,
175  double txPowerW,
176  uint16_t guardBandwidth,
177  double minInnerBandDbr,
178  double minOuterBandDbr,
179  double lowestPointDbr)
180 {
181  NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr
182  << minOuterBandDbr << lowestPointDbr);
183  uint32_t bandBandwidth = 0;
184  uint32_t innerSlopeWidth = 0;
185  switch (channelWidth)
186  {
187  case 20:
188  bandBandwidth = 312500;
189  innerSlopeWidth = static_cast<uint32_t>((2e6 / bandBandwidth) + 0.5); // [-11;-9] & [9;11]
190  break;
191  case 10:
192  bandBandwidth = 156250;
193  innerSlopeWidth =
194  static_cast<uint32_t>((1e6 / bandBandwidth) + 0.5); // [-5.5;-4.5] & [4.5;5.5]
195  break;
196  case 5:
197  bandBandwidth = 78125;
198  innerSlopeWidth =
199  static_cast<uint32_t>((5e5 / bandBandwidth) + 0.5); // [-2.75;-2.5] & [2.5;2.75]
200  break;
201  default:
202  NS_FATAL_ERROR("Channel width " << channelWidth << " should be correctly set.");
203  return nullptr;
204  }
205 
206  Ptr<SpectrumValue> c = Create<SpectrumValue>(
207  GetSpectrumModel(centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
208  uint32_t nGuardBands =
209  static_cast<uint32_t>(((2 * guardBandwidth * 1e6) / bandBandwidth) + 0.5);
210  uint32_t nAllocatedBands = static_cast<uint32_t>(((channelWidth * 1e6) / bandBandwidth) + 0.5);
211  NS_ASSERT_MSG(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1),
212  "Unexpected number of bands " << c->GetSpectrumModel()->GetNumBands());
213  // 52 subcarriers (48 data + 4 pilot)
214  // skip guard band and 6 subbands, then place power in 26 subbands, then
215  // skip the center subband, then place power in 26 subbands, then skip
216  // the final 6 subbands and the guard band.
217  double txPowerPerBandW = txPowerW / 52;
218  NS_LOG_DEBUG("Power per band " << txPowerPerBandW << "W");
219  uint32_t start1 = (nGuardBands / 2) + 6;
220  uint32_t stop1 = start1 + 26 - 1;
221  uint32_t start2 = stop1 + 2;
222  uint32_t stop2 = start2 + 26 - 1;
223 
224  // Build transmit spectrum mask
225  std::vector<WifiSpectrumBand> subBands{
226  std::make_pair(start1, stop1),
227  std::make_pair(start2, stop2),
228  };
229  WifiSpectrumBand maskBand(0, nAllocatedBands + nGuardBands);
231  subBands,
232  maskBand,
233  txPowerPerBandW,
234  nGuardBands,
235  innerSlopeWidth,
236  minInnerBandDbr,
237  minOuterBandDbr,
238  lowestPointDbr);
239  NormalizeSpectrumMask(c, txPowerW);
240  NS_ASSERT_MSG(std::abs(txPowerW - Integral(*c)) < 1e-6, "Power allocation failed");
241  return c;
242 }
243 
246  uint32_t centerFrequency,
247  uint16_t channelWidth,
248  double txPowerW,
249  uint16_t guardBandwidth,
250  double minInnerBandDbr,
251  double minOuterBandDbr,
252  double lowestPointDbr,
253  const std::vector<bool>& puncturedSubchannels)
254 {
255  NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr
256  << minOuterBandDbr << lowestPointDbr);
257  uint32_t bandBandwidth = 312500;
258  Ptr<SpectrumValue> c = Create<SpectrumValue>(
259  GetSpectrumModel(centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
260  uint32_t nGuardBands =
261  static_cast<uint32_t>(((2 * guardBandwidth * 1e6) / bandBandwidth) + 0.5);
262  uint32_t nAllocatedBands = static_cast<uint32_t>(((channelWidth * 1e6) / bandBandwidth) + 0.5);
263  NS_ASSERT_MSG(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1),
264  "Unexpected number of bands " << c->GetSpectrumModel()->GetNumBands());
265  std::size_t num20MhzBands = channelWidth / 20;
266  std::size_t numAllocatedSubcarriersPer20MHz = 52;
267  NS_ASSERT(puncturedSubchannels.empty() || (puncturedSubchannels.size() == num20MhzBands));
268  double txPowerPerBandW = (txPowerW / numAllocatedSubcarriersPer20MHz) / num20MhzBands;
269  NS_LOG_DEBUG("Power per band " << txPowerPerBandW << "W");
270 
271  std::size_t numSubcarriersPer20MHz = (20 * 1e6) / bandBandwidth;
272  std::size_t numUnallocatedSubcarriersPer20MHz =
273  numSubcarriersPer20MHz - numAllocatedSubcarriersPer20MHz;
274  std::vector<WifiSpectrumBand> subBands; // list of data/pilot-containing subBands (sent at 0dBr)
275  subBands.resize(num20MhzBands *
276  2); // the center subcarrier is skipped, hence 2 subbands per 20 MHz subchannel
277  uint32_t start = (nGuardBands / 2) + (numUnallocatedSubcarriersPer20MHz / 2);
278  uint32_t stop;
279  uint8_t index = 0;
280  for (auto it = subBands.begin(); it != subBands.end();)
281  {
282  if (!puncturedSubchannels.empty() && puncturedSubchannels.at(index++))
283  {
284  // if subchannel is punctured, skip it and go the next one
285  NS_LOG_DEBUG("20 MHz subchannel " << +index << " is punctured");
286  it += 2;
287  continue;
288  }
289  stop = start + (numAllocatedSubcarriersPer20MHz / 2) - 1;
290  *it = std::make_pair(start, stop);
291  ++it;
292  start = stop + 2; // skip center subcarrier
293  stop = start + (numAllocatedSubcarriersPer20MHz / 2) - 1;
294  *it = std::make_pair(start, stop);
295  ++it;
296  start = stop + numUnallocatedSubcarriersPer20MHz;
297  }
298 
299  // Prepare spectrum mask specific variables
300  uint32_t innerSlopeWidth = static_cast<uint32_t>(
301  (2e6 / bandBandwidth) +
302  0.5); // size in number of subcarriers of the 0dBr<->20dBr slope (2MHz for HT/VHT)
303  WifiSpectrumBand maskBand(0, nAllocatedBands + nGuardBands);
304 
305  // Build transmit spectrum mask
307  subBands,
308  maskBand,
309  txPowerPerBandW,
310  nGuardBands,
311  innerSlopeWidth,
312  minInnerBandDbr,
313  minOuterBandDbr,
314  lowestPointDbr);
315  NormalizeSpectrumMask(c, txPowerW);
316  NS_ASSERT_MSG(std::abs(txPowerW - Integral(*c)) < 1e-6, "Power allocation failed");
317  return c;
318 }
319 
322  uint16_t channelWidth,
323  double txPowerW,
324  uint16_t guardBandwidth,
325  double minInnerBandDbr,
326  double minOuterBandDbr,
327  double lowestPointDbr)
328 {
329  NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr
330  << minOuterBandDbr << lowestPointDbr);
331  uint32_t bandBandwidth = 312500;
332  Ptr<SpectrumValue> c = Create<SpectrumValue>(
333  GetSpectrumModel(centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
334  uint32_t nGuardBands =
335  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),
338  "Unexpected number of bands " << c->GetSpectrumModel()->GetNumBands());
339  std::size_t num20MhzBands = channelWidth / 20;
340  std::size_t numAllocatedSubcarriersPer20MHz = 56;
341  double txPowerPerBandW = (txPowerW / numAllocatedSubcarriersPer20MHz) / num20MhzBands;
342  NS_LOG_DEBUG("Power per band " << txPowerPerBandW << "W");
343 
344  std::size_t numSubcarriersPer20MHz = (20 * 1e6) / bandBandwidth;
345  std::size_t numUnallocatedSubcarriersPer20MHz =
346  numSubcarriersPer20MHz - numAllocatedSubcarriersPer20MHz;
347  std::vector<WifiSpectrumBand> subBands; // list of data/pilot-containing subBands (sent at 0dBr)
348  subBands.resize(num20MhzBands *
349  2); // the center subcarrier is skipped, hence 2 subbands per 20 MHz subchannel
350  uint32_t start = (nGuardBands / 2) + (numUnallocatedSubcarriersPer20MHz / 2);
351  uint32_t stop;
352  for (auto it = subBands.begin(); it != subBands.end();)
353  {
354  stop = start + (numAllocatedSubcarriersPer20MHz / 2) - 1;
355  *it = std::make_pair(start, stop);
356  ++it;
357  start = stop + 2; // skip center subcarrier
358  stop = start + (numAllocatedSubcarriersPer20MHz / 2) - 1;
359  *it = std::make_pair(start, stop);
360  ++it;
361  start = stop + numUnallocatedSubcarriersPer20MHz;
362  }
363 
364  // Prepare spectrum mask specific variables
365  uint32_t innerSlopeWidth = static_cast<uint32_t>(
366  (2e6 / bandBandwidth) +
367  0.5); // size in number of subcarriers of the inner band (2MHz for HT/VHT)
368  WifiSpectrumBand maskBand(0, nAllocatedBands + nGuardBands);
369 
370  // Build transmit spectrum mask
372  subBands,
373  maskBand,
374  txPowerPerBandW,
375  nGuardBands,
376  innerSlopeWidth,
377  minInnerBandDbr,
378  minOuterBandDbr,
379  lowestPointDbr);
380  NormalizeSpectrumMask(c, txPowerW);
381  NS_ASSERT_MSG(std::abs(txPowerW - Integral(*c)) < 1e-6, "Power allocation failed");
382  return c;
383 }
384 
387  uint32_t centerFrequency,
388  uint16_t channelWidth,
389  double txPowerW,
390  uint16_t guardBandwidth,
391  double minInnerBandDbr,
392  double minOuterBandDbr,
393  double lowestPointDbr,
394  const std::vector<bool>& puncturedSubchannels)
395 {
396  NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr
397  << minOuterBandDbr << lowestPointDbr);
398  uint32_t bandBandwidth = 78125;
399  Ptr<SpectrumValue> c = Create<SpectrumValue>(
400  GetSpectrumModel(centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
401  uint32_t nGuardBands =
402  static_cast<uint32_t>(((2 * guardBandwidth * 1e6) / bandBandwidth) + 0.5);
403  uint32_t nAllocatedBands = static_cast<uint32_t>(((channelWidth * 1e6) / bandBandwidth) + 0.5);
404  NS_ASSERT_MSG(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1),
405  "Unexpected number of bands " << c->GetSpectrumModel()->GetNumBands());
406  double txPowerPerBandW = 0.0;
407  uint32_t start1;
408  uint32_t stop1;
409  uint32_t start2;
410  uint32_t stop2;
411  uint32_t start3;
412  uint32_t stop3;
413  uint32_t start4;
414  uint32_t stop4;
415  // Prepare spectrum mask specific variables
416  uint32_t innerSlopeWidth = static_cast<uint32_t>(
417  (1e6 / bandBandwidth) + 0.5); // size in number of subcarriers of the inner band
418  std::vector<WifiSpectrumBand> subBands; // list of data/pilot-containing subBands (sent at 0dBr)
419  WifiSpectrumBand maskBand(0, nAllocatedBands + nGuardBands);
420  switch (channelWidth)
421  {
422  case 20:
423  // 242 subcarriers (234 data + 8 pilot)
424  txPowerPerBandW = txPowerW / 242;
425  innerSlopeWidth =
426  static_cast<uint32_t>((5e5 / bandBandwidth) + 0.5); // [-10.25;-9.75] & [9.75;10.25]
427  // skip the guard band and 6 subbands, then place power in 121 subbands, then
428  // skip 3 DC, then place power in 121 subbands, then skip
429  // the final 5 subbands and the guard band.
430  start1 = (nGuardBands / 2) + 6;
431  stop1 = start1 + 121 - 1;
432  start2 = stop1 + 4;
433  stop2 = start2 + 121 - 1;
434  subBands.emplace_back(start1, stop1);
435  subBands.emplace_back(start2, stop2);
436  break;
437  case 40:
438  // 484 subcarriers (468 data + 16 pilot)
439  txPowerPerBandW = txPowerW / 484;
440  // skip the guard band and 12 subbands, then place power in 242 subbands, then
441  // skip 5 DC, then place power in 242 subbands, then skip
442  // the final 11 subbands and the guard band.
443  start1 = (nGuardBands / 2) + 12;
444  stop1 = start1 + 242 - 1;
445  start2 = stop1 + 6;
446  stop2 = start2 + 242 - 1;
447  subBands.emplace_back(start1, stop1);
448  subBands.emplace_back(start2, stop2);
449  break;
450  case 80:
451  // 996 subcarriers (980 data + 16 pilot)
452  txPowerPerBandW = txPowerW / 996;
453  // skip the guard band and 12 subbands, then place power in 498 subbands, then
454  // skip 5 DC, then place power in 498 subbands, then skip
455  // the final 11 subbands and the guard band.
456  start1 = (nGuardBands / 2) + 12;
457  stop1 = start1 + 498 - 1;
458  start2 = stop1 + 6;
459  stop2 = start2 + 498 - 1;
460  subBands.emplace_back(start1, stop1);
461  subBands.emplace_back(start2, stop2);
462  break;
463  case 160:
464  // 2 x 996 subcarriers (2 x 80 MHZ bands)
465  txPowerPerBandW = txPowerW / (2 * 996);
466  start1 = (nGuardBands / 2) + 12;
467  stop1 = start1 + 498 - 1;
468  start2 = stop1 + 6;
469  stop2 = start2 + 498 - 1;
470  start3 = stop2 + (2 * 12);
471  stop3 = start3 + 498 - 1;
472  start4 = stop3 + 6;
473  stop4 = start4 + 498 - 1;
474  subBands.emplace_back(start1, stop1);
475  subBands.emplace_back(start2, stop2);
476  subBands.emplace_back(start3, stop3);
477  subBands.emplace_back(start4, stop4);
478  break;
479  default:
480  NS_FATAL_ERROR("ChannelWidth " << channelWidth << " unsupported");
481  break;
482  }
483 
484  // Create punctured bands
485  uint32_t puncturedSlopeWidth = static_cast<uint32_t>(
486  (500e3 / bandBandwidth) + 0.5); // size in number of subcarriers of the punctured slope band
487  std::vector<WifiSpectrumBand> puncturedBands;
488  std::size_t subcarriersPerSuband = (20 * 1e6 / bandBandwidth);
489  uint32_t start = (nGuardBands / 2);
490  uint32_t stop = start + subcarriersPerSuband - 1;
491  for (auto puncturedSubchannel : puncturedSubchannels)
492  {
493  if (puncturedSubchannel)
494  {
495  puncturedBands.emplace_back(start, stop);
496  }
497  start = stop + 1;
498  stop = start + subcarriersPerSuband - 1;
499  }
500 
501  // Build transmit spectrum mask
503  subBands,
504  maskBand,
505  txPowerPerBandW,
506  nGuardBands,
507  innerSlopeWidth,
508  minInnerBandDbr,
509  minOuterBandDbr,
510  lowestPointDbr,
511  puncturedBands,
512  puncturedSlopeWidth);
513  NormalizeSpectrumMask(c, txPowerW);
514  NS_ASSERT_MSG(std::abs(txPowerW - Integral(*c)) < 1e-6, "Power allocation failed");
515  return c;
516 }
517 
520  uint16_t channelWidth,
521  double txPowerW,
522  uint16_t guardBandwidth,
523  WifiSpectrumBand ru)
524 {
525  NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << ru.first
526  << ru.second);
527  uint32_t bandBandwidth = 78125;
528  Ptr<SpectrumValue> c = Create<SpectrumValue>(
529  GetSpectrumModel(centerFrequency, channelWidth, bandBandwidth, guardBandwidth));
530 
531  // Build spectrum mask
532  Values::iterator vit = c->ValuesBegin();
533  Bands::const_iterator bit = c->ConstBandsBegin();
534  double txPowerPerBandW = (txPowerW / (ru.second - ru.first + 1)); // FIXME: null subcarriers
535  uint32_t numBands = c->GetSpectrumModel()->GetNumBands();
536  for (size_t i = 0; i < numBands; i++, vit++, bit++)
537  {
538  if (i < ru.first || i > ru.second) // outside the spectrum mask
539  {
540  *vit = 0.0;
541  }
542  else
543  {
544  *vit = (txPowerPerBandW / (bit->fh - bit->fl));
545  }
546  }
547 
548  return c;
549 }
550 
553  uint16_t channelWidth,
554  uint32_t bandBandwidth,
555  double noiseFigure,
556  uint16_t guardBandwidth)
557 {
558  Ptr<SpectrumModel> model =
559  GetSpectrumModel(centerFrequency, channelWidth, bandBandwidth, guardBandwidth);
560  return CreateNoisePowerSpectralDensity(noiseFigure, model);
561 }
562 
565  Ptr<SpectrumModel> spectrumModel)
566 {
567  NS_LOG_FUNCTION(noiseFigureDb << spectrumModel);
568 
569  // see "LTE - From theory to practice"
570  // Section 22.4.4.2 Thermal Noise and Receiver Noise Figure
571  const double kT_dBm_Hz = -174.0; // dBm/Hz
572  double kT_W_Hz = DbmToW(kT_dBm_Hz);
573  double noiseFigureLinear = std::pow(10.0, noiseFigureDb / 10.0);
574  double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
575 
576  Ptr<SpectrumValue> noisePsd = Create<SpectrumValue>(spectrumModel);
577  (*noisePsd) = noisePowerSpectralDensity;
578  NS_LOG_INFO("NoisePowerSpectralDensity has integrated power of " << Integral(*noisePsd));
579  return noisePsd;
580 }
581 
584  uint16_t totalChannelWidth,
585  uint32_t bandBandwidth,
586  uint16_t guardBandwidth,
587  WifiSpectrumBand band)
588 {
589  uint32_t startIndex = band.first;
590  uint32_t stopIndex = band.second;
591  NS_LOG_FUNCTION(centerFrequency << totalChannelWidth << bandBandwidth << guardBandwidth
592  << startIndex << stopIndex);
593  Ptr<SpectrumValue> c = Create<SpectrumValue>(
594  GetSpectrumModel(centerFrequency, totalChannelWidth, bandBandwidth, guardBandwidth));
595  Bands::const_iterator bit = c->ConstBandsBegin();
596  Values::iterator vit = c->ValuesBegin();
597  vit += startIndex;
598  bit += startIndex;
599  for (size_t i = startIndex; i <= stopIndex; i++, vit++, bit++)
600  {
601  *vit = 1;
602  }
603  NS_LOG_LOGIC("Added subbands " << startIndex << " to " << stopIndex << " to filter");
604  return c;
605 }
606 
607 void
610  const std::vector<WifiSpectrumBand>& allocatedSubBands,
611  WifiSpectrumBand maskBand,
612  double txPowerPerBandW,
613  uint32_t nGuardBands,
614  uint32_t innerSlopeWidth,
615  double minInnerBandDbr,
616  double minOuterBandDbr,
617  double lowestPointDbr,
618  const std::vector<WifiSpectrumBand>& puncturedBands,
619  uint32_t puncturedSlopeWidth)
620 {
621  NS_LOG_FUNCTION(c << allocatedSubBands.front().first << allocatedSubBands.back().second
622  << maskBand.first << maskBand.second << txPowerPerBandW << nGuardBands
623  << innerSlopeWidth << minInnerBandDbr << minOuterBandDbr << lowestPointDbr
624  << puncturedSlopeWidth);
625  uint32_t numSubBands = allocatedSubBands.size();
626  uint32_t numBands = c->GetSpectrumModel()->GetNumBands();
627  uint32_t numMaskBands = maskBand.second - maskBand.first + 1;
628  NS_ASSERT(numSubBands && numBands && numMaskBands);
629  NS_LOG_LOGIC("Power per band " << txPowerPerBandW << "W");
630 
631  // Different power levels
632  double txPowerRefDbm = (10.0 * std::log10(txPowerPerBandW * 1000.0));
633  double txPowerInnerBandMinDbm = txPowerRefDbm + minInnerBandDbr;
634  double txPowerMiddleBandMinDbm = txPowerRefDbm + minOuterBandDbr;
635  double txPowerOuterBandMinDbm =
636  txPowerRefDbm + lowestPointDbr; // TODO also take into account dBm/MHz constraints
637 
638  // Different widths (in number of bands)
639  uint32_t outerSlopeWidth =
640  nGuardBands / 4; // nGuardBands is the total left+right guard band. The left/right outer
641  // part is half of the left/right guard band.
642  uint32_t middleSlopeWidth = outerSlopeWidth - (innerSlopeWidth / 2);
643  WifiSpectrumBand outerBandLeft(maskBand.first, // to handle cases where allocated channel is
644  // under WifiPhy configured channel width.
645  maskBand.first + outerSlopeWidth - 1);
646  WifiSpectrumBand middleBandLeft(outerBandLeft.second + 1,
647  outerBandLeft.second + middleSlopeWidth);
648  WifiSpectrumBand innerBandLeft(allocatedSubBands.front().first - innerSlopeWidth,
649  allocatedSubBands.front().first -
650  1); // better to place slope based on allocated subcarriers
651  WifiSpectrumBand flatJunctionLeft(middleBandLeft.second + 1,
652  innerBandLeft.first -
653  1); // in order to handle shift due to guard subcarriers
654  WifiSpectrumBand outerBandRight(
655  maskBand.second - outerSlopeWidth + 1,
656  maskBand.second); // start from outer edge to be able to compute flat junction width
657  WifiSpectrumBand middleBandRight(outerBandRight.first - middleSlopeWidth,
658  outerBandRight.first - 1);
659  WifiSpectrumBand innerBandRight(allocatedSubBands.back().second + 1,
660  allocatedSubBands.back().second + innerSlopeWidth);
661  WifiSpectrumBand flatJunctionRight(innerBandRight.second + 1, middleBandRight.first - 1);
662  std::ostringstream ss;
663  ss << "outerBandLeft=[" << outerBandLeft.first << ";" << outerBandLeft.second << "] "
664  << "middleBandLeft=[" << middleBandLeft.first << ";" << middleBandLeft.second << "] "
665  << "flatJunctionLeft=[" << flatJunctionLeft.first << ";" << flatJunctionLeft.second << "] "
666  << "innerBandLeft=[" << innerBandLeft.first << ";" << innerBandLeft.second << "] "
667  << "subBands=[" << allocatedSubBands.front().first << ";" << allocatedSubBands.back().second
668  << "] ";
669  if (!puncturedBands.empty())
670  {
671  ss << "puncturedBands=[" << puncturedBands.front().first << ";"
672  << puncturedBands.back().second << "] ";
673  }
674  ss << "innerBandRight=[" << innerBandRight.first << ";" << innerBandRight.second << "] "
675  << "flatJunctionRight=[" << flatJunctionRight.first << ";" << flatJunctionRight.second
676  << "] "
677  << "middleBandRight=[" << middleBandRight.first << ";" << middleBandRight.second << "] "
678  << "outerBandRight=[" << outerBandRight.first << ";" << outerBandRight.second << "] ";
679  NS_LOG_DEBUG(ss.str());
680  NS_ASSERT(numMaskBands ==
681  ((allocatedSubBands.back().second - allocatedSubBands.front().first +
682  1) // equivalent to allocatedBand (includes notches and DC)
683  + 2 * (innerSlopeWidth + middleSlopeWidth + outerSlopeWidth) +
684  (flatJunctionLeft.second - flatJunctionLeft.first + 1) // flat junctions
685  + (flatJunctionRight.second - flatJunctionRight.first + 1)));
686 
687  // Different slopes
688  double innerSlope = (-1 * minInnerBandDbr) / innerSlopeWidth;
689  double middleSlope = (-1 * (minOuterBandDbr - minInnerBandDbr)) / middleSlopeWidth;
690  double outerSlope = (txPowerMiddleBandMinDbm - txPowerOuterBandMinDbm) / outerSlopeWidth;
691  double puncturedSlope = (-1 * minInnerBandDbr) / puncturedSlopeWidth;
692 
693  // Build spectrum mask
694  Values::iterator vit = c->ValuesBegin();
695  Bands::const_iterator bit = c->ConstBandsBegin();
696  double txPowerW = 0.0;
697  double previousTxPowerW = 0.0;
698  for (size_t i = 0; i < numBands; i++, vit++, bit++)
699  {
700  if (i < maskBand.first || i > maskBand.second) // outside the spectrum mask
701  {
702  txPowerW = 0.0;
703  }
704  else if (i <= outerBandLeft.second &&
705  i >= outerBandLeft.first) // better to put greater first (less computation)
706  {
707  txPowerW = DbmToW(txPowerOuterBandMinDbm + ((i - outerBandLeft.first) * outerSlope));
708  }
709  else if (i <= middleBandLeft.second && i >= middleBandLeft.first)
710  {
711  txPowerW = DbmToW(txPowerMiddleBandMinDbm + ((i - middleBandLeft.first) * middleSlope));
712  }
713  else if (i <= flatJunctionLeft.second && i >= flatJunctionLeft.first)
714  {
715  txPowerW = DbmToW(txPowerInnerBandMinDbm);
716  }
717  else if (i <= innerBandLeft.second && i >= innerBandLeft.first)
718  {
719  txPowerW =
720  (!puncturedBands.empty() &&
721  (puncturedBands.front().first <= allocatedSubBands.front().first))
722  ? DbmToW(txPowerInnerBandMinDbm)
723  : // first 20 MHz band is punctured
724  DbmToW(txPowerInnerBandMinDbm + ((i - innerBandLeft.first) * innerSlope));
725  }
726  else if (i <= allocatedSubBands.back().second &&
727  i >= allocatedSubBands.front().first) // roughly in allocated band
728  {
729  bool insideSubBand = false;
730  for (uint32_t j = 0; !insideSubBand && j < numSubBands;
731  j++) // continue until inside a sub-band
732  {
733  insideSubBand =
734  (i <= allocatedSubBands[j].second) && (i >= allocatedSubBands[j].first);
735  }
736  if (insideSubBand)
737  {
738  bool insidePuncturedSubBand = false;
739  uint32_t j = 0;
740  for (; !insidePuncturedSubBand && j < puncturedBands.size();
741  j++) // continue until inside a punctured sub-band
742  {
743  insidePuncturedSubBand =
744  (i <= puncturedBands[j].second) && (i >= puncturedBands[j].first);
745  }
746  if (insidePuncturedSubBand)
747  {
748  uint32_t startPuncturedSlope =
749  (puncturedBands[puncturedBands.size() - 1].second -
750  puncturedSlopeWidth); // only consecutive subchannels can be punctured
751  if (i >= startPuncturedSlope)
752  {
753  txPowerW = DbmToW(txPowerInnerBandMinDbm +
754  ((i - startPuncturedSlope) * puncturedSlope));
755  }
756  else
757  {
758  txPowerW = std::max(DbmToW(txPowerInnerBandMinDbm),
759  DbmToW(txPowerRefDbm - ((i - puncturedBands[0].first) *
760  puncturedSlope)));
761  }
762  }
763  else
764  {
765  txPowerW = txPowerPerBandW;
766  }
767  }
768  else
769  {
770  txPowerW = DbmToW(txPowerInnerBandMinDbm);
771  }
772  }
773  else if (i <= innerBandRight.second && i >= innerBandRight.first)
774  {
775  // take min to handle the case where last 20 MHz band is punctured
776  txPowerW = std::min(
777  previousTxPowerW,
778  DbmToW(txPowerRefDbm - ((i - innerBandRight.first + 1) *
779  innerSlope))); // +1 so as to be symmetric with left slope
780  }
781  else if (i <= flatJunctionRight.second && i >= flatJunctionRight.first)
782  {
783  txPowerW = DbmToW(txPowerInnerBandMinDbm);
784  }
785  else if (i <= middleBandRight.second && i >= middleBandRight.first)
786  {
787  txPowerW = DbmToW(txPowerInnerBandMinDbm -
788  ((i - middleBandRight.first + 1) *
789  middleSlope)); // +1 so as to be symmetric with left slope
790  }
791  else if (i <= outerBandRight.second && i >= outerBandRight.first)
792  {
793  txPowerW = DbmToW(txPowerMiddleBandMinDbm -
794  ((i - outerBandRight.first + 1) *
795  outerSlope)); // +1 so as to be symmetric with left slope
796  }
797  else
798  {
799  NS_FATAL_ERROR("Should have handled all cases");
800  }
801  double txPowerDbr = 10 * std::log10(txPowerW / txPowerPerBandW);
802  NS_LOG_LOGIC(uint32_t(i) << " -> " << txPowerDbr);
803  *vit = txPowerW / (bit->fh - bit->fl);
804  previousTxPowerW = txPowerW;
805  }
806  NS_LOG_INFO("Added signal power to subbands " << allocatedSubBands.front().first << "-"
807  << allocatedSubBands.back().second);
808 }
809 
810 void
812 {
813  NS_LOG_FUNCTION(c << txPowerW);
814  // Normalize power so that total signal power equals transmit power
815  double currentTxPowerW = Integral(*c);
816  double normalizationRatio = currentTxPowerW / txPowerW;
817  NS_LOG_LOGIC("Current power: " << currentTxPowerW << "W vs expected power: " << txPowerW << "W"
818  << " -> ratio (C/E) = " << normalizationRatio);
819  Values::iterator vit = c->ValuesBegin();
820  for (size_t i = 0; i < c->GetSpectrumModel()->GetNumBands(); i++, vit++)
821  {
822  *vit = (*vit) / normalizationRatio;
823  }
824 }
825 
826 double
828 {
829  return std::pow(10.0, 0.1 * (dBm - 30.0));
830 }
831 
832 double
834 {
835  double powerWattPerHertz = 0.0;
836  auto valueIt = psd->ConstValuesBegin() + band.first;
837  auto end = psd->ConstValuesBegin() + band.second;
838  auto bandIt = psd->ConstBandsBegin() + band.first;
839  while (valueIt <= end)
840  {
841  powerWattPerHertz += *valueIt;
842  ++valueIt;
843  }
844  return powerWattPerHertz * (bandIt->fh - bandIt->fl);
845 }
846 
848 
850 {
851 }
852 
854 {
855 }
856 
861 {
862  public:
864  {
865  Bands bands;
866  for (int i = -4; i < 13 + 7; i++)
867  {
868  BandInfo bi;
869  bi.fl = 2407.0e6 + i * 5.0e6;
870  bi.fh = 2407.0e6 + (i + 1) * 5.0e6;
871  bi.fc = (bi.fl + bi.fh) / 2;
872  bands.push_back(bi);
873  }
874  g_WifiSpectrumModel5Mhz = Create<SpectrumModel>(bands);
875  }
877 
878 Ptr<SpectrumValue>
880 {
881  Ptr<SpectrumValue> c = Create<SpectrumValue>(g_WifiSpectrumModel5Mhz);
882  (*c) = v;
883  return c;
884 }
885 
888 {
889  Ptr<SpectrumValue> txPsd = Create<SpectrumValue>(g_WifiSpectrumModel5Mhz);
890 
891  // since the spectrum model has a resolution of 5 MHz, we model
892  // the transmitted signal with a constant density over a 20MHz
893  // bandwidth centered on the center frequency of the channel. The
894  // transmission power outside the transmission power density is
895  // calculated considering the transmit spectrum mask, see IEEE
896  // Std. 802.11-2007, Annex I
897 
898  double txPowerDensity = txPower / 20e6;
899 
900  NS_ASSERT(channel >= 1);
901  NS_ASSERT(channel <= 13);
902 
903  (*txPsd)[channel - 1] = txPowerDensity * 1e-4; // -40dB
904  (*txPsd)[channel] = txPowerDensity * 1e-4; // -40dB
905  (*txPsd)[channel + 1] = txPowerDensity * 0.0015849; // -28dB
906  (*txPsd)[channel + 2] = txPowerDensity * 0.0015849; // -28dB
907  (*txPsd)[channel + 3] = txPowerDensity;
908  (*txPsd)[channel + 4] = txPowerDensity;
909  (*txPsd)[channel + 5] = txPowerDensity;
910  (*txPsd)[channel + 6] = txPowerDensity;
911  (*txPsd)[channel + 7] = txPowerDensity * 0.0015849; // -28dB
912  (*txPsd)[channel + 8] = txPowerDensity * 0.0015849; // -28dB
913  (*txPsd)[channel + 9] = txPowerDensity * 1e-4; // -40dB
914  (*txPsd)[channel + 10] = txPowerDensity * 1e-4; // -40dB
915 
916  return txPsd;
917 }
918 
921 {
922  Ptr<SpectrumValue> rf = Create<SpectrumValue>(g_WifiSpectrumModel5Mhz);
923 
924  NS_ASSERT(channel >= 1);
925  NS_ASSERT(channel <= 13);
926 
927  (*rf)[channel + 3] = 1;
928  (*rf)[channel + 4] = 1;
929  (*rf)[channel + 5] = 1;
930  (*rf)[channel + 6] = 1;
931 
932  return rf;
933 }
934 
935 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
double f(double x, void *params)
Definition: 80211b.c:71
#define max(a, b)
Definition: 80211b.c:43
size_t GetNumBands() const
SpectrumModelUid_t GetUid() const
Values::const_iterator ConstValuesBegin() const
Values::iterator ValuesBegin()
Bands::const_iterator ConstBandsBegin() const
Ptr< const SpectrumModel > GetSpectrumModel() const
Static class to initialize the values for the 2.4 GHz Wi-Fi spectrum model.
virtual Ptr< SpectrumValue > CreateConstant(double psd)
Creates a SpectrumValue instance with a constant value for all frequencies.
virtual Ptr< SpectrumValue > CreateRfFilter(uint8_t channel)
Creates a SpectrumValue instance which represents the frequency response of the RF filter which is us...
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...
static void CreateSpectrumMaskForOfdm(Ptr< SpectrumValue > c, const std::vector< WifiSpectrumBand > &allocatedSubBands, WifiSpectrumBand maskBand, double txPowerPerBandW, uint32_t nGuardBands, uint32_t innerSlopeWidth, double minInnerBandDbr, double minOuterbandDbr, double lowestPointDbr, const std::vector< WifiSpectrumBand > &puncturedSubBands=std::vector< WifiSpectrumBand >{}, uint32_t puncturedSlopeWidth=0)
Create a transmit power spectral density corresponding to OFDM transmit spectrum mask requirements fo...
static Ptr< SpectrumValue > CreateDuplicated20MhzTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, double minInnerBandDbr=-20, double minOuterbandDbr=-28, double lowestPointDbr=-40, const std::vector< bool > &puncturedSubchannels=std::vector< bool >{})
Create a transmit power spectral density corresponding to OFDM duplicated over multiple 20 MHz subcha...
static Ptr< SpectrumValue > CreateHtOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, double minInnerBandDbr=-20, double minOuterbandDbr=-28, double lowestPointDbr=-40)
Create a transmit power spectral density corresponding to OFDM High Throughput (HT) (802....
static Ptr< SpectrumValue > CreateOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, double minInnerBandDbr=-20, double minOuterbandDbr=-28, double lowestPointDbr=-40)
Create a transmit power spectral density corresponding to OFDM (802.11a/g).
static Ptr< SpectrumValue > CreateDsssTxPowerSpectralDensity(uint32_t centerFrequency, double txPowerW, uint16_t guardBandwidth)
Create a transmit power spectral density corresponding to DSSS.
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.
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.
static Ptr< SpectrumValue > CreateHeMuOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, WifiSpectrumBand ru)
Create a transmit power spectral density corresponding to the OFDMA part of HE TB PPDUs for a given R...
static double DbmToW(double dbm)
Convert from dBm to Watts.
static void NormalizeSpectrumMask(Ptr< SpectrumValue > c, double txPowerW)
Normalize the transmit spectrum mask generated by CreateSpectrumMaskForOfdm so that the total transmi...
static double GetBandPowerW(Ptr< SpectrumValue > psd, const WifiSpectrumBand &band)
Calculate the power of the specified band composed of uniformly-sized sub-bands.
static Ptr< SpectrumValue > CreateRfFilter(uint32_t centerFrequency, uint16_t totalChannelWidth, uint32_t bandBandwidth, uint16_t guardBandwidth, WifiSpectrumBand band)
Create a spectral density corresponding to the RF filter.
static Ptr< SpectrumValue > CreateHeOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, double minInnerBandDbr=-20, double minOuterbandDbr=-28, double lowestPointDbr=-40, const std::vector< bool > &puncturedSubchannels=std::vector< bool >{})
Create a transmit power spectral density corresponding to OFDM High Efficiency (HE) (802....
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static Ptr< SpectrumModel > g_WifiSpectrumModel5Mhz
static initializer for the class
std::pair< uint32_t, uint32_t > WifiSpectrumBand
typedef for a pair of start and stop sub-band indexes
double Integral(const SpectrumValue &arg)
std::vector< BandInfo > Bands
Container of BandInfo.
static class ns3::WifiSpectrumModel5MhzInitializer g_WifiSpectrumModel5MhzInitializerInstance
initialization instance for WifiSpectrumModel5Mhz
bool operator<(const EventId &a, const EventId &b)
Definition: event-id.h:170
static std::map< WifiSpectrumModelId, Ptr< SpectrumModel > > g_wifiSpectrumModelMap
static initializer for the class
channel
Definition: third.py:81
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
Wifi Spectrum Model structure.
uint32_t m_centerFrequency
center frequency (in MHz)
uint16_t m_guardBandwidth
guard band width (in MHz)
double m_bandBandwidth
width of each band (in Hz)
uint16_t m_channelWidth
channel width (in MHz)
WifiSpectrumModelId(uint32_t f, uint16_t w, double b, uint16_t g)
Constructor.