NR_IF_Module.c 28.8 KB
Newer Older
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

/*! \file openair2/NR_PHY_INTERFACE/NR_IF_Module.c
* \brief data structures for PHY/MAC interface modules
* \author EURECOM/NTUST
* \date 2018
* \version 0.1
* \company Eurecom, NTUST
* \email: raymond.knopp@eurecom.fr, kroempa@gmail.com
* \note
* \warning
*/

33 34
#include "openair1/SCHED_NR/fapi_nr_l1.h"
#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h"
35
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
36 37
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include "common/ran_context.h"
38
#include "executables/softmodem-common.h"
Mahesh's avatar
Mahesh committed
39
#include "nfapi/oai_integration/vendor_ext.h" 
40

41
#define MAX_IF_MODULES 100
Francesco Mani's avatar
Francesco Mani committed
42
//#define UL_HARQ_PRINT
43 44 45

NR_IF_Module_t *if_inst[MAX_IF_MODULES];
NR_Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs];
46
extern const uint8_t slots_per_frame[5];
47 48 49 50 51 52 53
extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind);
extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind);
extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind);
extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind);
extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind);
extern uint8_t nfapi_mode;
extern uint16_t sf_ahead;
54
extern uint16_t sl_ahead;
55
void tci_handling(module_id_t Mod_idP, int UE_id, int CC_id, NR_UE_sched_ctrl_t *sched_ctrl, frame_t frame, slot_t slot);
56

57
void handle_nr_rach(NR_UL_IND_t *UL_info) {
58

59
  if (UL_info->rach_ind.number_of_pdus>0) {
kn.raju's avatar
kn.raju committed
60
    LOG_I(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot);
Francesco Mani's avatar
Francesco Mani committed
61 62 63 64 65 66
    int npdus = UL_info->rach_ind.number_of_pdus;
    for(int i = 0; i < npdus; i++) {
      UL_info->rach_ind.number_of_pdus--;
      if (UL_info->rach_ind.pdu_list[i].num_preamble>0)
      AssertFatal(UL_info->rach_ind.pdu_list[i].num_preamble==1,
                  "More than 1 preamble not supported\n");
67
    
Francesco Mani's avatar
Francesco Mani committed
68 69 70 71 72 73 74 75 76
      nr_initiate_ra_proc(UL_info->module_id,
                          UL_info->CC_id,
                          UL_info->rach_ind.sfn,
                          UL_info->rach_ind.slot,
                          UL_info->rach_ind.pdu_list[i].preamble_list[0].preamble_index,
                          UL_info->rach_ind.pdu_list[i].freq_index,
                          UL_info->rach_ind.pdu_list[i].symbol_index,
                          UL_info->rach_ind.pdu_list[i].preamble_list[0].timing_advance);
    }
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
77 78
  }
}
79 80

	else if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type)
81
	  *nb_resource_sets=csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[idx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count;
82 83 84 85 86 87 88 89 90 91 92 93

      } else {
        //TODO: find the CSI_RS IM resources
      }
    } else {
      AssertFatal(csi_ResourceConfigId, "csi_ResourceConfigId is not configured");
    }
  }

  return -1;
}

