A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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{
43 uint16_t m_channelWidth;
46};
47
54bool
56{
57 return (
61 (a.m_carrierSpacing < b.m_carrierSpacing)) // to cover coexistence of 11ax with legacy case
65 b.m_guardBandwidth))); // to cover 2.4 GHz case, where DSSS coexists with OFDM
66}
67
68static std::map<WifiSpectrumModelId, Ptr<SpectrumModel>>
70
73 uint16_t channelWidth,
74 uint32_t carrierSpacing,
75 uint16_t guardBandwidth)
76{
77 NS_LOG_FUNCTION(centerFrequency << channelWidth << carrierSpacing << guardBandwidth);
79 WifiSpectrumModelId key{centerFrequency, channelWidth, carrierSpacing, guardBandwidth};
80 std::map<WifiSpectrumModelId, Ptr<SpectrumModel>>::iterator it =
81 g_wifiSpectrumModelMap.find(key);
82 if (it != g_wifiSpectrumModelMap.end())
83 {
84 ret = it->second;
85 }
86 else
87 {
88 Bands bands;
89 double centerFrequencyHz = centerFrequency * 1e6;
90 double bandwidth = (channelWidth + (2.0 * guardBandwidth)) * 1e6;
91 // For OFDM, the center subcarrier is null (at center frequency)
92 uint32_t numBands = static_cast<uint32_t>((bandwidth / carrierSpacing) + 0.5);
93 NS_ASSERT(numBands > 0);
94 if (numBands % 2 == 0)
95 {
96 // round up to the nearest odd number of subbands so that bands
97 // are symmetric around center frequency
98 numBands += 1;
99 }
100 NS_ASSERT_MSG(numBands % 2 == 1, "Number of bands should be odd");
101 NS_LOG_DEBUG("Num bands " << numBands << " band bandwidth " << carrierSpacing);
102 // lay down numBands/2 bands symmetrically around center frequency
103 // and place an additional band at center frequency
104 double startingFrequencyHz =
105 centerFrequencyHz - (numBands / 2 * carrierSpacing) - carrierSpacing / 2;
106 for (size_t i = 0; i < numBands; i++)
107 {
108 BandInfo info;
109 double f = startingFrequencyHz + (i * carrierSpacing);
110 info.fl = f;
111 f += carrierSpacing / 2;
112 info.fc = f;
113 f += carrierSpacing / 2;
114 info.fh = f;
115 NS_LOG_DEBUG("creating band " << i << " (" << info.fl << ":" << info.fc << ":"
116 << info.fh << ")");
117 bands.push_back(info);
118 }
119 ret = Create<SpectrumModel>(std::move(bands));
121 }
122 NS_LOG_LOGIC("returning SpectrumModel::GetUid () == " << ret->GetUid());
123 return ret;
124}
125
126// Power allocated to 71 center subbands out of 135 total subbands in the band
129 double txPowerW,
130 uint16_t guardBandwidth)
131{
132 NS_LOG_FUNCTION(centerFrequency << txPowerW << +guardBandwidth);
133 uint16_t channelWidth = 22; // DSSS channels are 22 MHz wide
134 uint32_t carrierSpacing = 312500;
135 Ptr<SpectrumValue> c = Create<SpectrumValue>(
136 GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth));
137 Values::iterator vit = c->ValuesBegin();
138 Bands::const_iterator bit = c->ConstBandsBegin();
139 uint32_t nGuardBands =
140 static_cast<uint32_t>(((2 * guardBandwidth * 1e6) / carrierSpacing) + 0.5);
141 uint32_t nAllocatedBands = static_cast<uint32_t>(((channelWidth * 1e6) / carrierSpacing) + 0.5);
142 NS_ASSERT(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1));
143 // Evenly spread power across 22 MHz
144 double txPowerPerBand = txPowerW / nAllocatedBands;
145 for (size_t i = 0; i < c->GetSpectrumModel()->GetNumBands(); i++, vit++, bit++)
146 {
147 if ((i >= (nGuardBands / 2)) && (i <= ((nGuardBands / 2) + nAllocatedBands - 1)))
148 {
149 *vit = txPowerPerBand / (bit->fh - bit->fl);
150 }
151 }
152 return c;
153}
154
157 uint16_t channelWidth,
158 double txPowerW,
159 uint16_t guardBandwidth,
160 double minInnerBandDbr,
161 double minOuterBandDbr,
162 double lowestPointDbr)
163{
164 NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr
165 << minOuterBandDbr << lowestPointDbr);
166 uint32_t carrierSpacing = 0;
167 uint32_t innerSlopeWidth = 0;
168 switch (channelWidth)
169 {
170 case 20:
171 carrierSpacing = 312500;
172 innerSlopeWidth = static_cast<uint32_t>((2e6 / carrierSpacing) + 0.5); // [-11;-9] & [9;11]
173 break;
174 case 10:
175 carrierSpacing = 156250;
176 innerSlopeWidth =
177 static_cast<uint32_t>((1e6 / carrierSpacing) + 0.5); // [-5.5;-4.5] & [4.5;5.5]
178 break;
179 case 5:
180 carrierSpacing = 78125;
181 innerSlopeWidth =
182 static_cast<uint32_t>((5e5 / carrierSpacing) + 0.5); // [-2.75;-2.5] & [2.5;2.75]
183 break;
184 default:
185 NS_FATAL_ERROR("Channel width " << channelWidth << " should be correctly set.");
186 return nullptr;
187 }
188
189 Ptr<SpectrumValue> c = Create<SpectrumValue>(
190 GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth));
191 uint32_t nGuardBands =
192 static_cast<uint32_t>(((2 * guardBandwidth * 1e6) / carrierSpacing) + 0.5);
193 uint32_t nAllocatedBands = static_cast<uint32_t>(((channelWidth * 1e6) / carrierSpacing) + 0.5);
194 NS_ASSERT_MSG(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1),
195 "Unexpected number of bands " << c->GetSpectrumModel()->GetNumBands());
196 // 52 subcarriers (48 data + 4 pilot)
197 // skip guard band and 6 subbands, then place power in 26 subbands, then
198 // skip the center subband, then place power in 26 subbands, then skip
199 // the final 6 subbands and the guard band.
200 double txPowerPerBandW = txPowerW / 52;
201 NS_LOG_DEBUG("Power per band " << txPowerPerBandW << "W");
202 uint32_t start1 = (nGuardBands / 2) + 6;
203 uint32_t stop1 = start1 + 26 - 1;
204 uint32_t start2 = stop1 + 2;
205 uint32_t stop2 = start2 + 26 - 1;
206
207 // Build transmit spectrum mask
208 std::vector<WifiSpectrumBandIndices> subBands{
209 std::make_pair(start1, stop1),
210 std::make_pair(start2, stop2),
211 };
212 WifiSpectrumBandIndices maskBand(0, nAllocatedBands + nGuardBands);
214 subBands,
215 maskBand,
216 txPowerPerBandW,
217 nGuardBands,
218 innerSlopeWidth,
219 minInnerBandDbr,
220 minOuterBandDbr,
221 lowestPointDbr);
222 NormalizeSpectrumMask(c, txPowerW);
223 NS_ASSERT_MSG(std::abs(txPowerW - Integral(*c)) < 1e-6, "Power allocation failed");
224 return c;
225}
226
229 uint32_t centerFrequency,
230 uint16_t channelWidth,
231 double txPowerW,
232 uint16_t guardBandwidth,
233 double minInnerBandDbr,
234 double minOuterBandDbr,
235 double lowestPointDbr,
236 const std::vector<bool>& puncturedSubchannels)
237{
238 NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr
239 << minOuterBandDbr << lowestPointDbr);
240 uint32_t carrierSpacing = 312500;
241 Ptr<SpectrumValue> c = Create<SpectrumValue>(
242 GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth));
243 uint32_t nGuardBands =
244 static_cast<uint32_t>(((2 * guardBandwidth * 1e6) / carrierSpacing) + 0.5);
245 uint32_t nAllocatedBands = static_cast<uint32_t>(((channelWidth * 1e6) / carrierSpacing) + 0.5);
246 NS_ASSERT_MSG(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1),
247 "Unexpected number of bands " << c->GetSpectrumModel()->GetNumBands());
248 std::size_t num20MhzBands = channelWidth / 20;
249 std::size_t numAllocatedSubcarriersPer20MHz = 52;
250 NS_ASSERT(puncturedSubchannels.empty() || (puncturedSubchannels.size() == num20MhzBands));
251 double txPowerPerBandW = (txPowerW / numAllocatedSubcarriersPer20MHz) / num20MhzBands;
252 NS_LOG_DEBUG("Power per band " << txPowerPerBandW << "W");
253
254 std::size_t numSubcarriersPer20MHz = (20 * 1e6) / carrierSpacing;
255 std::size_t numUnallocatedSubcarriersPer20MHz =
256 numSubcarriersPer20MHz - numAllocatedSubcarriersPer20MHz;
257 std::vector<WifiSpectrumBandIndices>
258 subBands; // list of data/pilot-containing subBands (sent at 0dBr)
259 subBands.resize(num20MhzBands *
260 2); // the center subcarrier is skipped, hence 2 subbands per 20 MHz subchannel
261 uint32_t start = (nGuardBands / 2) + (numUnallocatedSubcarriersPer20MHz / 2);
262 uint32_t stop;
263 uint8_t index = 0;
264 for (auto it = subBands.begin(); it != subBands.end();)
265 {
266 if (!puncturedSubchannels.empty() && puncturedSubchannels.at(index++))
267 {
268 // if subchannel is punctured, skip it and go the next one
269 NS_LOG_DEBUG("20 MHz subchannel " << +index << " is punctured");
270 it += 2;
271 continue;
272 }
273 stop = start + (numAllocatedSubcarriersPer20MHz / 2) - 1;
274 *it = std::make_pair(start, stop);
275 ++it;
276 start = stop + 2; // skip center subcarrier
277 stop = start + (numAllocatedSubcarriersPer20MHz / 2) - 1;
278 *it = std::make_pair(start, stop);
279 ++it;
280 start = stop + numUnallocatedSubcarriersPer20MHz;
281 }
282
283 // Prepare spectrum mask specific variables
284 uint32_t innerSlopeWidth = static_cast<uint32_t>(
285 (2e6 / carrierSpacing) +
286 0.5); // size in number of subcarriers of the 0dBr<->20dBr slope (2MHz for HT/VHT)
287 WifiSpectrumBandIndices maskBand(0, nAllocatedBands + nGuardBands);
288
289 // Build transmit spectrum mask
291 subBands,
292 maskBand,
293 txPowerPerBandW,
294 nGuardBands,
295 innerSlopeWidth,
296 minInnerBandDbr,
297 minOuterBandDbr,
298 lowestPointDbr);
299 NormalizeSpectrumMask(c, txPowerW);
300 NS_ASSERT_MSG(std::abs(txPowerW - Integral(*c)) < 1e-6, "Power allocation failed");
301 return c;
302}
303
306 uint16_t channelWidth,
307 double txPowerW,
308 uint16_t guardBandwidth,
309 double minInnerBandDbr,
310 double minOuterBandDbr,
311 double lowestPointDbr)
312{
313 NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr
314 << minOuterBandDbr << lowestPointDbr);
315 uint32_t carrierSpacing = 312500;
316 Ptr<SpectrumValue> c = Create<SpectrumValue>(
317 GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth));
318 uint32_t nGuardBands =
319 static_cast<uint32_t>(((2 * guardBandwidth * 1e6) / carrierSpacing) + 0.5);
320 uint32_t nAllocatedBands = static_cast<uint32_t>(((channelWidth * 1e6) / carrierSpacing) + 0.5);
321 NS_ASSERT_MSG(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1),
322 "Unexpected number of bands " << c->GetSpectrumModel()->GetNumBands());
323 std::size_t num20MhzBands = channelWidth / 20;
324 std::size_t numAllocatedSubcarriersPer20MHz = 56;
325 double txPowerPerBandW = (txPowerW / numAllocatedSubcarriersPer20MHz) / num20MhzBands;
326 NS_LOG_DEBUG("Power per band " << txPowerPerBandW << "W");
327
328 std::size_t numSubcarriersPer20MHz = (20 * 1e6) / carrierSpacing;
329 std::size_t numUnallocatedSubcarriersPer20MHz =
330 numSubcarriersPer20MHz - numAllocatedSubcarriersPer20MHz;
331 std::vector<WifiSpectrumBandIndices>
332 subBands; // list of data/pilot-containing subBands (sent at 0dBr)
333 subBands.resize(num20MhzBands *
334 2); // the center subcarrier is skipped, hence 2 subbands per 20 MHz subchannel
335 uint32_t start = (nGuardBands / 2) + (numUnallocatedSubcarriersPer20MHz / 2);
336 uint32_t stop;
337 for (auto it = subBands.begin(); it != subBands.end();)
338 {
339 stop = start + (numAllocatedSubcarriersPer20MHz / 2) - 1;
340 *it = std::make_pair(start, stop);
341 ++it;
342 start = stop + 2; // skip center subcarrier
343 stop = start + (numAllocatedSubcarriersPer20MHz / 2) - 1;
344 *it = std::make_pair(start, stop);
345 ++it;
346 start = stop + numUnallocatedSubcarriersPer20MHz;
347 }
348
349 // Prepare spectrum mask specific variables
350 uint32_t innerSlopeWidth = static_cast<uint32_t>(
351 (2e6 / carrierSpacing) +
352 0.5); // size in number of subcarriers of the inner band (2MHz for HT/VHT)
353 WifiSpectrumBandIndices maskBand(0, nAllocatedBands + nGuardBands);
354
355 // Build transmit spectrum mask
357 subBands,
358 maskBand,
359 txPowerPerBandW,
360 nGuardBands,
361 innerSlopeWidth,
362 minInnerBandDbr,
363 minOuterBandDbr,
364 lowestPointDbr);
365 NormalizeSpectrumMask(c, txPowerW);
366 NS_ASSERT_MSG(std::abs(txPowerW - Integral(*c)) < 1e-6, "Power allocation failed");
367 return c;
368}
369
372 uint32_t centerFrequency,
373 uint16_t channelWidth,
374 double txPowerW,
375 uint16_t guardBandwidth,
376 double minInnerBandDbr,
377 double minOuterBandDbr,
378 double lowestPointDbr,
379 const std::vector<bool>& puncturedSubchannels)
380{
381 NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr
382 << minOuterBandDbr << lowestPointDbr);
383 uint32_t carrierSpacing = 78125;
384 Ptr<SpectrumValue> c = Create<SpectrumValue>(
385 GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth));
386 uint32_t nGuardBands =
387 static_cast<uint32_t>(((2 * guardBandwidth * 1e6) / carrierSpacing) + 0.5);
388 uint32_t nAllocatedBands = static_cast<uint32_t>(((channelWidth * 1e6) / carrierSpacing) + 0.5);
389 NS_ASSERT_MSG(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1),
390 "Unexpected number of bands " << c->GetSpectrumModel()->GetNumBands());
391 double txPowerPerBandW = 0.0;
392 uint32_t start1;
393 uint32_t stop1;
394 uint32_t start2;
395 uint32_t stop2;
396 uint32_t start3;
397 uint32_t stop3;
398 uint32_t start4;
399 uint32_t stop4;
400 // Prepare spectrum mask specific variables
401 uint32_t innerSlopeWidth = static_cast<uint32_t>(
402 (1e6 / carrierSpacing) + 0.5); // size in number of subcarriers of the inner band
403 std::vector<WifiSpectrumBandIndices>
404 subBands; // list of data/pilot-containing subBands (sent at 0dBr)
405 WifiSpectrumBandIndices maskBand(0, nAllocatedBands + nGuardBands);
406 switch (channelWidth)
407 {
408 case 20:
409 // 242 subcarriers (234 data + 8 pilot)
410 txPowerPerBandW = txPowerW / 242;
411 innerSlopeWidth =
412 static_cast<uint32_t>((5e5 / carrierSpacing) + 0.5); // [-10.25;-9.75] & [9.75;10.25]
413 // skip the guard band and 6 subbands, then place power in 121 subbands, then
414 // skip 3 DC, then place power in 121 subbands, then skip
415 // the final 5 subbands and the guard band.
416 start1 = (nGuardBands / 2) + 6;
417 stop1 = start1 + 121 - 1;
418 start2 = stop1 + 4;
419 stop2 = start2 + 121 - 1;
420 subBands.emplace_back(start1, stop1);
421 subBands.emplace_back(start2, stop2);
422 break;
423 case 40:
424 // 484 subcarriers (468 data + 16 pilot)
425 txPowerPerBandW = txPowerW / 484;
426 // skip the guard band and 12 subbands, then place power in 242 subbands, then
427 // skip 5 DC, then place power in 242 subbands, then skip
428 // the final 11 subbands and the guard band.
429 start1 = (nGuardBands / 2) + 12;
430 stop1 = start1 + 242 - 1;
431 start2 = stop1 + 6;
432 stop2 = start2 + 242 - 1;
433 subBands.emplace_back(start1, stop1);
434 subBands.emplace_back(start2, stop2);
435 break;
436 case 80:
437 // 996 subcarriers (980 data + 16 pilot)
438 txPowerPerBandW = txPowerW / 996;
439 // skip the guard band and 12 subbands, then place power in 498 subbands, then
440 // skip 5 DC, then place power in 498 subbands, then skip
441 // the final 11 subbands and the guard band.
442 start1 = (nGuardBands / 2) + 12;
443 stop1 = start1 + 498 - 1;
444 start2 = stop1 + 6;
445 stop2 = start2 + 498 - 1;
446 subBands.emplace_back(start1, stop1);
447 subBands.emplace_back(start2, stop2);
448 break;
449 case 160:
450 // 2 x 996 subcarriers (2 x 80 MHZ bands)
451 txPowerPerBandW = txPowerW / (2 * 996);
452 start1 = (nGuardBands / 2) + 12;
453 stop1 = start1 + 498 - 1;
454 start2 = stop1 + 6;
455 stop2 = start2 + 498 - 1;
456 start3 = stop2 + (2 * 12);
457 stop3 = start3 + 498 - 1;
458 start4 = stop3 + 6;
459 stop4 = start4 + 498 - 1;
460 subBands.emplace_back(start1, stop1);
461 subBands.emplace_back(start2, stop2);
462 subBands.emplace_back(start3, stop3);
463 subBands.emplace_back(start4, stop4);
464 break;
465 default:
466 NS_FATAL_ERROR("ChannelWidth " << channelWidth << " unsupported");
467 break;
468 }
469
470 // Create punctured bands
471 uint32_t puncturedSlopeWidth =
472 static_cast<uint32_t>((500e3 / carrierSpacing) +
473 0.5); // size in number of subcarriers of the punctured slope band
474 std::vector<WifiSpectrumBandIndices> puncturedBands;
475 std::size_t subcarriersPerSuband = (20 * 1e6 / carrierSpacing);
476 uint32_t start = (nGuardBands / 2);
477 uint32_t stop = start + subcarriersPerSuband - 1;
478 for (auto puncturedSubchannel : puncturedSubchannels)
479 {
480 if (puncturedSubchannel)
481 {
482 puncturedBands.emplace_back(start, stop);
483 }
484 start = stop + 1;
485 stop = start + subcarriersPerSuband - 1;
486 }
487
488 // Build transmit spectrum mask
490 subBands,
491 maskBand,
492 txPowerPerBandW,
493 nGuardBands,
494 innerSlopeWidth,
495 minInnerBandDbr,
496 minOuterBandDbr,
497 lowestPointDbr,
498 puncturedBands,
499 puncturedSlopeWidth);
500 NormalizeSpectrumMask(c, txPowerW);
501 NS_ASSERT_MSG(std::abs(txPowerW - Integral(*c)) < 1e-6, "Power allocation failed");
502 return c;
503}
504
507 uint16_t channelWidth,
508 double txPowerW,
509 uint16_t guardBandwidth,
510 const WifiSpectrumBandIndices& ru)
511{
512 NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << ru.first
513 << ru.second);
514 uint32_t carrierSpacing = 78125;
515 Ptr<SpectrumValue> c = Create<SpectrumValue>(
516 GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth));
517
518 // Build spectrum mask
519 Values::iterator vit = c->ValuesBegin();
520 Bands::const_iterator bit = c->ConstBandsBegin();
521 double txPowerPerBandW = (txPowerW / (ru.second - ru.first + 1)); // FIXME: null subcarriers
522 uint32_t numBands = c->GetSpectrumModel()->GetNumBands();
523 for (size_t i = 0; i < numBands; i++, vit++, bit++)
524 {
525 if (i < ru.first || i > ru.second) // outside the spectrum mask
526 {
527 *vit = 0.0;
528 }
529 else
530 {
531 *vit = (txPowerPerBandW / (bit->fh - bit->fl));
532 }
533 }
534
535 return c;
536}
537
540 uint16_t channelWidth,
541 uint32_t carrierSpacing,
542 double noiseFigure,
543 uint16_t guardBandwidth)
544{
545 Ptr<SpectrumModel> model =
546 GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth);
547 return CreateNoisePowerSpectralDensity(noiseFigure, model);
548}
549
552 Ptr<SpectrumModel> spectrumModel)
553{
554 NS_LOG_FUNCTION(noiseFigureDb << spectrumModel);
555
556 // see "LTE - From theory to practice"
557 // Section 22.4.4.2 Thermal Noise and Receiver Noise Figure
558 const double kT_dBm_Hz = -174.0; // dBm/Hz
559 double kT_W_Hz = DbmToW(kT_dBm_Hz);
560 double noiseFigureLinear = std::pow(10.0, noiseFigureDb / 10.0);
561 double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
562
563 Ptr<SpectrumValue> noisePsd = Create<SpectrumValue>(spectrumModel);
564 (*noisePsd) = noisePowerSpectralDensity;
565 NS_LOG_INFO("NoisePowerSpectralDensity has integrated power of " << Integral(*noisePsd));
566 return noisePsd;
567}
568
569void
572 const std::vector<WifiSpectrumBandIndices>& allocatedSubBands,
573 const WifiSpectrumBandIndices& maskBand,
574 double txPowerPerBandW,
575 uint32_t nGuardBands,
576 uint32_t innerSlopeWidth,
577 double minInnerBandDbr,
578 double minOuterBandDbr,
579 double lowestPointDbr,
580 const std::vector<WifiSpectrumBandIndices>& puncturedBands,
581 uint32_t puncturedSlopeWidth)
582{
583 NS_LOG_FUNCTION(c << allocatedSubBands.front().first << allocatedSubBands.back().second
584 << maskBand.first << maskBand.second << txPowerPerBandW << nGuardBands
585 << innerSlopeWidth << minInnerBandDbr << minOuterBandDbr << lowestPointDbr
586 << puncturedSlopeWidth);
587 uint32_t numSubBands = allocatedSubBands.size();
588 uint32_t numBands = c->GetSpectrumModel()->GetNumBands();
589 uint32_t numMaskBands = maskBand.second - maskBand.first + 1;
590 NS_ASSERT(numSubBands && numBands && numMaskBands);
591 NS_LOG_LOGIC("Power per band " << txPowerPerBandW << "W");
592
593 // Different power levels
594 double txPowerRefDbm = (10.0 * std::log10(txPowerPerBandW * 1000.0));
595 double txPowerInnerBandMinDbm = txPowerRefDbm + minInnerBandDbr;
596 double txPowerMiddleBandMinDbm = txPowerRefDbm + minOuterBandDbr;
597 double txPowerOuterBandMinDbm =
598 txPowerRefDbm + lowestPointDbr; // TODO also take into account dBm/MHz constraints
599
600 // Different widths (in number of bands)
601 uint32_t outerSlopeWidth =
602 nGuardBands / 4; // nGuardBands is the total left+right guard band. The left/right outer
603 // part is half of the left/right guard band.
604 uint32_t middleSlopeWidth = outerSlopeWidth - (innerSlopeWidth / 2);
605 WifiSpectrumBandIndices outerBandLeft(
606 maskBand.first, // to handle cases where allocated channel is
607 // under WifiPhy configured channel width.
608 maskBand.first + outerSlopeWidth - 1);
609 WifiSpectrumBandIndices middleBandLeft(outerBandLeft.second + 1,
610 outerBandLeft.second + middleSlopeWidth);
611 WifiSpectrumBandIndices innerBandLeft(
612 allocatedSubBands.front().first - innerSlopeWidth,
613 allocatedSubBands.front().first -
614 1); // better to place slope based on allocated subcarriers
615 WifiSpectrumBandIndices flatJunctionLeft(
616 middleBandLeft.second + 1,
617 innerBandLeft.first - 1); // in order to handle shift due to guard subcarriers
618 WifiSpectrumBandIndices outerBandRight(
619 maskBand.second - outerSlopeWidth + 1,
620 maskBand.second); // start from outer edge to be able to compute flat junction width
621 WifiSpectrumBandIndices middleBandRight(outerBandRight.first - middleSlopeWidth,
622 outerBandRight.first - 1);
623 WifiSpectrumBandIndices innerBandRight(allocatedSubBands.back().second + 1,
624 allocatedSubBands.back().second + innerSlopeWidth);
625 WifiSpectrumBandIndices flatJunctionRight(innerBandRight.second + 1, middleBandRight.first - 1);
626 std::ostringstream ss;
627 ss << "outerBandLeft=[" << outerBandLeft.first << ";" << outerBandLeft.second << "] "
628 << "middleBandLeft=[" << middleBandLeft.first << ";" << middleBandLeft.second << "] "
629 << "flatJunctionLeft=[" << flatJunctionLeft.first << ";" << flatJunctionLeft.second << "] "
630 << "innerBandLeft=[" << innerBandLeft.first << ";" << innerBandLeft.second << "] "
631 << "subBands=[" << allocatedSubBands.front().first << ";" << allocatedSubBands.back().second
632 << "] ";
633 if (!puncturedBands.empty())
634 {
635 ss << "puncturedBands=[" << puncturedBands.front().first << ";"
636 << puncturedBands.back().second << "] ";
637 }
638 ss << "innerBandRight=[" << innerBandRight.first << ";" << innerBandRight.second << "] "
639 << "flatJunctionRight=[" << flatJunctionRight.first << ";" << flatJunctionRight.second
640 << "] "
641 << "middleBandRight=[" << middleBandRight.first << ";" << middleBandRight.second << "] "
642 << "outerBandRight=[" << outerBandRight.first << ";" << outerBandRight.second << "] ";
643 NS_LOG_DEBUG(ss.str());
644 NS_ASSERT(numMaskBands ==
645 ((allocatedSubBands.back().second - allocatedSubBands.front().first +
646 1) // equivalent to allocatedBand (includes notches and DC)
647 + 2 * (innerSlopeWidth + middleSlopeWidth + outerSlopeWidth) +
648 (flatJunctionLeft.second - flatJunctionLeft.first + 1) // flat junctions
649 + (flatJunctionRight.second - flatJunctionRight.first + 1)));
650
651 // Different slopes
652 double innerSlope = (-1 * minInnerBandDbr) / innerSlopeWidth;
653 double middleSlope = (-1 * (minOuterBandDbr - minInnerBandDbr)) / middleSlopeWidth;
654 double outerSlope = (txPowerMiddleBandMinDbm - txPowerOuterBandMinDbm) / outerSlopeWidth;
655 double puncturedSlope = (-1 * minInnerBandDbr) / puncturedSlopeWidth;
656
657 // Build spectrum mask
658 Values::iterator vit = c->ValuesBegin();
659 Bands::const_iterator bit = c->ConstBandsBegin();
660 double txPowerW = 0.0;
661 double previousTxPowerW = 0.0;
662 for (size_t i = 0; i < numBands; i++, vit++, bit++)
663 {
664 if (i < maskBand.first || i > maskBand.second) // outside the spectrum mask
665 {
666 txPowerW = 0.0;
667 }
668 else if (i <= outerBandLeft.second &&
669 i >= outerBandLeft.first) // better to put greater first (less computation)
670 {
671 txPowerW = DbmToW(txPowerOuterBandMinDbm + ((i - outerBandLeft.first) * outerSlope));
672 }
673 else if (i <= middleBandLeft.second && i >= middleBandLeft.first)
674 {
675 txPowerW = DbmToW(txPowerMiddleBandMinDbm + ((i - middleBandLeft.first) * middleSlope));
676 }
677 else if (i <= flatJunctionLeft.second && i >= flatJunctionLeft.first)
678 {
679 txPowerW = DbmToW(txPowerInnerBandMinDbm);
680 }
681 else if (i <= innerBandLeft.second && i >= innerBandLeft.first)
682 {
683 txPowerW =
684 (!puncturedBands.empty() &&
685 (puncturedBands.front().first <= allocatedSubBands.front().first))
686 ? DbmToW(txPowerInnerBandMinDbm)
687 : // first 20 MHz band is punctured
688 DbmToW(txPowerInnerBandMinDbm + ((i - innerBandLeft.first) * innerSlope));
689 }
690 else if (i <= allocatedSubBands.back().second &&
691 i >= allocatedSubBands.front().first) // roughly in allocated band
692 {
693 bool insideSubBand = false;
694 for (uint32_t j = 0; !insideSubBand && j < numSubBands;
695 j++) // continue until inside a sub-band
696 {
697 insideSubBand =
698 (i <= allocatedSubBands[j].second) && (i >= allocatedSubBands[j].first);
699 }
700 if (insideSubBand)
701 {
702 bool insidePuncturedSubBand = false;
703 uint32_t j = 0;
704 for (; !insidePuncturedSubBand && j < puncturedBands.size();
705 j++) // continue until inside a punctured sub-band
706 {
707 insidePuncturedSubBand =
708 (i <= puncturedBands[j].second) && (i >= puncturedBands[j].first);
709 }
710 if (insidePuncturedSubBand)
711 {
712 uint32_t startPuncturedSlope =
713 (puncturedBands[puncturedBands.size() - 1].second -
714 puncturedSlopeWidth); // only consecutive subchannels can be punctured
715 if (i >= startPuncturedSlope)
716 {
717 txPowerW = DbmToW(txPowerInnerBandMinDbm +
718 ((i - startPuncturedSlope) * puncturedSlope));
719 }
720 else
721 {
722 txPowerW = std::max(DbmToW(txPowerInnerBandMinDbm),
723 DbmToW(txPowerRefDbm - ((i - puncturedBands[0].first) *
724 puncturedSlope)));
725 }
726 }
727 else
728 {
729 txPowerW = txPowerPerBandW;
730 }
731 }
732 else
733 {
734 txPowerW = DbmToW(txPowerInnerBandMinDbm);
735 }
736 }
737 else if (i <= innerBandRight.second && i >= innerBandRight.first)
738 {
739 // take min to handle the case where last 20 MHz band is punctured
740 txPowerW = std::min(
741 previousTxPowerW,
742 DbmToW(txPowerRefDbm - ((i - innerBandRight.first + 1) *
743 innerSlope))); // +1 so as to be symmetric with left slope
744 }
745 else if (i <= flatJunctionRight.second && i >= flatJunctionRight.first)
746 {
747 txPowerW = DbmToW(txPowerInnerBandMinDbm);
748 }
749 else if (i <= middleBandRight.second && i >= middleBandRight.first)
750 {
751 txPowerW = DbmToW(txPowerInnerBandMinDbm -
752 ((i - middleBandRight.first + 1) *
753 middleSlope)); // +1 so as to be symmetric with left slope
754 }
755 else if (i <= outerBandRight.second && i >= outerBandRight.first)
756 {
757 txPowerW = DbmToW(txPowerMiddleBandMinDbm -
758 ((i - outerBandRight.first + 1) *
759 outerSlope)); // +1 so as to be symmetric with left slope
760 }
761 else
762 {
763 NS_FATAL_ERROR("Should have handled all cases");
764 }
765 double txPowerDbr = 10 * std::log10(txPowerW / txPowerPerBandW);
766 NS_LOG_LOGIC(uint32_t(i) << " -> " << txPowerDbr);
767 *vit = txPowerW / (bit->fh - bit->fl);
768 previousTxPowerW = txPowerW;
769 }
770 NS_LOG_INFO("Added signal power to subbands " << allocatedSubBands.front().first << "-"
771 << allocatedSubBands.back().second);
772}
773
774void
776{
777 NS_LOG_FUNCTION(c << txPowerW);
778 // Normalize power so that total signal power equals transmit power
779 double currentTxPowerW = Integral(*c);
780 double normalizationRatio = currentTxPowerW / txPowerW;
781 NS_LOG_LOGIC("Current power: " << currentTxPowerW << "W vs expected power: " << txPowerW << "W"
782 << " -> ratio (C/E) = " << normalizationRatio);
783 Values::iterator vit = c->ValuesBegin();
784 for (size_t i = 0; i < c->GetSpectrumModel()->GetNumBands(); i++, vit++)
785 {
786 *vit = (*vit) / normalizationRatio;
787 }
788}
789
790double
792{
793 return std::pow(10.0, 0.1 * (dBm - 30.0));
794}
795
796double
798{
799 double powerWattPerHertz = 0.0;
800 auto valueIt = psd->ConstValuesBegin() + band.first;
801 auto end = psd->ConstValuesBegin() + band.second;
802 auto bandIt = psd->ConstBandsBegin() + band.first;
803 while (valueIt <= end)
804 {
805 powerWattPerHertz += *valueIt;
806 ++valueIt;
807 }
808 return powerWattPerHertz * (bandIt->fh - bandIt->fl);
809}
810
811bool
812operator<(const FrequencyRange& left, const FrequencyRange& right)
813{
814 return left.minFrequency < right.minFrequency;
815}
816
817bool
818operator==(const FrequencyRange& left, const FrequencyRange& right)
819{
820 return (left.minFrequency == right.minFrequency) && (left.maxFrequency == right.maxFrequency);
821}
822
823bool
824operator!=(const FrequencyRange& left, const FrequencyRange& right)
825{
826 return !(left == right);
827}
828
829std::ostream&
830operator<<(std::ostream& os, const FrequencyRange& freqRange)
831{
832 os << "[" << freqRange.minFrequency << " MHz - " << freqRange.maxFrequency << " MHz]";
833 return os;
834}
835
836} // namespace ns3
double f(double x, void *params)
Definition: 80211b.c:70
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static Ptr< SpectrumValue > CreateNoisePowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, uint32_t carrierSpacing, double noiseFigure, uint16_t guardBandwidth)
Create a power spectral density corresponding to the noise.
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 void CreateSpectrumMaskForOfdm(Ptr< SpectrumValue > c, const std::vector< WifiSpectrumBandIndices > &allocatedSubBands, const WifiSpectrumBandIndices &maskBand, double txPowerPerBandW, uint32_t nGuardBands, uint32_t innerSlopeWidth, double minInnerBandDbr, double minOuterbandDbr, double lowestPointDbr, const std::vector< WifiSpectrumBandIndices > &puncturedSubBands=std::vector< WifiSpectrumBandIndices >{}, uint32_t puncturedSlopeWidth=0)
Create a transmit power spectral density corresponding to OFDM transmit spectrum mask requirements fo...
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< SpectrumModel > GetSpectrumModel(uint32_t centerFrequency, uint16_t channelWidth, uint32_t carrierSpacing, uint16_t guardBandwidth)
Return a SpectrumModel instance corresponding to the center frequency and channel width.
static Ptr< SpectrumValue > CreateDsssTxPowerSpectralDensity(uint32_t centerFrequency, double txPowerW, uint16_t guardBandwidth)
Create a transmit power spectral density corresponding to DSSS.
static double GetBandPowerW(Ptr< SpectrumValue > psd, const WifiSpectrumBandIndices &band)
Calculate the power of the specified band composed of uniformly-sized sub-bands.
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 Ptr< SpectrumValue > CreateHeMuOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, const WifiSpectrumBandIndices &ru)
Create a transmit power spectral density corresponding to the OFDMA part of HE TB PPDUs for a given R...
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.
bool operator!=(Callback< R, Args... > a, Callback< R, Args... > b)
Inequality test.
Definition: callback.h:676
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.h:157
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:129
double Integral(const SpectrumValue &arg)
std::vector< BandInfo > Bands
Container of BandInfo.
std::pair< uint32_t, uint32_t > WifiSpectrumBandIndices
typedef for a pair of start and stop sub-band indices
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
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
Struct defining a frequency range between minFrequency (MHz) and maxFrequency (MHz).
uint16_t maxFrequency
the maximum frequency in MHz
uint16_t minFrequency
the minimum frequency in MHz
Wifi Spectrum Model structure.
uint32_t m_centerFrequency
center frequency (in MHz)
uint16_t m_guardBandwidth
guard band width (in MHz)
uint16_t m_channelWidth
channel width (in MHz)
uint32_t m_carrierSpacing
carrier spacing (in Hz)