A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lte-spectrum-value-helper.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Giuseppe Piro <g.piro@poliba.it>
7 * Nicola Baldo <nbaldo@cttc.es>
8 */
9
11
12#include <ns3/fatal-error.h>
13#include <ns3/log.h>
14
15#include <cmath>
16#include <map>
17
18// just needed to log a std::vector<int> properly...
19namespace std
20{
21
22/**
23 * \brief Stream insertion operator.
24 *
25 * \note This function scope is strictly local, and can not be
26 * used in other source files.
27 *
28 * \param [in] os The reference to the output stream.
29 * \param [in] v The std::vector<int>.
30 * \returns The reference to the output stream.
31 */
32ostream&
33operator<<(ostream& os, const vector<int>& v)
34{
35 auto it = v.begin();
36 while (it != v.end())
37 {
38 os << *it << " ";
39 ++it;
40 }
41 os << endl;
42 return os;
43}
44
45} // namespace std
46
47namespace ns3
48{
49
50NS_LOG_COMPONENT_DEFINE("LteSpectrumValueHelper");
51
52/**
53 * Table 5.7.3-1 "E-UTRA channel numbers" from 3GPP TS 36.101
54 * The table was converted to C syntax doing a cut & paste from TS 36.101 and running the following
55 * filter: awk '{if ((NR % 7) == 1) printf("{"); printf ("%s",$0); if ((NR % 7) == 0)
56 * printf("},\n"); else printf(", ");}' | sed 's/ – /, /g'
57 */
59{
60 uint8_t band; ///< band
61 double fDlLow; ///< DL low
62 uint32_t nOffsDl; ///< number offset DL
63 uint32_t rangeNdl1; ///< range DL 1
64 uint32_t rangeNdl2; ///< range DL 2
65 double fUlLow; ///< UL low
66 uint32_t nOffsUl; ///< number offset UL
67 uint32_t rangeNul1; ///< range UL 1
68 uint32_t rangeNul2; ///< range UL 2
69};
70
71/// Eutra channel numbers
73 {1, 2110, 0, 0, 599, 1920, 18000, 18000, 18599},
74 {2, 1930, 600, 600, 1199, 1850, 18600, 18600, 19199},
75 {3, 1805, 1200, 1200, 1949, 1710, 19200, 19200, 19949},
76 {4, 2110, 1950, 1950, 2399, 1710, 19950, 19950, 20399},
77 {5, 869, 2400, 2400, 2649, 824, 20400, 20400, 20649},
78 {6, 875, 2650, 2650, 2749, 830, 20650, 20650, 20749},
79 {7, 2620, 2750, 2750, 3449, 2500, 20750, 20750, 21449},
80 {8, 925, 3450, 3450, 3799, 880, 21450, 21450, 21799},
81 {9, 1844.9, 3800, 3800, 4149, 1749.9, 21800, 21800, 22149},
82 {10, 2110, 4150, 4150, 4749, 1710, 22150, 22150, 22749},
83 {11, 1475.9, 4750, 4750, 4949, 1427.9, 22750, 22750, 22949},
84 {12, 728, 5000, 5000, 5179, 698, 23000, 23000, 23179},
85 {13, 746, 5180, 5180, 5279, 777, 23180, 23180, 23279},
86 {14, 758, 5280, 5280, 5379, 788, 23280, 23280, 23379},
87 {17, 734, 5730, 5730, 5849, 704, 23730, 23730, 23849},
88 {18, 860, 5850, 5850, 5999, 815, 23850, 23850, 23999},
89 {19, 875, 6000, 6000, 6149, 830, 24000, 24000, 24149},
90 {20, 791, 6150, 6150, 6449, 832, 24150, 24150, 24449},
91 {21, 1495.9, 6450, 6450, 6599, 1447.9, 24450, 24450, 24599},
92 {33, 1900, 36000, 36000, 36199, 1900, 36000, 36000, 36199},
93 {34, 2010, 36200, 36200, 36349, 2010, 36200, 36200, 36349},
94 {35, 1850, 36350, 36350, 36949, 1850, 36350, 36350, 36949},
95 {36, 1930, 36950, 36950, 37549, 1930, 36950, 36950, 37549},
96 {37, 1910, 37550, 37550, 37749, 1910, 37550, 37550, 37749},
97 {38, 2570, 37750, 37750, 38249, 2570, 37750, 37750, 38249},
98 {39, 1880, 38250, 38250, 38649, 1880, 38250, 38250, 38649},
99 {40, 2300, 38650, 38650, 39649, 2300, 38650, 38650, 39649},
100};
101
102/// number of EUTRA bands
103#define NUM_EUTRA_BANDS (sizeof(g_eutraChannelNumbers) / sizeof(EutraChannelNumbers))
104
105double
107{
108 NS_LOG_FUNCTION(earfcn);
109 if (earfcn < 7000)
110 {
111 // FDD downlink
112 return GetDownlinkCarrierFrequency(earfcn);
113 }
114 else
115 {
116 // either FDD uplink or TDD (for which uplink & downlink have same frequency)
117 return GetUplinkCarrierFrequency(earfcn);
118 }
119}
120
121uint16_t
123{
124 NS_LOG_FUNCTION(nDl);
125 for (uint32_t i = 0; i < NUM_EUTRA_BANDS; ++i)
126 {
127 if (g_eutraChannelNumbers[i].rangeNdl1 <= nDl && g_eutraChannelNumbers[i].rangeNdl2 >= nDl)
128 {
129 NS_LOG_LOGIC("entry " << i << " fDlLow=" << g_eutraChannelNumbers[i].fDlLow);
130 return i;
131 }
132 }
133 NS_LOG_ERROR("invalid EARFCN " << nDl);
134 return NUM_EUTRA_BANDS;
135}
136
137uint16_t
139{
140 NS_LOG_FUNCTION(nUl);
141 for (uint32_t i = 0; i < NUM_EUTRA_BANDS; ++i)
142 {
143 if (g_eutraChannelNumbers[i].rangeNul1 <= nUl && g_eutraChannelNumbers[i].rangeNul2 >= nUl)
144 {
145 NS_LOG_LOGIC("entry " << i << " fUlLow=" << g_eutraChannelNumbers[i].fUlLow);
146 return i;
147 }
148 }
149 NS_LOG_ERROR("invalid EARFCN " << nUl);
150 return NUM_EUTRA_BANDS;
151}
152
153double
155{
156 NS_LOG_FUNCTION(nDl);
157 uint16_t i = GetDownlinkCarrierBand(nDl);
158 if (i == NUM_EUTRA_BANDS)
159 {
160 return 0.0;
161 }
162 return 1.0e6 *
164}
165
166double
168{
169 NS_LOG_FUNCTION(nUl);
170 uint16_t i = GetUplinkCarrierBand(nUl);
171 if (i == NUM_EUTRA_BANDS)
172 {
173 return 0.0;
174 }
175 return 1.0e6 *
177}
178
179double
180LteSpectrumValueHelper::GetChannelBandwidth(uint16_t transmissionBandwidth)
181{
182 NS_LOG_FUNCTION(transmissionBandwidth);
183 switch (transmissionBandwidth)
184 {
185 case 6:
186 return 1.4e6;
187 case 15:
188 return 3.0e6;
189 case 25:
190 return 5.0e6;
191 case 50:
192 return 10.0e6;
193 case 75:
194 return 15.0e6;
195 case 100:
196 return 20.0e6;
197 default:
198 NS_FATAL_ERROR("invalid bandwidth value " << transmissionBandwidth);
199 }
200}
201
202/// LteSpectrumModelId structure
204{
205 /**
206 * Constructor
207 *
208 * \param f earfcn
209 * \param b bandwidth
210 */
211 LteSpectrumModelId(uint32_t f, uint8_t b);
212 uint32_t earfcn; ///< EARFCN
213 uint16_t bandwidth; ///< bandwidth
214};
215
217 : earfcn(f),
218 bandwidth(b)
219{
220}
221
222/**
223 * Constructor
224 *
225 * \param a lhs
226 * \param b rhs
227 * \returns true if earfcn less than of if earfcn equal and bandwidth less than
228 */
229bool
231{
232 return ((a.earfcn < b.earfcn) || ((a.earfcn == b.earfcn) && (a.bandwidth < b.bandwidth)));
233}
234
235static std::map<LteSpectrumModelId, Ptr<SpectrumModel>>
236 g_lteSpectrumModelMap; ///< LTE spectrum model map
237
239LteSpectrumValueHelper::GetSpectrumModel(uint32_t earfcn, uint16_t txBandwidthConfiguration)
240{
241 NS_LOG_FUNCTION(earfcn << txBandwidthConfiguration);
243 LteSpectrumModelId key(earfcn, txBandwidthConfiguration);
244 auto it = g_lteSpectrumModelMap.find(key);
245 if (it != g_lteSpectrumModelMap.end())
246 {
247 ret = it->second;
248 }
249 else
250 {
251 double fc = GetCarrierFrequency(earfcn);
252 NS_ASSERT_MSG(fc != 0, "invalid EARFCN=" << earfcn);
253
254 double f = fc - (txBandwidthConfiguration * 180e3 / 2.0);
255 Bands rbs;
256 for (uint16_t numrb = 0; numrb < txBandwidthConfiguration; ++numrb)
257 {
258 BandInfo rb;
259 rb.fl = f;
260 f += 90e3;
261 rb.fc = f;
262 f += 90e3;
263 rb.fh = f;
264 rbs.push_back(rb);
265 }
266 ret = Create<SpectrumModel>(rbs);
267 g_lteSpectrumModelMap.insert(std::pair<LteSpectrumModelId, Ptr<SpectrumModel>>(key, ret));
268 }
269 NS_LOG_LOGIC("returning SpectrumModel::GetUid () == " << ret->GetUid());
270 return ret;
271}
272
275 uint16_t txBandwidthConfiguration,
276 double powerTx,
277 std::vector<int> activeRbs)
278{
279 NS_LOG_FUNCTION(earfcn << txBandwidthConfiguration << powerTx << activeRbs);
280
281 Ptr<SpectrumModel> model = GetSpectrumModel(earfcn, txBandwidthConfiguration);
283
284 // powerTx is expressed in dBm. We must convert it into natural unit.
285 double powerTxW = std::pow(10., (powerTx - 30) / 10);
286
287 double txPowerDensity = (powerTxW / (txBandwidthConfiguration * 180000));
288
289 for (auto it = activeRbs.begin(); it != activeRbs.end(); it++)
290 {
291 int rbId = (*it);
292 (*txPsd)[rbId] = txPowerDensity;
293 }
294
295 NS_LOG_LOGIC(*txPsd);
296
297 return txPsd;
298}
299
302 uint16_t txBandwidthConfiguration,
303 double powerTx,
304 std::map<int, double> powerTxMap,
305 std::vector<int> activeRbs)
306{
307 NS_LOG_FUNCTION(earfcn << txBandwidthConfiguration << activeRbs);
308
309 Ptr<SpectrumModel> model = GetSpectrumModel(earfcn, txBandwidthConfiguration);
311
312 // powerTx is expressed in dBm. We must convert it into natural unit.
313 double basicPowerTxW = std::pow(10., (powerTx - 30) / 10);
314
315 for (auto it = activeRbs.begin(); it != activeRbs.end(); it++)
316 {
317 int rbId = (*it);
318
319 auto powerIt = powerTxMap.find(rbId);
320
321 double txPowerDensity;
322
323 if (powerIt != powerTxMap.end())
324 {
325 double powerTxW = std::pow(10., (powerIt->second - 30) / 10);
326 txPowerDensity = (powerTxW / (txBandwidthConfiguration * 180000));
327 }
328 else
329 {
330 txPowerDensity = (basicPowerTxW / (txBandwidthConfiguration * 180000));
331 }
332
333 (*txPsd)[rbId] = txPowerDensity;
334 }
335
336 NS_LOG_LOGIC(*txPsd);
337
338 return txPsd;
339}
340
343 uint16_t txBandwidthConfiguration,
344 double powerTx,
345 std::vector<int> activeRbs)
346{
347 NS_LOG_FUNCTION(earfcn << txBandwidthConfiguration << powerTx << activeRbs);
348
349 Ptr<SpectrumModel> model = GetSpectrumModel(earfcn, txBandwidthConfiguration);
351
352 // powerTx is expressed in dBm. We must convert it into natural unit.
353 double powerTxW = std::pow(10., (powerTx - 30) / 10);
354
355 double txPowerDensity = (powerTxW / (activeRbs.size() * 180000));
356
357 for (auto it = activeRbs.begin(); it != activeRbs.end(); it++)
358 {
359 int rbId = (*it);
360 (*txPsd)[rbId] = txPowerDensity;
361 }
362
363 NS_LOG_LOGIC(*txPsd);
364
365 return txPsd;
366}
367
370 uint16_t txBandwidthConfiguration,
371 double noiseFigure)
372{
373 NS_LOG_FUNCTION(earfcn << txBandwidthConfiguration << noiseFigure);
374 Ptr<SpectrumModel> model = GetSpectrumModel(earfcn, txBandwidthConfiguration);
375 return CreateNoisePowerSpectralDensity(noiseFigure, model);
376}
377
380 Ptr<SpectrumModel> spectrumModel)
381{
382 NS_LOG_FUNCTION(noiseFigureDb << spectrumModel);
383
384 // see "LTE - From theory to practice"
385 // Section 22.4.4.2 Thermal Noise and Receiver Noise Figure
386 const double kT_dBm_Hz = -174.0; // dBm/Hz
387 double kT_W_Hz = std::pow(10.0, (kT_dBm_Hz - 30) / 10.0);
388 double noiseFigureLinear = std::pow(10.0, noiseFigureDb / 10.0);
389 double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
390
391 Ptr<SpectrumValue> noisePsd = Create<SpectrumValue>(spectrumModel);
392 (*noisePsd) = noisePowerSpectralDensity;
393 return noisePsd;
394}
395
396} // namespace ns3
static Ptr< SpectrumValue > CreateUlTxPowerSpectralDensity(uint16_t earfcn, uint16_t bandwidth, double powerTx, std::vector< int > activeRbs)
create a spectrum value representing the uplink power spectral density of a signal to be transmitted.
static Ptr< SpectrumValue > CreateNoisePowerSpectralDensity(uint32_t earfcn, uint16_t bandwidth, double noiseFigure)
create a SpectrumValue that models the power spectral density of AWGN
static Ptr< SpectrumValue > CreateTxPowerSpectralDensity(uint32_t earfcn, uint16_t bandwidth, double powerTx, std::vector< int > activeRbs)
create a spectrum value representing the power spectral density of a signal to be transmitted.
static uint16_t GetUplinkCarrierBand(uint32_t nUl)
Converts uplink EARFCN to corresponding LTE frequency band number.
static uint16_t GetDownlinkCarrierBand(uint32_t nDl)
Converts downlink EARFCN to corresponding LTE frequency band number.
static double GetChannelBandwidth(uint16_t txBandwidthConf)
static double GetUplinkCarrierFrequency(uint32_t earfcn)
Calculates the uplink carrier frequency from the E-UTRA Absolute Radio Frequency Channel Number (EARF...
static double GetCarrierFrequency(uint32_t earfcn)
Calculates the carrier frequency from the E-UTRA Absolute Radio Frequency Channel Number (EARFCN) acc...
static Ptr< SpectrumModel > GetSpectrumModel(uint32_t earfcn, uint16_t bandwidth)
static double GetDownlinkCarrierFrequency(uint32_t earfcn)
Calculates the downlink carrier frequency from the E-UTRA Absolute Radio Frequency Channel Number (EA...
Smart pointer class similar to boost::intrusive_ptr.
#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:75
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#define NUM_EUTRA_BANDS
number of EUTRA bands
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static std::map< LteSpectrumModelId, Ptr< SpectrumModel > > g_lteSpectrumModelMap
LTE spectrum model map.
static const EutraChannelNumbers g_eutraChannelNumbers[]
Eutra channel numbers.
std::vector< BandInfo > Bands
Container of BandInfo.
bool operator<(const EventId &a, const EventId &b)
Definition event-id.h:168
STL namespace.
ostream & operator<<(ostream &os, const vector< int > &v)
Stream insertion operator.
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
Table 5.7.3-1 "E-UTRA channel numbers" from 3GPP TS 36.101 The table was converted to C syntax doing ...
uint32_t nOffsDl
number offset DL
uint32_t nOffsUl
number offset UL
LteSpectrumModelId structure.
LteSpectrumModelId(uint32_t f, uint8_t b)
Constructor.