A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
yans-error-rate-model.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 * Sébastien Deronne <sebastien.deronne@gmail.com>
8 */
9
11
12#include "wifi-tx-vector.h"
13#include "wifi-utils.h"
14
15#include "ns3/log.h"
16
17#include <cmath>
18
19namespace ns3
20{
21
22NS_LOG_COMPONENT_DEFINE("YansErrorRateModel");
23
24NS_OBJECT_ENSURE_REGISTERED(YansErrorRateModel);
25
26TypeId
28{
29 static TypeId tid = TypeId("ns3::YansErrorRateModel")
31 .SetGroupName("Wifi")
32 .AddConstructor<YansErrorRateModel>();
33 return tid;
34}
35
39
40double
41YansErrorRateModel::GetBpskBer(double snr, uint32_t signalSpread, uint64_t phyRate) const
42{
43 NS_LOG_FUNCTION(this << snr << signalSpread << phyRate);
44 double EbNo = snr * signalSpread / phyRate;
45 double z = std::sqrt(EbNo);
46 double ber = 0.5 * erfc(z);
47 NS_LOG_INFO("bpsk snr=" << snr << " ber=" << ber);
48 return ber;
49}
50
51double
53 unsigned int m,
54 uint32_t signalSpread,
55 uint64_t phyRate) const
56{
57 NS_LOG_FUNCTION(this << snr << m << signalSpread << phyRate);
58 double EbNo = snr * signalSpread / phyRate;
59 double z = std::sqrt((1.5 * log2(m) * EbNo) / (m - 1.0));
60 double z1 = ((1.0 - 1.0 / std::sqrt(m)) * erfc(z));
61 double z2 = 1 - std::pow((1 - z1), 2);
62 double ber = z2 / log2(m);
63 NS_LOG_INFO("Qam m=" << m << " rate=" << phyRate << " snr=" << snr << " ber=" << ber);
64 return ber;
65}
66
69{
70 uint32_t fact = 1;
71 while (k > 0)
72 {
73 fact *= k;
74 k--;
75 }
76 return fact;
77}
78
79double
81{
82 double retval = Factorial(n) / (Factorial(k) * Factorial(n - k)) *
83 std::pow(p, static_cast<double>(k)) *
84 std::pow(1 - p, static_cast<double>(n - k));
85 return retval;
86}
87
88double
89YansErrorRateModel::CalculatePdOdd(double ber, unsigned int d) const
90{
91 NS_ASSERT((d % 2) == 1);
92 unsigned int dstart = (d + 1) / 2;
93 unsigned int dend = d;
94 double pd = 0;
95
96 for (unsigned int i = dstart; i < dend; i++)
97 {
98 pd += Binomial(i, ber, d);
99 }
100 return pd;
101}
102
103double
104YansErrorRateModel::CalculatePdEven(double ber, unsigned int d) const
105{
106 NS_ASSERT((d % 2) == 0);
107 unsigned int dstart = d / 2 + 1;
108 unsigned int dend = d;
109 double pd = 0;
110
111 for (unsigned int i = dstart; i < dend; i++)
112 {
113 pd += Binomial(i, ber, d);
114 }
115 pd += 0.5 * Binomial(d / 2, ber, d);
116
117 return pd;
118}
119
120double
121YansErrorRateModel::CalculatePd(double ber, unsigned int d) const
122{
123 NS_LOG_FUNCTION(this << ber << d);
124 double pd;
125 if ((d % 2) == 0)
126 {
127 pd = CalculatePdEven(ber, d);
128 }
129 else
130 {
131 pd = CalculatePdOdd(ber, d);
132 }
133 return pd;
134}
135
136double
138 uint64_t nbits,
139 uint32_t signalSpread,
140 uint64_t phyRate,
141 uint32_t dFree,
142 uint32_t adFree) const
143{
144 NS_LOG_FUNCTION(this << snr << nbits << signalSpread << phyRate << dFree << adFree);
145 double ber = GetBpskBer(snr, signalSpread, phyRate);
146 if (ber == 0.0)
147 {
148 return 1.0;
149 }
150 double pd = CalculatePd(ber, dFree);
151 double pmu = adFree * pd;
152 pmu = std::min(pmu, 1.0);
153 double pms = std::pow(1 - pmu, nbits);
154 return pms;
155}
156
157double
159 uint64_t nbits,
160 uint32_t signalSpread,
161 uint64_t phyRate,
162 uint32_t m,
163 uint32_t dFree,
164 uint32_t adFree,
165 uint32_t adFreePlusOne) const
166{
167 NS_LOG_FUNCTION(this << snr << nbits << signalSpread << phyRate << m << dFree << adFree
168 << adFreePlusOne);
169 double ber = GetQamBer(snr, m, signalSpread, phyRate);
170 if (ber == 0.0)
171 {
172 return 1.0;
173 }
174 /* first term */
175 double pd = CalculatePd(ber, dFree);
176 double pmu = adFree * pd;
177 /* second term */
178 pd = CalculatePd(ber, dFree + 1);
179 pmu += adFreePlusOne * pd;
180 pmu = std::min(pmu, 1.0);
181 double pms = std::pow(1 - pmu, nbits);
182 return pms;
183}
184
185double
187 const WifiTxVector& txVector,
188 double snr,
189 uint64_t nbits,
190 uint8_t numRxAntennas,
191 WifiPpduField field,
192 uint16_t staId) const
193{
194 NS_LOG_FUNCTION(this << mode << txVector << snr << nbits << +numRxAntennas << field << staId);
196 {
197 uint64_t phyRate;
198 if ((txVector.IsMu() && (staId == SU_STA_ID)) || (mode != txVector.GetMode(staId)))
199 {
200 phyRate = mode.GetPhyRate(txVector.GetChannelWidth() >= 40
201 ? 20
202 : txVector.GetChannelWidth()); // This is the PHY header
203 }
204 else
205 {
206 phyRate = mode.GetPhyRate(txVector, staId);
207 }
208 if (mode.GetConstellationSize() == 2)
209 {
210 if (mode.GetCodeRate() == WIFI_CODE_RATE_1_2)
211 {
212 return GetFecBpskBer(snr,
213 nbits,
214 txVector.GetChannelWidth() * 1000000, // signal spread
215 phyRate, // PHY rate
216 10, // dFree
217 11); // adFree
218 }
219 else
220 {
221 return GetFecBpskBer(snr,
222 nbits,
223 txVector.GetChannelWidth() * 1000000, // signal spread
224 phyRate, // PHY rate
225 5, // dFree
226 8); // adFree
227 }
228 }
229 else if (mode.GetConstellationSize() == 4)
230 {
231 if (mode.GetCodeRate() == WIFI_CODE_RATE_1_2)
232 {
233 return GetFecQamBer(snr,
234 nbits,
235 txVector.GetChannelWidth() * 1000000, // signal spread
236 phyRate, // PHY rate
237 4, // m
238 10, // dFree
239 11, // adFree
240 0); // adFreePlusOne
241 }
242 else
243 {
244 return GetFecQamBer(snr,
245 nbits,
246 txVector.GetChannelWidth() * 1000000, // signal spread
247 phyRate, // PHY rate
248 4, // m
249 5, // dFree
250 8, // adFree
251 31); // adFreePlusOne
252 }
253 }
254 else if (mode.GetConstellationSize() == 16)
255 {
256 if (mode.GetCodeRate() == WIFI_CODE_RATE_1_2)
257 {
258 return GetFecQamBer(snr,
259 nbits,
260 txVector.GetChannelWidth() * 1000000, // signal spread
261 phyRate, // PHY rate
262 16, // m
263 10, // dFree
264 11, // adFree
265 0); // adFreePlusOne
266 }
267 else
268 {
269 return GetFecQamBer(snr,
270 nbits,
271 txVector.GetChannelWidth() * 1000000, // signal spread
272 phyRate, // PHY rate
273 16, // m
274 5, // dFree
275 8, // adFree
276 31); // adFreePlusOne
277 }
278 }
279 else if (mode.GetConstellationSize() == 64)
280 {
281 if (mode.GetCodeRate() == WIFI_CODE_RATE_2_3)
282 {
283 return GetFecQamBer(snr,
284 nbits,
285 txVector.GetChannelWidth() * 1000000, // signal spread
286 phyRate, // PHY rate
287 64, // m
288 6, // dFree
289 1, // adFree
290 16); // adFreePlusOne
291 }
292 if (mode.GetCodeRate() == WIFI_CODE_RATE_5_6)
293 {
294 // Table B.32 in Pâl Frenger et al., "Multi-rate Convolutional Codes".
295 return GetFecQamBer(snr,
296 nbits,
297 txVector.GetChannelWidth() * 1000000, // signal spread
298 phyRate, // PHY rate
299 64, // m
300 4, // dFree
301 14, // adFree
302 69); // adFreePlusOne
303 }
304 else
305 {
306 return GetFecQamBer(snr,
307 nbits,
308 txVector.GetChannelWidth() * 1000000, // signal spread
309 phyRate, // PHY rate
310 64, // m
311 5, // dFree
312 8, // adFree
313 31); // adFreePlusOne
314 }
315 }
316 else if (mode.GetConstellationSize() == 256)
317 {
318 if (mode.GetCodeRate() == WIFI_CODE_RATE_5_6)
319 {
320 return GetFecQamBer(snr,
321 nbits,
322 txVector.GetChannelWidth() * 1000000, // signal spread
323 phyRate, // PHY rate
324 256, // m
325 4, // dFree
326 14, // adFree
327 69 // adFreePlusOne
328 );
329 }
330 else
331 {
332 return GetFecQamBer(snr,
333 nbits,
334 txVector.GetChannelWidth() * 1000000, // signal spread
335 phyRate, // PHY rate
336 256, // m
337 5, // dFree
338 8, // adFree
339 31 // adFreePlusOne
340 );
341 }
342 }
343 else if (mode.GetConstellationSize() == 1024)
344 {
345 if (mode.GetCodeRate() == WIFI_CODE_RATE_5_6)
346 {
347 return GetFecQamBer(snr,
348 nbits,
349 txVector.GetChannelWidth() * 1000000, // signal spread
350 phyRate, // PHY rate
351 1024, // m
352 4, // dFree
353 14, // adFree
354 69 // adFreePlusOne
355 );
356 }
357 else
358 {
359 return GetFecQamBer(snr,
360 nbits,
361 txVector.GetChannelWidth() * 1000000, // signal spread
362 phyRate, // PHY rate
363 1024, // m
364 5, // dFree
365 8, // adFree
366 31 // adFreePlusOne
367 );
368 }
369 }
370 else if (mode.GetConstellationSize() == 4096)
371 {
372 if (mode.GetCodeRate() == WIFI_CODE_RATE_5_6)
373 {
374 return GetFecQamBer(snr,
375 nbits,
376 txVector.GetChannelWidth() * 1000000, // signal spread
377 phyRate, // PHY rate
378 4096, // m
379 4, // dFree
380 14, // adFree
381 69 // adFreePlusOne
382 );
383 }
384 else
385 {
386 return GetFecQamBer(snr,
387 nbits,
388 txVector.GetChannelWidth() * 1000000, // signal spread
389 phyRate, // PHY rate
390 4096, // m
391 5, // dFree
392 8, // adFree
393 31 // adFreePlusOne
394 );
395 }
396 }
397 }
398 return 0;
399}
400
401} // namespace ns3
the interface for Wifi's error models
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
represent a single transmission mode
Definition wifi-mode.h:40
uint16_t GetConstellationSize() const
Definition wifi-mode.cc:130
WifiModulationClass GetModulationClass() const
Definition wifi-mode.cc:174
uint64_t GetPhyRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:80
WifiCodeRate GetCodeRate() const
Definition wifi-mode.cc:123
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
MHz_u GetChannelWidth() const
Model the error rate for different modulations.
double GetFecBpskBer(double snr, uint64_t nbits, uint32_t signalSpread, uint64_t phyRate, uint32_t dFree, uint32_t adFree) const
double DoGetChunkSuccessRate(WifiMode mode, const WifiTxVector &txVector, double snr, uint64_t nbits, uint8_t numRxAntennas, WifiPpduField field, uint16_t staId) const override
A pure virtual method that must be implemented in the subclass.
static TypeId GetTypeId()
Get the type ID.
double Binomial(uint32_t k, double p, uint32_t n) const
Return Binomial distribution for a given k, p, and n.
double CalculatePdEven(double ber, unsigned int d) const
double GetQamBer(double snr, unsigned int m, uint32_t signalSpread, uint64_t phyRate) const
Return BER of QAM-m with the given parameters.
uint32_t Factorial(uint32_t k) const
Return k!
double CalculatePdOdd(double ber, unsigned int d) const
double GetFecQamBer(double snr, uint64_t nbits, uint32_t signalSpread, uint64_t phyRate, uint32_t m, uint32_t dfree, uint32_t adFree, uint32_t adFreePlusOne) const
double CalculatePd(double ber, unsigned int d) const
double GetBpskBer(double snr, uint32_t signalSpread, uint64_t phyRate) const
Return BER of BPSK with the given parameters.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#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:264
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
WifiPpduField
The type of PPDU field (grouped for convenience)
@ WIFI_MOD_CLASS_ERP_OFDM
ERP-OFDM (18.4)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24
@ WIFI_CODE_RATE_2_3
2/3 coding rate
@ WIFI_CODE_RATE_1_2
1/2 coding rate
@ WIFI_CODE_RATE_5_6
5/6 coding rate