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
This commit is contained in:
@@ -318,7 +318,8 @@
|
|||||||
(Test25: Format 2 11-bit 2/273 PRB),
|
(Test25: Format 2 11-bit 2/273 PRB),
|
||||||
(Test26: Format 2 12-bit 8/273 PRB),
|
(Test26: Format 2 12-bit 8/273 PRB),
|
||||||
(Test27: Format 2 19-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>nr_pucchsim</main_exec>
|
||||||
<main_exec_args>-R 106 -i 1 -P 0 -b 1 -s-2 -n1000
|
<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
|
-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 -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 12 -s-3 -n1000
|
||||||
-R 273 -z8 -i 1 -P 2 -q8 -b 19 -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>
|
-R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -n1000
|
||||||
<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 -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_true>PUCCH test OK</search_expr_true>
|
||||||
<search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
|
<search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
|
||||||
<nruns>3</nruns>
|
<nruns>3</nruns>
|
||||||
|
|||||||
@@ -651,6 +651,10 @@ void log_dump(int component,
|
|||||||
wbuf=malloc((buffsize * 10) + 64 + MAX_LOG_TOTAL);
|
wbuf=malloc((buffsize * 10) + 64 + MAX_LOG_TOTAL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LOG_DUMP_C16:
|
||||||
|
wbuf = malloc((buffsize * 10) + 64 + MAX_LOG_TOTAL);
|
||||||
|
break;
|
||||||
|
|
||||||
case LOG_DUMP_CHAR:
|
case LOG_DUMP_CHAR:
|
||||||
default:
|
default:
|
||||||
wbuf=malloc((buffsize * 3 ) + 64 + MAX_LOG_TOTAL);
|
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]);
|
pos = pos + sprintf(wbuf+pos,"%04.4lf ", (double)((double *)buffer)[i]);
|
||||||
break;
|
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:
|
case LOG_DUMP_CHAR:
|
||||||
default:
|
default:
|
||||||
pos = pos + sprintf(wbuf+pos,"%02x ", (unsigned char)((unsigned char *)buffer)[i]);
|
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_CHAR 0
|
||||||
#define LOG_DUMP_DOUBLE 1
|
#define LOG_DUMP_DOUBLE 1
|
||||||
|
#define LOG_DUMP_I16 2
|
||||||
|
#define LOG_DUMP_C16 3
|
||||||
|
#define LOG_DUMP_C32 4
|
||||||
// debugging macros
|
// 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 */
|
#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;
|
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(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;
|
gNB->bad_pucch = 0;
|
||||||
if (gNB->TX_AMP == 0)
|
if (gNB->TX_AMP == 0)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -217,6 +217,8 @@ struct NR_DL_FRAME_PARMS {
|
|||||||
c16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16)));
|
c16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16)));
|
||||||
/// Table used to apply the delay compensation in DL/UL
|
/// Table used to apply the delay compensation in DL/UL
|
||||||
c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE];
|
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 configuration from TS 38.331 RRC
|
||||||
SRS_NR srs_nr;
|
SRS_NR srs_nr;
|
||||||
/// Power used by SSB in order to estimate signal strength and path loss
|
/// Power used by SSB in order to estimate signal strength and path loss
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
#define USE_128BIT
|
#define USE_128BIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define PEAK_DETECT_THRESHOLD 15
|
||||||
|
|
||||||
int16_t saturating_sub(int16_t a, int16_t b)
|
int16_t saturating_sub(int16_t a, int16_t b)
|
||||||
{
|
{
|
||||||
int32_t result = (int32_t)a - (int32_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;
|
int max_val = delay->delay_max_val;
|
||||||
const int sync_pos = 0;
|
const int sync_pos = 0;
|
||||||
|
|
||||||
|
uint64_t mean_val = 0;
|
||||||
for (int i = 0; i < ofdm_symbol_size; i++) {
|
for (int i = 0; i < ofdm_symbol_size; i++) {
|
||||||
int temp = c16amp2(ch_estimates_time[i]) >> 1;
|
int temp = c16amp2(ch_estimates_time[i]) >> 1;
|
||||||
|
mean_val += temp;
|
||||||
if (temp > max_val) {
|
if (temp > max_val) {
|
||||||
max_pos = i;
|
max_pos = i;
|
||||||
max_val = temp;
|
max_val = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mean_val /= ofdm_symbol_size;
|
||||||
|
|
||||||
if (max_pos > ofdm_symbol_size / 2)
|
if (max_pos > ofdm_symbol_size / 2)
|
||||||
max_pos = max_pos - ofdm_symbol_size;
|
max_pos = max_pos - ofdm_symbol_size;
|
||||||
|
|
||||||
delay->delay_max_pos = max_pos;
|
delay->delay_max_pos = max_pos;
|
||||||
delay->delay_max_val = max_val;
|
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)
|
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 sr_flag = 0;
|
||||||
int pucch_DTX_thres = 0;
|
int pucch_DTX_thres = 0;
|
||||||
cpuf = get_cpu_freq_GHz();
|
cpuf = get_cpu_freq_GHz();
|
||||||
|
bool print_perf = false;
|
||||||
|
|
||||||
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
|
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
|
||||||
exit_fun("[NR_PUCCHSIM] Error, configuration module init failed\n");
|
exit_fun("[NR_PUCCHSIM] Error, configuration module init failed\n");
|
||||||
@@ -153,8 +154,7 @@ int main(int argc, char **argv)
|
|||||||
logInit();
|
logInit();
|
||||||
|
|
||||||
int c;
|
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 */
|
/* 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' */
|
||||||
if (c == 1 || c == '-' || c == 'O')
|
if (c == 1 || c == '-' || c == 'O')
|
||||||
@@ -349,6 +349,10 @@ int main(int argc, char **argv)
|
|||||||
//nacktoack_flag=(uint8_t)atoi(optarg);
|
//nacktoack_flag=(uint8_t)atoi(optarg);
|
||||||
target_error_rate=0.001;
|
target_error_rate=0.001;
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
print_perf = 1;
|
||||||
|
cpu_meas_enabled = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
case 'h':
|
case 'h':
|
||||||
printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", argv[0]);
|
printf("%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("-x Transmission mode (1,2,6 for the moment)\n");
|
||||||
printf("-y Number of TX antennas used in eNB\n");
|
printf("-y Number of TX antennas used in eNB\n");
|
||||||
printf("-z Number of RX antennas used in UE\n");
|
printf("-z Number of RX antennas used in UE\n");
|
||||||
|
printf("-C print CPU cost\n");
|
||||||
exit (-1);
|
exit (-1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -406,8 +411,8 @@ int main(int argc, char **argv)
|
|||||||
if ((format < 2) && (actual_payload == 4)) do_DTX=1;
|
if ((format < 2) && (actual_payload == 4)) do_DTX=1;
|
||||||
|
|
||||||
if (random_payload) {
|
if (random_payload) {
|
||||||
srand(time(NULL)); // Initialization, should only be called once.
|
double tmp = uniformrandom();
|
||||||
actual_payload = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX.
|
memcpy(&actual_payload, &tmp, sizeof(actual_payload));
|
||||||
}
|
}
|
||||||
actual_payload &= nr_bit < 64 ? (1UL << nr_bit) - 1: 0xffffffffffffffff;
|
actual_payload &= nr_bit < 64 ? (1UL << nr_bit) - 1: 0xffffffffffffffff;
|
||||||
|
|
||||||
@@ -638,6 +643,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
// noise measurement (all PRBs)
|
// noise measurement (all PRBs)
|
||||||
gNB_I0_measurements(gNB, nr_slot_tx, 0, gNB->frame_parms.symbols_per_slot, rb_mask_ul);
|
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 (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){
|
if(format==0){
|
||||||
@@ -731,10 +737,21 @@ int main(int argc, char **argv)
|
|||||||
free(uci_pdu.csi_part1.csi_part1_payload);
|
free(uci_pdu.csi_part1.csi_part1_payload);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
stop_meas(&gNB->phy_proc_rx);
|
||||||
|
|
||||||
n_errors=((actual_payload^payload_received)&1)+(((actual_payload^payload_received)&2)>>1)+(((actual_payload^payload_received)&4)>>2)+n_errors;
|
n_errors=((actual_payload^payload_received)&1)+(((actual_payload^payload_received)&2)>>1)+(((actual_payload^payload_received)&4)>>2)+n_errors;
|
||||||
}
|
}
|
||||||
if (sr_flag == 1)
|
if (sr_flag == 1)
|
||||||
printf("SR: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,sr_errors);
|
printf("SR: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,sr_errors);
|
||||||
|
if (print_perf) {
|
||||||
|
time_stats_t *ts = &gNB->phy_proc_rx;
|
||||||
|
printf("cpu time for pucch format %d: per block %.2f us; nb blocks %d, max time %.2f;\n",
|
||||||
|
format,
|
||||||
|
ts->diff / ts->trials / cpuf / 1000.0,
|
||||||
|
ts->trials,
|
||||||
|
ts->max / cpuf / 1000.0);
|
||||||
|
reset_meas(ts);
|
||||||
|
}
|
||||||
if(nr_bit > 0)
|
if(nr_bit > 0)
|
||||||
printf("ACK/NACK: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors);
|
printf("ACK/NACK: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors);
|
||||||
if((float)(ack_nack_errors+sr_errors)/(float)(n_trials)<=target_error_rate){
|
if((float)(ack_nack_errors+sr_errors)/(float)(n_trials)<=target_error_rate){
|
||||||
|
|||||||
Reference in New Issue
Block a user