This commit provides CSI reporting support which is required for MIMO. It also updates the configuration files, provides sample BLER simualtion files for packet dropping in the MIMO 2x2 case. It also includes the hooks and functions (e.g., updating UCI2_3_4 PDU field) for MIMO 2x2 support. This commit will not include any channel abstraction code or modelling.
581 lines
28 KiB
C
581 lines
28 KiB
C
/*
|
|
* 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 fapi_nr_ue_l1.c
|
|
* \brief functions for NR UE FAPI-like interface
|
|
* \author R. Knopp, K.H. HSU
|
|
* \date 2018
|
|
* \version 0.1
|
|
* \company Eurecom / NTUST
|
|
* \email: knopp@eurecom.fr, kai-hsiang.hsu@eurecom.fr
|
|
* \note
|
|
* \warning
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "fapi_nr_ue_interface.h"
|
|
#include "fapi_nr_ue_l1.h"
|
|
#include "harq_nr.h"
|
|
//#include "PHY/phy_vars_nr_ue.h"
|
|
#include "openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h"
|
|
#include "PHY/defs_nr_UE.h"
|
|
#include "PHY/impl_defs_nr.h"
|
|
#include "utils.h"
|
|
#include "openair2/PHY_INTERFACE/queue_t.h"
|
|
|
|
extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
|
|
|
|
const char *dl_pdu_type[]={"DCI", "DLSCH", "RA_DLSCH", "SI_DLSCH", "P_DLSCH", "CSI_RS", "CSI_IM"};
|
|
const char *ul_pdu_type[]={"PRACH", "PUCCH", "PUSCH", "SRS"};
|
|
queue_t nr_rx_ind_queue;
|
|
queue_t nr_crc_ind_queue;
|
|
queue_t nr_uci_ind_queue;
|
|
|
|
static void fill_uci_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu_2_3_4,
|
|
fapi_nr_ul_config_pucch_pdu *pucch_pdu)
|
|
{
|
|
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
|
memset(pdu_2_3_4, 0, sizeof(*pdu_2_3_4));
|
|
pdu_2_3_4->handle = 0;
|
|
pdu_2_3_4->rnti = pucch_pdu->rnti;
|
|
pdu_2_3_4->pucch_format = 2;
|
|
pdu_2_3_4->ul_cqi = 255;
|
|
pdu_2_3_4->timing_advance = 0;
|
|
pdu_2_3_4->rssi = 0;
|
|
// TODO: Eventually check 38.212:Sect.631 to know when to use csi_part2, for now only using csi_part1
|
|
pdu_2_3_4->pduBitmap = 4;
|
|
pdu_2_3_4->csi_part1.csi_part1_bit_len = mac->nr_ue_emul_l1.num_csi_reports;
|
|
int csi_part1_byte_len = (int)((pdu_2_3_4->csi_part1.csi_part1_bit_len / 8) + 1);
|
|
AssertFatal(!pdu_2_3_4->csi_part1.csi_part1_payload, "pdu_2_3_4->csi_part1.csi_part1_payload != NULL\n");
|
|
pdu_2_3_4->csi_part1.csi_part1_payload = CALLOC(csi_part1_byte_len,
|
|
sizeof(pdu_2_3_4->csi_part1.csi_part1_payload));
|
|
for (int k = 0; k < csi_part1_byte_len; k++)
|
|
{
|
|
pdu_2_3_4->csi_part1.csi_part1_payload[k] = (pucch_pdu->payload >> (k * 8)) & 0xff;
|
|
}
|
|
pdu_2_3_4->csi_part1.csi_part1_crc = 0;
|
|
}
|
|
|
|
static void free_uci_inds(nfapi_nr_uci_indication_t *uci_ind)
|
|
{
|
|
for (int k = 0; k < uci_ind->num_ucis; k++)
|
|
{
|
|
if (uci_ind->uci_list[k].pdu_type == NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE)
|
|
{
|
|
nfapi_nr_uci_pucch_pdu_format_0_1_t *pdu_0_1 = &uci_ind->uci_list[k].pucch_pdu_format_0_1;
|
|
free(pdu_0_1->sr);
|
|
pdu_0_1->sr = NULL;
|
|
if (pdu_0_1->harq)
|
|
{
|
|
free(pdu_0_1->harq->harq_list);
|
|
pdu_0_1->harq->harq_list = NULL;
|
|
}
|
|
free(pdu_0_1->harq);
|
|
pdu_0_1->harq = NULL;
|
|
}
|
|
if (uci_ind->uci_list[k].pdu_type == NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE)
|
|
{
|
|
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu_2_3_4 = &uci_ind->uci_list[k].pucch_pdu_format_2_3_4;
|
|
free(pdu_2_3_4->sr.sr_payload);
|
|
pdu_2_3_4->sr.sr_payload = NULL;
|
|
free(pdu_2_3_4->harq.harq_payload);
|
|
pdu_2_3_4->harq.harq_payload = NULL;
|
|
}
|
|
}
|
|
free(uci_ind->uci_list);
|
|
uci_ind->uci_list = NULL;
|
|
free(uci_ind);
|
|
uci_ind = NULL;
|
|
}
|
|
|
|
int8_t nr_ue_scheduled_response_stub(nr_scheduled_response_t *scheduled_response) {
|
|
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
|
if(scheduled_response != NULL)
|
|
{
|
|
if (scheduled_response->ul_config != NULL)
|
|
{
|
|
fapi_nr_ul_config_request_t *ul_config = scheduled_response->ul_config;
|
|
AssertFatal(ul_config->number_pdus < sizeof(ul_config->ul_config_list) / sizeof(ul_config->ul_config_list[0]),
|
|
"Too many ul_config pdus %d", ul_config->number_pdus);
|
|
for (int i = 0; i < ul_config->number_pdus; ++i)
|
|
{
|
|
LOG_D(NR_PHY, "In %s: processing type %d PDU of %d total UL PDUs (ul_config %p) \n",
|
|
__FUNCTION__, ul_config->ul_config_list[i].pdu_type, ul_config->number_pdus, ul_config);
|
|
|
|
uint8_t pdu_type = ul_config->ul_config_list[i].pdu_type;
|
|
switch (pdu_type)
|
|
{
|
|
case (FAPI_NR_UL_CONFIG_TYPE_PUSCH):
|
|
{
|
|
nfapi_nr_rx_data_indication_t *rx_ind = CALLOC(1, sizeof(*rx_ind));
|
|
nfapi_nr_crc_indication_t *crc_ind = CALLOC(1, sizeof(*crc_ind));
|
|
nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[i].pusch_config_pdu;
|
|
if (scheduled_response->tx_request)
|
|
{
|
|
AssertFatal(scheduled_response->tx_request->number_of_pdus <
|
|
sizeof(scheduled_response->tx_request->tx_request_body) / sizeof(scheduled_response->tx_request->tx_request_body[0]),
|
|
"Too many tx_req pdus %d", scheduled_response->tx_request->number_of_pdus);
|
|
rx_ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION;
|
|
rx_ind->sfn = scheduled_response->ul_config->sfn;
|
|
rx_ind->slot = scheduled_response->ul_config->slot;
|
|
rx_ind->number_of_pdus = scheduled_response->tx_request->number_of_pdus;
|
|
rx_ind->pdu_list = CALLOC(rx_ind->number_of_pdus, sizeof(*rx_ind->pdu_list));
|
|
for (int j = 0; j < rx_ind->number_of_pdus; j++)
|
|
{
|
|
fapi_nr_tx_request_body_t *tx_req_body = &scheduled_response->tx_request->tx_request_body[j];
|
|
rx_ind->pdu_list[j].handle = pusch_config_pdu->handle;
|
|
rx_ind->pdu_list[j].harq_id = pusch_config_pdu->pusch_data.harq_process_id;
|
|
rx_ind->pdu_list[j].pdu_length = tx_req_body->pdu_length;
|
|
rx_ind->pdu_list[j].pdu = CALLOC(tx_req_body->pdu_length, sizeof(*rx_ind->pdu_list[j].pdu));
|
|
memcpy(rx_ind->pdu_list[j].pdu, tx_req_body->pdu, tx_req_body->pdu_length * sizeof(*rx_ind->pdu_list[j].pdu));
|
|
rx_ind->pdu_list[j].rnti = pusch_config_pdu->rnti;
|
|
/* TODO: Implement channel modeling to abstract TA and CQI. For now,
|
|
we hard code the values below since they are set in L1 and we are
|
|
abstracting L1. */
|
|
rx_ind->pdu_list[j].timing_advance = 31;
|
|
rx_ind->pdu_list[j].ul_cqi = 255;
|
|
}
|
|
|
|
crc_ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION;
|
|
crc_ind->number_crcs = scheduled_response->ul_config->number_pdus;
|
|
crc_ind->sfn = scheduled_response->ul_config->sfn;
|
|
crc_ind->slot = scheduled_response->ul_config->slot;
|
|
crc_ind->crc_list = CALLOC(crc_ind->number_crcs, sizeof(*crc_ind->crc_list));
|
|
for (int j = 0; j < crc_ind->number_crcs; j++)
|
|
{
|
|
crc_ind->crc_list[j].handle = pusch_config_pdu->handle;
|
|
crc_ind->crc_list[j].harq_id = pusch_config_pdu->pusch_data.harq_process_id;
|
|
LOG_D(NR_MAC, "This is the harq pid %d for crc_list[%d]\n", crc_ind->crc_list[j].harq_id, j);
|
|
LOG_D(NR_MAC, "This is sched sfn/sl [%d %d] and crc sfn/sl [%d %d]\n",
|
|
scheduled_response->frame, scheduled_response->slot, crc_ind->sfn, crc_ind->slot);
|
|
crc_ind->crc_list[j].num_cb = pusch_config_pdu->pusch_data.num_cb;
|
|
crc_ind->crc_list[j].rnti = pusch_config_pdu->rnti;
|
|
crc_ind->crc_list[j].tb_crc_status = 0;
|
|
crc_ind->crc_list[j].timing_advance = 31;
|
|
crc_ind->crc_list[j].ul_cqi = 255;
|
|
AssertFatal(mac->nr_ue_emul_l1.harq[crc_ind->crc_list[j].harq_id].active_ul_harq_sfn_slot == -1,
|
|
"We did not send an active CRC when we should have!\n");
|
|
mac->nr_ue_emul_l1.harq[crc_ind->crc_list[j].harq_id].active_ul_harq_sfn_slot = NFAPI_SFNSLOT2HEX(crc_ind->sfn, crc_ind->slot);
|
|
LOG_D(NR_MAC, "This is sched sfn/sl [%d %d] and crc sfn/sl [%d %d] with mcs_index in ul_cqi -> %d\n",
|
|
scheduled_response->frame, scheduled_response->slot, crc_ind->sfn, crc_ind->slot,pusch_config_pdu->mcs_index);
|
|
}
|
|
|
|
if (!put_queue(&nr_rx_ind_queue, rx_ind))
|
|
{
|
|
LOG_E(NR_MAC, "Put_queue failed for rx_ind\n");
|
|
for (int i = 0; i < rx_ind->number_of_pdus; i++)
|
|
{
|
|
free(rx_ind->pdu_list[i].pdu);
|
|
rx_ind->pdu_list[i].pdu = NULL;
|
|
}
|
|
|
|
free(rx_ind->pdu_list);
|
|
rx_ind->pdu_list = NULL;
|
|
free(rx_ind);
|
|
rx_ind = NULL;
|
|
}
|
|
if (!put_queue(&nr_crc_ind_queue, crc_ind))
|
|
{
|
|
LOG_E(NR_MAC, "Put_queue failed for crc_ind\n");
|
|
free(crc_ind->crc_list);
|
|
crc_ind->crc_list = NULL;
|
|
free(crc_ind);
|
|
crc_ind = NULL;
|
|
}
|
|
|
|
LOG_D(PHY, "In %s: Filled queue rx/crc_ind which was filled by ulconfig. \n", __FUNCTION__);
|
|
|
|
scheduled_response->tx_request->number_of_pdus = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FAPI_NR_UL_CONFIG_TYPE_PUCCH:
|
|
{
|
|
nfapi_nr_uci_indication_t *uci_ind = CALLOC(1, sizeof(*uci_ind));
|
|
uci_ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION;
|
|
uci_ind->sfn = scheduled_response->frame;
|
|
uci_ind->slot = scheduled_response->slot;
|
|
uci_ind->num_ucis = 1;
|
|
uci_ind->uci_list = CALLOC(uci_ind->num_ucis, sizeof(*uci_ind->uci_list));
|
|
for (int j = 0; j < uci_ind->num_ucis; j++)
|
|
{
|
|
LOG_D(NR_MAC, "ul_config->ul_config_list[%d].pucch_config_pdu.n_bit = %d\n", i, ul_config->ul_config_list[i].pucch_config_pdu.n_bit);
|
|
if (ul_config->ul_config_list[i].pucch_config_pdu.n_bit > 3 && mac->nr_ue_emul_l1.num_csi_reports > 0)
|
|
{
|
|
uci_ind->uci_list[j].pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE;
|
|
uci_ind->uci_list[j].pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t);
|
|
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu_2_3_4 = &uci_ind->uci_list[j].pucch_pdu_format_2_3_4;
|
|
fill_uci_2_3_4(pdu_2_3_4, &ul_config->ul_config_list[i].pucch_config_pdu);
|
|
}
|
|
else
|
|
{
|
|
nfapi_nr_uci_pucch_pdu_format_0_1_t *pdu_0_1 = &uci_ind->uci_list[j].pucch_pdu_format_0_1;
|
|
uci_ind->uci_list[j].pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE;
|
|
uci_ind->uci_list[j].pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t);
|
|
memset(pdu_0_1, 0, sizeof(*pdu_0_1));
|
|
pdu_0_1->handle = 0;
|
|
pdu_0_1->rnti = ul_config->ul_config_list[i].pucch_config_pdu.rnti;
|
|
pdu_0_1->pucch_format = 1;
|
|
pdu_0_1->ul_cqi = 255;
|
|
pdu_0_1->timing_advance = 0;
|
|
pdu_0_1->rssi = 0;
|
|
|
|
if (mac->nr_ue_emul_l1.num_harqs > 0) {
|
|
int harq_index = 0;
|
|
pdu_0_1->pduBitmap = 2; // (value->pduBitmap >> 1) & 0x01) == HARQ and (value->pduBitmap) & 0x01) == SR
|
|
pdu_0_1->harq = CALLOC(1, sizeof(*pdu_0_1->harq));
|
|
pdu_0_1->harq->num_harq = mac->nr_ue_emul_l1.num_harqs;
|
|
pdu_0_1->harq->harq_confidence_level = 0;
|
|
pdu_0_1->harq->harq_list = CALLOC(pdu_0_1->harq->num_harq, sizeof(*pdu_0_1->harq->harq_list));
|
|
int harq_pid = -1;
|
|
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++)
|
|
{
|
|
if (mac->nr_ue_emul_l1.harq[k].active &&
|
|
mac->nr_ue_emul_l1.harq[k].active_dl_harq_sfn == uci_ind->sfn &&
|
|
mac->nr_ue_emul_l1.harq[k].active_dl_harq_slot == uci_ind->slot)
|
|
{
|
|
mac->nr_ue_emul_l1.harq[k].active = false;
|
|
harq_pid = k;
|
|
AssertFatal(harq_index < pdu_0_1->harq->num_harq, "Invalid harq_index %d\n", harq_index);
|
|
pdu_0_1->harq->harq_list[harq_index].harq_value = !mac->dl_harq_info[k].ack;
|
|
harq_index++;
|
|
}
|
|
}
|
|
AssertFatal(harq_pid != -1, "No active harq_pid, sfn_slot = %u.%u", uci_ind->sfn, uci_ind->slot);
|
|
}
|
|
}
|
|
}
|
|
|
|
LOG_D(NR_PHY, "Sending UCI with %d PDUs in sfn.slot %d/%d\n",
|
|
uci_ind->num_ucis, uci_ind->sfn, uci_ind->slot);
|
|
NR_UL_IND_t ul_info = {
|
|
.uci_ind = *uci_ind,
|
|
};
|
|
send_nsa_standalone_msg(&ul_info, uci_ind->header.message_id);
|
|
free_uci_inds(uci_ind);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
LOG_W(NR_MAC, "Unknown ul_config->pdu_type %d\n", pdu_type);
|
|
break;
|
|
}
|
|
}
|
|
scheduled_response->ul_config->number_pdus = 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void configure_dlsch(NR_UE_DLSCH_t *dlsch0,
|
|
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu,
|
|
module_id_t module_id,
|
|
int rnti) {
|
|
|
|
const uint8_t current_harq_pid = dlsch_config_pdu->harq_process_nbr;
|
|
dlsch0->current_harq_pid = current_harq_pid;
|
|
dlsch0->active = 1;
|
|
dlsch0->rnti = rnti;
|
|
|
|
LOG_D(PHY,"current_harq_pid = %d\n", current_harq_pid);
|
|
|
|
NR_DL_UE_HARQ_t *dlsch0_harq = dlsch0->harq_processes[current_harq_pid];
|
|
AssertFatal(dlsch0_harq, "no harq_process for HARQ PID %d\n", current_harq_pid);
|
|
|
|
dlsch0_harq->BWPStart = dlsch_config_pdu->BWPStart;
|
|
dlsch0_harq->BWPSize = dlsch_config_pdu->BWPSize;
|
|
dlsch0_harq->nb_rb = dlsch_config_pdu->number_rbs;
|
|
dlsch0_harq->start_rb = dlsch_config_pdu->start_rb;
|
|
dlsch0_harq->nb_symbols = dlsch_config_pdu->number_symbols;
|
|
dlsch0_harq->start_symbol = dlsch_config_pdu->start_symbol;
|
|
dlsch0_harq->dlDmrsSymbPos = dlsch_config_pdu->dlDmrsSymbPos;
|
|
dlsch0_harq->dmrsConfigType = dlsch_config_pdu->dmrsConfigType;
|
|
dlsch0_harq->n_dmrs_cdm_groups = dlsch_config_pdu->n_dmrs_cdm_groups;
|
|
dlsch0_harq->dmrs_ports = dlsch_config_pdu->dmrs_ports;
|
|
dlsch0_harq->mcs = dlsch_config_pdu->mcs;
|
|
dlsch0_harq->rvidx = dlsch_config_pdu->rv;
|
|
dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH;
|
|
dlsch0_harq->R = dlsch_config_pdu->targetCodeRate;
|
|
dlsch0_harq->Qm = dlsch_config_pdu->qamModOrder;
|
|
dlsch0_harq->TBS = dlsch_config_pdu->TBS;
|
|
dlsch0_harq->tbslbrm = dlsch_config_pdu->tbslbrm;
|
|
dlsch0_harq->nscid = dlsch_config_pdu->nscid;
|
|
dlsch0_harq->dlDmrsScramblingId = dlsch_config_pdu->dlDmrsScramblingId;
|
|
//get nrOfLayers from DCI info
|
|
uint8_t Nl = 0;
|
|
for (int i = 0; i < 12; i++) { // max 12 ports
|
|
if ((dlsch_config_pdu->dmrs_ports>>i)&0x01) Nl += 1;
|
|
}
|
|
dlsch0_harq->Nl = Nl;
|
|
dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table;
|
|
downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch_config_pdu->rv, dlsch0->rnti_type);
|
|
if (dlsch0_harq->status != ACTIVE) {
|
|
// dlsch0_harq->status not ACTIVE due to false retransmission
|
|
// Reset the following flag to skip PDSCH procedures in that case and retrasmit harq status
|
|
dlsch0->active = 0;
|
|
update_harq_status(module_id,dlsch0->current_harq_pid,dlsch0_harq->ack);
|
|
}
|
|
/* PTRS */
|
|
dlsch0_harq->PTRSFreqDensity = dlsch_config_pdu->PTRSFreqDensity;
|
|
dlsch0_harq->PTRSTimeDensity = dlsch_config_pdu->PTRSTimeDensity;
|
|
dlsch0_harq->PTRSPortIndex = dlsch_config_pdu->PTRSPortIndex;
|
|
dlsch0_harq->nEpreRatioOfPDSCHToPTRS = dlsch_config_pdu->nEpreRatioOfPDSCHToPTRS;
|
|
dlsch0_harq->PTRSReOffset = dlsch_config_pdu->PTRSReOffset;
|
|
dlsch0_harq->pduBitmap = dlsch_config_pdu->pduBitmap;
|
|
LOG_D(MAC, ">>>> \tdlsch0->g_pucch = %d\tdlsch0_harq.mcs = %d\n", dlsch0->g_pucch, dlsch0_harq->mcs);
|
|
}
|
|
|
|
|
|
int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
|
|
|
|
bool found = false;
|
|
if(scheduled_response != NULL){
|
|
|
|
module_id_t module_id = scheduled_response->module_id;
|
|
uint8_t cc_id = scheduled_response->CC_id;
|
|
int slot = scheduled_response->slot;
|
|
|
|
// Note: we have to handle the thread IDs for this. To be revisited completely.
|
|
NR_UE_DLSCH_t *dlsch0 = NULL;
|
|
NR_UE_ULSCH_t *ulsch = PHY_vars_UE_g[module_id][cc_id]->ulsch[0];
|
|
NR_UE_PUCCH *pucch_vars = &((nr_phy_data_t *)scheduled_response->phy_data)->pucch_vars;
|
|
NR_UE_CSI_IM *csiim_vars = PHY_vars_UE_g[module_id][cc_id]->csiim_vars[0];
|
|
NR_UE_CSI_RS *csirs_vars = PHY_vars_UE_g[module_id][cc_id]->csirs_vars[0];
|
|
NR_UE_PDCCH_CONFIG *phy_pdcch_config = NULL;
|
|
|
|
if(scheduled_response->dl_config != NULL){
|
|
fapi_nr_dl_config_request_t *dl_config = scheduled_response->dl_config;
|
|
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu;
|
|
fapi_nr_dl_config_dci_dl_pdu_rel15_t *pdcch_config;
|
|
fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu;
|
|
fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu;
|
|
|
|
for (int i = 0; i < dl_config->number_pdus; ++i){
|
|
AssertFatal(dl_config->number_pdus < FAPI_NR_DL_CONFIG_LIST_NUM,"dl_config->number_pdus %d out of bounds\n",dl_config->number_pdus);
|
|
AssertFatal(dl_config->dl_config_list[i].pdu_type<=FAPI_NR_DL_CONFIG_TYPES,"pdu_type %d > 2\n",dl_config->dl_config_list[i].pdu_type);
|
|
LOG_D(PHY, "In %s: frame %d slot %d received 1 DL %s PDU of %d total DL PDUs:\n",
|
|
__FUNCTION__, scheduled_response->frame, slot, dl_pdu_type[dl_config->dl_config_list[i].pdu_type - 1], dl_config->number_pdus);
|
|
|
|
switch(dl_config->dl_config_list[i].pdu_type) {
|
|
case FAPI_NR_DL_CONFIG_TYPE_DCI:
|
|
if (NULL == phy_pdcch_config) {
|
|
phy_pdcch_config = (NR_UE_PDCCH_CONFIG *)scheduled_response->phy_data;
|
|
phy_pdcch_config->nb_search_space = 0;
|
|
}
|
|
pdcch_config = &dl_config->dl_config_list[i].dci_config_pdu.dci_config_rel15;
|
|
memcpy((void*)&phy_pdcch_config->pdcch_config[phy_pdcch_config->nb_search_space],(void*)pdcch_config,sizeof(*pdcch_config));
|
|
phy_pdcch_config->nb_search_space = phy_pdcch_config->nb_search_space + 1;
|
|
phy_pdcch_config->sfn = scheduled_response->frame;
|
|
phy_pdcch_config->slot = slot;
|
|
LOG_D(PHY,"Number of DCI SearchSpaces %d\n",phy_pdcch_config->nb_search_space);
|
|
break;
|
|
case FAPI_NR_DL_CONFIG_TYPE_CSI_IM:
|
|
csiim_config_pdu = &dl_config->dl_config_list[i].csiim_config_pdu.csiim_config_rel15;
|
|
memcpy((void*)&(csiim_vars->csiim_config_pdu), (void*)csiim_config_pdu, sizeof(fapi_nr_dl_config_csiim_pdu_rel15_t));
|
|
csiim_vars->active = true;
|
|
break;
|
|
case FAPI_NR_DL_CONFIG_TYPE_CSI_RS:
|
|
csirs_config_pdu = &dl_config->dl_config_list[i].csirs_config_pdu.csirs_config_rel15;
|
|
memcpy((void*)&(csirs_vars->csirs_config_pdu), (void*)csirs_config_pdu, sizeof(fapi_nr_dl_config_csirs_pdu_rel15_t));
|
|
csirs_vars->active = true;
|
|
break;
|
|
case FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH:
|
|
dlsch_config_pdu = &dl_config->dl_config_list[i].dlsch_config_pdu.dlsch_config_rel15;
|
|
dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch_ra[0];
|
|
dlsch0->rnti_type = _RA_RNTI_;
|
|
dlsch0->harq_processes[dlsch_config_pdu->harq_process_nbr]->status = ACTIVE;
|
|
configure_dlsch(dlsch0, dlsch_config_pdu, module_id,
|
|
dl_config->dl_config_list[i].dlsch_config_pdu.rnti);
|
|
break;
|
|
case FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH:
|
|
dlsch_config_pdu = &dl_config->dl_config_list[i].dlsch_config_pdu.dlsch_config_rel15;
|
|
dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch_SI[0];
|
|
dlsch0->rnti_type = _SI_RNTI_;
|
|
dlsch0->harq_processes[dlsch_config_pdu->harq_process_nbr]->status = ACTIVE;
|
|
configure_dlsch(dlsch0, dlsch_config_pdu, module_id,
|
|
dl_config->dl_config_list[i].dlsch_config_pdu.rnti);
|
|
break;
|
|
case FAPI_NR_DL_CONFIG_TYPE_DLSCH:
|
|
dlsch_config_pdu = &dl_config->dl_config_list[i].dlsch_config_pdu.dlsch_config_rel15;
|
|
dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch[0][0];
|
|
configure_dlsch(dlsch0, dlsch_config_pdu, module_id,
|
|
dl_config->dl_config_list[i].dlsch_config_pdu.rnti);
|
|
break;
|
|
}
|
|
}
|
|
dl_config->number_pdus = 0;
|
|
}
|
|
|
|
if (scheduled_response->ul_config != NULL){
|
|
|
|
fapi_nr_ul_config_request_t *ul_config = scheduled_response->ul_config;
|
|
int pdu_done = 0;
|
|
pthread_mutex_lock(&ul_config->mutex_ul_config);
|
|
|
|
LOG_D(PHY, "%d.%d ul S ul_config %p pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_done, ul_config->number_pdus);
|
|
for (int i = 0; i < ul_config->number_pdus; ++i){
|
|
|
|
AssertFatal(ul_config->ul_config_list[i].pdu_type <= FAPI_NR_UL_CONFIG_TYPES,"pdu_type %d out of bounds\n",ul_config->ul_config_list[i].pdu_type);
|
|
LOG_D(PHY, "In %s i %d: processing %s PDU of %d total UL PDUs (ul_config %p) \n", __FUNCTION__, i, ul_pdu_type[ul_config->ul_config_list[i].pdu_type - 1], ul_config->number_pdus, ul_config);
|
|
|
|
uint8_t pdu_type = ul_config->ul_config_list[i].pdu_type, current_harq_pid, gNB_id = 0;
|
|
/* PRACH */
|
|
//NR_PRACH_RESOURCES_t *prach_resources;
|
|
fapi_nr_ul_config_prach_pdu *prach_config_pdu;
|
|
/* PUSCH */
|
|
nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu;
|
|
/* PUCCH */
|
|
fapi_nr_ul_config_pucch_pdu *pucch_config_pdu;
|
|
LOG_D(PHY, "%d.%d ul B ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus);
|
|
/* SRS */
|
|
fapi_nr_ul_config_srs_pdu *srs_config_pdu;
|
|
|
|
switch (pdu_type){
|
|
|
|
case (FAPI_NR_UL_CONFIG_TYPE_PUSCH):
|
|
// pusch config pdu
|
|
pusch_config_pdu = &ul_config->ul_config_list[i].pusch_config_pdu;
|
|
current_harq_pid = pusch_config_pdu->pusch_data.harq_process_id;
|
|
NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch->harq_processes[current_harq_pid];
|
|
|
|
if (harq_process_ul_ue){
|
|
|
|
nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &harq_process_ul_ue->pusch_pdu;
|
|
|
|
LOG_D(PHY, "In %s i %d: copy pusch_config_pdu nrOfLayers:%d, num_dmrs_cdm_grps_no_data:%d \n", __FUNCTION__, i, pusch_config_pdu->nrOfLayers,pusch_config_pdu->num_dmrs_cdm_grps_no_data);
|
|
|
|
memcpy(pusch_pdu, pusch_config_pdu, sizeof(nfapi_nr_ue_pusch_pdu_t));
|
|
|
|
ulsch->f_pusch = pusch_config_pdu->absolute_delta_PUSCH;
|
|
|
|
if (scheduled_response->tx_request) {
|
|
for (int j=0; j<scheduled_response->tx_request->number_of_pdus; j++) {
|
|
fapi_nr_tx_request_body_t *tx_req_body = &scheduled_response->tx_request->tx_request_body[j];
|
|
if ((tx_req_body->pdu_index == i) && (tx_req_body->pdu_length > 0)) {
|
|
LOG_D(PHY,"%d.%d Copying %d bytes to harq_process_ul_ue->a (harq_pid %d)\n",scheduled_response->frame,slot,tx_req_body->pdu_length,current_harq_pid);
|
|
memcpy(harq_process_ul_ue->a, tx_req_body->pdu, tx_req_body->pdu_length);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
harq_process_ul_ue->status = ACTIVE;
|
|
ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
|
|
pdu_done++;
|
|
LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus);
|
|
|
|
} else {
|
|
|
|
LOG_E(PHY, "[phy_procedures_nrUE_TX] harq_process_ul_ue is NULL !!\n");
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case (FAPI_NR_UL_CONFIG_TYPE_PUCCH):
|
|
found = false;
|
|
pucch_config_pdu = &ul_config->ul_config_list[i].pucch_config_pdu;
|
|
for(int j=0; j<2; j++) {
|
|
if(pucch_vars->active[j] == false) {
|
|
LOG_D(PHY,"%d.%d Copying pucch pdu to UE PHY\n",scheduled_response->frame,slot);
|
|
memcpy((void*)&(pucch_vars->pucch_pdu[j]), (void*)pucch_config_pdu, sizeof(fapi_nr_ul_config_pucch_pdu));
|
|
pucch_vars->active[j] = true;
|
|
found = true;
|
|
ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
|
|
pdu_done++;
|
|
LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus);
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
LOG_E(PHY, "Couldn't find allocation for PUCCH PDU in PUCCH VARS\n");
|
|
break;
|
|
|
|
case (FAPI_NR_UL_CONFIG_TYPE_PRACH):
|
|
// prach config pdu
|
|
prach_config_pdu = &ul_config->ul_config_list[i].prach_config_pdu;
|
|
memcpy((void*)&(PHY_vars_UE_g[module_id][cc_id]->prach_vars[gNB_id]->prach_pdu), (void*)prach_config_pdu, sizeof(fapi_nr_ul_config_prach_pdu));
|
|
ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
|
|
pdu_done++;
|
|
LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus);
|
|
break;
|
|
|
|
case (FAPI_NR_UL_CONFIG_TYPE_DONE):
|
|
pdu_done++; // count the no of pdu processed
|
|
LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus);
|
|
break;
|
|
|
|
case (FAPI_NR_UL_CONFIG_TYPE_SRS):
|
|
// srs config pdu
|
|
srs_config_pdu = &ul_config->ul_config_list[i].srs_config_pdu;
|
|
memcpy((void*)&(PHY_vars_UE_g[module_id][cc_id]->srs_vars[gNB_id]->srs_config_pdu), (void*)srs_config_pdu, sizeof(fapi_nr_ul_config_srs_pdu));
|
|
PHY_vars_UE_g[module_id][cc_id]->srs_vars[gNB_id]->active = true;
|
|
ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
|
|
pdu_done++;
|
|
break;
|
|
|
|
default:
|
|
ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
|
|
pdu_done++; // count the no of pdu processed
|
|
LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//Clear the fields when all the config pdu are done
|
|
if (pdu_done == ul_config->number_pdus) {
|
|
if (scheduled_response->tx_request)
|
|
scheduled_response->tx_request->number_of_pdus = 0;
|
|
ul_config->sfn = 0;
|
|
ul_config->slot = 0;
|
|
ul_config->number_pdus = 0;
|
|
LOG_D(PHY, "%d.%d clear ul_config %p\n", scheduled_response->frame, slot, ul_config);
|
|
memset(ul_config->ul_config_list, 0, sizeof(ul_config->ul_config_list));
|
|
}
|
|
|
|
pthread_mutex_unlock(&ul_config->mutex_ul_config);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config){
|
|
|
|
fapi_nr_config_request_t *nrUE_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config;
|
|
|
|
if(phy_config != NULL) {
|
|
memcpy(nrUE_config,&phy_config->config_req,sizeof(fapi_nr_config_request_t));
|
|
if (PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->UE_mode[0] == NOT_SYNCHED)
|
|
PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->UE_mode[0] = PRACH;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|