Commit a2f0cef8 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/pucch_format1_MR' into integration_2026_w13 (!3966)

PUCCH Format 1 decoder implementation and validation with nr_pucchsim

This is the implementation of the PUCCH Format 1 decoder, validated with
pucchsim in the current branch.
Build:
  ./build_oai --nrUE --gNB --ninja --phy_simulators
Run tests:
  ctest -L nr_pucchsim -j 8
parents 0ceb5fd3 4649107d
......@@ -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,
......
......@@ -29,7 +29,7 @@
* \note
* \warning
*/
#include<stdio.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
......@@ -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;i<gNB->pucch0_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 (i<gNB->pucch0_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<<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.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}
};
{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,14 +225,14 @@ 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]];
......@@ -235,31 +241,30 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
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; l<pucch_pdu->nr_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;aa<frame_parms->nb_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;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;
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;aa<frame_parms->nb_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
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
startingPRB = startingPRB + startingPRB_intraSlotHopping;
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
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 * startingPRB + frame_parms->first_carrier_offset;
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
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 * startingPRB + frame_parms->first_carrier_offset;
else if (startingPRB > half_nb_rb_dl) // if number RBs in bandwidth is odd
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 * (startingPRB - half_nb_rb_dl) + 6;
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,10 +710,12 @@ 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",
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
......@@ -686,31 +731,34 @@ 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 r = 0; r < n_rx; r++) {
for (int n = 0; n < 12; n++) {
c16_t *zPtr = z_rx + m * 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 r = 0; r < n_rx; r++) {
for (int n = 0; n < 12; n++) {
c16_t *zDmrsPtr = z_dmrs_rx + m * 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
......@@ -720,10 +768,13 @@ 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",
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
......@@ -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 r = 0; r < n_rx; r++) {
for (int n = 0; n < 12; n++) {
c16_t *zPtr = z_rx + (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 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, 16);
*zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 15);
}
}
}
}
......@@ -771,89 +831,274 @@ 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 r = 0; r < n_rx; r++) {
for (int n = 0; n < 12; n++) {
c16_t *zDmrsPtr = z_dmrs_rx + (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 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, 16);
*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;
} // 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 / 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;
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 {
if (l < nrofSymbols / 4) {
} else { // with Frequency-hopping
if (l < pucch_pdu->nr_of_symbols / 4) {
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;
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) {
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 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;
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 {
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;
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));
}
}
}
}
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);
}
}
//Decoding QPSK or BPSK symbols to obtain payload bits
if (nr_bit == 1) {
if ((d.r + d.i) > 0) {
*payload = 0;
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 = 1;
}
} 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;
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 {
*payload = 3;
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;
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)));
......@@ -864,7 +1109,7 @@ 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<<j)) > 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;aa<Prx;aa++){
for (int symb=0;symb<nb_symbols;symb++) {
for (int aa = 0; aa < Prx; aa++) {
for (int symb = 0; symb < nb_symbols; symb++) {
c16_t *tmp_rp = ((c16_t *)&rxdataF[aa][soffset + (l2 + symb) * frame_parms->ofdm_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; symb<nb_symbols;symb++) {
for (int symb = 0; symb < nb_symbols; symb++) {
c16_t rdmrs_ext[Prx][nb_re_dmrs] __attribute__((aligned(32)));
// extract DMRS
......@@ -1072,7 +1310,10 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
% (1U << 31); // c_init calculation according to TS38.211 subclause
#ifdef DEBUG_NR_PUCCH_RX
printf("slot %d, start_symbol_index %d, symbol %d, dmrs_scrambling_id %d\n",
slot,pucch_pdu->start_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
......@@ -1134,7 +1375,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
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;aa<Prx;aa++) {
for (int aa = 0; aa < Prx; aa++) {
c16_t *pil_ptr = pil_dmrs;
for (int group = 0; group < ngroup; group++) {
// each group has 8*nc_group_size elements, compute 1 complex correlation with DMRS per group
......@@ -1164,7 +1405,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
}
}
int nb_bit = pucch_pdu->bit_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<nb_symbols;symb++) {
for (int group=0;group<ngroup;group++) {
for (int symb = 0; symb < nb_symbols; symb++) {
for (int group = 0; group < ngroup; group++) {
// do complex correlation
for (int aa = 0; aa < Prx; aa++) {
const simde__m256i *coeff = (simde__m256i *)&pucch2_lut[nb_bit - 3][cw].cw;
......@@ -1220,7 +1464,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
#endif
}
}// group loop
} // group loop
} // symb loop
if (corr_tmp > corr) {
corr = corr_tmp;
......@@ -1232,9 +1476,9 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
} // 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
......@@ -1242,13 +1486,13 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
// 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;symb<nb_symbols;symb++) {
for (int half_prb=0;half_prb<(2*pucch_pdu->prb_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<Prx;aa++) {
for (int cw = 0; cw < 256; cw++) {
int32_t corr_tmp = 0;
for (int aa = 0; aa < Prx; aa++) {
simde__m128i part1 = simde_mm_set_epi64x(0ULL, *(int64_t *)&pucch2_polar_4bit[cw & 15].cw);
simde__m128i part2 = simde_mm_set_epi64x(0ULL, *(int64_t *)&pucch2_polar_4bit[cw >> 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 (;i<csi_part1_bytes-1;i++) {
int i = 0;
for (; i < csi_part1_bytes - 1; i++) {
uci_pdu->csi_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);
}
......@@ -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);
......
......@@ -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;
......
......@@ -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,54 +155,53 @@ 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");
// write_output_file=1;
output_fd = fopen(optarg, "w");
if (output_fd==NULL) {
printf("Error opening %s\n",optarg);
if (output_fd == NULL) {
printf("Error opening %s\n", optarg);
exit(-1);
}
break;
case 'g':
switch((char)*optarg) {
switch ((char)*optarg) {
case 'A':
channel_model=SCM_A;
channel_model = SCM_A;
break;
case 'B':
channel_model=SCM_B;
channel_model = SCM_B;
break;
case 'C':
channel_model=SCM_C;
channel_model = SCM_C;
break;
case 'D':
channel_model=SCM_D;
channel_model = SCM_D;
break;
case 'E':
channel_model=EPA;
channel_model = EPA;
break;
case 'F':
channel_model=EVA;
channel_model = EVA;
break;
case 'G':
channel_model=ETU;
channel_model = ETU;
break;
case 'H':
channel_model = TDL_C;
......@@ -213,7 +214,7 @@ int main(int argc, char **argv)
break;
case 'J':
channel_model=TDL_D;
channel_model = TDL_D;
DS_TDL = .03;
break;
......@@ -229,69 +230,50 @@ int main(int argc, char **argv)
case 'o':
cfo = atof(optarg);
printf("Setting CFO to %f Hz\n",cfo);
printf("Setting CFO to %f Hz\n", cfo);
break;
case 's':
snr0 = atof(optarg);
printf("Setting SNR0 to %f\n",snr0);
printf("Setting SNR0 to %f\n", snr0);
break;
case 'S':
snr1 = atof(optarg);
snr1set=1;
printf("Setting SNR1 to %f\n",snr1);
snr1set = 1;
printf("Setting SNR1 to %f\n", snr1);
break;
case 't':
pucch_DTX_thres= atoi(optarg);
break;
/*
case 'p':
extended_prefix_flag=1;
pucch_DTX_thres = atoi(optarg);
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);
delay_us = atof(optarg);
break;
case 'x':
transmission_mode=atoi(optarg);
transmission_mode = atoi(optarg);
if ((transmission_mode!=1) &&
(transmission_mode!=2) &&
(transmission_mode!=6)) {
printf("Unsupported transmission mode %d\n",transmission_mode);
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);
n_tx = atoi(optarg);
if ((n_tx==0) || (n_tx>2)) {
printf("Unsupported number of tx antennas %d\n",n_tx);
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);
n_rx = atoi(optarg);
if ((n_rx==0) || (n_rx>8)) {
printf("Unsupported number of rx antennas %d\n",n_rx);
if ((n_rx == 0) || (n_rx > 8)) {
printf("Unsupported number of rx antennas %d\n", n_rx);
exit(-1);
}
break;
......@@ -305,10 +287,10 @@ int main(int argc, char **argv)
break;
case 'F':
input_fd = fopen(optarg,"r");
input_fd = fopen(optarg, "r");
if (input_fd==NULL) {
printf("Problem with filename %s\n",optarg);
if (input_fd == NULL) {
printf("Problem with filename %s\n", optarg);
exit(-1);
}
break;
......@@ -317,36 +299,40 @@ int main(int argc, char **argv)
loglvl = atoi(optarg);
break;
case 'i':
nrofSymbols=(uint8_t)atoi(optarg);
nrofSymbols = (uint8_t)atoi(optarg);
nrofSymbols_set = 1;
break;
case 'I':
startingSymbolIndex=(uint8_t)atoi(optarg);
startingSymbolIndex = (uint8_t)atoi(optarg);
break;
case 'r':
startingPRB=atoi(optarg);
startingPRB = atoi(optarg);
break;
case 'q':
nrofPRB=atoi(optarg);
nrofPRB = atoi(optarg);
break;
case 'P':
format=atoi(optarg);
format = atoi(optarg);
if ((format == 1 || format == 3) && nrofSymbols_set == 0)
nrofSymbols = 14;
break;
case 'm':
m0=atoi(optarg);
m0 = atoi(optarg);
break;
case 'b':
nr_bit=atoi(optarg);
nr_bit = atoi(optarg);
break;
case 'c':
sr_flag=1;
sr_flag = 1;
break;
case 'B':
actual_payload=atoi(optarg);
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;
// nacktoack_flag=(uint8_t)atoi(optarg);
target_error_rate = 0.001;
break;
case 'C':
print_perf = 1;
......@@ -354,8 +340,12 @@ int main(int argc, char **argv)
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(
"%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");
......@@ -363,7 +353,9 @@ int main(int argc, char **argv)
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(
"-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");
......@@ -385,43 +377,46 @@ int main(int argc, char **argv)
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);
exit(-1);
break;
}
}
double phase = (1<<mu)*30e-3*delay_us;
double phase = (1 << mu) * 30e-3 * delay_us;
set_glog(loglvl);
if (snr1set==0) snr1 = snr0+10;
if (snr1set == 0)
snr1 = snr0 + 10;
printf("Initializing gNodeB for mu %d, N_RB_DL %d, n_rx %d\n",mu,N_RB_DL,n_rx);
printf("Initializing gNodeB for mu %d, N_RB_DL %d, n_rx %d\n", mu, N_RB_DL, n_rx);
if((format!=0) && (format!=1) && (format!=2)){
printf("PUCCH format %d not supported\n",format);
if ((format != 0) && (format != 1) && (format != 2)) {
printf("PUCCH format %d not supported\n", format);
exit(0);
}
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;
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; aatx<n_tx; aatx++) {
s_re[aatx] = calloc(1,frame_length_complex_samples*sizeof(double));
s_im[aatx] = calloc(1,frame_length_complex_samples*sizeof(double));
for (int aatx = 0; aatx < n_tx; aatx++) {
s_re[aatx] = calloc(1, frame_length_complex_samples * sizeof(double));
s_im[aatx] = calloc(1, frame_length_complex_samples * sizeof(double));
}
for (int aarx=0; aarx<n_rx; aarx++) {
r_re[aarx] = calloc(1,frame_length_complex_samples*sizeof(double));
r_im[aarx] = calloc(1,frame_length_complex_samples*sizeof(double));
for (int aarx = 0; aarx < n_rx; aarx++) {
r_re[aarx] = calloc(1, frame_length_complex_samples * sizeof(double));
r_im[aarx] = calloc(1, frame_length_complex_samples * sizeof(double));
}
uint8_t mcs=0;
uint8_t mcs = 0;
int shift = 0;
if(format==0){
if (format == 0) {
if (sr_flag)
shift = 1<<nr_bit;
if (nr_bit ==0)
mcs=table1_mcs[0];
else if(nr_bit==1)
mcs=table1_mcs[actual_payload+shift];
else if(nr_bit==2)
mcs=table2_mcs[actual_payload+shift];
else AssertFatal(1==0,"Either nr_bit %d or sr_flag %d must be non-zero\n", nr_bit, sr_flag);
shift = 1 << nr_bit;
if (nr_bit == 0)
mcs = table1_mcs[0];
else if (nr_bit == 1)
mcs = table1_mcs[actual_payload + shift];
else if (nr_bit == 2)
mcs = table2_mcs[actual_payload + shift];
else
AssertFatal(1 == 0, "Either nr_bit %d or sr_flag %d must be non-zero\n", nr_bit, sr_flag);
}
startingPRB_intraSlotHopping = N_RB_DL-1;
startingPRB_intraSlotHopping = N_RB_DL - 1;
uint32_t hopping_id = Nid_cell;
uint32_t dmrs_scrambling_id = 0;
uint32_t data_scrambling_id = 0;
//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;
// 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; symb<gNB->frame_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);
for (int symb = 0; symb < gNB->frame_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<<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);
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;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;
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;aarx<n_rx;aarx++) rxlev += signal_energy((int32_t*)&rxdataF[aarx][startingSymbolIndex*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;aarx<n_rx;aarx++) rxlev_pucch += signal_energy((int32_t*)&rxdataF[aarx][startingSymbolIndex*frame_parms->ofdm_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;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;
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,14 +686,14 @@ 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.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;
......@@ -674,48 +706,76 @@ int main(int argc, char **argv)
pucch_pdu.prb_size = 1;
pucch_pdu.bwp_start = 0;
pucch_pdu.bwp_size = N_RB_DL;
if (nrofSymbols>1) {
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.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) {
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 = 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 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 == 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.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;
......@@ -728,29 +788,30 @@ int main(int argc, char **argv)
pucch_pdu.prb_start = startingPRB;
pucch_pdu.dmrs_scrambling_id = dmrs_scrambling_id;
pucch_pdu.data_scrambling_id = data_scrambling_id;
if (nrofSymbols>1) {
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.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<csi_part1_bytes;i++) {
if (uci_pdu.csi_part1.csi_part1_payload[i] != ((uint8_t*)&actual_payload)[i]) {
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 < 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<n_tx; aatx++) {
for (int aatx = 0; aatx < n_tx; aatx++) {
free(s_re[aatx]);
free(s_im[aatx]);
}
for (int aarx=0; aarx<n_rx; aarx++) {
for (int aarx = 0; aarx < n_rx; aarx++) {
free(r_re[aarx]);
free(r_im[aarx]);
}
......@@ -800,8 +861,10 @@ int main(int argc, char **argv)
free(r_re);
free(r_im);
if (output_fd) fclose(output_fd);
if (input_fd) fclose(input_fd);
if (output_fd)
fclose(output_fd);
if (input_fd)
fclose(input_fd);
loader_reset();
logTerm();
......
......@@ -262,6 +262,24 @@ add_physim_test(physim.5g.nr_pucchsim.test26 "Format 2 12-bit 8/273 PRB" nr_pucc
add_physim_test(physim.5g.nr_pucchsim.test27 "Format 2 19-bit 8/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q8 -b 19 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test28 "Format 2 64-bit 16/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test29 "Format 2 64-bit 16/273 PRB Delay 2us" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s0 -S7 -d 2 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test30 "Format 1 NACK number of symbols = 4 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 1 -B 0 -s-8 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test31 "Format 1 ACK number of symbols = 4 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 1 -B 1 -s-8 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test32 "Format 1 (NACK,NACK) number of symbols = 4, 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 0 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test33 "Format 1 (ACK,NACK) number of symbols = 4, 273PRB with SR" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 1 -s-8 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test34 "Format 1 (NACK,ACK) number of symbols = 4, 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 2 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test35 "Format 1 (ACK,ACK) number of symbols = 4, 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 3 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test36 "Format 1 NACK number of symbols = 8, 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 1 -B 0 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test37 "Format 1 ACK number of symbols = 8, 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 1 -B 1 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test38 "Format 1 (NACK,NACK) number of symbols = 8, 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 0 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test39 "Format 1 (ACK,NACK) number of symbols = 8, 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 1 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test40 "Format 1 (NACK,ACK) number of symbols = 8, 273PRB with SR" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 2 -s-8 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test41 "Format 1 (ACK,ACK) number of symbols = 8, 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 3 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test42 "Format 1 NACK number of symbols = 14, 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 1 -B 0 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test43 "Format 1 ACK number of symbols = 14, 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 1 -B 1 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test44 "Format 1 (NACK,NACK) number of symbols = 14, 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 0 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test45 "Format 1 (ACK,NACK) number of symbols = 14, 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 1 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test46 "Format 1 (NACK,ACK) number of symbols = 14, 273PRB with SR" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 2 -s-8 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test47 "Format 1 (ACK,ACK) number of symbols = 14, 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 3 -s-8 -n1000)
####################################################################################
###### nr_ulsim unit test ######
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment