diff --git a/src/lte/model/lte-spectrum-value-helper.cc b/src/lte/model/lte-spectrum-value-helper.cc index 7283cee9f..83fbb9df3 100644 --- a/src/lte/model/lte-spectrum-value-helper.cc +++ b/src/lte/model/lte-spectrum-value-helper.cc @@ -16,14 +16,119 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Giuseppe Piro + * Nicola Baldo */ -#include "lte-spectrum-value-helper.h" +#include #include +#include "lte-spectrum-value-helper.h" + +NS_LOG_COMPONENT_DEFINE ("LteSpectrumValueHelper"); + namespace ns3 { +/** + * Table 5.7.3-1 "E-UTRA channel numbers" from 3GPP TS 36.101 + * The table was converted to C syntax doing a cut & paste from TS 36.101 and running the following filter: + * awk '{if ((NR % 7) == 1) printf("{"); printf ("%s",$0); if ((NR % 7) == 0) printf("},\n"); else printf(", ");}' | sed 's/ – /, /g' + */ +struct EutraChannelNumbers +{ + uint8_t band; + double fDlLow; + uint16_t nOffsDl; + uint16_t rangeNdl1; + uint16_t rangeNdl2; + double fUlLow; + uint16_t nOffsUl; + uint16_t rangeNul1; + uint16_t rangeNul2; +} g_eutraChannelNumbers[] = { + {1, 2110, 0, 0, 599, 1920, 18000, 18000, 18599}, + {2, 1930, 600, 600, 1199, 1850, 18600, 18600, 19199}, + {3, 1805, 1200, 1200, 1949, 1710, 19200, 19200, 19949}, + {4, 2110, 1950, 1950, 2399, 1710, 19950, 19950, 20399}, + {5, 869, 2400, 2400, 2649, 824, 20400, 20400, 20649}, + {6, 875, 2650, 2650, 2749, 830, 20650, 20650, 20749}, + {7, 2620, 2750, 2750, 3449, 2500, 20750, 20750, 21449}, + {8, 925, 3450, 3450, 3799, 880, 21450, 21450, 21799}, + {9, 1844.9, 3800, 3800, 4149, 1749.9, 21800, 21800, 22149}, + {10, 2110, 4150, 4150, 4749, 1710, 22150, 22150, 22749}, + {11, 1475.9, 4750, 4750, 4949, 1427.9, 22750, 22750, 22949}, + {12, 728, 5000, 5000, 5179, 698, 23000, 23000, 23179}, + {13, 746, 5180, 5180, 5279, 777, 23180, 23180, 23279}, + {14, 758, 5280, 5280, 5379, 788, 23280, 23280, 23379}, + {17, 734, 5730, 5730, 5849, 704, 23730, 23730, 23849}, + {18, 860, 5850, 5850, 5999, 815, 23850, 23850, 23999}, + {19, 875, 6000, 6000, 6149, 830, 24000, 24000, 24149}, + {20, 791, 6150, 6150, 6449, 832, 24150, 24150 - 24449}, + {21, 1495.9, 6450, 6450, 6599, 1447.9, 24450, 24450, 24599}, + {33, 1900, 36000, 36000, 36199, 1900, 36000, 36000, 36199}, + {34, 2010, 36200, 36200, 36349, 2010, 36200, 36200, 36349}, + {35, 1850, 36350, 36350, 36949, 1850, 36350, 36350, 36949}, + {36, 1930, 36950, 36950, 37549, 1930, 36950, 36950, 37549}, + {37, 1910, 37550, 37550, 37749, 1910, 37550, 37550, 37749}, + {38, 2570, 37750, 37750, 38249, 2570, 37750, 37750, 38249}, + {39, 1880, 38250, 38250, 38649, 1880, 38250, 38250, 38649}, + {40, 2300, 38650, 38650, 39649, 2300, 38650, 38650, 39649} +}; + +#define NUM_EUTRA_BANDS (sizeof (g_eutraChannelNumbers) / sizeof (EutraChannelNumbers)) + +double +LteSpectrumValueHelper::GetCarrierFrequency (uint16_t earfcn) +{ + NS_LOG_FUNCTION (earfcn); + if (earfcn < 7000) + { + // FDD downlink + return GetDownlinkCarrierFrequency (earfcn); + } + else + { + // either FDD uplink or TDD (for which uplink & downlink have same frequency) + return GetUplinkCarrierFrequency (earfcn); + } +} + +double +LteSpectrumValueHelper::GetDownlinkCarrierFrequency (uint16_t nDl) +{ + NS_LOG_FUNCTION (nDl); + for (uint16_t i = 0; i < NUM_EUTRA_BANDS; ++i) + { + if ((g_eutraChannelNumbers[i].rangeNdl1 <= nDl) && + (g_eutraChannelNumbers[i].rangeNdl2 >= nDl)) + { + NS_LOG_LOGIC ("entry " << i << " fDlLow=" << g_eutraChannelNumbers[i].fDlLow); + return g_eutraChannelNumbers[i].fDlLow + 0.1 * (nDl - g_eutraChannelNumbers[i].nOffsDl); + } + } + NS_LOG_ERROR ("invalid EARFCN " << nDl); + return 0.0; +} + +double +LteSpectrumValueHelper::GetUplinkCarrierFrequency (uint16_t nUl) +{ + NS_LOG_FUNCTION (nUl); + for (uint16_t i = 0; i < NUM_EUTRA_BANDS; ++i) + { + if ((g_eutraChannelNumbers[i].rangeNul1 <= nUl) && + (g_eutraChannelNumbers[i].rangeNul2 >= nUl)) + { + NS_LOG_LOGIC ("entry " << i << " fUlLow=" << g_eutraChannelNumbers[i].fUlLow); + return g_eutraChannelNumbers[i].fUlLow + 0.1 * (nUl - g_eutraChannelNumbers[i].nOffsUl); + } + } + NS_LOG_ERROR ("invalid EARFCN " << nUl); + return 0.0; +} + + + Ptr LteDownlinkSpectrumModel; Ptr LteUplinkSpectrumModel; diff --git a/src/lte/model/lte-spectrum-value-helper.h b/src/lte/model/lte-spectrum-value-helper.h index d08591938..9083dc923 100644 --- a/src/lte/model/lte-spectrum-value-helper.h +++ b/src/lte/model/lte-spectrum-value-helper.h @@ -34,6 +34,41 @@ namespace ns3 { class LteSpectrumValueHelper { public: + + + /** + * Calculates the carrier frequency from the E-UTRA Absolute + * Radio Frequency Channel Number (EARFCN) according to 3GPP TS + * 36.101 section 5.7.3 "Carrier frequency and EARFCN". + * + * \param earfcn the EARFCN + * + * \return the carrier frequency in MHz + */ + static double GetCarrierFrequency (uint16_t earfcn); + + /** + * Calculates the dowlink carrier frequency from the E-UTRA Absolute + * Radio Frequency Channel Number (EARFCN) using the formula in 3GPP TS + * 36.101 section 5.7.3 "Carrier frequency and EARFCN". + * + * \param earfcn the EARFCN + * + * \return the dowlink carrier frequency in MHz + */ + static double GetDownlinkCarrierFrequency (uint16_t earfcn); + + /** + * Calculates the uplink carrier frequency from the E-UTRA Absolute + * Radio Frequency Channel Number (EARFCN) using the formula in 3GPP TS + * 36.101 section 5.7.3 "Carrier frequency and EARFCN". + * + * \param earfcn the EARFCN + * + * \return the uplink carrier frequency in MHz + */ + static double GetUplinkCarrierFrequency (uint16_t earfcn); + /** * \brief create spectrum value * \param powerTx the power transmission in dBm diff --git a/src/lte/test/lte-test-earfcn.cc b/src/lte/test/lte-test-earfcn.cc new file mode 100644 index 000000000..755afdfc1 --- /dev/null +++ b/src/lte/test/lte-test-earfcn.cc @@ -0,0 +1,155 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + + + +#include "ns3/test.h" +#include "ns3/log.h" + +#include "ns3/lte-spectrum-value-helper.h" + +NS_LOG_COMPONENT_DEFINE ("LteTestEarfcn"); + +namespace ns3 { + +class LteEarfcnTestCase : public TestCase +{ +public: + LteEarfcnTestCase (const char* str, uint16_t earfcn, double f); + virtual ~LteEarfcnTestCase (); + +protected: + uint16_t m_earfcn; + double m_f; + + private: + virtual void DoRun (void); +}; + +LteEarfcnTestCase::LteEarfcnTestCase (const char* str, uint16_t earfcn, double f) + : TestCase (str), + m_earfcn (earfcn), + m_f (f) +{ + NS_LOG_FUNCTION (this << str << earfcn << f); +} + +LteEarfcnTestCase::~LteEarfcnTestCase () +{ +} + +void +LteEarfcnTestCase::DoRun (void) +{ + double f = LteSpectrumValueHelper::GetCarrierFrequency (m_earfcn); + NS_TEST_ASSERT_MSG_EQ_TOL (f, m_f, 0.0000001, "wrong frequency"); +} + +class LteEarfcnDlTestCase : public LteEarfcnTestCase +{ +public: + LteEarfcnDlTestCase (const char* str, uint16_t earfcn, double f); + + private: + virtual void DoRun (void); +}; + +LteEarfcnDlTestCase::LteEarfcnDlTestCase (const char* str, uint16_t earfcn, double f) + : LteEarfcnTestCase (str, earfcn, f) +{ +} + +void +LteEarfcnDlTestCase::DoRun (void) +{ + LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL); + LogComponentEnable ("LteSpectrumValueHelper", logLevel); + LogComponentEnable ("LteTestEarfcn", logLevel); + + double f = LteSpectrumValueHelper::GetDownlinkCarrierFrequency (m_earfcn); + NS_TEST_ASSERT_MSG_EQ_TOL (f, m_f, 0.0000001, "wrong frequency"); +} + + +class LteEarfcnUlTestCase : public LteEarfcnTestCase +{ +public: + LteEarfcnUlTestCase (const char* str, uint16_t earfcn, double f); + + private: + virtual void DoRun (void); +}; + +LteEarfcnUlTestCase::LteEarfcnUlTestCase (const char* str, uint16_t earfcn, double f) + : LteEarfcnTestCase (str, earfcn, f) +{ +} + +void +LteEarfcnUlTestCase::DoRun (void) +{ + double f = LteSpectrumValueHelper::GetUplinkCarrierFrequency (m_earfcn); + NS_TEST_ASSERT_MSG_EQ_TOL (f, m_f, 0.0000001, "wrong frequency"); +} + + +/** + * Test the calculation of carrier frequency based on EARFCN + */ +class LteEarfcnTestSuite : public TestSuite +{ +public: + LteEarfcnTestSuite (); +}; + +static LteEarfcnTestSuite g_lteEarfcnTestSuite; + +LteEarfcnTestSuite::LteEarfcnTestSuite () + : TestSuite ("lte-earfcn", SYSTEM) +{ + NS_LOG_FUNCTION (this); + + AddTestCase (new LteEarfcnDlTestCase ("DL EARFCN=500", 500, 2110+50)); + AddTestCase (new LteEarfcnDlTestCase ("DL EARFCN=1000", 1000, 1930+(100-60))); + AddTestCase (new LteEarfcnDlTestCase ("DL EARFCN=1301", 1301, 1805+(130.1-120))); + AddTestCase (new LteEarfcnDlTestCase ("DL EARFCN=7000", 7000, 0.0)); + AddTestCase (new LteEarfcnDlTestCase ("DL EARFCN=20000", 20000, 0.0)); + AddTestCase (new LteEarfcnDlTestCase ("DL EARFCN=50000", 50000, 0.0)); + + AddTestCase (new LteEarfcnUlTestCase ("UL EARFCN=18100", 18100, 1920 + 1810 - 1800)); + AddTestCase (new LteEarfcnUlTestCase ("UL EARFCN=19000", 19000, 1850 + 1900 - 1860)); + AddTestCase (new LteEarfcnUlTestCase ("UL EARFCN=19400", 19400, 1710 + 1940 - 1920)); + AddTestCase (new LteEarfcnUlTestCase ("UL EARFCN=10", 10, 0.0)); + AddTestCase (new LteEarfcnUlTestCase ("UL EARFCN=1000", 1000, 0.0)); + AddTestCase (new LteEarfcnUlTestCase ("UL EARFCN=50000", 50000, 0.0)); + + AddTestCase (new LteEarfcnTestCase ("EARFCN=500", 500, 2110+50)); + AddTestCase (new LteEarfcnTestCase ("EARFCN=1000", 1000, 1930+(100-60))); + AddTestCase (new LteEarfcnTestCase ("EARFCN=1301", 1301, 1805+(130.1-120))); + AddTestCase (new LteEarfcnTestCase ("EARFCN=8000", 8000, 0.0)); + AddTestCase (new LteEarfcnTestCase ("EARFCN=50000", 50000, 0.0)); + AddTestCase (new LteEarfcnTestCase ("EARFCN=18100", 18100, 1920 + 1810 - 1800)); + AddTestCase (new LteEarfcnTestCase ("EARFCN=19000", 19000, 1850 + 1900 - 1860)); + AddTestCase (new LteEarfcnTestCase ("EARFCN=19400", 19400, 1710 + 1940 - 1920)); + AddTestCase (new LteEarfcnTestCase ("EARFCN=50000", 50000, 0.0)); +} + + +} // namespace ns3 diff --git a/src/lte/wscript b/src/lte/wscript index 38372c9b2..c8442bc40 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -51,6 +51,7 @@ def build(bld): 'test/lena-test-sinr-chunk-processor.cc', 'test/lena-test-rr-ff-mac-scheduler.cc', 'test/lena-test-pf-ff-mac-scheduler.cc', + 'test/lte-test-earfcn.cc', ] headers = bld.new_task_gen('ns3header')