94 95 96
//!TODO : smae function can be written to handle csi_resources
uint8_t get_ssb_resources (NR_CSI_MeasConfig_t *csi_MeasConfig, 
		NR_CSI_ResourceConfigId_t csi_ResourceConfigId, 
97 98
		NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type,
		uint8_t *nb_resource_sets) {
99
  uint8_t idx = 0;
100
  uint8_t csi_ssb_idx =0;
101 102 103 104 105 106

  for ( idx = 0; idx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; idx++) {
    if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[idx]->csi_ResourceConfigId == csi_ResourceConfigId) {
    //Finding the CSI_RS or SSB Resources
      if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[idx]->csi_RS_ResourceSetList.present == NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB) {

107 108 109 110 111 112 113 114 115 116 117 118 119
        if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type ){
          *nb_resource_sets=csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[idx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.count;
 
          for ( 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_MeasConfig->csi_ResourceConfigToAddModList->list.array[idx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) {
              return csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count;
            } else {
            //handle error condition
              AssertFatal(csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId, "csi_SSB_ResourcesSetId is not configured");
            }
          }
	}
120 121

	else if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type)
122
	  *nb_resource_sets=csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[idx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count;
123 124 125 126 127 128

void extract_pucch_csi_report ( NR_CSI_MeasConfig_t *csi_MeasConfig,
                                nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu,
                                NR_UE_sched_ctrl_t *sched_ctrl,
                                frame_t frame,
                                slot_t slot,
r.karey's avatar
r.karey committed
129 130
				NR_SubcarrierSpacing_t scs, int UE_id,
				module_id_t Mod_idP
131
                              ) {
132

133
  /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
r.karey's avatar
r.karey committed
134
  uint8_t idx = 0;
135
  uint8_t payload_size = ceil(((double)uci_pdu->csi_part1.csi_part1_bit_len)/8);
136
  uint8_t *payload = calloc (payload_size, sizeof(uint8_t));
137
  NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type = NR_CSI_ReportConfig__reportQuantity_PR_NOTHING;
r.karey's avatar
r.karey committed
138 139
  NR_UE_list_t *UE_list = &(RC.nrmac[Mod_idP]->UE_list);
  long periodicity;
140
  uint8_t csi_report_id = 0;
141

142
  memcpy ( payload, uci_pdu->csi_part1.csi_part1_payload, payload_size);
143 144
  
  reverse_n_bits(payload, uci_pdu->csi_part1.csi_part1_bit_len);
145

146
  UE_list->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = 0;
147 148
  for ( csi_report_id =0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++ ) {
    //Assuming in periodic reporting for one slot can be configured with only one CSI-ReportConfig
r.karey's avatar
r.karey committed
149
 //   if (csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_periodic) {
150
      //Has to implement according to reportSlotConfig type
r.karey's avatar
r.karey committed
151 152
    periodicity = UE_list->csi_report_template[UE_id][csi_report_id].periodicity;
    LOG_I(PHY,"SFN/SF:%d%d \n", frame,slot);
153 154
   /* if (((NR_SubcarrierSpacing_kHz30 == scs) && (((((frame & 0xf)+1)*20 + slot) & periodicity) == periodicity))
       ||((NR_SubcarrierSpacing_kHz120 == scs)&&(((((frame & 0xf)+1)*80 + slot) & periodicity) == periodicity))) {*/
155 156
    if (((slots_per_frame[scs]*frame + slot -UE_list->csi_report_template[UE_id][csi_report_id].offset)%periodicity)!=0) 
      continue;
157

158 159 160 161 162 163 164 165
    reportQuantity_type = UE_list->csi_report_template[UE_id][csi_report_id].reportQuantity_type;
    LOG_I(PHY,"SFN/SF:%d%d reportQuantity type = %d\n",frame,slot,reportQuantity_type);
    
    if ( NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type || 
		    NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type) {
      uint8_t csi_ssb_idx = 0;
      uint8_t diff_rsrp_idx = 0;
      uint8_t cri_ssbri_bitlen = UE_list->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.cri_ssbri_bitlen;
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184

    /*! As per the spec 38.212 and table:  6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report
     * the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE
     * From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set
     * From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1
     */
      
      /** from 38.214 sec 5.2.1.4.2
      - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE is
        not required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in
        a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting

      - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE is not
      required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in a
      single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB
      resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with
      multiple simultaneous spatial domain receive filter
      */

185 186
      idx = 0; //Since for SSB RSRP reporting in RRC can configure only one ssb resource set per one report config
      sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri = UE_list->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.nb_ssbri_cri;
187

188 189
      for (csi_ssb_idx = 0; csi_ssb_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri ; csi_ssb_idx++) {
	if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type)
190

191
          sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx] = 
192
		  *(UE_list->csi_report_template[UE_id][csi_report_id].SSB_Index_list[cri_ssbri_bitlen>0?((*payload)&~(~1<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]);
193
	else
194
          sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx] = 
195
		  *(UE_list->csi_report_template[UE_id][csi_report_id].CSI_Index_list[cri_ssbri_bitlen>0?((*payload)&~(~1<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]);
196 197
	  
        *payload >>= cri_ssbri_bitlen;
198
	LOG_I(PHY,"SSB_index = %d",sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx]);
199
      }
200

201 202
      sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP = (*payload) & 0x7f;
      *payload >>= 7;
203

204 205
      for ( diff_rsrp_idx =0; diff_rsrp_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri - 1; diff_rsrp_idx++ ) {
        sched_ctrl->CSI_report[idx].choice.ssb_cri_report.diff_RSRP[diff_rsrp_idx] = (*payload) & 0x0f;
206 207
        *payload >>= 4;
      }
208
      UE_list->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report++;
209
      LOG_I(MAC,"csi_payload size = %d, rsrp_id = %d\n",payload_size, sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP);
210
    }
211 212
  }

213 214 215 216
  if ( !(reportQuantity_type)) 
    AssertFatal(reportQuantity_type, "reportQuantity is not configured");


217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
#if 0

  if ( NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1 == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI== reportQuantity_type) {
    // Handling of extracting cri
    sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report.cri = calloc ( 1, ceil(bitlen_cri/8));
    *(sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report.cri) = *((uint32_t *)payload) & ~(~1<<(bitlen_cri-1));
    *payload >>= bitlen_cri;

    if ( 1 == RC.nrrrc[gnb_mod_idP]->carrier.pdsch_AntennaPorts ) {
      /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
      sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report->ri = NULL;
    } else {
      //Handling for the ri for multiple csi ports
    }
  }

  if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI== reportQuantity_type) {
    if ( 1 == RC.nrrrc[gnb_mod_idP]->carrier.pdsch_AntennaPorts )
      /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
      sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report->li = NULL;
    else {
      //Handle for li for multiple CSI ports
    }
  }

  //TODO: check for zero padding if available shift payload to the number of zero padding bits

  if ( NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI== reportQuantity_type) {
    if ( 1 == RC.nrrrc[gnb_mod_idP]->carrier.pdsch_AntennaPorts ) {
      /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
      sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report->pmi_x1 = NULL;
      sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report->pmi_x2 = NULL;
    }
  }

  if ( NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI== reportQuantity_type) {
    /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
    *(sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report->cqi) = *(payload) & 0x0f;
    *(payload) >>= 4;
  }

#endif
}
268 269 270 271 272 273 274 275 276

void extract_pucch_csi_report ( NR_CSI_MeasConfig_t *csi_MeasConfig,
                                nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu,
                                NR_UE_sched_ctrl_t *sched_ctrl,
                                frame_t frame,
                                slot_t slot,
				NR_SubcarrierSpacing_t scs
                              ) {
  /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
r.karey's avatar
r.karey committed
277
  uint8_t idx = 0;
278 279 280
  uint8_t payload_size = ceil(uci_pdu->csi_part1.csi_part1_bit_len/8);
  uint16_t *payload = calloc (1, payload_size);
  NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type = NR_CSI_ReportConfig__reportQuantity_PR_NOTHING;
r.karey's avatar
r.karey committed
281 282
  NR_UE_list_t *UE_list = &(RC.nrmac[Mod_idP]->UE_list);
  long periodicity;
283
  uint8_t csi_report_id = 0;
284

285 286 287 288
  memcpy ( payload, uci_pdu->csi_part1.csi_part1_payload, payload_size);

  for ( csi_report_id =0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++ ) {
    //Assuming in periodic reporting for one slot can be configured with only one CSI-ReportConfig
r.karey's avatar
r.karey committed
289
 //   if (csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportConfigType.present == NR_CSI_ReportConfig__reportConfigType_PR_periodic) {
290 291
      //considering 30khz scs and
      //Has to implement according to reportSlotConfig type
r.karey's avatar
r.karey committed
292 293
    periodicity = UE_list->csi_report_template[UE_id][csi_report_id].periodicity;
    LOG_I(PHY,"SFN/SF:%d%d \n", frame,slot);
294 295
   /* if (((NR_SubcarrierSpacing_kHz30 == scs) && (((((frame & 0xf)+1)*20 + slot) & periodicity) == periodicity))
       ||((NR_SubcarrierSpacing_kHz120 == scs)&&(((((frame & 0xf)+1)*80 + slot) & periodicity) == periodicity))) {*/
296 297
    if (((slots_per_frame[scs]*frame + slot -UE_list->csi_report_template[UE_id][csi_report_id].offset)%periodicity)!=0) 
      continue;
298

299 300 301 302 303 304 305 306
    reportQuantity_type = UE_list->csi_report_template[UE_id][csi_report_id].reportQuantity_type;
    LOG_I(PHY,"SFN/SF:%d%d reportQuantity type = %d\n",frame,slot,reportQuantity_type);
    
    if ( NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type || 
		    NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type) {
      uint8_t csi_ssb_idx = 0;
      uint8_t diff_rsrp_idx = 0;
      uint8_t cri_ssbri_bitlen = UE_list->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.cri_ssbri_bitlen;
307

308
      LOG_I(MAC,"csi_payload = %d, cri_ssbri_bitlen = %d\n",payload_size, cri_ssbri_bitlen);
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
    /*! As per the spec 38.212 and table:  6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report
     * the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE
     * From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set
     * From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1
     */
      
      /** from 38.214 sec 5.2.1.4.2
      - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE is
        not required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in
        a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting

      - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE is not
      required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in a
      single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB
      resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with
      multiple simultaneous spatial domain receive filter
      */

327 328
      idx = 0; //Since for SSB RSRP reporting in RRC can configure only one ssb resource set per one report config
      sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri = UE_list->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.nb_ssbri_cri;
329

330 331
      for (csi_ssb_idx = 0; csi_ssb_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri ; csi_ssb_idx++) {
	if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type)
332

333 334 335 336 337 338
          sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx] = *(UE_list->csi_report_template[UE_id][csi_report_id].SSB_Index_list [(*payload) & ~(~1<<(cri_ssbri_bitlen-1))]);
	else
          sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx] = *(UE_list->csi_report_template[UE_id][csi_report_id].CSI_Index_list [(*payload) & ~(~1<<(cri_ssbri_bitlen-1))]);
	  
        *payload >>= cri_ssbri_bitlen;
      }
339

340 341
      sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP = (*payload) & 0x7f;
      *payload >>= 7;
342

343 344
      for ( diff_rsrp_idx =0; diff_rsrp_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri - 1; diff_rsrp_idx++ ) {
        sched_ctrl->CSI_report[idx].choice.ssb_cri_report.diff_RSRP[diff_rsrp_idx] = (*payload) & 0x0f;
345 346
        *payload >>= 4;
      }
347 348
      UE_list->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report++;
    }
