Commit a20d229b authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/pucch2-delay-compensation' into integration_2025_w03 (!3034)

Delay compensation for PUCCH2

- Implementation of delay compensation for PUCCH2, which minimizes for
  exampe logs "reported RSRP index XXX invalid"
- Adding a test to the CI to perform the delay compensation in PUCCH2
- Refactor code to use c16_t data type in PUCCH decoder
parents 284a0ede 48226d10
......@@ -318,7 +318,8 @@
(Test25: Format 2 11-bit 2/273 PRB),
(Test26: Format 2 12-bit 8/273 PRB),
(Test27: Format 2 19-bit 8/273 PRB),
(Test28: Format 2 64-bit 16/273 PRB)</desc>
(Test28: Format 2 64-bit 16/273 PRB),
(Test29: Format 2 64-bit 16/273 PRB Delay 2us)</desc>
<main_exec>nr_pucchsim</main_exec>
<main_exec_args>-R 106 -i 1 -P 0 -b 1 -s-2 -n1000
-R 106 -i 1 -P 0 -b 2 -s-2 -n1000
......@@ -347,8 +348,9 @@
-R 273 -z8 -i 1 -P 2 -b 11 -s6 -n1000
-R 273 -z8 -i 1 -P 2 -q8 -b 12 -s-3 -n1000
-R 273 -z8 -i 1 -P 2 -q8 -b 19 -s-3 -n1000
-R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -n1000</main_exec_args>
<tags>test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13 test14 test15 test16 test17 test18 test19 test20 test21 test22 test23 test24 test25 test26 test27 test28</tags>
-R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -n1000
-R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -d 2 -n1000</main_exec_args>
<tags>test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13 test14 test15 test16 test17 test18 test19 test20 test21 test22 test23 test24 test25 test26 test27 test28 test29</tags>
<search_expr_true>PUCCH test OK</search_expr_true>
<search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
<nruns>3</nruns>
......
......@@ -651,6 +651,10 @@ void log_dump(int component,
wbuf=malloc((buffsize * 10) + 64 + MAX_LOG_TOTAL);
break;
case LOG_DUMP_C16:
wbuf = malloc((buffsize * 10) + 64 + MAX_LOG_TOTAL);
break;
case LOG_DUMP_CHAR:
default:
wbuf=malloc((buffsize * 3 ) + 64 + MAX_LOG_TOTAL);
......@@ -669,6 +673,21 @@ void log_dump(int component,
pos = pos + sprintf(wbuf+pos,"%04.4lf ", (double)((double *)buffer)[i]);
break;
case LOG_DUMP_I16: {
int16_t *tmp = ((int16_t *)buffer) + i;
pos = pos + sprintf(wbuf + pos, "%d, ", *tmp);
} break;
case LOG_DUMP_C16: {
int16_t *tmp = ((int16_t *)buffer) + i * 2;
pos = pos + sprintf(wbuf + pos, "(%d,%d), ", *tmp, *(tmp + 1));
} break;
case LOG_DUMP_C32: {
int32_t *tmp = ((int32_t *)buffer) + i * 2;
pos = pos + sprintf(wbuf + pos, "(%d,%d), ", *tmp, *(tmp + 1));
} break;
case LOG_DUMP_CHAR:
default:
pos = pos + sprintf(wbuf+pos,"%02x ", (unsigned char)((unsigned char *)buffer)[i]);
......
......@@ -335,6 +335,9 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
* @{*/
#define LOG_DUMP_CHAR 0
#define LOG_DUMP_DOUBLE 1
#define LOG_DUMP_I16 2
#define LOG_DUMP_C16 3
#define LOG_DUMP_C32 4
// debugging macros
#define LOG_F LOG_I /* because LOG_F was originaly to dump a message or buffer but is also used as a regular level...., to dump use LOG_DUMPMSG */
......
......@@ -138,6 +138,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;
init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table);
init_delay_table(128, MAX_DELAY_COMP, 128, fp->delay_table128);
gNB->bad_pucch = 0;
if (gNB->TX_AMP == 0)
......
This diff is collapsed.
......@@ -217,6 +217,8 @@ struct NR_DL_FRAME_PARMS {
c16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16)));
/// Table used to apply the delay compensation in DL/UL
c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE];
/// Table used to apply the delay compensation in PUCCH2
c16_t delay_table128[2 * MAX_DELAY_COMP + 1][128];
/// SRS configuration from TS 38.331 RRC
SRS_NR srs_nr;
/// Power used by SSB in order to estimate signal strength and path loss
......
......@@ -25,6 +25,8 @@
#define USE_128BIT
#endif
#define PEAK_DETECT_THRESHOLD 15
int16_t saturating_sub(int16_t a, int16_t b)
{
int32_t result = (int32_t)a - (int32_t)b;
......@@ -367,20 +369,28 @@ void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates
int max_val = delay->delay_max_val;
const int sync_pos = 0;
uint64_t mean_val = 0;
for (int i = 0; i < ofdm_symbol_size; i++) {
int temp = c16amp2(ch_estimates_time[i]) >> 1;
mean_val += temp;
if (temp > max_val) {
max_pos = i;
max_val = temp;
}
}
mean_val /= ofdm_symbol_size;
if (max_pos > ofdm_symbol_size / 2)
max_pos = max_pos - ofdm_symbol_size;
delay->delay_max_pos = max_pos;
delay->delay_max_val = max_val;
delay->est_delay = max_pos - sync_pos;
// The peak in general is quite clear. It only gives a small peak when the noise is high, generally obtaining an incorrect
// estimated delay, and causing the delay compensation to worsen the result instead of improving it. After analyzing several
// peaks, and doing many tests, a PEAK_DETECT_THRESHOLD = 15 is an adequate value, to apply delay compensation only when there is
// clearly a peak
delay->est_delay = mean_val > 0 && max_val / mean_val > PEAK_DETECT_THRESHOLD ? max_pos - sync_pos : 0;
}
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb)
......
......@@ -144,6 +144,7 @@ int main(int argc, char **argv)
int sr_flag = 0;
int pucch_DTX_thres = 0;
cpuf = get_cpu_freq_GHz();
bool print_perf = false;
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
exit_fun("[NR_PUCCHSIM] Error, configuration module init failed\n");
......@@ -153,8 +154,7 @@ int main(int argc, char **argv)
logInit();
int c;
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:")) != -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 */
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
if (c == 1 || c == '-' || c == 'O')
......@@ -349,6 +349,10 @@ int main(int argc, char **argv)
//nacktoack_flag=(uint8_t)atoi(optarg);
target_error_rate=0.001;
break;
case 'C':
print_perf = 1;
cpu_meas_enabled = 1;
break;
default:
case 'h':
printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", argv[0]);
......@@ -381,6 +385,7 @@ int main(int argc, char **argv)
printf("-x Transmission mode (1,2,6 for the moment)\n");
printf("-y Number of TX antennas used in eNB\n");
printf("-z Number of RX antennas used in UE\n");
printf("-C print CPU cost\n");
exit (-1);
break;
}
......@@ -406,8 +411,8 @@ int main(int argc, char **argv)
if ((format < 2) && (actual_payload == 4)) do_DTX=1;
if (random_payload) {
srand(time(NULL)); // Initialization, should only be called once.
actual_payload = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX.
double tmp = uniformrandom();
memcpy(&actual_payload, &tmp, sizeof(actual_payload));
}
actual_payload &= nr_bit < 64 ? (1UL << nr_bit) - 1: 0xffffffffffffffff;
......@@ -638,6 +643,7 @@ int main(int argc, char **argv)
// noise measurement (all PRBs)
gNB_I0_measurements(gNB, nr_slot_tx, 0, gNB->frame_parms.symbols_per_slot, rb_mask_ul);
start_meas(&gNB->phy_proc_rx);
if (n_trials==1) printf("noise rxlev %d (%d dB), rxlev pucch %d dB sigma2 %f dB, SNR %f, TX %f, I0 (pucch) %d, I0 (avg) %d\n",rxlev,dB_fixed(rxlev),dB_fixed(rxlev_pucch),sigma2_dB,SNR,10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/12),gNB->measurements.n0_subband_power_tot_dB[startingPRB],gNB->measurements.n0_subband_power_avg_dB);
if(format==0){
......@@ -731,10 +737,21 @@ int main(int argc, char **argv)
free(uci_pdu.csi_part1.csi_part1_payload);
}
stop_meas(&gNB->phy_proc_rx);
n_errors=((actual_payload^payload_received)&1)+(((actual_payload^payload_received)&2)>>1)+(((actual_payload^payload_received)&4)>>2)+n_errors;
}
if (sr_flag == 1)
printf("SR: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,sr_errors);
if (print_perf) {
time_stats_t *ts = &gNB->phy_proc_rx;
printf("cpu time for pucch format %d: per block %.2f us; nb blocks %d, max time %.2f;\n",
format,
ts->diff / ts->trials / cpuf / 1000.0,
ts->trials,
ts->max / cpuf / 1000.0);
reset_meas(ts);
}
if(nr_bit > 0)
printf("ACK/NACK: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors);
if((float)(ack_nack_errors+sr_errors)/(float)(n_trials)<=target_error_rate){
......
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