config.c 32.1 KB
Newer Older
WEI-TAI CHEN's avatar
WEI-TAI CHEN 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
/*
 * 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.c
 * \brief gNB configuration performed by RRC or as a consequence of RRC procedures
 * \author  Navid Nikaein and Raymond Knopp, WEI-TAI CHEN
 * \date 2010 - 2014, 2018
 * \version 0.1
 * \company Eurecom, NTUST
 * \email: navid.nikaein@eurecom.fr, kroempa@gmail.com
 * @ingroup _mac

 */

33 34 35
#include "COMMON/platform_types.h"
#include "COMMON/platform_constants.h"
#include "common/ran_context.h"
36
#include "common/utils/nr/nr_common.h"
Raymond Knopp's avatar
Raymond Knopp committed
37 38
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
39 40 41 42 43

#include "NR_BCCH-BCH-Message.h"
#include "NR_ServingCellConfigCommon.h"

#include "LAYER2/NR_MAC_gNB/mac_proto.h"
44
#include "SCHED_NR/phy_frame_config_nr.h"
45

Raymond Knopp's avatar
Raymond Knopp committed
46
#include "NR_MIB.h"
47
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
Mahesh's avatar
Mahesh committed
48
#include "../../../../nfapi/oai_integration/vendor_ext.h"
49 50 51
/* Softmodem params */
#include "executables/softmodem-common.h"

52 53 54 55
extern RAN_CONTEXT_t RC;
//extern int l2_init_gNB(void);
extern void mac_top_init_gNB(void);
extern uint8_t nfapi_mode;
Raymond Knopp's avatar
Raymond Knopp committed
56

57
void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list,
58 59 60
                             struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_bearer2release_list,
                             NR_UE_sched_ctrl_t *sched_ctrl) {

61 62 63 64 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 90
  if (rlc_bearer2release_list) {
    for (int i = 0; i < rlc_bearer2release_list->list.count; i++) {
      for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) {
        if (sched_ctrl->dl_lc_ids[idx] == *rlc_bearer2release_list->list.array[i]) {
          const int remaining_lcs = sched_ctrl->dl_lc_num - idx - 1;
          memmove(&sched_ctrl->dl_lc_ids[idx], &sched_ctrl->dl_lc_ids[idx + 1], sizeof(sched_ctrl->dl_lc_ids[idx]) * remaining_lcs);
          sched_ctrl->dl_lc_num--;
          break;
        }
      }
    }
  }

  if (rlc_bearer2add_list) {
    // keep lcids
    for (int i = 0; i < rlc_bearer2add_list->list.count; i++) {
      const int lcid = rlc_bearer2add_list->list.array[i]->logicalChannelIdentity;
      bool found = false;
      for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) {
        if (sched_ctrl->dl_lc_ids[idx] == lcid) {
          found = true;
          break;
        }
      }

      if (!found) {
        sched_ctrl->dl_lc_num++;
        sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num - 1] = lcid;
        LOG_D(NR_MAC, "Adding LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid);
      }
91
    }
92 93 94 95 96
  }

  LOG_D(NR_MAC, "In %s: total num of active bearers %d) \n",
      __FUNCTION__,
      sched_ctrl->dl_lc_num);
97

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
}


void process_drx_Config(NR_UE_sched_ctrl_t *sched_ctrl,NR_SetupRelease_DRX_Config_t *drx_Config) {
 if (!drx_Config) return;
 AssertFatal(drx_Config->present != NR_SetupRelease_DRX_Config_PR_NOTHING, "Cannot have NR_SetupRelease_DRX_Config_PR_NOTHING\n");

 if (drx_Config->present == NR_SetupRelease_DRX_Config_PR_setup) {
   LOG_I(NR_MAC,"Adding DRX config\n");
 }
 else {
   LOG_I(NR_MAC,"Removing DRX config\n");
 }
}

void process_schedulingRequestConfig(NR_UE_sched_ctrl_t *sched_ctrl,NR_SchedulingRequestConfig_t *schedulingRequestConfig) {
 if (!schedulingRequestConfig) return;

   LOG_I(NR_MAC,"Adding SchedulingRequestconfig\n");
}

void process_bsrConfig(NR_UE_sched_ctrl_t *sched_ctrl,NR_BSR_Config_t *bsr_Config) {
  if (!bsr_Config) return;
  LOG_I(NR_MAC,"Adding BSR config\n");
}

