Commit cff21926 authored by Francesco Mani's avatar Francesco Mani

Merge branch 'nr_pucch' into NR_RRC_harq

parents bb3883bf 57a612c5
......@@ -1516,6 +1516,7 @@ set(PHY_SRC_UE
${PHY_SMALLBLOCKSRC}
${PHY_NR_CODINGIF}
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/pucch_rx.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_uci_tools_common.c
)
set(PHY_NR_UE_SRC
${OPENAIR1_DIR}/PHY/INIT/nr_parms.c
......@@ -1539,6 +1540,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_tools_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pucch_nr.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_uci_tools_common.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c
......
......@@ -963,12 +963,12 @@ void init_gNB(int single_thread_flag,int wait_for_sync) {
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
LOG_I(PHY,"Setting indication lists\n");
gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = gNB->rx_pdu_list;
/*gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = gNB->rx_pdu_list;
gNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = gNB->crc_pdu_list;
gNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = gNB->sr_pdu_list;
gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list;
gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list;
gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;
gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;*/
gNB->prach_energy_counter = 0;
}
......
......@@ -19,6 +19,7 @@
#define NFAPI_MAX_NUM_UL_UE_PER_GROUP 6
#define NFAPI_MAX_NUM_UL_PDU 8
#define NFAPI_MAX_NUM_UCI_INDICATION 8
#define NFAPI_MAX_NUM_GROUPS 8
#define NFAPI_MAX_NUM_CB 8
......@@ -1519,8 +1520,8 @@ typedef struct
uint8_t ul_cqi;
uint16_t timing_advance;
uint16_t rssi;
nfapi_nr_sr_pdu_0_1_t sr;//67
nfapi_nr_harq_pdu_0_1_t harq;//68
nfapi_nr_sr_pdu_0_1_t *sr;//67
nfapi_nr_harq_pdu_0_1_t *harq;//68
}nfapi_nr_uci_pucch_pdu_format_0_1_t;
......@@ -1542,28 +1543,22 @@ typedef struct
}nfapi_nr_uci_pucch_pdu_format_2_3_4_t;
//for SR, HARQ and CSI Part 1/ 2 PDUs
typedef struct
{
nfapi_nr_uci_pusch_pdu_t* pusch_pdu;
nfapi_nr_uci_pucch_pdu_format_0_1_t* pucch_pdu_format_0_1;
nfapi_nr_uci_pucch_pdu_format_2_3_4_t* pucch_pdu_format_2_3_4;
nfapi_nr_sr_pdu_0_1_t* sr_pdu_0_1;
nfapi_nr_sr_pdu_2_3_4_t* sr_pdu_2_3_4;
nfapi_nr_harq_pdu_0_1_t* harq_pdu_0_1;
nfapi_nr_harq_pdu_2_3_4_t* harq_pdu_2_3_4;
nfapi_nr_csi_part1_pdu_t* csi_part1_pdu;
nfapi_nr_csi_part2_pdu_t* csi_part2_pdu;
} nfapi_nr_uci_pdu_information_t;
typedef enum {
NFAPI_NR_UCI_PDCCH_PDU_TYPE = 0,
NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE = 1,
NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE = 2,
} nfapi_nr_uci_pdu_type_e;
typedef struct
{
uint16_t pdu_type;
uint16_t pdu_type; // 0 for PDU on PUSCH, 1 for PUCCH format 0 or 1, 2 for PUCCH format 2 to 4
uint16_t pdu_size;
nfapi_nr_uci_pdu_information_t uci_pdu;
union
{
nfapi_nr_uci_pusch_pdu_t pusch_pdu;
nfapi_nr_uci_pucch_pdu_format_0_1_t pucch_pdu_format_0_1;
nfapi_nr_uci_pucch_pdu_format_2_3_4_t pucch_pdu_format_2_3_4;
};
} nfapi_nr_uci_t;
typedef struct
......@@ -1571,7 +1566,7 @@ typedef struct
uint16_t sfn;
uint16_t slot;
uint16_t num_ucis;
nfapi_nr_uci_t* uci_list;
nfapi_nr_uci_t uci_list[NFAPI_MAX_NUM_UCI_INDICATION];
} nfapi_nr_uci_indication_t;
......
......@@ -123,4 +123,26 @@ void rx_nr_prach_ru(RU_t *ru,
int frame,
int subframe);
void nr_decode_pucch1(int32_t **rxdataF,
pucch_GroupHopping_t pucch_GroupHopping,
uint32_t n_id, // hoppingID higher layer parameter
uint64_t *payload,
NR_DL_FRAME_PARMS *frame_parms,
int16_t amp,
int nr_tti_tx,
uint8_t m0,
uint8_t nrofSymbols,
uint8_t startingSymbolIndex,
uint16_t startingPRB,
uint16_t startingPRB_intraSlotHopping,
uint8_t timeDomainOCC,
uint8_t nr_bit);
void nr_decode_pucch0(int32_t **rxdataF,
NR_DL_FRAME_PARMS *frame_parms,
int slot,
nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu,
nfapi_nr_pucch_pdu_t* pucch_pdu);
#endif /*__NR_TRANSPORT__H__*/
......@@ -41,7 +41,19 @@
#define NR_PUSCH_y 3 // UCI placeholder bit
void nr_group_sequence_hopping(pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id,
uint8_t n_hop,
int nr_tti_tx,
uint8_t *u,
uint8_t *v);
double nr_cyclic_shift_hopping(uint32_t n_id,
uint8_t m0,
uint8_t mcs,
uint8_t lnormal,
uint8_t lprime,
int nr_tti_tx);
/** \brief Computes available bits G. */
......
/*
* 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 PHY/NR_TRANSPORT/nr_dci_tools_common.c
* \brief
* \author
* \date 2020
* \version 0.1
* \company Eurecom
* \email:
* \note
* \warning
*/
#include "nr_dci.h"
void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id,
uint8_t n_hop,
int nr_tti_tx,
uint8_t *u,
uint8_t *v) {
/*
* Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping
* The following variables are set by higher layers:
* - PUCCH_GroupHopping:
* - n_id: higher-layer parameter hoppingId
* - n_hop: frequency hopping index
* if intra-slot frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping
* n_hop=0
* if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping
* n_hop=0 for the first hop
* n_hop=1 for the second hop
*/
// depending on the value of the PUCCH_GroupHopping, we will obtain different values for u,v
//pucch_GroupHopping_t PUCCH_GroupHopping = ue->pucch_config_common_nr->pucch_GroupHopping; // from higher layers FIXME!!!
// n_id defined as per TS 38.211 subclause 6.3.2.2.1 (is given by the higher-layer parameter hoppingId)
// it is hoppingId from PUCCH-ConfigCommon:
// Cell-Specific scrambling ID for group hoppping and sequence hopping if enabled
// Corresponds to L1 parameter 'HoppingID' (see 38.211, section 6.3.2.2) BIT STRING (SIZE (10))
//uint16_t n_id = ue->pucch_config_common_nr->hoppingId; // from higher layers FIXME!!!
#ifdef DEBUG_NR_PUCCH_TX
printf("\t\t [nr_group_sequence_hopping] PUCCH_GroupHopping=%u, n_id=%u \n",PUCCH_GroupHopping,n_id);
#endif
uint8_t f_ss=0,f_gh=0;
*u=0;
*v=0;
uint32_t c_init = 0;
uint32_t x1,s; // TS 38.211 Subclause 5.2.1
int l = 32, minShift = ((2*nr_tti_tx+n_hop)<<3);
int tmpShift =0;
#ifdef DEBUG_NR_PUCCH_TX
printf("\t\t [nr_group_sequence_hopping] calculating u,v -> ");
#endif
if (PUCCH_GroupHopping == neither) { // PUCCH_GroupHopping 'neither'
f_ss = n_id%30;
}
if (PUCCH_GroupHopping == enable) { // PUCCH_GroupHopping 'enabled'
c_init = floor(n_id/30); // we initialize c_init to calculate u,v according to 6.3.2.2.1 of 38.211
s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
for (int m=0; m<8; m++) {
while(minShift >= l) {
s = lte_gold_generic(&x1, &c_init, 0);
l = l+32;
}
tmpShift = (minShift&((1<<5)-1)); //minShift%32;
f_gh = f_gh + ((1<<m)*((uint8_t)((s>>tmpShift)&1)));
minShift ++;
}
f_gh = f_gh%30;
f_ss = n_id%30;
/* for (int m=0; m<8; m++){
f_gh = f_gh + ((1<<m)*((uint8_t)((s>>(8*(2*nr_tti_tx+n_hop)+m))&1))); // Not sure we have to use nr_tti_tx FIXME!!!
}
f_gh = f_gh%30;
f_ss = n_id%30;*/
}
if (PUCCH_GroupHopping == disable) { // PUCCH_GroupHopping 'disabled'
c_init = (1<<5)*floor(n_id/30)+(n_id%30); // we initialize c_init to calculate u,v
s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
f_ss = n_id%30;
l = 32, minShift = (2*nr_tti_tx+n_hop);
while(minShift >= l) {
s = lte_gold_generic(&x1, &c_init, 0);
l = l+32;
}
tmpShift = (minShift&((1<<5)-1)); //minShift%32;
*v = (uint8_t)((s>>tmpShift)&1);
// *v = (uint8_t)((s>>(2*nr_tti_tx+n_hop))&1); // Not sure we have to use nr_tti_tx FIXME!!!
}
*u = (f_gh+f_ss)%30;
#ifdef DEBUG_NR_PUCCH_TX
printf("%d,%d\n",*u,*v);
#endif
}
double nr_cyclic_shift_hopping(uint32_t n_id,
uint8_t m0,
uint8_t mcs,
uint8_t lnormal,
uint8_t lprime,
int nr_tti_tx) {
/*
* Implements TS 38.211 subclause 6.3.2.2.2 Cyclic shift hopping
* - n_id: higher-layer parameter hoppingId
* - m0: provided by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift of PUCCH-F0-resource-config
* - mcs: mcs=0 except for PUCCH format 0 when it depends on information to be transmitted according to TS 38.213 subclause 9.2
* - lnormal: lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission
* - lprime: lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
*/
// alpha_init initialized to 2*PI/12=0.5235987756
double alpha = 0.5235987756;
uint32_t c_init = n_id; // we initialize c_init again to calculate n_cs
uint32_t x1,s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
uint8_t n_cs=0;
int l = 32, minShift = (14*8*nr_tti_tx )+ 8*(lnormal+lprime);
int tmpShift =0;
#ifdef DEBUG_NR_PUCCH_TX
printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%u -> \n",c_init);
#endif
for (int m=0; m<8; m++) {
while(minShift >= l) {
s = lte_gold_generic(&x1, &c_init, 0);
l = l+32;
}
tmpShift = (minShift&((1<<5)-1)); //minShift%32;
minShift ++;
n_cs = n_cs+((1<<m)*((uint8_t)((s>>tmpShift)&1)));
// calculating n_cs (Not sure we have to use nr_tti_tx FIXME!!!)
// n_cs = n_cs+((1<<m)*((uint8_t)((s>>((14*8*nr_tti_tx) + 8*(lnormal+lprime) + m))&1)));
}
alpha = (alpha * (double)((m0+mcs+n_cs)%12));
#ifdef DEBUG_NR_PUCCH_TX
printf("n_cs=%d -> %lf\n",n_cs,alpha);
#endif
return(alpha);
}
......@@ -10,35 +10,32 @@
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/NR_TRANSPORT/nr_transport.h"
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "T.h"
void nr_decode_pucch0( int32_t **rxdataF,
pucch_GroupHopping_t pucch_GroupHopping,
uint32_t n_id, // hoppingID higher layer parameter
uint64_t *payload,
void nr_decode_pucch0(int32_t **rxdataF,
NR_DL_FRAME_PARMS *frame_parms,
int16_t amp,
int nr_tti_tx,
uint8_t m0, // should come from resource set
uint8_t nrofSymbols, // should come from resource set
uint8_t startingSymbolIndex, // should come from resource set
uint16_t startingPRB, // should come from resource set
uint8_t nr_bit) { // is number of UCI bits to be decoded
int slot,
nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu,
nfapi_nr_pucch_pdu_t* pucch_pdu) {
int nr_sequences;
const uint8_t *mcs;
if(nr_bit==1){
pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
if(pucch_pdu->bit_len_harq==1){
mcs=table1_mcs;
nr_sequences=4;
nr_sequences=4>>(1-pucch_pdu->sr_flag);
}
else{
mcs=table2_mcs;
nr_sequences=8;
nr_sequences=8>>(1-pucch_pdu->sr_flag);
}
/*
* Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation
......@@ -53,8 +50,6 @@ void nr_decode_pucch0( int32_t **rxdataF,
//uint8_t lnormal;
// lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
//uint8_t lprime;
// mcs is provided by TC 38.213 subclauses 9.2.3, 9.2.4, 9.2.5 FIXME!
//uint8_t mcs;
/*
* in TS 38.213 Subclause 9.2.1 it is said that:
......@@ -73,26 +68,24 @@ void nr_decode_pucch0( int32_t **rxdataF,
// if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping
// n_hop = 0 for first hop
// n_hop = 1 for second hop
uint8_t n_hop = 0;
//uint8_t PUCCH_Frequency_Hopping; // from higher layers FIXME!!
uint8_t n_hop = 0; // Frequnecy hopping not implemented FIXME!!
// x_n contains the sequence r_u_v_alpha_delta(n)
int16_t x_n_re[nr_sequences][24],x_n_im[nr_sequences][24];
int n,i,l;
for(i=0;i<nr_sequences;i++){
// we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2
for (l=0; l<nrofSymbols; l++){
// if frequency hopping is enabled n_hop = 1 for second hop. Not sure frequency hopping concerns format 0. FIXME!!!
// if ((PUCCH_Frequency_Hopping == 1)&&(l == (nrofSymbols-1))) n_hop = 1;
nr_group_sequence_hopping(pucch_GroupHopping,n_id,n_hop,nr_tti_tx,&u,&v); // calculating u and v value
alpha = nr_cyclic_shift_hopping(n_id,m0,mcs[i],l,startingSymbolIndex,nr_tti_tx);
for (l=0; l<pucch_pdu->nr_of_symbols; l++){
nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,n_hop,slot,&u,&v); // calculating u and v value
alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,pucch_pdu->initial_cyclic_shift,mcs[i],l,pucch_pdu->start_symbol_index,slot);
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u,v,alpha,l);
#endif
for (n=0; n<12; n++){
x_n_re[i][(12*l)+n] = (int16_t)((int32_t)(amp)*(int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)
x_n_re[i][(12*l)+n] = (int16_t)((int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)
- (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)))>>15); // Re part of base sequence shifted by alpha
x_n_im[i][(12*l)+n] =(int16_t)((int32_t)(amp)* (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)
x_n_im[i][(12*l)+n] =(int16_t)((int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)
+ (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)))>>15); // Im part of base sequence shifted by alpha
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d,%d)\n",
......@@ -103,38 +96,31 @@ void nr_decode_pucch0( int32_t **rxdataF,
}
int16_t r_re[24],r_im[24];
/*
* Implementing TS 38.211 Subclause 6.3.2.3.2 Mapping to physical resources FIXME!
* Implementing TS 38.211 Subclause 6.3.2.3.2 Mapping to physical resources
*/
uint32_t re_offset=0;
for (l=0; l<nrofSymbols; l++) {
if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
}
if ((startingPRB >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1)));
}
if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
}
if ((startingPRB > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6;
}
if ((startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
}
uint8_t l2;
for (l=0; l<pucch_pdu->nr_of_symbols; l++) {
l2 = l+pucch_pdu->start_symbol_index;
re_offset = (12*pucch_pdu->prb_start) + frame_parms->first_carrier_offset;
if (re_offset>= frame_parms->ofdm_symbol_size)
re_offset-=frame_parms->ofdm_symbol_size;
for (n=0; n<12; n++){
if ((n==6) && (startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) {
// if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB)
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size);
}
r_re[(12*l)+n]=((int16_t *)&rxdataF[0][re_offset])[0];
r_im[(12*l)+n]=((int16_t *)&rxdataF[0][re_offset])[1];
r_re[(12*l)+n]=((int16_t *)&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset])[0];
r_im[(12*l)+n]=((int16_t *)&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset])[1];
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,re_offset,
l,n,((int16_t *)&rxdataF[0][re_offset])[0],((int16_t *)&rxdataF[0][re_offset])[1]);
printf("\t [nr_generate_pucch0] mapping to RE \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n",
frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,(l2*frame_parms->ofdm_symbol_size)+re_offset,
l,n,((int16_t *)&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset])[0],
((int16_t *)&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset])[1]);
#endif
re_offset++;
if (re_offset>= frame_parms->ofdm_symbol_size)
re_offset-=frame_parms->ofdm_symbol_size;
}
}
double corr[nr_sequences],corr_re[nr_sequences],corr_im[nr_sequences];
......@@ -142,7 +128,7 @@ void nr_decode_pucch0( int32_t **rxdataF,
memset(corr_re,0,nr_sequences*sizeof(double));
memset(corr_im,0,nr_sequences*sizeof(double));
for(i=0;i<nr_sequences;i++){
for(l=0;l<nrofSymbols;l++){
for(l=0;l<pucch_pdu->nr_of_symbols;l++){
for(n=0;n<12;n++){
corr_re[i]+= (double)(r_re[12*l+n])/32767*(double)(x_n_re[i][12*l+n])/32767+(double)(r_im[12*l+n])/32767*(double)(x_n_im[i][12*l+n])/32767;
corr_im[i]+= (double)(r_re[12*l+n])/32767*(double)(x_n_im[i][12*l+n])/32767-(double)(r_im[12*l+n])/32767*(double)(x_n_re[i][12*l+n])/32767;
......@@ -151,14 +137,35 @@ void nr_decode_pucch0( int32_t **rxdataF,
corr[i]=corr_re[i]*corr_re[i]+corr_im[i]*corr_im[i];
}
float max_corr=corr[0];
int index=0;
uint8_t index=0;
for(i=1;i<nr_sequences;i++){
if(corr[i]>max_corr){
index= i;
max_corr=corr[i];
}
}
*payload=(uint64_t)index; // payload bits 00..b3b2b0, b0 is the SR bit and b3b2 are HARQ bits
// first bit of bitmap for sr presence and second bit for acknack presence
uci_pdu->pdu_bit_map = pucch_pdu->sr_flag | ((pucch_pdu->bit_len_harq>0)<<1);
uci_pdu->pucch_format = 0; // format 0
uci_pdu->ul_cqi = 0xff; // currently not valid
uci_pdu->timing_advance = 0xffff; // currently not valid
uci_pdu->rssi = 0xffff; // currently not valid
if (pucch_pdu->sr_flag) {
//currently not supported
}
else
uci_pdu->sr = NULL;
if (pucch_pdu->bit_len_harq>0) {
uci_pdu->harq = calloc(1,sizeof(*uci_pdu->harq));
uci_pdu->harq->num_harq = pucch_pdu->bit_len_harq;
uci_pdu->harq->harq_confidence_level = 0xff; // currently not valid
uci_pdu->harq->harq_list = (nfapi_nr_harq_t*)malloc(uci_pdu->harq->num_harq);
for (i=0; i<uci_pdu->harq->num_harq; i++) // FIXME for non present
uci_pdu->harq->harq_list[i].harq_value = (index>>i)&0x01;
}
else
uci_pdu->harq = NULL;
}
......
......@@ -37,7 +37,7 @@
//#include "LAYER2/MAC/extern.h"
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
......@@ -46,148 +46,9 @@
#define DEBUG_PUCCH_TX
#define DEBUG_NR_PUCCH_TX
#endif
//#define ONE_OVER_SQRT2 23170 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2)
void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id,
uint8_t n_hop,
int nr_tti_tx,
uint8_t *u,
uint8_t *v) {
/*
* Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping
* The following variables are set by higher layers:
* - PUCCH_GroupHopping:
* - n_id: higher-layer parameter hoppingId
* - n_hop: frequency hopping index
* if intra-slot frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping
* n_hop=0
* if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping
* n_hop=0 for the first hop
* n_hop=1 for the second hop
*/
// depending on the value of the PUCCH_GroupHopping, we will obtain different values for u,v
//pucch_GroupHopping_t PUCCH_GroupHopping = ue->pucch_config_common_nr->pucch_GroupHopping; // from higher layers FIXME!!!
// n_id defined as per TS 38.211 subclause 6.3.2.2.1 (is given by the higher-layer parameter hoppingId)
// it is hoppingId from PUCCH-ConfigCommon:
// Cell-Specific scrambling ID for group hoppping and sequence hopping if enabled
// Corresponds to L1 parameter 'HoppingID' (see 38.211, section 6.3.2.2) BIT STRING (SIZE (10))
//uint16_t n_id = ue->pucch_config_common_nr->hoppingId; // from higher layers FIXME!!!
#ifdef DEBUG_NR_PUCCH_TX
// initialization to be removed
PUCCH_GroupHopping=neither;
n_id=10;
printf("\t\t [nr_group_sequence_hopping] initialization PUCCH_GroupHopping=%u, n_id=%u -> variable initializations TO BE REMOVED\n",PUCCH_GroupHopping,n_id);
#endif
uint8_t f_ss=0,f_gh=0;
*u=0;
*v=0;
uint32_t c_init = 0;
uint32_t x1,s; // TS 38.211 Subclause 5.2.1
int l = 32, minShift = ((2*nr_tti_tx+n_hop)<<3);
int tmpShift =0;
#ifdef DEBUG_NR_PUCCH_TX
printf("\t\t [nr_group_sequence_hopping] calculating u,v -> ");
#endif
if (PUCCH_GroupHopping == neither) { // PUCCH_GroupHopping 'neither'
f_ss = n_id%30;
}
if (PUCCH_GroupHopping == enable) { // PUCCH_GroupHopping 'enabled'
c_init = floor(n_id/30); // we initialize c_init to calculate u,v according to 6.3.2.2.1 of 38.211
s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
for (int m=0; m<8; m++) {
while(minShift >= l) {
s = lte_gold_generic(&x1, &c_init, 0);
l = l+32;
}
tmpShift = (minShift&((1<<5)-1)); //minShift%32;
f_gh = f_gh + ((1<<m)*((uint8_t)((s>>tmpShift)&1)));
minShift ++;
}
f_gh = f_gh%30;
f_ss = n_id%30;
/* for (int m=0; m<8; m++){
f_gh = f_gh + ((1<<m)*((uint8_t)((s>>(8*(2*nr_tti_tx+n_hop)+m))&1))); // Not sure we have to use nr_tti_tx FIXME!!!
}
f_gh = f_gh%30;
f_ss = n_id%30;*/
}
if (PUCCH_GroupHopping == disable) { // PUCCH_GroupHopping 'disabled'
c_init = (1<<5)*floor(n_id/30)+(n_id%30); // we initialize c_init to calculate u,v
s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
f_ss = n_id%30;
l = 32, minShift = (2*nr_tti_tx+n_hop);
while(minShift >= l) {
s = lte_gold_generic(&x1, &c_init, 0);
l = l+32;
}
tmpShift = (minShift&((1<<5)-1)); //minShift%32;
*v = (uint8_t)((s>>tmpShift)&1);
// *v = (uint8_t)((s>>(2*nr_tti_tx+n_hop))&1); // Not sure we have to use nr_tti_tx FIXME!!!
}
*u = (f_gh+f_ss)%30;
#ifdef DEBUG_NR_PUCCH_TX
printf("%d,%d\n",*u,*v);
#endif
}
double nr_cyclic_shift_hopping(uint32_t n_id,
uint8_t m0,
uint8_t mcs,
uint8_t lnormal,
uint8_t lprime,
int nr_tti_tx) {
/*
* Implements TS 38.211 subclause 6.3.2.2.2 Cyclic shift hopping
* - n_id: higher-layer parameter hoppingId
* - m0: provided by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift of PUCCH-F0-resource-config
* - mcs: mcs=0 except for PUCCH format 0 when it depends on information to be transmitted according to TS 38.213 subclause 9.2
* - lnormal: lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission
* - lprime: lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
*/
// alpha_init initialized to 2*PI/12=0.5235987756
double alpha = 0.5235987756;
uint32_t c_init = n_id; // we initialize c_init again to calculate n_cs
#ifdef DEBUG_NR_PUCCH_TX
// initialization to be remo.ved
c_init=10;
printf("\t\t [nr_cyclic_shift_hopping] initialization c_init=%u -> variable initialization TO BE REMOVED\n",c_init);
#endif
uint32_t x1,s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
uint8_t n_cs=0;
int l = 32, minShift = (14*8*nr_tti_tx )+ 8*(lnormal+lprime);
int tmpShift =0;
#ifdef DEBUG_NR_PUCCH_TX
printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%u -> \n",c_init);
#endif
for (int m=0; m<8; m++) {
while(minShift >= l) {
s = lte_gold_generic(&x1, &c_init, 0);
l = l+32;
}
tmpShift = (minShift&((1<<5)-1)); //minShift%32;
minShift ++;
n_cs = n_cs+((1<<m)*((uint8_t)((s>>tmpShift)&1)));
// calculating n_cs (Not sure we have to use nr_tti_tx FIXME!!!)
// n_cs = n_cs+((1<<m)*((uint8_t)((s>>((14*8*nr_tti_tx) + 8*(lnormal+lprime) + m))&1)));
}
//#define ONE_OVER_SQRT2 23170 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2)
alpha = (alpha * (double)((m0+mcs+n_cs)%12));
#ifdef DEBUG_NR_PUCCH_TX
printf("n_cs=%d -> %lf\n",n_cs,alpha);
#endif
return(alpha);
}
void nr_generate_pucch0(PHY_VARS_NR_UE *ue,
int32_t **txdataF,
NR_DL_FRAME_PARMS *frame_parms,
......@@ -271,46 +132,31 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue,
*/
//int32_t *txptr;
uint32_t re_offset=0;
uint8_t l2;
for (int l=0; l<nrofSymbols; l++) {
if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
}
if ((startingPRB >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1)));
}
if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
}
if ((startingPRB > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6;
}
if ((startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
}
l2=l+startingSymbolIndex;
re_offset = (12*startingPRB) + frame_parms->first_carrier_offset;
if (re_offset>= frame_parms->ofdm_symbol_size)
re_offset-=frame_parms->ofdm_symbol_size;
//txptr = &txdataF[0][re_offset];
for (int n=0; n<12; n++) {
if ((n==6) && (startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) {
// if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB)
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size);
}
((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)(((int32_t)(amp) * x_n_re[(12*l)+n])>>15);
((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)(((int32_t)(amp) * x_n_im[(12*l)+n])>>15);
((int16_t *)&txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset])[0] = (int16_t)(((int32_t)(amp) * x_n_re[(12*l)+n])>>15);
((int16_t *)&txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset])[1] = (int16_t)(((int32_t)(amp) * x_n_im[(12*l)+n])>>15);
//((int16_t *)txptr[0][re_offset])[0] = (int16_t)((int32_t)amp * x_n_re[(12*l)+n])>>15;
//((int16_t *)txptr[0][re_offset])[1] = (int16_t)((int32_t)amp * x_n_im[(12*l)+n])>>15;
//txptr[re_offset] = (x_n_re[(12*l)+n]<<16) + x_n_im[(12*l)+n];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,re_offset,
l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]);
amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,(l2*frame_parms->ofdm_symbol_size) + re_offset,
l2,n,((int16_t *)&txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset])[0],
((int16_t *)&txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset])[1]);
#endif
re_offset++;
if (re_offset>= frame_parms->ofdm_symbol_size)
re_offset-=frame_parms->ofdm_symbol_size;
}
}
}
......
......@@ -42,46 +42,7 @@
#include "T.h"
#define ONE_OVER_SQRT2 23170 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2)
void nr_decode_pucch1( int32_t **rxdataF,
pucch_GroupHopping_t pucch_GroupHopping,
uint32_t n_id, // hoppingID higher layer parameter
uint64_t *payload,
NR_DL_FRAME_PARMS *frame_parms,
int16_t amp,
int nr_tti_tx,
uint8_t m0,
uint8_t nrofSymbols,
uint8_t startingSymbolIndex,
uint16_t startingPRB,
uint16_t startingPRB_intraSlotHopping,
uint8_t timeDomainOCC,
uint8_t nr_bit);
void nr_decode_pucch0( int32_t **rxdataF,
pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id, //PHY_VARS_gNB *gNB, generally rxdataf is in gNB->common_vars
uint64_t *payload,
NR_DL_FRAME_PARMS *frame_parms,
int16_t amp,
int nr_tti_tx,
uint8_t m0, // should come from resource set
uint8_t nrofSymbols, // should come from resource set
uint8_t startingSymbolIndex, // should come from resource set
uint16_t startingPRB, // should come from resource set
uint8_t nr_bit);
void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id,
uint8_t n_hop,
int nr_tti_tx,
uint8_t *u,
uint8_t *v);
double nr_cyclic_shift_hopping(uint32_t n_id,
uint8_t m0,
uint8_t mcs,
uint8_t lnormal,
uint8_t lprime,
int nr_tti_tx);
void nr_generate_pucch0(PHY_VARS_NR_UE *ue,
int32_t **txdataF,
NR_DL_FRAME_PARMS *frame_parms,
......@@ -139,8 +100,8 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue,
uint8_t occ_index_format4);
// tables for mcs values for different payloads
static const uint8_t table1_mcs[]={0,3,6,9};
static const uint8_t table2_mcs[]={0,1,3,4,6,7,9,10};
static const uint8_t table1_mcs[]={0,6,3,9};
static const uint8_t table2_mcs[]={0,3,9,6,1,4,10,7};
/*
* The following tables implement TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (rows->u {0,1,..,29} / columns->n {0,1,...,M_ZC-1)
......
......@@ -623,23 +623,12 @@ typedef struct PHY_VARS_gNB_s {
NR_UL_IND_t UL_INFO;
pthread_mutex_t UL_INFO_mutex;
/// NFAPI RX ULSCH information
nfapi_rx_indication_pdu_t rx_pdu_list[NFAPI_RX_IND_MAX_PDU];
/// NFAPI RX ULSCH CRC information
nfapi_crc_indication_pdu_t crc_pdu_list[NFAPI_CRC_IND_MAX_PDU];
/// NFAPI HARQ information
nfapi_harq_indication_pdu_t harq_pdu_list[NFAPI_HARQ_IND_MAX_PDU];
/// NFAPI SR information
nfapi_sr_indication_pdu_t sr_pdu_list[NFAPI_SR_IND_MAX_PDU];
/// NFAPI CQI information
nfapi_cqi_indication_pdu_t cqi_pdu_list[NFAPI_CQI_IND_MAX_PDU];
/// NFAPI CQI information (raw component)
nfapi_cqi_indication_raw_pdu_t cqi_raw_pdu_list[NFAPI_CQI_IND_MAX_PDU];
/// NFAPI PRACH information
/// NFAPI PRACH information (to be removed)
nfapi_preamble_pdu_t preamble_list[MAX_NUM_RX_PRACH_PREAMBLES];
//Sched_Rsp_t Sched_INFO;
nfapi_nr_ul_tti_request_t UL_tti_req;
nfapi_nr_uci_indication_t uci_indication;
nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu;
nfapi_nr_ul_dci_request_pdus_t *ul_dci_pdu;
......
......@@ -28,6 +28,7 @@
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
#include "SCHED/sched_eNB.h"
#include "sched_nr.h"
#include "SCHED/sched_common_extern.h"
......@@ -285,6 +286,7 @@ void nr_fill_rx_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_
nfapi_rx_indication_pdu_t *pdu;
int timing_advance_update;
int sync_pos;
......@@ -394,18 +396,23 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
nfapi_nr_ul_tti_request_t *UL_tti_req = &gNB->UL_tti_req;
int num_pusch_pdu = UL_tti_req->n_pdus;
LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d, num_pusch_pdu %d\n",frame_rx,slot_rx,num_pusch_pdu);
int num_pdus = UL_tti_req->n_pdus;
gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus = 0;
for (int i = 0; i < num_pusch_pdu; i++) {
nfapi_nr_uci_indication_t *uci_indication = &gNB->uci_indication;
uci_indication->sfn = frame_rx;
uci_indication->slot = slot_rx;
uci_indication->num_ucis = 0;
LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d, num_pdus %d\n",frame_rx,slot_rx,num_pdus);
for (int i = 0; i < num_pdus; i++) {
switch (UL_tti_req->pdus_list[i].pdu_type) {
case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE:{
case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE:
LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE\n",frame_rx,slot_rx);
nfapi_nr_pusch_pdu_t *pusch_pdu = &UL_tti_req->pdus_list[0].pusch_pdu;
nfapi_nr_pusch_pdu_t *pusch_pdu = &UL_tti_req->pdus_list[i].pusch_pdu;
nr_fill_ulsch(gNB,frame_rx,slot_rx,pusch_pdu);
uint8_t ULSCH_id = find_nr_ulsch(pusch_pdu->rnti,gNB,SEARCH_EXIST);
......@@ -420,8 +427,31 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
//LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1);
nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid);
nr_fill_rx_indication(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid); // indicate SDU to MAC
nr_fill_crc_indication(gNB, frame_rx, slot_rx, ULSCH_id, 0);
break;
case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE:
LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE\n",frame_rx,slot_rx);
nfapi_nr_pucch_pdu_t *pucch_pdu = &UL_tti_req->pdus_list[i].pucch_pdu;
switch (pucch_pdu->format_type) {
case 0:
uci_indication->uci_list[uci_indication->num_ucis].pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE;
uci_indication->uci_list[uci_indication->num_ucis].pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t);
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &uci_indication->uci_list[uci_indication->num_ucis].pucch_pdu_format_0_1;
nr_decode_pucch0(gNB->common_vars.rxdataF,
&gNB->frame_parms,
slot_rx,
uci_pdu_format0,
pucch_pdu);
uci_indication->num_ucis += 1;
break;
case 1:
break;
default:
AssertFatal(1==0,"Only PUCCH format 0 and 1 are currently supported\n");
}
break;
}
}
}
......@@ -87,12 +87,13 @@ int main(int argc, char **argv)
uint8_t nacktoack_flag=0;
int16_t amp=0x7FFF;
int nr_tti_tx=0;
uint64_t actual_payload=0,payload_received;//payload bits b7b6...b2b1b0 where b7..b3=0 b2b1=HARQ b0 is SR. payload maximum value is 7 for pucch format 0
uint64_t actual_payload=0,payload_received;
int nr_bit=1; // maximum value possible is 2
uint8_t m0=0;// higher layer paramater initial cyclic shift
uint8_t nrofSymbols=1; //number of OFDM symbols can be 1-2 for format 1
uint8_t startingSymbolIndex=0; // resource allocated see 9.2.1, 38.213 for more info.should be actually present in the resource set provided
uint16_t startingPRB=0,startingPRB_intraSlotHopping=0; //PRB number not sure see 9.2.1, 38.213 for more info. Should be actually present in the resource set provided
uint32_t hoppingId=40;
uint8_t timeDomainOCC=0;
SCM_t channel_model=AWGN;//Rayleigh1_anticorr;
......@@ -114,7 +115,7 @@ int main(int argc, char **argv)
logInit();
set_glog(loglvl);
while ((c = getopt (argc, argv, "f:hA:f:g:i:P:b:T:n:o:s:S:x:y:z:N:F:GR:IL")) != -1) {
while ((c = getopt (argc, argv, "f:hA:f:g:i:I:P:B:b:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL")) != -1) {
switch (c) {
case 'f':
//write_output_file=1;
......@@ -257,12 +258,24 @@ int main(int argc, char **argv)
case 'i':
nrofSymbols=(uint8_t)atoi(optarg);
break;
case 'I':
startingSymbolIndex=(uint8_t)atoi(optarg);
break;
case 'r':
startingPRB=atoi(optarg);
break;
case 'P':
format=atoi(optarg);
break;
case 'm':
m0=atoi(optarg);
break;
case 'b':
nr_bit=atoi(optarg);
break;
case 'B':
actual_payload=atoi(optarg);
break;
case 'T':
nacktoack_flag=(uint8_t)atoi(optarg);
target_error_rate=0.001;
......@@ -292,8 +305,12 @@ int main(int argc, char **argv)
printf("-f Output filename (.txt format) for Pe/SNR results\n");
printf("-F Input filename (.txt format) for RX conformance testing\n");
printf("-i Enter number of ofdm symbols for pucch\n");
printf("-I Starting symbol index for pucch\n");
printf("-r PUCCCH starting PRB\n");
printf("-P Enter the format of PUCCH\n");
printf("-b number of HARQ bits (1-2)\n");
printf("-B payload to be transmitted on PUCCH\n");
printf("-m initial cyclic shift m0\n");
printf("-T to check nacktoack miss for format 1");
exit (-1);
break;
......@@ -304,6 +321,16 @@ int main(int argc, char **argv)
printf("Initializing gNodeB for mu %d, N_RB_DL %d\n",mu,N_RB_DL);
if((format!=0) && (format!=1)){
printf("PUCCH format %d not supported\n",format);
exit(0);
}
AssertFatal((nr_bit<3)&&(actual_payload<4),"Only format 0 and 1 currently supported. 2 bits max supported");
if (nr_bit==1) actual_payload = actual_payload&1;
printf("Transmitted payload is %ld\n",actual_payload);
RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *));
RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB));
......@@ -398,6 +425,7 @@ int main(int argc, char **argv)
//configure UE
UE = malloc(sizeof(PHY_VARS_NR_UE));
memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS));
UE->pucch_config_common_nr->hoppingId = hoppingId;
//phy_init_nr_top(UE); //called from init_nr_ue_signal
UE->perfect_ce = 0;
......@@ -414,35 +442,15 @@ int main(int argc, char **argv)
startingPRB_intraSlotHopping=N_RB_DL-1;
pucch_GroupHopping_t PUCCH_GroupHopping=UE->pucch_config_common_nr->pucch_GroupHopping;
uint32_t n_id=UE->pucch_config_common_nr->hoppingId;
if((format!=0) && (format!=1)){
printf("format not supported\n");
exit(0);
}
if(nacktoack_flag==0){
if(format==0){
if(nr_bit==1){
actual_payload=2;
mcs=table1_mcs[actual_payload];
}
else if(nr_bit==2){
actual_payload=6;
mcs=table2_mcs[actual_payload];
}
else{
printf("Number of HARQ bits possible is 1-2\n");
exit(0);
}
}
else {
// for now we are not considering SR just HARQ-ACK
if(nr_bit==1)
actual_payload=1;
mcs=table1_mcs[actual_payload];
else if(nr_bit==2)
actual_payload=3;
else{
printf("number of bits carried by PUCCH format1 is 1-2\n");
}
}
mcs=table2_mcs[actual_payload];
}
for(SNR=snr0;SNR<=snr1;SNR=SNR+1){
ack_nack_errors=0;
n_errors = 0;
......@@ -488,6 +496,7 @@ int main(int argc, char **argv)
}
n_errors=((actual_payload^payload_received)&1)+(((actual_payload^payload_received)&2)>>1)+(((actual_payload^payload_received)&4)>>2)+n_errors;
}
printf("Decoded payload is %ld\n",payload_received);
printf("SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,n_errors);
if((float)ack_nack_errors/(float)(nr_bit*n_trials)<=target_error_rate){
printf("PUCCH test OK\n");
......
......@@ -51,7 +51,6 @@ extern RAN_CONTEXT_t RC;
extern void mac_top_init_gNB(void);
extern uint8_t nfapi_mode;
void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) {
nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[Mod_idP]->config[0];
......@@ -283,7 +282,6 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
else LOG_I(PHY,"TDD has been properly configurated\n");
}
/*
// PDCCH-ConfigCommon
cfg->pdcch_config.controlResourceSetZero.value = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero;
......
......@@ -61,6 +61,8 @@
uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 };
uint8_t nr_slots_per_frame[5] = {10, 20, 40, 80, 160};
void clear_nr_nfapi_information(gNB_MAC_INST * gNB,
int CC_idP,
frame_t frameP,
......@@ -299,6 +301,67 @@ void copy_nr_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
}
*/
void nr_schedule_pucch(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP) {
uint16_t O_uci;
uint16_t O_ack;
uint8_t SR_flag = 0; // no SR in PUCCH implemented for now
NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list;
AssertFatal(UE_list->active[UE_id] >=0,"Cannot find UE_id %d is not active\n",UE_id);
NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id];
int bwp_id=1;
NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1];
nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0];
NR_sched_pucch *curr_pucch = UE_list->UE_sched_ctrl[UE_id].sched_pucch;
NR_sched_pucch *temp_pucch;
int release_pucch = 0;
if (curr_pucch != NULL) {
if ((frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) {
UL_tti_req->SFN = frameP;
UL_tti_req->Slot = slotP;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
nfapi_nr_pucch_pdu_t *pucch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pucch_pdu;
memset(pucch_pdu,0,sizeof(nfapi_nr_pucch_pdu_t));
UL_tti_req->n_pdus+=1;
O_ack = curr_pucch->dai_c;
O_uci = O_ack; // for now we are just sending acknacks in pucch
nr_configure_pucch(pucch_pdu,
scc,
ubwp,
curr_pucch->resource_indicator,
O_uci,
O_ack,
SR_flag);
release_pucch = 1;
}
}
if (release_pucch) {
temp_pucch = UE_list->UE_sched_ctrl[UE_id].sched_pucch;
UE_list->UE_sched_ctrl[UE_id].sched_pucch = UE_list->UE_sched_ctrl[UE_id].sched_pucch->next_sched_pucch;
free(temp_pucch);
}
}
bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot){
if((bitmap>>slot)&0x01)
return true;
else
return false;
}
void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
frame_t frame_rxP,
sub_frame_t slot_rxP,
......@@ -308,11 +371,24 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
//printf("gNB_dlsch_ulsch_scheduler frameRX %d slotRX %d frameTX %d slotTX %d\n",frame_rxP,slot_rxP,frame_txP,slot_txP);
protocol_ctxt_t ctxt;
int CC_id, UE_id = 0;
int CC_id;
int UE_id;
uint64_t *dlsch_in_slot_bitmap=NULL;
uint64_t *ulsch_in_slot_bitmap=NULL;
NR_sched_pucch *pucch_sched = (NR_sched_pucch*) malloc(sizeof(NR_sched_pucch));
if (get_softmodem_params()->phy_test) UE_id=0;
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
NR_UE_list_t *UE_list = &gNB->UE_list;
UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
NR_COMMON_channels_t *cc = gNB->common_channels;
NR_UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
NR_COMMON_channels_t *cc = RC.nrmac[module_idP]->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
int num_slots_per_tdd = (nr_slots_per_frame[*scc->ssbSubcarrierSpacing])>>(7-scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity);
//nfapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = NULL;
start_meas(&RC.nrmac[module_idP]->eNB_scheduler);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
......@@ -323,6 +399,27 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
RC.nrmac[module_idP]->frame = frame_rxP;
RC.nrmac[module_idP]->slot = slot_rxP;
if (get_softmodem_params()->phy_test) {
dlsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].dlsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains dlsch
ulsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].ulsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains ulsch
// hardcoding dlsch to be in slot 1
if (!(slot_txP%num_slots_per_tdd)) {
if(slot_txP==0)
*dlsch_in_slot_bitmap = 0x02;
else
*dlsch_in_slot_bitmap = 0x00;
}
// hardcoding ulsch to be in slot 8
if (!(slot_rxP%num_slots_per_tdd)) {
if(slot_rxP==0)
*ulsch_in_slot_bitmap = 0x100;
else
*ulsch_in_slot_bitmap = 0x00;
}
}
// Check if there are downlink symbols in the slot,
if (is_nr_DL_slot(cc->ServingCellConfigCommon,slot_txP)) {
......@@ -373,8 +470,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
}
// Phytest scheduling
if (get_softmodem_params()->phy_test && slot_txP==1){
nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP,NULL);
if (get_softmodem_params()->phy_test && (is_xlsch_in_slot(*dlsch_in_slot_bitmap,slot_txP%num_slots_per_tdd))) {
nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,pucch_sched);
nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, pucch_sched, NULL);
// resetting ta flag
gNB->ta_len = 0;
}
......@@ -388,10 +486,14 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
} //is_nr_DL_slot
if (is_nr_UL_slot(cc->ServingCellConfigCommon,slot_rxP)) {
if (get_softmodem_params()->phy_test && slot_rxP==8){
if (get_softmodem_params()->phy_test){
nr_schedule_pucch(module_idP, UE_id, frame_rxP, slot_rxP);
if (is_xlsch_in_slot(*ulsch_in_slot_bitmap,slot_rxP%num_slots_per_tdd)){
nr_schedule_uss_ulsch_phytest(module_idP, frame_rxP, slot_rxP);
}
}
}
stop_meas(&RC.nrmac[module_idP]->eNB_scheduler);
......
......@@ -252,20 +252,25 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
int configure_fapi_dl_pdu(int Mod_idP,
int *CCEIndex,
nfapi_nr_dl_tti_request_body_t *dl_req,
NR_sched_pucch *pucch_sched,
uint8_t *mcsIndex,
uint16_t *rbSize,
uint16_t *rbStart) {
gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP];
NR_COMMON_channels_t *cc = nr_mac->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu;
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu;
int TBS, bwp_id = 1, UE_id = 0;
NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list;
int TBS;
int bwp_id=1;
int UE_id = 0;
NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list;
NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id];
AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
......@@ -351,10 +356,10 @@ int configure_fapi_dl_pdu(int Mod_idP,
dci_pdu_rel15[0].ndi = 1;
dci_pdu_rel15[0].rv = 0;
dci_pdu_rel15[0].harq_pid = 0;
dci_pdu_rel15[0].dai = 2;
dci_pdu_rel15[0].dai = (pucch_sched->dai_c-1)&3;
dci_pdu_rel15[0].tpc = 2;
dci_pdu_rel15[0].pucch_resource_indicator = 7;
dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator = 7;
dci_pdu_rel15[0].pucch_resource_indicator = pucch_sched->resource_indicator;
dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator = pucch_sched->timing_indicator;
LOG_D(MAC, "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n",
dci_pdu_rel15[0].frequency_domain_assignment,
......@@ -491,6 +496,7 @@ void configure_fapi_dl_Tx(module_id_t Mod_idP,
void nr_schedule_uss_dlsch_phytest(module_id_t module_idP,
frame_t frameP,
sub_frame_t slotP,
NR_sched_pucch *pucch_sched,
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *dlsch_config){
LOG_D(MAC, "In nr_schedule_uss_dlsch_phytest \n");
......@@ -538,6 +544,7 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP,
TBS_bytes = configure_fapi_dl_pdu(module_idP,
CCEIndices,
dl_req,
pucch_sched,
dlsch_config!=NULL ? dlsch_config->mcsIndex : NULL,
dlsch_config!=NULL ? &dlsch_config->rbSize : NULL,
dlsch_config!=NULL ? &dlsch_config->rbStart : NULL);
......@@ -719,11 +726,11 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP,
UL_tti_req->SFN = frameP;
UL_tti_req->Slot = slotP;
UL_tti_req->n_pdus = 1;
UL_tti_req->pdus_list[0].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE;
UL_tti_req->pdus_list[0].pdu_size = sizeof(nfapi_nr_pusch_pdu_t);
nfapi_nr_pusch_pdu_t *pusch_pdu = &UL_tti_req->pdus_list[0].pusch_pdu;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t);
nfapi_nr_pusch_pdu_t *pusch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pusch_pdu;
memset(pusch_pdu,0,sizeof(nfapi_nr_pusch_pdu_t));
UL_tti_req->n_pdus+=1;
LOG_D(MAC, "Scheduling UE specific PUSCH\n");
//UL_tti_req = &nr_mac->UL_tti_req[CC_id];
......@@ -822,7 +829,6 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP,
scc,
bwp);
dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET];
AssertFatal(CCEIndex>=0,"CCEIndex is negative \n");
......
......@@ -563,14 +563,199 @@ uint8_t getNRBG(uint16_t bwp_size, uint16_t bwp_start, long rbg_size_config) {
return (uint8_t)ceil((bwp_size+(bwp_start % rbg_size))/rbg_size);
}
// This function configures pucch pdu fapi structure
void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
NR_ServingCellConfigCommon_t *scc,
NR_BWP_Uplink_t *bwp,
uint8_t pucch_resource,
uint16_t O_uci,
uint16_t O_ack,
uint8_t SR_flag) {
NR_PUCCH_Config_t *pucch_Config;
NR_PUCCH_Resource_t *pucchres;
NR_PUCCH_ResourceSet_t *pucchresset;
NR_PUCCH_FormatConfig_t *pucchfmt;
NR_PUCCH_ResourceId_t *resource_id = NULL;
long *id0 = NULL;
int n_list, n_set;
uint16_t N2,N3;
int res_found = 0;
pucch_pdu->bit_len_harq = O_ack;
if (bwp) { // This is not the InitialBWP
NR_PUSCH_Config_t *pusch_Config = bwp->bwp_Dedicated->pusch_Config->choice.setup;
long *pusch_id = pusch_Config->dataScramblingIdentityPUSCH;
if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL)
id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->transformPrecodingDisabled->scramblingID0;
if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL)
id0 = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->transformPrecodingDisabled->scramblingID0;
// hop flags and hopping id are valid for any BWP
switch (bwp->bwp_Common->pucch_ConfigCommon->choice.setup->pucch_GroupHopping){
case 0 :
// if neither, both disabled
pucch_pdu->group_hop_flag = 0;
pucch_pdu->sequence_hop_flag = 0;
break;
case 1 :
// if enable, group enabled
pucch_pdu->group_hop_flag = 1;
pucch_pdu->sequence_hop_flag = 0;
break;
case 2 :
// if disable, sequence disabled
pucch_pdu->group_hop_flag = 0;
pucch_pdu->sequence_hop_flag = 1;
break;
default:
AssertFatal(1==0,"Group hopping flag %ld undefined (0,1,2) \n", bwp->bwp_Common->pucch_ConfigCommon->choice.setup->pucch_GroupHopping);
}
if (bwp->bwp_Common->pucch_ConfigCommon->choice.setup->hoppingId != NULL)
pucch_pdu->hopping_id = *bwp->bwp_Common->pucch_ConfigCommon->choice.setup->hoppingId;
else
pucch_pdu->hopping_id = *scc->physCellId;
pucch_pdu->bwp_size = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275);
pucch_pdu->bwp_start = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275);
pucch_pdu->subcarrier_spacing = bwp->bwp_Common->genericParameters.subcarrierSpacing;
pucch_pdu->cyclic_prefix = (bwp->bwp_Common->genericParameters.cyclicPrefix==NULL) ? 0 : *bwp->bwp_Common->genericParameters.cyclicPrefix;
pucch_Config = bwp->bwp_Dedicated->pucch_Config->choice.setup;
AssertFatal(pucch_Config->resourceSetToAddModList!=NULL,
"PUCCH resourceSetToAddModList is null\n");
n_set = pucch_Config->resourceSetToAddModList->list.count;
AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n");
N2 = 2;
// procedure to select pucch resource id from resource sets according to
// number of uci bits and pucch resource indicator pucch_resource
// ( see table 9.2.3.2 in 38.213)
for (int i=0; i<n_set; i++) {
pucchresset = pucch_Config->resourceSetToAddModList->list.array[i];
n_list = pucchresset->resourceList.list.count;
if (pucchresset->pucch_ResourceSetId == 0 && O_uci<3) {
if (pucch_resource < n_list)
resource_id = pucchresset->resourceList.list.array[pucch_resource];
else
AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci);
}
else {
N3 = pucchresset->maxPayloadMinus1!= NULL ? *pucchresset->maxPayloadMinus1 : 1706;
if (N2<O_uci && N3>O_uci) {
if (pucch_resource < n_list)
resource_id = pucchresset->resourceList.list.array[pucch_resource];
else
AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci);
}
else N2 = N3;
}
}
AssertFatal(resource_id!=NULL,"Couldn-t find any matching PUCCH resource in the PUCCH resource sets");
AssertFatal(pucch_Config->resourceToAddModList!=NULL,
"PUCCH resourceToAddModList is null\n");
n_list = pucch_Config->resourceToAddModList->list.count;
AssertFatal(n_list>0,"PUCCH resourceToAddModList is empty\n");
// going through the list of PUCCH resources to find the one indexed by resource_id
for (int i=0; i<n_list; i++) {
pucchres = pucch_Config->resourceToAddModList->list.array[i];
if (pucchres->pucch_ResourceId == *resource_id) {
res_found = 1;
pucch_pdu->prb_start = pucchres->startingPRB;
// FIXME why there is only one frequency hopping flag
// what about inter slot frequency hopping?
pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0;
pucch_pdu->second_hop_prb = pucchres->secondHopPRB!= NULL ? *pucchres->secondHopPRB : 0;
switch(pucchres->format.present) {
case NR_PUCCH_Resource__format_PR_format0 :
pucch_pdu->format_type = 0;
pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format0->initialCyclicShift;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format0->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex;
pucch_pdu->sr_flag = SR_flag;
break;
case NR_PUCCH_Resource__format_PR_format1 :
pucch_pdu->format_type = 1;
pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format1->initialCyclicShift;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex;
pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC;
pucch_pdu->sr_flag = SR_flag;
break;
case NR_PUCCH_Resource__format_PR_format2 :
pucch_pdu->format_type = 2;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex;
pucch_pdu->prb_size = pucchres->format.choice.format2->nrofPRBs;
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : *scc->physCellId;
break;
case NR_PUCCH_Resource__format_PR_format3 :
pucch_pdu->format_type = 3;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex;
pucch_pdu->prb_size = pucchres->format.choice.format3->nrofPRBs;
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
if (pucch_Config->format3 == NULL) {
pucch_pdu->pi_2bpsk = 0;
pucch_pdu->add_dmrs_flag = 0;
}
else {
pucchfmt = pucch_Config->format3->choice.setup;
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
}
break;
case NR_PUCCH_Resource__format_PR_format4 :
pucch_pdu->format_type = 4;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format4->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex;
pucch_pdu->pre_dft_occ_len = pucchres->format.choice.format4->occ_Length;
pucch_pdu->pre_dft_occ_idx = pucchres->format.choice.format4->occ_Index;
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
if (pucch_Config->format3 == NULL) {
pucch_pdu->pi_2bpsk = 0;
pucch_pdu->add_dmrs_flag = 0;
}
else {
pucchfmt = pucch_Config->format3->choice.setup;
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
}
break;
default :
AssertFatal(1==0,"Undefined PUCCH format \n");
}
}
}
AssertFatal(res_found==1,"No PUCCH resource found corresponding to id %ld\n",*resource_id);
}
else { // this is for InitialBWP
AssertFatal(1==0,"Fill in InitialBWP PUCCH configuration\n");
}
}
void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup,
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15,
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
nfapi_nr_pusch_pdu_t *pusch_pdu,
dci_pdu_rel15_t *dci_pdu_rel15,
int *dci_formats,
int *rnti_types
) {
int *rnti_types) {
NR_PDSCH_Config_t *pdsch_config = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup;
uint16_t N_RB = pdcch_pdu_rel15->BWPSize;
......@@ -1143,6 +1328,171 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
return -1;
}
void get_pdsch_to_harq_feedback(int Mod_idP,
int UE_id,
NR_SearchSpace__searchSpaceType_PR ss_type,
uint8_t *pdsch_to_harq_feedback) {
int bwp_id=1;
NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list;
NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id];
NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1];
NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1];
NR_SearchSpace_t *ss;
// common search type uses DCI format 1_0
if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) {
for (int i=0; i<8; i++)
pdsch_to_harq_feedback[i] = i+1;
}
else {
// searching for a ue specific search space
int found=0;
for (int i=0;i<bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) {
ss=bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i];
AssertFatal(ss->controlResourceSetId != NULL,"ss->controlResourceSetId is null\n");
AssertFatal(ss->searchSpaceType != NULL,"ss->searchSpaceType is null\n");
if (ss->searchSpaceType->present == ss_type) {
found=1;
break;
}
}
AssertFatal(found==1,"Couldn't find a ue specific searchspace\n");
if (ss->searchSpaceType->choice.ue_Specific->dci_Formats == NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_0_And_1_0) {
for (int i=0; i<8; i++)
pdsch_to_harq_feedback[i] = i+1;
}
else {
if(ubwp->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK != NULL)
pdsch_to_harq_feedback = (uint8_t *)ubwp->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK;
else
AssertFatal(found==1,"There is no allocated dl_DataToUL_ACK for pdsch to harq feedback\n");
}
}
}
// function to update pucch scheduling parameters in UE list when a USS DL is scheduled
void nr_update_pucch_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
NR_sched_pucch *sched_pucch) {
NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list;
int first_ul_slot_tdd,k;
NR_sched_pucch *curr_pucch;
uint8_t pdsch_to_harq_feedback[8];
int found = 0;
int i = 0;
int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0)
nr_ulmix_slots++;
// this is hardcoded for now as ue specific
NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback);
// if the list of pucch to be scheduled is empty
if (UE_list->UE_sched_ctrl[UE_id].sched_pucch == NULL) {
sched_pucch->frame = frameP;
sched_pucch->next_sched_pucch = NULL;
sched_pucch->dai_c = 1;
sched_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource
if ( nr_ulmix_slots > 0 ) {
// first pucch occasion in first UL or MIXED slot
first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
for (k=0; k<nr_ulmix_slots; k++) { // for each possible UL or mixed slot
while (i<8 && found == 0) { // look if timing indicator is among allowed values
if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd))
found = 1;
if (found == 0) i++;
}
if (found == 1) break;
}
if (found == 1) {
// computing slot in which pucch is scheduled
sched_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd));
sched_pucch->timing_indicator = pdsch_to_harq_feedback[i];
}
else
AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n");
}
else
AssertFatal(1==0,"No Uplink Slots in this Frame\n");
UE_list->UE_sched_ctrl[UE_id].sched_pucch = sched_pucch;
}
else { // to be tested
curr_pucch = UE_list->UE_sched_ctrl[UE_id].sched_pucch;
if (curr_pucch->dai_c<11) { // we are scheduling at most 11 harq-ack in the same pucch
while (i<8 && found == 0) { // look if timing indicator is among allowed values for current pucch
if (pdsch_to_harq_feedback[i]==(curr_pucch->ul_slot % slots_per_tdd)-(slotP % slots_per_tdd))
found = 1;
if (found == 0) i++;
}
if (found == 1) { // scheduling this harq-ack in current pucch
sched_pucch = curr_pucch;
sched_pucch->dai_c = 1 + sched_pucch->dai_c;
sched_pucch->timing_indicator = pdsch_to_harq_feedback[i];
}
}
if (curr_pucch->dai_c==11 || found == 0) { // if current pucch is full or no timing indicator allowed
// look for pucch occasions in other UL of mixed slots
for (k=scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; k<slots_per_tdd; k++) { // for each possible UL or mixed slot
if (k!=(curr_pucch->ul_slot % slots_per_tdd)) { // skip current scheduled slot (already checked)
i = 0;
while (i<8 && found == 0) { // look if timing indicator is among allowed values
if (pdsch_to_harq_feedback[i]==k-(slotP % slots_per_tdd))
found = 1;
if (found == 0) i++;
}
if (found == 1) {
if (k<(curr_pucch->ul_slot % slots_per_tdd)) { // we need to add a pucch occasion before current pucch
sched_pucch->frame = frameP;
sched_pucch->ul_slot = k + (slotP - (slotP % slots_per_tdd));
sched_pucch->next_sched_pucch = curr_pucch;
sched_pucch->dai_c = 1;
sched_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource
sched_pucch->timing_indicator = pdsch_to_harq_feedback[i];
UE_list->UE_sched_ctrl[UE_id].sched_pucch = sched_pucch;
}
else {
while (curr_pucch->next_sched_pucch != NULL && k!=(curr_pucch->ul_slot % slots_per_tdd))
curr_pucch = curr_pucch->next_sched_pucch;
if (curr_pucch == NULL) { // creating a new item in the list
sched_pucch->frame = frameP;
sched_pucch->next_sched_pucch = NULL;
sched_pucch->dai_c = 1;
sched_pucch->timing_indicator = pdsch_to_harq_feedback[i];
sched_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource
sched_pucch->ul_slot = k + (slotP - (slotP % slots_per_tdd));
curr_pucch->next_sched_pucch = (NR_sched_pucch*) malloc(sizeof(NR_sched_pucch));
curr_pucch->next_sched_pucch = sched_pucch;
}
else {
if (curr_pucch->dai_c==11)
found = 0; // if pucch at index k is already full we have to find a new one in a following occasion
else { // scheduling this harq-ack in current pucch
sched_pucch = curr_pucch;
sched_pucch->dai_c = 1 + sched_pucch->dai_c;
sched_pucch->timing_indicator = pdsch_to_harq_feedback[i];
}
}
}
}
}
}
}
}
}
/*void fill_nfapi_coresets_and_searchspaces(NR_CellGroupConfig_t *cg,
nfapi_nr_coreset_t *coreset,
nfapi_nr_search_space_t *search_space) {
......
......@@ -80,13 +80,16 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP);
int configure_fapi_dl_pdu(int Mod_id,
int *CCEIndeces,
nfapi_nr_dl_tti_request_body_t *dl_req,
NR_sched_pucch *pucch_sched,
uint8_t *mcsIndex,
uint16_t *rbSize,
uint16_t *rbStart);
void config_uldci(NR_BWP_Uplink_t *ubwp,nfapi_nr_pusch_pdu_t *pusch_pdu,nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, int *rnti_types);
void configure_fapi_dl_Tx(module_id_t Mod_idP,
......@@ -100,12 +103,25 @@ void configure_fapi_dl_Tx(module_id_t Mod_idP,
void nr_schedule_uss_dlsch_phytest(module_id_t module_idP,
frame_t frameP,
sub_frame_t slotP,
NR_sched_pucch *pucch_sched,
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_config);
void nr_schedule_uss_ulsch_phytest(int Mod_idP,
frame_t frameP,
sub_frame_t slotP);
void nr_update_pucch_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
NR_sched_pucch *sched_pucch);
void get_pdsch_to_harq_feedback(int Mod_idP,
int UE_id,
NR_SearchSpace__searchSpaceType_PR ss_type,
uint8_t *pdsch_to_harq_feedback);
void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu,
nr_scs_e scs_common,
nr_scs_e pdcch_scs,
......@@ -125,6 +141,7 @@ int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space,
nfapi_nr_config_request_scf_t cfg);
*/
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu,
int ss_type,
NR_ServingCellConfigCommon_t *scc,
......@@ -138,6 +155,15 @@ void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup,
int *dci_formats,
int *rnti_types);
void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
NR_ServingCellConfigCommon_t *scc,
NR_BWP_Uplink_t *bwp,
uint8_t pucch_resource,
uint16_t O_uci,
uint16_t O_ack,
uint8_t SR_flag);
int get_spf(nfapi_nr_config_request_scf_t *cfg);
int to_absslot(nfapi_nr_config_request_scf_t *cfg,int frame,int slot);
......
......@@ -102,9 +102,22 @@ typedef struct {
uint8_t num_sf_allocation_pattern;
} NR_COMMON_channels_t;
/*! \brief scheduling control information set through an API (not used)*/
typedef struct NR_sched_pucch {
int frame;
int ul_slot;
uint8_t dai_c;
uint8_t timing_indicator;
uint8_t resource_indicator;
struct NR_sched_pucch *next_sched_pucch;
} NR_sched_pucch;
/*! \brief scheduling control information set through an API */
typedef struct {
int dummy;
uint64_t dlsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains dlsch
uint64_t ulsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains ulsch
NR_sched_pucch *sched_pucch;
uint16_t ta_timer;
int16_t ta_update;
} NR_UE_sched_ctrl_t;
/*! \brief UE list used by eNB to order UEs/CC for scheduling*/
......@@ -112,7 +125,7 @@ typedef struct {
DLSCH_PDU DLSCH_pdu[4][MAX_MOBILES_PER_GNB];
/// scheduling control info
UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_GNB];
NR_UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_GNB];
int next[MAX_MOBILES_PER_GNB];
int head;
int next_ul[MAX_MOBILES_PER_GNB];
......@@ -124,7 +137,7 @@ typedef struct {
NR_CellGroupConfig_t *secondaryCellGroup[MAX_MOBILES_PER_GNB];
} NR_UE_list_t;
/*! \brief top level eNB MAC structure */
/*! \brief top level gNB MAC structure */
typedef struct gNB_MAC_INST_s {
/// Ethernet parameters for northbound midhaul interface
eth_params_t eth_params_n;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment