Implementation of delay compensation in NFAPI_NR_DMRS_TYPE1_linear_interp() at UE
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
#include <stdint.h>
|
||||
#include "assertions.h"
|
||||
#include "nr_common.h"
|
||||
#include <complex.h>
|
||||
|
||||
const char *duplex_mode[]={"FDD","TDD"};
|
||||
|
||||
@@ -738,3 +739,27 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
|
||||
AssertFatal(sco % scs_scaling == 0, "ssb offset %d can create frequency offset\n", sco);
|
||||
return ssb_offset_point_a;
|
||||
}
|
||||
|
||||
int get_delay_idx(int delay, int max_delay_comp)
|
||||
{
|
||||
int delay_idx = max_delay_comp + delay;
|
||||
// If the measured delay is less than -MAX_DELAY_COMP, a -MAX_DELAY_COMP delay is compensated.
|
||||
delay_idx = max(delay_idx, 0);
|
||||
// If the measured delay is greater than +MAX_DELAY_COMP, a +MAX_DELAY_COMP delay is compensated.
|
||||
delay_idx = min(delay_idx, max_delay_comp << 1);
|
||||
return delay_idx;
|
||||
}
|
||||
|
||||
void init_delay_table(uint16_t ofdm_symbol_size,
|
||||
int max_delay_comp,
|
||||
int max_ofdm_symbol_size,
|
||||
c16_t delay_table[][max_ofdm_symbol_size])
|
||||
{
|
||||
for (int delay = -max_delay_comp; delay <= max_delay_comp; delay++) {
|
||||
for (int k = 0; k < ofdm_symbol_size; k++) {
|
||||
double complex delay_cexp = cexp(I * (2.0 * M_PI * k * delay / ofdm_symbol_size));
|
||||
delay_table[max_delay_comp + delay][k].r = (int16_t)round(256 * creal(delay_cexp));
|
||||
delay_table[max_delay_comp + delay][k].i = (int16_t)round(256 * cimag(delay_cexp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,7 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB,
|
||||
int ssbSubcarrierSpacing,
|
||||
int frequency_range);
|
||||
int get_ssb_subcarrier_offset(uint32_t absoluteFrequencySSB, uint32_t absoluteFrequencyPointA);
|
||||
int get_delay_idx(int delay, int max_delay_comp);
|
||||
|
||||
#define CEILIDIV(a,b) ((a+b-1)/b)
|
||||
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
|
||||
|
||||
@@ -66,17 +66,6 @@ int l1_north_init_gNB() {
|
||||
return(0);
|
||||
}
|
||||
|
||||
void init_ul_delay_table(NR_DL_FRAME_PARMS *fp)
|
||||
{
|
||||
for (int delay = -MAX_UL_DELAY_COMP; delay <= MAX_UL_DELAY_COMP; delay++) {
|
||||
for (int k = 0; k < fp->ofdm_symbol_size; k++) {
|
||||
double complex delay_cexp = cexp(I * (2.0 * M_PI * k * delay / fp->ofdm_symbol_size));
|
||||
fp->ul_delay_table[MAX_UL_DELAY_COMP + delay][k].r = (int16_t)round(256 * creal(delay_cexp));
|
||||
fp->ul_delay_table[MAX_UL_DELAY_COMP + delay][k].i = (int16_t)round(256 * cimag(delay_cexp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NR_gNB_PHY_STATS_t *get_phy_stats(PHY_VARS_gNB *gNB, uint16_t rnti)
|
||||
{
|
||||
NR_gNB_PHY_STATS_t *stats;
|
||||
@@ -544,7 +533,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;
|
||||
|
||||
init_codebook_gNB(gNB);
|
||||
init_ul_delay_table(fp);
|
||||
init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table);
|
||||
|
||||
// PBCH DMRS gold sequences generation
|
||||
nr_init_pbch_dmrs(gNB);
|
||||
|
||||
@@ -674,6 +674,7 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){
|
||||
|
||||
void phy_init_nr_top(PHY_VARS_NR_UE *ue) {
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
init_delay_table(frame_parms->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, frame_parms->delay_table);
|
||||
crcTableInit();
|
||||
init_scrambling_luts();
|
||||
load_dftslib();
|
||||
|
||||
@@ -56,5 +56,9 @@ void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCESSES],
|
||||
|
||||
void phy_init_nr_top(PHY_VARS_NR_UE *ue);
|
||||
void phy_term_nr_top(void);
|
||||
void init_delay_table(uint16_t ofdm_symbol_size,
|
||||
int max_delay_comp,
|
||||
int max_ofdm_symbol_size,
|
||||
c16_t delay_table[][max_ofdm_symbol_size]);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -104,19 +104,6 @@ __attribute__((always_inline)) inline c16_t c32x16cumulVectVectWithSteps(c16_t *
|
||||
return c16x32div(cumul, N);
|
||||
}
|
||||
|
||||
int get_delay_idx(int delay) {
|
||||
int delay_idx = MAX_UL_DELAY_COMP + delay;
|
||||
// If the measured delay is less than -MAX_UL_DELAY_COMP, a -MAX_UL_DELAY_COMP delay is compensated.
|
||||
if (delay_idx < 0) {
|
||||
delay_idx = 0;
|
||||
}
|
||||
// If the measured delay is greater than +MAX_UL_DELAY_COMP, a +MAX_UL_DELAY_COMP delay is compensated.
|
||||
if (delay_idx > MAX_UL_DELAY_COMP<<1) {
|
||||
delay_idx = MAX_UL_DELAY_COMP<<1;
|
||||
}
|
||||
return delay_idx;
|
||||
}
|
||||
|
||||
int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
unsigned char Ns,
|
||||
unsigned short p,
|
||||
@@ -240,12 +227,11 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
freq2time(symbolSize, (int16_t *)ul_ls_est, (int16_t *)pusch_vars->ul_ch_estimates_time[aarx]);
|
||||
|
||||
nr_est_timing_advance_pusch(&gNB->frame_parms, pusch_vars->ul_ch_estimates_time[aarx], delay);
|
||||
int pusch_delay = delay->est_delay;
|
||||
int delay_idx = get_delay_idx(pusch_delay);
|
||||
c16_t *ul_delay_table = gNB->frame_parms.ul_delay_table[delay_idx];
|
||||
int delay_idx = get_delay_idx(delay->est_delay, MAX_DELAY_COMP);
|
||||
c16_t *ul_delay_table = gNB->frame_parms.delay_table[delay_idx];
|
||||
|
||||
#ifdef DEBUG_PUSCH
|
||||
printf("Estimated delay = %i\n", pusch_delay >> 1);
|
||||
printf("Estimated delay = %i\n", delay->est_delay >> 1);
|
||||
#endif
|
||||
|
||||
pilot_cnt = 0;
|
||||
@@ -285,8 +271,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
// Revert delay
|
||||
pilot_cnt = 0;
|
||||
ul_ch = &ul_ch_estimates[p * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset];
|
||||
int inv_delay_idx = get_delay_idx(-pusch_delay);
|
||||
c16_t *ul_inv_delay_table = gNB->frame_parms.ul_delay_table[inv_delay_idx];
|
||||
int inv_delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP);
|
||||
c16_t *ul_inv_delay_table = gNB->frame_parms.delay_table[inv_delay_idx];
|
||||
for (int n = 0; n < 3 * nb_rb_pusch; n++) {
|
||||
for (int k_line = 0; k_line <= 1; k_line++) {
|
||||
int k = pilot_cnt << 1;
|
||||
@@ -326,9 +312,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
|
||||
// Delay compensation
|
||||
freq2time(symbolSize, (int16_t *)ul_ls_est, (int16_t *)pusch_vars->ul_ch_estimates_time[aarx]);
|
||||
nr_est_timing_advance_pusch(&gNB->frame_parms, pusch_vars->ul_ch_estimates_time[aarx], delay);
|
||||
int pusch_delay = delay->est_delay;
|
||||
int delay_idx = get_delay_idx(-pusch_delay);
|
||||
c16_t *ul_delay_table = gNB->frame_parms.ul_delay_table[delay_idx];
|
||||
int delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP);
|
||||
c16_t *ul_delay_table = gNB->frame_parms.delay_table[delay_idx];
|
||||
for (int n = 0; n < nb_rb_pusch * NR_NB_SC_PER_RB; n++) {
|
||||
ul_ch[n] = c16mulShift(ul_ls_est[n], ul_delay_table[n % 6], 8);
|
||||
}
|
||||
|
||||
@@ -1377,6 +1377,7 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
|
||||
int8_t delta,
|
||||
delay_t *delay)
|
||||
{
|
||||
c16_t *dl_ch0 = dl_ch;
|
||||
int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size;
|
||||
|
||||
c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
@@ -1409,21 +1410,33 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
|
||||
}
|
||||
|
||||
nr_est_delay_pdsch(frame_parms, dl_ls_est, delay);
|
||||
int delay_idx = get_delay_idx(delay->est_delay, MAX_DELAY_COMP);
|
||||
c16_t *dl_delay_table = frame_parms->delay_table[delay_idx];
|
||||
|
||||
for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt++) {
|
||||
int k = pilot_cnt << 1;
|
||||
c16_t ch = c16mulShift(dl_ls_est[k], dl_delay_table[k], 8);
|
||||
if (pilot_cnt == 0) { // Treat first pilot
|
||||
c16multaddVectRealComplex(filt16_ul_p0, &dl_ls_est[pilot_cnt << 1], dl_ch, 16);
|
||||
c16multaddVectRealComplex(filt16_ul_p0, &ch, dl_ch, 16);
|
||||
} else if (pilot_cnt == 1 || pilot_cnt == 2) {
|
||||
c16multaddVectRealComplex(filt16_ul_p1p2, &dl_ls_est[pilot_cnt << 1], dl_ch, 16);
|
||||
c16multaddVectRealComplex(filt16_ul_p1p2, &ch, dl_ch, 16);
|
||||
} else if (pilot_cnt == 6 * nb_rb_pdsch - 1) { // Treat last pilot
|
||||
c16multaddVectRealComplex(filt16_ul_last, &dl_ls_est[pilot_cnt << 1], dl_ch, 16);
|
||||
c16multaddVectRealComplex(filt16_ul_last, &ch, dl_ch, 16);
|
||||
} else { // Treat middle pilots
|
||||
c16multaddVectRealComplex(filt16_ul_middle, &dl_ls_est[pilot_cnt << 1], dl_ch, 16);
|
||||
c16multaddVectRealComplex(filt16_ul_middle, &ch, dl_ch, 16);
|
||||
if (pilot_cnt % 2 == 0) {
|
||||
dl_ch += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Revert delay
|
||||
dl_ch = dl_ch0;
|
||||
int inv_delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP);
|
||||
c16_t *dl_inv_delay_table = frame_parms->delay_table[inv_delay_idx];
|
||||
for (int k = 0; k < 12 * nb_rb_pdsch; k++) {
|
||||
dl_ch[k] = c16mulShift(dl_ch[k], dl_inv_delay_table[k], 8);
|
||||
}
|
||||
}
|
||||
|
||||
void NFAPI_NR_DMRS_TYPE1_average_prb(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
|
||||
#define NR_NB_NSCID 2
|
||||
|
||||
#define MAX_UL_DELAY_COMP 20
|
||||
#define MAX_DELAY_COMP 20
|
||||
|
||||
typedef enum {
|
||||
NR_MU_0=0,
|
||||
@@ -227,8 +227,8 @@ struct NR_DL_FRAME_PARMS {
|
||||
/// sequence used to compensate the phase rotation due to timeshifted OFDM symbols
|
||||
/// First dimenstion is for different CP lengths
|
||||
c16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16)));
|
||||
/// Table used to apply the delay compensation in UL
|
||||
c16_t ul_delay_table[2 * MAX_UL_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE * 2];
|
||||
/// Table used to apply the delay compensation in DL/UL
|
||||
c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE];
|
||||
/// shift of pilot position in one RB
|
||||
uint8_t nushift;
|
||||
/// SRS configuration from TS 38.331 RRC
|
||||
|
||||
Reference in New Issue
Block a user