void process_tag_Config(NR_UE_sched_ctrl_t *sched_ctrl,NR_TAG_Config_t *tag_Config) {
  if (!tag_Config) return;
  LOG_I(NR_MAC,"Adding TAG config\n");
}

void process_phr_Config(NR_UE_sched_ctrl_t *sched_ctrl,NR_SetupRelease_PHR_Config_t *phr_Config) {
   if (!phr_Config) return;
   AssertFatal(phr_Config->present != NR_SetupRelease_PHR_Config_PR_NOTHING, "Cannot have NR_SetupRelease_PHR_Config_PR_NOTHING\n");

   if (phr_Config->present == NR_SetupRelease_PHR_Config_PR_setup) {
     LOG_I(NR_MAC,"Adding PHR config\n");
   }
   else {
     LOG_I(NR_MAC,"Removing PHR config\n");
   }
}

void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sched_ctrl) {

   AssertFatal(CellGroup, "CellGroup is null\n");
   NR_MAC_CellGroupConfig_t   *mac_CellGroupConfig = CellGroup->mac_CellGroupConfig;
145

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160

   if (mac_CellGroupConfig) {
     process_drx_Config(sched_ctrl,mac_CellGroupConfig->drx_Config);
     process_schedulingRequestConfig(sched_ctrl,mac_CellGroupConfig->schedulingRequestConfig);
     process_bsrConfig(sched_ctrl,mac_CellGroupConfig->bsr_Config);
     process_tag_Config(sched_ctrl,mac_CellGroupConfig->tag_Config);
     process_phr_Config(sched_ctrl,mac_CellGroupConfig->phr_Config);
   }
   else {
     // apply defaults

   }

   process_rlcBearerConfig(CellGroup->rlc_BearerToAddModList,CellGroup->rlc_BearerToReleaseList,sched_ctrl);

161
}
francescomani's avatar
francescomani committed
162

163
void config_common(int Mod_idP, int pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) {
164 165 166 167 168

  nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[Mod_idP]->config[0];
  RC.nrmac[Mod_idP]->common_channels[0].ServingCellConfigCommon = scc;

  // Carrier configuration
Rakesh's avatar
Rakesh committed
169

170 171 172 173
  cfg->carrier_config.dl_bandwidth.value = config_bandwidth(scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
                                                            scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,
                                                            *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
  cfg->carrier_config.dl_bandwidth.tl.tag   = NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG; //temporary
174
  cfg->num_tlv++;
175
  LOG_I(NR_MAC,"%s() dl_BandwidthP:%d\n", __FUNCTION__, cfg->carrier_config.dl_bandwidth.value);
176

177
  cfg->carrier_config.dl_frequency.value = from_nrarfcn(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],
178
                                                        *scc->ssbSubcarrierSpacing,
179 180
                                                        scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA)/1000; // freq in kHz
  cfg->carrier_config.dl_frequency.tl.tag = NFAPI_NR_CONFIG_DL_FREQUENCY_TAG;
181 182
  cfg->num_tlv++;

183
  for (int i=0; i<5; i++) {
184 185 186 187 188 189 190 191 192 193 194 195 196
    if (i==scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) {
      cfg->carrier_config.dl_grid_size[i].value = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
      cfg->carrier_config.dl_k0[i].value = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier;
      cfg->carrier_config.dl_grid_size[i].tl.tag = NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG;
      cfg->carrier_config.dl_k0[i].tl.tag = NFAPI_NR_CONFIG_DL_K0_TAG;
      cfg->num_tlv++;
      cfg->num_tlv++;
    }
    else {
      cfg->carrier_config.dl_grid_size[i].value = 0;
      cfg->carrier_config.dl_k0[i].value = 0;
    }
  }
197

198 199 200 201
  cfg->carrier_config.uplink_bandwidth.value = config_bandwidth(scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
                                                                scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,
                                                                *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]);
  cfg->carrier_config.uplink_bandwidth.tl.tag   = NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG; //temporary
202
  cfg->num_tlv++;
203
  LOG_I(NR_MAC,"%s() dl_BandwidthP:%d\n", __FUNCTION__, cfg->carrier_config.uplink_bandwidth.value);
204

205 206 207 208 209
  int UL_pointA;
  if (scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA == NULL)
    UL_pointA = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
  else
    UL_pointA = *scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA; 
210

