17#include "ns3/assert.h"
18#include "ns3/fatal-error.h"
37 for (
const auto& centerFrequency : v)
39 ss << centerFrequency <<
" ";
68 return std::tie(
lhs.centerFrequencies,
79static std::map<WifiSpectrumModelId, Ptr<SpectrumModel>>
89 << channelWidth << carrierSpacing << guardBandwidth);
91 "Spectrum model does not support more than 2 segments");
92 if (centerFrequencies.size() != 1)
94 NS_ASSERT_MSG(centerFrequencies.front() != centerFrequencies.back(),
95 "Center frequency of each segment shall be different");
99 guardBandwidth /= centerFrequencies.size();
110 std::minmax_element(centerFrequencies.cbegin(), centerFrequencies.cend());
136 (
MHzToHz(channelWidth) / (2 * centerFrequencies.size())) -
137 MHzToHz(guardBandwidth) - (carrierSpacing / 2);
143 f += carrierSpacing / 2;
145 f += carrierSpacing / 2;
149 bands.push_back(info);
154 NS_LOG_LOGIC(
"returning SpectrumModel::GetUid () == " <<
ret->GetUid());
162 MHz_u guardBandwidth)
165 MHz_u channelWidth{22};
166 Hz_u carrierSpacing{312500};
169 auto vit =
c->ValuesBegin();
170 auto bit =
c->ConstBandsBegin();
172 static_cast<uint32_t>(((
MHzToHz(2 * guardBandwidth)) / carrierSpacing) + 0.5);
178 for (
size_t i = 0;
i <
c->GetSpectrumModel()->GetNumBands();
i++,
vit++,
bit++)
192 MHz_u guardBandwidth,
199 Hz_u carrierSpacing{0};
201 switch (
static_cast<uint16_t
>(channelWidth))
204 carrierSpacing =
Hz_u{312500};
209 carrierSpacing =
Hz_u{156250};
214 carrierSpacing =
Hz_u{78125};
219 NS_FATAL_ERROR(
"Channel width " << channelWidth <<
" should be correctly set.");
226 static_cast<uint32_t>(((
MHzToHz(2 * guardBandwidth)) / carrierSpacing) + 0.5);
229 "Unexpected number of bands " <<
c->GetSpectrumModel()->GetNumBands());
242 std::vector<WifiSpectrumBandIndices>
subBands{
263 const std::vector<MHz_u>& centerFrequencies,
266 MHz_u guardBandwidth,
273 (channelWidth ==
MHz_u{160} && centerFrequencies.size() <= 2),
274 "PSD for non-contiguous channels is only possible when the total width is 160 "
275 "MHz and cannot be made of more than 2 segments");
279 const Hz_u carrierSpacing{312500};
281 GetSpectrumModel(centerFrequencies, channelWidth, carrierSpacing, guardBandwidth));
284 guardBandwidth /= centerFrequencies.size();
286 static_cast<uint32_t>(((
MHzToHz(2 * guardBandwidth)) / carrierSpacing) + 0.5);
289 const auto separationWidth = std::abs(centerFrequencies.back() - centerFrequencies.front());
296 "Unexpected number of bands " <<
c->GetSpectrumModel()->GetNumBands());
307 centerFrequencies.size());
308 for (std::size_t
i = 0;
i < centerFrequencies.size(); ++
i)
324 *
it = std::make_pair(start, stop);
329 *
it = std::make_pair(start, stop);
343 (
Hz_u{2
e6} / carrierSpacing) +
369 const std::vector<MHz_u>& centerFrequencies,
372 MHz_u guardBandwidth,
378 (channelWidth ==
MHz_u{160} && centerFrequencies.size() <= 2),
379 "PSD for non-contiguous channels is only possible when the total width is 160 "
380 "MHz and cannot be made of more than 2 segments");
384 const Hz_u carrierSpacing{312500};
386 GetSpectrumModel(centerFrequencies, channelWidth, carrierSpacing, guardBandwidth));
389 guardBandwidth /= centerFrequencies.size();
391 static_cast<uint32_t>(((
MHzToHz(2 * guardBandwidth)) / carrierSpacing) + 0.5);
394 const auto separationWidth = std::abs(centerFrequencies.back() - centerFrequencies.front());
401 "Unexpected number of bands " <<
c->GetSpectrumModel()->GetNumBands());
411 centerFrequencies.size());
412 for (std::size_t
i = 0;
i < centerFrequencies.size(); ++
i)
425 *
it = std::make_pair(start, stop);
429 *
it = std::make_pair(start, stop);
438 (
Hz_u{2
e6} / carrierSpacing) +
462 MHz_u guardBandwidth,
480 const std::vector<MHz_u>& centerFrequencies,
483 MHz_u guardBandwidth,
490 centerFrequencies.size() == 1 || channelWidth ==
MHz_u{160},
491 "PSD for non-contiguous channels is only possible when the total width is 160 MHz");
495 const Hz_u carrierSpacing{78125};
497 GetSpectrumModel(centerFrequencies, channelWidth, carrierSpacing, guardBandwidth));
500 guardBandwidth /= centerFrequencies.size();
502 static_cast<uint32_t>(((
MHzToHz(2 * guardBandwidth)) / carrierSpacing) + 0.5);
503 const auto separationWidth = std::abs(centerFrequencies.back() - centerFrequencies.front());
512 "Unexpected number of bands " <<
c->GetSpectrumModel()->GetNumBands());
527 centerFrequencies.size());
529 switch (
static_cast<uint16_t
>(channelWidth))
574 "It is not possible to create a PSD made of more than 2 segments for a width "
593 NS_FATAL_ERROR(
"ChannelWidth " << channelWidth <<
" unsupported");
651 const std::vector<MHz_u>& centerFrequencies,
654 MHz_u guardBandwidth,
655 const std::vector<WifiSpectrumBandIndices>& ru)
657 auto printRuIndices = [](
const std::vector<WifiSpectrumBandIndices>& v) {
658 std::stringstream
ss;
659 for (
const auto& [start, stop] : v)
661 ss << start <<
"-" << stop <<
" ";
667 const Hz_u carrierSpacing{78125};
669 GetSpectrumModel(centerFrequencies, channelWidth, carrierSpacing, guardBandwidth));
672 auto vit =
c->ValuesBegin();
673 auto bit =
c->ConstBandsBegin();
675 std::accumulate(ru.cbegin(), ru.cend(), 0, [](
uint32_t sum,
const auto& p) {
676 return sum + (p.second - p.first) + 1;
683 const auto allocated = std::any_of(ru.cbegin(), ru.cend(), [
i](
const auto& p) {
684 return (i >= p.first && i <= p.second);
707 "Only PSDs for up to 2 frequency segments are supported");
799 std::ostringstream
ss;
804 ss <<
"PSD" <<
i + 1 <<
": ";
1070 auto vit =
c->ValuesBegin();
1071 auto bit =
c->ConstBandsBegin();
1097 auto vit =
c->ValuesBegin();
1098 for (
size_t i = 0;
i <
c->GetSpectrumModel()->GetNumBands();
i++,
vit++)
1106 const std::vector<WifiSpectrumBandIndices>&
segments)
1112 "Invalid width for subband [" <<
bandIt->fl <<
";" <<
bandIt->fh <<
"]");
1113 for (
const auto& [start, stop] :
segments)
1115 auto valueIt = psd->ConstValuesBegin() + start;
1116 auto end = psd->ConstValuesBegin() + stop;
1121 "Invalid power value " << *
valueIt <<
" in subband " << index);
1128 NS_ASSERT_MSG(power >= 0.0,
"Invalid calculated power " << power);
1135 return left.minFrequency <
right.minFrequency;
1141 return (
left.minFrequency ==
right.minFrequency) && (
left.maxFrequency ==
right.maxFrequency);
1153 os <<
"[" <<
freqRange.minFrequency <<
" MHz - " <<
freqRange.maxFrequency <<
" MHz]";
Smart pointer class similar to boost::intrusive_ptr.
static Ptr< SpectrumValue > CreateHtOfdmTxPowerSpectralDensity(const std::vector< MHz_u > ¢erFrequencies, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, dBr_u minInnerBand=dBr_u{-20}, dBr_u minOuterband=dBr_u{-28}, dBr_u lowestPoint=dBr_u{-40})
Create a transmit power spectral density corresponding to OFDM High Throughput (HT) (802....
static Ptr< SpectrumValue > CreateDsssTxPowerSpectralDensity(MHz_u centerFrequency, Watt_u txPower, MHz_u guardBandwidth)
Create a transmit power spectral density corresponding to DSSS.
static Ptr< SpectrumValue > CreateDuplicated20MhzTxPowerSpectralDensity(const std::vector< MHz_u > ¢erFrequencies, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, dBr_u minInnerBand=dBr_u{-20}, dBr_u minOuterband=dBr_u{-28}, dBr_u lowestPoint=dBr_u{-40}, const std::vector< bool > &puncturedSubchannels={})
Create a transmit power spectral density corresponding to OFDM duplicated over multiple 20 MHz subcha...
static void CreateSpectrumMaskForOfdm(Ptr< SpectrumValue > c, const std::vector< std::vector< WifiSpectrumBandIndices > > &allocatedSubBandsPerSegment, const WifiSpectrumBandIndices &maskBand, Watt_u txPowerPerBand, uint32_t nGuardBands, uint32_t innerSlopeWidth, dBr_u minInnerBand, dBr_u minOuterband, dBr_u lowestPoint, const std::vector< std::vector< WifiSpectrumBandIndices > > &puncturedSubBands={}, uint32_t puncturedSlopeWidth=0)
Create a transmit power spectral density corresponding to OFDM transmit spectrum mask requirements fo...
static Ptr< SpectrumModel > GetSpectrumModel(const std::vector< MHz_u > ¢erFrequencies, MHz_u channelWidth, Hz_u carrierSpacing, MHz_u guardBandwidth)
Return a SpectrumModel instance corresponding to the center frequency and channel width.
static Watt_u GetBandPowerW(Ptr< SpectrumValue > psd, const std::vector< WifiSpectrumBandIndices > &segments)
Calculate the power of the specified band composed of uniformly-sized sub-bands.
static Ptr< SpectrumValue > CreateHeMuOfdmTxPowerSpectralDensity(const std::vector< MHz_u > ¢erFrequencies, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, const std::vector< WifiSpectrumBandIndices > &ru)
Create a transmit power spectral density corresponding to the OFDMA part of HE TB PPDUs for a given R...
static Ptr< SpectrumValue > CreateOfdmTxPowerSpectralDensity(MHz_u centerFrequency, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, dBr_u minInnerBand=dBr_u{-20}, dBr_u minOuterband=dBr_u{-28}, dBr_u lowestPoint=dBr_u{-40})
Create a transmit power spectral density corresponding to OFDM (802.11a/g).
static Ptr< SpectrumValue > CreateHeOfdmTxPowerSpectralDensity(MHz_u centerFrequency, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, dBr_u minInnerBand=dBr_u{-20}, dBr_u minOuterband=dBr_u{-28}, dBr_u lowestPoint=dBr_u{-40}, const std::vector< bool > &puncturedSubchannels={})
Create a transmit power spectral density corresponding to OFDM High Efficiency (HE) (802....
static void NormalizeSpectrumMask(Ptr< SpectrumValue > c, Watt_u txPower)
Normalize the transmit spectrum mask generated by CreateSpectrumMaskForOfdm so that the total transmi...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
#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.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
auto printFrequencies
Lambda to print a vector of frequencies.
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.
bool operator==(const EventId &a, const EventId &b)
std::ostream & operator<<(std::ostream &os, const Angles &a)
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
std::size_t Count20MHzSubchannels(MHz_u channelWidth)
Return the number of 20 MHz subchannels covering the channel width.
bool operator<(const EventId &a, const EventId &b)
double Watt_u
Watt weak type.
static std::map< WifiSpectrumModelId, Ptr< SpectrumModel > > g_wifiSpectrumModelMap
static initializer for the class
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
Hz_u MHzToHz(MHz_u val)
Convert from MHz to Hz.
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 and maxFrequency.
Wifi Spectrum Model structure.
MHz_u channelWidth
channel width
std::vector< MHz_u > centerFrequencies
center frequency per segment
MHz_u guardBandwidth
guard band width
Hz_u carrierSpacing
carrier spacing