nr_common.c 32.6 KB
Newer Older
Raymond Knopp's avatar
Raymond Knopp committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/*
 * 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 config_ue.c
 * \brief common utility functions for NR (gNB and UE)
 * \author R. Knopp,
 * \date 2019
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr
 * \note
 * \warning
 */

#include <stdint.h>
#include "assertions.h"
mir's avatar
mir committed
35
#include "common/utils/assertions.h"
36
#include "nr_common.h"
37
#include <complex.h>
38

39 40
const char *duplex_mode[]={"FDD","TDD"};

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
static const uint8_t bit_reverse_table_256[] = {
    0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8,
    0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
    0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC,
    0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
    0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6,
    0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
    0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1,
    0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
    0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD,
    0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
    0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB,
    0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
    0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF};

mir's avatar
mir committed
56 57 58 59 60 61 62 63 64
void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out)
{
  DevAssert(in != NULL);
  DevAssert(out != NULL);

  for(size_t i = 0; i < sz; ++i)
    out[i] = bit_reverse_table_256[in[i]];
}

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
// Reverse bits implementation based on http://graphics.stanford.edu/~seander/bithacks.html
uint64_t reverse_bits(uint64_t in, int n_bits)
{
  // Reverse n_bits in uint64_t variable, example:
  // n_bits: 10
  // in:      10 0000 1111
  // return:  11 1100 0001

  AssertFatal(n_bits <= 64, "Maximum bits to reverse is 64, impossible to reverse %d bits!\n", n_bits);
  uint64_t rev_bits = 0;
  uint8_t *p = (uint8_t *)&in;
  uint8_t *q = (uint8_t *)&rev_bits;
  int n_bytes = n_bits >> 3;
  for (int n = 0; n < n_bytes; n++) {
    q[n_bytes - 1 - n] = bit_reverse_table_256[p[n]];
  }

  // Reverse remaining bits (not aligned with 8-bit)
  rev_bits = rev_bits << (n_bits % 8);
  for (int i = n_bytes * 8; i < n_bits; i++) {
    rev_bits |= ((in >> i) & 0x1) << (n_bits - i - 1);
  }
  return rev_bits;
}