211
  cfg->carrier_config.uplink_frequency.value = from_nrarfcn(*scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0],
212
                                                            *scc->ssbSubcarrierSpacing,
213 214
                                                            UL_pointA)/1000; // freq in kHz
  cfg->carrier_config.uplink_frequency.tl.tag = NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG;
215 216
  cfg->num_tlv++;

217
  for (int i=0; i<5; i++) {
218 219 220 221 222 223 224 225 226 227 228 229 230
    if (i==scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) {
      cfg->carrier_config.ul_grid_size[i].value = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
      cfg->carrier_config.ul_k0[i].value = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier;
      cfg->carrier_config.ul_grid_size[i].tl.tag = NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG;
      cfg->carrier_config.ul_k0[i].tl.tag = NFAPI_NR_CONFIG_UL_K0_TAG;
      cfg->num_tlv++;
      cfg->num_tlv++;
    }
    else {
      cfg->carrier_config.ul_grid_size[i].value = 0;
      cfg->carrier_config.ul_k0[i].value = 0;
    }
  }
231

232 233
  uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
  frequency_range_t frequency_range = band<100?FR1:FR2;
234

francescomani's avatar
francescomani committed
235
  frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
236
  RC.nrmac[Mod_idP]->common_channels[0].frame_type = frame_type;
Raymond Knopp's avatar
Raymond Knopp committed
237

238 239 240
  // Cell configuration
  cfg->cell_config.phy_cell_id.value = *scc->physCellId;
  cfg->cell_config.phy_cell_id.tl.tag = NFAPI_NR_CONFIG_PHY_CELL_ID_TAG;
241 242
  cfg->num_tlv++;

243
  cfg->cell_config.frame_duplex_type.value = frame_type;
244
  cfg->cell_config.frame_duplex_type.tl.tag = NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG;
245 246 247
  cfg->num_tlv++;


248 249 250
  // SSB configuration
  cfg->ssb_config.ss_pbch_power.value = scc->ss_PBCH_BlockPower;
  cfg->ssb_config.ss_pbch_power.tl.tag = NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG;
251 252
  cfg->num_tlv++;

253 254 255 256
  cfg->ssb_config.bch_payload.value = 1;
  cfg->ssb_config.bch_payload.tl.tag = NFAPI_NR_CONFIG_BCH_PAYLOAD_TAG;
  cfg->num_tlv++;

257 258
  cfg->ssb_config.scs_common.value = *scc->ssbSubcarrierSpacing;
  cfg->ssb_config.scs_common.tl.tag = NFAPI_NR_CONFIG_SCS_COMMON_TAG;
259
  cfg->num_tlv++;
260 261 262

  // PRACH configuration

263 264 265 266
  uint8_t nb_preambles = 64;
  if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL)
     nb_preambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles;

267
  cfg->prach_config.prach_sequence_length.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present-1;
268 269 270 271 272 273 274 275
  cfg->prach_config.prach_sequence_length.tl.tag = NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG;
  cfg->num_tlv++;  

  if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
    cfg->prach_config.prach_sub_c_spacing.value = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
  else 
    cfg->prach_config.prach_sub_c_spacing.value = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
  cfg->prach_config.prach_sub_c_spacing.tl.tag = NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG;
276
  cfg->num_tlv++;
277 278
  cfg->prach_config.restricted_set_config.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig;
  cfg->prach_config.restricted_set_config.tl.tag = NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG;
279
  cfg->num_tlv++;
280 281 282
  cfg->prach_config.prach_ConfigurationIndex.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
  cfg->prach_config.prach_ConfigurationIndex.tl.tag = NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG;
  cfg->num_tlv++;
283

284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
  switch (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM) {
    case 0 :
      cfg->prach_config.num_prach_fd_occasions.value = 1;
      break;
    case 1 :
      cfg->prach_config.num_prach_fd_occasions.value = 2;
      break;
    case 2 :
      cfg->prach_config.num_prach_fd_occasions.value = 4;
      break;
    case 3 :
      cfg->prach_config.num_prach_fd_occasions.value = 8;
      break;
    default:
      AssertFatal(1==0,"msg1 FDM identifier %ld undefined (0,1,2,3) \n", scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM);
  } 
  cfg->prach_config.num_prach_fd_occasions.tl.tag = NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG;
301
  cfg->num_tlv++;
302

