Commit 584ace46 authored by Raymond Knopp's avatar Raymond Knopp Committed by francescomani

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.
parent 2cb96ea5
...@@ -245,20 +245,13 @@ int get_nr_prach_duration(uint8_t prach_format); ...@@ -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 free_nr_prach_entry(prach_list_t *, prach_item_t *);
void nr_decode_pucch1(c16_t **rxdataF, void nr_decode_pucch1(PHY_VARS_gNB *gNB,
pucch_GroupHopping_t pucch_GroupHopping, c16_t **rxdataF,
uint32_t n_id, // hoppingID higher layer parameter int frame,
uint64_t *payload, int slot,
NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu,
int16_t amp, nfapi_nr_pucch_pdu_t *pucch_pdu);
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_pucch2(PHY_VARS_gNB *gNB, void nr_decode_pucch2(PHY_VARS_gNB *gNB,
c16_t **rxdataF, c16_t **rxdataF,
......
This diff is collapsed.
...@@ -190,7 +190,7 @@ void nr_generate_pucch1(c16_t **txdataF, ...@@ -190,7 +190,7 @@ void nr_generate_pucch1(c16_t **txdataF,
d = qpskSymbols[tmp]; d = qpskSymbols[tmp];
} }
#ifdef DEBUG_NR_PUCCH_TX #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 #endif
/* /*
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
...@@ -273,13 +273,14 @@ void nr_generate_pucch1(c16_t **txdataF, ...@@ -273,13 +273,14 @@ void nr_generate_pucch1(c16_t **txdataF,
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
printf( printf(
"\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) " "\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, u,
v, v,
alpha, alpha,
n, n,
r_u_v_alpha_delta[n].r, r_u_v_alpha_delta[n].r,
r_u_v_alpha_delta[n].i, r_u_v_alpha_delta[n].i,
d.r,d.i,
n, n,
y_n[n].r, y_n[n].r,
y_n[n].i); y_n[n].i);
......
...@@ -82,6 +82,9 @@ typedef struct { ...@@ -82,6 +82,9 @@ typedef struct {
int pucch01_DTX; int pucch01_DTX;
int pucch02_trials; int pucch02_trials;
int pucch02_DTX; int pucch02_DTX;
int pucch1_sr_trials;
int pucch1_positive_SR;
int pucch11_trials;
int pucch2_trials; int pucch2_trials;
int pucch2_DTX; int pucch2_DTX;
} NR_gNB_UCI_STATS_t; } NR_gNB_UCI_STATS_t;
......
...@@ -155,6 +155,7 @@ int main(int argc, char **argv) ...@@ -155,6 +155,7 @@ int main(int argc, char **argv)
logInit(); logInit();
int c; 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) { 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 */ /* 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' */ /* 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) ...@@ -299,6 +300,7 @@ int main(int argc, char **argv)
break; break;
case 'i': case 'i':
nrofSymbols = (uint8_t)atoi(optarg); nrofSymbols = (uint8_t)atoi(optarg);
nrofSymbols_set = 1;
break; break;
case 'I': case 'I':
startingSymbolIndex = (uint8_t)atoi(optarg); startingSymbolIndex = (uint8_t)atoi(optarg);
...@@ -311,6 +313,8 @@ int main(int argc, char **argv) ...@@ -311,6 +313,8 @@ int main(int argc, char **argv)
break; break;
case 'P': case 'P':
format = atoi(optarg); format = atoi(optarg);
if ((format == 1 || format == 3) && nrofSymbols_set == 0)
nrofSymbols = 14;
break; break;
case 'm': case 'm':
m0 = atoi(optarg); m0 = atoi(optarg);
...@@ -324,6 +328,7 @@ int main(int argc, char **argv) ...@@ -324,6 +328,7 @@ int main(int argc, char **argv)
case 'B': case 'B':
actual_payload = atoi(optarg); actual_payload = atoi(optarg);
random_payload = false; random_payload = false;
printf("Setting payload to %llx\n", (unsigned long long)actual_payload);
break; break;
case 'T': case 'T':
// nacktoack_flag=(uint8_t)atoi(optarg); // nacktoack_flag=(uint8_t)atoi(optarg);
...@@ -490,7 +495,7 @@ int main(int argc, char **argv) ...@@ -490,7 +495,7 @@ int main(int argc, char **argv)
exit(-1); exit(-1);
} }
fapi_nr_ul_config_pucch_pdu pucch_tx_pdu; fapi_nr_ul_config_pucch_pdu pucch_tx_pdu = {0};
if (format == 0) { if (format == 0) {
pucch_tx_pdu.format_type = 0; pucch_tx_pdu.format_type = 0;
pucch_tx_pdu.nr_of_symbols = nrofSymbols; pucch_tx_pdu.nr_of_symbols = nrofSymbols;
...@@ -505,7 +510,22 @@ int main(int argc, char **argv) ...@@ -505,7 +510,22 @@ int main(int argc, char **argv)
pucch_tx_pdu.initial_cyclic_shift = 0; pucch_tx_pdu.initial_cyclic_shift = 0;
pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping; 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.format_type = 2;
pucch_tx_pdu.rnti = 0x1234; pucch_tx_pdu.rnti = 0x1234;
pucch_tx_pdu.n_bit = nr_bit; pucch_tx_pdu.n_bit = nr_bit;
...@@ -628,12 +648,28 @@ int main(int argc, char **argv) ...@@ -628,12 +648,28 @@ int main(int argc, char **argv)
// set UL mask for pucch allocation // set UL mask for pucch allocation
uint32_t rb_mask_ul[14][9] = {0}; 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)) if (format == 1) {
for (int rb = 0; rb < N_RB; rb++) { for (int s = 0; s < frame_parms->symbols_per_slot; s++) {
int rb2 = rb + startingPRB; if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols / 2))
rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31)); 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) // noise measurement (all PRBs)
...@@ -695,24 +731,44 @@ int main(int argc, char **argv) ...@@ -695,24 +731,44 @@ int main(int argc, char **argv)
ack_nack_errors++; ack_nack_errors++;
} }
} else if (format == 1) { } else if (format == 1) {
nr_decode_pucch1((c16_t **)rxdataF, nfapi_nr_uci_pucch_pdu_format_0_1_t uci_pdu;
PUCCH_GroupHopping, nfapi_nr_pucch_pdu_t pucch_pdu;
hopping_id, gNB->phy_stats[0].rnti = 0x1234;
&(payload_received), pucch_pdu.rnti = 0x1234;
frame_parms, pucch_pdu.subcarrier_spacing = 1;
amp, pucch_pdu.group_hop_flag = PUCCH_GroupHopping & 1;
nr_slot_tx, pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping >> 1) & 1;
m0, pucch_pdu.bit_len_harq = nr_bit;
nrofSymbols, pucch_pdu.bit_len_csi_part1 = 0;
startingSymbolIndex, pucch_pdu.bit_len_csi_part2 = 0;
startingPRB, pucch_pdu.sr_flag = sr_flag;
startingPRB_intraSlotHopping, pucch_pdu.nr_of_symbols = nrofSymbols;
timeDomainOCC, pucch_pdu.hopping_id = hopping_id;
nr_bit); pucch_pdu.initial_cyclic_shift = m0;
if (nr_bit == 1) pucch_pdu.start_symbol_index = startingSymbolIndex;
ack_nack_errors += ((actual_payload ^ payload_received) & 1); pucch_pdu.prb_start = startingPRB;
else pucch_pdu.prb_size = 1;
ack_nack_errors += ((actual_payload ^ payload_received) & 1) + (((actual_payload ^ payload_received) & 2) >> 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) { } else if (format == 2) {
nfapi_nr_uci_pucch_pdu_format_2_3_4_t uci_pdu = {0}; nfapi_nr_uci_pucch_pdu_format_2_3_4_t uci_pdu = {0};
nfapi_nr_pucch_pdu_t pucch_pdu = {0}; nfapi_nr_pucch_pdu_t pucch_pdu = {0};
......
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