90 91 92 93 94 95
static const int tables_5_3_2[5][12] = {
    {25, 52, 79, 106, 133, 160, 216, 270, -1, -1, -1, -1}, // 15 FR1
    {11, 24, 38, 51, 65, 78, 106, 133, 162, 217, 245, 273}, // 30 FR1
    {-1, 11, 18, 24, 31, 38, 51, 65, 79, 107, 121, 135}, // 60 FR1
    {66, 132, 264, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 60 FR2
    {32, 66, 132, 264, -1, -1, -1, -1, -1, -1, -1, -1} // 120FR2
96 97
};

98
int get_supported_band_index(int scs, frequency_range_t freq_range, int n_rbs)
99
{
100
  int scs_index = scs + freq_range;
101 102
  for (int i = 0; i < 12; i++) {
    if(n_rbs == tables_5_3_2[scs_index][i])
103 104 105 106 107 108
      return i;
  }
  return (-1); // not found
}


109 110 111 112 113 114
// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101)
// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101)
// Notes:
// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL
// - Frequencies are expressed in KHz
// - col: NR_band ul_min  ul_max  dl_min  dl_max  step  N_OFFs_DL  deltaf_raster
115
const nr_bandentry_t nr_bandtable[] = {
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
  {1,   1920000, 1980000, 2110000, 2170000, 20, 422000, 100},
  {2,   1850000, 1910000, 1930000, 1990000, 20, 386000, 100},
  {3,   1710000, 1785000, 1805000, 1880000, 20, 361000, 100},
  {5,    824000,  849000,  869000,  894000, 20, 173800, 100},
  {7,   2500000, 2570000, 2620000, 2690000, 20, 524000, 100},
  {8,    880000,  915000,  925000,  960000, 20, 185000, 100},
  {12,   698000,  716000,  729000,  746000, 20, 145800, 100},
  {14,   788000,  798000,  758000,  768000, 20, 151600, 100},
  {18,   815000,  830000,  860000,  875000, 20, 172000, 100},
  {20,   832000,  862000,  791000,  821000, 20, 158200, 100},
  {25,  1850000, 1915000, 1930000, 1995000, 20, 386000, 100},
  {26,   814000,  849000,  859000,  894000, 20, 171800, 100},
  {28,   703000,  758000,  758000,  813000, 20, 151600, 100},
  {29,      000,     000,  717000,  728000, 20, 143400, 100},
  {30,  2305000, 2315000, 2350000, 2360000, 20, 470000, 100},
  {34,  2010000, 2025000, 2010000, 2025000, 20, 402000, 100},
  {38,  2570000, 2620000, 2570000, 2630000, 20, 514000, 100},
  {39,  1880000, 1920000, 1880000, 1920000, 20, 376000, 100},
  {40,  2300000, 2400000, 2300000, 2400000, 20, 460000, 100},
  {41,  2496000, 2690000, 2496000, 2690000,  3, 499200,  15},
  {41,  2496000, 2690000, 2496000, 2690000,  6, 499200,  30},
  {47,  5855000, 5925000, 5855000, 5925000,  1, 790334,  15},
138 139
  {48,  3550000, 3700000, 3550000, 3700000,  1, 636667,  15},
  {48,  3550000, 3700000, 3550000, 3700000,  2, 636668,  30},
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
  {50,  1432000, 1517000, 1432000, 1517000, 20, 286400, 100},
  {51,  1427000, 1432000, 1427000, 1432000, 20, 285400, 100},
  {53,  2483500, 2495000, 2483500, 2495000, 20, 496700, 100},
  {65,  1920000, 2010000, 2110000, 2200000, 20, 422000, 100},
  {66,  1710000, 1780000, 2110000, 2200000, 20, 422000, 100},
  {70,  1695000, 1710000, 1995000, 2020000, 20, 399000, 100},
  {71,   663000,  698000,  617000,  652000, 20, 123400, 100},
  {74,  1427000, 1470000, 1475000, 1518000, 20, 295000, 100},
  {75,      000,     000, 1432000, 1517000, 20, 286400, 100},
  {76,      000,     000, 1427000, 1432000, 20, 285400, 100},
  {77,  3300000, 4200000, 3300000, 4200000,  1, 620000,  15},
  {77,  3300000, 4200000, 3300000, 4200000,  2, 620000,  30},
  {78,  3300000, 3800000, 3300000, 3800000,  1, 620000,  15},
  {78,  3300000, 3800000, 3300000, 3800000,  2, 620000,  30},
  {79,  4400010, 5000000, 4400010, 5000000,  1, 693334,  15},
  {79,  4400010, 5000000, 4400010, 5000000,  2, 693334,  30},
  {80,  1710000, 1785000,     000,     000, 20, 342000, 100},
  {81,   880000,  915000,     000,     000, 20, 176000, 100},
  {82,   832000,  862000,     000,     000, 20, 166400, 100},
  {83,   703000,  748000,     000,     000, 20, 140600, 100},
  {84,  1920000, 1980000,     000,     000, 20, 384000, 100},
  {86,  1710000, 1785000,     000,     000, 20, 342000, 100},
  {89,   824000,  849000,     000,     000, 20, 342000, 100},
163 164
  {90,  2496000, 2690000, 2496000, 2690000,  3, 499200,  15},
  {90,  2496000, 2690000, 2496000, 2690000,  6, 499200,  30},
165 166 167 168 169 170
  {90,  2496000, 2690000, 2496000, 2690000, 20, 499200, 100},
  {91,   832000,  862000, 1427000, 1432000, 20, 285400, 100},
  {92,   832000,  862000, 1432000, 1517000, 20, 286400, 100},
  {93,   880000,  915000, 1427000, 1432000, 20, 285400, 100},
  {94,   880000,  915000, 1432000, 1517000, 20, 286400, 100},
  {95,  2010000, 2025000,     000,     000, 20, 402000, 100},
171
  {96,  5925000, 7125000, 5925000, 7125000,  1, 795000,  15},
172 173 174 175 176 177 178 179 180 181
  {257,26500020,29500000,26500020,29500000,  1,2054166,  60},
  {257,26500080,29500000,26500080,29500000,  2,2054167, 120},
  {258,24250080,27500000,24250080,27500000,  1,2016667,  60},
  {258,24250080,27500000,24250080,27500000,  2,2016667, 120},
  {260,37000020,40000000,37000020,40000000,  1,2229166,  60},
  {260,37000080,40000000,37000080,40000000,  2,2229167, 120},
  {261,27500040,28350000,27500040,28350000,  1,2070833,  60},
  {261,27500040,28350000,27500040,28350000,  2,2070833, 120}
};

182
int get_supported_bw_mhz(frequency_range_t frequency_range, int bw_index)
183 184 185 186
{
  if (frequency_range == FR1) {
    switch (bw_index) {
      case 0 :
187
        return 5; // 5MHz
188
      case 1 :
189
        return 10;
190
      case 2 :
191
        return 15;
192
      case 3 :
193
        return 20;
194
      case 4 :
195
        return 25;
196
      case 5 :
197
        return 30;
198
      case 6 :
199
        return 40;
200
      case 7 :
201
        return 50;
202
      case 8 :
203
        return 60;
204
      case 9 :
205
        return 80;
206
      case 10 :
207
        return 90;
208
      case 11 :
209
        return 100;
210 211 212 213 214 215 216
      default :
        AssertFatal(false, "Invalid band index for FR1 %d\n", bw_index);
    }
  }
  else {
    switch (bw_index) {
      case 0 :
217
        return 50; // 50MHz
218
      case 1 :
219
        return 100;
220
      case 2 :
221
        return 200;
222
      case 3 :
223
        return 400;
224 225 226 227 228 229 230 231 232 233 234
      default :
        AssertFatal(false, "Invalid band index for FR2 %d\n", bw_index);
    }
  }
}

bool compare_relative_ul_channel_bw(int nr_band, int scs, int nb_ul, frame_type_t frame_type)
{
  // 38.101-1 section 6.2.2
  // Relative channel bandwidth <= 4% for TDD bands and <= 3% for FDD bands
  int index = get_nr_table_idx(nr_band, scs);
235
  int bw_index = get_supported_band_index(scs, nr_band > 256 ? FR2 : FR1, nb_ul);
236
  int band_size_khz = get_supported_bw_mhz(nr_band > 256 ? FR2 : FR1, bw_index) * 1000;
237 238 239 240 241
  float limit = frame_type == TDD ? 0.04 : 0.03;
  float rel_bw = (float) (2 * band_size_khz) / (float) (nr_bandtable[index].ul_max + nr_bandtable[index].ul_min);
  return rel_bw <= limit;
}

francescomani's avatar
francescomani committed
242 243
uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex)
{
244
  const int64_t dl_freq_khz = downlink_frequency / 1000;
francescomani's avatar
francescomani committed
245 246
  const int32_t  delta_duplex_khz = delta_duplex / 1000;

247
  uint64_t center_freq_diff_khz = UINT64_MAX; // 2^64
francescomani's avatar
francescomani committed
248 249
  uint16_t current_band = 0;

250
  for (int ind = 0; ind < sizeofArray(nr_bandtable); ind++) {
francescomani's avatar
francescomani committed
251 252 253 254 255 256 257 258 259

    if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max)
      continue;

    int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min;

    if (current_offset_khz != delta_duplex_khz)
      continue;

260
    int64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2;
francescomani's avatar
francescomani committed
261

262
    if (labs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){
francescomani's avatar
francescomani committed
263
      current_band = nr_bandtable[ind].band;
264
      center_freq_diff_khz = labs(dl_freq_khz - center_frequency_khz);
francescomani's avatar
francescomani committed
265 266 267 268 269 270 271 272 273 274 275
    }
  }

  printf("DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n",
        downlink_frequency, current_band, downlink_frequency+delta_duplex);

  AssertFatal(current_band != 0, "Can't find EUTRA band for frequency %"PRIu64" and duplex_spacing %u\n", downlink_frequency, delta_duplex);

  return current_band;
}