kn.raju's avatar
kn.raju committed
303 304 305 306
  cfg->prach_config.prach_ConfigurationIndex.value =  scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
  cfg->prach_config.prach_ConfigurationIndex.tl.tag = NFAPI_NR_CONFIG_PRACH_CONFIG_INDEX_TAG;
  cfg->num_tlv++;

307
  cfg->prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(cfg->prach_config.num_prach_fd_occasions.value*sizeof(nfapi_nr_num_prach_fd_occasions_t));
308
  for (int i=0; i<cfg->prach_config.num_prach_fd_occasions.value; i++) {
309
//    cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i;
310 311 312 313 314 315
    if (cfg->prach_config.prach_sequence_length.value)
      cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139; 
    else
      cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l839;
    cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index.tl.tag = NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG;
    cfg->num_tlv++;
316
    cfg->prach_config.num_prach_fd_occasions_list[i].k1.value = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart + (get_N_RA_RB( cfg->prach_config.prach_sub_c_spacing.value, scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing ) * i);
rmagueta's avatar
rmagueta committed
317 318 319 320 321
    if (get_softmodem_params()->sa) {
      cfg->prach_config.num_prach_fd_occasions_list[i].k1.value = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart + (get_N_RA_RB( cfg->prach_config.prach_sub_c_spacing.value, scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing ) * i);
    } else {
      cfg->prach_config.num_prach_fd_occasions_list[i].k1.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart + (get_N_RA_RB( cfg->prach_config.prach_sub_c_spacing.value, scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing ) * i);
    }
322 323 324 325 326
    cfg->prach_config.num_prach_fd_occasions_list[i].k1.tl.tag = NFAPI_NR_CONFIG_K1_TAG;
    cfg->num_tlv++;
    cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig;
    cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf.tl.tag = NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG;
    cfg->num_tlv++;
327
    cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.value = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup,nb_preambles, frame_type, frequency_range);
328 329
    cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.tl.tag = NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG;
    cfg->num_tlv++;
330
    cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences.value = 1;
331 332
  }

Francesco Mani's avatar
Francesco Mani committed
333
  cfg->prach_config.ssb_per_rach.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present-1;
334
  cfg->prach_config.ssb_per_rach.tl.tag = NFAPI_NR_CONFIG_SSB_PER_RACH_TAG;
335
  cfg->num_tlv++;
Francesco Mani's avatar
Francesco Mani committed
336

337 338
  // SSB Table Configuration
  uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA);
339
  const int scaling_5khz = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000 ? 3 : 1;
340
  int sco = (absolute_diff/scaling_5khz) % 24;
341 342 343 344
  if(frequency_range == FR2)
    sco >>= 1; // this assumes 120kHz SCS for SSB and subCarrierSpacingCommon (only option supported by OAI for
  const int scs_scaling = frequency_range == FR2 ? 1 << (*scc->ssbSubcarrierSpacing - 2) : 1 << *scc->ssbSubcarrierSpacing;
  cfg->ssb_table.ssb_offset_point_a.value = absolute_diff/(12*scaling_5khz) - 10*scs_scaling; //absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total
345
  cfg->ssb_table.ssb_offset_point_a.tl.tag = NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG;
346
  cfg->num_tlv++;
347 348 349
  cfg->ssb_table.ssb_period.value = *scc->ssb_periodicityServingCell;
  cfg->ssb_table.ssb_period.tl.tag = NFAPI_NR_CONFIG_SSB_PERIOD_TAG;
  cfg->num_tlv++;
350
  cfg->ssb_table.ssb_subcarrier_offset.value = sco;
351 352
  cfg->ssb_table.ssb_subcarrier_offset.tl.tag = NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG;
  cfg->num_tlv++;
353

354 355 356
  RC.nrmac[Mod_idP]->ssb_SubcarrierOffset = cfg->ssb_table.ssb_subcarrier_offset.value;
  RC.nrmac[Mod_idP]->ssb_OffsetPointA = cfg->ssb_table.ssb_offset_point_a.value;

357 358
  switch (scc->ssb_PositionsInBurst->present) {
    case 1 :
359
      cfg->ssb_table.ssb_mask_list[0].ssb_mask.value = scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0]<<24;
360 361 362
      cfg->ssb_table.ssb_mask_list[1].ssb_mask.value = 0;
      break;
    case 2 :
363
      cfg->ssb_table.ssb_mask_list[0].ssb_mask.value = scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0]<<24;
