Reformat pucch_rx.c

This commit is contained in:
Robert Schmidt
2026-03-25 14:29:31 +01:00
committed by francescomani
parent ec7ad3b87c
commit 2cb96ea534
+262 -240
View File
@@ -29,7 +29,7 @@
* \note
* \warning
*/
#include<stdio.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
@@ -93,64 +93,63 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t
AssertFatal(found, "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}
};
static const int16_t idft12_re[12][12] = {
{23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170},
{23170, 20066, 11585, 0, -11585, -20066, -23170, -20066, -11585, 0, 11585, 20066},
{23170, 11585, -11585, -23170, -11585, 11585, 23170, 11585, -11585, -23170, -11585, 11585},
{23170, 0, -23170, 0, 23170, 0, -23170, 0, 23170, 0, -23170, 0},
{23170, -11585, -11585, 23170, -11585, -11585, 23170, -11585, -11585, 23170, -11585, -11585},
{23170, -20066, 11585, 0, -11585, 20066, -23170, 20066, -11585, 0, 11585, -20066},
{23170, -23170, 23170, -23170, 23170, -23170, 23170, -23170, 23170, -23170, 23170, -23170},
{23170, -20066, 11585, 0, -11585, 20066, -23170, 20066, -11585, 0, 11585, -20066},
{23170, -11585, -11585, 23170, -11585, -11585, 23170, -11585, -11585, 23170, -11585, -11585},
{23170, 0, -23170, 0, 23170, 0, -23170, 0, 23170, 0, -23170, 0},
{23170, 11585, -11585, -23170, -11585, 11585, 23170, 11585, -11585, -23170, -11585, 11585},
{23170, 20066, 11585, 0, -11585, -20066, -23170, -20066, -11585, 0, 11585, 20066}};
static const int16_t idft12_im[12][12] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 11585, 20066, 23170, 20066, 11585, 0, -11585, -20066, -23170, -20066, -11585},
{0, 20066, 20066, 0, -20066, -20066, 0, 20066, 20066, 0, -20066, -20066},
{0, 23170, 0, -23170, 0, 23170, 0, -23170, 0, 23170, 0, -23170},
{0, 20066, -20066, 0, 20066, -20066, 0, 20066, -20066, 0, 20066, -20066},
{0, 11585, -20066, 23170, -20066, 11585, 0, -11585, 20066, -23170, 20066, -11585},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, -11585, 20066, -23170, 20066, -11585, 0, 11585, -20066, 23170, -20066, 11585},
{0, -20066, 20066, 0, -20066, 20066, 0, -20066, 20066, 0, -20066, 20066},
{0, -23170, 0, 23170, 0, -23170, 0, 23170, 0, -23170, 0, 23170},
{0, -20066, -20066, 0, 20066, 20066, 0, -20066, -20066, 0, 20066, 20066},
{0, -11585, -20066, -23170, -20066, -11585, 0, 11585, 20066, 23170, 20066, 11585}};
//************************************************************************//
void nr_decode_pucch0(PHY_VARS_gNB *gNB,
c16_t **rxdataF,
@@ -179,24 +178,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
@@ -204,7 +211,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
@@ -212,7 +219,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,
@@ -221,47 +228,46 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
slot,
&u[1],
&v[1]); // calculating u and v value second hop
LOG_D(PHY,"pucch0 second hop: u %d, v %d\n",u[1],v[1]);
LOG_D(PHY, "pucch0 second hop: u %d, v %d\n", u[1], v[1]);
prb_offset[1] = pucch_pdu->bwp_start + pucch_pdu->second_hop_prb;
}
AssertFatal(pucch_pdu->nr_of_symbols < 3,"nr_of_symbols %d not allowed\n",pucch_pdu->nr_of_symbols);
AssertFatal(pucch_pdu->nr_of_symbols < 3, "nr_of_symbols %d not allowed\n", pucch_pdu->nr_of_symbols);
uint32_t re_offset[2] = {0};
const int16_t *x_re[2],*x_im[2];
const int16_t *x_re[2], *x_im[2];
x_re[0] = table_5_2_2_2_2_Re[u[0]];
x_im[0] = table_5_2_2_2_2_Im[u[0]];
x_re[1] = table_5_2_2_2_2_Re[u[1]];
x_im[1] = table_5_2_2_2_2_Im[u[1]];
c64_t xr[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][12] __attribute__((aligned(32)));
c64_t xr[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][12] __attribute__((aligned(32)));
memset(xr, 0, frame_parms->nb_antennas_rx * pucch_pdu->nr_of_symbols * 12 * sizeof(c64_t));
int64_t xrtmag=0,xrtmag_next=0;
uint8_t maxpos=0;
uint8_t index=0;
int64_t xrtmag = 0, xrtmag_next = 0;
uint8_t maxpos = 0;
uint8_t index = 0;
int nb_re_pucch = 12*pucch_pdu->prb_size; // prb size is 1
int nb_re_pucch = 12 * pucch_pdu->prb_size; // prb size is 1
int64_t signal_energy = 0, signal_energy_ant0 = 0;
for (int l=0; 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++) {
@@ -281,20 +287,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];
@@ -303,10 +308,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],
@@ -334,33 +343,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);
@@ -381,10 +389,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,
@@ -397,28 +405,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 "
@@ -440,23 +447,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,
@@ -473,11 +480,11 @@ 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);
}
}
}
@@ -519,12 +526,13 @@ void nr_decode_pucch1(c16_t **rxdataF,
*
*/
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]
// 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;
// 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:
@@ -535,21 +543,22 @@ 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
// uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers
const bool intraSlotFrequencyHopping = startingPRB != startingPRB_intraSlotHopping;
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n",intraSlotFrequencyHopping);
printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n", intraSlotFrequencyHopping);
#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
#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};
const int half_nb_rb_dl = frame_parms->N_RB_DL >> 1;
@@ -578,11 +587,12 @@ void nr_decode_pucch1(c16_t **rxdataF,
re_offset += 12 * startingPRB + frame_parms->first_carrier_offset;
}
for (int n=0; n<12; n++) {
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);
// 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);
}
if (l % 2 == 1) // mapping PUCCH or DM-RS according to TS38.211 subclause 6.4.1.3.1
@@ -610,11 +620,10 @@ void nr_decode_pucch1(c16_t **rxdataF,
}
}
cd_t y_n[12] = {0}, y1_n[12] = {0};
//generating transmitted sequence and dmrs
// generating transmitted sequence and dmrs
for (int l = 0; l < nrofSymbols; l++) {
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] for symbol l=%d, lprime=%d\n",
l,lprime);
printf("\t [nr_generate_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
@@ -626,13 +635,12 @@ void nr_decode_pucch1(c16_t **rxdataF,
const int n_hop = intraSlotFrequencyHopping && l >= nrofSymbols / 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_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n", n_hop, nr_tti_tx);
#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, n_id, n_hop, nr_tti_tx, &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
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)
@@ -660,8 +668,8 @@ void nr_decode_pucch1(c16_t **rxdataF,
* (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)
*
*/
@@ -672,8 +680,10 @@ void nr_decode_pucch1(c16_t **rxdataF,
const int w_index = timeDomainOCC;
if (intraSlotFrequencyHopping == false) { // intra-slot hopping disabled
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n",
intraSlotFrequencyHopping);
printf(
"\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, "
"intra-slot hopping disabled\n",
intraSlotFrequencyHopping);
#endif
// mprime is 0 in this not hopping case
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1
@@ -693,8 +703,8 @@ void nr_decode_pucch1(c16_t **rxdataF,
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++) {
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) {
@@ -707,7 +717,7 @@ void nr_decode_pucch1(c16_t **rxdataF,
}
}
} 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) {
@@ -725,8 +735,10 @@ void nr_decode_pucch1(c16_t **rxdataF,
if (intraSlotFrequencyHopping == true) { // intra-slot hopping enabled
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n",
intraSlotFrequencyHopping);
printf(
"\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, "
"intra-slot hopping enabled\n",
intraSlotFrequencyHopping);
#endif
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1
// (depending on number of PUCCH symbols nrofSymbols, mprime and
@@ -749,8 +761,14 @@ void nr_decode_pucch1(c16_t **rxdataF,
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)
#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_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);
#endif
for (int mprime = 0; mprime < 2; mprime++) { // mprime can get values {0,1}
@@ -786,7 +804,8 @@ void nr_decode_pucch1(c16_t **rxdataF,
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)
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)
}
}
}
@@ -835,7 +854,7 @@ void nr_decode_pucch1(c16_t **rxdataF,
d.i += H[n].r * y1_n[n].i - H[n].i * y1_n[n].r;
}
}
//Decoding QPSK or BPSK symbols to obtain payload bits
// Decoding QPSK or BPSK symbols to obtain payload bits
if (nr_bit == 1) {
if ((d.r + d.i) > 0) {
*payload = 0;
@@ -855,18 +874,20 @@ void nr_decode_pucch1(c16_t **rxdataF,
}
}
typedef struct {c16_t cw[16];} cw_t;
static cw_t pucch2_3bit[8] __attribute__((aligned(32)));
typedef struct {
c16_t cw[16];
} cw_t;
static cw_t pucch2_3bit[8] __attribute__((aligned(32)));
static cw_t pucch2_4bit[16] __attribute__((aligned(32)));
static cw_t pucch2_5bit[32] __attribute__((aligned(32)));
static cw_t pucch2_6bit[64] __attribute__((aligned(32)));
static cw_t pucch2_6bit[64] __attribute__((aligned(32)));
static cw_t pucch2_7bit[128] __attribute__((aligned(32)));
static cw_t pucch2_8bit[256] __attribute__((aligned(32)));
static cw_t pucch2_9bit[512] __attribute__((aligned(32)));
static cw_t pucch2_10bit[1024] __attribute__((aligned(32)));
static cw_t pucch2_11bit[2048] __attribute__((aligned(32)));
static cw_t* pucch2_lut[9] =
static cw_t *pucch2_lut[9] =
{pucch2_3bit, pucch2_4bit, pucch2_5bit, pucch2_6bit, pucch2_7bit, pucch2_8bit, pucch2_9bit, pucch2_10bit, pucch2_11bit};
typedef struct {
@@ -877,12 +898,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++) {
@@ -912,22 +933,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;
@@ -941,10 +960,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);
@@ -954,16 +970,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));
}
@@ -988,8 +1003,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;
@@ -1035,13 +1050,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
@@ -1074,7 +1088,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
@@ -1133,22 +1150,22 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
log_dump(PHY, r_ext[aa], nb_re_data, LOG_DUMP_C16, "after delay compensation ant %d data:\n", aa);
}
#endif
c16_t rdmrs_gold[Prx][nb_re_dmrs] __attribute__((aligned(32)));
for (int aa = 0; aa < Prx; aa++)
mult_complex_vectors(rdmrs_ext[aa], pil_dmrs, rdmrs_gold[aa], nb_re_dmrs, 0);
for (int aa=0;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
// non-coherent combining across groups
c16_t *rdmrs_p = &rdmrs_ext[aa][8 * group];
for (int z = 0; z < 8; z++) {
c16_t tmp = c16mulShift(*rdmrs_p++, *pil_ptr++, scaling);
corr32[symb][group][aa].r += tmp.r;
corr32[symb][group][aa].i += tmp.i;
}
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++) {
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
// non-coherent combining across groups
c16_t *rdmrs_p = &rdmrs_ext[aa][8 * group];
for (int z = 0; z < 8; z++) {
c16_t tmp = c16mulShift(*rdmrs_p++, *pil_ptr++, scaling);
corr32[symb][group][aa].r += tmp.r;
corr32[symb][group][aa].i += tmp.i;
}
}
}
#ifdef DEBUG_NR_PUCCH_RX
log_dump(PHY, corr32[symb][0], 8, LOG_DUMP_C32, "corr32:");
#endif
@@ -1166,7 +1183,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,
@@ -1176,20 +1193,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));
memset(decodedPayload, 0, sizeof(decodedPayload));
int8_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;
@@ -1222,35 +1242,35 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
#endif
}
}// group loop
} // group loop
} // symb loop
if (corr_tmp > corr) {
corr = corr_tmp;
cw_ML = cw;
#ifdef DEBUG_NR_PUCCH_RX
#ifdef DEBUG_NR_PUCCH_RX
printf("slot %d PUCCH2 cw_ML %d, corr %lu\n", slot, cw_ML, corr);
#endif
}
} // cw loop
corr_dB = dB_fixed64(corr);
#ifdef DEBUG_NR_PUCCH_RX
printf("slot %d PUCCH2 cw_ML %d, metric %d \n",slot,cw_ML,corr_dB);
printf("slot %d PUCCH2 cw_ML %d, metric %d \n", slot, cw_ML, corr_dB);
#endif
decodedPayload[0]=(uint64_t)cw_ML;
decodedPayload[0] = (uint64_t)cw_ML;
} else if (nb_bit >= 12) { // polar coded case
simde__m128i llrs[pucch_pdu->prb_size * 2 * nb_symbols];
// non-coherent LLR computation on groups of 4 REs (half-PRBs)
uint64_t corr = 0;
const simde__m128i ones = simde_mm_set1_epi16(1);
for (int symb=0;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++) {
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++) {
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);
@@ -1280,12 +1300,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);
@@ -1344,31 +1365,32 @@ 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;
}
}