Raymond Knopp's avatar
Raymond Knopp committed
276 277 278
int NRRIV2BW(int locationAndBandwidth,int N_RB) {
  int tmp = locationAndBandwidth/N_RB;
  int tmp2 = locationAndBandwidth%N_RB;
279
  if (tmp <= ((N_RB>>1)+1) && (tmp+tmp2)<N_RB) return(tmp+1);
280
  else                      return(N_RB+1-tmp);
Raymond Knopp's avatar
Raymond Knopp committed
281 282 283 284 285 286

}

int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB) {
  int tmp = locationAndBandwidth/N_RB;
  int tmp2 = locationAndBandwidth%N_RB;
287
  if (tmp <= ((N_RB>>1)+1) && (tmp+tmp2)<N_RB) return(tmp2);
288
  else                      return(N_RB-1-tmp2);
Raymond Knopp's avatar
Raymond Knopp committed
289 290
}

291
/* TS 38.214 ch. 6.1.2.2.2 - Resource allocation type 1 for DL and UL */
292 293 294 295 296
int PRBalloc_to_locationandbandwidth0(int NPRB, int RBstart, int BWPsize)
{
  AssertFatal(NPRB>0 && (NPRB + RBstart <= BWPsize),
              "Illegal NPRB/RBstart Configuration (%d,%d) for BWPsize %d\n",
              NPRB, RBstart, BWPsize);
297

298 299 300 301
  if (NPRB <= 1 + (BWPsize >> 1))
    return (BWPsize * (NPRB - 1) + RBstart);
  else
    return (BWPsize * (BWPsize + 1 - NPRB) + (BWPsize - 1 - RBstart));
Raymond Knopp's avatar
Raymond Knopp committed
302 303
}

Raymond Knopp's avatar
Raymond Knopp committed
304 305 306
int PRBalloc_to_locationandbandwidth(int NPRB,int RBstart) {
  return(PRBalloc_to_locationandbandwidth0(NPRB,RBstart,275));
}
307

308
int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs) {
Raymond Knopp's avatar
Raymond Knopp committed
309

310 311 312 313 314
  int f;  // interleaving function
  if(R==0)
    f = k;
  else {
    int c = k/R;
francescomani's avatar
francescomani committed
315 316
    int r = k % R;
    f = (r * C + c + n_shift) % (N_regs / L);
Raymond Knopp's avatar
Raymond Knopp committed
317
  }
318
  return f;
Raymond Knopp's avatar
Raymond Knopp committed
319
}
320