364 365 366 367 368
      cfg->ssb_table.ssb_mask_list[1].ssb_mask.value = 0;
      break;
    case 3 :
      cfg->ssb_table.ssb_mask_list[0].ssb_mask.value = 0;
      cfg->ssb_table.ssb_mask_list[1].ssb_mask.value = 0;
369
      for (int i=0; i<4; i++) {
370 371
        cfg->ssb_table.ssb_mask_list[0].ssb_mask.value += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[3-i]<<i*8);
        cfg->ssb_table.ssb_mask_list[1].ssb_mask.value += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-i]<<i*8);
372 373 374
      }
      break;
    default:
Francesco Mani's avatar
Francesco Mani committed
375
      AssertFatal(1==0,"SSB bitmap size value %d undefined (allowed values 1,2,3) \n", scc->ssb_PositionsInBurst->present);
376
  }
377

378
  cfg->ssb_table.ssb_mask_list[0].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG;
379
  cfg->ssb_table.ssb_mask_list[1].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG;
380
  cfg->num_tlv+=2;
381

francescomani's avatar
francescomani committed
382
  // logical antenna ports
383
  cfg->carrier_config.num_tx_ant.value = pdsch_AntennaPorts;
francescomani's avatar
francescomani committed
384
  AssertFatal(pdsch_AntennaPorts > 0 && pdsch_AntennaPorts < 33, "pdsch_AntennaPorts in 1...32\n");
Raymond Knopp's avatar
Raymond Knopp committed
385
  cfg->carrier_config.num_tx_ant.tl.tag = NFAPI_NR_CONFIG_NUM_TX_ANT_TAG;
386

387
  int num_ssb=0;
Raymond Knopp's avatar
Raymond Knopp committed
388
  for (int i=0;i<32;i++) {
389
    cfg->ssb_table.ssb_beam_id_list[i].beam_id.tl.tag = NFAPI_NR_CONFIG_BEAM_ID_TAG;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
390
    if ((cfg->ssb_table.ssb_mask_list[0].ssb_mask.value>>(31-i))&1) {
391 392 393 394 395 396
      cfg->ssb_table.ssb_beam_id_list[i].beam_id.value = num_ssb;
      num_ssb++;
    }
    cfg->num_tlv++;
  }
  for (int i=0;i<32;i++) {
397
    cfg->ssb_table.ssb_beam_id_list[32+i].beam_id.tl.tag = NFAPI_NR_CONFIG_BEAM_ID_TAG;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
398
    if ((cfg->ssb_table.ssb_mask_list[1].ssb_mask.value>>(31-i))&1) {
399 400 401 402
      cfg->ssb_table.ssb_beam_id_list[32+i].beam_id.value = num_ssb;
      num_ssb++;
    }
    cfg->num_tlv++;
Raymond Knopp's avatar
Raymond Knopp committed
403 404
  } 

405 406
  cfg->carrier_config.num_rx_ant.value = pusch_AntennaPorts;
  AssertFatal(pusch_AntennaPorts > 0 && pusch_AntennaPorts < 13, "pusch_AntennaPorts in 1...12\n");
Raymond Knopp's avatar
Raymond Knopp committed
407
  cfg->carrier_config.num_rx_ant.tl.tag = NFAPI_NR_CONFIG_NUM_RX_ANT_TAG;
408 409
  LOG_I(NR_MAC,"Set RX antenna number to %d, Set TX antenna number to %d (num ssb %d: %x,%x)\n",
        cfg->carrier_config.num_tx_ant.value,cfg->carrier_config.num_rx_ant.value,num_ssb,cfg->ssb_table.ssb_mask_list[0].ssb_mask.value,cfg->ssb_table.ssb_mask_list[1].ssb_mask.value);
Raymond Knopp's avatar
Raymond Knopp committed
410 411 412
  AssertFatal(cfg->carrier_config.num_tx_ant.value > 0,"carrier_config.num_tx_ant.value %d !\n",cfg->carrier_config.num_tx_ant.value );
  cfg->num_tlv++;
  cfg->num_tlv++;
413

414
  // TDD Table Configuration
