/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /*! \file nr_mac_common.c * \brief Common MAC functions for NR UE and gNB * \author Florian Kaltenberger and Raymond Knopp * \date 2019 * \version 0.1 * \company Eurecom, NTUST * \email: florian.kalteberger@eurecom.fr, raymond.knopp@eurecom.fr * @ingroup _mac */ #include "LAYER2/NR_MAC_gNB/mac_proto.h" nr_bandentry_t nr_bandtable[] = { {1, 1920000, 1980000, 2110000, 2170000, 20, 422000}, {2, 1850000, 1910000, 1930000, 1990000, 20, 386000}, {3, 1710000, 1785000, 1805000, 1880000, 20, 361000}, {5, 824000, 849000, 869000, 894000, 20, 173800}, {7, 2500000, 2570000, 2620000, 2690000, 20, 524000}, {8, 880000, 915000, 925000, 960000, 20, 185000}, {12, 698000, 716000, 728000, 746000, 20, 145800}, {20, 832000, 862000, 791000, 821000, 20, 158200}, {25, 1850000, 1915000, 1930000, 1995000, 20, 386000}, {28, 703000, 758000, 758000, 813000, 20, 151600}, {34, 2010000, 2025000, 2010000, 2025000, 20, 402000}, {38, 2570000, 2620000, 2570000, 2630000, 20, 514000}, {39, 1880000, 1920000, 1880000, 1920000, 20, 376000}, {40, 2300000, 2400000, 2300000, 2400000, 20, 460000}, {41, 2496000, 2690000, 2496000, 2690000, 3, 499200}, {50, 1432000, 1517000, 1432000, 1517000, 20, 286400}, {51, 1427000, 1432000, 1427000, 1432000, 20, 285400}, {66, 1710000, 1780000, 2110000, 2200000, 20, 422000}, {70, 1695000, 1710000, 1995000, 2020000, 20, 399000}, {71, 663000, 698000, 617000, 652000, 20, 123400}, {74, 1427000, 1470000, 1475000, 1518000, 20, 295000}, {75, 000, 000, 1432000, 1517000, 20, 286400}, {76, 000, 000, 1427000, 1432000, 20, 285400}, {77, 3300000, 4200000, 3300000, 4200000, 1, 620000}, {78, 3300000, 3800000, 3300000, 3800000, 1, 620000}, {79, 4400000, 5000000, 4400000, 5000000, 2, 693334}, {80, 1710000, 1785000, 000, 000, 20, 342000}, {81, 860000, 915000, 000, 000, 20, 176000}, {82, 832000, 862000, 000, 000, 20, 166400}, {83, 703000, 748000, 000, 000, 20, 140600}, {84, 1920000, 1980000, 000, 000, 20, 384000}, {86, 1710000, 1785000, 000, 000, 20, 342000} }; #define NR_BANDTABLE_SIZE (sizeof(nr_bandtable)/sizeof(nr_bandentry_t)) void get_band(uint32_t downlink_frequency, uint16_t *current_band, int32_t *current_offset, lte_frame_type_t *current_type) { int ind; uint64_t center_frequency_khz; uint64_t center_freq_diff_khz; uint64_t dl_freq_khz = downlink_frequency/1000; center_freq_diff_khz = 999999999999999999; // 2^64 *current_band = 0; for ( ind=0; ind < sizeof(nr_bandtable) / sizeof(nr_bandtable[0]); ind++) { LOG_I(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min,nr_bandtable[ind].ul_min); if ( nr_bandtable[ind].dl_min <= dl_freq_khz && nr_bandtable[ind].dl_max >= dl_freq_khz ) { center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min)/2; if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ *current_band = nr_bandtable[ind].band; *current_offset = (nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min)*1000; center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz); if (*current_offset == 0) *current_type = TDD; else *current_type = FDD; } } } LOG_I( PHY, "DL frequency %"PRIu32": band %d, frame_type %d, UL frequency %"PRIu32"\n", downlink_frequency, *current_band, *current_type, downlink_frequency+*current_offset); AssertFatal(*current_band != 0, "Can't find EUTRA band for frequency %u\n", downlink_frequency); } uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint32_t bw) { uint64_t dl_CarrierFreq_by_1k = dl_CarrierFreq / 1000; int bw_kHz = bw / 1000; int i; LOG_I(MAC,"Searching for nr band %d DL Carrier frequency %llu bw %u\n",nr_bandP,(long long unsigned int)dl_CarrierFreq,bw); AssertFatal(nr_bandP < 86, "nr_band %d > 86\n", nr_bandP); for (i = 0; i < 30 && nr_bandtable[i].band != nr_bandP; i++); AssertFatal(dl_CarrierFreq_by_1k >= nr_bandtable[i].dl_min, "Band %d, bw %u : DL carrier frequency %llu kHz < %llu\n", nr_bandP, bw, (long long unsigned int)dl_CarrierFreq_by_1k, (long long unsigned int)nr_bandtable[i].dl_min); AssertFatal(dl_CarrierFreq_by_1k <= (nr_bandtable[i].dl_max - bw_kHz), "Band %d, dl_CarrierFreq %llu bw %u: DL carrier frequency %llu kHz > %llu\n", nr_bandP, (long long unsigned int)dl_CarrierFreq,bw, (long long unsigned int)dl_CarrierFreq_by_1k, (long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz)); int deltaFglobal; if (dl_CarrierFreq < 3e9) deltaFglobal = 5; else deltaFglobal = 15; // This is equation before Table 5.4.2.1-1 in 38101-1-f30 // F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs) return (((dl_CarrierFreq_by_1k - nr_bandtable[i].dl_min)/deltaFglobal) + nr_bandtable[i].N_OFFs_DL); } uint64_t from_nrarfcn(int nr_bandP, uint32_t dl_nrarfcn) { int i; int deltaFglobal; if (nr_bandP < 77 || nr_bandP > 79) deltaFglobal = 5; else deltaFglobal = 15; AssertFatal(nr_bandP < 87, "nr_band %d > 86\n", nr_bandP); for (i = 0; i < 31 && nr_bandtable[i].band != nr_bandP; i++); AssertFatal(dl_nrarfcn>=nr_bandtable[i].N_OFFs_DL,"dl_nrarfcn %u < N_OFFs_DL %llu\n",dl_nrarfcn, (long long unsigned int)nr_bandtable[i].N_OFFs_DL); return 1000*(nr_bandtable[i].dl_min + (dl_nrarfcn - nr_bandtable[i].N_OFFs_DL) * deltaFglobal); } int32_t get_nr_uldl_offset(int nr_bandP) { int i; for (i = 0; i < NR_BANDTABLE_SIZE && nr_bandtable[i].band != nr_bandP; i++); AssertFatal(i < NR_BANDTABLE_SIZE, "i %d >= BANDTABLE_SIZE %ld\n", i, NR_BANDTABLE_SIZE); return (nr_bandtable[i].dl_min - nr_bandtable[i].ul_min); }