349 350
  }

351 352 353 354
  if ( !(reportQuantity_type)) 
    AssertFatal(reportQuantity_type, "reportQuantity is not configured");


355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
#if 0

  if ( NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1 == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI== reportQuantity_type) {
    // Handling of extracting cri
    sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report.cri = calloc ( 1, ceil(bitlen_cri/8));
    *(sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report.cri) = *((uint32_t *)payload) & ~(~1<<(bitlen_cri-1));
    *payload >>= bitlen_cri;

    if ( 1 == RC.nrrrc[gnb_mod_idP]->carrier.pdsch_AntennaPorts ) {
      /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
      sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report->ri = NULL;
    } else {
      //Handling for the ri for multiple csi ports
    }
  }

  if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI== reportQuantity_type) {
    if ( 1 == RC.nrrrc[gnb_mod_idP]->carrier.pdsch_AntennaPorts )
      /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
      sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report->li = NULL;
    else {
      //Handle for li for multiple CSI ports
    }
  }

  //TODO: check for zero padding if available shift payload to the number of zero padding bits

  if ( NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI== reportQuantity_type) {
    if ( 1 == RC.nrrrc[gnb_mod_idP]->carrier.pdsch_AntennaPorts ) {
      /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
      sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report->pmi_x1 = NULL;
      sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report->pmi_x2 = NULL;
    }
  }

  if ( NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI == reportQuantity_type ||
       NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI== reportQuantity_type) {
    /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
    *(sched_ctrl->CSI_report[UE_id][cqi_idx].choice.cri_ri_li_pmi_cqi_report->cqi) = *(payload) & 0x0f;
    *(payload) >>= 4;
  }