415 416 417 418 419 420 421 422 423 424 425
  if (cfg->cell_config.frame_duplex_type.value == TDD){
    cfg->tdd_table.tdd_period.tl.tag = NFAPI_NR_CONFIG_TDD_PERIOD_TAG;
    cfg->num_tlv++;
    if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 == NULL) {
      cfg->tdd_table.tdd_period.value = scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity;
    } else {
      AssertFatal(scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL,
                  "In %s: scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 is null\n", __FUNCTION__);
      cfg->tdd_table.tdd_period.value = *scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530;
    }
    LOG_I(NR_MAC, "Setting TDD configuration period to %d\n", cfg->tdd_table.tdd_period.value);
426 427 428 429 430 431 432 433
    int periods_per_frame = set_tdd_config_nr(cfg,
                                              scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
                                              scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots,
                                              scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols,
                                              scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,
                                              scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols);

    if (periods_per_frame < 0)
434
      LOG_E(NR_MAC,"TDD configuration can not be done\n");
435
    else {
436
      LOG_I(NR_MAC,"TDD has been properly configurated\n");
437
      RC.nrmac[Mod_idP]->tdd_beam_association = (int16_t *)malloc16(periods_per_frame*sizeof(int16_t));
438
    }
439
  }
440

441 442
}

443
int nr_mac_enable_ue_rrc_processing_timer(module_id_t Mod_idP, rnti_t rnti, NR_SubcarrierSpacing_t subcarrierSpacing, uint32_t rrc_reconfiguration_delay) {
444 445 446

  if (rrc_reconfiguration_delay == 0) {
    return -1;
447
  }
Laurent THOMAS's avatar
Laurent THOMAS committed
448 449 450

  NR_UE_info_t *UE_info = find_nr_UE(&RC.nrmac[Mod_idP]->UE_info,rnti);
  if (!UE_info) {
451 452 453
    LOG_W(NR_MAC, "Could not find UE for RNTI 0x%04x\n", rnti);
    return -1;
  }
Laurent THOMAS's avatar
Laurent THOMAS committed
454
  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl;
455
  const uint16_t sl_ahead = RC.nrmac[Mod_idP]->if_inst->sl_ahead;
456
  sched_ctrl->rrc_processing_timer = (rrc_reconfiguration_delay<<subcarrierSpacing) + sl_ahead;
Laurent THOMAS's avatar
Laurent THOMAS committed
457
  LOG_I(NR_MAC, "Activating RRC processing timer for UE %04x with %d ms\n", UE_info->rnti, rrc_reconfiguration_delay);
458

459 460
  return 0;
}
461

462
int rrc_mac_config_req_gNB(module_id_t Mod_idP,
463
                           rrc_pdsch_AntennaPorts_t pdsch_AntennaPorts,
464
                           int pusch_AntennaPorts,
francescomani's avatar
francescomani committed
465
                           int sib1_tda,
466
                           int minRXTXTIMEpdsch,
467
                           NR_ServingCellConfigCommon_t *scc,
468
                           NR_BCCH_BCH_Message_t *mib,
469 470
                           NR_BCCH_DL_SCH_Message_t *sib1,
                           int add_ue,
471
                           uint32_t rnti,
472
                           NR_CellGroupConfig_t *CellGroup) {
473

474
  if (scc != NULL ) {
475
    AssertFatal((scc->ssb_PositionsInBurst->present > 0) && (scc->ssb_PositionsInBurst->present < 4), "SSB Bitmap type %d is not valid\n",scc->ssb_PositionsInBurst->present);
476

477
    const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
Robert Schmidt's avatar
Robert Schmidt committed
478
    RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL =
479
        calloc(n * MAX_BWP_SIZE, sizeof(uint16_t));
Robert Schmidt's avatar
Robert Schmidt committed
480 481 482
    AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL,
                "could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n");

483
    LOG_I(NR_MAC,"Configuring common parameters from NR ServingCellConfig\n");
Raymond Knopp's avatar
Raymond Knopp committed
484

485 486
    int num_pdsch_antenna_ports = pdsch_AntennaPorts.N1 * pdsch_AntennaPorts.N2 * pdsch_AntennaPorts.XP;
    RC.nrmac[Mod_idP]->xp_pdsch_antenna_ports = pdsch_AntennaPorts.XP;
487
    config_common(Mod_idP,
488
                  num_pdsch_antenna_ports,
489
                  pusch_AntennaPorts,
490
		  scc);
rmagueta's avatar
rmagueta committed
491
    LOG_D(NR_MAC, "%s() %s:%d RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req:%p\n", __FUNCTION__, __FILE__, __LINE__, RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req);
492 493
  
    // if in nFAPI mode 
Mahesh's avatar
Mahesh committed
494
    if ( (NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) && (RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req == NULL) ){
495
      while(RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req == NULL) {
496 497 498
        // DJP AssertFatal(RC.nrmac[Mod_idP]->if_inst->PHY_config_req != NULL,"if_inst->phy_config_request is null\n");
        usleep(100 * 1000);
        printf("Waiting for PHY_config_req\n");
499
      }
500
    }
501
    RC.nrmac[Mod_idP]->minRXTXTIMEpdsch = minRXTXTIMEpdsch;
502

503 504 505 506
    NR_PHY_Config_t phycfg;
    phycfg.Mod_id = Mod_idP;
    phycfg.CC_id  = 0;
    phycfg.cfg    = &RC.nrmac[Mod_idP]->config[0];
507

508 509 510 511
    if (RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req) RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req(&phycfg);

    find_SSB_and_RO_available(Mod_idP);

512
    const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
513 514 515 516 517 518 519 520 521

    int nr_slots_period = n;
    int nr_dl_slots = n;
    int nr_ulstart_slot = 0;
    if (tdd) {
      nr_dl_slots = tdd->nrofDownlinkSlots + (tdd->nrofDownlinkSymbols != 0);
      nr_ulstart_slot = tdd->nrofDownlinkSlots + (tdd->nrofUplinkSymbols == 0);
      nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
    }
francescomani's avatar
francescomani committed
522 523 524
    else
      // if TDD configuration is not present and the band is not FDD, it means it is a dynamic TDD configuration
      AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].frame_type == FDD,"Dynamic TDD not handled yet\n");
