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