1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Manuel Requena <manuel.requena@cttc.es>
19 * Author: Marco Miozzo <marco.miozzo@cttc.es>
20 */
21
22 #include "lte-common.h"
23 #include <ns3/log.h>
24 #include <ns3/abort.h>
25
26 namespace ns3 {
27
28 NS_LOG_COMPONENT_DEFINE ("LteCommon");
29
LteFlowId_t()30 LteFlowId_t::LteFlowId_t ()
31 {
32 }
33
LteFlowId_t(const uint16_t a,const uint8_t b)34 LteFlowId_t::LteFlowId_t (const uint16_t a, const uint8_t b)
35 : m_rnti (a),
36 m_lcId (b)
37 {
38 }
39
40 /**
41 * Equality operator
42 *
43 * \param a lhs
44 * \param b rhs
45 * \returns true if "equal"
46 */
47 bool
operator ==(const LteFlowId_t & a,const LteFlowId_t & b)48 operator == (const LteFlowId_t &a, const LteFlowId_t &b)
49 {
50 return ( (a.m_rnti == b.m_rnti) && (a.m_lcId == b.m_lcId) );
51 }
52
53 /**
54 * Less than operator
55 *
56 * \param a lhs
57 * \param b rhs
58 * \returns true if "less than"
59 */
60 bool
operator <(const LteFlowId_t & a,const LteFlowId_t & b)61 operator < (const LteFlowId_t& a, const LteFlowId_t& b)
62 {
63 return ( (a.m_rnti < b.m_rnti) || ( (a.m_rnti == b.m_rnti) && (a.m_lcId < b.m_lcId) ) );
64 }
65
ImsiLcidPair_t()66 ImsiLcidPair_t::ImsiLcidPair_t ()
67 {
68 }
69
ImsiLcidPair_t(const uint64_t a,const uint8_t b)70 ImsiLcidPair_t::ImsiLcidPair_t (const uint64_t a, const uint8_t b)
71 : m_imsi (a),
72 m_lcId (b)
73 {
74 }
75
76 /**
77 * Equaity operator
78 *
79 * \param a lhs
80 * \param b rhs
81 * \returns true if "equal"
82 */
83 bool
operator ==(const ImsiLcidPair_t & a,const ImsiLcidPair_t & b)84 operator == (const ImsiLcidPair_t &a, const ImsiLcidPair_t &b)
85 {
86 return ((a.m_imsi == b.m_imsi) && (a.m_lcId == b.m_lcId));
87 }
88
89 /**
90 * Less than operator
91 *
92 * \param a lhs
93 * \param b rhs
94 * \returns true if "less than"
95 */
96 bool
operator <(const ImsiLcidPair_t & a,const ImsiLcidPair_t & b)97 operator < (const ImsiLcidPair_t& a, const ImsiLcidPair_t& b)
98 {
99 return ((a.m_imsi < b.m_imsi) || ((a.m_imsi == b.m_imsi) && (a.m_lcId
100 < b.m_lcId)));
101 }
102
103
LteUeConfig_t()104 LteUeConfig_t::LteUeConfig_t ()
105 {
106 }
107
108
109
110 /**
111 * Equality operator
112 *
113 * \param a lhs
114 * \param b rhs
115 * \returns true if "equal"
116 */
117 bool
operator ==(const LteUeConfig_t & a,const LteUeConfig_t & b)118 operator == (const LteUeConfig_t &a, const LteUeConfig_t &b)
119 {
120 return (a.m_rnti == b.m_rnti);
121 }
122
123 /**
124 * Less than operator
125 *
126 * \param a lhs
127 * \param b rhs
128 * \returns true if "less than"
129 */
130 bool
operator <(const LteUeConfig_t & a,const LteUeConfig_t & b)131 operator < (const LteUeConfig_t& a, const LteUeConfig_t& b)
132 {
133 return (a.m_rnti < b.m_rnti);
134 }
135
136
137 uint16_t
double2fpS11dot3(double val)138 LteFfConverter::double2fpS11dot3 (double val)
139 {
140 // convert from double to fixed point notation Sxxxxxxxxxxx.xxx
141 // truncate val to notation limits
142 if (val > 4095.88)
143 {
144 val = 4095.88;
145 }
146 if (val < -4096)
147 {
148 val = -4096;
149 }
150 int16_t valFp = (int16_t)(val * 8);
151 return (valFp);
152 }
153
154 double
fpS11dot3toDouble(uint16_t val)155 LteFfConverter::fpS11dot3toDouble (uint16_t val)
156 {
157 // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
158 double valD = ((int16_t)val) / 8.0;
159 return (valD);
160 }
161
162 double
getMinFpS11dot3Value()163 LteFfConverter::getMinFpS11dot3Value ()
164 {
165 return (-4096); // -4096 = 0x8000 = 1000 0000 0000 0000 b
166 }
167
168 //static double g_lowestFpS11dot3Value = -4096; // 0x8001 (1000 0000 0000 0000)
169
170
171 /// Buffer size level BSR table
172 static const uint32_t BufferSizeLevelBsrTable[64] = {
173
174 0, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91,
175 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603,
176 706, 826, 967, 1132, 1326, 1552, 1817, 2127, 2490, 2915, 3413,
177 3995, 4677, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507,
178 19325, 22624, 26487, 31009, 36304, 42502, 49759, 58255,
179 68201, 79846, 93749, 109439, 128125, 150000, 150000
180
181 };
182
183 uint32_t
BsrId2BufferSize(uint8_t val)184 BufferSizeLevelBsr::BsrId2BufferSize (uint8_t val)
185 {
186 NS_ABORT_MSG_UNLESS (val < 64, "val = " << val << " is out of range");
187 return BufferSizeLevelBsrTable[val];
188 }
189
190 uint8_t
BufferSize2BsrId(uint32_t val)191 BufferSizeLevelBsr::BufferSize2BsrId (uint32_t val)
192 {
193 int index = 0;
194 if (BufferSizeLevelBsrTable[63] < val)
195 {
196 index = 63;
197 }
198 else
199 {
200 while (BufferSizeLevelBsrTable[index] < val)
201 {
202 NS_ASSERT (index < 64);
203 index++;
204 }
205 }
206
207 return (index);
208 }
209
210
211 uint8_t
TxMode2LayerNum(uint8_t txMode)212 TransmissionModesLayers::TxMode2LayerNum (uint8_t txMode)
213 {
214 uint8_t nLayer = 0;
215 switch (txMode)
216 {
217 case 0: // Tx MODE 1: SISO
218 nLayer = 1;
219 break;
220 case 1: // Tx MODE 2: MIMO Tx Diversity
221 nLayer = 1;
222 break;
223 case 2: // Tx MODE 3: MIMO Spatial Multiplexity Open Loop
224 nLayer = 2;
225 break;
226 case 3: // Tx MODE 4: MIMO Spatial Multiplexity Closed Loop
227 nLayer = 2;
228 break;
229 case 4: // Tx MODE 5: MIMO Multi-User
230 nLayer = 2;
231 break;
232 case 5: // Tx MODE 6: Closer loop single layer percoding
233 nLayer = 1;
234 break;
235 case 6: // Tx MODE 7: Single antenna port 5
236 nLayer = 1;
237 break;
238 }
239 return (nLayer);
240 }
241
242
243 double
RsrpRange2Dbm(uint8_t range)244 EutranMeasurementMapping::RsrpRange2Dbm (uint8_t range)
245 {
246 // 3GPP TS 36.133 section 9.1.4 RSRP Measurement Report Mapping
247 NS_ASSERT_MSG (range <= 97, "value " << range << " is out of range");
248 return (double) range - 141.0;
249 }
250
251 uint8_t
Dbm2RsrpRange(double dbm)252 EutranMeasurementMapping::Dbm2RsrpRange (double dbm)
253 {
254 // 3GPP TS 36.133 section 9.1.4 RSRP Measurement Report Mapping
255 double range = std::min (std::max (std::floor (dbm + 141), 0.0), 97.0);
256 return (uint8_t) range;
257 }
258
259 double
RsrqRange2Db(uint8_t range)260 EutranMeasurementMapping::RsrqRange2Db (uint8_t range)
261 {
262 // 3GPP TS 36.133 section 9.1.7 RSRQ Measurement Report Mapping
263 NS_ASSERT_MSG (range <= 34, "value " << (uint16_t) range << " is out of range");
264 return ((double) range - 40.0)*0.5;
265 }
266
267 uint8_t
Db2RsrqRange(double db)268 EutranMeasurementMapping::Db2RsrqRange (double db)
269 {
270 // 3GPP TS 36.133 section 9.1.7 RSRQ Measurement Report Mapping
271 double range = std::min (std::max (std::floor (db*2 + 40), 0.0), 34.0);
272 return (uint8_t) range;
273 }
274
275 double
QuantizeRsrp(double v)276 EutranMeasurementMapping::QuantizeRsrp (double v)
277 {
278 return RsrpRange2Dbm (Dbm2RsrpRange (v));
279 }
280
281 double
QuantizeRsrq(double v)282 EutranMeasurementMapping::QuantizeRsrq (double v)
283 {
284 return RsrqRange2Db (Db2RsrqRange (v));
285 }
286
287 double
IeValue2ActualHysteresis(uint8_t hysteresisIeValue)288 EutranMeasurementMapping::IeValue2ActualHysteresis (uint8_t hysteresisIeValue)
289 {
290 if (hysteresisIeValue > 30)
291 {
292 NS_FATAL_ERROR ("The value " << (uint16_t) hysteresisIeValue
293 << " is out of the allowed range (0..30)"
294 << " for Hysteresis IE value");
295 }
296
297 double actual = static_cast<double> (hysteresisIeValue) * 0.5;
298 NS_ASSERT (actual >= 0.0);
299 NS_ASSERT (actual <= 15.0);
300 return actual;
301 }
302
303 uint8_t
ActualHysteresis2IeValue(double hysteresisDb)304 EutranMeasurementMapping::ActualHysteresis2IeValue (double hysteresisDb)
305 {
306 if ((hysteresisDb < 0.0) || (hysteresisDb > 15.0))
307 {
308 NS_FATAL_ERROR ("The value " << hysteresisDb
309 << " is out of the allowed range (0..15) dB"
310 << " for hysteresis");
311 }
312
313 uint8_t ieValue = lround (hysteresisDb * 2.0);
314 NS_ASSERT (ieValue <= 30);
315 return ieValue;
316 }
317
318 double
IeValue2ActualA3Offset(int8_t a3OffsetIeValue)319 EutranMeasurementMapping::IeValue2ActualA3Offset (int8_t a3OffsetIeValue)
320 {
321 if ((a3OffsetIeValue < -30) || (a3OffsetIeValue > 30))
322 {
323 NS_FATAL_ERROR ("The value " << (int16_t) a3OffsetIeValue
324 << " is out of the allowed range (-30..30)"
325 << " for a3-Offset IE value");
326 }
327
328 double actual = static_cast<double> (a3OffsetIeValue) * 0.5;
329 NS_ASSERT (actual >= -15.0);
330 NS_ASSERT (actual <= 15.0);
331 return actual;
332 }
333
334 int8_t
ActualA3Offset2IeValue(double a3OffsetDb)335 EutranMeasurementMapping::ActualA3Offset2IeValue (double a3OffsetDb)
336 {
337 if ((a3OffsetDb < -15.0) || (a3OffsetDb > 15.0))
338 {
339 NS_FATAL_ERROR ("The value " << a3OffsetDb
340 << " is out of the allowed range (-15..15) dB"
341 << " for A3 Offset");
342 }
343
344 int8_t ieValue = lround (a3OffsetDb * 2.0);
345 NS_ASSERT (ieValue >= -30);
346 NS_ASSERT (ieValue <= 30);
347 return ieValue;
348 }
349
350 double
IeValue2ActualQRxLevMin(int8_t qRxLevMinIeValue)351 EutranMeasurementMapping::IeValue2ActualQRxLevMin (int8_t qRxLevMinIeValue)
352 {
353 if ((qRxLevMinIeValue < -70) || (qRxLevMinIeValue > -22))
354 {
355 NS_FATAL_ERROR ("The value " << (int16_t) qRxLevMinIeValue
356 << " is out of the allowed range (-70..-22)"
357 << " for Q-RxLevMin IE value");
358 }
359
360 double actual = static_cast<double> (qRxLevMinIeValue) * 2;
361 NS_ASSERT (actual >= -140.0);
362 NS_ASSERT (actual <= -44.0);
363 return actual;
364 }
365
366 double
IeValue2ActualQQualMin(int8_t qQualMinIeValue)367 EutranMeasurementMapping::IeValue2ActualQQualMin (int8_t qQualMinIeValue)
368 {
369 if ((qQualMinIeValue < -34) || (qQualMinIeValue > -3))
370 {
371 NS_FATAL_ERROR ("The value " << (int16_t) qQualMinIeValue
372 << " is out of the allowed range (-34..-3)"
373 << " for Q-QualMin IE value");
374 }
375
376 double actual = static_cast<double> (qQualMinIeValue);
377 NS_ASSERT (actual >= -34.0);
378 NS_ASSERT (actual <= -3.0);
379 return actual;
380 }
381
382 }; // namespace ns3
383
384