nr_ue_procedures.c 163 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * 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
 */

22
/* \file ue_procedures.c
23
 * \brief procedures related to UE
24
 * \author R. Knopp, K.H. HSU, G. Casati
25 26 27
 * \date 2018
 * \version 0.1
 * \company Eurecom / NTUST
28
 * \email: knopp@eurecom.fr, kai-hsiang.hsu@eurecom.fr, guido.casati@iis.fraunhofer.de
29 30
 * \note
 * \warning
31
 */
32

33 34 35 36 37

#include <stdio.h>
#include <math.h>

/* exe */
38 39
#include "executables/nr-softmodem.h"

cig's avatar
cig committed
40 41 42
/* RRC*/
#include "RRC/NR_UE/rrc_proto.h"

43 44 45 46
/* MAC */
#include "NR_MAC_COMMON/nr_mac.h"
#include "NR_MAC_UE/mac_proto.h"
#include "NR_MAC_UE/mac_extern.h"
47
#include "NR_MAC_COMMON/nr_mac_extern.h"
cig's avatar
cig committed
48
#include "common/utils/nr/nr_common.h"
Melissa Elkadi's avatar
Melissa Elkadi committed
49
#include "openair2/NR_UE_PHY_INTERFACE/NR_Packet_Drop.h"
cig's avatar
cig committed
50

51
/* PHY */
52
#include "executables/softmodem-common.h"
53
#include "openair1/PHY/defs_nr_UE.h"
54

55 56
/* utils */
#include "assertions.h"
57
#include "oai_asn1.h"
58
#include "common/utils/LOG/log.h"
59
#include "common/utils/LOG/vcd_signal_dumper.h"
60

61
//#define DEBUG_MIB
62
//#define ENABLE_MAC_PAYLOAD_DEBUG 1
cig's avatar
cig committed
63
//#define DEBUG_EXTRACT_DCI
cig's avatar
cig committed
64
//#define DEBUG_RAR
65

66 67
extern uint32_t N_RB_DL;

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 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
/* TS 38.213 9.2.5.2 UE procedure for multiplexing HARQ-ACK/SR and CSI in a PUCCH */
/* this is a counter of number of pucch format 4 per subframe */
static int nb_pucch_format_4_in_subframes[LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] = { 0 } ;

/* TS 36.213 Table 9.2.3-3: Mapping of values for one HARQ-ACK bit to sequences */
static const int sequence_cyclic_shift_1_harq_ack_bit[2]
/*        HARQ-ACK Value        0    1 */
/* Sequence cyclic shift */ = { 0,   6 };

/* TS 36.213 Table 9.2.5-1: Mapping of values for one HARQ-ACK bit and positive SR to sequences */
static const int sequence_cyclic_shift_1_harq_ack_bit_positive_sr[2]
/*        HARQ-ACK Value        0    1 */
/* Sequence cyclic shift */ = { 3,   9 };

/* TS 36.213 Table 9.2.5-2: Mapping of values for two HARQ-ACK bits and positive SR to sequences */
static const int sequence_cyclic_shift_2_harq_ack_bits_positive_sr[4]
/*        HARQ-ACK Value      (0,0)  (0,1)   (1,0)  (1,1) */
/* Sequence cyclic shift */ = {  1,     4,     10,     7 };

/* TS 38.213 Table 9.2.3-4: Mapping of values for two HARQ-ACK bits to sequences */
static const int sequence_cyclic_shift_2_harq_ack_bits[4]
/*        HARQ-ACK Value       (0,0)  (0,1)  (1,0)  (1,1) */
/* Sequence cyclic shift */ = {   0,     3,     9,     6 };


/* TS 38.211 Table 6.4.1.3.3.2-1: DM-RS positions for PUCCH format 3 and 4 */
static const int nb_symbols_excluding_dmrs[11][2][2]
= {
/*                     No additional DMRS            Additional DMRS   */
/* PUCCH length      No hopping   hopping         No hopping   hopping */
/* index                  0          1                 0          1    */
/*    4     */    {{      3    ,     2   }   ,  {      3     ,    2    }},
/*    5     */    {{      3    ,     3   }   ,  {      3     ,    3    }},
/*    6     */    {{      4    ,     4   }   ,  {      4     ,    4    }},
/*    7     */    {{      5    ,     5   }   ,  {      5     ,    5    }},
/*    8     */    {{      6    ,     6   }   ,  {      6     ,    6    }},
/*    9     */    {{      7    ,     7   }   ,  {      7     ,    7    }},
/*   10     */    {{      8    ,     8   }   ,  {      6     ,    6    }},
/*   11     */    {{      9    ,     9   }   ,  {      7     ,    7    }},
/*   12     */    {{     10    ,    10   }   ,  {      8     ,    8    }},
/*   13     */    {{     11    ,    11   }   ,  {      9     ,    9    }},
/*   14     */    {{     12    ,    12   }   ,  {     10     ,   10    }},
};

/* TS 36.213 Table 9.2.1-1: PUCCH resource sets before dedicated PUCCH resource configuration */
const initial_pucch_resource_t initial_pucch_resource[16] = {
/*              format           first symbol     Number of symbols        PRB offset    nb index for       set of initial CS */
/*  0  */ {  0,      12,                  2,                   0,            2,       {    0,   3,    0,    0  }   },
/*  1  */ {  0,      12,                  2,                   0,            3,       {    0,   4,    8,    0  }   },
/*  2  */ {  0,      12,                  2,                   3,            3,       {    0,   4,    8,    0  }   },
/*  3  */ {  1,      10,                  4,                   0,            2,       {    0,   6,    0,    0  }   },
/*  4  */ {  1,      10,                  4,                   0,            4,       {    0,   3,    6,    9  }   },
/*  5  */ {  1,      10,                  4,                   2,            4,       {    0,   3,    6,    9  }   },
/*  6  */ {  1,      10,                  4,                   4,            4,       {    0,   3,    6,    9  }   },
/*  7  */ {  1,       4,                 10,                   0,            2,       {    0,   6,    0,    0  }   },
/*  8  */ {  1,       4,                 10,                   0,            4,       {    0,   3,    6,    9  }   },
/*  9  */ {  1,       4,                 10,                   2,            4,       {    0,   3,    6,    9  }   },
/* 10  */ {  1,       4,                 10,                   4,            4,       {    0,   3,    6,    9  }   },
/* 11  */ {  1,       0,                 14,                   0,            2,       {    0,   6,    0,    0  }   },
/* 12  */ {  1,       0,                 14,                   0,            4,       {    0,   3,    6,    9  }   },
/* 13  */ {  1,       0,                 14,                   2,            4,       {    0,   3,    6,    9  }   },
/* 14  */ {  1,       0,                 14,                   4,            4,       {    0,   3,    6,    9  }   },
/* 15  */ {  1,       0,                 14,                   0,            4,       {    0,   3,    6,    9  }   },
};


134 135
void nr_ue_init_mac(module_id_t module_idP) {
  int i;
136

137 138 139 140
  NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
  // default values as deined in 38.331 sec 9.2.2
  LOG_I(NR_MAC, "[UE%d] Applying default macMainConfig\n", module_idP);
  //mac->scheduling_info.macConfig=NULL;
141 142 143 144 145 146
  mac->scheduling_info.retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf10240;
  mac->scheduling_info.periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_infinity;
//  mac->scheduling_info.periodicPHR_Timer = NR_MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20;
//  mac->scheduling_info.prohibitPHR_Timer = NR_MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20;
//  mac->scheduling_info.PathlossChange_db = NR_MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1;
//  mac->PHR_state = NR_MAC_MainConfig__phr_Config_PR_setup;
147 148 149
  mac->scheduling_info.SR_COUNTER = 0;
  mac->scheduling_info.sr_ProhibitTimer = 0;
  mac->scheduling_info.sr_ProhibitTimer_Running = 0;
150
//  mac->scheduling_info.maxHARQ_Tx = NR_MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
151 152 153 154 155
//  mac->scheduling_info.ttiBundling = 0;
//  mac->scheduling_info.extendedBSR_Sizes_r10 = 0;
//  mac->scheduling_info.extendedPHR_r10 = 0;
//  mac->scheduling_info.drx_config = NULL;
//  mac->scheduling_info.phr_config = NULL;
156
  // set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value configured by the NW.
157 158
  mac->scheduling_info.periodicBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING;
  mac->scheduling_info.retxBSR_SF = MAC_UE_BSR_TIMER_NOT_RUNNING;
159
  mac->BSR_reporting_active = BSR_TRIGGER_NONE;
160 161 162
//  mac->scheduling_info.periodicPHR_SF = nr_get_sf_perioidicPHR_Timer(mac->scheduling_info.periodicPHR_Timer);
//  mac->scheduling_info.prohibitPHR_SF = nr_get_sf_prohibitPHR_Timer(mac->scheduling_info.prohibitPHR_Timer);
//  mac->scheduling_info.PathlossChange_db = nr_get_db_dl_PathlossChange(mac->scheduling_info.PathlossChange);
163
//  mac->PHR_reporting_active = 0;
164 165

  for (i = 0; i < NR_MAX_NUM_LCID; i++) {
166
    LOG_D(NR_MAC, "[UE%d] Applying default logical channel config for LCGID %d\n",
167
                 module_idP, i);
168 169 170 171 172 173 174 175 176
    mac->scheduling_info.Bj[i] = -1;
    mac->scheduling_info.bucket_size[i] = -1;

    if (i < UL_SCH_LCID_DTCH) {   // initialize all control channels lcgid to 0
      mac->scheduling_info.LCGID[i] = 0;
    } else {    // initialize all the data channels lcgid to 1
      mac->scheduling_info.LCGID[i] = 1;
    }

177
    mac->scheduling_info.LCID_status[i] = LCID_EMPTY;
178
    mac->scheduling_info.LCID_buffer_remain[i] = 0;
179
    for (int i=0;i<NR_MAX_HARQ_PROCESSES;i++) mac->first_ul_tx[i]=1;
180 181 182
  }
}

183 184 185 186 187 188 189 190 191 192 193 194
NR_BWP_DownlinkCommon_t *get_bwp_downlink_common(NR_UE_MAC_INST_t *mac, NR_BWP_Id_t dl_bwp_id) {
  NR_BWP_DownlinkCommon_t *bwp_Common = NULL;
  if (dl_bwp_id > 0 && mac->cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList) {
    bwp_Common = mac->cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[dl_bwp_id-1]->bwp_Common;
  } else if (mac->scc) {
    bwp_Common = mac->scc->downlinkConfigCommon->initialDownlinkBWP;
  } else if (mac->scc_SIB) {
    bwp_Common = &mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP;
  }
  return bwp_Common;
}

195 196
int get_rnti_type(NR_UE_MAC_INST_t *mac, uint16_t rnti)
{
197 198

    RA_config_t *ra = &mac->ra;
cig's avatar
cig committed
199
    int rnti_type;
200 201

    if (rnti == ra->ra_rnti) {
cig's avatar
cig committed
202
      rnti_type = NR_RNTI_RA;
rmagueta's avatar
rmagueta committed
203
    } else if (rnti == ra->t_crnti && (ra->ra_state == WAIT_RAR || ra->ra_state == WAIT_CONTENTION_RESOLUTION) ) {
204
      rnti_type = NR_RNTI_TC;
205
    } else if (rnti == mac->crnti) {
cig's avatar
cig committed
206
      rnti_type = NR_RNTI_C;
207
    } else if (rnti == 0xFFFE) {
cig's avatar
cig committed
208
      rnti_type = NR_RNTI_P;
209
    } else if (rnti == 0xFFFF) {
cig's avatar
cig committed
210
      rnti_type = NR_RNTI_SI;
211
    } else {
cig's avatar
cig committed
212
      AssertFatal(1 == 0, "In %s: Not identified/handled rnti %d \n", __FUNCTION__, rnti);
213 214
    }

cig's avatar
cig committed
215 216 217
    LOG_D(MAC, "In %s: returning rnti_type %s \n", __FUNCTION__, rnti_types[rnti_type]);

    return rnti_type;
218
}
219

220

221
int8_t nr_ue_decode_mib(module_id_t module_id,
yilmazt's avatar
yilmazt committed
222 223
                        int cc_id,
                        uint8_t gNB_index,
224
                        void *phy_data,
yilmazt's avatar
yilmazt committed
225 226 227 228
                        uint8_t extra_bits,	//	8bits 38.212 c7.1.1
                        uint32_t ssb_length,
                        uint32_t ssb_index,
                        void *pduP,
229
                        uint16_t ssb_start_subcarrier,
yilmazt's avatar
yilmazt committed
230 231
                        uint16_t cell_id)
{
rmagueta's avatar
rmagueta committed
232
  LOG_D(MAC,"[L2][MAC] decode mib\n");
233

234
  NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
235 236
  mac->physCellId = cell_id;

francescomani's avatar
francescomani committed
237
  nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_BCH, (uint8_t *) pduP, 3);    //  fixed 3 bytes MIB PDU
238
    
239
  AssertFatal(mac->mib != NULL, "nr_ue_decode_mib() mac->mib == NULL\n");
francescomani's avatar
francescomani committed
240

241 242
  uint16_t frame = (mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused);
  uint16_t frame_number_4lsb = 0;
243

244 245
  for (int i=0; i<4; i++)
    frame_number_4lsb |= ((extra_bits>>i)&1)<<(3-i);
246

247 248
  uint8_t ssb_subcarrier_offset_msb = ( extra_bits >> 5 ) & 0x1;    //	extra bits[5]
  uint8_t ssb_subcarrier_offset = (uint8_t)mac->mib->ssb_SubcarrierOffset;
249

250 251 252
  frame = frame << 4;
  frame = frame | frame_number_4lsb;
  if(ssb_length == 64){
253
    mac->frequency_range = FR2;
254 255
    for (int i=0; i<3; i++)
      ssb_index += (((extra_bits>>(7-i))&0x01)<<(3+i));
256
  }else{
257
    mac->frequency_range = FR1;
258 259 260 261
    if(ssb_subcarrier_offset_msb){
      ssb_subcarrier_offset = ssb_subcarrier_offset | 0x10;
    }
  }
262

263 264 265 266 267 268 269 270 271 272 273 274 275 276
#ifdef DEBUG_MIB
  uint8_t half_frame_bit = ( extra_bits >> 4 ) & 0x1; //	extra bits[4]
  LOG_I(MAC,"system frame number(6 MSB bits): %d\n",  mac->mib->systemFrameNumber.buf[0]);
  LOG_I(MAC,"system frame number(with LSB): %d\n", (int)frame);
  LOG_I(MAC,"subcarrier spacing (0=15or60, 1=30or120): %d\n", (int)mac->mib->subCarrierSpacingCommon);
  LOG_I(MAC,"ssb carrier offset(with MSB):  %d\n", (int)ssb_subcarrier_offset);
  LOG_I(MAC,"dmrs type A position (0=pos2,1=pos3): %d\n", (int)mac->mib->dmrs_TypeA_Position);
  LOG_I(MAC,"controlResourceSetZero: %d\n", (int)mac->mib->pdcch_ConfigSIB1.controlResourceSetZero);
  LOG_I(MAC,"searchSpaceZero: %d\n", (int)mac->mib->pdcch_ConfigSIB1.searchSpaceZero);
  LOG_I(MAC,"cell barred (0=barred,1=notBarred): %d\n", (int)mac->mib->cellBarred);
  LOG_I(MAC,"intra frequency reselection (0=allowed,1=notAllowed): %d\n", (int)mac->mib->intraFreqReselection);
  LOG_I(MAC,"half frame bit(extra bits):    %d\n", (int)half_frame_bit);
  LOG_I(MAC,"ssb index(extra bits):         %d\n", (int)ssb_index);
#endif
277

278 279
  //storing ssb index in the mac structure
  mac->mib_ssb = ssb_index;
280
  mac->ssb_subcarrier_offset = ssb_subcarrier_offset;
281

282 283 284
  uint8_t scs_ssb;
  uint32_t band;
  uint16_t ssb_start_symbol;
285

286 287
  if (get_softmodem_params()->sa == 1) {

288 289 290
    scs_ssb = get_softmodem_params()->numerology;
    band = mac->nr_band;
    ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index);
291 292 293 294 295
    int ssb_sc_offset_norm;
    if (ssb_subcarrier_offset<24 && mac->frequency_range == FR1)
      ssb_sc_offset_norm = ssb_subcarrier_offset>>scs_ssb;
    else
      ssb_sc_offset_norm = ssb_subcarrier_offset;
296

297
    if (!mac->sib1_decoded) {
298 299 300 301
      nr_ue_sib1_scheduler(module_id,
                           cc_id,
                           ssb_start_symbol,
                           frame,
302
                           ssb_sc_offset_norm,
303 304
                           ssb_index,
                           ssb_start_subcarrier,
305 306
                           mac->frequency_range,
                           phy_data);
307 308
      mac->first_sync_frame = frame;
    }
309
  }
310 311 312 313 314
  else {
    NR_ServingCellConfigCommon_t *scc = mac->scc;
    scs_ssb = *scc->ssbSubcarrierSpacing;
    band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
    ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index);
315 316
    if (mac->first_sync_frame == -1)
      mac->first_sync_frame = frame;
317
  }
318

319
  mac->dl_config_request.sfn = frame;
320
  mac->dl_config_request.slot = ssb_start_symbol/14;
321 322

  return 0;
323
}
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
324

325 326 327
int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id,
                                int cc_id,
                                unsigned int gNB_index,
328
                                uint8_t ack_nack,
329 330
                                uint8_t *pduP,
                                uint32_t pdu_len) {
331 332
  if(ack_nack) {
    LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n");
333 334
    NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
    mac->sib1_decoded = true;
335 336 337 338
    nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
  }
  else
    LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (SIB1 or SI)\n");
339
  return 0;
340
}
341

342
//  TODO: change to UE parameter, scs: 15KHz, slot duration: 1ms
343
uint32_t get_ssb_frame(uint32_t test){
344
  return test;
345 346
}

347 348
/*
 * This code contains all the functions needed to process all dci fields.
349
 * These tables and functions are going to be called by function nr_ue_process_dci
350
 */
351
int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu,
352 353 354 355 356
                                                      fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu,
                                                      uint16_t n_RB_ULBWP,
                                                      uint16_t n_RB_DLBWP,
                                                      uint16_t riv)
{
357

358
  /*
359 360
   * TS 38.214 subclause 5.1.2.2 Resource allocation in frequency domain (downlink)
   * when the scheduling grant is received with DCI format 1_0, then downlink resource allocation type 1 is used
361
   */
362 363 364 365 366 367 368 369 370 371 372
  if(dlsch_config_pdu != NULL){

    /*
     * TS 38.214 subclause 5.1.2.2.1 Downlink resource allocation type 0
     */
    /*
     * TS 38.214 subclause 5.1.2.2.2 Downlink resource allocation type 1
     */
    dlsch_config_pdu->number_rbs = NRRIV2BW(riv,n_RB_DLBWP);
    dlsch_config_pdu->start_rb   = NRRIV2PRBOFFSET(riv,n_RB_DLBWP);

373 374 375 376 377 378 379
    // Sanity check in case a false or erroneous DCI is received
    if ((dlsch_config_pdu->number_rbs < 1 ) || (dlsch_config_pdu->number_rbs > n_RB_DLBWP - dlsch_config_pdu->start_rb)) {
      // DCI is invalid!
      LOG_W(MAC, "Frequency domain assignment values are invalid! #RBs: %d, Start RB: %d, n_RB_DLBWP: %d \n", dlsch_config_pdu->number_rbs, dlsch_config_pdu->start_rb, n_RB_DLBWP);
      return -1;
    }

380 381 382 383
    LOG_D(MAC,"DLSCH riv = %i\n", riv);
    LOG_D(MAC,"DLSCH n_RB_DLBWP = %i\n", n_RB_DLBWP);
    LOG_D(MAC,"DLSCH number_rbs = %i\n", dlsch_config_pdu->number_rbs);
    LOG_D(MAC,"DLSCH start_rb = %i\n", dlsch_config_pdu->start_rb);
384

385
  }
386
  if(pusch_config_pdu != NULL){
387 388 389 390 391 392 393 394 395 396
    /*
     * TS 38.214 subclause 6.1.2.2 Resource allocation in frequency domain (uplink)
     */
    /*
     * TS 38.214 subclause 6.1.2.2.1 Uplink resource allocation type 0
     */
    /*
     * TS 38.214 subclause 6.1.2.2.2 Uplink resource allocation type 1
     */

397 398
    pusch_config_pdu->rb_size  = NRRIV2BW(riv,n_RB_ULBWP);
    pusch_config_pdu->rb_start = NRRIV2PRBOFFSET(riv,n_RB_ULBWP);
399 400

    // Sanity check in case a false or erroneous DCI is received
Shweta Shrivastava's avatar
Shweta Shrivastava committed
401
    if ((pusch_config_pdu->rb_size < 1) || (pusch_config_pdu->rb_size > n_RB_ULBWP - pusch_config_pdu->rb_start)) {
402
      // DCI is invalid!
403
      LOG_W(MAC, "Frequency domain assignment values are invalid! #RBs: %d, Start RB: %d, n_RB_ULBWP: %d \n",pusch_config_pdu->rb_size, pusch_config_pdu->rb_start, n_RB_ULBWP);
404 405
      return -1;
    }
406 407 408 409
    LOG_D(MAC,"ULSCH riv = %i\n", riv);
    LOG_D(MAC,"ULSCH n_RB_DLBWP = %i\n", n_RB_ULBWP);
    LOG_D(MAC,"ULSCH number_rbs = %i\n", pusch_config_pdu->rb_size);
    LOG_D(MAC,"ULSCH start_rb = %i\n", pusch_config_pdu->rb_start);
410 411 412 413
  }
  return 0;
}

414
int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci) {
415

416
  NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
417
  dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci->dci_format];
418

419 420
  LOG_D(MAC,"Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n",
	dci->rnti,dci->dci_format,dci->n_CCE,dci->payloadSize,*(unsigned long long*)dci->payloadBits);
421
  int8_t ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15);
422
  if ((ret&1) == 1) return -1;
423 424 425 426
  else if (ret == 2) {
    dci->dci_format = NR_UL_DCI_FORMAT_0_0;
    def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci->dci_format];
  }
427 428
  int8_t ret_proc = nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci);
  return ret_proc;
429
}
430

