From 7f0048ef78b3264eb2d05efd311e66c0debc08c3 Mon Sep 17 00:00:00 2001 From: Sebastien Deronne Date: Sun, 8 Nov 2020 14:53:44 +0100 Subject: [PATCH] wifi: Rework calculations in NistErrorRateModel --- src/wifi/model/nist-error-rate-model.cc | 222 +++++------------------- src/wifi/model/nist-error-rate-model.h | 106 ++++------- 2 files changed, 69 insertions(+), 259 deletions(-) diff --git a/src/wifi/model/nist-error-rate-model.cc b/src/wifi/model/nist-error-rate-model.cc index fbdfac231..5380bfa0d 100644 --- a/src/wifi/model/nist-error-rate-model.cc +++ b/src/wifi/model/nist-error-rate-model.cc @@ -19,9 +19,11 @@ * Sébastien Deronne */ +#include +#include #include "ns3/log.h" #include "nist-error-rate-model.h" -#include "wifi-phy.h" +#include "wifi-tx-vector.h" namespace ns3 { @@ -65,50 +67,21 @@ NistErrorRateModel::GetQpskBer (double snr) const } double -NistErrorRateModel::Get16QamBer (double snr) const +NistErrorRateModel::GetQamBer (uint16_t constellationSize, double snr) const { - NS_LOG_FUNCTION (this << snr); - double z = std::sqrt (snr / (5.0 * 2.0)); - double ber = 0.75 * 0.5 * erfc (z); - NS_LOG_INFO ("16-Qam" << " snr=" << snr << " ber=" << ber); + NS_LOG_FUNCTION (this << constellationSize << snr); + NS_ASSERT (std::bitset<16> (constellationSize).count () == 1); //constellationSize has to be a power of 2 + double z = std::sqrt (snr / ((2 * (constellationSize - 1)) / 3)); + uint8_t bitsPerSymbol = std::sqrt (constellationSize); + double ber = ((bitsPerSymbol - 1) / (bitsPerSymbol * std::log2 (bitsPerSymbol))) * erfc (z); + NS_LOG_INFO (constellationSize << "-QAM: snr=" << snr << " ber=" << ber); return ber; } double -NistErrorRateModel::Get64QamBer (double snr) const +NistErrorRateModel::GetFecBpskBer (double snr, uint64_t nbits, uint8_t bValue) const { - NS_LOG_FUNCTION (this << snr); - double z = std::sqrt (snr / (21.0 * 2.0)); - double ber = 7.0 / 12.0 * 0.5 * erfc (z); - NS_LOG_INFO ("64-Qam" << " snr=" << snr << " ber=" << ber); - return ber; -} - -double -NistErrorRateModel::Get256QamBer (double snr) const -{ - NS_LOG_FUNCTION (this << snr); - double z = std::sqrt (snr / (85.0 * 2.0)); - double ber = 15.0 / 32.0 * 0.5 * erfc (z); - NS_LOG_INFO ("256-Qam" << " snr=" << snr << " ber=" << ber); - return ber; -} - -double -NistErrorRateModel::Get1024QamBer (double snr) const -{ - NS_LOG_FUNCTION (this << snr); - double z = std::sqrt (snr / (341.0 * 2.0)); - double ber = 31.0 / 80.0 * 0.5 * erfc (z); - NS_LOG_INFO ("1024-Qam" << " snr=" << snr << " ber=" << ber); - return ber; -} - -double -NistErrorRateModel::GetFecBpskBer (double snr, uint64_t nbits, - uint32_t bValue) const -{ - NS_LOG_FUNCTION (this << snr << nbits << bValue); + NS_LOG_FUNCTION (this << snr << nbits << +bValue); double ber = GetBpskBer (snr); if (ber == 0.0) { @@ -121,10 +94,9 @@ NistErrorRateModel::GetFecBpskBer (double snr, uint64_t nbits, } double -NistErrorRateModel::GetFecQpskBer (double snr, uint64_t nbits, - uint32_t bValue) const +NistErrorRateModel::GetFecQpskBer (double snr, uint64_t nbits, uint8_t bValue) const { - NS_LOG_FUNCTION (this << snr << nbits << bValue); + NS_LOG_FUNCTION (this << snr << nbits << +bValue); double ber = GetQpskBer (snr); if (ber == 0.0) { @@ -137,9 +109,9 @@ NistErrorRateModel::GetFecQpskBer (double snr, uint64_t nbits, } double -NistErrorRateModel::CalculatePe (double p, uint32_t bValue) const +NistErrorRateModel::CalculatePe (double p, uint8_t bValue) const { - NS_LOG_FUNCTION (this << p << bValue); + NS_LOG_FUNCTION (this << p << +bValue); double D = std::sqrt (4.0 * p * (1.0 - p)); double pe = 1.0; if (bValue == 1) @@ -209,11 +181,10 @@ NistErrorRateModel::CalculatePe (double p, uint32_t bValue) const } double -NistErrorRateModel::GetFec16QamBer (double snr, uint64_t nbits, - uint32_t bValue) const +NistErrorRateModel::GetFecQamBer (uint16_t constellationSize, double snr, uint64_t nbits, uint8_t bValue) const { - NS_LOG_FUNCTION (this << snr << nbits << bValue); - double ber = Get16QamBer (snr); + NS_LOG_FUNCTION (this << constellationSize << snr << nbits << +bValue); + double ber = GetQamBer (constellationSize, snr); if (ber == 0.0) { return 1.0; @@ -224,52 +195,25 @@ NistErrorRateModel::GetFec16QamBer (double snr, uint64_t nbits, return pms; } -double -NistErrorRateModel::GetFec64QamBer (double snr, uint64_t nbits, - uint32_t bValue) const +uint8_t +NistErrorRateModel::GetBValue (WifiCodeRate codeRate) const { - NS_LOG_FUNCTION (this << snr << nbits << bValue); - double ber = Get64QamBer (snr); - if (ber == 0.0) + switch (codeRate) { - return 1.0; + case WIFI_CODE_RATE_3_4: + return 3; + case WIFI_CODE_RATE_2_3: + return 2; + case WIFI_CODE_RATE_1_2: + return 1; + case WIFI_CODE_RATE_5_6: + return 5; + case WIFI_CODE_RATE_UNDEFINED: + default: + NS_FATAL_ERROR ("Unknown code rate"); + break; } - double pe = CalculatePe (ber, bValue); - pe = std::min (pe, 1.0); - double pms = std::pow (1 - pe, nbits); - return pms; -} - -double -NistErrorRateModel::GetFec256QamBer (double snr, uint64_t nbits, - uint32_t bValue) const -{ - NS_LOG_FUNCTION (this << snr << nbits << bValue); - double ber = Get256QamBer (snr); - if (ber == 0.0) - { - return 1.0; - } - double pe = CalculatePe (ber, bValue); - pe = std::min (pe, 1.0); - double pms = std::pow (1 - pe, nbits); - return pms; -} - -double -NistErrorRateModel::GetFec1024QamBer (double snr, uint64_t nbits, - uint32_t bValue) const -{ - NS_LOG_FUNCTION (this << snr << nbits << bValue); - double ber = Get1024QamBer (snr); - if (ber == 0.0) - { - return 1.0; - } - double pe = CalculatePe (ber, bValue); - pe = std::min (pe, 1.0); - double pms = std::pow (1 - pe, nbits); - return pms; + return 0; } double @@ -284,103 +228,15 @@ NistErrorRateModel::DoGetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, { if (mode.GetConstellationSize () == 2) { - if (mode.GetCodeRate () == WIFI_CODE_RATE_1_2) - { - return GetFecBpskBer (snr, - nbits, - 1); //b value - } - else - { - return GetFecBpskBer (snr, - nbits, - 3); //b value - } + return GetFecBpskBer (snr, nbits, GetBValue (mode.GetCodeRate ())); } else if (mode.GetConstellationSize () == 4) { - if (mode.GetCodeRate () == WIFI_CODE_RATE_1_2) - { - return GetFecQpskBer (snr, - nbits, - 1); //b value - } - else - { - return GetFecQpskBer (snr, - nbits, - 3); //b value - } + return GetFecQpskBer (snr, nbits, GetBValue (mode.GetCodeRate ())); } - else if (mode.GetConstellationSize () == 16) + else { - if (mode.GetCodeRate () == WIFI_CODE_RATE_1_2) - { - return GetFec16QamBer (snr, - nbits, - 1); //b value - } - else - { - return GetFec16QamBer (snr, - nbits, - 3); //b value - } - } - else if (mode.GetConstellationSize () == 64) - { - if (mode.GetCodeRate () == WIFI_CODE_RATE_2_3) - { - return GetFec64QamBer (snr, - nbits, - 2); //b value - } - else if (mode.GetCodeRate () == WIFI_CODE_RATE_5_6) - { - return GetFec64QamBer (snr, - nbits, - 5); //b value - } - else - { - return GetFec64QamBer (snr, - nbits, - 3); //b value - } - } - else if (mode.GetConstellationSize () == 256) - { - if (mode.GetCodeRate () == WIFI_CODE_RATE_5_6) - { - return GetFec256QamBer (snr, - nbits, - 5 // b value - ); - } - else - { - return GetFec256QamBer (snr, - nbits, - 3 // b value - ); - } - } - else if (mode.GetConstellationSize () == 1024) - { - if (mode.GetCodeRate () == WIFI_CODE_RATE_5_6) - { - return GetFec1024QamBer (snr, - nbits, - 5 // b value - ); - } - else - { - return GetFec1024QamBer (snr, - nbits, - 3 // b value - ); - } + return GetFecQamBer (mode.GetConstellationSize (), snr, nbits, GetBValue (mode.GetCodeRate ())); } } return 0; diff --git a/src/wifi/model/nist-error-rate-model.h b/src/wifi/model/nist-error-rate-model.h index a2e5f12e6..d04cf4a40 100644 --- a/src/wifi/model/nist-error-rate-model.h +++ b/src/wifi/model/nist-error-rate-model.h @@ -22,6 +22,7 @@ #define NIST_ERROR_RATE_MODEL_H #include "error-rate-model.h" +#include "wifi-mode.h" namespace ns3 { @@ -48,19 +49,27 @@ public: private: //Inherited from ErrorRateModel double DoGetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, double snr, uint64_t nbits) const; + /** + * Return the bValue such that coding rate = bValue / (bValue + 1). + * + * \param codeRate the coding rate + * + * \return the bValue such that coding rate = bValue / (bValue + 1) + */ + uint8_t GetBValue (WifiCodeRate codeRate) const; /** * Return the coded BER for the given p and b. * - * \param p the SNR ratio (not dB) + * \param p the SNR ratio (in linear scale) * \param bValue such that coding rate = bValue / (bValue + 1) * * \return the coded BER */ - double CalculatePe (double p, uint32_t bValue) const; + double CalculatePe (double p, uint8_t bValue) const; /** * Return BER of BPSK at the given SNR. * - * \param snr SNR ratio (not dB) + * \param snr SNR ratio (in linear scale) * * \return BER of BPSK at the given SNR */ @@ -68,105 +77,50 @@ private: /** * Return BER of QPSK at the given SNR. * - * \param snr SNR ratio (not dB) + * \param snr SNR ratio (in linear scale) * * \return BER of QPSK at the given SNR */ double GetQpskBer (double snr) const; /** - * Return BER of QAM16 at the given SNR. + * Return BER of QAM for a given constellation size at the given SNR. * - * \param snr SNR ratio (not dB) - * - * \return BER of QAM16 at the given SNR + * \param constellationSize the constellation size (M) + * \param snr SNR ratio (in linear scale) + * \return BER of QAM for a given constellation size at the given SNR */ - double Get16QamBer (double snr) const; - /** - * Return BER of QAM64 at the given SNR. - * - * \param snr SNR ratio (not dB) - * - * \return BER of QAM64 at the given SNR - */ - double Get64QamBer (double snr) const; - /** - * Return BER of QAM256 at the given SNR. - * - * \param snr SNR ratio (not dB) - * \return BER of QAM256 at the given SNR - */ - double Get256QamBer (double snr) const; - /** - * Return BER of QAM1024 at the given SNR. - * - * \param snr SNR ratio (not dB) - * \return BER of QAM1024 at the given SNR - */ - double Get1024QamBer (double snr) const; + double GetQamBer (uint16_t constellationSize, double snr) const; /** * Return BER of BPSK at the given SNR after applying FEC. * - * \param snr SNR ratio (not dB) + * \param snr SNR ratio (in linear scale) * \param nbits the number of bits in the chunk - * \param bValue such that coding rate = bValue / (bValue + 1) + * \param bValue the bValue such that coding rate = bValue / (bValue + 1) * * \return BER of BPSK at the given SNR after applying FEC */ - double GetFecBpskBer (double snr, uint64_t nbits, - uint32_t bValue) const; + double GetFecBpskBer (double snr, uint64_t nbits, uint8_t bValue) const; /** * Return BER of QPSK at the given SNR after applying FEC. * - * \param snr SNR ratio (not dB) + * \param snr SNR ratio (in linear scale) * \param nbits the number of bits in the chunk - * \param bValue such that coding rate = bValue / (bValue + 1) + * \param bValue the bValue such that coding rate = bValue / (bValue + 1) * * \return BER of QPSK at the given SNR after applying FEC */ - double GetFecQpskBer (double snr, uint64_t nbits, - uint32_t bValue) const; + double GetFecQpskBer (double snr, uint64_t nbits, uint8_t bValue) const; /** - * Return BER of QAM16 at the given SNR after applying FEC. + * Return BER of QAM for a given constellation size at the given SNR after applying FEC. * - * \param snr SNR ratio (not dB) + * \param constellationSize the constellation size (M) + * \param snr SNR ratio (in linear scale) * \param nbits the number of bits in the chunk - * \param bValue such that coding rate = bValue / (bValue + 1) + * \param bValue the bValue such that coding rate = bValue / (bValue + 1) * - * \return BER of QAM16 at the given SNR after applying FEC + * \return BER of QAM for a given constellation size at the given SNR after applying FEC */ - double GetFec16QamBer (double snr, uint64_t nbits, - uint32_t bValue) const; - /** - * Return BER of QAM64 at the given SNR after applying FEC. - * - * \param snr SNR ratio (not dB) - * \param nbits the number of bits in the chunk - * \param bValue such that coding rate = bValue / (bValue + 1) - * - * \return BER of QAM64 at the given SNR after applying FEC - */ - double GetFec64QamBer (double snr, uint64_t nbits, - uint32_t bValue) const; - /** - * Return BER of QAM256 at the given SNR after applying FEC. - * - * \param snr SNR ratio (not dB) - * \param nbits the number of bits in the chunk - * \param bValue such that coding rate = bValue / (bValue + 1) - * \return BER of QAM256 at the given SNR after applying FEC - */ - double GetFec256QamBer (double snr, uint64_t nbits, - uint32_t bValue) const; - /** - * Return BER of QAM1024 at the given SNR after applying FEC. - * - * \param snr SNR ratio (not dB) - * \param nbits the number of bits in the chunk - * \param bValue such that coding rate = bValue / (bValue + 1) - * \return BER of QAM1024 at the given SNR after applying FEC - */ - double GetFec1024QamBer (double snr, uint64_t nbits, - uint32_t bValue) const; + double GetFecQamBer (uint16_t constellationSize, double snr, uint64_t nbits, uint8_t bValue) const; }; } //namespace ns3