525

526
    for (int slot = 0; slot < n; ++slot) {
Robert Schmidt's avatar
Robert Schmidt committed
527
      RC.nrmac[Mod_idP]->dlsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) < nr_dl_slots) << (slot % 64);
rmagueta's avatar
rmagueta committed
528
      RC.nrmac[Mod_idP]->ulsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64);
529 530 531

      LOG_I(NR_MAC, "In %s: slot %d DL %d UL %d\n",
            __FUNCTION__,
532
            slot,
rmagueta's avatar
rmagueta committed
533 534
            (RC.nrmac[Mod_idP]->dlsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0,
            (RC.nrmac[Mod_idP]->ulsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0);
535 536 537 538 539 540 541 542 543
    }

    if (get_softmodem_params()->phy_test) {
      RC.nrmac[Mod_idP]->pre_processor_dl = nr_preprocessor_phytest;
      RC.nrmac[Mod_idP]->pre_processor_ul = nr_ul_preprocessor_phytest;
    } else {
      RC.nrmac[Mod_idP]->pre_processor_dl = nr_init_fr1_dlsch_preprocessor(Mod_idP, 0);
      RC.nrmac[Mod_idP]->pre_processor_ul = nr_init_fr1_ulsch_preprocessor(Mod_idP, 0);
    }
544

545 546
    if (get_softmodem_params()->sa > 0) {
      NR_COMMON_channels_t *cc = &RC.nrmac[Mod_idP]->common_channels[0];
francescomani's avatar
francescomani committed
547
      RC.nrmac[Mod_idP]->sib1_tda = sib1_tda;
548
      for (int n=0;n<NR_NB_RA_PROC_MAX;n++ ) {
549 550 551 552 553 554 555
        cc->ra[n].cfra = false;
        cc->ra[n].msg3_dcch_dtch = false;
        cc->ra[n].rnti = 0;
        cc->ra[n].preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES;
        cc->ra[n].preambles.preamble_list = (uint8_t *) malloc(MAX_NUM_NR_PRACH_PREAMBLES*sizeof(uint8_t));
        for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++)
          cc->ra[n].preambles.preamble_list[i] = i;
556 557
      }
    }
558
  }
559
 
560 561 562
  if (mib) RC.nrmac[Mod_idP]->common_channels[0].mib = mib;
  if (sib1) RC.nrmac[Mod_idP]->common_channels[0].sib1 = sib1;