321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset) {

  uint8_t count=0, start=0, start_set=0;

  uint64_t bitmap = (((uint64_t)FreqDomainResource[0])<<37)|
    (((uint64_t)FreqDomainResource[1])<<29)|
    (((uint64_t)FreqDomainResource[2])<<21)|
    (((uint64_t)FreqDomainResource[3])<<13)|
    (((uint64_t)FreqDomainResource[4])<<5)|
    (((uint64_t)FreqDomainResource[5])>>3);

  for (int i=0; i<45; i++)
    if ((bitmap>>(44-i))&1) {
      count++;
      if (!start_set) {
        start = i;
        start_set = 1;
      }
    }
  *rb_offset = 6*start;
  *n_rb = 6*count;
}

344 345
int get_nb_periods_per_frame(uint8_t tdd_period)
{
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386

  int nb_periods_per_frame;
  switch(tdd_period) {
    case 0:
      nb_periods_per_frame = 20; // 10ms/0p5ms
      break;

    case 1:
      nb_periods_per_frame = 16; // 10ms/0p625ms
      break;

    case 2:
      nb_periods_per_frame = 10; // 10ms/1ms
      break;

    case 3:
      nb_periods_per_frame = 8; // 10ms/1p25ms
      break;

    case 4:
      nb_periods_per_frame = 5; // 10ms/2ms
      break;

    case 5:
      nb_periods_per_frame = 4; // 10ms/2p5ms
      break;

    case 6:
      nb_periods_per_frame = 2; // 10ms/5ms
      break;

    case 7:
      nb_periods_per_frame = 1; // 10ms/10ms
      break;

    default:
      AssertFatal(1==0,"Undefined tdd period %d\n", tdd_period);
  }
  return nb_periods_per_frame;
}

387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
void get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs)
{
  uint32_t delta_arfcn = nrarfcn - N_OFFs;

  if(delta_arfcn % (nr_bandtable[i].step_size) != 0)
    LOG_E(NR_MAC, "nrarfcn %u is not on the channel raster for step size %lu\n", nrarfcn, nr_bandtable[i].step_size);
}

uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw)
{
  uint64_t dl_CarrierFreq_by_1k = dl_CarrierFreq / 1000;
  int bw_kHz = bw / 1000;
  uint32_t nrarfcn;
  int i = get_nr_table_idx(nr_bandP, scs_index);

402
  LOG_D(NR_MAC, "Searching for nr band %d DL Carrier frequency %llu bw %u\n", nr_bandP, (long long unsigned int)dl_CarrierFreq, bw);
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495

  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/2),
              "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/2));

  int deltaFglobal = 60;
  uint32_t N_REF_Offs = 2016667;
  uint64_t F_REF_Offs_khz = 24250080;

  if (dl_CarrierFreq < 24.25e9) {
    deltaFglobal = 15;
    N_REF_Offs = 600000;
    F_REF_Offs_khz = 3000000;
  }
  if (dl_CarrierFreq < 3e9) {
    deltaFglobal = 5;
    N_REF_Offs = 0;
    F_REF_Offs_khz = 0;
  }

  // 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)
  nrarfcn =  (((dl_CarrierFreq_by_1k - F_REF_Offs_khz) / deltaFglobal) + N_REF_Offs);
  //get_delta_arfcn(i, nrarfcn, nr_bandtable[i].N_OFFs_DL);

  return nrarfcn;
}

// This function computes the RF reference frequency from the NR-ARFCN according to 5.4.2.1 of 3GPP TS 38.104
// this function applies to both DL and UL
uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t nrarfcn)
{
  int deltaFglobal = 5;
  uint32_t N_REF_Offs = 0;
  uint64_t F_REF_Offs_khz = 0;
  uint64_t N_OFFs, frequency, freq_min;
  int i = get_nr_table_idx(nr_bandP, scs_index);

  if (nrarfcn > 599999 && nrarfcn < 2016667) {
    deltaFglobal = 15;
    N_REF_Offs = 600000;
    F_REF_Offs_khz = 3000000;
  }
  if (nrarfcn > 2016666 && nrarfcn < 3279166) {
    deltaFglobal = 60;
    N_REF_Offs = 2016667;
    F_REF_Offs_khz = 24250080;
  }

  int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index);

  if (delta_duplex <= 0){ // DL band >= UL band
    if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL
      N_OFFs = nr_bandtable[i].N_OFFs_DL;
      freq_min = nr_bandtable[i].dl_min;
    } else {// is FDD UL
      N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal;
      freq_min = nr_bandtable[i].ul_min;
    }
  } else { // UL band > DL band
    if (nrarfcn >= nr_bandtable[i].N_OFFs_DL + delta_duplex / deltaFglobal){ // is FDD UL
      N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex / deltaFglobal;
      freq_min = nr_bandtable[i].ul_min;
    } else { // is FDD DL
      N_OFFs = nr_bandtable[i].N_OFFs_DL;
      freq_min = nr_bandtable[i].dl_min;
    }
  }

  LOG_D(NR_MAC, "Frequency from NR-ARFCN for N_OFFs %lu, duplex spacing %d KHz, deltaFglobal %d KHz\n",
        N_OFFs,
        delta_duplex,
        deltaFglobal);

  AssertFatal(nrarfcn >= N_OFFs,"nrarfcn %u < N_OFFs[%d] %llu\n", nrarfcn, nr_bandtable[i].band, (long long unsigned int)N_OFFs);
  get_delta_arfcn(i, nrarfcn, N_OFFs);

  frequency = 1000 * (F_REF_Offs_khz + (nrarfcn - N_REF_Offs) * deltaFglobal);

  LOG_D(NR_MAC, "Computing frequency (nrarfcn %llu => %llu KHz (freq_min %llu KHz, NR band %d N_OFFs %llu))\n",
        (unsigned long long)nrarfcn,
        (unsigned long long)frequency/1000,
        (unsigned long long)freq_min,
        nr_bandP,
        (unsigned long long)N_OFFs);

  return frequency;
}
496

497 498 499 500 501 502 503
int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols)
{
  return (nrofDownlinkSlots + (nrofDownlinkSymbols != 0 && nrofUplinkSymbols == 0));
}

int get_dmrs_port(int nl, uint16_t dmrs_ports)
{
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520

  if (dmrs_ports == 0) return 0; // dci 1_0
  int p = -1;
  int found = -1;
  for (int i=0; i<12; i++) { // loop over dmrs ports
    if((dmrs_ports>>i)&0x01) { // check if current bit is 1
      found++;
      if (found == nl) { // found antenna port number corresponding to current layer
        p = i;
        break;
      }
    }
  }
  AssertFatal(p>-1,"No dmrs port corresponding to layer %d found\n",nl);
  return p;
}

francescomani's avatar
francescomani committed
521
frame_type_t get_frame_type(uint16_t current_band, uint8_t scs_index)
522
{
francescomani's avatar
francescomani committed
523
  frame_type_t current_type;
524 525 526 527 528 529 530
  int32_t delta_duplex = get_delta_duplex(current_band, scs_index);

  if (delta_duplex == 0)
    current_type = TDD;
  else
    current_type = FDD;

531
  LOG_I(NR_MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex);
532 533 534 535 536 537 538 539 540 541 542

  return current_type;
}

// Computes the duplex spacing (either positive or negative) in KHz
int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index)
{
  int nr_table_idx = get_nr_table_idx(nr_bandP, scs_index);

  int32_t delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min);

543
  LOG_I(NR_MAC, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band);
544 545 546 547 548

  return delta_duplex;
}

// Returns the corresponding row index of the NR table
549 550
int get_nr_table_idx(int nr_bandP, uint8_t scs_index)
{
551
  int scs_khz = 15 << scs_index;
552 553 554 555 556 557
  int supplementary_bands[] = {29, 75, 76, 80, 81, 82, 83, 84, 86, 89, 95};
  for(int j = 0; j < sizeofArray(supplementary_bands); j++) {
    AssertFatal(nr_bandP != supplementary_bands[j],
                "Band %d is a supplementary band (%d). This is not supported yet.\n",
                nr_bandP,
                supplementary_bands[j]);
558
  }
559 560
  int i;
  for (i = 0; i < sizeofArray(nr_bandtable); i++) {
561
    if (nr_bandtable[i].band == nr_bandP && nr_bandtable[i].deltaf_raster == scs_khz)
562
      break;
563 564
  }

565
  if (i == sizeofArray(nr_bandtable)) {
566 567 568
    LOG_D(PHY, "Not found same deltaf_raster == scs_khz, use only band and last deltaf_raster \n");
    for(i = sizeofArray(nr_bandtable) - 1; i >= 0; i--)
       if (nr_bandtable[i].band == nr_bandP)
569 570
         break;
  }
571

572 573 574 575 576 577 578
  AssertFatal(i >= 0 && i < sizeofArray(nr_bandtable), "band is not existing: %d\n", nr_bandP);
  LOG_D(PHY,
        "NR band table index %d (Band %d, dl_min %lu, ul_min %lu)\n",
         i,
         nr_bandtable[i].band,
         nr_bandtable[i].dl_min,
         nr_bandtable[i].ul_min);
579 580 581

  return i;
}
582

