Files
openairinterface5g/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c
T

1215 lines
52 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
*/
/************************************************************************
*
* MODULE : PUCCH Packed Uplink Control Channel for UE NR
* PUCCH is used to transmit Uplink Control Information UCI
* which is composed of:
* - SR Scheduling Request
* - HARQ ACK/NACK
* - CSI Channel State Information
* UCI can also be transmitted on a PUSCH if it schedules.
*
* DESCRIPTION : functions related to PUCCH UCI management
* TS 38.213 9 UE procedure for reporting control information
*
**************************************************************************/
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
#include "PHY/defs_nr_UE.h"
#ifndef NO_RAT_NR
#include "SCHED_NR_UE/harq_nr.h"
#include "SCHED_NR_UE/pucch_power_control_ue_nr.h"
#define DEFINE_VARIABLES_PUCCH_UE_NR_H
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
#undef DEFINE_VARIABLES_PUCCH_UE_NR_H
#endif
int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe);
uint8_t is_cqi_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id);
uint8_t is_ri_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id);
/*
void nr_generate_pucch0(int32_t **txdataF,
NR_DL_FRAME_PARMS *frame_parms,
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
int16_t amp,
int nr_tti_tx,
uint8_t mcs,
uint8_t nrofSymbols,
uint8_t startingSymbolIndex,
uint16_t startingPRB);
void nr_generate_pucch1(int32_t **txdataF,
NR_DL_FRAME_PARMS *frame_parms,
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
uint64_t payload,
int16_t amp,
int nr_tti_tx,
uint8_t nrofSymbols,
uint8_t startingSymbolIndex,
uint16_t startingPRB,
uint16_t startingPRB_intraSlotHopping,
uint8_t timeDomainOCC,
uint8_t nr_bit);
void nr_generate_pucch2(int32_t **txdataF,
NR_DL_FRAME_PARMS *frame_parms,
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
uint64_t payload,
int16_t amp,
int nr_tti_tx,
uint8_t nrofSymbols,
uint8_t startingSymbolIndex,
uint8_t nrofPRB,
uint16_t startingPRB,
uint8_t nr_bit);
void nr_generate_pucch3_4(int32_t **txdataF,
NR_DL_FRAME_PARMS *frame_parms,
pucch_format_nr_t fmt,
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
uint64_t payload,
int16_t amp,
int nr_tti_tx,
uint8_t nrofSymbols,
uint8_t startingSymbolIndex,
uint8_t nrofPRB,
uint16_t startingPRB,
uint8_t nr_bit,
uint8_t occ_length_format4,
uint8_t occ_index_format4);
*/
/**************** variables **************************************/
/**************** functions **************************************/
//extern uint8_t is_cqi_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id);
//extern uint8_t is_ri_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id);
/*******************************************************************
*
* NAME : pucch_procedures_ue_nr
*
* PARAMETERS : ue context
* processing slots of reception/transmission
* gNB_id identifier
*
* RETURN : bool TRUE PUCCH will be transmitted
* FALSE No PUCCH to transmit
*
* DESCRIPTION : determines UCI (uplink Control Information) payload
* and PUCCH format and its parameters.
* PUCCH is no transmitted if:
* - there is no valid data to transmit
* - Pucch parameters are not valid
*
* Below information is scanned in order to know what information should be transmitted to network.
*
* (SR Scheduling Request) (HARQ ACK/NACK) (CSI Channel State Information)
* | | - CQI Channel Quality Indicator
* | | - RI Rank Indicator
* | | - PMI Primary Matrux Indicator
* | | - LI Layer Indicator
* | | - L1-RSRP
* | | - CSI-RS resource idicator
* | V |
* +-------------------- -> + <------------------
* |
* +--------------------------------+
* | UCI Uplink Control Information |
* +--------------------------------+
* V PUCCH Configuration
* +----------------------------------------+ +--------------------------+
* | Determine PUCCH payload and its | | PUCCH Resource Set |
* +----------------------------------------+ | PUCCH Resource |
* V | Format parameters |
* +-----------------------------------------+ | |
* | Select PUCCH format with its parameters | <----------------+--------------------------+
* +-----------------------------------------+
* V
* +-----------------+
* | Generate PUCCH |
* +-----------------+
*
* TS 38.213 9 UE procedure for reporting control information
*
*********************************************************************/
bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, bool reset_harq)
{
uint8_t sr_payload = 0;
uint32_t pucch_ack_payload = 0; /* maximum number of bits for pucch payload is supposed to be 32 */
uint64_t pucch_payload = 0;
uint32_t csi_payload = 0;
int frame_tx = proc->frame_tx;
int nr_tti_tx = proc->nr_tti_tx;
int Mod_id = ue->Mod_id;
int CC_id = ue->CC_id;
int O_SR = 0;
int O_ACK = 0;
int O_CSI = 0; /* channel state information */
int N_UCI = 0; /* size in bits for Uplink Control Information */
int cqi_status = 0;
int ri_status = 0;
int csi_status = 0;
int initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE;
int pucch_resource_set = MAX_NB_OF_PUCCH_RESOURCE_SETS;
int pucch_resource_id = MAX_NB_OF_PUCCH_RESOURCES;
int pucch_resource_indicator = MAX_PUCCH_RESOURCE_INDICATOR;
int n_HARQ_ACK;
/* update current context */
int subframe_number = (proc->nr_tti_rx)/(ue->frame_parms.ttis_per_subframe);
nb_pucch_format_4_in_subframes[subframe_number] = 0; /* reset pucch format 4 counter at current rx position */
int dl_harq_pid = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid;
if (dl_harq_pid < ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->number_harq_processes_for_pdsch) {
/* pucch indicator can be reseted in function get_downlink_ack so it should be get now */
pucch_resource_indicator = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[dl_harq_pid]->harq_ack.pucch_resource_indicator;
}
/* Part - I
* Collect feedback that should be transmitted at this nr_tti_tx :
* - ACK/NACK, SR, CSI (CQI, RI, ...)
*/
sr_payload = 0;
if (trigger_periodic_scheduling_request( ue, gNB_id, proc ) == 1) {
O_SR = 1; /* sr should be transmitted */
if (ue->mac_enabled == 1) {
/* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */
sr_payload = nr_ue_get_SR(Mod_id,
CC_id,
frame_tx,
gNB_id,
ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][gNB_id]->crnti,
nr_tti_tx); // nr_tti_rx used for meas gap
}
else {
sr_payload = 1;
}
}
O_ACK = get_downlink_ack( ue, gNB_id, proc, &pucch_ack_payload,
&n_HARQ_ACK, reset_harq); // 1 to reset ACK/NACK status : 0 otherwise
cqi_status = ((ue->cqi_report_config[gNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0) &&
(is_cqi_TXOp(ue,proc,gNB_id) == 1));
ri_status = ((ue->cqi_report_config[gNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) &&
(is_ri_TXOp(ue,proc,gNB_id) == 1));
csi_status = get_csi_nr(ue, gNB_id, &csi_payload);
O_CSI = cqi_status + ri_status + csi_status;
/* Part - II */
/* if payload is empty or only negative SR -> no pucch transmission */
if(O_ACK == 0) {
N_UCI = O_SR + O_CSI;
if ((N_UCI == 0) || ((O_CSI == 0) && (sr_payload == 0))) { /* TS 38.213 9.2.4 UE procedure for reporting SR */
NR_TST_PHY_PRINTF("PUCCH No feedback AbsSubframe %d.%d \n", frame_tx%1024, nr_tti_tx);
LOG_D(PHY,"PUCCH No feedback AbsSubframe %d.%d \n", frame_tx%1024, nr_tti_tx);
return (FALSE);
}
else {
/* a resource set and a resource should be find according to payload size */
pucch_resource_set = find_pucch_resource_set( ue, gNB_id, N_UCI);
if (pucch_resource_set != MAX_NB_OF_PUCCH_RESOURCE_SETS) {
pucch_resource_indicator = 0;
pucch_resource_id = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set]->pucch_resource_id[pucch_resource_indicator]; /* get the first resource of the set */
}
else {
LOG_W(PHY,"PUCCH no resource set found for CSI at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
O_CSI = 0;
csi_payload = 0;
}
if (O_CSI == 0) {
/* only SR has to be send */
/* in this case there is no DCI related to PUCCH parameters so pucch resource should be get from sr configuration */
/* TS 38.213 9.2.4 UE procedure for reporting SR */
pucch_resource_set = 0; /* force it to a valid value */
if (ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[ue->scheduling_request_config_nr[gNB_id].active_sr_id] != NULL) {
pucch_resource_id = ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[ue->scheduling_request_config_nr[gNB_id].active_sr_id]->resource;
}
else {
LOG_E(PHY,"PUCCH No scheduling request configuration : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return(FALSE);
}
}
}
}
else {
N_UCI = O_SR + O_ACK + O_CSI;
}
/* Part - III */
/* Choice PUCCH format and its related parameters */
pucch_format_nr_t format = pucch_format0_nr;
uint8_t starting_symbol_index;
uint8_t nb_symbols_total = 0;
uint8_t nb_symbols = 0;
uint16_t starting_prb = 0;; /* it can be considered as first hop on case of pucch hopping */
uint16_t second_hop = 0; /* second part for pucch for hopping */
uint8_t nb_of_prbs = 0;
int m_0 = 0; /* format 0 only */
int m_CS = 0; /* for all format except for format 0 */
int index_additional_dmrs = I_PUCCH_NO_ADDITIONAL_DMRS;
int index_hopping = I_PUCCH_NO_HOPPING;
int time_domain_occ = 0;
int occ_length = 0;
int occ_Index = 0;
NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[dl_harq_pid]->harq_ack;
if (select_pucch_resource(ue, gNB_id, N_UCI, pucch_resource_indicator, &initial_pucch_id, &pucch_resource_set,
&pucch_resource_id, harq_status) == TRUE) {
/* use of initial pucch configuration provided by system information 1 */
/***********************************************************************/
if (initial_pucch_id != NB_INITIAL_PUCCH_RESOURCE) {
format = initial_pucch_resource[initial_pucch_id].format;
starting_symbol_index = initial_pucch_resource[initial_pucch_id].startingSymbolIndex;
nb_symbols_total = initial_pucch_resource[initial_pucch_id].nrofSymbols;
int N_CS = initial_pucch_resource[initial_pucch_id].nb_CS_indexes;
/* see TS 38213 Table 9.2.1-1: PUCCH resource sets before dedicated PUCCH resource configuration */
int RB_BWP_offset;
if (initial_pucch_id == 15) {
RB_BWP_offset = ue->systemInformationBlockType1_nr.N_BWP_SIZE/4;
}
else
{
RB_BWP_offset = initial_pucch_resource[initial_pucch_id].PRB_offset;
}
if (initial_pucch_id/8 == 0) {
starting_prb = RB_BWP_offset + (initial_pucch_id/N_CS);
second_hop = ue->systemInformationBlockType1_nr.N_BWP_SIZE - 1 - RB_BWP_offset - (initial_pucch_id/N_CS);
m_0 = initial_pucch_resource[initial_pucch_id].initial_CS_indexes[initial_pucch_id%N_CS];
}
else if (initial_pucch_id/8 == 1)
{
starting_prb = RB_BWP_offset + (initial_pucch_id/N_CS);
second_hop = ue->systemInformationBlockType1_nr.N_BWP_SIZE - 1 - RB_BWP_offset - ((initial_pucch_id - 8)/N_CS);
m_0 = initial_pucch_resource[initial_pucch_id].initial_CS_indexes[(initial_pucch_id - 8)%N_CS];
}
if ((ue->UE_mode[gNB_id] != PUSCH) && (O_ACK > 1)) {
O_ACK = 1;
pucch_ack_payload &= 0x1; /* take only first ack */
LOG_W(PHY,"PUCCH ue is not expected to generate more than one HARQ-ACK at AbsSubframe %d.%d \n", frame_tx%1024, nr_tti_tx);
}
NR_TST_PHY_PRINTF("PUCCH common configuration with index %d \n", initial_pucch_id);
}
/* use dedicated pucch resource configuration */
/**********************************************/
else if ((pucch_resource_set != MAX_NB_OF_PUCCH_RESOURCE_SETS) && (pucch_resource_id != MAX_NB_OF_PUCCH_RESOURCES)) {
/* check that current configuration is supported */
if ((ue->cell_group_config.physicalCellGroupConfig.harq_ACK_SpatialBundlingPUCCH != FALSE)
|| (ue->cell_group_config.physicalCellGroupConfig.pdsch_HARQ_ACK_Codebook != dynamic)) {
LOG_E(PHY,"PUCCH Unsupported cell group configuration : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return(FALSE);
}
else if (ue->PDSCH_ServingCellConfig.codeBlockGroupTransmission != NULL) {
LOG_E(PHY,"PUCCH Unsupported code block group for serving cell config : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return(FALSE);
}
format = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.format;
nb_symbols_total = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.nrofSymbols;
starting_symbol_index = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.startingSymbolIndex;
starting_prb = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->startingPRB;
second_hop = starting_prb;
time_domain_occ = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.timeDomainOCC; /* format 1 only */
occ_length = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.occ_length; /* format 4 only */
occ_Index = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.occ_Index; /* format 4 only */
if ((format == pucch_format0_nr) || (format == pucch_format1_nr)) {
m_0 = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.initialCyclicShift;
}
else if ((format == pucch_format3_nr) || (format == pucch_format4_nr)) {
if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1]->additionalDMRS == enable_feature) {
index_additional_dmrs = I_PUCCH_ADDITIONAL_DMRS;
}
if (ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->intraSlotFrequencyHopping == feature_enabled) {
index_hopping = I_PUCCH_HOPING;
}
}
NR_TST_PHY_PRINTF("PUCCH dedicated configuration with resource index %d \n", pucch_resource_id);
}
}
else {
LOG_W(PHY,"PUCCH No PUCCH resource found at AbsSubframe %d.%d \n", frame_tx%1024, nr_tti_tx);
return (FALSE);
}
int max_code_rate = 0;
int Q_m = BITS_PER_SYMBOL_QPSK; /* default pucch modulation type is QPSK with 2 bits per symbol */
int N_sc_ctrl_RB = 0;
int O_CRC = 0;
nb_symbols = nb_symbols_total; /* by default, it can be reduced due to symbols reserved for dmrs */
switch(format) {
case pucch_format0_nr:
{
nb_of_prbs = 1;
N_sc_ctrl_RB = N_SC_RB;
break;
}
case pucch_format1_nr:
{
nb_of_prbs = 1;
N_sc_ctrl_RB = N_SC_RB;
break;
}
case pucch_format2_nr:
{
nb_of_prbs = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.nrofPRBs;
N_sc_ctrl_RB = N_SC_RB - 4;
break;
}
case pucch_format3_nr:
{
nb_of_prbs = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.nrofPRBs;
if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1]->pi2PBSK == feature_enabled) {
Q_m = BITS_PER_SYMBOL_BPSK; /* set bpsk modulation type with 1 bit per modulation symbol */
}
N_sc_ctrl_RB = N_SC_RB;
nb_symbols = nb_symbols_excluding_dmrs[nb_symbols_total-4][index_additional_dmrs][index_hopping];
break;
}
case pucch_format4_nr:
{
if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1]->pi2PBSK == feature_enabled) {
Q_m = BITS_PER_SYMBOL_BPSK; /* set bpsk modulation type with 1 bit per modulation symbol */
}
nb_symbols = nb_symbols_excluding_dmrs[nb_symbols_total-4][index_additional_dmrs][index_hopping];
nb_of_prbs = 1;
subframe_number = nr_tti_tx/(ue->frame_parms.ttis_per_subframe);
nb_pucch_format_4_in_subframes[subframe_number]++; /* increment number of transmit pucch 4 in current subframe */
NR_TST_PHY_PRINTF("PUCCH Number of pucch format 4 in subframe %d is %d \n", subframe_number, nb_pucch_format_4_in_subframes[subframe_number]);
N_sc_ctrl_RB = N_SC_RB/(nb_pucch_format_4_in_subframes[subframe_number]);
break;
}
}
/* TS 38.213 9.2.5.2 UE procedure for multiplexing HARQ-ACK/SR and CSI */
/* drop CSI report if simultaneous HARQ-ACK/SR and periodic/semi-periodic CSI cannot be transmitted at the same time */
if (format != pucch_format0_nr) {
if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1] != NULL) {
max_code_rate = code_rate_r_time_100[ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1]->maxCodeRate]; /* it is code rate * 10 */
if ((O_ACK != 0) && (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1]->simultaneousHARQ_ACK_CSI == disable_feature)) {
N_UCI = N_UCI - O_CSI;
O_CSI = cqi_status = ri_status = 0;
csi_payload = 0; /* csi should be dropped in this case */
}
}
/* TS 38.212 6.3.1.2 Code block segmentation and CRC attachment */
/* crc attachment can be done depending of payload size */
if (N_UCI < 11) {
O_CRC = 0; /* no additional crc bits */
}
else if ((N_UCI >= 12) && (N_UCI <= 19)) {
O_CRC = 6; /* number of additional crc bits */
}
else if (N_UCI >= 20) {
O_CRC = 11; /* number of additional crc bits */
}
N_UCI = N_UCI + O_CRC;
/* for format 2 and 3, number of prb should be adjusted to minimum value which cope to information size */
if (nb_of_prbs > 1 ) {
int nb_prb_min = 0;
int payload_in_bits;
do {
nb_prb_min++;
payload_in_bits = (nb_prb_min * N_sc_ctrl_RB * nb_symbols * Q_m * max_code_rate)/100; /* code rate has been multiplied by 100 */
NR_TST_PHY_PRINTF("PUCCH Adjust number of prb : (N_UCI : %d ) (payload_in_bits : %d) (N_sc_ctrl_RB : %d) (nb_symbols : %d) (Q_m : %d) (max_code_rate*100 : %d) \n",
N_UCI, payload_in_bits, N_sc_ctrl_RB, nb_symbols, Q_m, max_code_rate);
} while (N_UCI > payload_in_bits);
if (nb_prb_min > nb_of_prbs) {
LOG_E(PHY,"PUCCH Number of prbs too small for current pucch bits to transmit : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
else {
nb_of_prbs = nb_prb_min;
}
}
/* TS 38.213 9.2.4 for a positive SR transmission, payload b(0) = 0 */
if ((O_SR == 1) && (format == pucch_format1_nr)) {
sr_payload = 0;
}
}
else { /* only format 0 here */
if ((O_SR == 0) && (O_CSI == 0)) { /* only ack is transmitted TS 36.213 9.2.3 UE procedure for reporting HARQ-ACK */
if (O_ACK == 1) {
m_CS = sequence_cyclic_shift_1_harq_ack_bit[pucch_ack_payload & 0x1]; /* only harq of 1 bit */
}
else {
m_CS = sequence_cyclic_shift_2_harq_ack_bits[pucch_ack_payload & 0x3]; /* only harq with 2 bits */
}
}
else if ((O_SR == 1) && (O_CSI == 0)) { /* SR + eventually ack are transmitted TS 36.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR */
if (sr_payload == 1) { /* positive scheduling request */
if (O_ACK == 1) {
m_CS = 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) {
m_CS = sequence_cyclic_shift_2_harq_ack_bits_positive_sr[pucch_ack_payload & 0x3]; /* positive SR and harq with 2 bits */
}
else {
m_CS = 0; /* only positive SR */
}
}
}
N_UCI = O_SR = O_ACK = 0;
pucch_payload = sr_payload = pucch_ack_payload = 0; /* no data for format 0 */
}
/* TS 38.212 6.3.1 Uplink control information on PUCCH */
/* information concatenation of payload */
/* CSI SR HARQ-ACK */
/* bit order of payload of size n : a(n)....................................a(0) */
/* a(0) is the LSB and a(n) the MSB <--------><--------------><------------><----------> */
/* O_CRC O_CSI O_SR O_ACK */
/* */
/* remark: crc is not part of payload, it is later added by block coding. */
if (N_UCI > (sizeof(uint64_t)*8)) {
LOG_E(PHY,"PUCCH number of UCI bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return(0);
}
pucch_payload = pucch_payload | (csi_payload << (O_ACK + O_SR)) | (sr_payload << O_ACK) | pucch_ack_payload;
NR_TST_PHY_PRINTF("PUCCH ( AbsSubframe : %d.%d ) ( total payload size %d data 0x%02x ) ( ack length %d data 0x%02x ) ( sr length %d value %d ) ( csi length %d data : 0x%02x ) \n",
frame_tx%1024, nr_tti_tx, N_UCI, pucch_payload, O_ACK, pucch_ack_payload, O_SR, sr_payload, csi_status, csi_payload);
NR_TST_PHY_PRINTF("PUCCH ( format : %d ) ( modulation : %s ) ( nb prb : %d ) ( nb symbols total: %d ) ( nb symbols : %d ) ( max code rate*100 : %d ) ( starting_symbol_index : %d ) \n",
format, (Q_m == BITS_PER_SYMBOL_QPSK ? " QPSK " : " BPSK "), nb_of_prbs, nb_symbols_total, nb_symbols, max_code_rate, starting_symbol_index);
NR_TST_PHY_PRINTF("PUCCH ( starting_prb : %d ) ( second_hop : %d ) ( m_0 : %d ) ( m_CS : %d ) ( time_domain_occ %d ) (occ_length : %d ) ( occ_Index : %d ) \n",
starting_prb, second_hop, m_0, m_CS, time_domain_occ, occ_length, occ_Index);
/* Part - IV */
/* Generate PUCCH signal according to its format and parameters */
ue->generate_ul_signal[gNB_id] = 1;
int16_t pucch_tx_power = get_pucch_tx_power_ue( ue, gNB_id, proc, format,
nb_of_prbs, N_sc_ctrl_RB, nb_symbols, N_UCI, O_SR, O_CSI, O_ACK,
O_CRC, n_HARQ_ACK);
/* set tx power */
ue->tx_power_dBm[nr_tti_tx] = pucch_tx_power;
ue->tx_total_RE[nr_tti_tx] = nb_of_prbs*N_SC_RB;
int tx_amp;
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)
tx_amp = get_tx_amp(pucch_tx_power,
ue->tx_power_max_dBm,
ue->frame_parms.N_RB_UL,
nb_of_prbs);
#else
tx_amp = AMP;
#endif
switch(format) {
case pucch_format0_nr:
{
nr_generate_pucch0(ue,ue->common_vars.txdataF,
&ue->frame_parms,
&ue->pucch_config_dedicated_nr[gNB_id],
tx_amp,
nr_tti_tx,
(uint8_t)m_0,
(uint8_t)m_CS,
nb_symbols_total,
starting_symbol_index,
starting_prb);
break;
}
case pucch_format1_nr:
{
nr_generate_pucch1(ue,ue->common_vars.txdataF,
&ue->frame_parms,
&ue->pucch_config_dedicated_nr[gNB_id],
pucch_payload,
tx_amp,
nr_tti_tx,
(uint8_t)m_0,
nb_symbols_total,
starting_symbol_index,
starting_prb,
second_hop,
(uint8_t)time_domain_occ,
(uint8_t)N_UCI);
break;
}
case pucch_format2_nr:
{
nr_generate_pucch2(ue,
ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][gNB_id]->crnti,
ue->common_vars.txdataF,
&ue->frame_parms,
&ue->pucch_config_dedicated_nr[gNB_id],
pucch_payload,
tx_amp,
nr_tti_tx,
nb_symbols_total,
starting_symbol_index,
nb_of_prbs,
starting_prb,
(uint8_t)N_UCI);
break;
}
case pucch_format3_nr:
case pucch_format4_nr:
{
nr_generate_pucch3_4(ue,
ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][gNB_id]->crnti,
ue->common_vars.txdataF,
&ue->frame_parms,
format,
&ue->pucch_config_dedicated_nr[gNB_id],
pucch_payload,
tx_amp,
nr_tti_tx,
nb_symbols_total,
starting_symbol_index,
nb_of_prbs,
starting_prb,
second_hop,
(uint8_t)N_UCI,
(uint8_t)occ_length,
(uint8_t)occ_Index);
break;
}
}
return (TRUE);
}
/*******************************************************************
*
* 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(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc,
uint32_t *o_ACK, int *n_HARQ_ACK,
bool do_reset) // 1 to reset ACK/NACK status : 0 otherwise
{
NR_UE_HARQ_STATUS_t *harq_status;
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;
int number_pid_dl = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->number_harq_processes_for_pdsch;
bool two_transport_blocks = FALSE;
int number_of_code_word = 1;
int U_DAI_c = 0;
int N_m_c_rx = 0;
int V_DAI_m_DL = 0;
if (ue->PDSCH_Config.maxNrofCodeWordsScheduledByDCI == nb_code_n2) {
two_transport_blocks = TRUE;
number_of_code_word = 2;
}
else {
number_of_code_word = 1;
}
if (ue->n_connected_eNB > 1) {
LOG_E(PHY,"PUCCH ACK feedback is not implemented for mutiple gNB cells : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (0);
}
/* 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 < number_pid_dl; dl_harq_pid++) {
harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->harq_processes[dl_harq_pid]->harq_ack;
/* check if current tx slot should transmit downlink acknowlegment */
if (harq_status->slot_for_feedback_ack == proc->nr_tti_tx) {
if (harq_status->ack == DL_ACKNACK_NO_SET) {
LOG_E(PHY,"PUCCH Downlink acknowledgment has not been set : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (0);
}
else if (harq_status->vDAI_DL == DL_DAI_NO_SET) {
LOG_E(PHY,"PUCCH Downlink DAI has not been set : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (0);
}
else if (harq_status->vDAI_DL > NR_DL_MAX_DAI) {
LOG_E(PHY,"PUCCH Downlink DAI has an invalid value : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (0);
}
else if (harq_status->send_harq_status == 0) {
LOG_E(PHY,"PUCCH Downlink ack can not be transmitted : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return(0);
}
else {
dai_current = harq_status->vDAI_DL;
if (dai_current == 0) {
LOG_E(PHY,"PUCCH Downlink dai is invalid : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return(0);
} else if (dai_current > dai_max) {
dai_max = dai_current;
}
number_harq_feedback++;
ack_data[code_word][dai_current - 1] = harq_status->ack;
dai[code_word][dai_current - 1] = dai_current;
}
}
if (do_reset == TRUE) {
init_downlink_harq_status(&ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->harq_processes[dl_harq_pid]);
}
}
}
/* no any ack to transmit */
if (number_harq_feedback == 0) {
*n_HARQ_ACK = 0;
return(0);
}
else if (number_harq_feedback > (sizeof(uint32_t)*8)) {
LOG_E(PHY,"PUCCH number of ack bits exceeds payload size : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
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 */
if (ue->cell_group_config.physicalCellGroupConfig.harq_ACK_SpatialBundlingPUCCH == FALSE) {
int N_TB_max_DL = ue->PDSCH_Config.maxNrofCodeWordsScheduledByDCI;
*n_HARQ_ACK = (((V_DAI_m_DL - U_DAI_c)%4) * N_TB_max_DL) + N_m_c_rx + N_SPS_c;
NR_TST_PHY_PRINTF("PUCCH power n(%d) = ( V(%d) - U(%d) )mod4 * N_TB(%d) + N(%d) \n", *n_HARQ_ACK, V_DAI_m_DL, U_DAI_c, N_TB_max_DL, N_m_c_rx);
}
/*
* 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
* if spatial bundling is not applied (HARQ-ACK-spatial-bundling-PUCCH = FALSE) and generates HARQ-ACK value of ACK for the second
* 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++;
}
if (two_transport_blocks == TRUE) {
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;
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);
}
if (two_transport_blocks == TRUE) {
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);
}
if (V_temp2 < V_temp) {
j = j + 1;
}
if (two_transport_blocks == TRUE) {
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) {
LOG_E(PHY,"PUCCH Error for number of bits for acknowledgment : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (0);
}
return(number_harq_feedback);
}
/*******************************************************************
*
* NAME : select_pucch_format
*
* PARAMETERS : ue context
* processing slots of reception/transmission
* gNB_id identifier
*
* RETURN : TRUE a valid resource has been found
*
* 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
*
*********************************************************************/
boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size, int pucch_resource_indicator,
int *initial_pucch_id, int *resource_set_id, int *resource_id, NR_UE_HARQ_STATUS_t *harq_status)
{
boolean_t resource_set_found = FALSE;
int nb_symbols_for_tx = 0;
int current_resource_id = MAX_NB_OF_PUCCH_RESOURCES;
pucch_format_nr_t format_pucch;
int ready_pucch_resource_id = FALSE; /* in the case that it is already given */
/* ini values to unset */
*initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE;
//*resource_set_id = MAX_NB_OF_PUCCH_RESOURCE_SETS;
//*resource_id = MAX_NB_OF_PUCCH_RESOURCES;
if (ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[0] == NULL) {
/* No resource set has been already configured so pucch_configCommon from Sib1 should be used in this case */
if (ue->UE_mode[gNB_id] != PUSCH) {
*initial_pucch_id = ue->pucch_config_common_nr[gNB_id].pucch_ResourceCommon;
if (*initial_pucch_id >= NB_INITIAL_PUCCH_RESOURCE) {
LOG_E(PHY,"PUCCH Invalid initial resource index : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
*initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE;
return (FALSE);
}
}
else {
/* see TS 38.213 9.2.1 PUCCH Resource Sets */
int delta_PRI = harq_status->pucch_resource_indicator;
// n_CCE can be obtained from ue->dci_ind.dci_list[i].n_CCE. FIXME!!!
// N_CCE can be obtained from ue->dci_ind.dci_list[i].N_CCE. FIXME!!!
//int n_CCE = ue->dci_ind.dci_list[0].n_CCE;
//int N_CCE = ue->dci_ind.dci_list[0].N_CCE;
int n_CCE_0 = harq_status->n_CCE;
int N_CCE_0 = harq_status->N_CCE;
if (N_CCE_0 == 0) {
LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
int r_PUCCH = ((2 * n_CCE_0)/N_CCE_0) + (2 * delta_PRI);
*initial_pucch_id = r_PUCCH;
}
nb_symbols_for_tx = initial_pucch_resource[*initial_pucch_id].nrofSymbols;
format_pucch = initial_pucch_resource[*initial_pucch_id].format;
if (check_pucch_format(ue, gNB_id, format_pucch, nb_symbols_for_tx, uci_size) == TRUE) {
return (TRUE);
}
else {
LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
}
else {
/* dedicated resources have been configured */
int pucch_resource_set_id = 0;
if (*resource_set_id == MAX_NB_OF_PUCCH_RESOURCE_SETS) {
/* 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 */
pucch_resource_set_id = find_pucch_resource_set( ue, gNB_id, uci_size);
if (pucch_resource_set_id != MAX_NB_OF_PUCCH_RESOURCE_SETS) {
resource_set_found = TRUE;
}
}
else {
/* a valid resource has already be found outside this function */
resource_set_found = TRUE;
ready_pucch_resource_id = TRUE;
pucch_resource_indicator = pucch_resource_indicator;
}
if (resource_set_found == TRUE) {
if (pucch_resource_indicator < MAX_PUCCH_RESOURCE_INDICATOR) {
/* check if resource indexing by pucch_resource_indicator of this set is compatible */
if ((ready_pucch_resource_id == TRUE) || (ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set_id]->pucch_resource_id[pucch_resource_indicator] != MAX_NB_OF_PUCCH_RESOURCES)) {
if (ready_pucch_resource_id == TRUE) {
current_resource_id = *resource_id;
}
else {
int R_PUCCH = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set_id]->first_resources_set_R_PUCCH;
/* is it the first resource and its size exceeds 8 */
if ((pucch_resource_set_id == 0)
&& (R_PUCCH > MAX_NB_OF_PUCCH_RESOURCES_PER_SET_NOT_0)) {
/* see TS 38.213 9.2.3 UE procedure for reporting HARQ-ACK */
int delta_PRI = pucch_resource_indicator;
int n_CCE_p = harq_status->n_CCE;
int N_CCE_p = harq_status->N_CCE;
int r_PUCCH;
if (N_CCE_p == 0) {
LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
if (pucch_resource_set_id < (R_PUCCH%8)) {
r_PUCCH = ((n_CCE_p * (R_PUCCH/8))/N_CCE_p) + (delta_PRI*(R_PUCCH/8));
}
else {
r_PUCCH = ((n_CCE_p * (R_PUCCH/8))/N_CCE_p) + (delta_PRI*(R_PUCCH/8)) + (R_PUCCH%8);
}
current_resource_id = r_PUCCH;
}
else {
current_resource_id = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set_id]->pucch_resource_id[pucch_resource_indicator];
}
}
if (ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[current_resource_id] != NULL) {
nb_symbols_for_tx = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[current_resource_id]->format_parameters.nrofSymbols;
format_pucch = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[current_resource_id]->format_parameters.format;
if (check_pucch_format(ue, gNB_id, format_pucch, nb_symbols_for_tx, uci_size) == TRUE) {
*resource_set_id = pucch_resource_set_id;
*resource_id = current_resource_id;
return (TRUE);
}
else {
LOG_E(PHY,"PUCCH Found format no compatible with payload size and symbol length : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
}
}
else {
LOG_E(PHY,"PUCCH Undefined Resource related to pucch resource indicator: at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
}
else {
LOG_E(PHY,"PUCCH Invalid pucch resource indicator: at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
}
/* check that a resource has been found */
if (*resource_set_id == MAX_NB_OF_PUCCH_RESOURCES) {
LOG_E(PHY,"PUCCH No compatible pucch format found : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
}
return (FALSE);
}
/*******************************************************************
*
* 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(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size)
{
int pucch_resource_set_id = 0;
/* 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) {
if (ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set_id] != NULL) {
if (uci_size <= ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set_id]->maxPayloadMinus1 + 1) {
NR_TST_PHY_PRINTF("PUCCH found resource set %d \n", pucch_resource_set_id);
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 : check_pucch_format
*
* PARAMETERS : ue context
* processing slots of reception/transmission
* 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
*
*********************************************************************/
boolean_t check_pucch_format(PHY_VARS_NR_UE *ue, uint8_t gNB_id, pucch_format_nr_t format_pucch, int nb_symbols_for_tx, int uci_size)
{
pucch_format_nr_t selected_pucch_format;
pucch_format_nr_t selected_pucch_format_second;
if (format_pucch != pucch_format0_nr) {
if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format_pucch-1] != NULL) {
if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format_pucch-1]->nrofSlots != 1) {
LOG_E(PHY,"PUCCH not implemented multislots transmission : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
}
}
if (nb_symbols_for_tx <= 2) {
if (uci_size <= 2) {
selected_pucch_format = pucch_format0_nr;
selected_pucch_format_second = selected_pucch_format;
}
else {
selected_pucch_format = pucch_format2_nr;
selected_pucch_format_second = selected_pucch_format;
}
}
else {
if (nb_symbols_for_tx >= 4) {
if (uci_size <= 2) {
selected_pucch_format = pucch_format1_nr;
selected_pucch_format_second = selected_pucch_format;
}
else {
selected_pucch_format = pucch_format3_nr; /* in this case choice can be done between two formats */
selected_pucch_format_second = pucch_format4_nr;
}
}
else {
LOG_D(PHY,"PUCCH Undefined PUCCH format : set PUCCH to format 4 : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
}
NR_TST_PHY_PRINTF("PUCCH format %d nb symbols total %d uci size %d selected format %d \n", format_pucch, nb_symbols_for_tx, uci_size, selected_pucch_format);
if (format_pucch != selected_pucch_format) {
if (format_pucch != selected_pucch_format_second) {
NR_TST_PHY_PRINTF("PUCCH mismatched of selected format: at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
LOG_D(PHY,"PUCCH format mismatched of selected format: at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (FALSE);
}
else {
return (TRUE);
}
}
else {
return (TRUE);
}
}
/*******************************************************************
*
* NAME : trigger_periodic_scheduling_request
*
* PARAMETERS : pointer to resource set
*
* RETURN : 1 if peridic scheduling request is triggered
* 0 no periodic scheduling request
*
* DESCRIPTION : TS 38.213 9.2.4 UE procedure for reporting SR
*
*********************************************************************/
int trigger_periodic_scheduling_request(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc)
{
const int max_sr_periodicity[NB_NUMEROLOGIES_NR] = { 80, 160, 320, 640, 640 };
int active_scheduling_request = ue->scheduling_request_config_nr[gNB_id].active_sr_id;
/* is there any valid scheduling request configuration */
if (ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request] == NULL) {
return (0);
}
if (ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request]->periodicity < 2) {
LOG_W(PHY,"PUCCH Not supported scheduling request period smaller than 1 slot : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (0);
}
int16_t SR_periodicity = scheduling_request_periodicity[ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request]->periodicity];
uint16_t SR_offset = ue->scheduling_request_config_nr[gNB_id].sr_ResourceConfig[active_scheduling_request]->offset;
if (SR_periodicity > max_sr_periodicity[ue->frame_parms.numerology_index]) {
LOG_W(PHY,"PUCCH Invalid scheduling request period : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME);
return (0);
}
if (SR_offset > SR_periodicity) {
LOG_E(PHY,"PUCCH SR offset %d is greater than SR periodicity %d : at line %d in function %s of file %s \n", SR_offset, SR_periodicity, LINE_FILE , __func__, FILE_NAME);
return (0);
}
else if (SR_periodicity == 1) {
return (1); /* period is slot */
}
int16_t N_slot_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME * ue->frame_parms.ttis_per_subframe;
if (((proc->frame_tx * N_slot_frame) + proc->nr_tti_tx - SR_offset)%SR_periodicity == 0) {
return (1);
}
else {
return (0);
}
}
/*******************************************************************
*
* NAME : get_csi_nr
* PARAMETERS : ue context
* processing slots of reception/transmission
* gNB_id identifier
*
* RETURN : size of csi payload
*
* DESCRIPTION : CSI management is not already implemented
* so it has been simulated thank to two functions:
* - set_csi_nr
* - get_csi_nr
*
*********************************************************************/
int dummy_csi_status = 0;
uint32_t dummy_csi_payload = 0;
/* FFS TODO_NR code that should be developed */
int get_csi_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint32_t *csi_payload)
{
VOID_PARAMETER ue;
VOID_PARAMETER gNB_id;
if (dummy_csi_status == 0) {
*csi_payload = 0;
}
else {
*csi_payload = dummy_csi_payload;
}
return (dummy_csi_status);
}
/* FFS TODO_NR code that should be removed */
void set_csi_nr(int csi_status, uint32_t csi_payload)
{
dummy_csi_status = csi_status;
if (dummy_csi_status == 0) {
dummy_csi_payload = 0;
}
else {
dummy_csi_payload = csi_payload;
}
}