#endif
}
406

407 408 409 410 411
void handle_nr_uci(NR_UL_IND_t *UL_info)
{
  const module_id_t mod_id = UL_info->module_id;
  const frame_t frame = UL_info->frame;
  const sub_frame_t slot = UL_info->slot;
412 413
  int num_ucis = UL_info->uci_ind.num_ucis;
  nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list;
414
  uint8_t UE_id = 0;
415 416 417

  for (int i = 0; i < num_ucis; i++) {
    switch (uci_list[i].pdu_type) {
418 419 420
      case NFAPI_NR_UCI_PUSCH_PDU_TYPE:
        LOG_E(MAC, "%s(): unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE\n", __func__);
        break;
421 422

      case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: {
423 424
        const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1;
        handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu);
425 426 427
        break;
      }
      case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: {
428 429
        const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4;
        handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu);
430 431 432 433 434 435
        break;
      }
    }
  }

  UL_info->uci_ind.num_ucis = 0;
436

437 438 439
  // mark corresponding PUCCH resources as free
  // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs
  RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0;
440 441
}

442

443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
void handle_nr_ulsch(NR_UL_IND_t *UL_info)
{
  if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) {
    for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) {
      for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) {
        // find crc_indication j corresponding rx_indication i
        const nfapi_nr_rx_data_pdu_t *rx = &UL_info->rx_ind.pdu_list[i];
        const nfapi_nr_crc_t *crc = &UL_info->crc_ind.crc_list[j];
        LOG_D(PHY,
              "UL_info->crc_ind.pdu_list[%d].rnti:%04x "
              "UL_info->rx_ind.pdu_list[%d].rnti:%04x\n",
              j,
              crc->rnti,
              i,
              rx->rnti);

        if (crc->rnti != rx->rnti)
          continue;

        LOG_D(MAC,
              "%4d.%2d Calling rx_sdu (CRC %s/tb_crc_status %d)\n",
              UL_info->frame,
              UL_info->slot,
              crc->tb_crc_status ? "error" : "ok",
              crc->tb_crc_status);

        /* if CRC passes, pass PDU, otherwise pass NULL as error indication */
        nr_rx_sdu(UL_info->module_id,
                  UL_info->CC_id,
                  UL_info->rx_ind.sfn,
                  UL_info->rx_ind.slot,
                  rx->rnti,
                  crc->tb_crc_status ? NULL : rx->pdu,
                  rx->pdu_length,
                  rx->timing_advance,
                  rx->ul_cqi,
                  rx->rssi);
        handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc);
        break;
      } //    for (j=0;j<UL_info->crc_ind.number_crcs;j++)
    } //   for (i=0;i<UL_info->rx_ind.number_of_pdus;i++)

    UL_info->crc_ind.number_crcs = 0;
    UL_info->rx_ind.number_of_pdus = 0;
  } else if (UL_info->rx_ind.number_of_pdus != 0
             || UL_info->crc_ind.number_crcs != 0) {
    LOG_E(PHY,
          "hoping not to have mis-match between CRC ind and RX ind - "
          "hopefully the missing message is coming shortly "
          "rx_ind:%d(SFN/SL:%d/%d) crc_ind:%d(SFN/SL:%d/%d) \n",
          UL_info->rx_ind.number_of_pdus,
          UL_info->rx_ind.sfn,
          UL_info->rx_ind.slot,
          UL_info->crc_ind.number_crcs,
          UL_info->rx_ind.sfn,
          UL_info->rx_ind.slot);
WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
499 500 501
  }
}