583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
int get_subband_size(int NPRB,int size) {
  // implements table  5.2.1.4-2 from 36.214
  //
  //Bandwidth part (PRBs)	Subband size (PRBs)
  // < 24	                   N/A
  //24 – 72	                   4, 8
  //73 – 144	                   8, 16
  //145 – 275	                  16, 32

  if (NPRB<24) return(1);
  if (NPRB<72) return (size==0 ? 4 : 8);
  if (NPRB<144) return (size==0 ? 8 : 16);
  if (NPRB<275) return (size==0 ? 16 : 32);
  AssertFatal(1==0,"Shouldn't get here, NPRB %d\n",NPRB);
 
}
Raymond Knopp's avatar
Raymond Knopp committed
599

600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
void get_samplerate_and_bw(int mu,
                           int n_rb,
                           int8_t threequarter_fs,
                           double *sample_rate,
                           unsigned int *samples_per_frame,
                           double *tx_bw,
                           double *rx_bw) {

  if (mu == 0) {
    switch(n_rb) {
    case 270:
      if (threequarter_fs) {
        *sample_rate=92.16e6;
        *samples_per_frame = 921600;
        *tx_bw = 50e6;
        *rx_bw = 50e6;
      } else {
        *sample_rate=61.44e6;
        *samples_per_frame = 614400;
        *tx_bw = 50e6;
        *rx_bw = 50e6;
      }
622
      break;
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
    case 216:
      if (threequarter_fs) {
        *sample_rate=46.08e6;
        *samples_per_frame = 460800;
        *tx_bw = 40e6;
        *rx_bw = 40e6;
      }
      else {
        *sample_rate=61.44e6;
        *samples_per_frame = 614400;
        *tx_bw = 40e6;
        *rx_bw = 40e6;
      }
      break;
    case 160: //30 MHz
    case 133: //25 MHz
      if (threequarter_fs) {
        AssertFatal(1==0,"N_RB %d cannot use 3/4 sampling\n",n_rb);
      }
      else {
        *sample_rate=30.72e6;
        *samples_per_frame = 307200;
        *tx_bw = 20e6;
        *rx_bw = 20e6;
      }
648
      break;
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
    case 106:
      if (threequarter_fs) {
        *sample_rate=23.04e6;
        *samples_per_frame = 230400;
        *tx_bw = 20e6;
        *rx_bw = 20e6;
      }
      else {
        *sample_rate=30.72e6;
        *samples_per_frame = 307200;
        *tx_bw = 20e6;
        *rx_bw = 20e6;
      }
      break;
    case 52:
      if (threequarter_fs) {
        *sample_rate=11.52e6;
        *samples_per_frame = 115200;
        *tx_bw = 10e6;
        *rx_bw = 10e6;
      }
      else {
        *sample_rate=15.36e6;
        *samples_per_frame = 153600;
        *tx_bw = 10e6;
        *rx_bw = 10e6;
      }
676
      break;
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
    case 25:
      if (threequarter_fs) {
        *sample_rate=5.76e6;
        *samples_per_frame = 57600;
        *tx_bw = 5e6;
        *rx_bw = 5e6;
      }
      else {
        *sample_rate=7.68e6;
        *samples_per_frame = 76800;
        *tx_bw = 5e6;
        *rx_bw = 5e6;
      }
      break;
    default:
      AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",n_rb,mu);
    }
  } else if (mu == 1) {
    switch(n_rb) {

    case 273:
      if (threequarter_fs) {
        *sample_rate=184.32e6;
        *samples_per_frame = 1843200;
        *tx_bw = 100e6;
        *rx_bw = 100e6;
      } else {
        *sample_rate=122.88e6;
        *samples_per_frame = 1228800;
        *tx_bw = 100e6;
        *rx_bw = 100e6;
      }
      break;
    case 217:
      if (threequarter_fs) {
        *sample_rate=92.16e6;
        *samples_per_frame = 921600;
        *tx_bw = 80e6;
        *rx_bw = 80e6;
      } else {
        *sample_rate=122.88e6;
        *samples_per_frame = 1228800;
        *tx_bw = 80e6;
        *rx_bw = 80e6;
      }
      break;
    case 162 :
      if (threequarter_fs) {
        AssertFatal(1==0,"N_RB %d cannot use 3/4 sampling\n",n_rb);
      }
      else {
        *sample_rate=61.44e6;
        *samples_per_frame = 614400;
        *tx_bw = 60e6;
        *rx_bw = 60e6;
      }

      break;

    case 133 :
      if (threequarter_fs) {
	AssertFatal(1==0,"N_RB %d cannot use 3/4 sampling\n",n_rb);
      }
      else {
        *sample_rate=61.44e6;
        *samples_per_frame = 614400;
        *tx_bw = 50e6;
        *rx_bw = 50e6;
      }

      break;
    case 106:
      if (threequarter_fs) {
        *sample_rate=46.08e6;
        *samples_per_frame = 460800;
        *tx_bw = 40e6;
        *rx_bw = 40e6;
      }
      else {
        *sample_rate=61.44e6;
        *samples_per_frame = 614400;
        *tx_bw = 40e6;
        *rx_bw = 40e6;
      }
     break;
    case 51:
      if (threequarter_fs) {
        *sample_rate=23.04e6;
        *samples_per_frame = 230400;
        *tx_bw = 20e6;
        *rx_bw = 20e6;
      }
      else {
        *sample_rate=30.72e6;
        *samples_per_frame = 307200;
        *tx_bw = 20e6;
        *rx_bw = 20e6;
      }
      break;
    case 24:
      if (threequarter_fs) {
        *sample_rate=11.52e6;
        *samples_per_frame = 115200;
        *tx_bw = 10e6;
        *rx_bw = 10e6;
      }
      else {
        *sample_rate=15.36e6;
        *samples_per_frame = 153600;
        *tx_bw = 10e6;
        *rx_bw = 10e6;
      }
      break;
    default:
      AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",n_rb,mu);
    }
  } else if (mu == 3) {
    switch(n_rb) {
795 796
      case 132:
      case 128:
797 798 799
        if (threequarter_fs) {
          *sample_rate=184.32e6;
          *samples_per_frame = 1843200;
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
          *tx_bw = 200e6;
          *rx_bw = 200e6;
        } else {
          *sample_rate = 245.76e6;
          *samples_per_frame = 2457600;
          *tx_bw = 200e6;
          *rx_bw = 200e6;
        }
        break;

      case 66:
      case 64:
        if (threequarter_fs) {
          *sample_rate=92.16e6;
          *samples_per_frame = 921600;
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
          *tx_bw = 100e6;
          *rx_bw = 100e6;
        } else {
          *sample_rate = 122.88e6;
          *samples_per_frame = 1228800;
          *tx_bw = 100e6;
          *rx_bw = 100e6;
        }
        break;

      case 32:
        if (threequarter_fs) {
          *sample_rate=92.16e6;
          *samples_per_frame = 921600;
          *tx_bw = 50e6;
          *rx_bw = 50e6;
        } else {
          *sample_rate=61.44e6;
          *samples_per_frame = 614400;
          *tx_bw = 50e6;
          *rx_bw = 50e6;
        }
        break;

      default:
        AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",n_rb,mu);
    }
  } else {
    AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu);
  }
}

