Add PUCCH Format 1 decoder
This commit completes the PUCCH Format 1 decoder implementation using maximum-likelihood detection with RE averaging across symbols/RB (and hop-wise averaging for intra-slot hopping). It also updates the PUCCH simulation/test flow to align with the decoder changes, including payload and logging consistency fixes needed for correct validation.
This commit is contained in:
committed by
francescomani
parent
2cb96ea534
commit
584ace460c
@@ -245,20 +245,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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
bool found = false;
|
||||
@@ -490,24 +489,16 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
|
||||
}
|
||||
}
|
||||
//*****************************************************************//
|
||||
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",
|
||||
@@ -519,16 +510,19 @@ 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;
|
||||
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 = startingSymbolIndex;
|
||||
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
|
||||
@@ -549,81 +543,137 @@ void nr_decode_pucch1(c16_t **rxdataF,
|
||||
// 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;
|
||||
const bool intraSlotFrequencyHopping = pucch_pdu->prb_start != pucch_pdu->second_hop_prb;
|
||||
float inv_sqrt2 = 0.70710678118f; // 1 / sqrt(2)
|
||||
int64_t signal_energy = 0, signal_energy_ant0 = 0;
|
||||
uint8_t nb_re_pucch = pucch_pdu->prb_size * 12;
|
||||
pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag << 1);
|
||||
int16_t amp = 0x7FFF;
|
||||
int xrtmag_dBtimes10 = 0;
|
||||
|
||||
NR_gNB_UCI_STATS_t stack_uci_stats = {0};
|
||||
NR_gNB_UCI_STATS_t *uci_stats = &stack_uci_stats;
|
||||
NR_gNB_PHY_STATS_t *phy_stats = get_phy_stats(gNB, pucch_pdu->rnti);
|
||||
if (phy_stats != NULL) {
|
||||
phy_stats->frame = frame;
|
||||
uci_stats = &phy_stats->uci_stats;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NR_PUCCH_RX
|
||||
printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n", intraSlotFrequencyHopping);
|
||||
printf("\t [nr_decode_pucch1] intraSlotFrequencyHopping = %d \n", intraSlotFrequencyHopping);
|
||||
printf("\t [nr_decode_pucch1] soffset= %d\n", soffset);
|
||||
#endif
|
||||
/*
|
||||
* Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources
|
||||
*/
|
||||
#define MAX_SIZE_Z \
|
||||
168 // this value has to be calculated from mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n
|
||||
c16_t z_rx[MAX_SIZE_Z] = {0};
|
||||
c16_t z_dmrs_rx[MAX_SIZE_Z] = {0};
|
||||
// This value has to be calculated from mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n
|
||||
#define MAX_SIZE_Z 168
|
||||
c16_t z_rx[16][MAX_SIZE_Z] = {0};
|
||||
c16_t z_dmrs_rx[16][MAX_SIZE_Z] = {0};
|
||||
c16_t z[16][12] = {0};
|
||||
const int half_nb_rb_dl = frame_parms->N_RB_DL >> 1;
|
||||
const bool nb_rb_is_even = (frame_parms->N_RB_DL & 1) == 0;
|
||||
for (int l = 0; l < nrofSymbols; l++) { // extracting data and dmrs from rxdataF
|
||||
if (intraSlotFrequencyHopping && (l < floor(nrofSymbols / 2))) { // intra-slot hopping enabled, we need
|
||||
// to calculate new offset PRB
|
||||
startingPRB = startingPRB + startingPRB_intraSlotHopping;
|
||||
for (int l = 0; l < pucch_pdu->nr_of_symbols; l++) { // extracting data and dmrs from rxdataF
|
||||
if (intraSlotFrequencyHopping && (l >= floor(pucch_pdu->nr_of_symbols / 2))) { // intra-slot hopping enabled, we need
|
||||
// to calculate new offset PRB
|
||||
pucch_pdu->prb_start = pucch_pdu->bwp_start + pucch_pdu->second_hop_prb;
|
||||
}
|
||||
int re_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size;
|
||||
int re_offset = (l + pucch_pdu->start_symbol_index) * frame_parms->ofdm_symbol_size;
|
||||
|
||||
if (nb_rb_is_even) {
|
||||
if (startingPRB < half_nb_rb_dl) // if number RBs in bandwidth is even and
|
||||
// current PRB is lower band
|
||||
re_offset += 12 * startingPRB + frame_parms->first_carrier_offset;
|
||||
if (pucch_pdu->prb_start < half_nb_rb_dl) // if number RBs in bandwidth is even and
|
||||
// current PRB is lower band
|
||||
re_offset += 12 * pucch_pdu->prb_start + frame_parms->first_carrier_offset;
|
||||
else // if number RBs in bandwidth is even and current PRB is upper band
|
||||
re_offset += 12 * (startingPRB - half_nb_rb_dl);
|
||||
re_offset += 12 * (pucch_pdu->prb_start - half_nb_rb_dl);
|
||||
} else {
|
||||
if (startingPRB < half_nb_rb_dl) // if number RBs in bandwidth is odd and
|
||||
// current PRB is lower band
|
||||
re_offset += 12 * startingPRB + frame_parms->first_carrier_offset;
|
||||
else if (startingPRB > half_nb_rb_dl) // if number RBs in bandwidth is odd
|
||||
// and current PRB is upper band
|
||||
re_offset += 12 * (startingPRB - half_nb_rb_dl) + 6;
|
||||
if (pucch_pdu->prb_start < half_nb_rb_dl) // if number RBs in bandwidth is odd and
|
||||
// current PRB is lower band
|
||||
re_offset += 12 * pucch_pdu->prb_start + frame_parms->first_carrier_offset;
|
||||
else if (pucch_pdu->prb_start > half_nb_rb_dl) // if number RBs in bandwidth is odd
|
||||
// and current PRB is upper band
|
||||
re_offset += 12 * (pucch_pdu->prb_start - half_nb_rb_dl) + 6;
|
||||
else // if number RBs in bandwidth is odd and current PRB contains DC
|
||||
re_offset += 12 * startingPRB + frame_parms->first_carrier_offset;
|
||||
re_offset += 12 * pucch_pdu->prb_start + frame_parms->first_carrier_offset;
|
||||
}
|
||||
|
||||
for (int n = 0; n < 12; n++) {
|
||||
const int current_subcarrier = l * 12 + n;
|
||||
if (n == 6 && startingPRB == half_nb_rb_dl && !nb_rb_is_even) {
|
||||
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 + startingSymbolIndex) * frame_parms->ofdm_symbol_size);
|
||||
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};
|
||||
|
||||
} // 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 < nrofSymbols; l++) {
|
||||
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
|
||||
@@ -632,14 +682,14 @@ 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);
|
||||
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]};
|
||||
@@ -647,21 +697,6 @@ void nr_decode_pucch1(c16_t **rxdataF,
|
||||
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)
|
||||
@@ -677,11 +712,11 @@ 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, "
|
||||
"\t [nr_decode_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, "
|
||||
"intra-slot hopping disabled\n",
|
||||
intraSlotFrequencyHopping);
|
||||
#endif
|
||||
@@ -698,21 +733,23 @@ 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)
|
||||
|
||||
// only if intra-slot hopping not enabled (PUCCH)
|
||||
int N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_pdu->nr_of_symbols - 1];
|
||||
// only if intra-slot hopping not enabled (DM-RS)
|
||||
int N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_pdu->nr_of_symbols - 1];
|
||||
if (l % 2 == 1) {
|
||||
for (int m = 0; m < N_SF_mprime_PUCCH_1; m++) {
|
||||
c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
|
||||
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
|
||||
if (l / 2 == m) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
c16_t *zPtr = z_rx + m * 12 + n;
|
||||
*zPtr = c16MulConjShift(table, *zPtr, 15);
|
||||
// multiplying with conjugate of low papr sequence
|
||||
*zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 16);
|
||||
for (int r = 0; r < n_rx; r++) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
c16_t *zPtr = z_rx[r] + m * 12 + n;
|
||||
*zPtr = c16MulConjShift(table, *zPtr, 15);
|
||||
// multiplying with conjugate of low papr sequence
|
||||
*zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -721,12 +758,14 @@ void nr_decode_pucch1(c16_t **rxdataF,
|
||||
const c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m],
|
||||
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m]};
|
||||
if (l / 2 == m) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
c16_t *zDmrsPtr = z_dmrs_rx + m * 12 + n;
|
||||
*zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15);
|
||||
// finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and
|
||||
// z_dmrs_im_rx arrays
|
||||
*zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 16);
|
||||
for (int r = 0; r < n_rx; r++) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
c16_t *zDmrsPtr = z_dmrs_rx[r] + m * 12 + n;
|
||||
*zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15);
|
||||
// finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and
|
||||
// z_dmrs_im_rx arrays
|
||||
*zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -736,7 +775,7 @@ 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, "
|
||||
"\t [nr_decode_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, "
|
||||
"intra-slot hopping enabled\n",
|
||||
intraSlotFrequencyHopping);
|
||||
#endif
|
||||
@@ -752,18 +791,19 @@ 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",
|
||||
"\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,
|
||||
@@ -777,10 +817,12 @@ void nr_decode_pucch1(c16_t **rxdataF,
|
||||
c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
|
||||
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
|
||||
if (floor(l / 2) * 12 == (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12)) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
c16_t *zPtr = z_rx + (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12) + n;
|
||||
*zPtr = c16MulConjShift(table, *zPtr, 15);
|
||||
*zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 16);
|
||||
for (int r = 0; r < n_rx; r++) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
c16_t *zPtr = z_rx[r] + (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12) + n;
|
||||
*zPtr = c16MulConjShift(table, *zPtr, 15);
|
||||
*zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -791,85 +833,267 @@ void nr_decode_pucch1(c16_t **rxdataF,
|
||||
c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
|
||||
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
|
||||
if (floor(l / 2) * 12 == (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 12)) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
c16_t *zDmrsPtr = z_dmrs_rx + (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 12) + n;
|
||||
*zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15);
|
||||
// finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and
|
||||
// z_dmrs_im_rx arrays
|
||||
*zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 16);
|
||||
for (int r = 0; r < n_rx; r++) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
c16_t *zDmrsPtr = z_dmrs_rx[r] + (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 12) + n;
|
||||
*zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15);
|
||||
// finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and
|
||||
// z_dmrs_im_rx arrays
|
||||
*zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
N_SF_mprime_PUCCH_1 =
|
||||
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH)
|
||||
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[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS)
|
||||
table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[pucch_pdu->nr_of_symbols
|
||||
- 1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS)
|
||||
}
|
||||
}
|
||||
}
|
||||
cd_t H[12] = {0}, H1[12] = {0};
|
||||
const double half_nb_symbols = nrofSymbols / 2.0;
|
||||
const double quarter_nb_symbols = nrofSymbols / 4.0;
|
||||
for (int l = 0; l <= half_nb_symbols; l++) {
|
||||
if (intraSlotFrequencyHopping == false) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
H[n].r += z_dmrs_rx[l * 12 + n].r / half_nb_symbols;
|
||||
H[n].i += z_dmrs_rx[l * 12 + n].i / half_nb_symbols;
|
||||
y_n[n].r += z_rx[l * 12 + n].r / half_nb_symbols;
|
||||
y_n[n].i += z_rx[l * 12 + n].i / half_nb_symbols;
|
||||
}
|
||||
} else {
|
||||
if (l < nrofSymbols / 4) {
|
||||
} // end of symbols loop
|
||||
|
||||
cd_t H[16] = {0}, H1[16] = {0};
|
||||
const double half_nb_symbols = pucch_pdu->nr_of_symbols / 2.0;
|
||||
for (int r = 0; r < n_rx; r++) {
|
||||
for (int l = 0; l <= half_nb_symbols; l++) {
|
||||
if (intraSlotFrequencyHopping == false) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
H[n].r += z_dmrs_rx[l * 12 + n].r / quarter_nb_symbols;
|
||||
H[n].i += z_dmrs_rx[l * 12 + n].i / quarter_nb_symbols;
|
||||
y_n[n].r += z_rx[l * 12 + n].r / quarter_nb_symbols;
|
||||
y_n[n].i += z_rx[l * 12 + n].i / quarter_nb_symbols;
|
||||
H[r].r += z_dmrs_rx[r][l * 12 + n].r / half_nb_symbols / 12;
|
||||
H[r].i += z_dmrs_rx[r][l * 12 + n].i / half_nb_symbols / 12;
|
||||
y[r].r += z_rx[r][l * 12 + n].r / half_nb_symbols / 12;
|
||||
y[r].i += z_rx[r][l * 12 + n].i / half_nb_symbols / 12;
|
||||
}
|
||||
} else {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
H1[n].r += z_dmrs_rx[l * 12 + n].r / quarter_nb_symbols;
|
||||
H1[n].i += z_dmrs_rx[l * 12 + n].i / quarter_nb_symbols;
|
||||
y1_n[n].r += z_rx[l * 12 + n].r / quarter_nb_symbols;
|
||||
y1_n[n].i += z_rx[l * 12 + n].i / quarter_nb_symbols;
|
||||
} else { // with Frequency-hopping
|
||||
if (l < pucch_pdu->nr_of_symbols / 4) {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
H[r].r += z_dmrs_rx[r][l * 12 + n].r / half_nb_symbols / 12;
|
||||
H[r].i += z_dmrs_rx[r][l * 12 + n].i / half_nb_symbols / 12;
|
||||
y[r].r += z_rx[r][l * 12 + n].r / half_nb_symbols / 12;
|
||||
y[r].i += z_rx[r][l * 12 + n].i / half_nb_symbols / 12;
|
||||
}
|
||||
} else {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
H1[r].r += z_dmrs_rx[r][l * 12 + n].r / half_nb_symbols / 12;
|
||||
H1[r].i += z_dmrs_rx[r][l * 12 + n].i / half_nb_symbols / 12;
|
||||
y1[r].r += z_rx[r][l * 12 + n].r / half_nb_symbols / 12;
|
||||
y1[r].i += z_rx[r][l * 12 + n].i / half_nb_symbols / 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// mrc combining to obtain z_re and z_im
|
||||
cd_t d = {0};
|
||||
if (intraSlotFrequencyHopping == false) {
|
||||
// complex-valued symbol d_re, d_im containing complex-valued symbol d(0):
|
||||
for (int n = 0; n < 12; n++) {
|
||||
d.r += H[n].r * y_n[n].r + H[n].i * y_n[n].i;
|
||||
d.i += H[n].r * y_n[n].i - H[n].i * y_n[n].r;
|
||||
}
|
||||
} else {
|
||||
for (int n = 0; n < 12; n++) {
|
||||
d.r += H[n].r * y_n[n].r + H[n].i * y_n[n].i;
|
||||
d.i += H[n].r * y_n[n].i - H[n].i * y_n[n].r;
|
||||
d.r += H[n].r * y1_n[n].r + H[n].i * y1_n[n].i;
|
||||
d.i += H[n].r * y1_n[n].i - H[n].i * y1_n[n].r;
|
||||
cd_t dp1 = {0}, dm1 = {0}, d0 = {0}, d1 = {0}, d2 = {0}, d3 = {0};
|
||||
double dp1mag = 0, dm1mag = 0, d0mag = 0, d1mag = 0, d2mag = 0, d3mag = 0;
|
||||
// complex-valued symbol d_re, d_im containing complex-valued symbol d(0):
|
||||
for (int r = 0; r < n_rx; r++) {
|
||||
if (pucch_pdu->bit_len_harq == 1) // BPSK
|
||||
{
|
||||
dp1.r = H[r].r + inv_sqrt2 * (y[r].r + y[r].i);
|
||||
dp1.i = H[r].i + inv_sqrt2 * (y[r].i - y[r].r);
|
||||
dm1.r = H[r].r + inv_sqrt2 * (-y[r].r - y[r].i);
|
||||
dm1.i = H[r].i + inv_sqrt2 * (y[r].r - y[r].i);
|
||||
dp1mag += squaredMod(dp1);
|
||||
dm1mag += squaredMod(dm1);
|
||||
|
||||
LOG_D(PHY,
|
||||
"r %d y : (%f,%f) H (%f,%f) dp1 : (%f,%f) : %f dm1 : (%f,%f) : %f\n",
|
||||
r,
|
||||
y[r].r,
|
||||
y[r].i,
|
||||
H[r].r,
|
||||
H[r].i,
|
||||
dp1.r,
|
||||
dp1.i,
|
||||
dp1mag,
|
||||
dm1.r,
|
||||
dm1.i,
|
||||
dm1mag);
|
||||
|
||||
if (intraSlotFrequencyHopping == true) {
|
||||
dp1.r = H1[r].r + inv_sqrt2 * (y1[r].r + y1[r].i);
|
||||
dp1.i = H1[r].i + inv_sqrt2 * (y1[r].i - y1[r].r);
|
||||
dm1.r = H1[r].r + inv_sqrt2 * (-y1[r].r - y1[r].i);
|
||||
dm1.i = H1[r].i + inv_sqrt2 * (y1[r].r - y1[r].i);
|
||||
dp1mag += squaredMod(dp1);
|
||||
dm1mag += squaredMod(dm1);
|
||||
}
|
||||
if (r == n_rx - 1) {
|
||||
if (dp1mag > dm1mag) {
|
||||
uci_pdu->harq.harq_list[0].harq_value = 1;
|
||||
xrtmag_dBtimes10 = 10 * (int)dB_fixed64(dp1mag / (12 * pucch_pdu->nr_of_symbols));
|
||||
} else {
|
||||
//*payload = 1;
|
||||
uci_pdu->harq.harq_list[0].harq_value = 0;
|
||||
xrtmag_dBtimes10 = 10 * (int)dB_fixed64(dm1mag / (12 * pucch_pdu->nr_of_symbols));
|
||||
}
|
||||
}
|
||||
} else if (pucch_pdu->bit_len_harq == 2) // QPSK
|
||||
{
|
||||
// d0 = H + (1 - j)*y
|
||||
d0.r = H[r].r + inv_sqrt2 * (y[r].r + y[r].i);
|
||||
d0.i = H[r].i + inv_sqrt2 * (y[r].i - y[r].r);
|
||||
d0mag += squaredMod(d0);
|
||||
|
||||
// d1 = H + (-1 - j)*y
|
||||
d1.r = H[r].r + inv_sqrt2 * (-y[r].r + y[r].i);
|
||||
d1.i = H[r].i + inv_sqrt2 * (-y[r].r - y[r].i);
|
||||
d1mag += squaredMod(d1);
|
||||
|
||||
// d2 = H + (1 + j)*y
|
||||
d2.r = H[r].r + inv_sqrt2 * (y[r].r - y[r].i);
|
||||
d2.i = H[r].i + inv_sqrt2 * (y[r].i + y[r].r);
|
||||
d2mag += squaredMod(d2);
|
||||
|
||||
// d3 = H + (-1 + j)*y
|
||||
d3.r = H[r].r + inv_sqrt2 * (-y[r].r - y[r].i);
|
||||
d3.i = H[r].i + inv_sqrt2 * (y[r].r - y[r].i);
|
||||
d3mag += squaredMod(d3);
|
||||
|
||||
// with frequency hopping
|
||||
if (intraSlotFrequencyHopping == true) {
|
||||
d0.r = H1[r].r + inv_sqrt2 * (y1[r].r + y1[r].i);
|
||||
d0.i = H1[r].i + inv_sqrt2 * (y1[r].i - y1[r].r);
|
||||
d0mag += squaredMod(d0);
|
||||
|
||||
d1.r = H1[r].r + inv_sqrt2 * (-y1[r].r + y1[r].i);
|
||||
d1.i = H1[r].i + inv_sqrt2 * (-y1[r].r - y1[r].i);
|
||||
d1mag += squaredMod(d1);
|
||||
|
||||
d2.r = H1[r].r + inv_sqrt2 * (y1[r].r - y1[r].i);
|
||||
d2.i = H1[r].i + inv_sqrt2 * (y1[r].i + y1[r].r);
|
||||
d2mag += squaredMod(d2);
|
||||
|
||||
d3.r = H1[r].r + inv_sqrt2 * (-y1[r].r - y1[r].i);
|
||||
d3.i = H1[r].i + inv_sqrt2 * (y1[r].r - y1[r].i);
|
||||
d3mag += squaredMod(d3);
|
||||
}
|
||||
|
||||
LOG_D(PHY,
|
||||
"r %d y : (%f,%f) H (%f,%f) d0 : (%f,%f) : %f d1 : (%f,%f) : %f d2 : (%f,%f) : %f d3 : (%f,%f) : %f\n",
|
||||
r,
|
||||
y[r].r,
|
||||
y[r].i,
|
||||
H[r].r,
|
||||
H[r].i,
|
||||
d0.r,
|
||||
d0.i,
|
||||
d0mag,
|
||||
d1.r,
|
||||
d1.i,
|
||||
d1mag,
|
||||
d2.r,
|
||||
d2.i,
|
||||
d2mag,
|
||||
d3.r,
|
||||
d3.i,
|
||||
d3mag);
|
||||
|
||||
if (r == n_rx - 1) {
|
||||
if (d0mag >= d1mag && d0mag >= d2mag && d0mag >= d3mag) {
|
||||
uci_pdu->harq.harq_list[0].harq_value = 1;
|
||||
uci_pdu->harq.harq_list[1].harq_value = 1;
|
||||
xrtmag_dBtimes10 = 10 * (int)dB_fixed64(d0mag / (12 * pucch_pdu->nr_of_symbols));
|
||||
} else if (d1mag >= d0mag && d1mag >= d2mag && d1mag >= d3mag) {
|
||||
uci_pdu->harq.harq_list[0].harq_value = 1;
|
||||
uci_pdu->harq.harq_list[1].harq_value = 0;
|
||||
xrtmag_dBtimes10 = 10 * (int)dB_fixed64(d1mag / (12 * pucch_pdu->nr_of_symbols));
|
||||
} else if (d2mag >= d0mag && d2mag >= d1mag && d2mag >= d3mag) {
|
||||
uci_pdu->harq.harq_list[0].harq_value = 0;
|
||||
uci_pdu->harq.harq_list[1].harq_value = 1;
|
||||
xrtmag_dBtimes10 = 10 * (int)dB_fixed64(d2mag / (12 * pucch_pdu->nr_of_symbols));
|
||||
} else {
|
||||
uci_pdu->harq.harq_list[0].harq_value = 0;
|
||||
uci_pdu->harq.harq_list[1].harq_value = 0;
|
||||
xrtmag_dBtimes10 = 10 * (int)dB_fixed64(d3mag / (12 * pucch_pdu->nr_of_symbols));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Decoding QPSK or BPSK symbols to obtain payload bits
|
||||
if (nr_bit == 1) {
|
||||
if ((d.r + d.i) > 0) {
|
||||
*payload = 0;
|
||||
} else {
|
||||
*payload = 1;
|
||||
|
||||
bool no_conf = false;
|
||||
if (pucch_pdu->bit_len_harq > 0 || pucch_pdu->sr_flag > 0) {
|
||||
if (/*xrtmag_dBtimes10 < (30+xrtmag_next_dBtimes10) ||*/ SNRtimes10 <= gNB->pucch0_thres) {
|
||||
no_conf = true;
|
||||
LOG_D(PHY, "%d.%d PUCCH F1 bad confidence: %d threshold, %d,\n", frame, slot, gNB->pucch0_thres, SNRtimes10);
|
||||
}
|
||||
} else if (nr_bit == 2) {
|
||||
if ((d.r > 0) && (d.i > 0)) {
|
||||
*payload = 0;
|
||||
} else if ((d.r < 0) && (d.i > 0)) {
|
||||
*payload = 1;
|
||||
} else if ((d.r > 0) && (d.i < 0)) {
|
||||
*payload = 2;
|
||||
}
|
||||
gNB->bad_pucch += no_conf;
|
||||
// first bit of bitmap for sr presence and second bit for acknack presence
|
||||
uci_pdu->pduBitmap = pucch_pdu->sr_flag | ((pucch_pdu->bit_len_harq > 0) << 1);
|
||||
uci_pdu->pucch_format = 1; // format 1
|
||||
uci_pdu->rnti = pucch_pdu->rnti;
|
||||
uci_pdu->ul_cqi = cqi;
|
||||
uci_pdu->timing_advance = 0xffff; // currently not valid
|
||||
uci_pdu->rssi = 1280 - (10 * dB_fixed(32767 * 32767) - dB_fixed_times10(signal_energy_ant0));
|
||||
|
||||
if (pucch_pdu->bit_len_harq == 0) {
|
||||
uci_pdu->sr.sr_confidence_level = SNRtimes10 < gNB->pucch0_thres;
|
||||
uci_stats->pucch1_sr_trials++;
|
||||
if (xrtmag_dBtimes10 >= (10 * max_n0 /*+100*/)) {
|
||||
uci_pdu->sr.sr_indication = 1;
|
||||
uci_stats->pucch1_positive_SR++;
|
||||
LOG_D(PHY, "PUCCH1 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch1_positive_SR);
|
||||
} else {
|
||||
*payload = 3;
|
||||
uci_pdu->sr.sr_indication = 0;
|
||||
}
|
||||
} else if (pucch_pdu->bit_len_harq == 1) {
|
||||
uci_pdu->harq.num_harq = 1;
|
||||
uci_pdu->harq.harq_confidence_level = no_conf;
|
||||
LOG_D(PHY,
|
||||
"[PUCCH F1] %d.%d HARQ %s with confidence level %s"
|
||||
" xrtmag_dBtimes10 %d pucch_power_dBtimes10 %d n0 %d "
|
||||
"pucch0_thres %d, "
|
||||
"cqi %d, SNRtimes10 %d, energy %f\n",
|
||||
frame,
|
||||
slot,
|
||||
uci_pdu->harq.harq_list[0].harq_value == 0 ? "ACK" : "NACK",
|
||||
uci_pdu->harq.harq_confidence_level == 0 ? "good" : "bad",
|
||||
xrtmag_dBtimes10,
|
||||
pucch_power_dBtimes10,
|
||||
max_n0,
|
||||
gNB->pucch0_thres, // using same pucch threshold for both pucch 0 and pucch 1.
|
||||
cqi,
|
||||
SNRtimes10,
|
||||
10 * log10((double)signal_energy_ant0));
|
||||
|
||||
if (pucch_pdu->sr_flag == 1) {
|
||||
uci_pdu->sr.sr_indication = 0; // Upper layers determine if SR when the PUCCH resource is an SR resource or not
|
||||
uci_pdu->sr.sr_confidence_level = no_conf;
|
||||
if (uci_pdu->sr.sr_indication == 1 && uci_pdu->sr.sr_confidence_level == 0) {
|
||||
uci_stats->pucch1_positive_SR++;
|
||||
LOG_D(PHY, "PUCCH F1 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch1_positive_SR);
|
||||
}
|
||||
}
|
||||
uci_stats->pucch11_trials++;
|
||||
} else {
|
||||
uci_pdu->harq.num_harq = 2;
|
||||
uci_pdu->harq.harq_confidence_level = no_conf;
|
||||
LOG_D(PHY,
|
||||
"[PUCCH F1] %d.%d HARQ values (%s, %s) with confidence level %s, xrtmag_dBtimes10 %d pucch_power_dBtimes10 %d n0 %d "
|
||||
"pucch0_thres %d, cqi %d, SNRtimes10 %d\n",
|
||||
frame,
|
||||
slot,
|
||||
uci_pdu->harq.harq_list[1].harq_value == 0 ? "ACK" : "NACK",
|
||||
uci_pdu->harq.harq_list[0].harq_value == 0 ? "ACK" : "NACK",
|
||||
uci_pdu->harq.harq_confidence_level == 0 ? "good" : "bad",
|
||||
xrtmag_dBtimes10,
|
||||
pucch_power_dBtimes10,
|
||||
max_n0,
|
||||
gNB->pucch0_thres, // using same pucch threshold for both pucch 0 and pucch 1.
|
||||
cqi,
|
||||
SNRtimes10);
|
||||
if (pucch_pdu->sr_flag == 1) {
|
||||
uci_pdu->sr.sr_indication = 0; // Upper layers determine if SR when the PUCCH resource is an SR resource or not
|
||||
uci_pdu->sr.sr_confidence_level = no_conf;
|
||||
if (uci_pdu->sr.sr_indication == 1 && uci_pdu->sr.sr_confidence_level == 0) {
|
||||
uci_stats->pucch1_positive_SR++;
|
||||
LOG_D(PHY, "PUCCH F1 got positive SR. Cumulative number of positive SR %d\n", uci_stats->pucch1_positive_SR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1124,7 +1348,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
|
||||
for (int aa = 0; aa < Prx; aa++)
|
||||
mult_complex_vectors(rp[aa][symb], delay_table, rp[aa][symb], nb_re_pucch, 8);
|
||||
}
|
||||
|
||||
|
||||
// extract again DMRS, and signal, after delay compensation
|
||||
for (int aa = 0; aa < Prx; aa++) {
|
||||
c16_t *r_ext_p = r_ext[aa][symb];
|
||||
@@ -1194,7 +1418,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
|
||||
|
||||
uint64_t decodedPayload[nb_symbols];
|
||||
memset(decodedPayload, 0, sizeof(decodedPayload));
|
||||
int8_t corr_dB;
|
||||
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)
|
||||
@@ -1394,3 +1618,68 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
|
||||
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;
|
||||
|
||||
@@ -155,6 +155,7 @@ 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' */
|
||||
@@ -299,6 +300,7 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case 'i':
|
||||
nrofSymbols = (uint8_t)atoi(optarg);
|
||||
nrofSymbols_set = 1;
|
||||
break;
|
||||
case 'I':
|
||||
startingSymbolIndex = (uint8_t)atoi(optarg);
|
||||
@@ -311,6 +313,8 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case 'P':
|
||||
format = atoi(optarg);
|
||||
if ((format == 1 || format == 3) && nrofSymbols_set == 0)
|
||||
nrofSymbols = 14;
|
||||
break;
|
||||
case 'm':
|
||||
m0 = atoi(optarg);
|
||||
@@ -324,6 +328,7 @@ int main(int argc, char **argv)
|
||||
case 'B':
|
||||
actual_payload = atoi(optarg);
|
||||
random_payload = false;
|
||||
printf("Setting payload to %llx\n", (unsigned long long)actual_payload);
|
||||
break;
|
||||
case 'T':
|
||||
// nacktoack_flag=(uint8_t)atoi(optarg);
|
||||
@@ -490,7 +495,7 @@ int main(int argc, char **argv)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fapi_nr_ul_config_pucch_pdu pucch_tx_pdu;
|
||||
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;
|
||||
@@ -505,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;
|
||||
@@ -628,12 +648,28 @@ int main(int argc, char **argv)
|
||||
|
||||
// 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;
|
||||
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
|
||||
}
|
||||
|
||||
if (format == 1) {
|
||||
for (int s = 0; s < frame_parms->symbols_per_slot; s++) {
|
||||
if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols / 2))
|
||||
for (int rb = 0; rb < N_RB; rb++) {
|
||||
int rb2 = rb + startingPRB;
|
||||
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
|
||||
}
|
||||
else if (s >= (startingSymbolIndex + nrofSymbols / 2) && s < startingSymbolIndex + nrofSymbols)
|
||||
for (int rb = 0; rb < N_RB; rb++) {
|
||||
int rb2 = rb + startingPRB_intraSlotHopping;
|
||||
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int s = 0; s < frame_parms->symbols_per_slot; s++) {
|
||||
if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols))
|
||||
for (int rb = 0; rb < N_RB; rb++) {
|
||||
int rb2 = rb + startingPRB;
|
||||
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// noise measurement (all PRBs)
|
||||
@@ -695,24 +731,44 @@ int main(int argc, char **argv)
|
||||
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);
|
||||
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 == 2) {
|
||||
nfapi_nr_uci_pucch_pdu_format_2_3_4_t uci_pdu = {0};
|
||||
nfapi_nr_pucch_pdu_t pucch_pdu = {0};
|
||||
|
||||
Reference in New Issue
Block a user