431
int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, fapi_nr_dci_indication_pdu_t *dci_ind) {
432

433 434
  uint16_t rnti = dci_ind->rnti;
  uint8_t dci_format = dci_ind->dci_format;
435
  int coreset_type = dci_ind->coreset_type == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; // 0 for coreset0, 1 otherwise
cig's avatar
cig committed
436
  int ret = 0;
437
  int pucch_res_set_cnt = 0, valid = 0;
cig's avatar
cig committed
438 439
  frame_t frame_tx = 0;
  int slot_tx = 0;
440
  bool valid_ptrs_setup = 0;
441
  NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
442
  RA_config_t *ra = &mac->ra;
443
  fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request;
cig's avatar
cig committed
444
  uint8_t is_Msg3 = 0;
445 446
  NR_UE_DL_BWP_t *current_DL_BWP = &mac->current_DL_BWP;
  NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP;
447
  int mux_pattern = 1;
448

francescomani's avatar
francescomani committed
449
  LOG_D(MAC, "In %s: Processing received DCI format %s\n", __FUNCTION__, dci_formats[dci_format]);
450
  NR_tda_info_t tda_info = {0};
451
  NR_PUCCH_Config_t *pucch_Config = current_UL_BWP->pucch_Config;
452 453

  switch(dci_format){
454
  case NR_UL_DCI_FORMAT_0_0: {
455 456 457 458 459 460 461 462 463 464 465 466 467 468
    /*
     *  with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI
     *    0  IDENTIFIER_DCI_FORMATS:
     *    10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered
     *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
     *    17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0
     *    24 MCS:
     *    25 NDI:
     *    26 RV:
     *    27 HARQ_PROCESS_NUMBER:
     *    32 TPC_PUSCH:
     *    49 PADDING_NR_DCI: (Note 2) If DCI format 0_0 is monitored in common search space
     *    50 SUL_IND_0_0:
     */
469 470 471
    // Calculate the slot in which ULSCH should be scheduled. This is current slot + K2,
    // where K2 is the offset between the slot in which UL DCI is received and the slot
    // in which ULSCH should be scheduled. K2 is configured in RRC configuration.  
cig's avatar
cig committed
472 473
    // todo:
    // - SUL_IND_0_0
474

cig's avatar
cig committed
475
    // Schedule PUSCH
476
    tda_info = get_ul_tda_info(current_UL_BWP, coreset_type, dci_ind->ss_type, get_rnti_type(mac, rnti), dci->time_domain_assignment.val);
477
    if (tda_info.nrOfSymbols == 0)
478 479 480
      ret = -1;
    else
      ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, tda_info.k2);
481

cig's avatar
cig committed
482
    if (ret != -1){
483

cig's avatar
cig committed
484 485
      // Get UL config request corresponding slot_tx
      fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx);
486

cig's avatar
cig committed
487 488 489 490
      if (!ul_config) {
        LOG_W(MAC, "In %s: ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n", __FUNCTION__, frame, slot);
        return -1;
      }
491
      pthread_mutex_lock(&ul_config->mutex_ul_config);
492
      AssertFatal(ul_config->number_pdus<FAPI_NR_UL_CONFIG_LIST_NUM, "ul_config->number_pdus %d out of bounds\n",ul_config->number_pdus);
cig's avatar
cig committed
493
      nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu;
494

cig's avatar
cig committed
495
      fill_ul_config(ul_config, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
496
      pthread_mutex_unlock(&ul_config->mutex_ul_config);
497

cig's avatar
cig committed
498
      // Config PUSCH PDU
499
      ret = nr_config_pusch_pdu(mac, &tda_info, pusch_config_pdu, dci, NULL, rnti, &dci_format);
500 501
    } else
      LOG_E(MAC, "Cannot schedule PUSCH\n");
502
    break;
503
  }
504

505
  case NR_UL_DCI_FORMAT_0_1: {
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
    /*
     *  with CRC scrambled by C-RNTI or CS-RNTI or SP-CSI-RNTI or new-RNTI
     *    0  IDENTIFIER_DCI_FORMATS:
     *    1  CARRIER_IND
     *    2  SUL_IND_0_1
     *    7  BANDWIDTH_PART_IND
     *    10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered
     *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
     *    17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0
     *    24 MCS:
     *    25 NDI:
     *    26 RV:
     *    27 HARQ_PROCESS_NUMBER:
     *    29 FIRST_DAI
     *    30 SECOND_DAI
     *    32 TPC_PUSCH:
     *    36 SRS_RESOURCE_IND:
     *    37 PRECOD_NBR_LAYERS:
     *    38 ANTENNA_PORTS:
     *    40 SRS_REQUEST:
     *    42 CSI_REQUEST:
     *    43 CBGTI
     *    45 PTRS_DMRS
     *    46 BETA_OFFSET_IND
     *    47 DMRS_SEQ_INI
     *    48 UL_SCH_IND
     *    49 PADDING_NR_DCI: (Note 2) If DCI format 0_0 is monitored in common search space
     */
cig's avatar
cig committed
534 535 536 537
    // TODO: 
    // - FIRST_DAI
    // - SECOND_DAI
    // - SRS_RESOURCE_IND
538

cig's avatar
cig committed
539
    // Schedule PUSCH
540
    tda_info = get_ul_tda_info(current_UL_BWP, coreset_type, dci_ind->ss_type, get_rnti_type(mac, rnti), dci->time_domain_assignment.val);
541
    if (tda_info.nrOfSymbols == 0)
542 543 544
      ret = -1;
    else
      ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, tda_info.k2);
545

cig's avatar
cig committed
546
    if (ret != -1){
547

cig's avatar
cig committed
548 549
      // Get UL config request corresponding slot_tx
      fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx);
550

cig's avatar
cig committed
551 552 553 554
      if (!ul_config) {
        LOG_W(MAC, "In %s: ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n", __FUNCTION__, frame, slot);
        return -1;
      }
555
      ul_config->number_pdus = 0;
556

557 558
      pthread_mutex_lock(&ul_config->mutex_ul_config);
      AssertFatal(ul_config->number_pdus<FAPI_NR_UL_CONFIG_LIST_NUM, "ul_config->number_pdus %d out of bounds\n",ul_config->number_pdus);
cig's avatar
cig committed
559
      nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu;
560

cig's avatar
cig committed
561
      fill_ul_config(ul_config, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
562
      pthread_mutex_unlock(&ul_config->mutex_ul_config);
563

cig's avatar
cig committed
564
      // Config PUSCH PDU
565
      ret = nr_config_pusch_pdu(mac, &tda_info, pusch_config_pdu, dci, NULL, rnti, &dci_format);
566 567
    } else
      LOG_E(MAC, "Cannot schedule PUSCH\n");
568
    break;
569
  }
570

571
  case NR_DL_DCI_FORMAT_1_0: {
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
    /*
     *  with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI
     *    0  IDENTIFIER_DCI_FORMATS:
     *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
     *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
     *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
     *    24 MCS:
     *    25 NDI:
     *    26 RV:
     *    27 HARQ_PROCESS_NUMBER:
     *    28 DAI_: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
     *    33 TPC_PUCCH:
     *    34 PUCCH_RESOURCE_IND:
     *    35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND:
     *    55 RESERVED_NR_DCI
     *  with CRC scrambled by P-RNTI
     *    8  SHORT_MESSAGE_IND
     *    9  SHORT_MESSAGES
     *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
     *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
     *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
     *    24 MCS:
     *    31 TB_SCALING
     *    55 RESERVED_NR_DCI
     *  with CRC scrambled by SI-RNTI
     *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
     *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
     *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
     *    24 MCS:
     *    26 RV:
     *    55 RESERVED_NR_DCI
     *  with CRC scrambled by RA-RNTI
     *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
     *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
     *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
     *    24 MCS:
     *    31 TB_SCALING
     *    55 RESERVED_NR_DCI
     *  with CRC scrambled by TC-RNTI
     *    0  IDENTIFIER_DCI_FORMATS:
     *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
     *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
     *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
     *    24 MCS:
     *    25 NDI:
     *    26 RV:
     *    27 HARQ_PROCESS_NUMBER:
     *    28 DAI_: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
     *    33 TPC_PUCCH:
     */

    dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti;
    fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_0 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15;
625

francescomani's avatar
francescomani committed
626 627
    NR_PDSCH_Config_t *pdsch_config = current_DL_BWP ? current_DL_BWP->pdsch_Config : NULL;
    int is_common = 0;
628 629 630 631 632 633 634 635
    if (dci_ind->ss_type == NR_SearchSpace__searchSpaceType_PR_common) {
      dlsch_config_pdu_1_0->BWPSize = mac->type0_PDCCH_CSS_config.num_rbs ? mac->type0_PDCCH_CSS_config.num_rbs : current_DL_BWP->initial_BWPSize;
      dlsch_config_pdu_1_0->BWPStart = dci_ind->cset_start;
    }
    else {
      dlsch_config_pdu_1_0->BWPSize = current_DL_BWP->BWPSize;
      dlsch_config_pdu_1_0->BWPStart = current_DL_BWP->BWPStart;
    }
rmagueta's avatar
rmagueta committed
636
    if(rnti == SI_RNTI) {
637
      NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config = mac->type0_PDCCH_CSS_config;
638
      mux_pattern = type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern;
639 640
      dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH;
      dlsch_config_pdu_1_0->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon;
641
      if (pdsch_config) pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NULL; // For PDSCH with mapping type A, the UE shall assume dmrs-AdditionalPosition='pos2'
rmagueta's avatar
rmagueta committed
642
    } else {
643
      dlsch_config_pdu_1_0->SubcarrierSpacing = current_DL_BWP->scs;
644
      if (ra->RA_window_cnt >= 0 && rnti == ra->ra_rnti){
rmagueta's avatar
rmagueta committed
645 646 647 648
        dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH;
      } else {
        dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH;
      }
649
      if ((ra->RA_window_cnt >= 0 && rnti == ra->ra_rnti) || (rnti == ra->t_crnti)) {
francescomani's avatar
francescomani committed
650
        if (mac->scc == NULL) // use coreset0
651
          is_common = 1;
francescomani's avatar
francescomani committed
652
      }
653
    }
654

655 656
    /* IDENTIFIER_DCI_FORMATS */
    /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */
657
    if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,dlsch_config_pdu_1_0->BWPSize,dci->frequency_domain_assignment.val) < 0) {
658
      LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot);
659
      return -1;
660
    }
661 662

    /* TIME_DOM_RESOURCE_ASSIGNMENT */
663 664 665 666 667 668 669
    int dmrs_typeA_pos = (mac->scc != NULL) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position;
    // TODO need to differentiate SI_RNTI between SIB1 and other SIB
    NR_tda_info_t tda_info = get_dl_tda_info(current_DL_BWP, dci_ind->ss_type, dci->time_domain_assignment.val,
                                             dmrs_typeA_pos, mux_pattern, get_rnti_type(mac, rnti), coreset_type, rnti == SI_RNTI);

    dlsch_config_pdu_1_0->number_symbols = tda_info.nrOfSymbols;
    dlsch_config_pdu_1_0->start_symbol = tda_info.startSymbolIndex;
670

671
    struct NR_DMRS_DownlinkConfig *dl_dmrs_config = NULL;
672
    if (pdsch_config)
673
      dl_dmrs_config = (tda_info.mapping_type == typeA) ? pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup : pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup;
674 675

    dlsch_config_pdu_1_0->nscid = 0;
676
    if(dl_dmrs_config && dl_dmrs_config->scramblingID0)
677 678 679 680
      dlsch_config_pdu_1_0->dlDmrsScramblingId = *dl_dmrs_config->scramblingID0;
    else
      dlsch_config_pdu_1_0->dlDmrsScramblingId = mac->physCellId;

681
    /* dmrs symbol positions*/
682
    dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config,
683
                                                         NR_DL_DCI_FORMAT_1_0,
684
                                                         (get_softmodem_params()->nsa) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position,
685 686
                                                         dlsch_config_pdu_1_0->number_symbols,
                                                         dlsch_config_pdu_1_0->start_symbol,
687
                                                         tda_info.mapping_type,
688
                                                         1);
689

690
    dlsch_config_pdu_1_0->dmrsConfigType = (dl_dmrs_config != NULL) ?
691
                                           (dl_dmrs_config->dmrs_Type == NULL ? 0 : 1) : 0;
692

693 694 695 696 697
    /* number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214 version 15.9.0 Release 15 */
    if (dlsch_config_pdu_1_0->number_symbols == 2)
      dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 1;
    else
      dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 2;
698
    dlsch_config_pdu_1_0->dmrs_ports = 1; // only port 0 in case of DCI 1_0
699
    /* VRB_TO_PRB_MAPPING */
700
    dlsch_config_pdu_1_0->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved;
701
    /* MCS TABLE INDEX */
702
    dlsch_config_pdu_1_0->mcs_table = (pdsch_config) ? ((pdsch_config->mcs_Table) ? (*pdsch_config->mcs_Table + 1) : 0) : 0;
703 704
    /* MCS */
    dlsch_config_pdu_1_0->mcs = dci->mcs;
705 706
    // Basic sanity check for MCS value to check for a false or erroneous DCI
    if (dlsch_config_pdu_1_0->mcs > 28) {
707
      LOG_W(MAC, "[%d.%d] MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_0->mcs);
708 709
      return -1;
    }
710

711 712
    dlsch_config_pdu_1_0->qamModOrder = nr_get_Qm_dl(dlsch_config_pdu_1_0->mcs, dlsch_config_pdu_1_0->mcs_table);
    int R = nr_get_code_rate_dl(dlsch_config_pdu_1_0->mcs, dlsch_config_pdu_1_0->mcs_table);
713
    dlsch_config_pdu_1_0->targetCodeRate = R;
714 715 716 717 718 719 720 721 722 723 724 725 726 727
    if (dlsch_config_pdu_1_0->targetCodeRate == 0 || dlsch_config_pdu_1_0->qamModOrder == 0) {
      LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n");
      return -1;
    }

    int nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs
    int nb_re_dmrs = ((dlsch_config_pdu_1_0->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? 6:4)*dlsch_config_pdu_1_0->n_dmrs_cdm_groups;
    dlsch_config_pdu_1_0->TBS = nr_compute_tbs(dlsch_config_pdu_1_0->qamModOrder,
                                               R,
                                               dlsch_config_pdu_1_0->number_rbs,
                                               dlsch_config_pdu_1_0->number_symbols,
                                               nb_re_dmrs*get_num_dmrs(dlsch_config_pdu_1_0->dlDmrsSymbPos),
                                               nb_rb_oh, 0, 1);

francescomani's avatar
francescomani committed
728
    int bw_tbslbrm;
729 730
    if (current_DL_BWP->initial_BWPSize > 0)
      bw_tbslbrm = get_dlbw_tbslbrm(current_DL_BWP->initial_BWPSize, mac->cg);
francescomani's avatar
francescomani committed
731 732
    else
      bw_tbslbrm = dlsch_config_pdu_1_0->BWPSize;
733
    dlsch_config_pdu_1_0->tbslbrm = nr_compute_tbslbrm(dlsch_config_pdu_1_0->mcs_table,
734 735
                                                       bw_tbslbrm,
                                                       1);
736

737 738 739 740 741
    /* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
    dlsch_config_pdu_1_0->ndi = dci->ndi;
    /* RV (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
    dlsch_config_pdu_1_0->rv = dci->rv;
    /* HARQ_PROCESS_NUMBER (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
742
    dlsch_config_pdu_1_0->harq_process_nbr = dci->harq_pid;
743 744 745 746 747 748 749 750
    /* TB_SCALING (only if CRC scrambled by P-RNTI or RA-RNTI) */
    // according to TS 38.214 Table 5.1.3.2-3
    if (dci->tb_scaling == 0) dlsch_config_pdu_1_0->scaling_factor_S = 1;
    if (dci->tb_scaling == 1) dlsch_config_pdu_1_0->scaling_factor_S = 0.5;
    if (dci->tb_scaling == 2) dlsch_config_pdu_1_0->scaling_factor_S = 0.25;
    if (dci->tb_scaling == 3) dlsch_config_pdu_1_0->scaling_factor_S = 0; // value not defined in table
    /* TPC_PUCCH (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
    // according to TS 38.213 Table 7.2.1-1
751 752 753 754
    if (dci->tpc == 0) dlsch_config_pdu_1_0->accumulated_delta_PUCCH = -1;
    if (dci->tpc == 1) dlsch_config_pdu_1_0->accumulated_delta_PUCCH = 0;
    if (dci->tpc == 2) dlsch_config_pdu_1_0->accumulated_delta_PUCCH = 1;
    if (dci->tpc == 3) dlsch_config_pdu_1_0->accumulated_delta_PUCCH = 3;
755 756
    // Sanity check for pucch_resource_indicator value received to check for false DCI.
    valid = 0;
757
    if (pucch_Config && pucch_Config->resourceSetToAddModList) {
758
      pucch_res_set_cnt = pucch_Config->resourceSetToAddModList->list.count;
759
      for (int id = 0; id < pucch_res_set_cnt; id++) {
760 761 762 763
        if (dci->pucch_resource_indicator < pucch_Config->resourceSetToAddModList->list.array[id]->resourceList.list.count) {
          valid = 1;
          break;
        }
764
      }
765 766
    } else
      valid = 1;
767
    if (!valid) {
768
      LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dci->pucch_resource_indicator);
769 770 771
      return -1;
    }

772 773 774
   if(rnti != ra->ra_rnti && rnti != SI_RNTI)
     AssertFatal(1+dci->pdsch_to_harq_feedback_timing_indicator.val>=DURATION_RX_TO_TX,"PDSCH to HARQ feedback time (%d) cannot be less than DURATION_RX_TO_TX (%d).\n",
                 1+dci->pdsch_to_harq_feedback_timing_indicator.val,DURATION_RX_TO_TX);
775

776 777 778 779 780 781
   // set the harq status at MAC for feedback
   set_harq_status(mac,dci->pucch_resource_indicator,
                   dci->harq_pid,
                   dlsch_config_pdu_1_0->accumulated_delta_PUCCH,
                   1+dci->pdsch_to_harq_feedback_timing_indicator.val,
                   dci->dai[0].val,
782
                   dci_ind->n_CCE,dci_ind->N_CCE,is_common,
783
                   frame,slot);
784

cig's avatar
cig committed
785
    LOG_D(MAC,"(nr_ue_procedures.c) rnti = %x dl_config->number_pdus = %d\n",
786 787 788
	  dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti,
	  dl_config->number_pdus);
    LOG_D(MAC,"(nr_ue_procedures.c) frequency_domain_resource_assignment=%d \t number_rbs=%d \t start_rb=%d\n",
789
	  dci->frequency_domain_assignment.val,
790 791 792
	  dlsch_config_pdu_1_0->number_rbs,
	  dlsch_config_pdu_1_0->start_rb);
    LOG_D(MAC,"(nr_ue_procedures.c) time_domain_resource_assignment=%d \t number_symbols=%d \t start_symbol=%d\n",
793
	  dci->time_domain_assignment.val,
794 795 796 797 798 799 800 801
	  dlsch_config_pdu_1_0->number_symbols,
	  dlsch_config_pdu_1_0->start_symbol);
    LOG_D(MAC,"(nr_ue_procedures.c) vrb_to_prb_mapping=%d \n>>> mcs=%d\n>>> ndi=%d\n>>> rv=%d\n>>> harq_process_nbr=%d\n>>> dai=%d\n>>> scaling_factor_S=%f\n>>> tpc_pucch=%d\n>>> pucch_res_ind=%d\n>>> pdsch_to_harq_feedback_time_ind=%d\n",
	  dlsch_config_pdu_1_0->vrb_to_prb_mapping,
	  dlsch_config_pdu_1_0->mcs,
	  dlsch_config_pdu_1_0->ndi,
	  dlsch_config_pdu_1_0->rv,
	  dlsch_config_pdu_1_0->harq_process_nbr,
802
	  dci->dai[0].val,
803 804
	  dlsch_config_pdu_1_0->scaling_factor_S,
	  dlsch_config_pdu_1_0->accumulated_delta_PUCCH,
805 806
	  dci->pucch_resource_indicator,
	  1+dci->pdsch_to_harq_feedback_timing_indicator.val);
807
	    
808
    LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type);
809
            
810
    dl_config->number_pdus = dl_config->number_pdus + 1;
811

812
    break;
813
  }
814

815
  case NR_DL_DCI_FORMAT_1_1: {
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
    /*
     *  with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI
     *    0  IDENTIFIER_DCI_FORMATS:
     *    1  CARRIER_IND:
     *    7  BANDWIDTH_PART_IND:
     *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
     *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
     *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
     *    14 PRB_BUNDLING_SIZE_IND:
     *    15 RATE_MATCHING_IND:
     *    16 ZP_CSI_RS_TRIGGER:
     *    18 TB1_MCS:
     *    19 TB1_NDI:
     *    20 TB1_RV:
     *    21 TB2_MCS:
     *    22 TB2_NDI:
     *    23 TB2_RV:
     *    27 HARQ_PROCESS_NUMBER:
     *    28 DAI_: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
     *    33 TPC_PUCCH:
     *    34 PUCCH_RESOURCE_IND:
     *    35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND:
     *    38 ANTENNA_PORTS:
     *    39 TCI:
     *    40 SRS_REQUEST:
     *    43 CBGTI:
     *    44 CBGFI:
     *    47 DMRS_SEQ_INI:
     */
845

luis_pereira87's avatar
luis_pereira87 committed
846 847
    if (dci->bwp_indicator.val > NR_MAX_NUM_BWP) {
      LOG_W(NR_MAC,"[%d.%d] bwp_indicator %d > NR_MAX_NUM_BWP Possibly due to false DCI. Ignoring DCI!\n", frame, slot,dci->bwp_indicator.val);
848
      return -1;
849
    }
francescomani's avatar
francescomani committed
850
    NR_PDSCH_Config_t *pdsch_Config = current_DL_BWP->pdsch_Config;
851

852 853
    dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH;
    dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti;
854

855
    fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_1 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15;
856

francescomani's avatar
francescomani committed
857 858 859
    dlsch_config_pdu_1_1->BWPSize = current_DL_BWP->BWPSize;
    dlsch_config_pdu_1_1->BWPStart = current_DL_BWP->BWPStart;
    dlsch_config_pdu_1_1->SubcarrierSpacing = current_DL_BWP->scs;
860

861 862 863 864 865
    /* IDENTIFIER_DCI_FORMATS */
    /* CARRIER_IND */
    /* BANDWIDTH_PART_IND */
    //    dlsch_config_pdu_1_1->bandwidth_part_ind = dci->bandwidth_part_ind;
    /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */
francescomani's avatar
francescomani committed
866
    if (nr_ue_process_dci_freq_dom_resource_assignment(NULL, dlsch_config_pdu_1_1, 0, current_DL_BWP->BWPSize, dci->frequency_domain_assignment.val) < 0) {
867
      LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot);
868
      return -1;
869
    }
870
    /* TIME_DOM_RESOURCE_ASSIGNMENT */
871 872 873
    int dmrs_typeA_pos = (mac->scc != NULL) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position;
    NR_tda_info_t tda_info = get_dl_tda_info(current_DL_BWP, dci_ind->ss_type, dci->time_domain_assignment.val,
                                             dmrs_typeA_pos, mux_pattern, get_rnti_type(mac, rnti), coreset_type, false);
874

875 876
    dlsch_config_pdu_1_1->number_symbols = tda_info.nrOfSymbols;
    dlsch_config_pdu_1_1->start_symbol = tda_info.startSymbolIndex;
877

878
    struct NR_DMRS_DownlinkConfig *dl_dmrs_config = (tda_info.mapping_type == typeA) ?
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
                                                    pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup :
                                                    pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup;

    switch (dci->dmrs_sequence_initialization.val) {
      case 0:
        dlsch_config_pdu_1_1->nscid = 0;
        if(dl_dmrs_config->scramblingID0)
          dlsch_config_pdu_1_1->dlDmrsScramblingId = *dl_dmrs_config->scramblingID0;
        else
          dlsch_config_pdu_1_1->dlDmrsScramblingId = mac->physCellId;
        break;
      case 1:
        dlsch_config_pdu_1_1->nscid = 1;
        if(dl_dmrs_config->scramblingID1)
          dlsch_config_pdu_1_1->dlDmrsScramblingId = *dl_dmrs_config->scramblingID1;
        else
          dlsch_config_pdu_1_1->dlDmrsScramblingId = mac->physCellId;
        break;
      default:
        AssertFatal(1==0,"Invalid dmrs sequence initialization value\n");
    }

    dlsch_config_pdu_1_1->dmrsConfigType = dl_dmrs_config->dmrs_Type == NULL ? NFAPI_NR_DMRS_TYPE1 : NFAPI_NR_DMRS_TYPE2;
902

903 904 905
    /* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214,
             using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */
    dlsch_config_pdu_1_1->n_dmrs_cdm_groups = 1;
906
    /* VRB_TO_PRB_MAPPING */
907
    if ((pdsch_Config->resourceAllocation == 1) && (pdsch_Config->vrb_ToPRB_Interleaver != NULL))
908
      dlsch_config_pdu_1_1->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved;
909
    /* PRB_BUNDLING_SIZE_IND */
910
    dlsch_config_pdu_1_1->prb_bundling_size_ind = dci->prb_bundling_size_indicator.val;
911
    /* RATE_MATCHING_IND */
912
    dlsch_config_pdu_1_1->rate_matching_ind = dci->rate_matching_indicator.val;
913
    /* ZP_CSI_RS_TRIGGER */
914
    dlsch_config_pdu_1_1->zp_csi_rs_trigger = dci->zp_csi_rs_trigger.val;
915
    /* MCS (for transport block 1)*/
916
    dlsch_config_pdu_1_1->mcs = dci->mcs;
917 918
    // Basic sanity check for MCS value to check for a false or erroneous DCI
    if (dlsch_config_pdu_1_1->mcs > 28) {
919
      LOG_W(MAC, "[%d.%d] MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_1->mcs);
920 921
      return -1;
    }
922
    /* NDI (for transport block 1)*/
923
    dlsch_config_pdu_1_1->ndi = dci->ndi;
924
    /* RV (for transport block 1)*/
925
    dlsch_config_pdu_1_1->rv = dci->rv;
926
    /* MCS (for transport block 2)*/
927
    dlsch_config_pdu_1_1->tb2_mcs = dci->mcs2.val;
928 929
    // Basic sanity check for MCS value to check for a false or erroneous DCI
    if (dlsch_config_pdu_1_1->tb2_mcs > 28) {
930
      LOG_W(MAC, "[%d.%d] MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_1->tb2_mcs);
931 932
      return -1;
    }
933
    /* NDI (for transport block 2)*/
934
    dlsch_config_pdu_1_1->tb2_ndi = dci->ndi2.val;
935
    /* RV (for transport block 2)*/
936
    dlsch_config_pdu_1_1->tb2_rv = dci->rv2.val;
937
    /* HARQ_PROCESS_NUMBER */
938
    dlsch_config_pdu_1_1->harq_process_nbr = dci->harq_pid;
939 940
    /* TPC_PUCCH */
    // according to TS 38.213 Table 7.2.1-1
941 942 943 944
    if (dci->tpc == 0) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = -1;
    if (dci->tpc == 1) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 0;
    if (dci->tpc == 2) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 1;
    if (dci->tpc == 3) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 3;
945

946 947
    // Sanity check for pucch_resource_indicator value received to check for false DCI.
    valid = 0;
948
    pucch_res_set_cnt = pucch_Config->resourceSetToAddModList->list.count;
949
    for (int id = 0; id < pucch_res_set_cnt; id++) {
950
      if (dci->pucch_resource_indicator < pucch_Config->resourceSetToAddModList->list.array[id]->resourceList.list.count) {
951 952 953 954 955
        valid = 1;
        break;
      }
    }
    if (!valid) {
956
      LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dci->pucch_resource_indicator);
957 958 959
      return -1;
    }

960 961
    /* ANTENNA_PORTS */
    uint8_t n_codewords = 1; // FIXME!!!
962 963 964
    long *max_length = dl_dmrs_config->maxLength;
    long *dmrs_type = dl_dmrs_config->dmrs_Type;

965
    dlsch_config_pdu_1_1->n_front_load_symb = 1; // default value
966

967
    if ((dmrs_type == NULL) && (max_length == NULL)){
968
      // Table 7.3.1.2.2-1: Antenna port(s) (1000 + DMRS port), dmrs-Type=1, maxLength=1
969
      dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_1[dci->antenna_ports.val][0];
970 971
      dlsch_config_pdu_1_1->dmrs_ports = (table_7_3_2_3_3_1[dci->antenna_ports.val][1] +
                                          (table_7_3_2_3_3_1[dci->antenna_ports.val][2]<<1) +
972
                                          (table_7_3_2_3_3_1[dci->antenna_ports.val][3]<<2) +
973
                                          (table_7_3_2_3_3_1[dci->antenna_ports.val][4]<<3));
974
    }
975
    if ((dmrs_type == NULL) && (max_length != NULL)){
976 977
      // Table 7.3.1.2.2-2: Antenna port(s) (1000 + DMRS port), dmrs-Type=1, maxLength=2
      if (n_codewords == 1) {
978
	dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][0];
979 980
        dlsch_config_pdu_1_1->dmrs_ports = (table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][1] +
                                            (table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][2]<<1) +
981
                                            (table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][3]<<2) +
982 983 984 985 986 987
                                            (table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][4]<<3) +
                                            (table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][5]<<4) +
                                            (table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][6]<<5) +
                                            (table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][7]<<6) +
                                            (table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][8]<<7));
	dlsch_config_pdu_1_1->n_front_load_symb = table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][9];
988
      }
989
      if (n_codewords == 2) {
990
	dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][0];
991 992
        dlsch_config_pdu_1_1->dmrs_ports = (table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][1] +
                                            (table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][2]<<1) +
993
                                            (table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][3]<<2) +
994 995 996 997 998
                                            (table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][4]<<3) +
                                            (table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][5]<<4) +
                                            (table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][6]<<5) +
                                            (table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][7]<<6) +
                                            (table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][8]<<7));
999
	dlsch_config_pdu_1_1->n_front_load_symb = table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][9];
1000 1001
      }
    }
1002
    if ((dmrs_type != NULL) && (max_length == NULL)){
1003 1004
      // Table 7.3.1.2.2-3: Antenna port(s) (1000 + DMRS port), dmrs-Type=2, maxLength=1
      if (n_codewords == 1) {
1005
	dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][0];
1006 1007
        dlsch_config_pdu_1_1->dmrs_ports = (table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][1] +
                                            (table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][2]<<1) +
1008
                                            (table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][3]<<2) +
1009 1010 1011
                                            (table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][4]<<3) +
                                            (table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][5]<<4) +
                                            (table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][6]<<5));
1012
      }
1013
      if (n_codewords == 2) {
1014
	dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][0];
1015 1016
        dlsch_config_pdu_1_1->dmrs_ports = (table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][1] +
                                            (table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][2]<<1) +
1017
                                            (table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][3]<<2) +
1018 1019 1020
                                            (table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][4]<<3) +
                                            (table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][5]<<4) +
                                            (table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][6]<<5));
1021 1022
      }
    }
1023
    if ((dmrs_type != NULL) && (max_length != NULL)){
1024 1025
      // Table 7.3.1.2.2-4: Antenna port(s) (1000 + DMRS port), dmrs-Type=2, maxLength=2
      if (n_codewords == 1) {
1026
	dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][0];
1027 1028
        dlsch_config_pdu_1_1->dmrs_ports = (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][1] +
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][2]<<1) +
1029
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][3]<<2) +
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][4]<<3) +
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][5]<<4) +
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][6]<<5) +
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][7]<<6) +
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][8]<<7) +
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][9]<<8) +
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][10]<<9) +
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][11]<<10) +
                                            (table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][12]<<11));
	dlsch_config_pdu_1_1->n_front_load_symb = table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][13];
1040
      }
1041
      if (n_codewords == 2) {
1042
	dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][0];
1043 1044
        dlsch_config_pdu_1_1->dmrs_ports = (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][1] +
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][2]<<1) +
1045
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][3]<<2) +
1046 1047 1048 1049 1050 1051 1052 1053 1054
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][4]<<3) +
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][5]<<4) +
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][6]<<5) +
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][7]<<6) +
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][8]<<7) +
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][9]<<8) +
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][10]<<9) +
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][11]<<10) +
                                            (table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][12]<<11));
1055
	dlsch_config_pdu_1_1->n_front_load_symb = table_7_3_2_3_3_4_twoCodeword[dci->antenna_ports.val][9];
1056 1057
      }
    }
1058 1059

    /* dmrs symbol positions*/
1060
    dlsch_config_pdu_1_1->dlDmrsSymbPos = fill_dmrs_mask(pdsch_Config,
1061
                                                         NR_DL_DCI_FORMAT_1_1,
1062 1063
                                                         mac->scc? mac->scc->dmrs_TypeA_Position:mac->mib->dmrs_TypeA_Position,
                                                         dlsch_config_pdu_1_1->number_symbols,
1064
                                                         dlsch_config_pdu_1_1->start_symbol,
1065
                                                         tda_info.mapping_type,
1066 1067
                                                         dlsch_config_pdu_1_1->n_front_load_symb);

1068 1069 1070 1071
    /* TCI */
    if (mac->dl_config_request.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.tci_present_in_dci == 1){
      // 0 bit if higher layer parameter tci-PresentInDCI is not enabled
      // otherwise 3 bits as defined in Subclause 5.1.5 of [6, TS38.214]
1072
      dlsch_config_pdu_1_1->tci_state = dci->transmission_configuration_indication.val;
1073 1074 1075
    }
    /* SRS_REQUEST */
    // if SUL is supported in the cell, there is an additional bit in this field and the value of this bit represents table 7.1.1.1-1 TS 38.212 FIXME!!!
1076
    dlsch_config_pdu_1_1->srs_config.aperiodicSRS_ResourceTrigger = (dci->srs_request.val & 0x11); // as per Table 7.3.1.1.2-24 TS 38.212
1077
    /* CBGTI */
1078
    dlsch_config_pdu_1_1->cbgti = dci->cbgti.val;
1079
    /* CBGFI */
1080
    dlsch_config_pdu_1_1->codeBlockGroupFlushIndicator = dci->cbgfi.val;
1081 1082 1083
    /* DMRS_SEQ_INI */
    //FIXME!!!

1084 1085
    /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
    // according to TS 38.213 Table 9.2.3-1
1086
    uint8_t feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0];
1087

1088
    AssertFatal(feedback_ti>=DURATION_RX_TO_TX,"PDSCH to HARQ feedback time (%d) cannot be less than DURATION_RX_TO_TX (%d). Min feedback time set in config file (min_rxtxtime).\n",
francescomani's avatar
francescomani committed
1089 1090 1091 1092 1093 1094 1095 1096 1097
                feedback_ti,DURATION_RX_TO_TX);

    // set the harq status at MAC for feedback
    set_harq_status(mac,dci->pucch_resource_indicator,
                    dci->harq_pid,
                    dlsch_config_pdu_1_1->accumulated_delta_PUCCH,
                    feedback_ti,
                    dci->dai[0].val,
                    dci_ind->n_CCE,dci_ind->N_CCE,
francescomani's avatar
francescomani committed
1098
                    0,frame,slot);
1099

1100 1101
    dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH;
    LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type);
1102
            
1103
    dl_config->number_pdus = dl_config->number_pdus + 1;
1104
    /* TODO same calculation for MCS table as done in UL */
1105
    dlsch_config_pdu_1_1->mcs_table = (pdsch_Config->mcs_Table) ? (*pdsch_Config->mcs_Table + 1) : 0;
1106 1107
    dlsch_config_pdu_1_1->qamModOrder = nr_get_Qm_dl(dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table);
    int R = nr_get_code_rate_dl(dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table);
1108
    dlsch_config_pdu_1_1->targetCodeRate = R;
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
    if (dlsch_config_pdu_1_1->targetCodeRate == 0 || dlsch_config_pdu_1_1->qamModOrder == 0) {
      LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n");
      return -1;
    }
    uint8_t Nl = 0;
    for (int i = 0; i < 12; i++) { // max 12 ports
      if ((dlsch_config_pdu_1_1->dmrs_ports>>i)&0x01) Nl += 1;
    }
    int nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs
    int nb_re_dmrs = ((dmrs_type == NULL) ? 6:4)*dlsch_config_pdu_1_1->n_dmrs_cdm_groups;
    dlsch_config_pdu_1_1->TBS = nr_compute_tbs(dlsch_config_pdu_1_1->qamModOrder,
                                               R,
                                               dlsch_config_pdu_1_1->number_rbs,
                                               dlsch_config_pdu_1_1->number_symbols,
                                               nb_re_dmrs*get_num_dmrs(dlsch_config_pdu_1_1->dlDmrsSymbPos),
                                               nb_rb_oh, 0, Nl);
1125 1126

    // TBS_LBRM according to section 5.4.2.1 of 38.212
1127
    long *maxMIMO_Layers = current_DL_BWP->pdsch_servingcellconfig->ext1->maxMIMO_Layers;
1128 1129
    AssertFatal (maxMIMO_Layers != NULL,"Option with max MIMO layers not configured is not supported\n");
    int nl_tbslbrm = *maxMIMO_Layers < 4 ? *maxMIMO_Layers : 4;
1130
    int bw_tbslbrm = get_dlbw_tbslbrm(current_DL_BWP->initial_BWPSize, mac->cg);
1131 1132 1133
    dlsch_config_pdu_1_1->tbslbrm = nr_compute_tbslbrm(dlsch_config_pdu_1_1->mcs_table,
			                               bw_tbslbrm,
		                                       nl_tbslbrm);
1134
    /*PTRS configuration */
Laurent THOMAS's avatar
Laurent THOMAS committed
1135
    dlsch_config_pdu_1_1->pduBitmap = 0;
1136 1137
    if(pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) {
      valid_ptrs_setup = set_dl_ptrs_values(pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup,
1138 1139 1140 1141
                                            dlsch_config_pdu_1_1->number_rbs, dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table,
                                            &dlsch_config_pdu_1_1->PTRSFreqDensity,&dlsch_config_pdu_1_1->PTRSTimeDensity,
                                            &dlsch_config_pdu_1_1->PTRSPortIndex,&dlsch_config_pdu_1_1->nEpreRatioOfPDSCHToPTRS,
                                            &dlsch_config_pdu_1_1->PTRSReOffset, dlsch_config_pdu_1_1->number_symbols);
1142
      if(valid_ptrs_setup==true) {
1143
        dlsch_config_pdu_1_1->pduBitmap |= 0x1;
1144
        LOG_D(MAC, "DL PTRS values: PTRS time den: %d, PTRS freq den: %d\n", dlsch_config_pdu_1_1->PTRSTimeDensity, dlsch_config_pdu_1_1->PTRSFreqDensity);
1145 1146
      }
    }
1147

1148
    break;
1149
  }
1150

1151 1152
  case NR_DL_DCI_FORMAT_2_0:
    break;
1153

1154 1155
  case NR_DL_DCI_FORMAT_2_1:        
    break;
1156

1157 1158
  case NR_DL_DCI_FORMAT_2_2:        
    break;
1159

1160 1161
  case NR_DL_DCI_FORMAT_2_3:
    break;
1162

1163 1164 1165
  default: 
    break;
  }
1166

cig's avatar
cig committed
1167
  return ret;
1168
}
1169

1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
int8_t nr_ue_process_csirs_measurements(module_id_t module_id,
                                        frame_t frame,
                                        int slot,
                                        fapi_nr_csirs_measurements_t *csirs_measurements) {
  LOG_D(NR_MAC,"(%d.%d) Received CSI-RS measurements\n", frame, slot);
  NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
  memcpy(&mac->csirs_measurements, csirs_measurements, sizeof(*csirs_measurements));
  return 0;
}

1180 1181 1182 1183 1184 1185 1186 1187
void set_harq_status(NR_UE_MAC_INST_t *mac,
                     uint8_t pucch_id,
                     uint8_t harq_id,
                     int8_t delta_pucch,
                     uint8_t data_toul_fb,
                     uint8_t dai,
                     int n_CCE,
                     int N_CCE,
1188
                     int is_common,
1189 1190 1191 1192 1193 1194 1195 1196 1197
                     frame_t frame,
                     int slot) {

  NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id];

  current_harq->active = true;
  current_harq->ack_received = false;
  current_harq->pucch_resource_indicator = pucch_id;
  current_harq->feedback_to_ul = data_toul_fb;
1198
  current_harq->is_common = is_common;
1199 1200 1201 1202 1203 1204 1205
  current_harq->dai = dai;
  current_harq->n_CCE = n_CCE;
  current_harq->N_CCE = N_CCE;
  current_harq->delta_pucch = delta_pucch;
  // FIXME k0 != 0 currently not taken into consideration
  current_harq->dl_frame = frame;
  current_harq->dl_slot = slot;
1206
  if (get_softmodem_params()->emulate_l1) {
Melissa Elkadi's avatar
Melissa Elkadi committed
1207
    int scs = get_softmodem_params()->numerology;
Melissa Elkadi's avatar
Melissa Elkadi committed
1208
    int slots_per_frame = nr_slots_per_frame[scs];
Melissa Elkadi's avatar
Melissa Elkadi committed
1209 1210
    slot += data_toul_fb;
    if (slot >= slots_per_frame) {
Melissa Elkadi's avatar
Melissa Elkadi committed
1211
      frame = (frame + 1) % 1024;
Melissa Elkadi's avatar
Melissa Elkadi committed
1212
      slot %= slots_per_frame;
Melissa Elkadi's avatar
Melissa Elkadi committed
1213
    }
1214
  }
1215

1216
  LOG_D(NR_PHY,"Setting harq_status for harq_id %d, dl %d.%d, sched ul %d.%d\n",
1217
        harq_id, current_harq->dl_frame, current_harq->dl_slot, frame, slot);
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
}


void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
                           int slot,
                           uint16_t rnti,
                           PUCCH_sched_t *pucch,
                           fapi_nr_ul_config_pucch_pdu *pucch_pdu,
                           int O_SR, int O_ACK, int O_CSI) {

  int O_CRC = 0; //FIXME
  uint16_t O_uci = O_CSI + O_ACK;
1230
  NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP;
1231
  NR_UE_DL_BWP_t *current_DL_BWP = &mac->current_DL_BWP;
1232 1233 1234
  NR_PUCCH_FormatConfig_t *pucchfmt;
  long *pusch_id = NULL;
  long *id0 = NULL;
francescomani's avatar
francescomani committed
1235
  const int scs = current_UL_BWP->scs;
1236 1237 1238 1239 1240 1241

  int subframe_number = slot / (nr_slots_per_frame[scs]/10);
  nb_pucch_format_4_in_subframes[subframe_number] = 0;

  pucch_pdu->rnti = rnti;

1242
  LOG_D(NR_MAC,"initial_pucch_id %d, pucch_resource %p\n",pucch->initial_pucch_id,pucch->pucch_resource);
1243
  // configure pucch from Table 9.2.1-1
1244
  // only for ack/nack
1245 1246
  if (pucch->initial_pucch_id > -1 &&
      pucch->pucch_resource == NULL) {
1247 1248 1249 1250
    int pucch_resourcecommon = *current_UL_BWP->pucch_ConfigCommon->pucch_ResourceCommon;
    pucch_pdu->format_type = initial_pucch_resource[pucch_resourcecommon].format;
    pucch_pdu->start_symbol_index = initial_pucch_resource[pucch_resourcecommon].startingSymbolIndex;
    pucch_pdu->nr_of_symbols = initial_pucch_resource[pucch_resourcecommon].nrofSymbols;
1251

francescomani's avatar
francescomani committed
1252 1253
    pucch_pdu->bwp_size = current_UL_BWP->BWPSize;
    pucch_pdu->bwp_start = current_UL_BWP->BWPStart;
1254

1255 1256 1257
    pucch_pdu->prb_size = 1; // format 0 or 1
    int RB_BWP_offset;
    if (pucch->initial_pucch_id == 15)
1258
      RB_BWP_offset = pucch_pdu->bwp_size >> 2;
1259
    else
1260 1261 1262
      RB_BWP_offset = initial_pucch_resource[pucch_resourcecommon].PRB_offset;

    int N_CS = initial_pucch_resource[pucch_resourcecommon].nb_CS_indexes;
1263

1264 1265 1266 1267
    if (pucch->initial_pucch_id >> 3 == 0) {
      pucch_pdu->prb_start = RB_BWP_offset + (pucch->initial_pucch_id / N_CS);
      pucch_pdu->second_hop_prb = pucch_pdu->bwp_size - 1 - RB_BWP_offset - (pucch->initial_pucch_id / N_CS);
      pucch_pdu->initial_cyclic_shift = initial_pucch_resource[pucch_resourcecommon].initial_CS_indexes[pucch->initial_pucch_id % N_CS];
1268
    } else {
1269 1270
      pucch_pdu->prb_start = pucch_pdu->bwp_size - 1 - RB_BWP_offset - ((pucch->initial_pucch_id - 8) / N_CS);
      pucch_pdu->second_hop_prb = RB_BWP_offset + ((pucch->initial_pucch_id - 8) / N_CS);
1271
      pucch_pdu->initial_cyclic_shift = initial_pucch_resource[pucch_resourcecommon].initial_CS_indexes[(pucch->initial_pucch_id - 8) % N_CS];
1272 1273 1274
    }
    pucch_pdu->freq_hop_flag = 1;
    pucch_pdu->time_domain_occ_idx = 0;
1275

1276 1277 1278 1279
    if (O_ACK == 1)
      pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit[pucch->ack_payload & 0x1];   /* only harq of 1 bit */
    else
      pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits[pucch->ack_payload & 0x3];  /* only harq with 2 bits */
1280

1281
    pucch_pdu->payload = pucch->ack_payload;
1282 1283 1284 1285 1286
  }
  else if (pucch->pucch_resource != NULL) {

    NR_PUCCH_Resource_t *pucchres = pucch->pucch_resource;

1287
    if (current_UL_BWP->harq_ACK_SpatialBundlingPUCCH != NULL || *current_DL_BWP->pdsch_HARQ_ACK_Codebook != 1) {
1288
      LOG_E(MAC,"PUCCH Unsupported cell group configuration\n");
1289
      return;
1290
    } else if (current_DL_BWP && current_DL_BWP->pdsch_servingcellconfig && current_DL_BWP->pdsch_servingcellconfig->codeBlockGroupTransmission != NULL) {
1291
      LOG_E(MAC,"PUCCH Unsupported code block group for serving cell config\n");
1292 1293
      return;
    }
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303

    NR_PUSCH_Config_t *pusch_Config = current_UL_BWP ? current_UL_BWP->pusch_Config : NULL;
    if (pusch_Config) {
      pusch_id = pusch_Config->dataScramblingIdentityPUSCH;
      if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL)
        id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->transformPrecodingDisabled->scramblingID0;
      else if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL)
        id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->transformPrecodingDisabled->scramblingID0;
    }

1304
    NR_PUCCH_Config_t *pucch_Config = current_UL_BWP->pucch_Config;
1305
    AssertFatal(pucch_Config, "no pucch_Config\n");
1306

francescomani's avatar
francescomani committed
1307 1308
    pucch_pdu->bwp_size = current_UL_BWP->BWPSize;
    pucch_pdu->bwp_start = current_UL_BWP->BWPStart;
1309 1310 1311
    pucch_pdu->prb_start = pucchres->startingPRB;
    pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ?  1 : 0;
    pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ?  *pucchres->secondHopPRB : 0;
francescomani's avatar
francescomani committed
1312
    pucch_pdu->prb_size = 1; // format 0 or 1
1313 1314

    if ((O_SR+O_CSI+O_SR) > (sizeof(uint64_t)*8)) {
1315
      LOG_E(MAC,"PUCCH number of UCI bits exceeds payload size\n");
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354
      return;
    }
    pucch_pdu->payload = (pucch->csi_part1_payload << (O_ACK + O_SR)) |  (pucch->sr_payload << O_ACK) | pucch->ack_payload;

    switch(pucchres->format.present) {
      case NR_PUCCH_Resource__format_PR_format0 :
        pucch_pdu->format_type = 0;
        pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format0->initialCyclicShift;
        pucch_pdu->nr_of_symbols = pucchres->format.choice.format0->nrofSymbols;
        pucch_pdu->start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex;
        if (O_SR == 0 || pucch->sr_payload == 0) {  /* only ack is transmitted TS 36.213 9.2.3 UE procedure for reporting HARQ-ACK */
          if (O_ACK == 1)
            pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit[pucch->ack_payload & 0x1];   /* only harq of 1 bit */
          else
            pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits[pucch->ack_payload & 0x3];  /* only harq with 2 bits */
        }
        else { /* SR + eventually ack are transmitted TS 36.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR */
          if (pucch->sr_payload == 1) {                /* positive scheduling request */
            if (O_ACK == 1)
              pucch_pdu->mcs = sequence_cyclic_shift_1_harq_ack_bit_positive_sr[pucch->ack_payload & 0x1];   /* positive SR and harq of 1 bit */
            else if (O_ACK == 2)
              pucch_pdu->mcs = sequence_cyclic_shift_2_harq_ack_bits_positive_sr[pucch->ack_payload & 0x3];  /* positive SR and harq with 2 bits */
            else
              pucch_pdu->mcs = 0;  /* only positive SR */
          }
        }
        break;
      case NR_PUCCH_Resource__format_PR_format1 :
        pucch_pdu->format_type = 1;
        pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format1->initialCyclicShift;
        pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols;
        pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex;
        pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC;
        break;
      case NR_PUCCH_Resource__format_PR_format2 :
        pucch_pdu->format_type = 2;
        pucch_pdu->n_bit = O_uci+O_SR;
        pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols;
        pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex;
1355 1356
        pucch_pdu->data_scrambling_id = pusch_id != NULL ? *pusch_id : mac->physCellId;
        pucch_pdu->dmrs_scrambling_id = id0 != NULL ? *id0 : mac->physCellId;
1357 1358 1359 1360 1361 1362 1363 1364 1365
        pucch_pdu->prb_size = compute_pucch_prb_size(2,pucchres->format.choice.format2->nrofPRBs,
                                                     O_uci+O_SR,O_CSI,pucch_Config->format2->choice.setup->maxCodeRate,
                                                     2,pucchres->format.choice.format2->nrofSymbols,8);
        break;
      case NR_PUCCH_Resource__format_PR_format3 :
        pucch_pdu->format_type = 3;
        pucch_pdu->n_bit = O_uci+O_SR;
        pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols;
        pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex;
1366
        pucch_pdu->data_scrambling_id = pusch_id != NULL ? *pusch_id : mac->physCellId;
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408
        if (pucch_Config->format3 == NULL) {
          pucch_pdu->pi_2bpsk = 0;
          pucch_pdu->add_dmrs_flag = 0;
        }
        else {
          pucchfmt = pucch_Config->format3->choice.setup;
          pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ?  1 : 0;
          pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ?  1 : 0;
        }
        int f3_dmrs_symbols;
        if (pucchres->format.choice.format3->nrofSymbols==4)
          f3_dmrs_symbols = 1<<pucch_pdu->freq_hop_flag;
        else {
          if(pucchres->format.choice.format3->nrofSymbols<10)
            f3_dmrs_symbols = 2;
          else
            f3_dmrs_symbols = 2<<pucch_pdu->add_dmrs_flag;
        }
        pucch_pdu->prb_size = compute_pucch_prb_size(3,pucchres->format.choice.format3->nrofPRBs,
                                                     O_uci+O_SR,O_CSI,pucch_Config->format3->choice.setup->maxCodeRate,
                                                     2-pucch_pdu->pi_2bpsk,pucchres->format.choice.format3->nrofSymbols-f3_dmrs_symbols,12);
        break;
      case NR_PUCCH_Resource__format_PR_format4 :
        pucch_pdu->format_type = 4;
        pucch_pdu->nr_of_symbols = pucchres->format.choice.format4->nrofSymbols;
        pucch_pdu->start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex;
        pucch_pdu->pre_dft_occ_len = pucchres->format.choice.format4->occ_Length;
        pucch_pdu->pre_dft_occ_idx = pucchres->format.choice.format4->occ_Index;
        pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : mac->physCellId;
        if (pucch_Config->format3 == NULL) {
          pucch_pdu->pi_2bpsk = 0;
          pucch_pdu->add_dmrs_flag = 0;
        }
        else {
          pucchfmt = pucch_Config->format3->choice.setup;
          pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ?  1 : 0;
          pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ?  1 : 0;
        }
        break;
      default :
        AssertFatal(1==0,"Undefined PUCCH format \n");
    }
1409

1410
    pucch_pdu->pucch_tx_power = get_pucch_tx_power_ue(mac,
francescomani's avatar
francescomani committed
1411
                                                      scs,
1412 1413 1414 1415 1416 1417
                                                      pucch_Config,
                                                      pucch,
                                                      pucch_pdu->format_type,
                                                      pucch_pdu->prb_size,
                                                      pucch_pdu->freq_hop_flag,
                                                      pucch_pdu->add_dmrs_flag,
francescomani's avatar
francescomani committed
1418 1419 1420 1421
                                                      pucch_pdu->nr_of_symbols,
                                                      subframe_number,
                                                      O_ACK, O_SR,
                                                      O_CSI, O_CRC);
1422
  }
1423 1424
  else AssertFatal(1==0,"problem with pucch configuration\n");

1425 1426
  NR_PUCCH_ConfigCommon_t *pucch_ConfigCommon = current_UL_BWP->pucch_ConfigCommon;

1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
  if (pucch_ConfigCommon->hoppingId != NULL)
    pucch_pdu->hopping_id = *pucch_ConfigCommon->hoppingId;
  else
    pucch_pdu->hopping_id = mac->physCellId;

  switch (pucch_ConfigCommon->pucch_GroupHopping){
      case 0 :
      // if neither, both disabled
      pucch_pdu->group_hop_flag = 0;
      pucch_pdu->sequence_hop_flag = 0;
      break;
    case 1 :
      // if enable, group enabled
      pucch_pdu->group_hop_flag = 1;
      pucch_pdu->sequence_hop_flag = 0;
      break;
    case 2 :
      // if disable, sequence disabled
      pucch_pdu->group_hop_flag = 0;
      pucch_pdu->sequence_hop_flag = 1;
      break;
    default:
      AssertFatal(1==0,"Group hopping flag undefined (0,1,2) \n");
    }
1451 1452 1453 1454
}


int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
francescomani's avatar
francescomani committed
1455
                              int scs,
1456 1457 1458 1459 1460 1461 1462 1463 1464 1465
                              NR_PUCCH_Config_t *pucch_Config,
                              PUCCH_sched_t *pucch,
                              uint8_t format_type,
                              uint16_t nb_of_prbs,
                              uint8_t  freq_hop_flag,
                              uint8_t  add_dmrs_flag,
                              uint8_t N_symb_PUCCH,
                              int subframe_number,
                              int O_ACK, int O_SR,
                              int O_CSI, int O_CRC) {
1466
  NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP;
1467
  int PUCCH_POWER_DEFAULT = 0;
1468
  int16_t P_O_NOMINAL_PUCCH = *current_UL_BWP->pucch_ConfigCommon->p0_nominal;
1469 1470

  struct NR_PUCCH_PowerControl *power_config = pucch_Config->pucch_PowerControl;
1471 1472 1473 1474

  if (!power_config)
    return (PUCCH_POWER_DEFAULT);

1475 1476 1477 1478
  int16_t P_O_UE_PUCCH;
  int16_t G_b_f_c = 0;

  if (pucch_Config->spatialRelationInfoToAddModList != NULL) {  /* FFS TODO NR */
1479
    LOG_D(MAC,"PUCCH Spatial relation infos are not yet implemented\n");
1480 1481 1482 1483 1484 1485 1486 1487 1488
    return (PUCCH_POWER_DEFAULT);
  }

  if (power_config->p0_Set != NULL) {
    P_O_UE_PUCCH = power_config->p0_Set->list.array[0]->p0_PUCCH_Value; /* get from index 0 if no spatial relation set */
    G_b_f_c = 0;
  }
  else {
    G_b_f_c = pucch->delta_pucch;
1489
    LOG_E(MAC,"PUCCH Transmit power control command not yet implemented for NR\n");
1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549
    return (PUCCH_POWER_DEFAULT);
  }

  int P_O_PUCCH = P_O_NOMINAL_PUCCH + P_O_UE_PUCCH;

  int16_t delta_F_PUCCH;
  int DELTA_TF;
  uint16_t N_ref_PUCCH;
  int N_sc_ctrl_RB = 0;

  /* computing of pucch transmission power adjustment */
  switch (format_type) {
    case 0:
      N_ref_PUCCH = 2;
      DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH);
      delta_F_PUCCH =  *power_config->deltaF_PUCCH_f0;
      break;
    case 1:
      N_ref_PUCCH = 14;
      DELTA_TF = 10 * log10(N_ref_PUCCH/N_symb_PUCCH);
      delta_F_PUCCH =  *power_config->deltaF_PUCCH_f1;
      break;
    case 2:
      N_sc_ctrl_RB = 10;
      DELTA_TF = get_deltatf(nb_of_prbs,
                             N_symb_PUCCH,
                             freq_hop_flag,
                             add_dmrs_flag,
                             N_sc_ctrl_RB,
                             pucch->n_HARQ_ACK,
                             O_ACK, O_SR,
                             O_CSI, O_CRC);
      delta_F_PUCCH =  *power_config->deltaF_PUCCH_f2;
      break;
    case 3:
      N_sc_ctrl_RB = 14;
      DELTA_TF = get_deltatf(nb_of_prbs,
                             N_symb_PUCCH,
                             freq_hop_flag,
                             add_dmrs_flag,
                             N_sc_ctrl_RB,
                             pucch->n_HARQ_ACK,
                             O_ACK, O_SR,
                             O_CSI, O_CRC);
      delta_F_PUCCH =  *power_config->deltaF_PUCCH_f3;
      break;
    case 4:
      N_sc_ctrl_RB = 14/(nb_pucch_format_4_in_subframes[subframe_number]);
      DELTA_TF = get_deltatf(nb_of_prbs,
                             N_symb_PUCCH,
                             freq_hop_flag,
                             add_dmrs_flag,
                             N_sc_ctrl_RB,
                             pucch->n_HARQ_ACK,
                             O_ACK, O_SR,
                             O_CSI, O_CRC);
      delta_F_PUCCH =  *power_config->deltaF_PUCCH_f4;
      break;
    default:
    {
1550
      LOG_E(MAC,"PUCCH unknown pucch format %d\n", format_type);
1551 1552 1553 1554 1555
      return (0);
    }
  }

  if (*power_config->twoPUCCH_PC_AdjustmentStates > 1) {
1556
    LOG_E(MAC,"PUCCH power control adjustment states with 2 states not yet implemented\n");
1557 1558 1559
    return (PUCCH_POWER_DEFAULT);
  }

francescomani's avatar
francescomani committed
1560 1561 1562 1563
  int16_t pathloss = compute_nr_SSB_PL(mac, mac->phy_measurements.ssb_rsrp_dBm);
  int M_pucch_component = (10 * log10((double)(pow(2,scs) * nb_of_prbs)));

  int16_t pucch_power = P_O_PUCCH + M_pucch_component + pathloss + delta_F_PUCCH + DELTA_TF + G_b_f_c;
1564

1565 1566
  LOG_D(MAC, "PUCCH ( Tx power : %d dBm ) ( 10Log(...) : %d ) ( from Path Loss : %d ) ( delta_F_PUCCH : %d ) ( DELTA_TF : %d ) ( G_b_f_c : %d ) \n",
        pucch_power, M_pucch_component, pathloss, delta_F_PUCCH, DELTA_TF, G_b_f_c);
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611

  return (pucch_power);
}

int get_deltatf(uint16_t nb_of_prbs,
                uint8_t N_symb_PUCCH,
                uint8_t freq_hop_flag,
                uint8_t add_dmrs_flag,
                int N_sc_ctrl_RB,
                int n_HARQ_ACK,
                int O_ACK, int O_SR,
                int O_CSI, int O_CRC){

  int DELTA_TF;
  int O_UCI = O_ACK + O_SR + O_CSI + O_CRC;
  int N_symb = nb_symbols_excluding_dmrs[N_symb_PUCCH-4][add_dmrs_flag][freq_hop_flag];
  float N_RE = nb_of_prbs * N_sc_ctrl_RB * N_symb;
  float K1 = 6;
  if (O_UCI < 12)
    DELTA_TF = 10 * log10((double)(((K1 * (n_HARQ_ACK + O_SR + O_CSI))/N_RE)));
  else {
    float K2 = 2.4;
    float BPRE = O_UCI/N_RE;
    DELTA_TF = 10 * log10((double)(pow(2,(K2*BPRE)) - 1));
  }
  return DELTA_TF;
}

/*******************************************************************
*
* NAME :         find_pucch_resource_set
*
* PARAMETERS :   ue context
*                gNB_id identifier
*
*
* RETURN :       harq process identifier
*
* DESCRIPTION :  return tx harq process identifier for given transmission slot
*                YS 38.213 9.2.2  PUCCH Formats for UCI transmission
*
*********************************************************************/

int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, int uci_size) {
  int pucch_resource_set_id = 0;
1612
  NR_PUCCH_Config_t *pucch_Config = mac->current_UL_BWP.pucch_Config;
1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624

  //long *pucch_max_pl_bits = NULL;

  /* from TS 38.331 field maxPayloadMinus1
    -- Maximum number of payload bits minus 1 that the UE may transmit using this PUCCH resource set. In a PUCCH occurrence, the UE
    -- chooses the first of its PUCCH-ResourceSet which supports the number of bits that the UE wants to transmit.
    -- The field is not present in the first set (Set0) since the maximum Size of Set0 is specified to be 3 bit.
    -- The field is not present in the last configured set since the UE derives its maximum payload size as specified in 38.213.
    -- This field can take integer values that are multiples of 4. Corresponds to L1 parameter 'N_2' or 'N_3' (see 38.213, section 9.2)
  */
  /* look for the first resource set which supports uci_size number of bits for payload */
  while (pucch_resource_set_id < MAX_NB_OF_PUCCH_RESOURCE_SETS) {
1625
    if (pucch_Config && pucch_Config->resourceSetToAddModList && pucch_Config->resourceSetToAddModList->list.array[pucch_resource_set_id] != NULL) {
1626
      // PUCCH with format0 can be up to 3 bits (2 ack/nacks + 1 sr is 3 max bits)
1627
      if (uci_size <= 3) {
1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654
        pucch_resource_set_id = 0;
        return (pucch_resource_set_id);
        break;
      }
      else {
        pucch_resource_set_id = 1;
        return (pucch_resource_set_id);
        break;
      }
    }
    pucch_resource_set_id++;
  }

  pucch_resource_set_id = MAX_NB_OF_PUCCH_RESOURCE_SETS;

  return (pucch_resource_set_id);
}


/*******************************************************************
*
* NAME :         select_pucch_format
*
* PARAMETERS :   ue context
*                processing slots of reception/transmission
*                gNB_id identifier
*
1655
* RETURN :       true a valid resource has been found
1656 1657 1658 1659 1660 1661 1662 1663
*
* DESCRIPTION :  return tx harq process identifier for given transmission slot
*                TS 38.213 9.2.1  PUCCH Resource Sets
*                TS 38.213 9.2.2  PUCCH Formats for UCI transmission
*                In the case of pucch for scheduling request only, resource is already get from scheduling request configuration
*
*********************************************************************/

1664
void select_pucch_resource(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *pucch)
1665
{
1666
  NR_PUCCH_ResourceId_t *current_resource_id = NULL;
1667
  NR_PUCCH_Config_t *pucch_Config = mac->current_UL_BWP.pucch_Config;
1668
  int n_list;
1669
  if (pucch->is_common == 1 || !pucch_Config || !pucch_Config->resourceSetToAddModList || pucch_Config->resourceSetToAddModList->list.array[0] == NULL) {
1670 1671 1672 1673 1674
    /* see TS 38.213 9.2.1  PUCCH Resource Sets */
    int delta_PRI = pucch->resource_indicator;
    int n_CCE_0 = pucch->n_CCE;
    int N_CCE_0 = pucch->N_CCE;
    if (N_CCE_0 == 0) {
1675
      AssertFatal(1==0,"PUCCH No compatible pucch format found\n");
1676 1677 1678 1679
    }
    int r_PUCCH = ((2 * n_CCE_0)/N_CCE_0) + (2 * delta_PRI);
    pucch->initial_pucch_id = r_PUCCH;
    pucch->pucch_resource = NULL;
1680
  } else {
1681 1682
    struct NR_PUCCH_Config__resourceSetToAddModList *resourceSetToAddModList = pucch_Config->resourceSetToAddModList;
    struct NR_PUCCH_Config__resourceToAddModList *resourceToAddModList = pucch_Config->resourceToAddModList;
1683 1684
    n_list = resourceSetToAddModList->list.count;
    if (pucch->resource_set_id > n_list) {
1685
      LOG_E(MAC,"Invalid PUCCH resource set id %d\n",pucch->resource_set_id);
1686 1687 1688 1689 1690
      pucch->pucch_resource = NULL;
      return;
    }
    n_list = resourceSetToAddModList->list.array[pucch->resource_set_id]->resourceList.list.count;
    if (pucch->resource_indicator > n_list) {
1691
      LOG_E(MAC,"Invalid PUCCH resource id %d\n",pucch->resource_indicator);
1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705
      pucch->pucch_resource = NULL;
      return;
    }
    current_resource_id = resourceSetToAddModList->list.array[pucch->resource_set_id]->resourceList.list.array[pucch->resource_indicator];
    n_list = resourceToAddModList->list.count;
    int res_found = 0;
    for (int i=0; i<n_list; i++) {
      if (resourceToAddModList->list.array[i]->pucch_ResourceId == *current_resource_id) {
        pucch->pucch_resource = resourceToAddModList->list.array[i];
        res_found = 1;
        break;
      }
    }
    if (res_found == 0) {
1706
      LOG_E(MAC,"Couldn't find PUCCH Resource\n");
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750
      pucch->pucch_resource = NULL;
    }
  }
}

/*******************************************************************
*
* NAME :         get_downlink_ack
*
* PARAMETERS :   ue context
*                processing slots of reception/transmission
*                gNB_id identifier
*
* RETURN :       o_ACK acknowledgment data
*                o_ACK_number_bits number of bits for acknowledgment
*
* DESCRIPTION :  return acknowledgment value
*                TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination
*
*          --+--------+-------+--------+-------+---  ---+-------+--
*            | PDCCH1 |       | PDCCH2 |PDCCH3 |        | PUCCH |
*          --+--------+-------+--------+-------+---  ---+-------+--
*    DAI_DL      1                 2       3              ACK for
*                V                 V       V        PDCCH1, PDDCH2 and PCCH3
*                |                 |       |               ^
*                +-----------------+-------+---------------+
*
*                PDCCH1, PDCCH2 and PDCCH3 are PDCCH monitoring occasions
*                M is the total of monitoring occasions
*
*********************************************************************/

uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac,
                         frame_t frame,
                         int slot,
                         PUCCH_sched_t *pucch) {


  uint32_t ack_data[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}};
  uint32_t dai[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}};       /* for serving cell */
  uint32_t dai_total[NR_DL_MAX_NB_CW][NR_DL_MAX_DAI] = {{0},{0}}; /* for multiple cells */
  int number_harq_feedback = 0;
  uint32_t dai_current = 0;
  uint32_t dai_max = 0;
1751
  bool two_transport_blocks = false;
1752 1753 1754 1755 1756 1757
  int number_of_code_word = 1;
  int U_DAI_c = 0;
  int N_m_c_rx = 0;
  int V_DAI_m_DL = 0;
  NR_UE_HARQ_STATUS_t *current_harq;
  int sched_frame,sched_slot;
francescomani's avatar
francescomani committed
1758
  int slots_per_frame;
1759

1760 1761
  NR_UE_DL_BWP_t *current_DL_BWP = &mac->current_DL_BWP;
  NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP;
1762

1763
  if (current_DL_BWP && current_DL_BWP->pdsch_Config && current_DL_BWP->pdsch_Config->maxNrofCodeWordsScheduledByDCI && current_DL_BWP->pdsch_Config->maxNrofCodeWordsScheduledByDCI[0] == 2) {
1764
    two_transport_blocks = true;
1765 1766 1767
    number_of_code_word = 2;
  }

francescomani's avatar
francescomani committed
1768
  int scs = current_UL_BWP->scs;
1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784

  slots_per_frame = nr_slots_per_frame[scs];

  /* look for dl acknowledgment which should be done on current uplink slot */
  for (int code_word = 0; code_word < number_of_code_word; code_word++) {

    for (int dl_harq_pid = 0; dl_harq_pid < 16; dl_harq_pid++) {

      current_harq = &mac->dl_harq_info[dl_harq_pid];

      if (current_harq->active) {

        sched_slot = current_harq->dl_slot + current_harq->feedback_to_ul;
        sched_frame = current_harq->dl_frame;
        if (sched_slot>=slots_per_frame){
          sched_slot %= slots_per_frame;
Melissa Elkadi's avatar
Melissa Elkadi committed
1785
          sched_frame = (sched_frame + 1) % 1024;
1786
        }
Melissa Elkadi's avatar
Melissa Elkadi committed
1787
        AssertFatal(sched_slot < slots_per_frame, "sched_slot was calculated incorrect %d\n", sched_slot);
1788
        LOG_D(PHY, "HARQ pid %d is active for %d.%d (dl_slot %d, feedback_to_ul %d\n", dl_harq_pid, sched_frame, sched_slot, current_harq->dl_slot, current_harq->feedback_to_ul);
1789 1790
        /* check if current tx slot should transmit downlink acknowlegment */
        if (sched_frame == frame && sched_slot == slot) {
1791 1792
          if (get_softmodem_params()->emulate_l1) {
            mac->nr_ue_emul_l1.harq[dl_harq_pid].active = true;
Melissa Elkadi's avatar
Melissa Elkadi committed
1793 1794
            mac->nr_ue_emul_l1.harq[dl_harq_pid].active_dl_harq_sfn = frame;
            mac->nr_ue_emul_l1.harq[dl_harq_pid].active_dl_harq_slot = slot;
1795
          }
1796 1797

          if (current_harq->dai > NR_DL_MAX_DAI) {
1798
            LOG_E(MAC,"PUCCH Downlink DAI has an invalid value of %d\n", current_harq->dai);
1799 1800 1801 1802
          }
          else {

            if ((pucch->resource_indicator != -1) && (pucch->resource_indicator != current_harq->pucch_resource_indicator))
1803
              LOG_E(MAC, "Value of pucch_resource_indicator %d not matching with what set before %d (Possibly due to a false DCI) \n",
1804 1805 1806 1807 1808
                    current_harq->pucch_resource_indicator,pucch->resource_indicator);
            else{
              dai_current = current_harq->dai+1; // DCI DAI to counter DAI conversion

              if (dai_current == 0) {
1809
                LOG_E(MAC,"PUCCH Downlink dai is invalid\n");
1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825
                return(0);
              } else if (dai_current > dai_max) {
                dai_max = dai_current;
              }

              number_harq_feedback++;
              if (current_harq->ack_received)
                ack_data[code_word][dai_current - 1] = current_harq->ack;
              else
                ack_data[code_word][dai_current - 1] = 0;
              dai[code_word][dai_current - 1] = dai_current;

              pucch->resource_indicator = current_harq->pucch_resource_indicator;
              pucch->n_CCE = current_harq->n_CCE;
              pucch->N_CCE = current_harq->N_CCE;
              pucch->delta_pucch = current_harq->delta_pucch;
1826
              pucch->is_common = current_harq->is_common;
1827 1828
              current_harq->active = false;
              current_harq->ack_received = false;
Robert Schmidt's avatar
Robert Schmidt committed
1829
	      LOG_D(PHY,"%4d.%2d Sent %d ack on harq pid %d\n", frame, slot, current_harq->ack, dl_harq_pid);
1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842
            }
          }
        }
      }
    }
  }

  /* no any ack to transmit */
  if (number_harq_feedback == 0) {
    pucch->n_HARQ_ACK = 0;
    return(0);
  }
  else  if (number_harq_feedback > (sizeof(uint32_t)*8)) {
1843
    LOG_E(MAC,"PUCCH number of ack bits exceeds payload size\n");
1844 1845 1846 1847 1848 1849 1850 1851
    return(0);
  }

  /* for computing n_HARQ_ACK for power */
  V_DAI_m_DL = dai_max;
  U_DAI_c = number_harq_feedback/number_of_code_word;
  N_m_c_rx = number_harq_feedback;
  int N_SPS_c = 0; /* FFS TODO_NR multicells and SPS are not supported at the moment */
1852
  if (current_UL_BWP->harq_ACK_SpatialBundlingPUCCH != NULL) {
francescomani's avatar
francescomani committed
1853
    int N_TB_max_DL = current_DL_BWP->pdsch_Config->maxNrofCodeWordsScheduledByDCI[0];
1854
    pucch->n_HARQ_ACK = (((V_DAI_m_DL - U_DAI_c)%4) * N_TB_max_DL) + N_m_c_rx + N_SPS_c;
1855
    LOG_D(MAC, "PUCCH power n(%d) = ( V(%d) - U(%d) )mod4 * N_TB(%d) + N(%d) \n", pucch->n_HARQ_ACK, V_DAI_m_DL, U_DAI_c, N_TB_max_DL, N_m_c_rx);
1856 1857 1858 1859 1860 1861
  }

  /*
  * For a monitoring occasion of a PDCCH with DCI format 1_0 or DCI format 1_1 in at least one serving cell,
  * when a UE receives a PDSCH with one transport block and the value of higher layer parameter maxNrofCodeWordsScheduledByDCI is 2,
  * the HARQ-ACK response is associated with the first transport block and the UE generates a NACK for the second transport block
1862
  * if spatial bundling is not applied (HARQ-ACK-spatial-bundling-PUCCH = false) and generates HARQ-ACK value of ACK for the second
1863 1864 1865 1866 1867 1868 1869 1870 1871 1872
  * transport block if spatial bundling is applied.
  */

  for (int code_word = 0; code_word < number_of_code_word; code_word++) {
    for (uint32_t i = 0; i < dai_max ; i++ ) {
      if (dai[code_word][i] != i + 1) { /* fill table with consistent value for each dai */
        dai[code_word][i] = i + 1;      /* it covers case for which PDCCH DCI has not been successfully decoded and so it has been missed */
        ack_data[code_word][i] = 0;     /* nack data transport block which has been missed */
        number_harq_feedback++;
      }
1873
      if (two_transport_blocks == true) {
1874 1875 1876 1877 1878 1879 1880 1881 1882 1883
        dai_total[code_word][i] = dai[code_word][i]; /* for a single cell, dai_total is the same as dai of first cell */
      }
    }
  }

  int M = dai_max;
  int j = 0;
  uint32_t V_temp = 0;
  uint32_t V_temp2 = 0;
  int O_ACK = 0;
francescomani's avatar
francescomani committed
1884
  uint8_t o_ACK = 0;
1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903
  int O_bit_number_cw0 = 0;
  int O_bit_number_cw1 = 0;

  for (int m = 0; m < M ; m++) {

    if (dai[0][m] <= V_temp) {
      j = j + 1;
    }

    V_temp = dai[0][m]; /* value of the counter DAI for format 1_0 and format 1_1 on serving cell c */

    if (dai_total[0][m] == 0) {
      V_temp2 = dai[0][m];
    } else {
      V_temp2 = dai[1][m];         /* second code word has been received */
      O_bit_number_cw1 = (8 * j) + 2*(V_temp - 1) + 1;
      o_ACK = o_ACK | (ack_data[1][m] << O_bit_number_cw1);
    }

1904
    if (two_transport_blocks == true) {
1905 1906 1907 1908 1909 1910 1911
      O_bit_number_cw0 = (8 * j) + 2*(V_temp - 1);
    }
    else {
      O_bit_number_cw0 = (4 * j) + (V_temp - 1);
    }

    o_ACK = o_ACK | (ack_data[0][m] << O_bit_number_cw0);
francescomani's avatar
francescomani committed
1912
    LOG_D(MAC,"m %d bit number %d o_ACK %d\n",m,O_bit_number_cw0,o_ACK);
1913 1914 1915 1916 1917 1918
  }

  if (V_temp2 < V_temp) {
    j = j + 1;
  }

1919
  if (two_transport_blocks == true) {
1920 1921 1922 1923 1924 1925 1926
    O_ACK = 2 * ( 4 * j + V_temp2);  /* for two transport blocks */
  }
  else {
    O_ACK = 4 * j + V_temp2;         /* only one transport block */
  }

  if (number_harq_feedback != O_ACK) {
1927
    LOG_E(MAC,"PUCCH Error for number of bits for acknowledgment\n");
1928 1929 1930
    return (0);
  }

francescomani's avatar
francescomani committed
1931
  reverse_n_bits(&o_ACK,number_harq_feedback);
1932
  pucch->ack_payload = o_ACK;
1933

1934
  LOG_D(MAC,"frame %d slot %d pucch acknack payload %d\n",frame,slot,o_ACK);
francescomani's avatar
francescomani committed
1935

1936 1937 1938 1939
  return(number_harq_feedback);
}


1940 1941 1942 1943
bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac,
                                         PUCCH_sched_t *pucch,
                                         frame_t frame,
                                         int slot) {
1944

1945
  NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP;
1946
  NR_PUCCH_Config_t *pucch_Config = current_UL_BWP->pucch_Config;
1947

francescomani's avatar
francescomani committed
1948
  const int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs];
1949

1950 1951
  if(!pucch_Config ||
     !pucch_Config->schedulingRequestResourceToAddModList ||
1952
     pucch_Config->schedulingRequestResourceToAddModList->list.count==0)
1953 1954 1955 1956 1957 1958
    return false; // SR not configured

  for (int SR_resource_id =0; SR_resource_id < pucch_Config->schedulingRequestResourceToAddModList->list.count;SR_resource_id++) {
    NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id];
    int SR_period; int SR_offset;

francescomani's avatar
francescomani committed
1959
    find_period_offset_SR(SchedulingRequestResourceConfig,&SR_period,&SR_offset);
1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985
    int sfn_sf = frame * n_slots_frame + slot;

    if ((sfn_sf - SR_offset) % SR_period == 0) {
      LOG_D(MAC, "Scheduling Request active in frame %d slot %d \n", frame, slot);
      NR_PUCCH_ResourceId_t *PucchResourceId = SchedulingRequestResourceConfig->resource;

      int found = -1;
      NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0]; // set with formats 0,1
      int n_list = pucchresset->resourceList.list.count;
       for (int i=0; i<n_list; i++) {
        if (*pucchresset->resourceList.list.array[i] == *PucchResourceId ) {
          found = i;
          break;
        }
      }
      if (found == -1) {
        LOG_E(MAC,"Couldn't find PUCCH resource for SR\n");
        return false;
      }
      pucch->resource_indicator = found;
      return true;
    }
  }
  return false;
}

1986
int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slot){
mjoang's avatar
mjoang committed
1987
  // no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti
Robert Schmidt's avatar
Robert Schmidt committed
1988
  DevCheck(module_idP < NB_NR_UE_MAC_INST, module_idP, NB_NR_UE_MAC_INST, 0);
mjoang's avatar
mjoang committed
1989
  NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
1990
  DSR_TRANSMAX_t dsr_TransMax = sr_n64; // todo
1991
  LOG_D(NR_MAC, "[UE %d] Frame %d slot %d send SR indication (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n",
1992
        module_idP, frameP, slot,
mjoang's avatar
mjoang committed
1993
        mac->scheduling_info.SR_COUNTER,
1994
        (1 << (2 + dsr_TransMax)),
mjoang's avatar
mjoang committed
1995
        mac->scheduling_info.SR_pending); // todo
1996

mjoang's avatar
mjoang committed
1997
  if ((mac->scheduling_info.SR_pending == 1) &&
1998 1999
      (mac->scheduling_info.SR_COUNTER < (1 << (2 + dsr_TransMax)))) {
    LOG_D(NR_MAC, "[UE %d] Frame %d slot %d PHY asks for SR (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d, increment SR_COUNTER\n",
2000
          module_idP, frameP, slot,
mjoang's avatar
mjoang committed
2001
          mac->scheduling_info.SR_COUNTER,
2002
          (1 << (2 + dsr_TransMax)),
2003
          mac->scheduling_info.SR_pending); // todo
mjoang's avatar
mjoang committed
2004 2005 2006 2007 2008
    mac->scheduling_info.SR_COUNTER++;

    // start the sr-prohibittimer : rel 9 and above
    if (mac->scheduling_info.sr_ProhibitTimer > 0) { // timer configured
      mac->scheduling_info.sr_ProhibitTimer--;
francescomani's avatar
francescomani committed
2009
      mac->scheduling_info.sr_ProhibitTimer_Running = 1;
mjoang's avatar
mjoang committed
2010
    } else {
francescomani's avatar
francescomani committed
2011
      mac->scheduling_info.sr_ProhibitTimer_Running = 0;
mjoang's avatar
mjoang committed
2012 2013 2014 2015 2016 2017 2018 2019 2020
    }
    //mac->ul_active =1;
    return (1);   //instruct phy to signal SR
  } else {
    // notify RRC to relase PUCCH/SRS
    // clear any configured dl/ul
    // initiate RA
    if (mac->scheduling_info.SR_pending) {
      // release all pucch resource
2021 2022
      //mac->physicalConfigDedicated = NULL; // todo
      //mac->ul_active = 0; // todo
mjoang's avatar
mjoang committed
2023 2024
      mac->BSR_reporting_active =
        NR_BSR_TRIGGER_NONE;
mjoang's avatar
mjoang committed
2025
      LOG_I(NR_MAC, "[UE %d] Release all SRs \n", module_idP);
mjoang's avatar
mjoang committed
2026 2027 2028 2029 2030 2031
    }

    mac->scheduling_info.SR_pending = 0;
    mac->scheduling_info.SR_COUNTER = 0;
    return (0);
  }
2032 2033
}

2034 2035 2036 2037 2038 2039

uint8_t nr_get_csi_measurements(NR_UE_MAC_INST_t *mac,
                                frame_t frame,
                                int slot,
                                PUCCH_sched_t *pucch) {

2040
  NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP;
francescomani's avatar
francescomani committed
2041
  NR_BWP_Id_t bwp_id = current_UL_BWP->bwp_id;
2042
  NR_PUCCH_Config_t *pucch_Config = current_UL_BWP->pucch_Config;
2043 2044
  int csi_bits = 0;

2045
  if (current_UL_BWP->csi_MeasConfig) {
2046
    NR_CSI_MeasConfig_t *csi_measconfig = current_UL_BWP->csi_MeasConfig;
2047 2048

    for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
2049
      NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
2050 2051

      if(csirep->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_periodic){
2052 2053 2054 2055 2056

        const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
        if(pucchcsires->uplinkBandwidthPartId != bwp_id)
          continue;

2057
        int period, offset;
2058
        csi_period_offset(csirep, NULL, &period, &offset);
2059

francescomani's avatar
francescomani committed
2060
        const int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs];
2061
        if (((n_slots_frame*frame + slot - offset)%period) == 0 && pucch_Config) {
2062
          LOG_D(NR_MAC, "Preparing CSI report in frame %d slot %d CSI report ID %d\n", frame, slot, csi_report_id);
2063 2064 2065 2066 2067
          NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
          NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
          int n = pucchresset->resourceList.list.count;

          int res_index;
2068
          int found = -1;
2069
          for (res_index = 0; res_index < n; res_index++) {
2070 2071
            if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource) {
              found = res_index;
2072
              break;
2073
            }
2074
          }
2075
          AssertFatal(found != -1,
2076
                      "CSI resource not found among PUCCH resources\n");
2077
          LOG_D(NR_MAC, "CSI reporting in frame %d slot %d CSI report ID %ld\n", frame, slot, csirep->reportConfigId);
2078
          pucch->resource_indicator = found;
francescomani's avatar
francescomani committed
2079
          csi_bits += nr_get_csi_payload(mac, pucch, csi_report_id, csi_measconfig);
2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092
        }
      }
      else
        AssertFatal(1==0,"Only periodic CSI reporting is currently implemented\n");
    }
  }

  return csi_bits;
}


uint8_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
                           PUCCH_sched_t *pucch,
francescomani's avatar
francescomani committed
2093
                           int csi_report_id,
2094 2095 2096 2097 2098 2099
                           NR_CSI_MeasConfig_t *csi_MeasConfig) {

  int n_csi_bits = 0;

  AssertFatal(csi_MeasConfig->csi_ReportConfigToAddModList->list.count>0,"No CSI Report configuration available\n");

francescomani's avatar
francescomani committed
2100 2101 2102 2103 2104 2105 2106 2107 2108
  struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
  NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement;
  switch(csi_reportconfig->reportQuantity.present) {
    case NR_CSI_ReportConfig__reportQuantity_PR_none:
      break;
    case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
      n_csi_bits = get_ssb_rsrp_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig);
      break;
    case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
2109 2110 2111
      n_csi_bits = get_csirs_RI_PMI_CQI_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig);
      break;
    case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
2112 2113
      n_csi_bits = get_csirs_RSRP_payload(mac,pucch,csi_reportconfig,csi_ResourceConfigId,csi_MeasConfig);
      break;
francescomani's avatar
francescomani committed
2114 2115 2116 2117
    case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1:
    case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI:
    case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
    case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
Roberto Louro Magueta's avatar
Roberto Louro Magueta committed
2118
      LOG_E(NR_MAC,"Measurement report %d based on CSI-RS is not available\n", csi_reportconfig->reportQuantity.present);
2119
      break;
francescomani's avatar
francescomani committed
2120 2121
    default:
      AssertFatal(1==0,"Invalid CSI report quantity type %d\n",csi_reportconfig->reportQuantity.present);
2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149
  }
  return (n_csi_bits);
}


uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
                             PUCCH_sched_t *pucch,
                             struct NR_CSI_ReportConfig *csi_reportconfig,
                             NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
                             NR_CSI_MeasConfig_t *csi_MeasConfig) {

  int nb_ssb = 0;  // nb of ssb in the resource
  int nb_meas = 0; // nb of ssb to report measurements on
  int bits = 0;
  uint32_t temp_payload = 0;

  for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {
    struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx];
    if (csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) {

      if (csi_reportconfig->groupBasedBeamReporting.present == NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled) {
        if (csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS != NULL)
          nb_meas = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1;
        else
          nb_meas = 1;
      } else
        nb_meas = 2;

2150
      struct NR_CSI_SSB_ResourceSet__csi_SSB_ResourceList SSB_resource;
2151 2152 2153
      for (int csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
        if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId ==
            *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){
2154
          SSB_resource = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList;
2155
          ///only one SSB resource set from spec 38.331 IE CSI-ResourceConfig
2156
          nb_ssb = SSB_resource.list.count;
2157 2158 2159 2160 2161
          break;
        }
      }

      AssertFatal(nb_ssb>0,"No SSB found in the resource set\n");
2162
      AssertFatal(nb_meas==1,"PHY currently reports only the strongest SSB to MAC. Can't report more than 1 RSRP\n");
2163 2164 2165 2166 2167
      int ssbri_bits = ceil(log2(nb_ssb));

      int ssb_rsrp[2][nb_meas]; // the array contains index and RSRP of each SSB to be reported (nb_meas highest RSRPs)

      //TODO replace the following 2 lines with a function to order the nb_meas highest SSB RSRPs
2168 2169 2170 2171 2172 2173 2174
      for (int i=0; i<nb_ssb; i++) {
        if(*SSB_resource.list.array[i] == mac->mib_ssb) {
          ssb_rsrp[0][0] = i;
          break;
        }
      }
      AssertFatal(*SSB_resource.list.array[ssb_rsrp[0][0]] == mac->mib_ssb, "Couldn't find corresponding SSB in csi_SSB_ResourceList\n");
2175
      ssb_rsrp[1][0] = mac->phy_measurements.ssb_rsrp_dBm;
2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202

      uint8_t ssbi;

      if (ssbri_bits > 0) {
        ssbi = ssb_rsrp[0][0];
        reverse_n_bits(&ssbi, ssbri_bits);
        temp_payload = ssbi;
        bits += ssbri_bits;
      }

      uint8_t rsrp_idx = get_rsrp_index(ssb_rsrp[1][0]);
      reverse_n_bits(&rsrp_idx, 7);
      temp_payload |= (rsrp_idx<<bits);
      bits += 7; // 7 bits for highest RSRP

      // from the second SSB, differential report
      for (int i=1; i<nb_meas; i++){
        ssbi = ssb_rsrp[0][i];
        reverse_n_bits(&ssbi, ssbri_bits);
        temp_payload = ssbi;
        bits += ssbri_bits;

        rsrp_idx = get_rsrp_diff_index(ssb_rsrp[1][0],ssb_rsrp[1][i]);
        reverse_n_bits(&rsrp_idx, 4);
        temp_payload |= (rsrp_idx<<bits);
        bits += 4; // 7 bits for highest RSRP
      }
2203
      break; // resorce found
2204 2205 2206 2207 2208 2209
    }
  }
  pucch->csi_part1_payload = temp_payload;
  return bits;
}

2210 2211 2212 2213 2214 2215
uint8_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
                                     PUCCH_sched_t *pucch,
                                     struct NR_CSI_ReportConfig *csi_reportconfig,
                                     NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
                                     NR_CSI_MeasConfig_t *csi_MeasConfig) {

2216
  int n_bits = 0;
2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227
  uint32_t temp_payload = 0;

  for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {

    struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx];
    if (csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) {

      for (int csi_idx = 0; csi_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_idx++) {
        if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_ResourceSetId ==
            *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) {

2228
          nr_csi_report_t *csi_report = &mac->csi_report_template[csi_idx];
2229
          compute_csi_bitlen(csi_MeasConfig, mac->csi_report_template);
2230
          n_bits = nr_get_csi_bitlen(mac->csi_report_template, csi_idx);
2231 2232 2233

          int cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen;
          int ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen;
2234 2235 2236
          int pmi_x1_bitlen = csi_report->csi_meas_bitlen.pmi_x1_bitlen[mac->csirs_measurements.rank_indicator];
          int pmi_x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[mac->csirs_measurements.rank_indicator];
          int cqi_bitlen = csi_report->csi_meas_bitlen.cqi_bitlen[mac->csirs_measurements.rank_indicator];
2237
          int padding_bitlen = n_bits - (cri_bitlen + ri_bitlen + pmi_x1_bitlen + pmi_x2_bitlen + cqi_bitlen);
2238

Melissa Elkadi's avatar
Melissa Elkadi committed
2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249
          if (get_softmodem_params()->emulate_l1) {
            static const uint8_t mcs_to_cqi[] = {0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
                                                 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15};
            CHECK_INDEX(nr_bler_data, NR_NUM_MCS - 1);
            int mcs = get_mcs_from_sinr(nr_bler_data, (mac->nr_ue_emul_l1.cqi - 640) * 0.1);
            CHECK_INDEX(mcs_to_cqi, mcs);
            mac->csirs_measurements.rank_indicator = mac->nr_ue_emul_l1.ri;
            mac->csirs_measurements.i1 = mac->nr_ue_emul_l1.pmi;
            mac->csirs_measurements.cqi = mcs_to_cqi[mcs];
          }

2250
          // TODO: Improvements will be needed to cri_bitlen>0 and pmi_x1_bitlen>0
2251 2252 2253 2254
          temp_payload = (mac->csirs_measurements.rank_indicator<<(cri_bitlen+cqi_bitlen+pmi_x2_bitlen+padding_bitlen+pmi_x1_bitlen)) |
                         (mac->csirs_measurements.i1<<(cri_bitlen+cqi_bitlen+pmi_x2_bitlen)) |
                         (mac->csirs_measurements.i2<<(cri_bitlen+cqi_bitlen)) |
                         (mac->csirs_measurements.cqi<<cri_bitlen) |
2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
                         0;

          reverse_n_bits((uint8_t *)&temp_payload, n_bits);

          LOG_D(NR_MAC, "cri_bitlen = %d\n", cri_bitlen);
          LOG_D(NR_MAC, "ri_bitlen = %d\n", ri_bitlen);
          LOG_D(NR_MAC, "pmi_x1_bitlen = %d\n", pmi_x1_bitlen);
          LOG_D(NR_MAC, "pmi_x2_bitlen = %d\n", pmi_x2_bitlen);
          LOG_D(NR_MAC, "cqi_bitlen = %d\n", cqi_bitlen);
          LOG_D(NR_MAC, "csi_part1_payload = 0x%x\n", temp_payload);
2265

2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295
          LOG_D(NR_MAC, "n_bits = %d\n", n_bits);
          LOG_D(NR_MAC, "csi_part1_payload = 0x%x\n", temp_payload);

          break;
        }
      }
    }
  }
  pucch->csi_part1_payload = temp_payload;
  return n_bits;
}

uint8_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac,
                               PUCCH_sched_t *pucch,
                               struct NR_CSI_ReportConfig *csi_reportconfig,
                               NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
                               NR_CSI_MeasConfig_t *csi_MeasConfig) {

  int n_bits = 0;
  uint32_t temp_payload = 0;

  for (int csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {

    struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx];
    if (csi_resourceconfig->csi_ResourceConfigId == csi_ResourceConfigId) {

      for (int csi_idx = 0; csi_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_idx++) {
        if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_idx]->nzp_CSI_ResourceSetId ==
            *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) {

2296
          nr_csi_report_t *csi_report = &mac->csi_report_template[csi_idx];
2297
          compute_csi_bitlen(csi_MeasConfig, mac->csi_report_template);
2298
          n_bits = nr_get_csi_bitlen(mac->csi_report_template, csi_idx);
2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310

          int cri_ssbri_bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen;
          int rsrp_bitlen = csi_report->CSI_report_bitlen.rsrp_bitlen;
          int diff_rsrp_bitlen = csi_report->CSI_report_bitlen.diff_rsrp_bitlen;

          if (cri_ssbri_bitlen > 0) {
            LOG_E(NR_MAC, "Implementation for cri_ssbri_bitlen>0 is not supported yet!\n");;
          }

          // TODO: Improvements will be needed to cri_ssbri_bitlen>0
          // TS 38.133 - Table 10.1.6.1-1
          int rsrp_dBm = mac->csirs_measurements.rsrp_dBm;
2311 2312 2313 2314
          if (rsrp_dBm < -140) {
            temp_payload = 16;
          } else if (rsrp_dBm > -44) {
            temp_payload = 113;
2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327
          } else {
            temp_payload = mac->csirs_measurements.rsrp_dBm + 157;
          }

          reverse_n_bits((uint8_t *)&temp_payload, n_bits);

          LOG_D(NR_MAC, "cri_ssbri_bitlen = %d\n", cri_ssbri_bitlen);
          LOG_D(NR_MAC, "rsrp_bitlen = %d\n", rsrp_bitlen);
          LOG_D(NR_MAC, "diff_rsrp_bitlen = %d\n", diff_rsrp_bitlen);

          LOG_D(NR_MAC, "n_bits = %d\n", n_bits);
          LOG_D(NR_MAC, "csi_part1_payload = 0x%x\n", temp_payload);

2328 2329 2330 2331 2332
          break;
        }
      }
    }
  }
2333

2334
  pucch->csi_part1_payload = temp_payload;
2335
  return n_bits;
2336
}
2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364

// returns index from RSRP
// according to Table 10.1.6.1-1 in 38.133

uint8_t get_rsrp_index(int rsrp) {

  int index = rsrp + 157;
  if (rsrp>-44)
    index = 113;
  if (rsrp<-140)
    index = 16;

  return index;
}


// returns index from differential RSRP
// according to Table 10.1.6.1-2 in 38.133
uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp) {

  int diff = best_rsrp-current_rsrp;
  if (diff>30)
    return 15;
  else
    return (diff>>1);

}

cig's avatar
cig committed
2365
void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){
2366

2367
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
2368

cig's avatar
cig committed
2369 2370
  LOG_D(MAC, "In %s [%d.%d] Handling DLSCH PDU...\n", __FUNCTION__, dl_info->frame, dl_info->slot);

2371 2372
  // Processing MAC PDU
  // it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs
cig's avatar
cig committed
2373 2374 2375 2376 2377 2378 2379 2380 2381 2382
  switch (dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type){
    case FAPI_NR_RX_PDU_TYPE_DLSCH:
    nr_ue_process_mac_pdu(dl_info, ul_time_alignment, pdu_id);
    break;
    case FAPI_NR_RX_PDU_TYPE_RAR:
    nr_ue_process_rar(dl_info, ul_time_alignment, pdu_id);
    break;
    default:
    break;
  }
2383

2384
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
2385

2386 2387
}

laurent's avatar
laurent committed
2388
static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac,
2389 2390 2391 2392 2393 2394 2395
                                   uint8_t dci_format,
                                   uint8_t dci_size,
                                   uint16_t rnti,
                                   int ss_type,
                                   uint64_t *dci_pdu,
                                   dci_pdu_rel15_t *dci_pdu_rel15)
{
2396

2397 2398 2399
  int pos = 0;
  int fsize = 0;
  int rnti_type = get_rnti_type(mac, rnti);
2400 2401
  NR_UE_DL_BWP_t *current_DL_BWP = &mac->current_DL_BWP;
  NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP;
2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412
  int N_RB;
  if(current_DL_BWP)
    N_RB = get_rb_bwp_dci(dci_format,
                          ss_type,
                          mac->type0_PDCCH_CSS_config.num_rbs,
                          current_UL_BWP->BWPSize,
                          current_DL_BWP->BWPSize,
                          current_UL_BWP->initial_BWPSize,
                          current_DL_BWP->initial_BWPSize);
  else
    N_RB = mac->type0_PDCCH_CSS_config.num_rbs;
2413
  LOG_D(MAC,"nr_extract_dci_info : dci_pdu %lx, size %d\n",*dci_pdu,dci_size);
2414 2415 2416 2417 2418 2419
  switch(dci_format) {

  case NR_DL_DCI_FORMAT_1_0:
    switch(rnti_type) {
    case NR_RNTI_RA:
      // Freq domain assignment
2420
      fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
2421
      pos=fsize;
2422
      dci_pdu_rel15->frequency_domain_assignment.val = *dci_pdu>>(dci_size-pos)&((1<<fsize)-1);
2423
#ifdef DEBUG_EXTRACT_DCI
2424
      LOG_D(MAC,"frequency-domain assignment %d (%d bits) N_RB_BWP %d=> %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,N_RB,dci_size-pos,*dci_pdu);
2425 2426 2427
#endif
      // Time domain assignment
      pos+=4;
2428
      dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu >> (dci_size-pos))&0xf;
2429
#ifdef DEBUG_EXTRACT_DCI
2430
      LOG_D(MAC,"time-domain assignment %d  (4 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu);
2431 2432 2433 2434
#endif
      // VRB to PRB mapping
	
      pos++;
2435
      dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&0x1;
2436
#ifdef DEBUG_EXTRACT_DCI
2437
      LOG_D(MAC,"vrb to prb mapping %d  (1 bits)=> %d (0x%lx)\n",dci_pdu_rel15->vrb_to_prb_mapping.val,dci_size-pos,*dci_pdu);
2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451
#endif
      // MCS
      pos+=5;
      dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f;
#ifdef DEBUG_EXTRACT_DCI
      LOG_D(MAC,"mcs %d  (5 bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,dci_size-pos,*dci_pdu);
#endif
      // TB scaling
      pos+=2;
      dci_pdu_rel15->tb_scaling = (*dci_pdu>>(dci_size-pos))&0x3;
#ifdef DEBUG_EXTRACT_DCI
      LOG_D(MAC,"tb_scaling %d  (2 bits)=> %d (0x%lx)\n",dci_pdu_rel15->tb_scaling,dci_size-pos,*dci_pdu);
#endif
      break;
cig's avatar
cig committed
2452

2453
    case NR_RNTI_C:
2454 2455 2456 2457

      //Identifier for DCI formats
      pos++;
      dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1;
2458 2459

      //switch to DCI_0_0
francescomani's avatar
francescomani committed
2460
      if (dci_pdu_rel15->format_indicator == 0) {
2461
        dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0];
2462
        return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15);
francescomani's avatar
francescomani committed
2463
      }
2464 2465 2466
#ifdef DEBUG_EXTRACT_DCI
      LOG_D(MAC,"Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,N_RB,dci_size-pos,*dci_pdu);
#endif
2467

2468 2469
     // Freq domain assignment (275rb >> fsize = 16)
      fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
2470
      pos+=fsize;
2471
      dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<<fsize)-1);
2472 2473
  	
#ifdef DEBUG_EXTRACT_DCI
2474
      LOG_D(MAC,"Freq domain assignment %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,dci_size-pos,*dci_pdu);
2475 2476 2477 2478
#endif
    	
      uint16_t is_ra = 1;
      for (int i=0; i<fsize; i++)
2479
	if (!((dci_pdu_rel15->frequency_domain_assignment.val>>i)&1)) {
2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490
	  is_ra = 0;
	  break;
	}
      if (is_ra) //fsize are all 1  38.212 p86
	{
	  // ra_preamble_index 6 bits
	  pos+=6;
	  dci_pdu_rel15->ra_preamble_index = (*dci_pdu>>(dci_size-pos))&0x3f;
	    
	  // UL/SUL indicator  1 bit
	  pos++;
2491
	  dci_pdu_rel15->ul_sul_indicator.val = (*dci_pdu>>(dci_size-pos))&1;
2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
	    
	  // SS/PBCH index  6 bits
	  pos+=6;
	  dci_pdu_rel15->ss_pbch_index = (*dci_pdu>>(dci_size-pos))&0x3f;
	    
	  //  prach_mask_index  4 bits
	  pos+=4;
	  dci_pdu_rel15->prach_mask_index = (*dci_pdu>>(dci_size-pos))&0xf;
	    
	}  //end if
      else {
	  
	// Time domain assignment 4bit
		  
	pos+=4;
2507
	dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf;
2508
#ifdef DEBUG_EXTRACT_DCI
2509
	LOG_D(MAC,"Time domain assignment %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,4,dci_size-pos,*dci_pdu);
2510 2511 2512 2513
#endif
	  
	// VRB to PRB mapping  1bit
	pos++;
2514
	dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&1;
2515
#ifdef DEBUG_EXTRACT_DCI
2516
	LOG_D(MAC,"VRB to PRB %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->vrb_to_prb_mapping.val,1,dci_size-pos,*dci_pdu);
2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541
#endif
	
	// MCS 5bit  //bit over 32, so dci_pdu ++
	pos+=5;
	dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f;
#ifdef DEBUG_EXTRACT_DCI
	LOG_D(MAC,"MCS %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,5,dci_size-pos,*dci_pdu);
#endif
	  
	// New data indicator 1bit
	pos++;
	dci_pdu_rel15->ndi = (*dci_pdu>>(dci_size-pos))&1;
#ifdef DEBUG_EXTRACT_DCI
	LOG_D(MAC,"NDI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->ndi,1,dci_size-pos,*dci_pdu);
#endif      
	  
	// Redundancy version  2bit
	pos+=2;
	dci_pdu_rel15->rv = (*dci_pdu>>(dci_size-pos))&0x3;
#ifdef DEBUG_EXTRACT_DCI
	LOG_D(MAC,"RV %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->rv,2,dci_size-pos,*dci_pdu);
#endif
	  
	// HARQ process number  4bit
	pos+=4;
2542
	dci_pdu_rel15->harq_pid  = (*dci_pdu>>(dci_size-pos))&0xf;
2543
#ifdef DEBUG_EXTRACT_DCI
2544
	LOG_D(MAC,"HARQ_PID %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->harq_pid,4,dci_size-pos,*dci_pdu);
2545 2546 2547 2548
#endif
	  
	// Downlink assignment index  2bit
	pos+=2;
2549
	dci_pdu_rel15->dai[0].val = (*dci_pdu>>(dci_size-pos))&3;
2550
#ifdef DEBUG_EXTRACT_DCI
2551
	LOG_D(MAC,"DAI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->dai[0].val,2,dci_size-pos,*dci_pdu);
2552 2553 2554 2555
#endif
	  
	// TPC command for scheduled PUCCH  2bit
	pos+=2;
2556
	dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&3;
2557
#ifdef DEBUG_EXTRACT_DCI
2558
	LOG_D(MAC,"TPC %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->tpc,2,dci_size-pos,*dci_pdu);
2559 2560 2561 2562
#endif
	  
	// PUCCH resource indicator  3bit
	pos+=3;
2563
	dci_pdu_rel15->pucch_resource_indicator = (*dci_pdu>>(dci_size-pos))&0x7;
2564
#ifdef DEBUG_EXTRACT_DCI
2565
	LOG_D(MAC,"PUCCH RI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->pucch_resource_indicator,3,dci_size-pos,*dci_pdu);
2566 2567 2568 2569
#endif
	  
	// PDSCH-to-HARQ_feedback timing indicator 3bit
	pos+=3;
2570
	dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val = (*dci_pdu>>(dci_size-pos))&0x7;
2571
#ifdef DEBUG_EXTRACT_DCI
2572
	LOG_D(MAC,"PDSCH to HARQ TI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val,3,dci_size-pos,*dci_pdu);
2573 2574 2575 2576
#endif
	  
      } //end else
      break;
2577

2578 2579
    case NR_RNTI_P:
      /*
yaojie's avatar
yaojie committed
2580
      // Short Messages Indicator  E2 bits
2581 2582
      for (int i=0; i<2; i++)
      dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages_indicator>>(1-i))&1)<<(dci_size-pos++);
yaojie's avatar
yaojie committed
2583
      // Short Messages  E8 bits
2584 2585 2586 2587 2588 2589 2590 2591 2592 2593
      for (int i=0; i<8; i++)
      *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages>>(7-i))&1)<<(dci_size-pos++);
      // Freq domain assignment 0-16 bit
      fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) );
      for (int i=0; i<fsize; i++)
      *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment>>(fsize-i-1))&1)<<(dci_size-pos++);
      // Time domain assignment 4 bit
      for (int i=0; i<4; i++)
      *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_size-pos++);
      // VRB to PRB mapping 1 bit
2594
      *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++);
2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606
      // MCS 5 bit
      for (int i=0; i<5; i++)
      *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++);
	
      // TB scaling 2 bit
      for (int i=0; i<2; i++)
      *dci_pdu |= (((uint64_t)dci_pdu_rel15->tb_scaling>>(1-i))&1)<<(dci_size-pos++);
      */	
	
      break;
  	
    case NR_RNTI_SI:
2607
      // Freq domain assignment 0-16 bit
2608
      fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
2609 2610
      pos+=fsize;
      dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<<fsize)-1);
2611

2612 2613 2614
      // Time domain assignment 4 bit
      pos+=4;
      dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf;
2615

2616 2617 2618
      // VRB to PRB mapping 1 bit
      pos++;
      dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&0x1;
2619

2620 2621 2622
      // MCS 5bit  //bit over 32, so dci_pdu ++
      pos+=5;
      dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f;
2623

2624 2625 2626
      // Redundancy version  2 bit
      pos+=2;
      dci_pdu_rel15->rv = (*dci_pdu>>(dci_size-pos))&3;
2627

2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640
      // System information indicator 1 bit
      pos++;
      dci_pdu_rel15->system_info_indicator = (*dci_pdu>>(dci_size-pos))&0x1;

      LOG_D(MAC,"N_RB = %i\n", N_RB);
      LOG_D(MAC,"dci_size = %i\n", dci_size);
      LOG_D(MAC,"fsize = %i\n", fsize);
      LOG_D(MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val);
      LOG_D(MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val);
      LOG_D(MAC,"dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val);
      LOG_D(MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs);
      LOG_D(MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv);
      LOG_D(MAC,"dci_pdu_rel15->system_info_indicator = %i\n", dci_pdu_rel15->system_info_indicator);
2641

2642 2643 2644
      break;
	
    case NR_RNTI_TC:
2645

2646 2647
      // indicating a DL DCI format 1bit
      pos++;
2648
      dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1;
2649

francescomani's avatar
francescomani committed
2650
      //switch to DCI_0_0
francescomani's avatar
francescomani committed
2651
      if (dci_pdu_rel15->format_indicator == 0) {
2652
        dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0];
2653
        return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15);
francescomani's avatar
francescomani committed
2654
      }
francescomani's avatar
francescomani committed
2655

2656 2657
      if (dci_pdu_rel15->format_indicator == 0)
        return 1; // discard dci, format indicator not corresponding to dci_format
2658 2659

        // Freq domain assignment 0-16 bit
2660
      fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
2661
      pos+=fsize;
2662
      dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<<fsize)-1);
2663 2664

      // Time domain assignment - 4 bits
2665
      pos+=4;
2666
      dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf;
2667 2668 2669

      // VRB to PRB mapping - 1 bit
      pos++;
2670
      dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&1;
2671

2672 2673 2674
      // MCS 5bit  //bit over 32, so dci_pdu ++
      pos+=5;
      dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f;
2675 2676 2677

      // New data indicator - 1 bit
      pos++;
2678
      dci_pdu_rel15->ndi = (*dci_pdu>>(dci_size-pos))&1;
2679 2680

      // Redundancy version - 2 bits
2681 2682
      pos+=2;
      dci_pdu_rel15->rv = (*dci_pdu>>(dci_size-pos))&3;
2683 2684

      // HARQ process number - 4 bits
2685
      pos+=4;
2686
      dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf;
2687 2688

      // Downlink assignment index - 2 bits
2689
      pos+=2;
2690
      dci_pdu_rel15->dai[0].val = (*dci_pdu>>(dci_size-pos))&3;
2691 2692

      // TPC command for scheduled PUCCH - 2 bits
2693
      pos+=2;
2694
      dci_pdu_rel15->tpc  = (*dci_pdu>>(dci_size-pos))&3;
2695 2696 2697 2698 2699 2700

      // PUCCH resource indicator - 3 bits
      pos+=3;
      dci_pdu_rel15->pucch_resource_indicator = (*dci_pdu>>(dci_size-pos))&7;

      // PDSCH-to-HARQ_feedback timing indicator - 3 bits
2701
      pos+=3;
2702
      dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val = (*dci_pdu>>(dci_size-pos))&7;
2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718

      LOG_D(NR_MAC,"N_RB = %i\n", N_RB);
      LOG_D(NR_MAC,"dci_size = %i\n", dci_size);
      LOG_D(NR_MAC,"fsize = %i\n", fsize);
      LOG_D(NR_MAC,"dci_pdu_rel15->format_indicator = %i\n", dci_pdu_rel15->format_indicator);
      LOG_D(NR_MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val);
      LOG_D(NR_MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val);
      LOG_D(NR_MAC,"dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val);
      LOG_D(NR_MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs);
      LOG_D(NR_MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv);
      LOG_D(NR_MAC,"dci_pdu_rel15->harq_pid = %i\n", dci_pdu_rel15->harq_pid);
      LOG_D(NR_MAC,"dci_pdu_rel15->dai[0].val = %i\n", dci_pdu_rel15->dai[0].val);
      LOG_D(NR_MAC,"dci_pdu_rel15->tpc = %i\n", dci_pdu_rel15->tpc);
      LOG_D(NR_MAC,"dci_pdu_rel15->pucch_resource_indicator = %i\n", dci_pdu_rel15->pucch_resource_indicator);
      LOG_D(NR_MAC,"dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val = %i\n", dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val);

2719 2720 2721 2722 2723 2724 2725 2726
      break;
    }
    break;
  
  case NR_UL_DCI_FORMAT_0_0:
    switch(rnti_type)
      {
      case NR_RNTI_C:
2727 2728 2729
        //Identifier for DCI formats
        pos++;
        dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1;
2730 2731 2732
#ifdef DEBUG_EXTRACT_DCI
	LOG_D(MAC,"Format indicator %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,dci_size-pos,*dci_pdu);
#endif
2733 2734
        if (dci_pdu_rel15->format_indicator == 1)
          return 1; // discard dci, format indicator not corresponding to dci_format
2735
	fsize = dci_pdu_rel15->frequency_domain_assignment.nbits;
2736
	pos+=fsize;
2737
	dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<<fsize)-1);
2738 2739 2740
#ifdef DEBUG_EXTRACT_DCI
	LOG_D(MAC,"Freq domain assignment %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,dci_size-pos,*dci_pdu);
#endif
2741 2742
	// Time domain assignment 4bit
	pos+=4;
2743
	dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf;
2744 2745 2746
#ifdef DEBUG_EXTRACT_DCI
      LOG_D(MAC,"time-domain assignment %d  (4 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu);
#endif
yaojie's avatar
yaojie committed
2747
	// Frequency hopping flag  E1 bit
2748
	pos++;
2749
	dci_pdu_rel15->frequency_hopping_flag.val= (*dci_pdu>>(dci_size-pos))&1;
2750 2751 2752
#ifdef DEBUG_EXTRACT_DCI
      LOG_D(MAC,"frequency_hopping %d  (1 bit)=> %d (0x%lx)\n",dci_pdu_rel15->frequency_hopping_flag.val,dci_size-pos,*dci_pdu);
#endif
2753 2754 2755
	// MCS  5 bit
	pos+=5;
	dci_pdu_rel15->mcs= (*dci_pdu>>(dci_size-pos))&0x1f;
2756 2757 2758
#ifdef DEBUG_EXTRACT_DCI
      LOG_D(MAC,"mcs %d  (5 bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,dci_size-pos,*dci_pdu);
#endif
2759 2760 2761
	// New data indicator 1bit
	pos++;
	dci_pdu_rel15->ndi= (*dci_pdu>>(dci_size-pos))&1;
2762 2763 2764
#ifdef DEBUG_EXTRACT_DCI
	LOG_D(MAC,"NDI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->ndi,1,dci_size-pos,*dci_pdu);
#endif
2765 2766 2767
	// Redundancy version  2bit
	pos+=2;
	dci_pdu_rel15->rv= (*dci_pdu>>(dci_size-pos))&3;
2768 2769 2770
#ifdef DEBUG_EXTRACT_DCI
	LOG_D(MAC,"RV %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->rv,2,dci_size-pos,*dci_pdu);
#endif
2771 2772
	// HARQ process number  4bit
	pos+=4;
2773
	dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf;
2774 2775 2776
#ifdef DEBUG_EXTRACT_DCI
	LOG_D(MAC,"HARQ_PID %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->harq_pid,4,dci_size-pos,*dci_pdu);
#endif
yaojie's avatar
yaojie committed
2777
	// TPC command for scheduled PUSCH  E2 bits
2778
	pos+=2;
2779
	dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&3;
2780 2781 2782
#ifdef DEBUG_EXTRACT_DCI
	LOG_D(MAC,"TPC %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->tpc,2,dci_size-pos,*dci_pdu);
#endif
yaojie's avatar
yaojie committed
2783
	// UL/SUL indicator  E1 bit
2784 2785 2786 2787 2788 2789 2790
	/* commented for now (RK): need to get this from BWP descriptor
	   if (cfg->pucch_config.pucch_GroupHopping.value)
	   dci_pdu->= ((uint64_t)*dci_pdu>>(dci_size-pos)ul_sul_indicator&1)<<(dci_size-pos++);
	*/
	break;
	
      case NR_RNTI_TC:
francescomani's avatar
francescomani committed
2791 2792 2793 2794 2795 2796 2797 2798
        //Identifier for DCI formats
        pos++;
        dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1;
#ifdef DEBUG_EXTRACT_DCI
	LOG_I(MAC,"Format indicator %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,dci_size-pos,*dci_pdu);
#endif
        if (dci_pdu_rel15->format_indicator == 1)
          return 1; // discard dci, format indicator not corresponding to dci_format
2799
	fsize = dci_pdu_rel15->frequency_domain_assignment.nbits;
francescomani's avatar
francescomani committed
2800 2801 2802 2803 2804
	pos+=fsize;
	dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<<fsize)-1);
#ifdef DEBUG_EXTRACT_DCI
	LOG_I(MAC,"Freq domain assignment %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,dci_size-pos,*dci_pdu);
#endif
2805
	// Time domain assignment 4bit
francescomani's avatar
francescomani committed
2806 2807 2808 2809 2810
	pos+=4;
	dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf;
#ifdef DEBUG_EXTRACT_DCI
      LOG_I(MAC,"time-domain assignment %d  (4 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu);
#endif
yaojie's avatar
yaojie committed
2811
	// Frequency hopping flag  E1 bit
francescomani's avatar
francescomani committed
2812 2813 2814 2815 2816
	pos++;
	dci_pdu_rel15->frequency_hopping_flag.val= (*dci_pdu>>(dci_size-pos))&1;
#ifdef DEBUG_EXTRACT_DCI
      LOG_I(MAC,"frequency_hopping %d  (1 bit)=> %d (0x%lx)\n",dci_pdu_rel15->frequency_hopping_flag.val,dci_size-pos,*dci_pdu);
#endif
2817
	// MCS  5 bit
francescomani's avatar
francescomani committed
2818 2819 2820 2821 2822
	pos+=5;
	dci_pdu_rel15->mcs= (*dci_pdu>>(dci_size-pos))&0x1f;
#ifdef DEBUG_EXTRACT_DCI
      LOG_I(MAC,"mcs %d  (5 bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,dci_size-pos,*dci_pdu);
#endif
2823
	// New data indicator 1bit
francescomani's avatar
francescomani committed
2824 2825 2826 2827 2828
	pos++;
	dci_pdu_rel15->ndi= (*dci_pdu>>(dci_size-pos))&1;
#ifdef DEBUG_EXTRACT_DCI
	LOG_I(MAC,"NDI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->ndi,1,dci_size-pos,*dci_pdu);
#endif
2829
	// Redundancy version  2bit
francescomani's avatar
francescomani committed
2830 2831 2832 2833 2834
	pos+=2;
	dci_pdu_rel15->rv= (*dci_pdu>>(dci_size-pos))&3;
#ifdef DEBUG_EXTRACT_DCI
	LOG_I(MAC,"RV %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->rv,2,dci_size-pos,*dci_pdu);
#endif
2835
	// HARQ process number  4bit
francescomani's avatar
francescomani committed
2836 2837 2838 2839 2840
	pos+=4;
	dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf;
#ifdef DEBUG_EXTRACT_DCI
	LOG_I(MAC,"HARQ_PID %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->harq_pid,4,dci_size-pos,*dci_pdu);
#endif
yaojie's avatar
yaojie committed
2841
	// TPC command for scheduled PUSCH  E2 bits
francescomani's avatar
francescomani committed
2842 2843 2844 2845 2846
	pos+=2;
	dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&3;
#ifdef DEBUG_EXTRACT_DCI
	LOG_I(MAC,"TPC %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->tpc,2,dci_size-pos,*dci_pdu);
#endif
2847 2848 2849 2850
	break;
	
      }
    break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
2851 2852

  case NR_DL_DCI_FORMAT_1_1:
2853 2854 2855
  switch(rnti_type)
    {
      case NR_RNTI_C:
2856 2857 2858 2859 2860
        //Identifier for DCI formats
        pos++;
        dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1;
        if (dci_pdu_rel15->format_indicator == 0)
          return 1; // discard dci, format indicator not corresponding to dci_format
2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940
        // Carrier indicator
        pos+=dci_pdu_rel15->carrier_indicator.nbits;
        dci_pdu_rel15->carrier_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->carrier_indicator.nbits)-1);
        // BWP Indicator
        pos+=dci_pdu_rel15->bwp_indicator.nbits;
        dci_pdu_rel15->bwp_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->bwp_indicator.nbits)-1);
        // Frequency domain resource assignment
        pos+=dci_pdu_rel15->frequency_domain_assignment.nbits;
        dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->frequency_domain_assignment.nbits)-1);
        // Time domain resource assignment
        pos+=dci_pdu_rel15->time_domain_assignment.nbits;
        dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->time_domain_assignment.nbits)-1);
        // VRB-to-PRB mapping
        pos+=dci_pdu_rel15->vrb_to_prb_mapping.nbits;
        dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->vrb_to_prb_mapping.nbits)-1);
        // PRB bundling size indicator
        pos+=dci_pdu_rel15->prb_bundling_size_indicator.nbits;
        dci_pdu_rel15->prb_bundling_size_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->prb_bundling_size_indicator.nbits)-1);
        // Rate matching indicator
        pos+=dci_pdu_rel15->rate_matching_indicator.nbits;
        dci_pdu_rel15->rate_matching_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->rate_matching_indicator.nbits)-1);
        // ZP CSI-RS trigger
        pos+=dci_pdu_rel15->zp_csi_rs_trigger.nbits;
        dci_pdu_rel15->zp_csi_rs_trigger.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->zp_csi_rs_trigger.nbits)-1);
        //TB1
        // MCS 5bit
        pos+=5;
        dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f;
        // New data indicator 1bit
        pos+=1;
        dci_pdu_rel15->ndi = (*dci_pdu>>(dci_size-pos))&0x1;
        // Redundancy version  2bit
        pos+=2;
        dci_pdu_rel15->rv = (*dci_pdu>>(dci_size-pos))&0x3;
        //TB2
        // MCS 5bit
        pos+=dci_pdu_rel15->mcs2.nbits;
        dci_pdu_rel15->mcs2.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->mcs2.nbits)-1);
        // New data indicator 1bit
        pos+=dci_pdu_rel15->ndi2.nbits;
        dci_pdu_rel15->ndi2.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->ndi2.nbits)-1);
        // Redundancy version  2bit
        pos+=dci_pdu_rel15->rv2.nbits;
        dci_pdu_rel15->rv2.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->rv2.nbits)-1);
        // HARQ process number  4bit
        pos+=4;
        dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf;
        // Downlink assignment index
        pos+=dci_pdu_rel15->dai[0].nbits;
        dci_pdu_rel15->dai[0].val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->dai[0].nbits)-1);
        // TPC command for scheduled PUCCH  2bit
        pos+=2;
        dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&0x3;
        // PUCCH resource indicator  3bit
        pos+=3;
        dci_pdu_rel15->pucch_resource_indicator = (*dci_pdu>>(dci_size-pos))&0x3;
        // PDSCH-to-HARQ_feedback timing indicator
        pos+=dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits;
        dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits)-1);
        // Antenna ports
        pos+=dci_pdu_rel15->antenna_ports.nbits;
        dci_pdu_rel15->antenna_ports.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->antenna_ports.nbits)-1);
        // TCI
        pos+=dci_pdu_rel15->transmission_configuration_indication.nbits;
        dci_pdu_rel15->transmission_configuration_indication.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->transmission_configuration_indication.nbits)-1);
        // SRS request
        pos+=dci_pdu_rel15->srs_request.nbits;
        dci_pdu_rel15->srs_request.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->srs_request.nbits)-1);
        // CBG transmission information
        pos+=dci_pdu_rel15->cbgti.nbits;
        dci_pdu_rel15->cbgti.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->cbgti.nbits)-1);
        // CBG flushing out information
        pos+=dci_pdu_rel15->cbgfi.nbits;
        dci_pdu_rel15->cbgfi.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->cbgfi.nbits)-1);
        // DMRS sequence init
        pos+=1;
        dci_pdu_rel15->dmrs_sequence_initialization.val = (*dci_pdu>>(dci_size-pos))&0x1;
        break;
      }
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
2941