502
void NR_UL_indication(NR_UL_IND_t *UL_info) {
503 504 505 506
  AssertFatal(UL_info!=NULL,"UL_INFO is null\n");
#ifdef DUMP_FAPI
  dump_ul(UL_info);
#endif
507 508 509 510 511
  module_id_t      module_id   = UL_info->module_id;
  int              CC_id       = UL_info->CC_id;
  NR_Sched_Rsp_t   *sched_info = &Sched_INFO[module_id][CC_id];
  NR_IF_Module_t   *ifi        = if_inst[module_id];
  gNB_MAC_INST     *mac        = RC.nrmac[module_id];
512
  LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rach_pdus:%d rx_ind:%d crcs:%d]\n",
513
        UL_info->frame,UL_info->slot,
514
        module_id,CC_id, UL_info->rach_ind.number_of_pdus,
515
        UL_info->rx_ind.number_of_pdus, UL_info->crc_ind.number_crcs);
516

517
  if (NFAPI_MODE != NFAPI_MODE_PNF) {
518 519
    if (ifi->CC_mask==0) {
      ifi->current_frame    = UL_info->frame;
520
      ifi->current_slot = UL_info->slot;
521
    } else {
522
      AssertFatal(UL_info->frame != ifi->current_frame,"CC_mask %x is not full and frame has changed\n",ifi->CC_mask);
523
      AssertFatal(UL_info->slot != ifi->current_slot,"CC_mask %x is not full and slot has changed\n",ifi->CC_mask);
524
    }
525

526 527 528
    ifi->CC_mask |= (1<<CC_id);
  }

