diff --git a/src/wifi/model/he/he-phy.cc b/src/wifi/model/he/he-phy.cc index 60657b450..d4937f26a 100644 --- a/src/wifi/model/he/he-phy.cc +++ b/src/wifi/model/he/he-phy.cc @@ -1357,7 +1357,7 @@ HePhy::GetTxPowerSpectralDensity(double txPowerW, const auto ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType()); channelWidth = (ruWidth < 20) ? 20 : ruWidth; return WifiSpectrumValueHelper::CreateDuplicated20MhzTxPowerSpectralDensity( - GetCenterFrequenciesForNonHePart(ppdu, staId).front(), + GetCenterFrequenciesForNonHePart(ppdu, staId), channelWidth, txPowerW, GetGuardBandwidth(channelWidth), @@ -1370,7 +1370,7 @@ HePhy::GetTxPowerSpectralDensity(double txPowerW, { const auto band = GetRuBandForTx(txVector, GetStaId(ppdu)).indices; return WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity( - centerFrequencies.front(), + centerFrequencies, channelWidth, txPowerW, GetGuardBandwidth(channelWidth), @@ -1381,7 +1381,7 @@ HePhy::GetTxPowerSpectralDensity(double txPowerW, if (flag == HePpdu::PSD_NON_HE_PORTION) { return WifiSpectrumValueHelper::CreateDuplicated20MhzTxPowerSpectralDensity( - centerFrequencies.front(), + centerFrequencies, channelWidth, txPowerW, GetGuardBandwidth(channelWidth), @@ -1393,7 +1393,7 @@ HePhy::GetTxPowerSpectralDensity(double txPowerW, else { return WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity( - centerFrequencies.front(), + centerFrequencies, channelWidth, txPowerW, GetGuardBandwidth(channelWidth), @@ -1407,7 +1407,7 @@ HePhy::GetTxPowerSpectralDensity(double txPowerW, default: { NS_ASSERT(puncturedSubchannels.empty()); return WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity( - centerFrequencies.front(), + centerFrequencies, channelWidth, txPowerW, GetGuardBandwidth(channelWidth), diff --git a/src/wifi/model/ht/ht-phy.cc b/src/wifi/model/ht/ht-phy.cc index 2ed70a768..5396fe810 100644 --- a/src/wifi/model/ht/ht-phy.cc +++ b/src/wifi/model/ht/ht-phy.cc @@ -469,7 +469,7 @@ HtPhy::GetTxPowerSpectralDensity(double txPowerW, Ptr ppdu) cons NS_LOG_FUNCTION(this << centerFrequencies.front() << channelWidth << txPowerW); const auto& txMaskRejectionParams = GetTxMaskRejectionParams(); Ptr v = WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity( - centerFrequencies.front(), + centerFrequencies, channelWidth, txPowerW, GetGuardBandwidth(channelWidth), diff --git a/src/wifi/model/non-ht/ofdm-phy.cc b/src/wifi/model/non-ht/ofdm-phy.cc index 5a58ccc3a..934670ec9 100644 --- a/src/wifi/model/non-ht/ofdm-phy.cc +++ b/src/wifi/model/non-ht/ofdm-phy.cc @@ -377,7 +377,7 @@ OfdmPhy::GetTxPowerSpectralDensity(double txPowerW, Ptr ppdu) co if (txVector.IsNonHtDuplicate()) { v = WifiSpectrumValueHelper::CreateDuplicated20MhzTxPowerSpectralDensity( - centerFrequencies.front(), + centerFrequencies, channelWidth, txPowerW, GetGuardBandwidth(channelWidth), diff --git a/src/wifi/model/wifi-spectrum-value-helper.cc b/src/wifi/model/wifi-spectrum-value-helper.cc index 3947f6744..bf0aa5005 100644 --- a/src/wifi/model/wifi-spectrum-value-helper.cc +++ b/src/wifi/model/wifi-spectrum-value-helper.cc @@ -218,7 +218,7 @@ WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity(uint16_t centerFrequen Ptr WifiSpectrumValueHelper::CreateDuplicated20MhzTxPowerSpectralDensity( - uint16_t centerFrequency, + const std::vector& centerFrequencies, ChannelWidthMhz channelWidth, double txPowerW, ChannelWidthMhz guardBandwidth, @@ -227,11 +227,14 @@ WifiSpectrumValueHelper::CreateDuplicated20MhzTxPowerSpectralDensity( double lowestPointDbr, const std::vector& puncturedSubchannels) { - NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr - << minOuterBandDbr << lowestPointDbr); + NS_ASSERT_MSG(centerFrequencies.size() == 1, + "There is no support for HE OFDM PSD for non-contiguous channels"); + NS_LOG_FUNCTION(centerFrequencies.front() + << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr + << minOuterBandDbr << lowestPointDbr); uint32_t carrierSpacing = 312500; Ptr c = Create( - GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth)); + GetSpectrumModel(centerFrequencies.front(), channelWidth, carrierSpacing, guardBandwidth)); auto nGuardBands = static_cast(((2 * guardBandwidth * 1e6) / carrierSpacing) + 0.5); auto nAllocatedBands = static_cast(((channelWidth * 1e6) / carrierSpacing) + 0.5); NS_ASSERT_MSG(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1), @@ -293,19 +296,23 @@ WifiSpectrumValueHelper::CreateDuplicated20MhzTxPowerSpectralDensity( } Ptr -WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity(uint16_t centerFrequency, - ChannelWidthMhz channelWidth, - double txPowerW, - ChannelWidthMhz guardBandwidth, - double minInnerBandDbr, - double minOuterBandDbr, - double lowestPointDbr) +WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity( + const std::vector& centerFrequencies, + ChannelWidthMhz channelWidth, + double txPowerW, + ChannelWidthMhz guardBandwidth, + double minInnerBandDbr, + double minOuterBandDbr, + double lowestPointDbr) { - NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr - << minOuterBandDbr << lowestPointDbr); + NS_ASSERT_MSG(centerFrequencies.size() == 1, + "There is no support for HE OFDM PSD for non-contiguous channels"); + NS_LOG_FUNCTION(centerFrequencies.front() + << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr + << minOuterBandDbr << lowestPointDbr); uint32_t carrierSpacing = 312500; Ptr c = Create( - GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth)); + GetSpectrumModel(centerFrequencies.front(), channelWidth, carrierSpacing, guardBandwidth)); auto nGuardBands = static_cast(((2 * guardBandwidth * 1e6) / carrierSpacing) + 0.5); auto nAllocatedBands = static_cast(((channelWidth * 1e6) / carrierSpacing) + 0.5); NS_ASSERT_MSG(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1), @@ -368,11 +375,35 @@ WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity( double lowestPointDbr, const std::vector& puncturedSubchannels) { - NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr - << minOuterBandDbr << lowestPointDbr); + return CreateHeOfdmTxPowerSpectralDensity(std::vector{centerFrequency}, + channelWidth, + txPowerW, + guardBandwidth, + minInnerBandDbr, + minOuterBandDbr, + lowestPointDbr, + puncturedSubchannels); +} + +Ptr +WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity( + const std::vector& centerFrequencies, + uint16_t channelWidth, + double txPowerW, + uint16_t guardBandwidth, + double minInnerBandDbr, + double minOuterBandDbr, + double lowestPointDbr, + const std::vector& puncturedSubchannels) +{ + NS_ASSERT_MSG(centerFrequencies.size() == 1, + "There is no support for HE OFDM PSD for non-contiguous channels"); + NS_LOG_FUNCTION(centerFrequencies.front() + << channelWidth << txPowerW << guardBandwidth << minInnerBandDbr + << minOuterBandDbr << lowestPointDbr); uint32_t carrierSpacing = 78125; Ptr c = Create( - GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth)); + GetSpectrumModel(centerFrequencies.front(), channelWidth, carrierSpacing, guardBandwidth)); auto nGuardBands = static_cast(((2 * guardBandwidth * 1e6) / carrierSpacing) + 0.5); auto nAllocatedBands = static_cast(((channelWidth * 1e6) / carrierSpacing) + 0.5); NS_ASSERT_MSG(c->GetSpectrumModel()->GetNumBands() == (nAllocatedBands + nGuardBands + 1), @@ -492,17 +523,20 @@ WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity( } Ptr -WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity(uint16_t centerFrequency, - ChannelWidthMhz channelWidth, - double txPowerW, - ChannelWidthMhz guardBandwidth, - const WifiSpectrumBandIndices& ru) +WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity( + const std::vector& centerFrequencies, + ChannelWidthMhz channelWidth, + double txPowerW, + ChannelWidthMhz guardBandwidth, + const WifiSpectrumBandIndices& ru) { - NS_LOG_FUNCTION(centerFrequency << channelWidth << txPowerW << guardBandwidth << ru.first - << ru.second); + NS_ASSERT_MSG(centerFrequencies.size() == 1, + "There is no support for HE OFDM PSD for non-contiguous channels"); + NS_LOG_FUNCTION(centerFrequencies.front() + << channelWidth << txPowerW << guardBandwidth << ru.first << ru.second); uint32_t carrierSpacing = 78125; Ptr c = Create( - GetSpectrumModel(centerFrequency, channelWidth, carrierSpacing, guardBandwidth)); + GetSpectrumModel(centerFrequencies.front(), channelWidth, carrierSpacing, guardBandwidth)); // Build spectrum mask auto vit = c->ValuesBegin(); diff --git a/src/wifi/model/wifi-spectrum-value-helper.h b/src/wifi/model/wifi-spectrum-value-helper.h index b4ecbb8cb..bf1ada302 100644 --- a/src/wifi/model/wifi-spectrum-value-helper.h +++ b/src/wifi/model/wifi-spectrum-value-helper.h @@ -26,6 +26,8 @@ #include +#include + namespace ns3 { @@ -114,8 +116,8 @@ class WifiSpectrumValueHelper * Create a transmit power spectral density corresponding to OFDM duplicated over multiple 20 * MHz subchannels. Channel width may vary between 20, 40, 80, and 160 MHz. * - * \param centerFrequency center frequency (MHz) - * \param channelWidth channel width (MHz) + * \param centerFrequencies center frequency (MHz) per segment + * \param channelWidth total allocated channel width (MHz) over all segments * \param txPowerW transmit power (W) to allocate * \param guardBandwidth width of the guard band * \param minInnerBandDbr the minimum relative power in the inner band (in dBr) @@ -127,22 +129,22 @@ class WifiSpectrumValueHelper * Transmit Power Spectral Density in W/Hz for each Band */ static Ptr CreateDuplicated20MhzTxPowerSpectralDensity( - uint16_t centerFrequency, + const std::vector& centerFrequencies, ChannelWidthMhz channelWidth, double txPowerW, ChannelWidthMhz guardBandwidth, double minInnerBandDbr = -20, double minOuterbandDbr = -28, double lowestPointDbr = -40, - const std::vector& puncturedSubchannels = std::vector{}); + const std::vector& puncturedSubchannels = {}); /** * Create a transmit power spectral density corresponding to OFDM * High Throughput (HT) (802.11n/ac). Channel width may vary between * 20, 40, 80, and 160 MHz. * - * \param centerFrequency center frequency (MHz) - * \param channelWidth channel width (MHz) + * \param centerFrequencies center frequency (MHz) per segment + * \param channelWidth total allocated channel width (MHz) over all segments * \param txPowerW transmit power (W) to allocate * \param guardBandwidth width of the guard band * \param minInnerBandDbr the minimum relative power in the inner band (in dBr) @@ -152,22 +154,23 @@ class WifiSpectrumValueHelper * \return a pointer to a newly allocated SpectrumValue representing the HT OFDM Transmit Power * Spectral Density in W/Hz for each Band */ - static Ptr CreateHtOfdmTxPowerSpectralDensity(uint16_t centerFrequency, - ChannelWidthMhz channelWidth, - double txPowerW, - ChannelWidthMhz guardBandwidth, - double minInnerBandDbr = -20, - double minOuterbandDbr = -28, - double lowestPointDbr = -40); + static Ptr CreateHtOfdmTxPowerSpectralDensity( + const std::vector& centerFrequencies, + ChannelWidthMhz channelWidth, + double txPowerW, + ChannelWidthMhz guardBandwidth, + double minInnerBandDbr = -20, + double minOuterbandDbr = -28, + double lowestPointDbr = -40); /** * Create a transmit power spectral density corresponding to OFDM - * High Efficiency (HE) (802.11ax). Channel width may vary between - * 20, 40, 80, and 160 MHz. + * High Efficiency (HE) (802.11ax) for contiguous channels. + * Channel width may vary between 20, 40, 80, and 160 MHz. * * \param centerFrequency center frequency (MHz) * \param channelWidth channel width (MHz) - * \param txPowerW transmit power (W) to allocate + * \param txPowerW transmit power (W) to allocate * \param guardBandwidth width of the guard band (MHz) * \param minInnerBandDbr the minimum relative power in the inner band (in dBr) * \param minOuterbandDbr the minimum relative power in the outer band (in dBr) @@ -185,15 +188,42 @@ class WifiSpectrumValueHelper double minInnerBandDbr = -20, double minOuterbandDbr = -28, double lowestPointDbr = -40, - const std::vector& puncturedSubchannels = std::vector{}); + const std::vector& puncturedSubchannels = {}); + + /** + * Create a transmit power spectral density corresponding to OFDM + * High Efficiency (HE) (802.11ax) made of one or more frequency segment(s). + * Channel width may vary between 20, 40, 80, and 160 MHz. + * + * \param centerFrequencies center frequency (MHz) per segment + * \param channelWidth total allocated channel width (MHz) over all segments + * \param txPowerW transmit power (W) to allocate + * \param guardBandwidth width of the guard band (MHz) + * \param minInnerBandDbr the minimum relative power in the inner band (in dBr) + * \param minOuterbandDbr the minimum relative power in the outer band (in dBr) + * \param lowestPointDbr maximum relative power of the outermost subcarriers of the guard band + * (in dBr) + * \param puncturedSubchannels bitmap indicating whether a 20 MHz subchannel is punctured or not + * \return a pointer to a newly allocated SpectrumValue representing the HE OFDM Transmit Power + * Spectral Density in W/Hz for each Band + */ + static Ptr CreateHeOfdmTxPowerSpectralDensity( + const std::vector& centerFrequencies, + uint16_t channelWidth, + double txPowerW, + uint16_t guardBandwidth, + double minInnerBandDbr = -20, + double minOuterbandDbr = -28, + double lowestPointDbr = -40, + const std::vector& puncturedSubchannels = {}); /** * Create a transmit power spectral density corresponding to the OFDMA part * of HE TB PPDUs for a given RU. * An ideal (i.e. rectangular) spectral mask is considered for the time being. * - * \param centerFrequency center frequency (MHz) - * \param channelWidth channel width (MHz) + * \param centerFrequencies center frequency (MHz) per segment + * \param channelWidth total allocated channel width (MHz) over all segments * \param txPowerW transmit power (W) to allocate * \param guardBandwidth width of the guard band (MHz) * \param ru the RU band used by the STA @@ -201,7 +231,7 @@ class WifiSpectrumValueHelper * Spectral Density on the RU used by the STA in W/Hz for each Band */ static Ptr CreateHeMuOfdmTxPowerSpectralDensity( - uint16_t centerFrequency, + const std::vector& centerFrequencies, ChannelWidthMhz channelWidth, double txPowerW, ChannelWidthMhz guardBandwidth, @@ -292,8 +322,7 @@ class WifiSpectrumValueHelper double minInnerBandDbr, double minOuterbandDbr, double lowestPointDbr, - const std::vector& puncturedSubBands = - std::vector{}, + const std::vector& puncturedSubBands = {}, uint32_t puncturedSlopeWidth = 0); /** diff --git a/src/wifi/test/wifi-phy-ofdma-test.cc b/src/wifi/test/wifi-phy-ofdma-test.cc index 999b538e1..8042fbcbc 100644 --- a/src/wifi/test/wifi-phy-ofdma-test.cc +++ b/src/wifi/test/wifi-phy-ofdma-test.cc @@ -2465,7 +2465,7 @@ TestMultipleHeTbPreambles::RxHeTbPpdu(uint64_t uid, ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION); const auto band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId); Ptr rxPsdOfdma = - WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity(DEFAULT_FREQUENCY, + WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity({DEFAULT_FREQUENCY}, DEFAULT_CHANNEL_WIDTH, txPowerWatts, DEFAULT_GUARD_WIDTH, diff --git a/src/wifi/test/wifi-transmit-mask-test.cc b/src/wifi/test/wifi-transmit-mask-test.cc index 54c7517bf..c93b10349 100644 --- a/src/wifi/test/wifi-transmit-mask-test.cc +++ b/src/wifi/test/wifi-transmit-mask-test.cc @@ -198,7 +198,7 @@ WifiOfdmMaskSlopesTestCase::DoSetup() case WIFI_STANDARD_80211n: NS_ASSERT(m_channelWidth == 20 || m_channelWidth == 40); m_actualSpectrum = - WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity(freq, + WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity({freq}, m_channelWidth, refTxPowerW, m_channelWidth, @@ -212,7 +212,7 @@ WifiOfdmMaskSlopesTestCase::DoSetup() NS_ASSERT(m_channelWidth == 20 || m_channelWidth == 40 || m_channelWidth == 80 || m_channelWidth == 160); m_actualSpectrum = - WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity(freq, + WifiSpectrumValueHelper::CreateHtOfdmTxPowerSpectralDensity({freq}, m_channelWidth, refTxPowerW, m_channelWidth,