2942 2943 2944 2945
  case NR_UL_DCI_FORMAT_0_1:
    switch(rnti_type)
      {
      case NR_RNTI_C:
2946 2947 2948 2949 2950
        //Identifier for DCI formats
        pos++;
        dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1;
        if (dci_pdu_rel15->format_indicator == 1)
          return 1; // discard dci, format indicator not corresponding to dci_format
2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961
        // Carrier indicator
        pos+=dci_pdu_rel15->carrier_indicator.nbits;
        dci_pdu_rel15->carrier_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->carrier_indicator.nbits)-1);
        
        // UL/SUL Indicator
        pos+=dci_pdu_rel15->ul_sul_indicator.nbits;
        dci_pdu_rel15->ul_sul_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->ul_sul_indicator.nbits)-1);
        
        // BWP Indicator
        pos+=dci_pdu_rel15->bwp_indicator.nbits;
        dci_pdu_rel15->bwp_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->bwp_indicator.nbits)-1);
2962

2963
        // Freq domain assignment  max 16 bit
2964
        fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
2965 2966 2967
        pos+=fsize;
        dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<<fsize)-1);
        
2968
        // Time domain assignment
2969 2970
        //pos+=4;
        pos+=dci_pdu_rel15->time_domain_assignment.nbits;
2971
        dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->time_domain_assignment.nbits)-1);
2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054
        
        // Not supported yet - skip for now
        // Frequency hopping flag – 1 bit 
        //pos++;
        //dci_pdu_rel15->frequency_hopping_flag.val= (*dci_pdu>>(dci_size-pos))&1;

        // MCS  5 bit
        pos+=5;
        dci_pdu_rel15->mcs= (*dci_pdu>>(dci_size-pos))&0x1f;

        // New data indicator 1bit
        pos++;
        dci_pdu_rel15->ndi= (*dci_pdu>>(dci_size-pos))&1;

        // Redundancy version  2bit
        pos+=2;
        dci_pdu_rel15->rv= (*dci_pdu>>(dci_size-pos))&3;

        // HARQ process number  4bit
        pos+=4;
        dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf;

        // 1st Downlink assignment index
        pos+=dci_pdu_rel15->dai[0].nbits;
        dci_pdu_rel15->dai[0].val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->dai[0].nbits)-1);

        // 2nd Downlink assignment index
        pos+=dci_pdu_rel15->dai[1].nbits;
        dci_pdu_rel15->dai[1].val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->dai[1].nbits)-1);

        // TPC command for scheduled PUSCH – 2 bits
        pos+=2;
        dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&3;

        // SRS resource indicator
        pos+=dci_pdu_rel15->srs_resource_indicator.nbits;
        dci_pdu_rel15->srs_resource_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->srs_resource_indicator.nbits)-1);

        // Precoding info and n. of layers
        pos+=dci_pdu_rel15->precoding_information.nbits;
        dci_pdu_rel15->precoding_information.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->precoding_information.nbits)-1);

        // Antenna ports
        pos+=dci_pdu_rel15->antenna_ports.nbits;
        dci_pdu_rel15->antenna_ports.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->antenna_ports.nbits)-1);

        // SRS request
        pos+=dci_pdu_rel15->srs_request.nbits;
        dci_pdu_rel15->srs_request.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->srs_request.nbits)-1);

        // CSI request
        pos+=dci_pdu_rel15->csi_request.nbits;
        dci_pdu_rel15->csi_request.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->csi_request.nbits)-1);

        // CBG transmission information
        pos+=dci_pdu_rel15->cbgti.nbits;
        dci_pdu_rel15->cbgti.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->cbgti.nbits)-1);

        // PTRS DMRS association
        pos+=dci_pdu_rel15->ptrs_dmrs_association.nbits;
        dci_pdu_rel15->ptrs_dmrs_association.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->ptrs_dmrs_association.nbits)-1);

        // Beta offset indicator
        pos+=dci_pdu_rel15->beta_offset_indicator.nbits;
        dci_pdu_rel15->beta_offset_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->beta_offset_indicator.nbits)-1);

        // DMRS sequence initialization
        pos+=dci_pdu_rel15->dmrs_sequence_initialization.nbits;
        dci_pdu_rel15->dmrs_sequence_initialization.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->dmrs_sequence_initialization.nbits)-1);

        // UL-SCH indicator
        pos+=1;
        dci_pdu_rel15->ulsch_indicator = (*dci_pdu>>(dci_size-pos))&0x1;

        // UL/SUL indicator – 1 bit
        /* commented for now (RK): need to get this from BWP descriptor
          if (cfg->pucch_config.pucch_GroupHopping.value)
          dci_pdu->= ((uint64_t)*dci_pdu>>(dci_size-pos)ul_sul_indicator&1)<<(dci_size-pos++);
        */
        break;
      }
    break;
       }
3055
    
3056
    return 0;
3057
}
3058

cig's avatar
cig committed
3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096
///////////////////////////////////
// brief:     nr_ue_process_mac_pdu
// function:  parsing DL PDU header
///////////////////////////////////
//  Header for DLSCH:
//  Except:
//   - DL-SCH: fixed-size MAC CE(known by LCID)
//   - DL-SCH: padding
//
//  |0|1|2|3|4|5|6|7|  bit-wise
//  |R|F|   LCID    |
//  |       L       |
//  |0|1|2|3|4|5|6|7|  bit-wise
//  |R|F|   LCID    |
//  |       L       |
//  |       L       |
////////////////////////////////
//  Header for DLSCH:
//   - DLSCH: fixed-size MAC CE(known by LCID)
//   - DLSCH: padding, for single/multiple 1-oct padding CE(s)
//
//  |0|1|2|3|4|5|6|7|  bit-wise
//  |R|R|   LCID    |
//  LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described
//         in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits;
//  L:    The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders
//         corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field;
//  F:    lenght of L is 0:8 or 1:16 bits wide
//  R:    Reserved bit, set to zero.
////////////////////////////////
void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
                           NR_UL_TIME_ALIGNMENT_t *ul_time_alignment,
                           int pdu_id){

  module_id_t module_idP = dl_info->module_id;
  frame_t frameP         = dl_info->frame;
  int slot               = dl_info->slot;
  uint8_t *pduP          = (dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu;
mjoang's avatar
mjoang committed
3097
  int32_t pdu_len        = (int32_t)(dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu_length;
cig's avatar
cig committed
3098 3099 3100 3101
  uint8_t gNB_index      = dl_info->gNB_index;
  uint8_t CC_id          = dl_info->cc_id;
  uint8_t done           = 0;
  NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
3102
  RA_config_t *ra = &mac->ra;
cig's avatar
cig committed
3103 3104 3105 3106 3107

  if (!pduP){
    return;
  }

3108
  LOG_D(MAC, "In %s [%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n", __FUNCTION__, frameP, slot, pdu_id, pdu_len, dl_info->rx_ind->number_pdus);
3109

francescomani's avatar
francescomani committed
3110
  while (!done && pdu_len > 0){
3111 3112 3113
    uint16_t mac_len = 0x0000;
    uint16_t mac_subheader_len = 0x0001; //  default to fixed-length subheader = 1-oct
    uint8_t rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID;
francescomani's avatar
francescomani committed
3114 3115

    LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", rx_lcid, pdu_len);
Laurent THOMAS's avatar
Laurent THOMAS committed
3116
    bool ret;
francescomani's avatar
francescomani committed
3117 3118 3119 3120 3121
    switch(rx_lcid){
      //  MAC CE
      case DL_SCH_LCID_CCCH:
        //  MSG4 RRC Setup 38.331
        //  variable length
Laurent THOMAS's avatar
Laurent THOMAS committed
3122 3123
        ret=get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len);
        AssertFatal(ret, "The mac_len (%d) has an invalid size. PDU len = %d! \n",
3124
                    mac_len, pdu_len);
3125

francescomani's avatar
francescomani committed
3126 3127
        // Check if it is a valid CCCH message, we get all 00's messages very often
        int i = 0;
3128
        for(i=0; i<(mac_subheader_len+mac_len); i++) {
francescomani's avatar
francescomani committed
3129 3130 3131 3132
          if(pduP[i] != 0) {
            break;
          }
        }
3133
        if (i == (mac_subheader_len+mac_len)) {
francescomani's avatar
francescomani committed
3134 3135 3136 3137
          LOG_D(NR_MAC, "%s() Invalid CCCH message!, pdu_len: %d\n", __func__, pdu_len);
          done = 1;
          break;
        }
3138

3139 3140
        if ( mac_len > 0 ) {
          LOG_D(NR_MAC,"DL_SCH_LCID_CCCH (e.g. RRCSetup) with payload len %d\n", mac_len);
francescomani's avatar
francescomani committed
3141 3142 3143
          for (int i = 0; i < mac_subheader_len; i++) {
            LOG_D(NR_MAC, "MAC header %d: 0x%x\n", i, pduP[i]);
          }
3144
          for (int i = 0; i < mac_len; i++) {
francescomani's avatar
francescomani committed
3145 3146
            LOG_D(NR_MAC, "%d: 0x%x\n", i, pduP[mac_subheader_len + i]);
          }
3147
          nr_mac_rrc_data_ind_ue(module_idP, CC_id, gNB_index, frameP, 0, mac->crnti, CCCH, pduP+mac_subheader_len, mac_len);
francescomani's avatar
francescomani committed
3148 3149 3150 3151 3152 3153
        }
        break;
      case DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH:
      case DL_SCH_LCID_APERIODIC_CSI_TRI_STATE_SUBSEL:
      case DL_SCH_LCID_SP_CSI_RS_CSI_IM_RES_SET_ACT:
      case DL_SCH_LCID_SP_SRS_ACTIVATION:
3154 3155

        //  38.321 Ch6.1.3.14
francescomani's avatar
francescomani committed
3156
        //  varialbe length
Laurent THOMAS's avatar
Laurent THOMAS committed
3157
        get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len);
francescomani's avatar
francescomani committed
3158
        break;
3159

francescomani's avatar
francescomani committed
3160 3161
      case DL_SCH_LCID_RECOMMENDED_BITRATE:
        //  38.321 Ch6.1.3.20
3162
        mac_len = 2;
francescomani's avatar
francescomani committed
3163 3164 3165
        break;
      case DL_SCH_LCID_SP_ZP_CSI_RS_RES_SET_ACT:
        //  38.321 Ch6.1.3.19
3166
        mac_len = 2;
francescomani's avatar
francescomani committed
3167 3168 3169
        break;
      case DL_SCH_LCID_PUCCH_SPATIAL_RELATION_ACT:
        //  38.321 Ch6.1.3.18
3170
        mac_len = 3;
francescomani's avatar
francescomani committed
3171 3172 3173
        break;
      case DL_SCH_LCID_SP_CSI_REP_PUCCH_ACT:
        //  38.321 Ch6.1.3.16
3174
        mac_len = 2;
francescomani's avatar
francescomani committed
3175 3176 3177
        break;
      case DL_SCH_LCID_TCI_STATE_IND_UE_SPEC_PDCCH:
        //  38.321 Ch6.1.3.15
3178
        mac_len = 2;
francescomani's avatar
francescomani committed
3179 3180 3181
        break;
      case DL_SCH_LCID_DUPLICATION_ACT:
        //  38.321 Ch6.1.3.11
3182
        mac_len = 1;
francescomani's avatar
francescomani committed
3183 3184 3185
        break;
      case DL_SCH_LCID_SCell_ACT_4_OCT:
        //  38.321 Ch6.1.3.10
3186
        mac_len = 4;
francescomani's avatar
francescomani committed
3187 3188 3189
        break;
      case DL_SCH_LCID_SCell_ACT_1_OCT:
        //  38.321 Ch6.1.3.10
3190
        mac_len = 1;
francescomani's avatar
francescomani committed
3191 3192 3193 3194
        break;
      case DL_SCH_LCID_L_DRX:
        //  38.321 Ch6.1.3.6
        //  fixed length but not yet specify.
3195
        mac_len = 0;
francescomani's avatar
francescomani committed
3196 3197 3198 3199
        break;
      case DL_SCH_LCID_DRX:
        //  38.321 Ch6.1.3.5
        //  fixed length but not yet specify.
3200
        mac_len = 0;
francescomani's avatar
francescomani committed
3201 3202 3203
        break;
      case DL_SCH_LCID_TA_COMMAND:
        //  38.321 Ch6.1.3.4
3204
        mac_len = 1;
3205

francescomani's avatar
francescomani committed
3206 3207
        /*uint8_t ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND;
          uint8_t tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID;*/
3208

Arash Sahbafard's avatar
Arash Sahbafard committed
3209 3210
        const int ta = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND;
        const int tag = ((NR_MAC_CE_TA *)pduP)[1].TAGID;
francescomani's avatar
francescomani committed
3211
        ul_time_alignment->apply_ta = 1;
Arash Sahbafard's avatar
Arash Sahbafard committed
3212 3213 3214
        ul_time_alignment->ta_command = ta; //here
        ul_time_alignment->ta_total += ta - 31;
        ul_time_alignment->tag_id = tag;
3215

francescomani's avatar
francescomani committed
3216 3217 3218 3219 3220 3221
        /*
        #ifdef DEBUG_HEADER_PARSING
        LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pduP[1]);
        #endif
        */

3222 3223 3224 3225
        if (ta == 31)
          LOG_D(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d TA total %d\n", frameP, slot, ta, tag, CC_id, ul_time_alignment->ta_total);
        else
          LOG_I(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d TA total %d\n", frameP, slot, ta, tag, CC_id, ul_time_alignment->ta_total);
francescomani's avatar
francescomani committed
3226 3227 3228 3229 3230 3231

        break;
      case DL_SCH_LCID_CON_RES_ID:
        //  Clause 5.1.5 and 6.1.3.3 of 3GPP TS 38.321 version 16.2.1 Release 16
        // MAC Header: 1 byte (R/R/LCID)
        // MAC SDU: 6 bytes (UE Contention Resolution Identity)
3232
        mac_len = 6;
francescomani's avatar
francescomani committed
3233 3234 3235 3236 3237 3238

        if(ra->ra_state == WAIT_CONTENTION_RESOLUTION) {
          LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n",
                module_idP, frameP, pduP[1], pduP[2], pduP[3], pduP[4], pduP[5], pduP[6]);

          bool ra_success = true;
3239
          for(int i = 0; i<mac_len; i++) {
francescomani's avatar
francescomani committed
3240 3241
            if(ra->cont_res_id[i] != pduP[i+1]) {
              ra_success = false;
rmagueta's avatar
rmagueta committed
3242
              break;
francescomani's avatar
francescomani committed
3243 3244
            }
          }
3245

francescomani's avatar
francescomani committed
3246 3247 3248 3249 3250 3251 3252 3253
          if ( (ra->RA_active == 1) && ra_success) {
            nr_ra_succeeded(module_idP, frameP, slot);
          } else if (!ra_success){
            // TODO: Handle failure of RA procedure @ MAC layer
            //  nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure
            ra->ra_state = RA_UE_IDLE;
            ra->RA_active = 0;
          }
3254
        }
francescomani's avatar
francescomani committed
3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265
        break;
      case DL_SCH_LCID_PADDING:
        done = 1;
        //  end of MAC PDU, can ignore the rest.
        break;
        //  MAC SDU
      case DL_SCH_LCID_DCCH:
        //  check if LCID is valid at current time.
      case DL_SCH_LCID_DCCH1:
        //  check if LCID is valid at current time.
      default:
3266
            {
Laurent THOMAS's avatar
Laurent THOMAS committed
3267 3268
	      if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len))
		    return;
Robert Schmidt's avatar
Robert Schmidt committed
3269
                LOG_D(NR_MAC, "[UE %d] %4d.%2d : DLSCH -> DL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, slot, rx_lcid, gNB_index, mac_len);
3270 3271 3272 3273 3274

                #if defined(ENABLE_MAC_PAYLOAD_DEBUG)
                    LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP);

                    for (i = 0; i < 32; i++)
cig's avatar
cig committed
3275
                      LOG_T(MAC, "%x.", (pduP + mac_subheader_len)[i]);
3276 3277 3278 3279

                    LOG_T(MAC, "\n");
                #endif

3280 3281 3282 3283 3284 3285 3286 3287 3288 3289
                if (rx_lcid < NB_RB_MAX && rx_lcid >= DL_SCH_LCID_DCCH) {

                mac_rlc_data_ind(module_idP,
                                mac->crnti,
                                gNB_index,
                                frameP,
                                ENB_FLAG_NO,
                                MBMS_FLAG_NO,
                                rx_lcid,
                                (char *) (pduP + mac_subheader_len),
3290
                                mac_len,
3291 3292 3293 3294
                                1,
                                NULL);
                } else {
                  LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (gNB %d)\n", module_idP, frameP, rx_lcid, gNB_index);
3295
                }
francescomani's avatar
francescomani committed
3296 3297


3298
            break;
3299
            }
francescomani's avatar
francescomani committed
3300
      }
3301 3302
      pduP += ( mac_subheader_len + mac_len );
      pdu_len -= ( mac_subheader_len + mac_len );
francescomani's avatar
francescomani committed
3303 3304
      if (pdu_len < 0)
        LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", module_idP, frameP, slot, pdu_len);
3305 3306
    }
}
cig's avatar
cig committed
3307

