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
34namespace ns3
35{
36
37NS_LOG_COMPONENT_DEFINE("WifiSpectrumValueHelper");
38
41{
49 WifiSpectrumModelId(uint32_t f, uint16_t w, double b, uint16_t g);
51 uint16_t m_channelWidth;
54};
55
56WifiSpectrumModelId::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
71bool
73{
74 return (
78 (a.m_bandBandwidth < b.m_bandBandwidth)) // to cover coexistence of 11ax with legacy case
82 b.m_guardBandwidth))); // to cover 2.4 GHz case, where DSSS coexists with OFDM
83}
84
85static 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));
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,
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
607void
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
810void
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
826double
828{
829 return std::pow(10.0, 0.1 * (dBm - 30.0));
830}
831
832double
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
878Ptr<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:160
#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
def start()
Definition: core.py:1861
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.