Commit 7611fe67 authored by rmagueta's avatar rmagueta

Implementation of delay estimation in NFAPI_NR_DMRS_TYPE1_linear_interp() at UE

parent 72aae255
......@@ -72,6 +72,15 @@ typedef enum frequency_range_e {
FR2
} frequency_range_t;
typedef struct {
/// Time shift in number of samples estimated based on DMRS-PDSCH/PUSCH
int est_delay;
/// Max position in OFDM symbol related to time shift estimation based on DMRS-PDSCH/PUSCH
int delay_max_pos;
/// Max value related to time shift estimation based on DMRS-PDSCH/PUSCH
int delay_max_val;
} delay_t;
extern const nr_bandentry_t nr_bandtable[];
static inline int get_num_dmrs(uint16_t dmrs_mask ) {
......@@ -114,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);
#define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
......
......@@ -38,10 +38,10 @@
extern openair0_config_t openair0_cfg[MAX_CARDS];
void nr_est_timing_advance_pusch(const NR_DL_FRAME_PARMS *frame_parms, const int32_t *ul_ch_estimates_time, NR_ULSCH_delay_t *delay)
void nr_est_timing_advance_pusch(const NR_DL_FRAME_PARMS *frame_parms, const int32_t *ul_ch_estimates_time, delay_t *delay)
{
int max_pos = delay->pusch_delay_max_pos;
int max_val = delay->pusch_delay_max_val;
int max_pos = delay->delay_max_pos;
int max_val = delay->delay_max_val;
const int sync_pos = 0;
for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) {
......@@ -56,9 +56,9 @@ void nr_est_timing_advance_pusch(const NR_DL_FRAME_PARMS *frame_parms, const int
if (max_pos > frame_parms->ofdm_symbol_size / 2)
max_pos = max_pos - frame_parms->ofdm_symbol_size;
delay->pusch_delay_max_pos = max_pos;
delay->pusch_delay_max_val = max_val;
delay->pusch_est_delay = max_pos - sync_pos;
delay->delay_max_pos = max_pos;
delay->delay_max_val = max_val;
delay->est_delay = max_pos - sync_pos;
}
int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms,
......
......@@ -42,9 +42,10 @@
#define NO_INTERP 1
#define dBc(x,y) (dB_fixed(((int32_t)(x))*(x) + ((int32_t)(y))*(y)))
void freq2time(uint16_t ofdm_symbol_size,
int16_t *freq_signal,
int16_t *time_signal) {
static void freq2time(uint16_t ofdm_symbol_size,
int16_t *freq_signal,
int16_t *time_signal)
{
switch (ofdm_symbol_size) {
case 128:
......@@ -194,7 +195,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
uint64_t noise_amp2 = 0;
c16_t ul_ls_est[symbolSize] __attribute__((aligned(32)));
memset(ul_ls_est, 0, sizeof(c16_t) * symbolSize);
NR_ULSCH_delay_t *delay = &gNB->ulsch[ul_id].delay;
delay_t *delay = &gNB->ulsch[ul_id].delay;
memset(delay, 0, sizeof(*delay));
for (int aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {
......@@ -239,7 +240,7 @@ 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->pusch_est_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];
......@@ -325,7 +326,7 @@ 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->pusch_est_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];
for (int n = 0; n < nb_rb_pusch * NR_NB_SC_PER_RB; n++) {
......
......@@ -61,8 +61,7 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB,
uint8_t nrOfLayers);
void nr_est_timing_advance_pusch(const NR_DL_FRAME_PARMS *frame_parms,
const int32_t *ul_ch_estimates_time,
NR_ULSCH_delay_t *delay);
const int32_t *ul_ch_estimates_time, delay_t *delay);
int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms,
const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]);
......
......@@ -1303,112 +1303,127 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
}
}
static void freq2time(uint16_t ofdm_symbol_size,
int16_t *freq_signal,
int16_t *time_signal)
{
switch (ofdm_symbol_size) {
case 128:
idft(IDFT_128, freq_signal, time_signal, 1);
break;
case 256:
idft(IDFT_256, freq_signal, time_signal, 1);
break;
case 512:
idft(IDFT_512, freq_signal, time_signal, 1);
break;
case 1024:
idft(IDFT_1024, freq_signal, time_signal, 1);
break;
case 1536:
idft(IDFT_1536, freq_signal, time_signal, 1);
break;
case 2048:
idft(IDFT_2048, freq_signal, time_signal, 1);
break;
case 4096:
idft(IDFT_4096, freq_signal, time_signal, 1);
break;
case 6144:
idft(IDFT_6144, freq_signal, time_signal, 1);
break;
case 8192:
idft(IDFT_8192, freq_signal, time_signal, 1);
break;
default:
AssertFatal (1 == 0, "Invalid ofdm_symbol_size %i\n", ofdm_symbol_size);
break;
}
}
void nr_est_delay_pdsch(const NR_DL_FRAME_PARMS *frame_parms, const c16_t *dl_ls_est, delay_t *delay)
{
c16_t dl_ch_estimates_time[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
memset(dl_ch_estimates_time, 0, sizeof(dl_ch_estimates_time));
freq2time(frame_parms->ofdm_symbol_size, (int16_t *)dl_ls_est, (int16_t *)dl_ch_estimates_time);
int max_pos = delay->delay_max_pos;
int max_val = delay->delay_max_val;
const int sync_pos = 0;
for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) {
int temp = c16amp2(dl_ch_estimates_time[i]) >> 1;
if (temp > max_val) {
max_pos = i;
max_val = temp;
}
}
if (max_pos > frame_parms->ofdm_symbol_size / 2)
max_pos = max_pos - frame_parms->ofdm_symbol_size;
delay->delay_max_pos = max_pos;
delay->delay_max_val = max_val;
delay->est_delay = max_pos - sync_pos;
}
void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
c16_t *rxF,
c16_t *pil,
c16_t *dl_ch,
unsigned short bwp_start_subcarrier,
unsigned short nb_rb_pdsch,
int8_t delta)
int8_t delta,
delay_t *delay)
{
int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size;
c16_t *pil0 = pil;
c16_t *dl_ch0 = dl_ch;
c16_t ch = {0};
const int16_t *fdcl = NULL;
const int16_t *fdcr = NULL;
const int16_t *fdclh = NULL;
const int16_t *fdcrh = NULL;
switch (delta) {
case 0: // port 0,1
fdcl = filt8_dcl0; // left DC interpolation Filter (even RB)
fdcr = filt8_dcr0; // right DC interpolation Filter (even RB)
fdclh = filt8_dcl0_h; // left DC interpolation Filter (odd RB)
fdcrh = filt8_dcr0_h; // right DC interpolation Filter (odd RB)
break;
case 1: // port2,3
fdcl = filt8_dcl1;
fdcr = filt8_dcr1;
fdclh = filt8_dcl1_h;
fdcrh = filt8_dcr1_h;
break;
default:
AssertFatal(1 == 0, "pdsch_channel_estimation: Invalid delta %i\n", delta);
break;
}
c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
memset(dl_ls_est, 0, sizeof(dl_ls_est));
for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt++) {
if (pilot_cnt % 2 == 0) {
ch = c16mulShift(*pil, rxF[re_offset], 15);
c16_t ch = c16mulShift(*pil, rxF[re_offset], 15);
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
ch = c16maddShift(*pil, rxF[re_offset], ch, 15);
ch = c16Shift(ch, 1);
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
for (int k = pilot_cnt << 1; k < (pilot_cnt << 1) + 4; k++) {
dl_ls_est[k] = ch;
}
}
#ifdef DEBUG_PDSCH
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch.r, ch.i);
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n",
pilot_cnt,
pil->r,
pil->i,
rxF[re_offset].r,
rxF[re_offset].i,
dl_ls_est[pilot_cnt << 1].r,
dl_ls_est[pilot_cnt << 1].i);
#endif
}
nr_est_delay_pdsch(frame_parms, dl_ls_est, delay);
for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt++) {
if (pilot_cnt == 0) { // Treat first pilot
c16multaddVectRealComplex(filt16_ul_p0, &ch, dl_ch, 16);
c16multaddVectRealComplex(filt16_ul_p0, &dl_ls_est[pilot_cnt << 1], dl_ch, 16);
} else if (pilot_cnt == 1 || pilot_cnt == 2) {
c16multaddVectRealComplex(filt16_ul_p1p2, &ch, dl_ch, 16);
c16multaddVectRealComplex(filt16_ul_p1p2, &dl_ls_est[pilot_cnt << 1], dl_ch, 16);
} else if (pilot_cnt == 6 * nb_rb_pdsch - 1) { // Treat last pilot
c16multaddVectRealComplex(filt16_ul_last, &ch, dl_ch, 16);
c16multaddVectRealComplex(filt16_ul_last, &dl_ls_est[pilot_cnt << 1], dl_ch, 16);
} else { // Treat middle pilots
c16multaddVectRealComplex(filt16_ul_middle, &ch, dl_ch, 16);
c16multaddVectRealComplex(filt16_ul_middle, &dl_ls_est[pilot_cnt << 1], dl_ch, 16);
if (pilot_cnt % 2 == 0) {
dl_ch += 4;
}
}
}
// check if PRB crosses DC and improve estimates around DC
if ((bwp_start_subcarrier < frame_parms->ofdm_symbol_size) && (bwp_start_subcarrier + nb_rb_pdsch * 12 >= frame_parms->ofdm_symbol_size)) {
dl_ch = dl_ch0;
uint16_t idxDC = 2 * (frame_parms->ofdm_symbol_size - bwp_start_subcarrier);
uint16_t idxPil = idxDC / 4;
re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size;
pil = pil0;
pil += (idxPil - 1);
dl_ch += (idxDC / 2 - 2);
dl_ch = memset(dl_ch, 0, sizeof(c16_t) * 5);
re_offset = (re_offset + idxDC / 2 - 2) % frame_parms->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
ch = c16maddShift(*pil, rxF[re_offset], ch, 15);
ch = c16Shift(ch, 1);
// for proper allignment of SIMD vectors
if ((frame_parms->N_RB_DL & 1) == 0) {
c16multaddVectRealComplex(fdcl, &ch, dl_ch - 2, 8);
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
ch = c16maddShift(*pil, rxF[re_offset], ch, 15);
ch = c16Shift(ch, 1);
c16multaddVectRealComplex(fdcr, &ch, dl_ch - 2, 8);
} else {
c16multaddVectRealComplex(fdclh, &ch, dl_ch, 8);
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
ch = c16maddShift(*pil, rxF[re_offset], ch, 15);
ch = c16Shift(ch, 1);
c16multaddVectRealComplex(fdcrh, &ch, dl_ch, 8);
}
}
}
void NFAPI_NR_DMRS_TYPE1_average_prb(NR_DL_FRAME_PARMS *frame_parms,
......@@ -1503,7 +1518,8 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
unsigned short bwp_start_subcarrier,
unsigned short nb_rb_pdsch,
int8_t delta,
unsigned short p)
unsigned short p,
delay_t *delay)
{
int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size;
c16_t *dl_ch0 = dl_ch;
......@@ -1715,6 +1731,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
ue->frame_parms.nushift = nushift;
}
delay_t delay = {0};
for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) {
#ifdef DEBUG_PDSCH
......@@ -1734,7 +1752,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
dl_ch,
bwp_start_subcarrier,
nb_rb_pdsch,
delta);
delta,
&delay);
} else if (config_type == NFAPI_NR_DMRS_TYPE2 && ue->chest_freq == 0) {
NFAPI_NR_DMRS_TYPE2_linear_interp(&ue->frame_parms,
......
......@@ -255,15 +255,6 @@ typedef struct {
int subband_cqi_tot_dB[275];
} ulsch_measurements_gNB;
typedef struct {
/// Time shift in number of samples estimated based on DMRS-PUSCH
int pusch_est_delay;
/// Max position in OFDM symbol related to time shift estimation based on DMRS-PUSCH
int pusch_delay_max_pos;
/// Max value related to time shift estimation based on DMRS-PUSCH
int pusch_delay_max_val;
} NR_ULSCH_delay_t;
typedef struct {
uint32_t frame;
uint32_t slot;
......@@ -281,7 +272,7 @@ typedef struct {
bool active;
/// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around
uint8_t handled;
NR_ULSCH_delay_t delay;
delay_t delay;
ulsch_measurements_gNB ulsch_measurements;
} NR_gNB_ULSCH_t;
......
......@@ -422,7 +422,7 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id,
nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu;
// Get estimated timing advance for MAC
int sync_pos = ulsch->delay.pusch_est_delay;
int sync_pos = ulsch->delay.est_delay;
// scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size
uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048;
......
......@@ -1540,9 +1540,9 @@ int main(int argc, char **argv)
if (!crc_status)
effRate += ((double)TBS) / (double)round;
sum_pusch_delay += ulsch_gNB->delay.pusch_est_delay;
min_pusch_delay = ulsch_gNB->delay.pusch_est_delay < min_pusch_delay ? ulsch_gNB->delay.pusch_est_delay : min_pusch_delay;
max_pusch_delay = ulsch_gNB->delay.pusch_est_delay > max_pusch_delay ? ulsch_gNB->delay.pusch_est_delay : max_pusch_delay;
sum_pusch_delay += ulsch_gNB->delay.est_delay;
min_pusch_delay = min(ulsch_gNB->delay.est_delay, min_pusch_delay);
max_pusch_delay = max(ulsch_gNB->delay.est_delay, max_pusch_delay);
delay_pusch_est_count++;
} // trial loop
......
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