563
  if (CellGroup) {
564

565
    if (add_ue == 1 && get_softmodem_params()->phy_test) {
Laurent THOMAS's avatar
Laurent THOMAS committed
566
      NR_UE_info_t* UE = add_new_nr_ue(RC.nrmac[Mod_idP], rnti, CellGroup);
567 568 569 570 571
      if (UE) {
        LOG_I(NR_MAC,"Added new UE %x with initial CellGroup\n", rnti);
      } else {
        LOG_E(NR_MAC,"Error adding UE %04x\n", rnti);
        return -1;
Laurent THOMAS's avatar
Laurent THOMAS committed
572 573
      }
      process_CellGroup(CellGroup,&UE->UE_sched_ctrl);
574 575
    } else if (add_ue == 1 && !get_softmodem_params()->phy_test) {
      const int CC_id = 0;
576 577 578 579 580 581 582
      NR_COMMON_channels_t *cc = &RC.nrmac[Mod_idP]->common_channels[CC_id];
      uint8_t ra_index = 0;
      /* checking for free RA process */
      for(; ra_index < NR_NB_RA_PROC_MAX; ra_index++) {
        if((cc->ra[ra_index].state == RA_IDLE) && (!cc->ra[ra_index].cfra)) break;
      }
      if (ra_index == NR_NB_RA_PROC_MAX) {
583
        LOG_E(NR_MAC, "%s() %s:%d RA processes are not available for CFRA RNTI :%x\n", __FUNCTION__, __FILE__, __LINE__, rnti);
584 585 586
        return -1;
      }	
      NR_RA_t *ra = &cc->ra[ra_index];
587 588
      ra->CellGroup = CellGroup;
      if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync &&
589
	        CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated!=NULL) {
590
        if (CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra != NULL) {
Francesco Mani's avatar
Francesco Mani committed
591
          ra->cfra = true;
Francesco Mani's avatar
Francesco Mani committed
592
          ra->rnti = rnti;
593
          struct NR_CFRA *cfra = CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra;
594
          uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count;
Francesco Mani's avatar
Francesco Mani committed
595 596
          ra->preambles.num_preambles = num_preamble;
          ra->preambles.preamble_list = (uint8_t *) malloc(num_preamble*sizeof(uint8_t));
597 598
          for(int i=0; i<cc->num_active_ssb; i++) {
            for(int j=0; j<num_preamble; j++) {
guhan's avatar
guhan committed
599
              if (cc->ssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) {
600 601
                // one dedicated preamble for each beam
                ra->preambles.preamble_list[i] =
guhan's avatar
guhan committed
602
                    cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ra_PreambleIndex;
603 604 605 606
                break;
              }
            }
          }
Francesco Mani's avatar
Francesco Mani committed
607
        }
rmagueta's avatar
rmagueta committed
608 609
      } else {
        ra->cfra = false;
610
        ra->rnti = 0;
611 612 613
        ra->preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES;
        ra->preambles.preamble_list = (uint8_t *) malloc(MAX_NUM_NR_PRACH_PREAMBLES*sizeof(uint8_t));
        for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++)
rmagueta's avatar
rmagueta committed
614
          ra->preambles.preamble_list[i] = i;
Francesco Mani's avatar
Francesco Mani committed
615
      }
616
      ra->msg3_dcch_dtch = false;
617
      LOG_I(NR_MAC,"Added new RA process for UE RNTI %04x with initial CellGroup\n", rnti);
618
    } else { // CellGroup has been updated
619
      NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[Mod_idP]->UE_info, rnti);
Laurent THOMAS's avatar
Laurent THOMAS committed
620
      if (!UE) {
621 622
        LOG_E(NR_MAC, "Can't find UE %04x\n", rnti);
        return -1;
Laurent THOMAS's avatar
Laurent THOMAS committed
623 624
      }

625 626 627 628 629 630 631
      /* copy CellGroup by calling asn1c encode
         this is a temporary hack to avoid the gNB having
         a pointer to RRC CellGroup structure
         (otherwise it would be applied to early)
         TODO remove once we have a proper implementation */
      UE->enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
                                           NULL,
632
                                           (void *) CellGroup,
633 634 635
                                           UE->cg_buf,
                                           32768);

636
      if (UE->enc_rval.encoded == -1) {
637 638 639
        LOG_E(NR_MAC, "ASN1 message CellGroupConfig encoding failed (%s, %lu)!\n",
              UE->enc_rval.failed_type->name, UE->enc_rval.encoded);
        exit(1);
640
      }
641 642

      process_CellGroup(CellGroup,&UE->UE_sched_ctrl);
643 644 645
    }
  }
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_OUT);
646

647
  return 0;
648
}// END rrc_mac_config_req_gNB