cig's avatar
cig committed
3308 3309
/**
 * Function:      generating MAC CEs (MAC CE and subheader) for the ULSCH PDU
cig's avatar
cig committed
3310 3311
 * Notes:         TODO: PHR and BSR reporting
 * Parameters:
cig's avatar
cig committed
3312
 * @mac_ce        pointer to the MAC sub-PDUs including the MAC CEs
cig's avatar
cig committed
3313 3314
 * @mac           pointer to the MAC instance
 * Return:        number of written bytes
cig's avatar
cig committed
3315
 */
cig's avatar
cig committed
3316
int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
mjoang's avatar
mjoang committed
3317 3318
                          NR_UE_MAC_INST_t *mac,
                          uint8_t power_headroom,  // todo: NR_POWER_HEADROOM_CMD *power_headroom,
3319
                          uint16_t *crnti,
mjoang's avatar
mjoang committed
3320 3321 3322
                          NR_BSR_SHORT *truncated_bsr,
                          NR_BSR_SHORT *short_bsr,
                          NR_BSR_LONG  *long_bsr) {
cig's avatar
cig committed
3323

cig's avatar
cig committed
3324 3325
  int      mac_ce_len = 0;
  uint8_t mac_ce_size = 0;
mjoang's avatar
mjoang committed
3326
  uint8_t *pdu = mac_ce;
mjoang's avatar
mjoang committed
3327
  if (power_headroom) {
cig's avatar
cig committed
3328

cig's avatar
cig committed
3329 3330 3331 3332
    // MAC CE fixed subheader
    ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0;
    ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_SINGLE_ENTRY_PHR;
    mac_ce++;
cig's avatar
cig committed
3333

cig's avatar
cig committed
3334
    // PHR MAC CE (1 octet)
mjoang's avatar
mjoang committed
3335
    ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->PH = power_headroom;
cig's avatar
cig committed
3336
    ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->R1 = 0;
mjoang's avatar
mjoang committed
3337
    ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->PCMAX = 0; // todo
cig's avatar
cig committed
3338
    ((NR_SINGLE_ENTRY_PHR_MAC_CE *) mac_ce)->R2 = 0;
cig's avatar
cig committed
3339

cig's avatar
cig committed
3340 3341 3342 3343
    // update pointer and length
    mac_ce_size = sizeof(NR_SINGLE_ENTRY_PHR_MAC_CE);
    mac_ce += mac_ce_size;
    mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
mjoang's avatar
mjoang committed
3344
    LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : power_headroom pdu %p mac_ce %p b\n",
3345
          pdu, mac_ce);
cig's avatar
cig committed
3346
  }
cig's avatar
cig committed
3347

mjoang's avatar
mjoang committed
3348
  if (crnti && (!get_softmodem_params()->sa && get_softmodem_params()->do_ra && mac->ra.ra_state != RA_SUCCEEDED)) {
cig's avatar
cig committed
3349

mjoang's avatar
mjoang committed
3350
    LOG_D(NR_MAC, "In %s: generating C-RNTI MAC CE with C-RNTI %x\n", __FUNCTION__, (*crnti));
cig's avatar
cig committed
3351

cig's avatar
cig committed
3352 3353 3354 3355
    // MAC CE fixed subheader
    ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0;
    ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_C_RNTI;
    mac_ce++;
cig's avatar
cig committed
3356

cig's avatar
cig committed
3357
    // C-RNTI MAC CE (2 octets)
mjoang's avatar
mjoang committed
3358
    *(uint16_t *) mac_ce = (*crnti);
cig's avatar
cig committed
3359

cig's avatar
cig committed
3360 3361 3362 3363
    // update pointer and length
    mac_ce_size = sizeof(uint16_t);
    mac_ce += mac_ce_size;
    mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
cig's avatar
cig committed
3364 3365 3366

  }

mjoang's avatar
mjoang committed
3367
  if (truncated_bsr) {
cig's avatar
cig committed
3368

3369
	// MAC CE fixed subheader
cig's avatar
cig committed
3370 3371 3372
    ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0;
    ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_S_TRUNCATED_BSR;
    mac_ce++;
cig's avatar
cig committed
3373 3374

    // Short truncated BSR MAC CE (1 octet)
mjoang's avatar
mjoang committed
3375 3376
    ((NR_BSR_SHORT_TRUNCATED *) mac_ce)-> Buffer_size = truncated_bsr->Buffer_size;
    ((NR_BSR_SHORT_TRUNCATED *) mac_ce)-> LcgID = truncated_bsr->LcgID;;
cig's avatar
cig committed
3377 3378 3379 3380 3381

    // update pointer and length
    mac_ce_size = sizeof(NR_BSR_SHORT_TRUNCATED);
    mac_ce += mac_ce_size;
    mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
mjoang's avatar
mjoang committed
3382
    LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : truncated_bsr Buffer_size %d LcgID %d pdu %p mac_ce %p\n",
3383
          truncated_bsr->Buffer_size, truncated_bsr->LcgID, pdu, mac_ce);
cig's avatar
cig committed
3384

mjoang's avatar
mjoang committed
3385
  } else if (short_bsr) {
cig's avatar
cig committed
3386

3387
	// MAC CE fixed subheader
cig's avatar
cig committed
3388 3389 3390
    ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->R = 0;
    ((NR_MAC_SUBHEADER_FIXED *) mac_ce)->LCID = UL_SCH_LCID_S_BSR;
    mac_ce++;
cig's avatar
cig committed
3391 3392

    // Short truncated BSR MAC CE (1 octet)
mjoang's avatar
mjoang committed
3393 3394
    ((NR_BSR_SHORT *) mac_ce)->Buffer_size = short_bsr->Buffer_size;
    ((NR_BSR_SHORT *) mac_ce)->LcgID = short_bsr->LcgID;
cig's avatar
cig committed
3395 3396 3397 3398 3399

    // update pointer and length
    mac_ce_size = sizeof(NR_BSR_SHORT);
    mac_ce += mac_ce_size;
    mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
mjoang's avatar
mjoang committed
3400
    LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : short_bsr Buffer_size %d LcgID %d pdu %p mac_ce %p\n",
3401
          short_bsr->Buffer_size, short_bsr->LcgID, pdu, mac_ce);
mjoang's avatar
mjoang committed
3402
  } else if (long_bsr) {
3403 3404

	// MAC CE variable subheader
mjoang's avatar
mjoang committed
3405 3406 3407 3408
    // ch 6.1.3.1. TS 38.321
    ((NR_MAC_SUBHEADER_SHORT *) mac_ce)->R = 0;
    ((NR_MAC_SUBHEADER_SHORT *) mac_ce)->F = 0;
    ((NR_MAC_SUBHEADER_SHORT *) mac_ce)->LCID = UL_SCH_LCID_L_BSR;
3409

mjoang's avatar
mjoang committed
3410 3411
    NR_MAC_SUBHEADER_SHORT *mac_pdu_subheader_ptr = (NR_MAC_SUBHEADER_SHORT *) mac_ce;
    mac_ce += 2;
mjoang's avatar
mjoang committed
3412

3413 3414
    // Could move to nr_get_sdu()
    uint8_t *Buffer_size_ptr= (uint8_t*) mac_ce + 1;
mjoang's avatar
mjoang committed
3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463
    //int NR_BSR_LONG_SIZE = 1;
    if (long_bsr->Buffer_size0 == 0) {
      ((NR_BSR_LONG *) mac_ce)->LcgID0 = 0;
    } else {
      ((NR_BSR_LONG *) mac_ce)->LcgID0 = 1;
      *Buffer_size_ptr++ = long_bsr->Buffer_size0;
    }
    if (long_bsr->Buffer_size1 == 0) {
      ((NR_BSR_LONG *) mac_ce)->LcgID1 = 0;
    } else {
      ((NR_BSR_LONG *) mac_ce)->LcgID1 = 1;
      *Buffer_size_ptr++ = long_bsr->Buffer_size1;
    }
    if (long_bsr->Buffer_size2 == 0) {
      ((NR_BSR_LONG *) mac_ce)->LcgID2 = 0;
    } else {
      ((NR_BSR_LONG *) mac_ce)->LcgID2 = 1;
      *Buffer_size_ptr++ = long_bsr->Buffer_size2;
    }
    if (long_bsr->Buffer_size3 == 0) {
      ((NR_BSR_LONG *) mac_ce)->LcgID3 = 0;
    } else {
      ((NR_BSR_LONG *) mac_ce)->LcgID3 = 1;
      *Buffer_size_ptr++ = long_bsr->Buffer_size3;
    }
    if (long_bsr->Buffer_size4 == 0) {
      ((NR_BSR_LONG *) mac_ce)->LcgID4 = 0;
    } else {
      ((NR_BSR_LONG *) mac_ce)->LcgID4 = 1;
      *Buffer_size_ptr++ = long_bsr->Buffer_size4;
    }
    if (long_bsr->Buffer_size5 == 0) {
      ((NR_BSR_LONG *) mac_ce)->LcgID5 = 0;
    } else {
      ((NR_BSR_LONG *) mac_ce)->LcgID5 = 1;
      *Buffer_size_ptr++ = long_bsr->Buffer_size5;
    }
    if (long_bsr->Buffer_size6 == 0) {
      ((NR_BSR_LONG *) mac_ce)->LcgID6 = 0;
    } else {
      ((NR_BSR_LONG *) mac_ce)->LcgID6 = 1;
      *Buffer_size_ptr++ = long_bsr->Buffer_size6;
    }
    if (long_bsr->Buffer_size7 == 0) {
      ((NR_BSR_LONG *) mac_ce)->LcgID7 = 0;
    } else {
      ((NR_BSR_LONG *) mac_ce)->LcgID7 = 1;
      *Buffer_size_ptr++ = long_bsr->Buffer_size7;
    }
3464 3465
    ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_subheader_ptr)->L = mac_ce_size = (uint8_t*) Buffer_size_ptr - (uint8_t*) mac_ce;
    LOG_D(NR_MAC, "[UE] Generating ULSCH PDU : long_bsr size %d Lcgbit 0x%02x Buffer_size %d %d %d %d %d %d %d %d\n", mac_ce_size, *((uint8_t*) mac_ce),
3466 3467
          ((NR_BSR_LONG *) mac_ce)->Buffer_size0, ((NR_BSR_LONG *) mac_ce)->Buffer_size1, ((NR_BSR_LONG *) mac_ce)->Buffer_size2, ((NR_BSR_LONG *) mac_ce)->Buffer_size3,
          ((NR_BSR_LONG *) mac_ce)->Buffer_size4, ((NR_BSR_LONG *) mac_ce)->Buffer_size5, ((NR_BSR_LONG *) mac_ce)->Buffer_size6, ((NR_BSR_LONG *) mac_ce)->Buffer_size7);
mjoang's avatar
mjoang committed
3468
    // update pointer and length
3469
    mac_ce = Buffer_size_ptr;
mjoang's avatar
mjoang committed
3470
    mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_SHORT);
cig's avatar
cig committed
3471
  }
3472

cig's avatar
cig committed
3473
  return mac_ce_len;
3474

3475
}
3476

cig's avatar
cig committed
3477

3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515
/////////////////////////////////////
//    Random Access Response PDU   //
//         TS 38.213 ch 8.2        //
//        TS 38.321 ch 6.2.3       //
/////////////////////////////////////
//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
//| E | T |       R A P I D       |//
//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |//
//| R |           T A             |//
//|       T A         |  UL grant |//
//|            UL grant           |//
//|            UL grant           |//
//|            UL grant           |//
//|         T C - R N T I         |//
//|         T C - R N T I         |//
/////////////////////////////////////
//       UL grant  (27 bits)       //
/////////////////////////////////////
//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
//|-------------------|FHF|F_alloc|//
//|        Freq allocation        |//
//|    F_alloc    |Time allocation|//
//|      MCS      |     TPC   |CSI|//
/////////////////////////////////////
// TbD WIP Msg3 development ongoing
// - apply UL grant freq alloc & time alloc as per 8.2 TS 38.213
// - apply tpc command
// WIP fix:
// - time domain indication hardcoded to 0 for k2 offset
// - extend TS 38.213 ch 8.3 Msg3 PUSCH
// - b buffer
// - ulsch power offset
// - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures
int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){

  module_id_t mod_id       = dl_info->module_id;
  frame_t frame            = dl_info->frame;
  int slot                 = dl_info->slot;
3516 3517 3518 3519 3520 3521

  if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack == 0) {
    LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] CRC check failed on RAR (NAK)\n", mod_id, frame, slot);
    return 0;
  }

3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532
  NR_UE_MAC_INST_t *mac    = get_mac_inst(mod_id);
  RA_config_t *ra          = &mac->ra;
  uint8_t n_subPDUs        = 0;  // number of RAR payloads
  uint8_t n_subheaders     = 0;  // number of MAC RAR subheaders
  uint8_t *dlsch_buffer    = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu;
  uint8_t is_Msg3          = 1;
  frame_t frame_tx         = 0;
  int slot_tx              = 0;
  int ret                  = 0;
  NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; // RAR subheader pointer
  NR_MAC_RAR *rar          = (NR_MAC_RAR *) (dlsch_buffer + 1);   // RAR subPDU pointer
3533
  uint8_t preamble_index   = ra->ra_PreambleIndex;
3534

3535
  LOG_D(NR_MAC, "In %s:[%d.%d]: [UE %d][RAPROC] invoking MAC for received RAR (current preamble %d)\n", __FUNCTION__, frame, slot, mod_id, preamble_index);
3536 3537 3538 3539 3540

  while (1) {
    n_subheaders++;
    if (rarh->T == 1) {
      n_subPDUs++;
3541
      LOG_I(NR_MAC, "[UE %d][RAPROC] Got RAPID RAR subPDU\n", mod_id);
3542 3543 3544
    } else {
      ra->RA_backoff_indicator = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI];
      ra->RA_BI_found = 1;
3545 3546 3547 3548 3549 3550 3551
      LOG_I(NR_MAC, "[UE %d][RAPROC] Got BI RAR subPDU %d ms\n", mod_id, ra->RA_backoff_indicator);
      if ( ((NR_RA_HEADER_BI *)rarh)->E == 1) {
        rarh += sizeof(NR_RA_HEADER_BI);
        continue;
      } else {
        break;
      }
3552 3553
    }
    if (rarh->RAPID == preamble_index) {
3554
      LOG_A(NR_MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mod_id, frame, slot, rarh->RAPID);
3555 3556
      rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR));
      ra->RA_RAPID_found = 1;
3557
      if (get_softmodem_params()->emulate_l1) {
3558 3559 3560 3561 3562
        /* When we are emulating L1 with multiple UEs, the rx_indication will have
           multiple RAR PDUs. The code would previously handle each of these PDUs,
           but it should only be handling the single RAR that matches the current
           UE. */
        LOG_I(NR_MAC, "RAR PDU found for our UE with PDU index %d\n", pdu_id);
3563 3564 3565 3566 3567 3568 3569 3570 3571
        dl_info->rx_ind->number_pdus = 1;
        if (pdu_id != 0) {
          memcpy(&dl_info->rx_ind->rx_indication_body[0],
                &dl_info->rx_ind->rx_indication_body[pdu_id],
                sizeof(fapi_nr_rx_indication_body_t));
        }
        mac->nr_ue_emul_l1.expected_rar = false;
        memset(mac->nr_ue_emul_l1.index_has_rar, 0, sizeof(mac->nr_ue_emul_l1.index_has_rar));
      }
3572 3573 3574
      break;
    }
    if (rarh->E == 0) {
3575
      LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] Received RAR preamble (%d) doesn't match the intended RAPID (%d)\n", mod_id, frame, slot, rarh->RAPID, preamble_index);
3576 3577 3578 3579 3580
      break;
    } else {
      rarh += sizeof(NR_MAC_RAR) + 1;
    }
  }
3581

3582 3583 3584 3585
  #ifdef DEBUG_RAR
  LOG_D(MAC, "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n", frame, slot, n_subheaders, n_subPDUs);
  LOG_D(MAC, "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index);
  #endif
3586

3587
  if (ra->RA_RAPID_found) {
3588

3589
    RAR_grant_t rar_grant;
3590

3591 3592 3593 3594 3595
    unsigned char tpc_command;
#ifdef DEBUG_RAR
    unsigned char csi_req;
#endif

3596 3597
    // TA command
    ul_time_alignment->apply_ta = 1;
Arash Sahbafard's avatar
Arash Sahbafard committed
3598 3599 3600
    const int ta = rar->TA2 + (rar->TA1 << 5);
    ul_time_alignment->ta_command = 31 + ta;
    ul_time_alignment->ta_total = ta;
3601
    LOG_W(MAC, "received TA command %d\n", ul_time_alignment->ta_command);
3602 3603

#ifdef DEBUG_RAR
3604 3605
    // CSI
    csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01);
3606 3607
#endif

3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635
    // TPC
    tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07);
    switch (tpc_command){
      case 0:
        ra->Msg3_TPC = -6;
        break;
      case 1:
        ra->Msg3_TPC = -4;
        break;
      case 2:
        ra->Msg3_TPC = -2;
        break;
      case 3:
        ra->Msg3_TPC = 0;
        break;
      case 4:
        ra->Msg3_TPC = 2;
        break;
      case 5:
        ra->Msg3_TPC = 4;
        break;
      case 6:
        ra->Msg3_TPC = 6;
        break;
      case 7:
        ra->Msg3_TPC = 8;
        break;
    }
3636 3637 3638 3639 3640 3641 3642 3643 3644
    // MCS
    rar_grant.mcs = (unsigned char) (rar->UL_GRANT_4 >> 4);
    // time alloc
    rar_grant.Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x07);
    // frequency alloc
    rar_grant.Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12));
    // frequency hopping
    rar_grant.freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2);

rmagueta's avatar
rmagueta committed
3645
#ifdef DEBUG_RAR
rmagueta's avatar
rmagueta committed
3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662
    LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E);
    LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T);
    LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID);

    LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R);
    LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1);

    LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2);
    LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1);

    LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2);
    LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3);
    LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4);

    LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1);
    LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2);

rmagueta's avatar
rmagueta committed
3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675
    LOG_I(NR_MAC, "In %s:[%d.%d]: [UE %d] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d t_crnti %x \n",
      __FUNCTION__,
      frame,
      slot,
      mod_id,
      rar_grant.Msg3_t_alloc,
      rar_grant.Msg3_f_alloc,
      ul_time_alignment->ta_command,
      rar_grant.mcs,
      rar_grant.freq_hopping,
      tpc_command,
      ra->t_crnti);
#endif
3676 3677

    // Schedule Msg3
3678
    NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP;
3679
    NR_tda_info_t tda_info = get_ul_tda_info(current_UL_BWP, *ra->ss->controlResourceSetId, ra->ss->searchSpaceType->present, NR_RNTI_RA, rar_grant.Msg3_t_alloc);
3680
    if (tda_info.nrOfSymbols == 0) {
3681 3682 3683 3684
      LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n");
      return -1;
    }
    ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, tda_info.k2);
3685 3686 3687 3688

    if (ret != -1){

      fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx);
cig's avatar
cig committed
3689
      uint16_t rnti = mac->crnti;
3690 3691 3692 3693 3694

      if (!ul_config) {
        LOG_W(MAC, "In %s: ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n", __FUNCTION__, frame, slot);
        return -1;
      }
3695
      AssertFatal(ul_config->number_pdus < sizeof(ul_config->ul_config_list) / sizeof(ul_config->ul_config_list[0]),
3696
                  "Number of PDUS in ul_config = %d > ul_config_list num elements", ul_config->number_pdus);
3697

cig's avatar
cig committed
3698 3699 3700 3701 3702 3703
      // Upon successful reception, set the T-CRNTI to the RAR value if the RA preamble is selected among the contention-based RA Preambles
      if (!ra->cfra) {
        ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
        rnti = ra->t_crnti;
      }

3704 3705
      pthread_mutex_lock(&ul_config->mutex_ul_config);
      AssertFatal(ul_config->number_pdus<FAPI_NR_UL_CONFIG_LIST_NUM, "ul_config->number_pdus %d out of bounds\n",ul_config->number_pdus);
3706 3707 3708
      nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu;

      fill_ul_config(ul_config, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
3709
      pthread_mutex_unlock(&ul_config->mutex_ul_config);
3710 3711

      // Config Msg3 PDU
3712
      nr_config_pusch_pdu(mac, &tda_info, pusch_config_pdu, NULL, &rar_grant, rnti, NULL);
3713 3714 3715 3716 3717 3718
    }

  } else {

    ra->t_crnti = 0;
    ul_time_alignment->ta_command = (0xffff);
3719

3720 3721
  }

3722
  return ret;
francescomani's avatar
francescomani committed
3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748
}

// Returns the pathloss in dB for the active UL BWP on the selected carrier based on the DL RS associated with the PRACH transmission
// computation according to clause 7.4 (Physical random access channel) of 3GPP TS 38.213 version 16.3.0 Release 16
// Assumptions:
// - PRACH transmission from a UE is not in response to a detection of a PDCCH order by the UE
// Measurement units:
// - referenceSignalPower:   dBm/RE (average EPRE of the resources elements that carry secondary synchronization signals in dBm)
int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm)
{

  long referenceSignalPower;
  //TODO improve PL measurements. Probably not correct as it is.
  if (mac->scc)
    referenceSignalPower = mac->scc->ss_PBCH_BlockPower;
  else
    referenceSignalPower = mac->scc_SIB->ss_PBCH_BlockPower;

  int16_t pathloss = (int16_t)(referenceSignalPower - ssb_rsrp_dBm);

  LOG_D(NR_MAC, "pathloss %d dB, referenceSignalPower %ld dBm/RE (%f mW), RSRP %d dBm (%f mW)\n",
        pathloss,
        referenceSignalPower,
        pow(10, referenceSignalPower/10),
        ssb_rsrp_dBm,
        pow(10, ssb_rsrp_dBm/10));
3749

francescomani's avatar
francescomani committed
3750
  return pathloss;
3751
}