francescomani's avatar
francescomani committed
847
// from start symbol index and nb or symbols to symbol occupation bitmap in a slot
848
uint16_t SL_to_bitmap(int startSymbolIndex, int nrOfSymbols) {
849
 return ((1<<nrOfSymbols)-1)<<startSymbolIndex;
francescomani's avatar
francescomani committed
850 851
}

852 853 854 855
int get_SLIV(uint8_t S, uint8_t L) {
  return ( (uint16_t)(((L-1)<=7)? (14*(L-1)+S) : (14*(15-L)+(13-S))) );
}

Raymond Knopp's avatar
Raymond Knopp committed
856 857 858 859 860 861 862 863 864 865 866 867 868
void SLIV2SL(int SLIV,int *S,int *L) {

  int SLIVdiv14 = SLIV/14;
  int SLIVmod14 = SLIV%14;
  // Either SLIV = 14*(L-1) + S, or SLIV = 14*(14-L+1) + (14-1-S). Condition is 0 <= L <= 14-S
  if ((SLIVdiv14 + 1) >= 0 && (SLIVdiv14 <= 13-SLIVmod14)) {
    *L=SLIVdiv14+1;
    *S=SLIVmod14;
  } else  {
    *L=15-SLIVdiv14;
    *S=13-SLIVmod14;
  }
}
869

870
int get_ssb_subcarrier_offset(uint32_t absoluteFrequencySSB, uint32_t absoluteFrequencyPointA, int scs)
871
{
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
  // for FR1 k_SSB expressed in terms of 15kHz SCS
  // for FR2 k_SSB expressed in terms of the subcarrier spacing provided by the higher-layer parameter subCarrierSpacingCommon
  // absoluteFrequencySSB and absoluteFrequencyPointA are ARFCN
  // NR-ARFCN delta frequency is 5kHz if f < 3 GHz, 15kHz for other FR1 freq and 60kHz for FR2
  const uint32_t absolute_diff = absoluteFrequencySSB - absoluteFrequencyPointA;
  int scaling = 1;
  if (absoluteFrequencyPointA < 600000) // correspond to 3GHz
    scaling = 3;
  if (scs > 2) // FR2
    scaling <<= (scs - 2);
  int sco_limit = scs == 1 ? 24 : 12;
  int subcarrier_offset = (absolute_diff / scaling) % sco_limit;
  // 30kHz is the only case where k_SSB is expressed in terms of a different SCS (15kHz)
  // the assertion is to avoid having an offset of half a subcarrier
  if (scs == 1)
    AssertFatal(subcarrier_offset % 2 == 0, "ssb offset %d invalid for scs %d\n", subcarrier_offset, scs);
  return subcarrier_offset;
889 890 891 892 893 894 895
}

uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
                                  uint32_t absoluteFrequencyPointA,
                                  int ssbSubcarrierSpacing,
                                  int frequency_range)
{
896 897
  // offset to pointA is expressed in terms of 15kHz SCS for FR1 and 60kHz for FR2
  // only difference wrt NR-ARFCN is delta frequency 5kHz if f < 3 GHz for ARFCN
898 899
  uint32_t absolute_diff = (absoluteFrequencySSB - absoluteFrequencyPointA);
  const int scaling_5khz = absoluteFrequencyPointA < 600000 ? 3 : 1;
900 901 902 903 904 905
  const int scaling = frequency_range == FR2 ? 1 << (ssbSubcarrierSpacing - 2) : 1 << ssbSubcarrierSpacing;
  const int scaled_abs_diff = absolute_diff / (scaling_5khz * scaling);
  // absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total
  const int ssb_offset_point_a = ((scaled_abs_diff / 12) - 10) * scaling;
  // Offset to point A needs to be divisible by scaling
  AssertFatal(ssb_offset_point_a % scaling == 0, "PRB offset %d not valid for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing);
906 907
  return ssb_offset_point_a;
}
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931

int get_delay_idx(int delay, int max_delay_comp)
{
  int delay_idx = max_delay_comp + delay;
  // If the measured delay is less than -MAX_DELAY_COMP, a -MAX_DELAY_COMP delay is compensated.
  delay_idx = max(delay_idx, 0);
  // If the measured delay is greater than +MAX_DELAY_COMP, a +MAX_DELAY_COMP delay is compensated.
  delay_idx = min(delay_idx, max_delay_comp << 1);
  return delay_idx;
}

void init_delay_table(uint16_t ofdm_symbol_size,
                      int max_delay_comp,
                      int max_ofdm_symbol_size,
                      c16_t delay_table[][max_ofdm_symbol_size])
{
  for (int delay = -max_delay_comp; delay <= max_delay_comp; delay++) {
    for (int k = 0; k < ofdm_symbol_size; k++) {
      double complex delay_cexp = cexp(I * (2.0 * M_PI * k * delay / ofdm_symbol_size));
      delay_table[max_delay_comp + delay][k].r = (int16_t)round(256 * creal(delay_cexp));
      delay_table[max_delay_comp + delay][k].i = (int16_t)round(256 * cimag(delay_cexp));
    }
  }
}
932 933 934 935 936

void freq2time(uint16_t ofdm_symbol_size,
               int16_t *freq_signal,
               int16_t *time_signal)
{
937 938
  const idft_size_idx_t idft_size = get_idft(ofdm_symbol_size);
  idft(idft_size, freq_signal, time_signal, 1);
939
}
940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963

void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay)
{
  freq2time(ofdm_symbol_size, (int16_t *)ls_est, (int16_t *)ch_estimates_time);

  int max_pos = delay->delay_max_pos;
  int max_val = delay->delay_max_val;
  const int sync_pos = 0;

  for (int i = 0; i < ofdm_symbol_size; i++) {
    int temp = c16amp2(ch_estimates_time[i]) >> 1;
    if (temp > max_val) {
      max_pos = i;
      max_val = temp;
    }
  }

  if (max_pos > ofdm_symbol_size / 2)
    max_pos = max_pos - ofdm_symbol_size;

  delay->delay_max_pos = max_pos;
  delay->delay_max_val = max_val;
  delay->est_delay = max_pos - sync_pos;
}
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986

void nr_timer_start(NR_timer_t *timer)
{
  timer->active = true;
  timer->counter = 0;
}

void nr_timer_stop(NR_timer_t *timer)
{
  timer->active = false;
  timer->counter = 0;
}

bool is_nr_timer_active(NR_timer_t timer)
{
  return timer.active;
}

bool nr_timer_tick(NR_timer_t *timer)
{
  bool expired = false;
  if (timer->active) {
    timer->counter += timer->step;
987 988
    if (timer->target == UINT_MAX) // infinite target, never expires
      return false;
989 990 991 992 993 994 995 996 997
    expired = nr_timer_expired(*timer);
    if (expired)
      timer->active = false;
  }
  return expired;
}

bool nr_timer_expired(NR_timer_t timer)
{
998 999
  if (timer.target == UINT_MAX) // infinite target, never expires
    return false;
1000 1001 1002
  return (timer.counter >= timer.target);
}

1003 1004 1005 1006 1007
uint32_t nr_timer_elapsed_time(NR_timer_t timer)
{
  return timer.counter;
}

1008 1009 1010 1011 1012 1013
void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t step)
{
  timer->target = target;
  timer->step = step;
  nr_timer_stop(timer);
}