WEI-TAI CHEN's avatar
WEI-TAI CHEN committed
529
  handle_nr_rach(UL_info);
530
  
531
  handle_nr_uci(UL_info);
532
  // clear HI prior to handling ULSCH
533
  mac->UL_dci_req[CC_id].numPdus = 0;
534
  handle_nr_ulsch(UL_info);
535

536
  if (NFAPI_MODE != NFAPI_MODE_PNF) {
537
    if (ifi->CC_mask == ((1<<MAX_NUM_CCs)-1)) {
538
      /*
539
      eNB_dlsch_ulsch_scheduler(module_id,
540 541
          (UL_info->frame+((UL_info->slot>(9-sl_ahead))?1:0)) % 1024,
          (UL_info->slot+sl_ahead)%10);
542
      */
543
      nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id];
544
      int spf = get_spf(cfg);
545
      gNB_dlsch_ulsch_scheduler(module_id,
546 547
				(UL_info->frame+((UL_info->slot>(spf-1-sl_ahead))?1:0)) % 1024,
				(UL_info->slot+sl_ahead)%spf);
548
      
549 550 551
      ifi->CC_mask            = 0;
      sched_info->module_id   = module_id;
      sched_info->CC_id       = CC_id;
552 553
      sched_info->frame       = (UL_info->frame + ((UL_info->slot>(spf-1-sl_ahead)) ? 1 : 0)) % 1024;
      sched_info->slot        = (UL_info->slot+sl_ahead)%spf;
554
      sched_info->DL_req      = &mac->DL_req[CC_id];
555
      sched_info->UL_dci_req  = &mac->UL_dci_req[CC_id];
556

557
      sched_info->UL_tti_req  = mac->UL_tti_req[CC_id];
558 559 560 561 562 563

      sched_info->TX_req      = &mac->TX_req[CC_id];
#ifdef DUMP_FAPI
      dump_dl(sched_info);
#endif

564
      if (ifi->NR_Schedule_response) {
565 566 567 568 569
        AssertFatal(ifi->NR_Schedule_response!=NULL,
                    "nr_schedule_response is null (mod %d, cc %d)\n",
                    module_id,
                    CC_id);
        ifi->NR_Schedule_response(sched_info);
570 571
      }

Raymond Knopp's avatar
Raymond Knopp committed
572 573 574
      LOG_D(PHY,"NR_Schedule_response: SFN_SF:%d%d dl_pdus:%d\n",
	    sched_info->frame,
	    sched_info->slot,
575
	    sched_info->DL_req->dl_tti_request_body.nPDUs);
576 577 578 579
    }
  }
}

580
NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {
581
  AssertFatal(Mod_id<MAX_MODULES,"Asking for Module %d > %d\n",Mod_id,MAX_IF_MODULES);
Raymond Knopp's avatar
Raymond Knopp committed
582
  LOG_I(PHY,"Installing callbacks for IF_Module - UL_indication\n");
583 584 585 586 587

  if (if_inst[Mod_id]==NULL) {
    if_inst[Mod_id] = (NR_IF_Module_t*)malloc(sizeof(NR_IF_Module_t));
    memset((void*)if_inst[Mod_id],0,sizeof(NR_IF_Module_t));

588 589
    LOG_I(MAC,"Allocating shared L1/L2 interface structure for instance %d @ %p\n",Mod_id,if_inst[Mod_id]);

590
    if_inst[Mod_id]->CC_mask=0;
591
    if_inst[Mod_id]->NR_UL_indication = NR_UL_indication;
592
    AssertFatal(pthread_mutex_init(&if_inst[Mod_id]->if_mutex,NULL)==0,
593
                "allocation of if_inst[%d]->if_mutex fails\n",Mod_id);
594
  }
595

596
  return if_inst[Mod_id];
597
}