diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 3051545a16..3db66036de 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -241,20 +241,13 @@ int get_nr_prach_duration(uint8_t prach_format); void free_nr_prach_entry(prach_list_t *, prach_item_t *); -void nr_decode_pucch1(c16_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_pucch1(PHY_VARS_gNB *gNB, + c16_t **rxdataF, + int frame, + int slot, + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu, + nfapi_nr_pucch_pdu_t *pucch_pdu); + void nr_decode_pucch2(PHY_VARS_gNB *gNB, c16_t **rxdataF, diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index ce9401ba7d..bf702996b6 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -29,7 +29,7 @@ * \note * \warning */ -#include +#include #include #include #include @@ -55,7 +55,6 @@ #include "nr_phy_common.h" //#define DEBUG_NR_PUCCH_RX 1 - void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { for (int i = 0; i < gNB->max_nb_pucch; i++) { @@ -91,64 +90,63 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t LOG_W(PHY, "PUCCH list is full\n"); } - -int get_pucch0_cs_lut_index(PHY_VARS_gNB *gNB,nfapi_nr_pucch_pdu_t* pucch_pdu) { - - int i=0; +int get_pucch0_cs_lut_index(PHY_VARS_gNB *gNB, nfapi_nr_pucch_pdu_t *pucch_pdu) +{ + int i = 0; #ifdef DEBUG_NR_PUCCH_RX - printf("getting index for LUT with %d entries, Nid %d\n",gNB->pucch0_lut.nb_id, pucch_pdu->hopping_id); + printf("getting index for LUT with %d entries, Nid %d\n", gNB->pucch0_lut.nb_id, pucch_pdu->hopping_id); #endif - for (i=0;ipucch0_lut.nb_id;i++) { - if (gNB->pucch0_lut.Nid[i] == pucch_pdu->hopping_id) break; + for (i = 0; i < gNB->pucch0_lut.nb_id; i++) { + if (gNB->pucch0_lut.Nid[i] == pucch_pdu->hopping_id) + break; } #ifdef DEBUG_NR_PUCCH_RX - printf("found index %d\n",i); + printf("found index %d\n", i); #endif - if (ipucch0_lut.nb_id) return(i); + if (i < gNB->pucch0_lut.nb_id) + return (i); #ifdef DEBUG_NR_PUCCH_RX - printf("Initializing PUCCH0 LUT index %i with Nid %d\n",i, pucch_pdu->hopping_id); + printf("Initializing PUCCH0 LUT index %i with Nid %d\n", i, pucch_pdu->hopping_id); #endif // initialize - gNB->pucch0_lut.Nid[gNB->pucch0_lut.nb_id]=pucch_pdu->hopping_id; - for (int slot=0;slot<10<subcarrier_spacing;slot++) - for (int symbol=0;symbol<14;symbol++) - gNB->pucch0_lut.lut[gNB->pucch0_lut.nb_id][slot][symbol] = (int)floor(nr_cyclic_shift_hopping(pucch_pdu->hopping_id,0,0,symbol,0,slot)/0.5235987756); + gNB->pucch0_lut.Nid[gNB->pucch0_lut.nb_id] = pucch_pdu->hopping_id; + for (int slot = 0; slot < 10 << pucch_pdu->subcarrier_spacing; slot++) + for (int symbol = 0; symbol < 14; symbol++) + gNB->pucch0_lut.lut[gNB->pucch0_lut.nb_id][slot][symbol] = + (int)floor(nr_cyclic_shift_hopping(pucch_pdu->hopping_id, 0, 0, symbol, 0, slot) / 0.5235987756); gNB->pucch0_lut.nb_id++; - return(gNB->pucch0_lut.nb_id-1); + return (gNB->pucch0_lut.nb_id - 1); } - -static const int16_t idft12_re[12][12] = { - {23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170,23170}, - {23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066}, - {23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585}, - {23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0}, - {23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585}, - {23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066}, - {23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170,23170,-23170}, - {23170,-20066,11585,0,-11585,20066,-23170,20066,-11585,0,11585,-20066}, - {23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585,23170,-11585,-11585}, - {23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170,0}, - {23170,11585,-11585,-23170,-11585,11585,23170,11585,-11585,-23170,-11585,11585}, - {23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585,0,11585,20066} -}; -static const int16_t idft12_im[12][12] = { - {0,0,0,0,0,0,0,0,0,0,0,0}, - {0,11585,20066,23170,20066,11585,0,-11585,-20066,-23170,-20066,-11585}, - {0,20066,20066,0,-20066,-20066,0,20066,20066,0,-20066,-20066}, - {0,23170,0,-23170,0,23170,0,-23170,0,23170,0,-23170}, - {0,20066,-20066,0,20066,-20066,0,20066,-20066,0,20066,-20066}, - {0,11585,-20066,23170,-20066,11585,0,-11585,20066,-23170,20066,-11585}, - {0,0,0,0,0,0,0,0,0,0,0,0}, - {0,-11585,20066,-23170,20066,-11585,0,11585,-20066,23170,-20066,11585}, - {0,-20066,20066,0,-20066,20066,0,-20066,20066,0,-20066,20066}, - {0,-23170,0,23170,0,-23170,0,23170,0,-23170,0,23170}, - {0,-20066,-20066,0,20066,20066,0,-20066,-20066,0,20066,20066}, - {0,-11585,-20066,-23170,-20066,-11585,0,11585,20066,23170,20066,11585} -}; +static const int16_t idft12_re[12][12] = { + {23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170}, + {23170, 20066, 11585, 0, -11585, -20066, -23170, -20066, -11585, 0, 11585, 20066}, + {23170, 11585, -11585, -23170, -11585, 11585, 23170, 11585, -11585, -23170, -11585, 11585}, + {23170, 0, -23170, 0, 23170, 0, -23170, 0, 23170, 0, -23170, 0}, + {23170, -11585, -11585, 23170, -11585, -11585, 23170, -11585, -11585, 23170, -11585, -11585}, + {23170, -20066, 11585, 0, -11585, 20066, -23170, 20066, -11585, 0, 11585, -20066}, + {23170, -23170, 23170, -23170, 23170, -23170, 23170, -23170, 23170, -23170, 23170, -23170}, + {23170, -20066, 11585, 0, -11585, 20066, -23170, 20066, -11585, 0, 11585, -20066}, + {23170, -11585, -11585, 23170, -11585, -11585, 23170, -11585, -11585, 23170, -11585, -11585}, + {23170, 0, -23170, 0, 23170, 0, -23170, 0, 23170, 0, -23170, 0}, + {23170, 11585, -11585, -23170, -11585, 11585, 23170, 11585, -11585, -23170, -11585, 11585}, + {23170, 20066, 11585, 0, -11585, -20066, -23170, -20066, -11585, 0, 11585, 20066}}; + +static const int16_t idft12_im[12][12] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 11585, 20066, 23170, 20066, 11585, 0, -11585, -20066, -23170, -20066, -11585}, + {0, 20066, 20066, 0, -20066, -20066, 0, 20066, 20066, 0, -20066, -20066}, + {0, 23170, 0, -23170, 0, 23170, 0, -23170, 0, 23170, 0, -23170}, + {0, 20066, -20066, 0, 20066, -20066, 0, 20066, -20066, 0, 20066, -20066}, + {0, 11585, -20066, 23170, -20066, 11585, 0, -11585, 20066, -23170, 20066, -11585}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, -11585, 20066, -23170, 20066, -11585, 0, 11585, -20066, 23170, -20066, 11585}, + {0, -20066, 20066, 0, -20066, 20066, 0, -20066, 20066, 0, -20066, 20066}, + {0, -23170, 0, 23170, 0, -23170, 0, 23170, 0, -23170, 0, 23170}, + {0, -20066, -20066, 0, 20066, 20066, 0, -20066, -20066, 0, 20066, 20066}, + {0, -11585, -20066, -23170, -20066, -11585, 0, 11585, 20066, 23170, 20066, 11585}}; //************************************************************************// void nr_decode_pucch0(PHY_VARS_gNB *gNB, c16_t **rxdataF, @@ -177,24 +175,32 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int nr_sequences; const uint8_t *mcs; - if(pucch_pdu->bit_len_harq==0){ - mcs=table1_mcs; - nr_sequences=1; - } - else if(pucch_pdu->bit_len_harq==1){ - mcs=table1_mcs; - nr_sequences=4>>(1-pucch_pdu->sr_flag); - } - else{ - mcs=table2_mcs; - nr_sequences=8>>(1-pucch_pdu->sr_flag); + if (pucch_pdu->bit_len_harq == 0) { + mcs = table1_mcs; + nr_sequences = 1; + } else if (pucch_pdu->bit_len_harq == 1) { + mcs = table1_mcs; + nr_sequences = 4 >> (1 - pucch_pdu->sr_flag); + } else { + mcs = table2_mcs; + nr_sequences = 8 >> (1 - pucch_pdu->sr_flag); } - LOG_D(PHY,"pucch0: nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, O_ACK %d, O_SR %d, mcs %d initial_cyclic_shift %d\n", - pucch_pdu->nr_of_symbols,pucch_pdu->start_symbol_index,pucch_pdu->prb_start,pucch_pdu->second_hop_prb,pucch_pdu->group_hop_flag,pucch_pdu->sequence_hop_flag,pucch_pdu->bit_len_harq, - pucch_pdu->sr_flag,mcs[0],pucch_pdu->initial_cyclic_shift); + LOG_D(PHY, + "pucch0: nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, O_ACK " + "%d, O_SR %d, mcs %d initial_cyclic_shift %d\n", + pucch_pdu->nr_of_symbols, + pucch_pdu->start_symbol_index, + pucch_pdu->prb_start, + pucch_pdu->second_hop_prb, + pucch_pdu->group_hop_flag, + pucch_pdu->sequence_hop_flag, + pucch_pdu->bit_len_harq, + pucch_pdu->sr_flag, + mcs[0], + pucch_pdu->initial_cyclic_shift); - int cs_ind = get_pucch0_cs_lut_index(gNB,pucch_pdu); + int cs_ind = get_pucch0_cs_lut_index(gNB, pucch_pdu); /* * Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 @@ -202,7 +208,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, * for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift * is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift */ - int prb_offset[2] = {pucch_pdu->bwp_start+pucch_pdu->prb_start, pucch_pdu->bwp_start+pucch_pdu->prb_start}; + int prb_offset[2] = {pucch_pdu->bwp_start + pucch_pdu->prb_start, pucch_pdu->bwp_start + pucch_pdu->prb_start}; pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag << 1); // the value of u,v (delta always 0 for PUCCH) has to be calculated according @@ -210,7 +216,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, uint8_t u[2] = {0}, v[2] = {0}; nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, 0, slot, u, v); // calculating u and v value first hop - LOG_D(PHY,"pucch0: u %d, v %d\n",u[0],v[0]); + LOG_D(PHY, "pucch0: u %d, v %d\n", u[0], v[0]); if (pucch_pdu->freq_hop_flag == 1) { nr_group_sequence_hopping(pucch_GroupHopping, @@ -219,47 +225,46 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, slot, &u[1], &v[1]); // calculating u and v value second hop - LOG_D(PHY,"pucch0 second hop: u %d, v %d\n",u[1],v[1]); + LOG_D(PHY, "pucch0 second hop: u %d, v %d\n", u[1], v[1]); prb_offset[1] = pucch_pdu->bwp_start + pucch_pdu->second_hop_prb; } - AssertFatal(pucch_pdu->nr_of_symbols < 3,"nr_of_symbols %d not allowed\n",pucch_pdu->nr_of_symbols); + AssertFatal(pucch_pdu->nr_of_symbols < 3, "nr_of_symbols %d not allowed\n", pucch_pdu->nr_of_symbols); uint32_t re_offset[2] = {0}; - const int16_t *x_re[2],*x_im[2]; + const int16_t *x_re[2], *x_im[2]; x_re[0] = table_5_2_2_2_2_Re[u[0]]; x_im[0] = table_5_2_2_2_2_Im[u[0]]; x_re[1] = table_5_2_2_2_2_Re[u[1]]; x_im[1] = table_5_2_2_2_2_Im[u[1]]; - c64_t xr[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][12] __attribute__((aligned(32))); + c64_t xr[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][12] __attribute__((aligned(32))); memset(xr, 0, frame_parms->nb_antennas_rx * pucch_pdu->nr_of_symbols * 12 * sizeof(c64_t)); - int64_t xrtmag=0,xrtmag_next=0; - uint8_t maxpos=0; - uint8_t index=0; + int64_t xrtmag = 0, xrtmag_next = 0; + uint8_t maxpos = 0; + uint8_t index = 0; - int nb_re_pucch = 12*pucch_pdu->prb_size; // prb size is 1 + int nb_re_pucch = 12 * pucch_pdu->prb_size; // prb size is 1 int64_t signal_energy = 0, signal_energy_ant0 = 0; - for (int l=0; lnr_of_symbols; l++) { + for (int l = 0; l < pucch_pdu->nr_of_symbols; l++) { uint8_t l2 = l + pucch_pdu->start_symbol_index; - re_offset[l] = (12*prb_offset[l]) + frame_parms->first_carrier_offset; - if (re_offset[l]>= frame_parms->ofdm_symbol_size) - re_offset[l]-=frame_parms->ofdm_symbol_size; + re_offset[l] = (12 * prb_offset[l]) + frame_parms->first_carrier_offset; + if (re_offset[l] >= frame_parms->ofdm_symbol_size) + re_offset[l] -= frame_parms->ofdm_symbol_size; - for (int aa=0;aanb_antennas_rx;aa++) { + for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { c16_t rp[nb_re_pucch]; memset(rp, 0, sizeof(rp)); c16_t *tmp_rp = &rxdataF[aa][soffset + l2 * frame_parms->ofdm_symbol_size]; - if(re_offset[l] + nb_re_pucch > frame_parms->ofdm_symbol_size) { - int neg_length = frame_parms->ofdm_symbol_size-re_offset[l]; - int pos_length = nb_re_pucch-neg_length; + if (re_offset[l] + nb_re_pucch > frame_parms->ofdm_symbol_size) { + int neg_length = frame_parms->ofdm_symbol_size - re_offset[l]; + int pos_length = nb_re_pucch - neg_length; memcpy(rp, &tmp_rp[re_offset[l]], neg_length * sizeof(*tmp_rp)); memcpy(&rp[neg_length], tmp_rp, pos_length * sizeof(*tmp_rp)); - } - else + } else memcpy(rp, &tmp_rp[re_offset[l]], nb_re_pucch * sizeof(*tmp_rp)); for (int n = 0; n < nb_re_pucch; n++) { @@ -279,20 +284,19 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, signal_energy_ant0 /= pucch_pdu->nr_of_symbols; int pucch_power_dBtimes10 = 10 * dB_fixed(signal_energy); - //int32_t no_corr = 0; + // int32_t no_corr = 0; int seq_index = 0; for (int i = 0; i < nr_sequences; i++) { c64_t corr[frame_parms->nb_antennas_rx][2]; - for (int aa=0;aanb_antennas_rx;aa++) { - for (int l=0;lnr_of_symbols;l++) { - seq_index = (pucch_pdu->initial_cyclic_shift+ - mcs[i]+ - gNB->pucch0_lut.lut[cs_ind][slot][l+pucch_pdu->start_symbol_index])%12; + for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + for (int l = 0; l < pucch_pdu->nr_of_symbols; l++) { + seq_index = + (pucch_pdu->initial_cyclic_shift + mcs[i] + gNB->pucch0_lut.lut[cs_ind][slot][l + pucch_pdu->start_symbol_index]) % 12; #ifdef DEBUG_NR_PUCCH_RX - printf("PUCCH symbol %d seq %d, seq_index %d, mcs %d\n",l,i,seq_index,mcs[i]); + printf("PUCCH symbol %d seq %d, seq_index %d, mcs %d\n", l, i, seq_index, mcs[i]); #endif - corr[aa][l]=(c64_t){0}; + corr[aa][l] = (c64_t){0}; for (int n = 0; n < 12; n++) { corr[aa][l].r += xr[aa][l][n].r * idft12_re[seq_index][n] + xr[aa][l][n].i * idft12_im[seq_index][n]; corr[aa][l].i += xr[aa][l][n].r * idft12_im[seq_index][n] - xr[aa][l][n].i * idft12_re[seq_index][n]; @@ -301,10 +305,14 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, corr[aa][l].i >>= 31; } } - LOG_D(PHY,"PUCCH IDFT[%d/%d] = (%ld,%ld)=>%f\n", - mcs[i],seq_index,corr[0][0].r,corr[0][0].i, - 10*log10((double)squaredMod(corr[0][0]))); - if (pucch_pdu->nr_of_symbols==2) + LOG_D(PHY, + "PUCCH IDFT[%d/%d] = (%ld,%ld)=>%f\n", + mcs[i], + seq_index, + corr[0][0].r, + corr[0][0].i, + 10 * log10((double)squaredMod(corr[0][0]))); + if (pucch_pdu->nr_of_symbols == 2) LOG_D(PHY, "PUCCH 2nd symbol IDFT[%d/%d] = (%ld,%ld)=>%f\n", mcs[i], @@ -332,33 +340,32 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, temp += squaredMod(corr[aa][0]) + squaredMod(corr[aa][1]); } - if (temp>xrtmag) { + if (temp > xrtmag) { xrtmag_next = xrtmag; - xrtmag=temp; - LOG_D(PHY,"Sequence %d xrtmag %ld xrtmag_next %ld\n", i, xrtmag, xrtmag_next); - maxpos=i; + xrtmag = temp; + LOG_D(PHY, "Sequence %d xrtmag %ld xrtmag_next %ld\n", i, xrtmag, xrtmag_next); + maxpos = i; uci_stats->current_pucch0_stat0 = 0; - int64_t temp2=0,temp3=0;; - for (int aa=0;aanb_antennas_rx;aa++) { + int64_t temp2 = 0, temp3 = 0; + for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { temp2 += squaredMod(corr[aa][0]); - if (pucch_pdu->nr_of_symbols==2) + if (pucch_pdu->nr_of_symbols == 2) temp3 += squaredMod(corr[aa][1]); } - uci_stats->current_pucch0_stat0= dB_fixed64(temp2); - if ( pucch_pdu->nr_of_symbols==2) + uci_stats->current_pucch0_stat0 = dB_fixed64(temp2); + if (pucch_pdu->nr_of_symbols == 2) uci_stats->current_pucch0_stat1 = dB_fixed64(temp3); - } - else if (temp>xrtmag_next) + } else if (temp > xrtmag_next) xrtmag_next = temp; } - int xrtmag_dBtimes10 = 10*(int)dB_fixed64(xrtmag/(12*pucch_pdu->nr_of_symbols)); - int xrtmag_next_dBtimes10 = 10*(int)dB_fixed64(xrtmag_next/(12*pucch_pdu->nr_of_symbols)); + int xrtmag_dBtimes10 = 10 * (int)dB_fixed64(xrtmag / (12 * pucch_pdu->nr_of_symbols)); + int xrtmag_next_dBtimes10 = 10 * (int)dB_fixed64(xrtmag_next / (12 * pucch_pdu->nr_of_symbols)); #ifdef DEBUG_NR_PUCCH_RX - printf("PUCCH 0 : maxpos %d\n",maxpos); + printf("PUCCH 0 : maxpos %d\n", maxpos); #endif - index=maxpos; + index = maxpos; int pucch0_n00 = gNB->measurements.n0_subband_power_tot_dB[prb_offset[0]]; int pucch0_n01 = gNB->measurements.n0_subband_power_tot_dB[prb_offset[1]]; LOG_D(PHY, "n00[%d] = %d, n01[%d] = %d\n", prb_offset[0], pucch0_n00, prb_offset[1], pucch0_n01); @@ -379,10 +386,10 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, else cqi = (640 + SNRtimes10) / 5; - bool no_conf=false; - if (nr_sequences>1) { + bool no_conf = false; + if (nr_sequences > 1) { if (/*xrtmag_dBtimes10 < (30+xrtmag_next_dBtimes10) ||*/ SNRtimes10 < gNB->pucch0_thres) { - no_conf=true; + no_conf = true; LOG_D(PHY, "%d.%d PUCCH bad confidence: %d threshold, %d, %d, %d\n", frame, @@ -395,28 +402,27 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, } gNB->bad_pucch += no_conf; // first bit of bitmap for sr presence and second bit for acknack presence - uci_pdu->pduBitmap = pucch_pdu->sr_flag | ((pucch_pdu->bit_len_harq>0)<<1); + uci_pdu->pduBitmap = pucch_pdu->sr_flag | ((pucch_pdu->bit_len_harq > 0) << 1); uci_pdu->pucch_format = 0; // format 0 uci_pdu->rnti = pucch_pdu->rnti; uci_pdu->ul_cqi = cqi; uci_pdu->timing_advance = 0xffff; // currently not valid uci_pdu->rssi = 1280 - (10 * dB_fixed(32767 * 32767) - dB_fixed_times10(signal_energy_ant0)); - if (pucch_pdu->bit_len_harq==0) { + if (pucch_pdu->bit_len_harq == 0) { uci_pdu->sr.sr_confidence_level = SNRtimes10 < gNB->pucch0_thres; uci_stats->pucch0_sr_trials++; - if (xrtmag_dBtimes10>(10*max_n0+100)) { + if (xrtmag_dBtimes10 > (10 * max_n0 + 100)) { uci_pdu->sr.sr_indication = 1; uci_stats->pucch0_positive_SR++; - LOG_D(PHY,"PUCCH0 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch0_positive_SR); + LOG_D(PHY, "PUCCH0 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch0_positive_SR); } else { uci_pdu->sr.sr_indication = 0; } - } - else if (pucch_pdu->bit_len_harq==1) { + } else if (pucch_pdu->bit_len_harq == 1) { uci_pdu->harq.num_harq = 1; uci_pdu->harq.harq_confidence_level = no_conf; - uci_pdu->harq.harq_list[0].harq_value = !(index&0x01); + uci_pdu->harq.harq_list[0].harq_value = !(index & 0x01); LOG_D(PHY, "[DLSCH/PDSCH/PUCCH] %d.%d HARQ %s with confidence level %s xrt_mag " "%d xrt_mag_next %d pucch_power_dBtimes10 %d n0 %d " @@ -438,23 +444,23 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, 10 * log10((double)signal_energy_ant0)); if (pucch_pdu->sr_flag == 1) { - uci_pdu->sr.sr_indication = (index>1); + uci_pdu->sr.sr_indication = (index > 1); uci_pdu->sr.sr_confidence_level = no_conf; - if(uci_pdu->sr.sr_indication == 1 && uci_pdu->sr.sr_confidence_level == 0) { + if (uci_pdu->sr.sr_indication == 1 && uci_pdu->sr.sr_confidence_level == 0) { uci_stats->pucch0_positive_SR++; - LOG_D(PHY,"PUCCH0 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch0_positive_SR); + LOG_D(PHY, "PUCCH0 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch0_positive_SR); } } uci_stats->pucch01_trials++; - } - else { + } else { uci_pdu->harq.num_harq = 2; uci_pdu->harq.harq_confidence_level = no_conf; - uci_pdu->harq.harq_list[1].harq_value = !(index&0x01); - uci_pdu->harq.harq_list[0].harq_value = !((index>>1)&0x01); + uci_pdu->harq.harq_list[1].harq_value = !(index & 0x01); + uci_pdu->harq.harq_list[0].harq_value = !((index >> 1) & 0x01); LOG_D(PHY, - "[DLSCH/PDSCH/PUCCH] %d.%d HARQ values (%s, %s) with confidence level %s, xrt_mag %d xrt_mag_next %d pucch_power_dBtimes10 %d n0 %d (%d,%d) " + "[DLSCH/PDSCH/PUCCH] %d.%d HARQ values (%s, %s) with confidence level %s, xrt_mag %d xrt_mag_next %d " + "pucch_power_dBtimes10 %d n0 %d (%d,%d) " "pucch0_thres %d, cqi %d, SNRtimes10 %d\n", frame, slot, @@ -471,34 +477,26 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, cqi, SNRtimes10); if (pucch_pdu->sr_flag == 1) { - uci_pdu->sr.sr_indication = (index>3) ? 1 : 0; + uci_pdu->sr.sr_indication = (index > 3) ? 1 : 0; uci_pdu->sr.sr_confidence_level = no_conf; - if(uci_pdu->sr.sr_indication == 1 && uci_pdu->sr.sr_confidence_level == 0) { + if (uci_pdu->sr.sr_indication == 1 && uci_pdu->sr.sr_confidence_level == 0) { uci_stats->pucch0_positive_SR++; - LOG_D(PHY,"PUCCH0 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch0_positive_SR); + LOG_D(PHY, "PUCCH0 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch0_positive_SR); } } } } //*****************************************************************// -void nr_decode_pucch1(c16_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_pucch1(PHY_VARS_gNB *gNB, + c16_t **rxdataF, + int frame, + int slot, + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu, + nfapi_nr_pucch_pdu_t *pucch_pdu) { #ifdef DEBUG_NR_PUCCH_RX printf( - "\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d " + "\t [nr_decode_pucch1] start function at slot(nr_tti_tx)=%d " "payload=%lux m0=%d nrofSymbols=%d startingSymbolIndex=%d " "startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d " "nr_bit=%d\n", @@ -510,19 +508,23 @@ void nr_decode_pucch1(c16_t **rxdataF, startingPRB, startingPRB_intraSlotHopping, timeDomainOCC, - nr_bit); + pucch_pdu->bit_len_harq); #endif /* * Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation * */ - const int soffset = (nr_tti_tx % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; - // 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] - const int lprime = startingSymbolIndex; + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + uint8_t n_rx = frame_parms->nb_antennas_rx; + + const int soffset = (slot & 3) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; + // 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] + const int lprime = pucch_pdu->start_symbol_index; // mcs = 0 except for PUCCH format 0 const uint8_t mcs = 0; - // r_u_v_alpha_delta_re and r_u_v_alpha_delta_im tables containing the sequence y(n) for the PUCCH, when they are multiplied by d(0) - // r_u_v_alpha_delta_dmrs_re and r_u_v_alpha_delta_dmrs_im tables containing the sequence for the DM-RS. + // r_u_v_alpha_delta_re and r_u_v_alpha_delta_im tables containing the sequence y(n) for the PUCCH, when they are multiplied by + // d(0) r_u_v_alpha_delta_dmrs_re and r_u_v_alpha_delta_dmrs_im tables containing the sequence for the DM-RS. c16_t r_u_v_alpha_delta[12], r_u_v_alpha_delta_dmrs[12]; /* * in TS 38.213 Subclause 9.2.1 it is said that: @@ -533,86 +535,143 @@ void nr_decode_pucch1(c16_t **rxdataF, * the complex-valued symbol d_0 shall be multiplied with a sequence r_u_v_alpha_delta(n): y(n) = d_0 * r_u_v_alpha_delta(n) */ // the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1 - uint8_t u=0,v=0;//,delta=0; + uint8_t u = 0, v = 0; //,delta=0; // Intra-slot frequency hopping shall be assumed when the higher-layer parameter intraSlotFrequencyHopping is provided, // regardless of whether the frequency-hop distance is zero or not, // otherwise no intra-slot frequency hopping shall be assumed - //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers - const bool intraSlotFrequencyHopping = startingPRB != startingPRB_intraSlotHopping; + // uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers + const bool intraSlotFrequencyHopping = pucch_pdu->prb_start != pucch_pdu->second_hop_prb; + float inv_sqrt2 = 0.70710678118f; // 1 / sqrt(2) + int64_t signal_energy = 0, signal_energy_ant0 = 0; + uint8_t nb_re_pucch = pucch_pdu->prb_size * 12; + pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag << 1); + int16_t amp = 0x7FFF; + int xrtmag_dBtimes10 = 0; + + NR_gNB_UCI_STATS_t stack_uci_stats = {0}; + NR_gNB_UCI_STATS_t *uci_stats = &stack_uci_stats; + NR_gNB_PHY_STATS_t *phy_stats = get_phy_stats(gNB, pucch_pdu->rnti); + if (phy_stats != NULL) { + phy_stats->frame = frame; + uci_stats = &phy_stats->uci_stats; + } #ifdef DEBUG_NR_PUCCH_RX - printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n",intraSlotFrequencyHopping); + printf("\t [nr_decode_pucch1] intraSlotFrequencyHopping = %d \n", intraSlotFrequencyHopping); + printf("\t [nr_decode_pucch1] soffset= %d\n", soffset); #endif /* * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources */ -#define MAX_SIZE_Z 168 // this value has to be calculated from mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n - c16_t z_rx[MAX_SIZE_Z] = {0}; - c16_t z_dmrs_rx[MAX_SIZE_Z] = {0}; +// This value has to be calculated from mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n +#define MAX_SIZE_Z 168 + c16_t z_rx[16][MAX_SIZE_Z] = {0}; + c16_t z_dmrs_rx[16][MAX_SIZE_Z] = {0}; + c16_t z[16][12] = {0}; const int half_nb_rb_dl = frame_parms->N_RB_DL >> 1; const bool nb_rb_is_even = (frame_parms->N_RB_DL & 1) == 0; - for (int l = 0; l < nrofSymbols; l++) { // extracting data and dmrs from rxdataF - if (intraSlotFrequencyHopping && (l < floor(nrofSymbols / 2))) { // intra-slot hopping enabled, we need - // to calculate new offset PRB - startingPRB = startingPRB + startingPRB_intraSlotHopping; + for (int l = 0; l < pucch_pdu->nr_of_symbols; l++) { // extracting data and dmrs from rxdataF + if (intraSlotFrequencyHopping && (l >= floor(pucch_pdu->nr_of_symbols / 2))) { // intra-slot hopping enabled, we need + // to calculate new offset PRB + pucch_pdu->prb_start = pucch_pdu->bwp_start + pucch_pdu->second_hop_prb; } - int re_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size; + int re_offset = (l + pucch_pdu->start_symbol_index) * frame_parms->ofdm_symbol_size; if (nb_rb_is_even) { - if (startingPRB < half_nb_rb_dl) // if number RBs in bandwidth is even and - // current PRB is lower band - re_offset += 12 * startingPRB + frame_parms->first_carrier_offset; + if (pucch_pdu->prb_start < half_nb_rb_dl) // if number RBs in bandwidth is even and + // current PRB is lower band + re_offset += 12 * pucch_pdu->prb_start + frame_parms->first_carrier_offset; else // if number RBs in bandwidth is even and current PRB is upper band - re_offset += 12 * (startingPRB - half_nb_rb_dl); + re_offset += 12 * (pucch_pdu->prb_start - half_nb_rb_dl); } else { - if (startingPRB < half_nb_rb_dl) // if number RBs in bandwidth is odd and - // current PRB is lower band - re_offset += 12 * startingPRB + frame_parms->first_carrier_offset; - else if (startingPRB > half_nb_rb_dl) // if number RBs in bandwidth is odd - // and current PRB is upper band - re_offset += 12 * (startingPRB - half_nb_rb_dl) + 6; + if (pucch_pdu->prb_start < half_nb_rb_dl) // if number RBs in bandwidth is odd and + // current PRB is lower band + re_offset += 12 * pucch_pdu->prb_start + frame_parms->first_carrier_offset; + else if (pucch_pdu->prb_start > half_nb_rb_dl) // if number RBs in bandwidth is odd + // and current PRB is upper band + re_offset += 12 * (pucch_pdu->prb_start - half_nb_rb_dl) + 6; else // if number RBs in bandwidth is odd and current PRB contains DC - re_offset += 12 * startingPRB + frame_parms->first_carrier_offset; + re_offset += 12 * pucch_pdu->prb_start + frame_parms->first_carrier_offset; } - for (int n=0; n<12; n++) { - const int current_subcarrier = l * 12 + n; - if (n == 6 && startingPRB == half_nb_rb_dl && !nb_rb_is_even) { - // 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); + for (int n = 0; n < 12; n++) { + const int current_subcarrier = (l / 2) * 12 + n; + if (n == 6 && pucch_pdu->prb_start == half_nb_rb_dl && !nb_rb_is_even) { + // 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 + pucch_pdu->start_symbol_index) * frame_parms->ofdm_symbol_size); } if (l % 2 == 1) // mapping PUCCH or DM-RS according to TS38.211 subclause 6.4.1.3.1 - z_rx[current_subcarrier] = rxdataF[0][soffset + re_offset]; + for (int r = 0; r < n_rx; r++) { + z_rx[r][current_subcarrier] = rxdataF[r][soffset + re_offset]; + z[r][n] = z_rx[r][current_subcarrier]; + } else - z_dmrs_rx[current_subcarrier] = rxdataF[0][soffset + re_offset]; + for (int r = 0; r < n_rx; r++) { + z_dmrs_rx[r][current_subcarrier] = rxdataF[r][soffset + re_offset]; + z[r][n] = z_dmrs_rx[r][current_subcarrier]; + } + #ifdef DEBUG_NR_PUCCH_RX printf( - "\t [nr_generate_pucch1] mapping %s to RE \t amp=%d " + "\t [nr_decode_pucch1] mapping %s to RE \t amp=%d " "\tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d " - "\tz_pucch[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", + "\tz_pucch[%d]=rxptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", l % 2 ? "PUCCH" : "DM-RS", amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, current_subcarrier, - re_offset, + soffset + re_offset, l, n, rxdataF[0][soffset + re_offset].r, rxdataF[0][soffset + re_offset].i); #endif re_offset++; + } // end sc loop + + // compute signal energy + + for (int r = 0; r < n_rx; r++) { + int energ = signal_energy_nodc(z[r], nb_re_pucch); + signal_energy += energ; + if (!r) + signal_energy_ant0 += energ; } - } - cd_t y_n[12] = {0}, y1_n[12] = {0}; - //generating transmitted sequence and dmrs - for (int l = 0; l < nrofSymbols; l++) { + + } // end symbols loop + + signal_energy /= (pucch_pdu->nr_of_symbols * n_rx); + signal_energy_ant0 /= pucch_pdu->nr_of_symbols; + int pucch_power_dBtimes10 = 10 * dB_fixed(signal_energy); + int max_n0 = max(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->bwp_start + pucch_pdu->prb_start], + gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->bwp_start + pucch_pdu->second_hop_prb]); + const int SNRtimes10 = pucch_power_dBtimes10 - (10 * max_n0); + + LOG_D(PHY, + "signal_energy %lld signal_energy_ant0 %lld pucch_power_dBtimes10 %d max_n0 %d SNRtimes10 %d\n", + (long long)signal_energy, + (long long)signal_energy_ant0, + pucch_power_dBtimes10, + max_n0, + SNRtimes10); + int cqi; + if (SNRtimes10 < -640) + cqi = 0; + else if (SNRtimes10 > 635) + cqi = 255; + else + cqi = (640 + SNRtimes10) / 5; + + cd_t y[16] = {0}, y1[16] = {0}; + // generating transmitted sequence and dmrs + for (int l = 0; l < pucch_pdu->nr_of_symbols; l++) { #ifdef DEBUG_NR_PUCCH_RX - printf("\t [nr_generate_pucch1] for symbol l=%d, lprime=%d\n", - l,lprime); + printf("\t [nr_decode_pucch1] for symbol l=%d, lprime=%d\n", l, lprime); #endif // y_n contains the complex value d multiplied by the sequence r_u_v // if frequency hopping is disabled, intraSlotFrequencyHopping is not @@ -621,45 +680,29 @@ void nr_decode_pucch1(c16_t **rxdataF, // if frequency hopping is enabled, intraSlotFrequencyHopping is provided // n_hop = 0 for first hop // n_hop = 1 for second hop - const int n_hop = intraSlotFrequencyHopping && l >= nrofSymbols / 2 ? 1 : 0; + const int n_hop = intraSlotFrequencyHopping && l >= pucch_pdu->nr_of_symbols / 2 ? 1 : 0; #ifdef DEBUG_NR_PUCCH_RX - printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n", - n_hop,nr_tti_tx); + printf("\t [nr_decode_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n", n_hop, slot); #endif - nr_group_sequence_hopping(pucch_GroupHopping,n_id,n_hop,nr_tti_tx,&u,&v); // calculating u and v value + nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, n_hop, slot, &u, &v); // calculating u and v value // Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 - double alpha = nr_cyclic_shift_hopping(n_id, m0, mcs, l, lprime, nr_tti_tx); - for (int n=0; n<12; n++) { // generating low papr sequences + double alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id, pucch_pdu->initial_cyclic_shift, mcs, l, lprime, slot); + for (int n = 0; n < 12; n++) { // generating low papr sequences const c16_t angle = {lround(32767 * cos(alpha * n)), lround(32767 * sin(alpha * n))}; const c16_t table = {table_5_2_2_2_2_Re[u][n], table_5_2_2_2_2_Im[u][n]}; if (l % 2 == 1) r_u_v_alpha_delta[n] = c16mulShift(angle, table, 15); else r_u_v_alpha_delta_dmrs[n] = c16mulRealShift(c16mulShift(angle, table, 15), amp, 15); -#ifdef DEBUG_NR_PUCCH_RX - printf( - "\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d " - "\talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) " - "\ty_n[n=%d]=(%f,%f)\n", - u, - v, - alpha, - n, - r_u_v_alpha_delta[n].r, - r_u_v_alpha_delta[n].i, - n, - y_n[n].r, - y_n[n].i); -#endif } /* * The block of complex-valued symbols y(n) shall be block-wise spread with the orthogonal sequence wi(m) * (defined in table_6_3_2_4_1_2_Wi_Re and table_6_3_2_4_1_2_Wi_Im) * z(mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n)=wi(m)*y(n) * - * The block of complex-valued symbols r_u_v_alpha_dmrs_delta(n) for DM-RS shall be block-wise spread with the orthogonal sequence wi(m) - * (defined in table_6_3_2_4_1_2_Wi_Re and table_6_3_2_4_1_2_Wi_Im) + * The block of complex-valued symbols r_u_v_alpha_dmrs_delta(n) for DM-RS shall be block-wise spread with the orthogonal + * sequence wi(m) (defined in table_6_3_2_4_1_2_Wi_Re and table_6_3_2_4_1_2_Wi_Im) * z(mprime*12*table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n)=wi(m)*y(n) * */ @@ -667,11 +710,13 @@ void nr_decode_pucch1(c16_t **rxdataF, // the index of the orthogonal cover code is from a set determined as described in [4, TS 38.211] // and is indicated by higher layer parameter PUCCH-F1-time-domain-OCC // In the PUCCH_Config IE, the PUCCH-format1, timeDomainOCC field - const int w_index = timeDomainOCC; + const int w_index = pucch_pdu->time_domain_occ_idx; if (intraSlotFrequencyHopping == false) { // intra-slot hopping disabled #ifdef DEBUG_NR_PUCCH_RX - printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n", - intraSlotFrequencyHopping); + printf( + "\t [nr_decode_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, " + "intra-slot hopping disabled\n", + intraSlotFrequencyHopping); #endif // mprime is 0 in this not hopping case // N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1 @@ -686,35 +731,39 @@ void nr_decode_pucch1(c16_t **rxdataF, // symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled) // mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot // hopping - int N_SF_mprime_PUCCH_1 = - table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols - 1]; // only if intra-slot hopping not enabled (PUCCH) - int N_SF_mprime_PUCCH_DMRS_1 = - table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols - 1]; // only if intra-slot hopping not enabled (DM-RS) - if(l%2==1){ - for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { + // only if intra-slot hopping not enabled (PUCCH) + int N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_pdu->nr_of_symbols - 1]; + // only if intra-slot hopping not enabled (DM-RS) + int N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_pdu->nr_of_symbols - 1]; + if (l % 2 == 1) { + for (int m = 0; m < N_SF_mprime_PUCCH_1; m++) { c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m], table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]}; if (l / 2 == m) { - for (int n = 0; n < 12; n++) { - c16_t *zPtr = z_rx + m * 12 + n; - *zPtr = c16MulConjShift(table, *zPtr, 15); - // multiplying with conjugate of low papr sequence - *zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 16); + for (int r = 0; r < n_rx; r++) { + for (int n = 0; n < 12; n++) { + c16_t *zPtr = z_rx[r] + m * 12 + n; + *zPtr = c16MulConjShift(table, *zPtr, 15); + // multiplying with conjugate of low papr sequence + *zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 16); + } } } } } else { - for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { + for (int m = 0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { const c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m], table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m]}; if (l / 2 == m) { - for (int n = 0; n < 12; n++) { - c16_t *zDmrsPtr = z_dmrs_rx + m * 12 + n; - *zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15); - // finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and - // z_dmrs_im_rx arrays - *zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 16); + for (int r = 0; r < n_rx; r++) { + for (int n = 0; n < 12; n++) { + c16_t *zDmrsPtr = z_dmrs_rx[r] + m * 12 + n; + *zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15); + // finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and + // z_dmrs_im_rx arrays + *zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 16); + } } } } @@ -723,8 +772,10 @@ void nr_decode_pucch1(c16_t **rxdataF, if (intraSlotFrequencyHopping == true) { // intra-slot hopping enabled #ifdef DEBUG_NR_PUCCH_RX - printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n", - intraSlotFrequencyHopping); + printf( + "\t [nr_decode_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, " + "intra-slot hopping enabled\n", + intraSlotFrequencyHopping); #endif // N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1 // (depending on number of PUCCH symbols nrofSymbols, mprime and @@ -738,17 +789,24 @@ void nr_decode_pucch1(c16_t **rxdataF, // symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled) // mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot // hopping - int N_SF_mprime_PUCCH_1 = - table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH) - int N_SF_mprime_PUCCH_DMRS_1 = - table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS) - int N_SF_mprime0_PUCCH_1 = - table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH) - int N_SF_mprime0_PUCCH_DMRS_1 = - table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS) + + // only if intra-slot hopping enabled mprime = 0 (PUCCH) + int N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[pucch_pdu->nr_of_symbols - 1]; + // only if intra-slot hopping enabled mprime = 0 (DM-RS) + int N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[pucch_pdu->nr_of_symbols - 1]; + // only if intra-slot hopping enabled mprime = 0 (PUCCH) + int N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[pucch_pdu->nr_of_symbols - 1]; + // only if intra-slot hopping enabled mprime = 0 (DM-RS) + int N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[pucch_pdu->nr_of_symbols - 1]; #ifdef DEBUG_NR_PUCCH_RX - printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n", - w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1); + printf( + "\t [nr_decode_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, " + "N_SF_mprime0_PUCCH_DMRS_1 = %d\n", + w_index, + N_SF_mprime_PUCCH_1, + N_SF_mprime_PUCCH_DMRS_1, + N_SF_mprime0_PUCCH_1, + N_SF_mprime0_PUCCH_DMRS_1); #endif for (int mprime = 0; mprime < 2; mprime++) { // mprime can get values {0,1} @@ -757,10 +815,12 @@ void nr_decode_pucch1(c16_t **rxdataF, c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m], table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]}; if (floor(l / 2) * 12 == (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12)) { - for (int n = 0; n < 12; n++) { - c16_t *zPtr = z_rx + (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12) + n; - *zPtr = c16MulConjShift(table, *zPtr, 15); - *zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 16); + for (int r = 0; r < n_rx; r++) { + for (int n = 0; n < 12; n++) { + c16_t *zPtr = z_rx[r] + (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12) + n; + *zPtr = c16MulConjShift(table, *zPtr, 15); + *zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 15); + } } } } @@ -771,100 +831,285 @@ void nr_decode_pucch1(c16_t **rxdataF, c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m], table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]}; if (floor(l / 2) * 12 == (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 12)) { - for (int n = 0; n < 12; n++) { - c16_t *zDmrsPtr = z_dmrs_rx + (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 12) + n; - *zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15); - // finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and - // z_dmrs_im_rx arrays - *zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 16); + for (int r = 0; r < n_rx; r++) { + for (int n = 0; n < 12; n++) { + c16_t *zDmrsPtr = z_dmrs_rx[r] + (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 12) + n; + *zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15); + // finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and + // z_dmrs_im_rx arrays + *zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 15); + } } } } } N_SF_mprime_PUCCH_1 = - table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH) - N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS) + table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[pucch_pdu->nr_of_symbols + - 1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH) + N_SF_mprime_PUCCH_DMRS_1 = + table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[pucch_pdu->nr_of_symbols + - 1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS) } } - } - cd_t H[12] = {0}, H1[12] = {0}; - const double half_nb_symbols = nrofSymbols / 2.0; - const double quarter_nb_symbols = nrofSymbols / 4.0; - for (int l = 0; l <= half_nb_symbols; l++) { - if (intraSlotFrequencyHopping == false) { - for (int n = 0; n < 12; n++) { - H[n].r += z_dmrs_rx[l * 12 + n].r / half_nb_symbols; - H[n].i += z_dmrs_rx[l * 12 + n].i / half_nb_symbols; - y_n[n].r += z_rx[l * 12 + n].r / half_nb_symbols; - y_n[n].i += z_rx[l * 12 + n].i / half_nb_symbols; - } - } else { - if (l < nrofSymbols / 4) { + } // end of symbols loop + + cd_t H[16] = {0}, H1[16] = {0}; + const double half_nb_symbols = pucch_pdu->nr_of_symbols / 2.0; + for (int r = 0; r < n_rx; r++) { + for (int l = 0; l <= half_nb_symbols; l++) { + if (intraSlotFrequencyHopping == false) { for (int n = 0; n < 12; n++) { - H[n].r += z_dmrs_rx[l * 12 + n].r / quarter_nb_symbols; - H[n].i += z_dmrs_rx[l * 12 + n].i / quarter_nb_symbols; - y_n[n].r += z_rx[l * 12 + n].r / quarter_nb_symbols; - y_n[n].i += z_rx[l * 12 + n].i / quarter_nb_symbols; + H[r].r += z_dmrs_rx[r][l * 12 + n].r / half_nb_symbols / 12; + H[r].i += z_dmrs_rx[r][l * 12 + n].i / half_nb_symbols / 12; + y[r].r += z_rx[r][l * 12 + n].r / half_nb_symbols / 12; + y[r].i += z_rx[r][l * 12 + n].i / half_nb_symbols / 12; } - } else { - for (int n = 0; n < 12; n++) { - H1[n].r += z_dmrs_rx[l * 12 + n].r / quarter_nb_symbols; - H1[n].i += z_dmrs_rx[l * 12 + n].i / quarter_nb_symbols; - y1_n[n].r += z_rx[l * 12 + n].r / quarter_nb_symbols; - y1_n[n].i += z_rx[l * 12 + n].i / quarter_nb_symbols; + } else { // with Frequency-hopping + if (l < pucch_pdu->nr_of_symbols / 4) { + for (int n = 0; n < 12; n++) { + H[r].r += z_dmrs_rx[r][l * 12 + n].r / half_nb_symbols / 12; + H[r].i += z_dmrs_rx[r][l * 12 + n].i / half_nb_symbols / 12; + y[r].r += z_rx[r][l * 12 + n].r / half_nb_symbols / 12; + y[r].i += z_rx[r][l * 12 + n].i / half_nb_symbols / 12; + } + } else { + for (int n = 0; n < 12; n++) { + H1[r].r += z_dmrs_rx[r][l * 12 + n].r / half_nb_symbols / 12; + H1[r].i += z_dmrs_rx[r][l * 12 + n].i / half_nb_symbols / 12; + y1[r].r += z_rx[r][l * 12 + n].r / half_nb_symbols / 12; + y1[r].i += z_rx[r][l * 12 + n].i / half_nb_symbols / 12; + } } } } } // mrc combining to obtain z_re and z_im - cd_t d = {0}; - if (intraSlotFrequencyHopping == false) { - // complex-valued symbol d_re, d_im containing complex-valued symbol d(0): - for (int n = 0; n < 12; n++) { - d.r += H[n].r * y_n[n].r + H[n].i * y_n[n].i; - d.i += H[n].r * y_n[n].i - H[n].i * y_n[n].r; - } - } else { - for (int n = 0; n < 12; n++) { - d.r += H[n].r * y_n[n].r + H[n].i * y_n[n].i; - d.i += H[n].r * y_n[n].i - H[n].i * y_n[n].r; - d.r += H[n].r * y1_n[n].r + H[n].i * y1_n[n].i; - d.i += H[n].r * y1_n[n].i - H[n].i * y1_n[n].r; + cd_t dp1 = {0}, dm1 = {0}, d0 = {0}, d1 = {0}, d2 = {0}, d3 = {0}; + double dp1mag = 0, dm1mag = 0, d0mag = 0, d1mag = 0, d2mag = 0, d3mag = 0; + // complex-valued symbol d_re, d_im containing complex-valued symbol d(0): + for (int r = 0; r < n_rx; r++) { + if (pucch_pdu->bit_len_harq == 1) // BPSK + { + dp1.r = H[r].r + inv_sqrt2 * (y[r].r + y[r].i); + dp1.i = H[r].i + inv_sqrt2 * (y[r].i - y[r].r); + dm1.r = H[r].r + inv_sqrt2 * (-y[r].r - y[r].i); + dm1.i = H[r].i + inv_sqrt2 * (y[r].r - y[r].i); + dp1mag += squaredMod(dp1); + dm1mag += squaredMod(dm1); + + LOG_D(PHY, + "r %d y : (%f,%f) H (%f,%f) dp1 : (%f,%f) : %f dm1 : (%f,%f) : %f\n", + r, + y[r].r, + y[r].i, + H[r].r, + H[r].i, + dp1.r, + dp1.i, + dp1mag, + dm1.r, + dm1.i, + dm1mag); + + if (intraSlotFrequencyHopping == true) { + dp1.r = H1[r].r + inv_sqrt2 * (y1[r].r + y1[r].i); + dp1.i = H1[r].i + inv_sqrt2 * (y1[r].i - y1[r].r); + dm1.r = H1[r].r + inv_sqrt2 * (-y1[r].r - y1[r].i); + dm1.i = H1[r].i + inv_sqrt2 * (y1[r].r - y1[r].i); + dp1mag += squaredMod(dp1); + dm1mag += squaredMod(dm1); + } + if (r == n_rx - 1) { + if (dp1mag > dm1mag) { + uci_pdu->harq.harq_list[0].harq_value = 1; + xrtmag_dBtimes10 = 10 * (int)dB_fixed64(dp1mag / (12 * pucch_pdu->nr_of_symbols)); + } else { + //*payload = 1; + uci_pdu->harq.harq_list[0].harq_value = 0; + xrtmag_dBtimes10 = 10 * (int)dB_fixed64(dm1mag / (12 * pucch_pdu->nr_of_symbols)); + } + } + } else if (pucch_pdu->bit_len_harq == 2) // QPSK + { + // d0 = H + (1 - j)*y + d0.r = H[r].r + inv_sqrt2 * (y[r].r + y[r].i); + d0.i = H[r].i + inv_sqrt2 * (y[r].i - y[r].r); + d0mag += squaredMod(d0); + + // d1 = H + (-1 - j)*y + d1.r = H[r].r + inv_sqrt2 * (-y[r].r + y[r].i); + d1.i = H[r].i + inv_sqrt2 * (-y[r].r - y[r].i); + d1mag += squaredMod(d1); + + // d2 = H + (1 + j)*y + d2.r = H[r].r + inv_sqrt2 * (y[r].r - y[r].i); + d2.i = H[r].i + inv_sqrt2 * (y[r].i + y[r].r); + d2mag += squaredMod(d2); + + // d3 = H + (-1 + j)*y + d3.r = H[r].r + inv_sqrt2 * (-y[r].r - y[r].i); + d3.i = H[r].i + inv_sqrt2 * (y[r].r - y[r].i); + d3mag += squaredMod(d3); + + // with frequency hopping + if (intraSlotFrequencyHopping == true) { + d0.r = H1[r].r + inv_sqrt2 * (y1[r].r + y1[r].i); + d0.i = H1[r].i + inv_sqrt2 * (y1[r].i - y1[r].r); + d0mag += squaredMod(d0); + + d1.r = H1[r].r + inv_sqrt2 * (-y1[r].r + y1[r].i); + d1.i = H1[r].i + inv_sqrt2 * (-y1[r].r - y1[r].i); + d1mag += squaredMod(d1); + + d2.r = H1[r].r + inv_sqrt2 * (y1[r].r - y1[r].i); + d2.i = H1[r].i + inv_sqrt2 * (y1[r].i + y1[r].r); + d2mag += squaredMod(d2); + + d3.r = H1[r].r + inv_sqrt2 * (-y1[r].r - y1[r].i); + d3.i = H1[r].i + inv_sqrt2 * (y1[r].r - y1[r].i); + d3mag += squaredMod(d3); + } + + LOG_D(PHY, + "r %d y : (%f,%f) H (%f,%f) d0 : (%f,%f) : %f d1 : (%f,%f) : %f d2 : (%f,%f) : %f d3 : (%f,%f) : %f\n", + r, + y[r].r, + y[r].i, + H[r].r, + H[r].i, + d0.r, + d0.i, + d0mag, + d1.r, + d1.i, + d1mag, + d2.r, + d2.i, + d2mag, + d3.r, + d3.i, + d3mag); + + if (r == n_rx - 1) { + if (d0mag >= d1mag && d0mag >= d2mag && d0mag >= d3mag) { + uci_pdu->harq.harq_list[0].harq_value = 1; + uci_pdu->harq.harq_list[1].harq_value = 1; + xrtmag_dBtimes10 = 10 * (int)dB_fixed64(d0mag / (12 * pucch_pdu->nr_of_symbols)); + } else if (d1mag >= d0mag && d1mag >= d2mag && d1mag >= d3mag) { + uci_pdu->harq.harq_list[0].harq_value = 1; + uci_pdu->harq.harq_list[1].harq_value = 0; + xrtmag_dBtimes10 = 10 * (int)dB_fixed64(d1mag / (12 * pucch_pdu->nr_of_symbols)); + } else if (d2mag >= d0mag && d2mag >= d1mag && d2mag >= d3mag) { + uci_pdu->harq.harq_list[0].harq_value = 0; + uci_pdu->harq.harq_list[1].harq_value = 1; + xrtmag_dBtimes10 = 10 * (int)dB_fixed64(d2mag / (12 * pucch_pdu->nr_of_symbols)); + } else { + uci_pdu->harq.harq_list[0].harq_value = 0; + uci_pdu->harq.harq_list[1].harq_value = 0; + xrtmag_dBtimes10 = 10 * (int)dB_fixed64(d3mag / (12 * pucch_pdu->nr_of_symbols)); + } + } } } - //Decoding QPSK or BPSK symbols to obtain payload bits - if (nr_bit == 1) { - if ((d.r + d.i) > 0) { - *payload = 0; - } else { - *payload = 1; + + bool no_conf = false; + if (pucch_pdu->bit_len_harq > 0 || pucch_pdu->sr_flag > 0) { + if (/*xrtmag_dBtimes10 < (30+xrtmag_next_dBtimes10) ||*/ SNRtimes10 <= gNB->pucch0_thres) { + no_conf = true; + LOG_D(PHY, "%d.%d PUCCH F1 bad confidence: %d threshold, %d,\n", frame, slot, gNB->pucch0_thres, SNRtimes10); } - } else if (nr_bit == 2) { - if ((d.r > 0) && (d.i > 0)) { - *payload = 0; - } else if ((d.r < 0) && (d.i > 0)) { - *payload = 1; - } else if ((d.r > 0) && (d.i < 0)) { - *payload = 2; + } + gNB->bad_pucch += no_conf; + // first bit of bitmap for sr presence and second bit for acknack presence + uci_pdu->pduBitmap = pucch_pdu->sr_flag | ((pucch_pdu->bit_len_harq > 0) << 1); + uci_pdu->pucch_format = 1; // format 1 + uci_pdu->rnti = pucch_pdu->rnti; + uci_pdu->ul_cqi = cqi; + uci_pdu->timing_advance = 0xffff; // currently not valid + uci_pdu->rssi = 1280 - (10 * dB_fixed(32767 * 32767) - dB_fixed_times10(signal_energy_ant0)); + + if (pucch_pdu->bit_len_harq == 0) { + uci_pdu->sr.sr_confidence_level = SNRtimes10 < gNB->pucch0_thres; + uci_stats->pucch1_sr_trials++; + if (xrtmag_dBtimes10 >= (10 * max_n0 /*+100*/)) { + uci_pdu->sr.sr_indication = 1; + uci_stats->pucch1_positive_SR++; + LOG_D(PHY, "PUCCH1 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch1_positive_SR); } else { - *payload = 3; + uci_pdu->sr.sr_indication = 0; + } + } else if (pucch_pdu->bit_len_harq == 1) { + uci_pdu->harq.num_harq = 1; + uci_pdu->harq.harq_confidence_level = no_conf; + LOG_D(PHY, + "[PUCCH F1] %d.%d HARQ %s with confidence level %s" + " xrtmag_dBtimes10 %d pucch_power_dBtimes10 %d n0 %d " + "pucch0_thres %d, " + "cqi %d, SNRtimes10 %d, energy %f\n", + frame, + slot, + uci_pdu->harq.harq_list[0].harq_value == 0 ? "ACK" : "NACK", + uci_pdu->harq.harq_confidence_level == 0 ? "good" : "bad", + xrtmag_dBtimes10, + pucch_power_dBtimes10, + max_n0, + gNB->pucch0_thres, // using same pucch threshold for both pucch 0 and pucch 1. + cqi, + SNRtimes10, + 10 * log10((double)signal_energy_ant0)); + + if (pucch_pdu->sr_flag == 1) { + uci_pdu->sr.sr_indication = 0; // Upper layers determine if SR when the PUCCH resource is an SR resource or not + uci_pdu->sr.sr_confidence_level = no_conf; + if (uci_pdu->sr.sr_indication == 1 && uci_pdu->sr.sr_confidence_level == 0) { + uci_stats->pucch1_positive_SR++; + LOG_D(PHY, "PUCCH F1 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch1_positive_SR); + } + } + uci_stats->pucch11_trials++; + } else { + uci_pdu->harq.num_harq = 2; + uci_pdu->harq.harq_confidence_level = no_conf; + LOG_D(PHY, + "[PUCCH F1] %d.%d HARQ values (%s, %s) with confidence level %s, xrtmag_dBtimes10 %d pucch_power_dBtimes10 %d n0 %d " + "pucch0_thres %d, cqi %d, SNRtimes10 %d\n", + frame, + slot, + uci_pdu->harq.harq_list[1].harq_value == 0 ? "ACK" : "NACK", + uci_pdu->harq.harq_list[0].harq_value == 0 ? "ACK" : "NACK", + uci_pdu->harq.harq_confidence_level == 0 ? "good" : "bad", + xrtmag_dBtimes10, + pucch_power_dBtimes10, + max_n0, + gNB->pucch0_thres, // using same pucch threshold for both pucch 0 and pucch 1. + cqi, + SNRtimes10); + if (pucch_pdu->sr_flag == 1) { + uci_pdu->sr.sr_indication = 0; // Upper layers determine if SR when the PUCCH resource is an SR resource or not + uci_pdu->sr.sr_confidence_level = no_conf; + if (uci_pdu->sr.sr_indication == 1 && uci_pdu->sr.sr_confidence_level == 0) { + uci_stats->pucch1_positive_SR++; + LOG_D(PHY, "PUCCH F1 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch1_positive_SR); + } } } } -typedef struct {c16_t cw[16];} cw_t; -static cw_t pucch2_3bit[8] __attribute__((aligned(32))); +typedef struct { + c16_t cw[16]; +} cw_t; +static cw_t pucch2_3bit[8] __attribute__((aligned(32))); static cw_t pucch2_4bit[16] __attribute__((aligned(32))); static cw_t pucch2_5bit[32] __attribute__((aligned(32))); -static cw_t pucch2_6bit[64] __attribute__((aligned(32))); +static cw_t pucch2_6bit[64] __attribute__((aligned(32))); static cw_t pucch2_7bit[128] __attribute__((aligned(32))); static cw_t pucch2_8bit[256] __attribute__((aligned(32))); static cw_t pucch2_9bit[512] __attribute__((aligned(32))); static cw_t pucch2_10bit[1024] __attribute__((aligned(32))); static cw_t pucch2_11bit[2048] __attribute__((aligned(32))); -static cw_t* pucch2_lut[9] = +static cw_t *pucch2_lut[9] = {pucch2_3bit, pucch2_4bit, pucch2_5bit, pucch2_6bit, pucch2_7bit, pucch2_8bit, pucch2_9bit, pucch2_10bit, pucch2_11bit}; typedef struct { @@ -875,12 +1120,12 @@ static simde__m128i pucch2_polar_llr_num_lut[256]; void init_pucch2_luts() { - for (int b=3;b<12;b++) { + for (int b = 3; b < 12; b++) { for (int cw = 0; cw < (1 << b); cw++) { uint32_t out = encodeSmallBlock(cw, b); uint16_t *tmp = (uint16_t *)pucch2_lut[b - 3][cw].cw; for (int j = 0; j < 32; j++) - *tmp++ = (out & (1U< 0 ? -1 : 1; + *tmp++ = (out & (1U << j)) > 0 ? -1 : 1; } } for (int i = 0; i < 16; i++) { @@ -910,22 +1155,20 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, c16_t **rxdataF, int frame, int slot, - nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, - nfapi_nr_pucch_pdu_t* pucch_pdu) + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu, + nfapi_nr_pucch_pdu_t *pucch_pdu) { NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - //pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); - const int nb_symbols=pucch_pdu->nr_of_symbols; + // pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); + const int nb_symbols = pucch_pdu->nr_of_symbols; - AssertFatal(nb_symbols == 1 || nb_symbols == 2, - "Illegal number of symbols for PUCCH 2 %d\n", - nb_symbols); + AssertFatal(nb_symbols == 1 || nb_symbols == 2, "Illegal number of symbols for PUCCH 2 %d\n", nb_symbols); - AssertFatal((pucch_pdu->prb_start-((pucch_pdu->prb_start>>2)<<2))==0, + AssertFatal((pucch_pdu->prb_start - ((pucch_pdu->prb_start >> 2) << 2)) == 0, "Current pucch2 receiver implementation requires a PRB offset multiple of 4. The one selected is %d", pucch_pdu->prb_start); - //extract pucch and dmrs first + // extract pucch and dmrs first int l2 = pucch_pdu->start_symbol_index; int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; @@ -939,10 +1182,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, else re_offset[1] = re_offset[0]; } - AssertFatal(pucch_pdu->prb_size * nb_symbols > 1, - "number of PRB*SYMB (%d,%d)< 2", - pucch_pdu->prb_size, - nb_symbols); + AssertFatal(pucch_pdu->prb_size * nb_symbols > 1, "number of PRB*SYMB (%d,%d)< 2", pucch_pdu->prb_size, nb_symbols); int Prx = gNB->gNB_config.carrier_config.num_rx_ant.value; // AssertFatal((pucch_pdu->prb_size&1) == 0,"prb_size %d is not a multiple of2\n",pucch_pdu->prb_size); @@ -952,16 +1192,15 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, memset(rp, 0, sizeof(rp)); int64_t pucch2_lev = 0; - for (int aa=0;aaofdm_symbol_size]); if (re_offset[symb] + nb_re_pucch < frame_parms->ofdm_symbol_size) { memcpy(rp[aa][symb], &tmp_rp[re_offset[symb]], nb_re_pucch * sizeof(c16_t)); - } - else { - int neg_length = frame_parms->ofdm_symbol_size-re_offset[symb]; - int pos_length = nb_re_pucch-neg_length; + } else { + int neg_length = frame_parms->ofdm_symbol_size - re_offset[symb]; + int pos_length = nb_re_pucch - neg_length; memcpy(rp[aa][symb], &tmp_rp[re_offset[symb]], neg_length * sizeof(c16_t)); memcpy(&rp[aa][symb][neg_length], tmp_rp, pos_length * sizeof(c16_t)); } @@ -986,8 +1225,8 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, scaling); int prb_size_ext = pucch_pdu->prb_size + (pucch_pdu->prb_size & 1); - int nc_group_size=1; // 2 PRB - int ngroup = prb_size_ext/nc_group_size/2; + int nc_group_size = 1; // 2 PRB + int ngroup = prb_size_ext / nc_group_size / 2; c32_t corr32[nb_symbols][ngroup][Prx]; memset(corr32, 0, sizeof(corr32)); const int nb_re_data = 8 * prb_size_ext; @@ -1033,13 +1272,12 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, #endif c16_t scramb_data[nb_re_data] __attribute__((aligned(32))); - uint32_t *sGold = gold_cache(x2, nb_symbols * nb_re_data/2); + uint32_t *sGold = gold_cache(x2, nb_symbols * nb_re_data / 2); uint8_t *sGold8 = (uint8_t *)sGold; for (int i = 0; i < nb_re_data; i += 4) *(simde__m128i *)(scramb_data + i) = byte2m128i[*sGold8++]; - - for (int symb=0; symbstart_symbol_index,symb,pucch_pdu->dmrs_scrambling_id); + slot, + pucch_pdu->start_symbol_index, + symb, + pucch_pdu->dmrs_scrambling_id); #endif uint32_t *sGold = gold_cache(x2, starting_prb / 4 + ngroup / 2); // Compute pilot conjugate @@ -1105,7 +1346,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, for (int aa = 0; aa < Prx; aa++) mult_complex_vectors(rp[aa][symb], delay_table, rp[aa][symb], nb_re_pucch, 8); } - + // extract again DMRS, and signal, after delay compensation for (int aa = 0; aa < Prx; aa++) { c16_t *r_ext_p = r_ext[aa][symb]; @@ -1131,22 +1372,22 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, log_dump(PHY, r_ext[aa], nb_re_data, LOG_DUMP_C16, "after delay compensation ant %d data:\n", aa); } #endif - c16_t rdmrs_gold[Prx][nb_re_dmrs] __attribute__((aligned(32))); - for (int aa = 0; aa < Prx; aa++) - mult_complex_vectors(rdmrs_ext[aa], pil_dmrs, rdmrs_gold[aa], nb_re_dmrs, 0); - for (int aa=0;aabit_len_harq+pucch_pdu->sr_flag+pucch_pdu->bit_len_csi_part1+pucch_pdu->bit_len_csi_part2; + int nb_bit = pucch_pdu->bit_len_harq + pucch_pdu->sr_flag + pucch_pdu->bit_len_csi_part1 + pucch_pdu->bit_len_csi_part2; AssertFatal(nb_bit > 2 && nb_bit < 65, "illegal length (%d : %d,%d,%d,%d)\n", nb_bit, @@ -1174,20 +1415,23 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, pucch_pdu->bit_len_csi_part2); uint64_t decodedPayload[nb_symbols]; - memset(decodedPayload,0,sizeof(decodedPayload)); - int8_t corr_dB; + memset(decodedPayload, 0, sizeof(decodedPayload)); + uint8_t corr_dB; int decoderState = 2; if (pucch2_levdB < gNB->measurements.n0_subband_power_avg_dB + (gNB->pucch0_thres / 10)) decoderState = 1; // assuming missed detection, only attempt to decode for polar case (with CRC) - LOG_D(NR_PHY, "n0+thres %d decoderState %d\n", gNB->measurements.n0_subband_power_avg_dB + (gNB->pucch0_thres / 10), decoderState); + LOG_D(NR_PHY, + "n0+thres %d decoderState %d\n", + gNB->measurements.n0_subband_power_avg_dB + (gNB->pucch0_thres / 10), + decoderState); if (nb_bit < 12 && decoderState == 2) { // short blocklength case - uint64_t corr=0; - int cw_ML=0; + uint64_t corr = 0; + int cw_ML = 0; for (int cw = 0; cw < 1 << nb_bit; cw++) { uint64_t corr_tmp = 0; - for (int symb=0;symb corr) { corr = corr_tmp; cw_ML = cw; -#ifdef DEBUG_NR_PUCCH_RX +#ifdef DEBUG_NR_PUCCH_RX printf("slot %d PUCCH2 cw_ML %d, corr %lu\n", slot, cw_ML, corr); #endif } } // cw loop corr_dB = dB_fixed64(corr); #ifdef DEBUG_NR_PUCCH_RX - printf("slot %d PUCCH2 cw_ML %d, metric %d \n",slot,cw_ML,corr_dB); + printf("slot %d PUCCH2 cw_ML %d, metric %d \n", slot, cw_ML, corr_dB); #endif - decodedPayload[0]=(uint64_t)cw_ML; - + decodedPayload[0] = (uint64_t)cw_ML; + } else if (nb_bit >= 12) { // polar coded case - + simde__m128i llrs[pucch_pdu->prb_size * 2 * nb_symbols]; // non-coherent LLR computation on groups of 4 REs (half-PRBs) uint64_t corr = 0; const simde__m128i ones = simde_mm_set1_epi16(1); - for (int symb=0;symbprb_size);half_prb++) { + for (int symb = 0; symb < nb_symbols; symb++) { + for (int half_prb = 0; half_prb < (2 * pucch_pdu->prb_size); half_prb++) { simde__m128i llr_num = simde_mm_set1_epi16(0); - simde__m128i llr_den = simde_mm_set1_epi16(0); - for (int cw=0;cw<256;cw++) { - int32_t corr_tmp=0; - for (int aa=0;aa> 4].cw); simde__m128i factor = simde_mm_unpacklo_epi16(part1, part2); @@ -1278,12 +1522,13 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } // compute llrs llrs[half_prb + symb * 2 * pucch_pdu->prb_size] = simde_mm_subs_epi16(llr_num, llr_den); - LOG_DDUMP(PHY, llrs+half_prb + symb * 2 * pucch_pdu->prb_size, 8, LOG_DUMP_I16, "llrs:"); + LOG_DDUMP(PHY, llrs + half_prb + symb * 2 * pucch_pdu->prb_size, 8, LOG_DUMP_I16, "llrs:"); } // half_prb } // symb // run polar decoder on llrs - decoderState = polar_decoder_int16((int16_t *)llrs, decodedPayload, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size); + decoderState = + polar_decoder_int16((int16_t *)llrs, decodedPayload, 0, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, nb_bit, pucch_pdu->prb_size); // Decoder reversal decodedPayload[0] = reverse_bits(decodedPayload[0], nb_bit); @@ -1342,31 +1587,97 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } if (pucch_pdu->sr_flag == 1) { - uci_pdu->pduBitmap|=1; + uci_pdu->pduBitmap |= 1; uci_pdu->sr.sr_bit_len = 1; uci_pdu->sr.sr_payload = malloc(1); - uci_pdu->sr.sr_payload[0] = decodedPayload[0]&1; - decodedPayload[0] = decodedPayload[0]>>1; + uci_pdu->sr.sr_payload[0] = decodedPayload[0] & 1; + decodedPayload[0] = decodedPayload[0] >> 1; } // csi - if (pucch_pdu->bit_len_csi_part1>0) { - uci_pdu->pduBitmap|=4; - uci_pdu->csi_part1.csi_part1_bit_len=pucch_pdu->bit_len_csi_part1; - int csi_part1_bytes=pucch_pdu->bit_len_csi_part1>>3; - if ((pucch_pdu->bit_len_csi_part1&7) > 0) csi_part1_bytes++; - uci_pdu->csi_part1.csi_part1_payload = (uint8_t*)malloc(csi_part1_bytes); + if (pucch_pdu->bit_len_csi_part1 > 0) { + uci_pdu->pduBitmap |= 4; + uci_pdu->csi_part1.csi_part1_bit_len = pucch_pdu->bit_len_csi_part1; + int csi_part1_bytes = pucch_pdu->bit_len_csi_part1 >> 3; + if ((pucch_pdu->bit_len_csi_part1 & 7) > 0) + csi_part1_bytes++; + uci_pdu->csi_part1.csi_part1_payload = (uint8_t *)malloc(csi_part1_bytes); uci_pdu->csi_part1.csi_part1_crc = decoderState; - int i=0; - for (;icsi_part1.csi_part1_payload[i] = decodedPayload[0] & 255; - decodedPayload[0]>>=8; + decodedPayload[0] >>= 8; } - int bit_left = pucch_pdu->bit_len_csi_part1-((csi_part1_bytes-1)<<3); + int bit_left = pucch_pdu->bit_len_csi_part1 - ((csi_part1_bytes - 1) << 3); uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1 << bit_left) - 1); decodedPayload[0] = pucch_pdu->bit_len_csi_part1 < 64 ? decodedPayload[0] >> bit_left : 0; } - - if (pucch_pdu->bit_len_csi_part2>0) { - uci_pdu->pduBitmap|=8; + + if (pucch_pdu->bit_len_csi_part2 > 0) { + uci_pdu->pduBitmap |= 8; } } + +void nr_dump_uci_stats(FILE *fd, PHY_VARS_gNB *gNB, int frame) +{ + int strpos = 0; + char output[16384]; + + for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { + NR_gNB_PHY_STATS_t *stats = &gNB->phy_stats[i]; + if (!stats->active) + return; + NR_gNB_UCI_STATS_t *uci_stats = &stats->uci_stats; + if (uci_stats->pucch0_sr_trials > 0) + strpos += sprintf(output + strpos, + "UCI %d RNTI %x: pucch0_sr_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_sr_thres %d dB, current " + "pucch1_stat0 %d dB, current pucch1_stat1 %d dB, positive SR count %d\n", + i, + stats->rnti, + uci_stats->pucch0_sr_trials, + uci_stats->pucch0_n00, + uci_stats->pucch0_n01, + uci_stats->pucch0_sr_thres, + dB_fixed(uci_stats->current_pucch0_sr_stat0), + dB_fixed(uci_stats->current_pucch0_sr_stat1), + uci_stats->pucch0_positive_SR); + if (uci_stats->pucch01_trials > 0) + strpos += sprintf(output + strpos, + "UCI %d RNTI %x: pucch01_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_thres %d dB, current " + "pucch0_stat0 %d dB, current pucch1_stat1 %d dB, pucch01_DTX %d\n", + i, + stats->rnti, + uci_stats->pucch01_trials, + uci_stats->pucch0_n01, + uci_stats->pucch0_n01, + uci_stats->pucch0_thres, + dB_fixed(uci_stats->current_pucch0_stat0), + dB_fixed(uci_stats->current_pucch0_stat1), + uci_stats->pucch01_DTX); + + if (uci_stats->pucch02_trials > 0) + strpos += sprintf(output + strpos, + "UCI %d RNTI %x: pucch01_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_thres %d dB, current " + "pucch0_stat0 %d dB, current pucch0_stat1 %d dB, pucch01_DTX %d\n", + i, + stats->rnti, + uci_stats->pucch02_trials, + uci_stats->pucch0_n00, + uci_stats->pucch0_n01, + uci_stats->pucch0_thres, + dB_fixed(uci_stats->current_pucch0_stat0), + dB_fixed(uci_stats->current_pucch0_stat1), + uci_stats->pucch02_DTX); + + if (uci_stats->pucch2_trials > 0) + strpos += sprintf(output + strpos, + "UCI %d RNTI %x: pucch2_trials %d, pucch2_DTX %d\n", + i, + stats->rnti, + uci_stats->pucch2_trials, + uci_stats->pucch2_DTX); + } + if (fd) + fprintf(fd, "%s", output); + else + printf("%s", output); +} diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index 5f54b916b1..77a64d8fcc 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -190,7 +190,7 @@ void nr_generate_pucch1(c16_t **txdataF, d = qpskSymbols[tmp]; } #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] sequence modulation: payload=%lx \tde_re=%d \tde_im=%d\n", payload, d.r, d.i); + printf("\t [nr_generate_pucch1] sequence modulation (amp %d/%d): payload=%lx \tde_re=%d \tde_im=%d\n", amp, baseVal,payload, d.r, d.i); #endif /* * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 @@ -273,13 +273,14 @@ void nr_generate_pucch1(c16_t **txdataF, #ifdef DEBUG_NR_PUCCH_TX printf( "\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) " - "\ty_n[n=%d]=(%d,%d)\n", + "\td=(%d,%d)\ty_n[n=%d]=(%d,%d)\n", u, v, alpha, n, r_u_v_alpha_delta[n].r, r_u_v_alpha_delta[n].i, + d.r,d.i, n, y_n[n].r, y_n[n].i); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 695f6c6363..fd97adbd2d 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -82,6 +82,9 @@ typedef struct { int pucch01_DTX; int pucch02_trials; int pucch02_DTX; + int pucch1_sr_trials; + int pucch1_positive_SR; + int pucch11_trials; int pucch2_trials; int pucch2_DTX; } NR_gNB_UCI_STATS_t; diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 9ddd76e038..7a180f0570 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -29,7 +29,7 @@ #include "common/utils/load_module_shlib.h" #include "common/utils/nr/nr_common.h" #include "common/utils/LOG/log.h" -#include "common/ran_context.h" +#include "common/ran_context.h" #include "PHY/types.h" #include "PHY/defs_nr_common.h" #include "PHY/defs_nr_UE.h" @@ -61,13 +61,22 @@ uint8_t const nr_rv_round_map[4] = {0, 2, 3, 1}; // needed for some functions PHY_VARS_NR_UE *PHY_vars_UE_g[1][1] = {{NULL}}; static softmodem_params_t softmodem_params; -softmodem_params_t *get_softmodem_params(void) { +softmodem_params_t *get_softmodem_params(void) +{ return &softmodem_params; } -void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} -NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); } -nfapi_mode_t nfapi_getmode(void) { return NFAPI_MODE_UNKNOWN; } +void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) +{ +} +NR_IF_Module_t *NR_IF_Module_init(int Mod_id) +{ + return (NULL); +} +nfapi_mode_t nfapi_getmode(void) +{ + return NFAPI_MODE_UNKNOWN; +} void inc_ref_sched_response(int _) { @@ -80,9 +89,10 @@ void deref_sched_response(int _) exit(1); } -nrUE_params_t nrUE_params={0}; +nrUE_params_t nrUE_params = {0}; -nrUE_params_t *get_nrUE_params(void) { +nrUE_params_t *get_nrUE_params(void) +{ return &nrUE_params; } @@ -93,53 +103,45 @@ int main(int argc, char **argv) __attribute__((unused)) struct sigaction oldaction; sigaction(SIGINT, &sigint_action, &oldaction); - int i;//,l; + int i; double SNR, snr0 = -2.0, snr1 = 2.0; - double cfo=0; - uint8_t snr1set=0; - double **s_re,**s_im,**r_re,**r_im; - //int sync_pos, sync_pos_slot; - //FILE *rx_frame_file; + double cfo = 0; + uint8_t snr1set = 0; + double **s_re, **s_im, **r_re, **r_im; FILE *output_fd = NULL; - //uint8_t write_output_file=0; - //int result; - //int freq_offset; - //int subframe_offset; - //char fname[40], vname[40]; - int trial,n_trials=100,n_errors=0,ack_nack_errors=0,sr_errors=0; + int trial, n_trials = 100, n_errors = 0, ack_nack_errors = 0, sr_errors = 0; int ret = 1; - uint8_t transmission_mode = 1,n_tx=1,n_rx=1; - uint16_t Nid_cell=0; - uint64_t SSB_positions=0x01; + uint8_t transmission_mode = 1, n_tx = 1, n_rx = 1; + uint16_t Nid_cell = 0; + uint64_t SSB_positions = 0x01; channel_desc_t *UE2gNB; - int format=0; - //uint8_t extended_prefix_flag=0; - FILE *input_fd=NULL; - //uint8_t nacktoack_flag=0; - int16_t amp=0x7FFF; - int nr_slot_tx=0; - int nr_frame_tx=0; + int format = 0; + FILE *input_fd = NULL; + int16_t amp = 0x7FFF; + int nr_slot_tx = 0; + int nr_frame_tx = 0; uint64_t actual_payload = 0, payload_received = 0; bool random_payload = true; - 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 - uint16_t nrofPRB=2; - uint8_t timeDomainOCC=0; - SCM_t channel_model=AWGN;//Rayleigh1_anticorr; + 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 + // resource allocated see 9.2.1, 38.213 for more info.should be actually present in the resource set provided + uint8_t startingSymbolIndex = 0; + uint16_t startingPRB = 0; + // PRB number not sure see 9.2.1, 38.213 for more info. Should be actually present in the resource set provided + uint16_t startingPRB_intraSlotHopping = 0; + uint16_t nrofPRB = 2; + uint8_t timeDomainOCC = 0; + SCM_t channel_model = AWGN; // Rayleigh1_anticorr; double DS_TDL = .03; - + double delay_us = 0; - int N_RB_DL=273,mu=1; - float target_error_rate=0.001; + int N_RB_DL = 273, mu = 1; + float target_error_rate = 0.001; int frame_length_complex_samples; - //int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; - //unsigned char frame_type = 0; - int loglvl=OAILOG_WARNING; + int loglvl = OAILOG_WARNING; int sr_flag = 0; int pucch_DTX_thres = 0; cpuf = get_cpu_freq_GHz(); @@ -153,275 +155,268 @@ int main(int argc, char **argv) logInit(); int c; + int nrofSymbols_set = 0; while ((c = getopt(argc, argv, "--:O:f:hA:f:g:i:I:P:B:b:t:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:cd:C")) != -1) { /* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */ /* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */ if (c == 1 || c == '-' || c == 'O') continue; - printf("handling optarg %c\n",c); + printf("handling optarg %c\n", c); switch (c) { - case 'f': - //write_output_file=1; - output_fd = fopen(optarg,"w"); + case 'f': + // write_output_file=1; + output_fd = fopen(optarg, "w"); - if (output_fd==NULL) { - printf("Error opening %s\n",optarg); - exit(-1); - } - break; - - - - case 'g': - switch((char)*optarg) { - case 'A': - channel_model=SCM_A; + if (output_fd == NULL) { + printf("Error opening %s\n", optarg); + exit(-1); + } break; - case 'B': - channel_model=SCM_B; + case 'g': + switch ((char)*optarg) { + case 'A': + channel_model = SCM_A; + break; + + case 'B': + channel_model = SCM_B; + break; + + case 'C': + channel_model = SCM_C; + break; + + case 'D': + channel_model = SCM_D; + break; + + case 'E': + channel_model = EPA; + break; + + case 'F': + channel_model = EVA; + break; + + case 'G': + channel_model = ETU; + break; + case 'H': + channel_model = TDL_C; + DS_TDL = .030; // 30 ns + break; + + case 'I': + channel_model = TDL_C; + DS_TDL = .3; // 300ns + break; + + case 'J': + channel_model = TDL_D; + DS_TDL = .03; + break; + + default: + printf("Unsupported channel model!\n"); + exit(-1); + } break; - case 'C': - channel_model=SCM_C; + case 'n': + n_trials = atoi(optarg); break; - case 'D': - channel_model=SCM_D; + case 'o': + cfo = atof(optarg); + printf("Setting CFO to %f Hz\n", cfo); break; - case 'E': - channel_model=EPA; + case 's': + snr0 = atof(optarg); + printf("Setting SNR0 to %f\n", snr0); + break; + + case 'S': + snr1 = atof(optarg); + snr1set = 1; + printf("Setting SNR1 to %f\n", snr1); + break; + + case 't': + pucch_DTX_thres = atoi(optarg); + break; + + case 'd': + delay_us = atof(optarg); + break; + case 'x': + transmission_mode = atoi(optarg); + + if ((transmission_mode != 1) && (transmission_mode != 2) && (transmission_mode != 6)) { + printf("Unsupported transmission mode %d\n", transmission_mode); + exit(-1); + } + break; + + case 'y': + n_tx = atoi(optarg); + + if ((n_tx == 0) || (n_tx > 2)) { + printf("Unsupported number of tx antennas %d\n", n_tx); + exit(-1); + } + break; + + case 'z': + n_rx = atoi(optarg); + + if ((n_rx == 0) || (n_rx > 8)) { + printf("Unsupported number of rx antennas %d\n", n_rx); + exit(-1); + } + break; + + case 'N': + Nid_cell = atoi(optarg); + break; + + case 'R': + N_RB_DL = atoi(optarg); break; case 'F': - channel_model=EVA; + input_fd = fopen(optarg, "r"); + + if (input_fd == NULL) { + printf("Problem with filename %s\n", optarg); + exit(-1); + } break; - case 'G': - channel_model=ETU; + case 'L': + loglvl = atoi(optarg); + break; + case 'i': + nrofSymbols = (uint8_t)atoi(optarg); + nrofSymbols_set = 1; break; - case 'H': - channel_model = TDL_C; - DS_TDL = .030; // 30 ns - break; - case 'I': - channel_model = TDL_C; - DS_TDL = .3; // 300ns + startingSymbolIndex = (uint8_t)atoi(optarg); + break; + case 'r': + startingPRB = atoi(optarg); + break; + case 'q': + nrofPRB = atoi(optarg); + break; + case 'P': + format = atoi(optarg); + if ((format == 1 || format == 3) && nrofSymbols_set == 0) + nrofSymbols = 14; + break; + case 'm': + m0 = atoi(optarg); + break; + case 'b': + nr_bit = atoi(optarg); + break; + case 'c': + sr_flag = 1; + break; + case 'B': + actual_payload = atoi(optarg); + random_payload = false; + printf("Setting payload to %llx\n", (unsigned long long)actual_payload); + break; + case 'T': + // nacktoack_flag=(uint8_t)atoi(optarg); + target_error_rate = 0.001; + break; + case 'C': + print_perf = 1; + cpu_meas_enabled = 1; break; - - case 'J': - channel_model=TDL_D; - DS_TDL = .03; - break; - default: - printf("Unsupported channel model!\n"); + case 'h': + printf( + "%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t " + "Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A " + "interpolation_file -C(alibration offset dB) -N CellId\n", + argv[0]); + // printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n"); + printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n"); + printf("-b number of HARQ bits (1-2)\n"); + printf("-B payload to be transmitted on PUCCH\n"); + printf("-c Activate scheduling request\n"); + printf("-d Use TDD\n"); + printf("-f Output filename (.txt format) for Pe/SNR results\n"); + printf("-F Input filename (.txt format) for RX conformance testing\n"); + printf( + "-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean " + "factor)\n"); + printf("-i Enter number of ofdm symbols for pucch\n"); + printf("-I Starting symbol index for pucch\n"); + printf("-h This message\n"); + printf("-m initial cyclic shift m0\n"); + printf("-n Number of frames to simulate\n"); + printf("-N Nid_cell\n"); + printf("-o Carrier frequency offset in Hz\n"); + printf("-O oversampling factor (1,2,4,8,16)\n"); + printf("-p Use extended prefix mode\n"); + printf("-P Enter the format of PUCCH\n"); + printf("-q PUCCH number of PRB\n"); + printf("-r PUCCH starting PRB\n"); + printf("-R N_RB_DL\n"); + printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB. If n_frames is 1 then just SNR is simulated\n"); + printf("-S Ending SNR, runs from SNR0 to SNR1\n"); + printf("-t Delay spread for multipath channel\n"); + printf("-T to check nacktoack miss for format 1\n"); + printf("-x Transmission mode (1,2,6 for the moment)\n"); + printf("-y Number of TX antennas used in eNB\n"); + printf("-z Number of RX antennas used in UE\n"); + printf("-C print CPU cost\n"); exit(-1); - } - break; - - case 'n': - n_trials = atoi(optarg); - break; - - case 'o': - cfo = atof(optarg); - printf("Setting CFO to %f Hz\n",cfo); - break; - - case 's': - snr0 = atof(optarg); - printf("Setting SNR0 to %f\n",snr0); - break; - - case 'S': - snr1 = atof(optarg); - snr1set=1; - printf("Setting SNR1 to %f\n",snr1); - break; - - - case 't': - pucch_DTX_thres= atoi(optarg); - break; - /* - case 'p': - extended_prefix_flag=1; - break; - - case 'd': - frame_type = 1; - break; - - case 'r': - ricean_factor = pow(10,-.1*atof(optarg)); - if (ricean_factor>1) { - printf("Ricean factor must be between 0 and 1\n"); - exit(-1); - } - break; - */ - case 'd': - delay_us=atof(optarg); - break; - case 'x': - transmission_mode=atoi(optarg); - - if ((transmission_mode!=1) && - (transmission_mode!=2) && - (transmission_mode!=6)) { - printf("Unsupported transmission mode %d\n",transmission_mode); - exit(-1); - } - break; - - case 'y': - n_tx=atoi(optarg); - - if ((n_tx==0) || (n_tx>2)) { - printf("Unsupported number of tx antennas %d\n",n_tx); - exit(-1); - } - break; - - case 'z': - n_rx=atoi(optarg); - - if ((n_rx==0) || (n_rx>8)) { - printf("Unsupported number of rx antennas %d\n",n_rx); - exit(-1); - } - break; - - case 'N': - Nid_cell = atoi(optarg); - break; - - case 'R': - N_RB_DL = atoi(optarg); - break; - - case 'F': - input_fd = fopen(optarg,"r"); - - if (input_fd==NULL) { - printf("Problem with filename %s\n",optarg); - exit(-1); - } - break; - - case 'L': - loglvl = atoi(optarg); - break; - case 'i': - nrofSymbols=(uint8_t)atoi(optarg); - break; - case 'I': - startingSymbolIndex=(uint8_t)atoi(optarg); - break; - case 'r': - startingPRB=atoi(optarg); - break; - case 'q': - nrofPRB=atoi(optarg); - break; - case 'P': - format=atoi(optarg); - break; - case 'm': - m0=atoi(optarg); - break; - case 'b': - nr_bit=atoi(optarg); - break; - case 'c': - sr_flag=1; - break; - case 'B': - actual_payload=atoi(optarg); - random_payload = false; - break; - case 'T': - //nacktoack_flag=(uint8_t)atoi(optarg); - target_error_rate=0.001; - break; - case 'C': - print_perf = 1; - cpu_meas_enabled = 1; - break; - default: - case 'h': - printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", argv[0]); - //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n"); - printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n"); - printf("-b number of HARQ bits (1-2)\n"); - printf("-B payload to be transmitted on PUCCH\n"); - printf("-c Activate scheduling request\n"); - printf("-d Use TDD\n"); - printf("-f Output filename (.txt format) for Pe/SNR results\n"); - printf("-F Input filename (.txt format) for RX conformance testing\n"); - printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n"); - printf("-i Enter number of ofdm symbols for pucch\n"); - printf("-I Starting symbol index for pucch\n"); - printf("-h This message\n"); - printf("-m initial cyclic shift m0\n"); - printf("-n Number of frames to simulate\n"); - printf("-N Nid_cell\n"); - printf("-o Carrier frequency offset in Hz\n"); - printf("-O oversampling factor (1,2,4,8,16)\n"); - printf("-p Use extended prefix mode\n"); - printf("-P Enter the format of PUCCH\n"); - printf("-q PUCCH number of PRB\n"); - printf("-r PUCCH starting PRB\n"); - printf("-R N_RB_DL\n"); - printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB. If n_frames is 1 then just SNR is simulated\n"); - printf("-S Ending SNR, runs from SNR0 to SNR1\n"); - printf("-t Delay spread for multipath channel\n"); - printf("-T to check nacktoack miss for format 1\n"); - printf("-x Transmission mode (1,2,6 for the moment)\n"); - printf("-y Number of TX antennas used in eNB\n"); - printf("-z Number of RX antennas used in UE\n"); - printf("-C print CPU cost\n"); - exit (-1); - break; + break; } } - double phase = (1<2)&&(nr_bit<65)),"illegal combination format %d, nr_bit %d\n", - format,nr_bit); - int do_DTX=0; - if ((format < 2) && (actual_payload == 4)) do_DTX=1; + AssertFatal(((format < 2) && (nr_bit < 3) && (actual_payload < 5)) || ((format == 2) && (nr_bit > 2) && (nr_bit < 65)), + "illegal combination format %d, nr_bit %d\n", + format, + nr_bit); + int do_DTX = 0; + if ((format < 2) && (actual_payload == 4)) + do_DTX = 1; if (random_payload) { double tmp = uniformrandom(); memcpy(&actual_payload, &tmp, sizeof(actual_payload)); } - actual_payload &= nr_bit < 64 ? (1UL << nr_bit) - 1: 0xffffffffffffffff; + actual_payload &= nr_bit < 64 ? (1UL << nr_bit) - 1 : 0xffffffffffffffff; - printf("Transmitted payload is %lu, do_DTX = %d\n",actual_payload,do_DTX); + printf("Transmitted payload is %lu, do_DTX = %d\n", actual_payload, do_DTX); RC.gNB = calloc(1, sizeof(PHY_VARS_gNB *)); - RC.gNB[0] = calloc(1,sizeof(PHY_VARS_gNB)); + RC.gNB[0] = calloc(1, sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; gNB->pucch0_thres = pucch_DTX_thres; - frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) + frame_parms = &gNB->frame_parms; // to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; frame_parms->nb_antennas_rx = n_rx; frame_parms->N_RB_DL = N_RB_DL; @@ -431,7 +426,7 @@ int main(int argc, char **argv) nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; cfg->carrier_config.num_tx_ant.value = n_tx; cfg->carrier_config.num_rx_ant.value = n_rx; - nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); + nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell, SSB_positions); // TDD configuration gNB->gNB_config.tdd_table.tdd_period.value = 6; do_tdd_config_sim(gNB, mu); @@ -442,71 +437,66 @@ int main(int argc, char **argv) for (i = 0; i < n_rx; i++) gNB->common_vars.rxdataF[0][i] = malloc16_clear(gNB->frame_parms.samples_per_frame_wCP * sizeof(c16_t)); - double fs,txbw,rxbw; - get_samplerate_and_bw(mu, - N_RB_DL, - frame_parms->threequarter_fs, - &fs, - &txbw, - &rxbw); + double fs, txbw, rxbw; + get_samplerate_and_bw(mu, N_RB_DL, frame_parms->threequarter_fs, &fs, &txbw, &rxbw); UE2gNB = new_channel_desc_scm(n_tx, n_rx, channel_model, fs, 0, txbw, DS_TDL, 0.0, CORR_LEVEL_LOW, 0, 0, 0, 0); - if (UE2gNB==NULL) { + if (UE2gNB == NULL) { printf("Problem generating channel model. Exiting.\n"); exit(-1); } - frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; - //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP; + frame_length_complex_samples = frame_parms->samples_per_subframe * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; + // frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP; - s_re = malloc(n_tx*sizeof(double*)); - s_im = malloc(n_tx*sizeof(double*)); - r_re = malloc(n_rx*sizeof(double*)); - r_im = malloc(n_rx*sizeof(double*)); + s_re = malloc(n_tx * sizeof(double *)); + s_im = malloc(n_tx * sizeof(double *)); + r_re = malloc(n_rx * sizeof(double *)); + r_im = malloc(n_rx * sizeof(double *)); memcpy((void *)&gNB->frame_parms, (void *)frame_parms, sizeof(*frame_parms)); - for (int aatx=0; aatxframe_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS)); - UE->frame_parms.nb_antennas_rx=1; + // configure UE + UE = calloc(1, sizeof(PHY_VARS_NR_UE)); + memcpy(&UE->frame_parms, frame_parms, sizeof(NR_DL_FRAME_PARMS)); + UE->frame_parms.nb_antennas_rx = 1; - if (init_nr_ue_signal(UE, 1) != 0) - { + if (init_nr_ue_signal(UE, 1) != 0) { printf("Error at UE NR initialisation\n"); exit(-1); } - fapi_nr_ul_config_pucch_pdu pucch_tx_pdu; - if (format==0) { + fapi_nr_ul_config_pucch_pdu pucch_tx_pdu = {0}; + if (format == 0) { pucch_tx_pdu.format_type = 0; pucch_tx_pdu.nr_of_symbols = nrofSymbols; pucch_tx_pdu.start_symbol_index = startingSymbolIndex; @@ -520,7 +510,22 @@ int main(int argc, char **argv) pucch_tx_pdu.initial_cyclic_shift = 0; pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping; } - if (format==2) { + else if (format == 1) { + pucch_tx_pdu.format_type = 0; + pucch_tx_pdu.n_bit = nr_bit; + pucch_tx_pdu.payload = actual_payload; + pucch_tx_pdu.nr_of_symbols = nrofSymbols; + pucch_tx_pdu.start_symbol_index = startingSymbolIndex; + pucch_tx_pdu.bwp_start = 0; + pucch_tx_pdu.prb_start = startingPRB; + pucch_tx_pdu.hopping_id = hopping_id; + pucch_tx_pdu.group_hop_flag = 0; + pucch_tx_pdu.sequence_hop_flag = 0; + pucch_tx_pdu.freq_hop_flag = 1; + pucch_tx_pdu.initial_cyclic_shift = m0; + pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping; + pucch_tx_pdu.time_domain_occ_idx = timeDomainOCC; + } else if (format == 2) { pucch_tx_pdu.format_type = 2; pucch_tx_pdu.rnti = 0x1234; pucch_tx_pdu.n_bit = nr_bit; @@ -539,28 +544,28 @@ int main(int argc, char **argv) pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping; } - pucch_GroupHopping_t PUCCH_GroupHopping = pucch_tx_pdu.group_hop_flag + (pucch_tx_pdu.sequence_hop_flag<<1); + pucch_GroupHopping_t PUCCH_GroupHopping = pucch_tx_pdu.group_hop_flag + (pucch_tx_pdu.sequence_hop_flag << 1); double tx_level_fp = 100.0; c16_t **rxdataF = gNB->common_vars.rxdataF[0]; - for(SNR = snr0; SNR <= snr1 && !stop; SNR += 1) { - ack_nack_errors=0; + for (SNR = snr0; SNR <= snr1 && !stop; SNR += 1) { + ack_nack_errors = 0; sr_errors = 0; n_errors = 0; c16_t **txdataF = gNB->common_vars.txdataF[0]; for (trial = 0; trial < n_trials && !stop; trial++) { - for (int aatx=0;aatx<1;aatx++) - bzero(txdataF[aatx],frame_parms->ofdm_symbol_size*sizeof(int)); - if(format==0 && do_DTX==0){ + for (int aatx = 0; aatx < 1; aatx++) + bzero(txdataF[aatx], frame_parms->ofdm_symbol_size * sizeof(int)); + if (format == 0 && do_DTX == 0) { nr_generate_pucch0(txdataF, frame_parms, amp, nr_slot_tx, &pucch_tx_pdu); - } else if (format == 1 && do_DTX==0){ + } else if (format == 1 && do_DTX == 0) { nr_generate_pucch1(txdataF, frame_parms, amp, nr_slot_tx, &pucch_tx_pdu); - } else if (do_DTX == 0){ + } else if (do_DTX == 0) { nr_generate_pucch2(txdataF, frame_parms, amp, nr_slot_tx, &pucch_tx_pdu); } // SNR Computation - // standard says: SNR = S / N, where S is the total signal energy, N is the noise energy in the transmission bandwidth (i.e. N_RB_DL resource blocks) - // txlev = S. + // standard says: SNR = S / N, where S is the total signal energy, N is the noise energy in the transmission bandwidth (i.e. + // N_RB_DL resource blocks) txlev = S. // Compute transmitter energy level int symbol_offset = startingSymbolIndex * frame_parms->ofdm_symbol_size; @@ -572,14 +577,14 @@ int main(int argc, char **argv) int N_RB = (format == 0 || format == 1) ? 1 : nrofPRB; double sigma2 = compute_noise_variance(txlev, N_RB_DL * 12, N_RB, 1, SNR, n_trials); - for (int symb=0; symbframe_parms.symbols_per_slot;symb++) { - if (symb= startingSymbolIndex+nrofSymbols) { - int i0 = symb*gNB->frame_parms.ofdm_symbol_size; - for (int re=0;reframe_parms.first_carrier_offset + re)%gNB->frame_parms.ofdm_symbol_size); - for (int aarx=0;aarxframe_parms.symbols_per_slot; symb++) { + if (symb < startingSymbolIndex || symb >= startingSymbolIndex + nrofSymbols) { + int i0 = symb * gNB->frame_parms.ofdm_symbol_size; + for (int re = 0; re < N_RB_DL * 12; re++) { + i = i0 + ((gNB->frame_parms.first_carrier_offset + re) % gNB->frame_parms.ofdm_symbol_size); + for (int aarx = 0; aarx < n_rx; aarx++) { + double nr = sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0); + double ni = sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0); rxdataF[aarx][i].r = (int16_t)(tx_level_fp * (nr) / sqrt((double)txlev)); rxdataF[aarx][i].i = (int16_t)(tx_level_fp * (ni) / sqrt((double)txlev)); } @@ -587,57 +592,84 @@ int main(int argc, char **argv) } } - random_channel(UE2gNB,0); - freq_channel(UE2gNB,N_RB_DL,2*N_RB_DL+1,15<frame_parms.ofdm_symbol_size; - for (int re=0;reframe_parms.first_carrier_offset + re)%gNB->frame_parms.ofdm_symbol_size); + random_channel(UE2gNB, 0); + freq_channel(UE2gNB, N_RB_DL, 2 * N_RB_DL + 1, 15 << mu); + for (int symb = 0; symb < nrofSymbols; symb++) { + int i0 = (startingSymbolIndex + symb) * gNB->frame_parms.ofdm_symbol_size; + for (int re = 0; re < N_RB_DL * 12; re++) { + i = i0 + ((gNB->frame_parms.first_carrier_offset + re) % gNB->frame_parms.ofdm_symbol_size); struct complexd phasor; - phasor.r = cos(2*M_PI*phase*re); - phasor.i = sin(2*M_PI*phase*re); - for (int aarx=0;aarxchannel_length; l++) { - rxr = txr*UE2gNB->chF[aarx][l].r - txi*UE2gNB->chF[aarx][l].i; - rxi = txr*UE2gNB->chF[aarx][l].i + txi*UE2gNB->chF[aarx][l].r; - } - double rxr_tmp = rxr*phasor.r - rxi*phasor.i; - rxi = rxr*phasor.i + rxi*phasor.r; + phasor.r = cos(2 * M_PI * phase * re); + phasor.i = sin(2 * M_PI * phase * re); + for (int aarx = 0; aarx < n_rx; aarx++) { + double txr = (double)(((int16_t *)txdataF[0])[(i << 1)]); + double txi = (double)(((int16_t *)txdataF[0])[1 + (i << 1)]); + double rxr = {0}, rxi = {0}; + for (int l = 0; l < UE2gNB->channel_length; l++) { + rxr = txr * UE2gNB->chF[aarx][l].r - txi * UE2gNB->chF[aarx][l].i; + rxi = txr * UE2gNB->chF[aarx][l].i + txi * UE2gNB->chF[aarx][l].r; + } + double rxr_tmp = rxr * phasor.r - rxi * phasor.i; + rxi = rxr * phasor.i + rxi * phasor.r; rxr = rxr_tmp; - double nr = sqrt(sigma2/2)*gaussdouble(0.0,1.0); - double ni = sqrt(sigma2/2)*gaussdouble(0.0,1.0); + double nr = sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0); + double ni = sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0); rxdataF[aarx][i].r = (int16_t)(tx_level_fp * (rxr + nr) / sqrt((double)txlev)); rxdataF[aarx][i].i = (int16_t)(tx_level_fp * (rxi + ni) / sqrt((double)txlev)); - if (n_trials==1 && fabs(txr) > 0) printf("symb %d, re %d , aarx %d : txr %f, txi %f, chr %f, chi %f, nr %f, ni %f, rxr %f, rxi %f => %d,%d\n", - symb, re, aarx, txr,txi, - UE2gNB->chF[aarx][re].r,UE2gNB->chF[aarx][re].i, - nr,ni, rxr,rxi, - rxdataF[aarx][i].r,rxdataF[aarx][i].i); + if (n_trials == 1 && fabs(txr) > 0) + printf("symb %d, re %d , aarx %d : txr %f, txi %f, chr %f, chi %f, nr %f, ni %f, rxr %f, rxi %f => %d,%d\n", + symb, + re, + aarx, + txr, + txi, + UE2gNB->chF[aarx][re].r, + UE2gNB->chF[aarx][re].i, + nr, + ni, + rxr, + rxi, + rxdataF[aarx][i].r, + rxdataF[aarx][i].i); } } } - int rxlev=0; - for (int aarx=0;aarxofdm_symbol_size], - frame_parms->ofdm_symbol_size); + int rxlev = 0; + for (int aarx = 0; aarx < n_rx; aarx++) + rxlev += signal_energy((int32_t *)&rxdataF[aarx][startingSymbolIndex * frame_parms->ofdm_symbol_size], + frame_parms->ofdm_symbol_size); - int rxlev_pucch=0; + int rxlev_pucch = 0; - for (int aarx=0;aarxofdm_symbol_size], - 12); + for (int aarx = 0; aarx < n_rx; aarx++) + rxlev_pucch += signal_energy((int32_t *)&rxdataF[aarx][startingSymbolIndex * frame_parms->ofdm_symbol_size], 12); // set UL mask for pucch allocation uint32_t rb_mask_ul[14][9] = {0}; - for (int s=0;ssymbols_per_slot;s++){ - if (s>=startingSymbolIndex && s<(startingSymbolIndex+nrofSymbols)) - for (int rb=0; rb> 5] |= (1 << (rb2 & 31)); - } + + if (format == 1) { + for (int s = 0; s < frame_parms->symbols_per_slot; s++) { + if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols / 2)) + for (int rb = 0; rb < N_RB; rb++) { + int rb2 = rb + startingPRB; + rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31)); + } + else if (s >= (startingSymbolIndex + nrofSymbols / 2) && s < startingSymbolIndex + nrofSymbols) + for (int rb = 0; rb < N_RB; rb++) { + int rb2 = rb + startingPRB_intraSlotHopping; + rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31)); + } + } + } else { + for (int s = 0; s < frame_parms->symbols_per_slot; s++) { + if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols)) + for (int rb = 0; rb < N_RB; rb++) { + int rb2 = rb + startingPRB; + rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31)); + } + } } // noise measurement (all PRBs) @@ -654,103 +686,132 @@ int main(int argc, char **argv) 10 * log10((double)txlev * UE->frame_parms.ofdm_symbol_size / 12), gNB->measurements.n0_subband_power_tot_dB[startingPRB], gNB->measurements.n0_subband_power_avg_dB); - if(format==0){ + if (format == 0) { nfapi_nr_uci_pucch_pdu_format_0_1_t uci_pdu; nfapi_nr_pucch_pdu_t pucch_pdu; gNB->phy_stats[0].rnti = 0x1234; - pucch_pdu.rnti = 0x1234; - pucch_pdu.subcarrier_spacing = 1; - pucch_pdu.group_hop_flag = PUCCH_GroupHopping&1; - pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping>>1)&1; - pucch_pdu.bit_len_harq = nr_bit; - pucch_pdu.bit_len_csi_part1 = 0; - pucch_pdu.bit_len_csi_part2 = 0; - pucch_pdu.sr_flag = sr_flag; - pucch_pdu.nr_of_symbols = nrofSymbols; - pucch_pdu.hopping_id = hopping_id; - pucch_pdu.initial_cyclic_shift = 0; - pucch_pdu.start_symbol_index = startingSymbolIndex; - pucch_pdu.prb_start = startingPRB; - pucch_pdu.prb_size = 1; - pucch_pdu.bwp_start = 0; - pucch_pdu.bwp_size = N_RB_DL; - if (nrofSymbols>1) { - pucch_pdu.freq_hop_flag = 1; - pucch_pdu.second_hop_prb = N_RB_DL-1; - } - else pucch_pdu.freq_hop_flag = 0; + pucch_pdu.rnti = 0x1234; + pucch_pdu.subcarrier_spacing = 1; + pucch_pdu.group_hop_flag = PUCCH_GroupHopping & 1; + pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping >> 1) & 1; + pucch_pdu.bit_len_harq = nr_bit; + pucch_pdu.bit_len_csi_part1 = 0; + pucch_pdu.bit_len_csi_part2 = 0; + pucch_pdu.sr_flag = sr_flag; + pucch_pdu.nr_of_symbols = nrofSymbols; + pucch_pdu.hopping_id = hopping_id; + pucch_pdu.initial_cyclic_shift = 0; + pucch_pdu.start_symbol_index = startingSymbolIndex; + pucch_pdu.prb_start = startingPRB; + pucch_pdu.prb_size = 1; + pucch_pdu.bwp_start = 0; + pucch_pdu.bwp_size = N_RB_DL; + if (nrofSymbols > 1) { + pucch_pdu.freq_hop_flag = 1; + pucch_pdu.second_hop_prb = N_RB_DL - 1; + } else + pucch_pdu.freq_hop_flag = 0; - nr_decode_pucch0(gNB, rxdataF, nr_frame_tx, nr_slot_tx,&uci_pdu,&pucch_pdu); - if(sr_flag==1){ + nr_decode_pucch0(gNB, rxdataF, nr_frame_tx, nr_slot_tx, &uci_pdu, &pucch_pdu); + if (sr_flag == 1) { if (uci_pdu.sr.sr_indication == 0 || uci_pdu.sr.sr_confidence_level == 1) - sr_errors+=1; + sr_errors += 1; } // harq value 0 -> pass nfapi_nr_harq_t *harq_list = uci_pdu.harq.harq_list; // confidence value 0 -> good confidence const int confidence_lvl = uci_pdu.harq.harq_confidence_level; - if(nr_bit>0){ - if (nr_bit==1 && do_DTX == 0) - ack_nack_errors+=(actual_payload^(!harq_list[0].harq_value)); + if (nr_bit > 0) { + if (nr_bit == 1 && do_DTX == 0) + ack_nack_errors += (actual_payload ^ (!harq_list[0].harq_value)); else if (do_DTX == 0) - ack_nack_errors+=(((actual_payload&1)^(!harq_list[1].harq_value))+((actual_payload>>1)^(!harq_list[0].harq_value))); - else if ((!confidence_lvl && !harq_list[0].harq_value) || - (!confidence_lvl && nr_bit == 2 && !harq_list[1].harq_value)) + ack_nack_errors += + (((actual_payload & 1) ^ (!harq_list[1].harq_value)) + ((actual_payload >> 1) ^ (!harq_list[0].harq_value))); + else if ((!confidence_lvl && !harq_list[0].harq_value) || (!confidence_lvl && nr_bit == 2 && !harq_list[1].harq_value)) ack_nack_errors++; } - } - else if (format==1) { - nr_decode_pucch1((c16_t **)rxdataF,PUCCH_GroupHopping,hopping_id, - &(payload_received),frame_parms,amp,nr_slot_tx, - m0,nrofSymbols,startingSymbolIndex,startingPRB, - startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); - if(nr_bit==1) - ack_nack_errors+=((actual_payload^payload_received)&1); - else - ack_nack_errors+=((actual_payload^payload_received)&1) + (((actual_payload^payload_received)&2)>>1); - } - else if (format==2) { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t uci_pdu={0}; - nfapi_nr_pucch_pdu_t pucch_pdu={0}; + } else if (format == 1) { + nfapi_nr_uci_pucch_pdu_format_0_1_t uci_pdu; + nfapi_nr_pucch_pdu_t pucch_pdu; + gNB->phy_stats[0].rnti = 0x1234; pucch_pdu.rnti = 0x1234; - pucch_pdu.subcarrier_spacing = 1; - pucch_pdu.group_hop_flag = PUCCH_GroupHopping&1; - pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping>>1)&1; - pucch_pdu.bit_len_csi_part1 = nr_bit; - pucch_pdu.bit_len_harq = 0; - pucch_pdu.bit_len_csi_part2 = 0; - pucch_pdu.sr_flag = 0; - pucch_pdu.nr_of_symbols = nrofSymbols; - pucch_pdu.hopping_id = hopping_id; - pucch_pdu.initial_cyclic_shift = 0; - pucch_pdu.start_symbol_index = startingSymbolIndex; - pucch_pdu.prb_size = nrofPRB; - pucch_pdu.prb_start = startingPRB; - pucch_pdu.dmrs_scrambling_id = dmrs_scrambling_id; - pucch_pdu.data_scrambling_id = data_scrambling_id; - if (nrofSymbols>1) { - pucch_pdu.freq_hop_flag = 1; - pucch_pdu.second_hop_prb = N_RB_DL-1; + pucch_pdu.subcarrier_spacing = 1; + pucch_pdu.group_hop_flag = PUCCH_GroupHopping & 1; + pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping >> 1) & 1; + pucch_pdu.bit_len_harq = nr_bit; + pucch_pdu.bit_len_csi_part1 = 0; + pucch_pdu.bit_len_csi_part2 = 0; + pucch_pdu.sr_flag = sr_flag; + pucch_pdu.nr_of_symbols = nrofSymbols; + pucch_pdu.hopping_id = hopping_id; + pucch_pdu.initial_cyclic_shift = m0; + pucch_pdu.start_symbol_index = startingSymbolIndex; + pucch_pdu.prb_start = startingPRB; + pucch_pdu.prb_size = 1; + pucch_pdu.bwp_start = 0; + pucch_pdu.bwp_size = N_RB_DL; + pucch_pdu.freq_hop_flag = 1; + pucch_pdu.second_hop_prb = N_RB_DL - 2; + pucch_pdu.time_domain_occ_idx = timeDomainOCC; + + nr_decode_pucch1(gNB, rxdataF, nr_frame_tx, nr_slot_tx, &uci_pdu, &pucch_pdu); + // harq value 0 -> pass + nfapi_nr_harq_t *harq_list = uci_pdu.harq.harq_list; + // confidence value 0 -> good confidence + const int confidence_lvl = uci_pdu.harq.harq_confidence_level; + if (nr_bit > 0) { + if (nr_bit == 1 && do_DTX == 0) + ack_nack_errors += (actual_payload ^ (!harq_list[0].harq_value)); + else if (do_DTX == 0) + ack_nack_errors += + (((actual_payload & 1) ^ (!harq_list[1].harq_value)) + ((actual_payload >> 1) ^ (!harq_list[0].harq_value))); + else if ((!confidence_lvl && !harq_list[0].harq_value) || (!confidence_lvl && nr_bit == 2 && !harq_list[1].harq_value)) + ack_nack_errors++; } - else pucch_pdu.freq_hop_flag = 0; + + } else if (format == 2) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t uci_pdu = {0}; + nfapi_nr_pucch_pdu_t pucch_pdu = {0}; + pucch_pdu.rnti = 0x1234; + pucch_pdu.subcarrier_spacing = 1; + pucch_pdu.group_hop_flag = PUCCH_GroupHopping & 1; + pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping >> 1) & 1; + pucch_pdu.bit_len_csi_part1 = nr_bit; + pucch_pdu.bit_len_harq = 0; + pucch_pdu.bit_len_csi_part2 = 0; + pucch_pdu.sr_flag = 0; + pucch_pdu.nr_of_symbols = nrofSymbols; + pucch_pdu.hopping_id = hopping_id; + pucch_pdu.initial_cyclic_shift = 0; + pucch_pdu.start_symbol_index = startingSymbolIndex; + pucch_pdu.prb_size = nrofPRB; + pucch_pdu.prb_start = startingPRB; + pucch_pdu.dmrs_scrambling_id = dmrs_scrambling_id; + pucch_pdu.data_scrambling_id = data_scrambling_id; + if (nrofSymbols > 1) { + pucch_pdu.freq_hop_flag = 1; + pucch_pdu.second_hop_prb = N_RB_DL - 1; + } else + pucch_pdu.freq_hop_flag = 0; nr_decode_pucch2(gNB, rxdataF, nr_frame_tx, nr_slot_tx, &uci_pdu, &pucch_pdu); - int csi_part1_bytes=pucch_pdu.bit_len_csi_part1>>3; - if ((pucch_pdu.bit_len_csi_part1&7) > 0) csi_part1_bytes++; - for (int i=0;i> 3; + if ((pucch_pdu.bit_len_csi_part1 & 7) > 0) + csi_part1_bytes++; + for (int i = 0; i < csi_part1_bytes; i++) { + if (uci_pdu.csi_part1.csi_part1_payload[i] != ((uint8_t *)&actual_payload)[i]) { ack_nack_errors++; break; } } free(uci_pdu.csi_part1.csi_part1_payload); - } stop_meas(&gNB->phy_proc_rx); - n_errors=((actual_payload^payload_received)&1)+(((actual_payload^payload_received)&2)>>1)+(((actual_payload^payload_received)&4)>>2)+n_errors; + n_errors = ((actual_payload ^ payload_received) & 1) + (((actual_payload ^ payload_received) & 2) >> 1) + + (((actual_payload ^ payload_received) & 4) >> 2) + n_errors; } if (sr_flag == 1) - printf("SR: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,sr_errors); + printf("SR: SNR=%f, n_trials=%d, n_bit_errors=%d\n", SNR, n_trials, sr_errors); if (print_perf) { time_stats_t *ts = &gNB->phy_proc_rx; printf("cpu time for pucch format %d: per block %.2f us; nb blocks %d, max time %.2f;\n", @@ -760,9 +821,9 @@ int main(int argc, char **argv) ts->max / cpuf / 1000.0); reset_meas(ts); } - if(nr_bit > 0) - printf("ACK/NACK: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors); - if((float)(ack_nack_errors+sr_errors)/(float)(n_trials)<=target_error_rate){ + if (nr_bit > 0) + printf("ACK/NACK: SNR=%f, n_trials=%d, n_bit_errors=%d\n", SNR, n_trials, ack_nack_errors); + if ((float)(ack_nack_errors + sr_errors) / (float)(n_trials) <= target_error_rate) { printf("PUCCH test OK\n"); ret = 0; break; @@ -787,11 +848,11 @@ int main(int argc, char **argv) term_nr_ue_signal(UE); free(UE); - for (int aatx=0; aatx