|
|
|
@@ -938,6 +938,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
|
|
|
|
|
const freq_alloc_bitmap_t *freq_alloc,
|
|
|
|
|
c16_t *rxF,
|
|
|
|
|
c16_t *pil,
|
|
|
|
|
c16_t *dl_ch,
|
|
|
|
@@ -948,45 +949,49 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
|
|
|
|
|
{
|
|
|
|
|
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)));
|
|
|
|
|
memset(dl_ls_est, 0, sizeof(dl_ls_est));
|
|
|
|
|
|
|
|
|
|
int nest_count = 0;
|
|
|
|
|
uint64_t noise_amp2 = 0;
|
|
|
|
|
|
|
|
|
|
for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt += 2) {
|
|
|
|
|
c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15);
|
|
|
|
|
int idx = 0;
|
|
|
|
|
for (int rb = freq_alloc->start; rb < freq_alloc->start + nb_rb_pdsch; rb++) {
|
|
|
|
|
bool allocated_rb = (freq_alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01;
|
|
|
|
|
if (allocated_rb) {
|
|
|
|
|
for (int pilot_cnt = 0; pilot_cnt < 6; pilot_cnt += 2) {
|
|
|
|
|
c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15);
|
|
|
|
|
#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_l.r, ch_l.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, ch_l.r, ch_l.i);
|
|
|
|
|
#endif
|
|
|
|
|
pil++;
|
|
|
|
|
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
|
|
|
|
|
c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15);
|
|
|
|
|
pil++;
|
|
|
|
|
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
|
|
|
|
|
c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15);
|
|
|
|
|
#ifdef DEBUG_PDSCH
|
|
|
|
|
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i);
|
|
|
|
|
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i);
|
|
|
|
|
#endif
|
|
|
|
|
c16_t ch = c16addShift(ch_l, ch_r, 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;
|
|
|
|
|
c16_t ch = c16addShift(ch_l, ch_r, 1);
|
|
|
|
|
pil++;
|
|
|
|
|
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
|
|
|
|
|
for (int k = 0; k < 4; k++) {
|
|
|
|
|
dl_ls_est[idx] = ch;
|
|
|
|
|
idx++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
pil += 6;
|
|
|
|
|
re_offset = (re_offset + 12) % frame_parms->ofdm_symbol_size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c16_t ch_estimates_time[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
|
|
|
|
nr_est_delay(frame_parms->ofdm_symbol_size, dl_ls_est, ch_estimates_time, 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++) {
|
|
|
|
|
for (int pilot_cnt = 0; pilot_cnt < idx >> 1; 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, &ch, dl_ch, 16);
|
|
|
|
|
} else if (pilot_cnt == 1 || pilot_cnt == 2) {
|
|
|
|
|
c16multaddVectRealComplex(filt16_ul_p1p2, &ch, dl_ch, 16);
|
|
|
|
|
} else if (pilot_cnt == 6 * nb_rb_pdsch - 1) { // Treat last pilot
|
|
|
|
|
} else if (pilot_cnt == (idx >> 1) - 1) { // Treat last pilot
|
|
|
|
|
c16multaddVectRealComplex(filt16_ul_last, &ch, dl_ch, 16);
|
|
|
|
|
} else { // Treat middle pilots
|
|
|
|
|
c16multaddVectRealComplex(filt16_ul_middle, &ch, dl_ch, 16);
|
|
|
|
@@ -998,9 +1003,11 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
|
|
|
|
|
|
|
|
|
|
// Revert delay
|
|
|
|
|
dl_ch = dl_ch0;
|
|
|
|
|
int nest_count = 0;
|
|
|
|
|
uint64_t noise_amp2 = 0;
|
|
|
|
|
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++) {
|
|
|
|
|
for (int k = 0; k < idx; k++) {
|
|
|
|
|
dl_ch[k] = c16mulShift(dl_ch[k], dl_inv_delay_table[k], 8);
|
|
|
|
|
noise_amp2 += c16amp2(c16sub(dl_ls_est[k], dl_ch[k]));
|
|
|
|
|
nest_count++;
|
|
|
|
@@ -1096,6 +1103,7 @@ void NFAPI_NR_DMRS_TYPE1_average_prb(NR_DL_FRAME_PARMS *frame_parms,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
|
|
|
|
|
const freq_alloc_bitmap_t *freq_alloc,
|
|
|
|
|
c16_t *rxF,
|
|
|
|
|
c16_t *pil,
|
|
|
|
|
c16_t *dl_ch,
|
|
|
|
@@ -1106,45 +1114,50 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
|
|
|
|
|
{
|
|
|
|
|
int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size;
|
|
|
|
|
c16_t *dl_ch0 = dl_ch;
|
|
|
|
|
|
|
|
|
|
c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
|
|
|
|
memset(dl_ls_est, 0, sizeof(dl_ls_est));
|
|
|
|
|
|
|
|
|
|
int nest_count = 0;
|
|
|
|
|
uint64_t noise_amp2 = 0;
|
|
|
|
|
|
|
|
|
|
for (int pilot_cnt = 0; pilot_cnt < 4 * nb_rb_pdsch; pilot_cnt += 2) {
|
|
|
|
|
c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15);
|
|
|
|
|
int idx = 0;
|
|
|
|
|
for (int rb = freq_alloc->start; rb < freq_alloc->start + nb_rb_pdsch; rb++) {
|
|
|
|
|
bool allocated_rb = (freq_alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01;
|
|
|
|
|
if (allocated_rb) {
|
|
|
|
|
for (int pilot_cnt = 0; pilot_cnt < 4; pilot_cnt += 2) {
|
|
|
|
|
c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15);
|
|
|
|
|
#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_l.r, ch_l.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, ch_l.r, ch_l.i);
|
|
|
|
|
#endif
|
|
|
|
|
pil++;
|
|
|
|
|
re_offset = (re_offset + 1) % frame_parms->ofdm_symbol_size;
|
|
|
|
|
c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15);
|
|
|
|
|
pil++;
|
|
|
|
|
re_offset = (re_offset + 1) % frame_parms->ofdm_symbol_size;
|
|
|
|
|
c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15);
|
|
|
|
|
#ifdef DEBUG_PDSCH
|
|
|
|
|
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i);
|
|
|
|
|
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i);
|
|
|
|
|
#endif
|
|
|
|
|
c16_t ch = c16addShift(ch_l, ch_r, 1);
|
|
|
|
|
for (int k = 3 * pilot_cnt; k < (3 * pilot_cnt) + 6; k++) {
|
|
|
|
|
dl_ls_est[k] = ch;
|
|
|
|
|
c16_t ch = c16addShift(ch_l, ch_r, 1);
|
|
|
|
|
pil++;
|
|
|
|
|
re_offset = (re_offset + 5) % frame_parms->ofdm_symbol_size;
|
|
|
|
|
for (int k = 0; k < 6; k++) {
|
|
|
|
|
dl_ls_est[idx] = ch;
|
|
|
|
|
idx++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
pil += 4;
|
|
|
|
|
re_offset = (re_offset + 12) % frame_parms->ofdm_symbol_size;
|
|
|
|
|
}
|
|
|
|
|
pil++;
|
|
|
|
|
re_offset = (re_offset + 5) % frame_parms->ofdm_symbol_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c16_t ch_estimates_time[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
|
|
|
|
nr_est_delay(frame_parms->ofdm_symbol_size, dl_ls_est, ch_estimates_time, 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 / 3) * 6;
|
|
|
|
|
// kept the same as before but unclear why would it be nb_rb_pdsch / 2 and not / 3
|
|
|
|
|
for (int pilot_cnt = 0; pilot_cnt < idx >> 1; 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, &ch, dl_ch, 16);
|
|
|
|
|
} else if (pilot_cnt == 1 || pilot_cnt == 2) {
|
|
|
|
|
c16multaddVectRealComplex(filt16_ul_p1p2, &ch, dl_ch, 16);
|
|
|
|
|
} else if (pilot_cnt == 6 * nb_rb_pdsch - 1) { // Treat last pilot
|
|
|
|
|
} else if (pilot_cnt == (idx >> 1) - 1) { // Treat last pilot
|
|
|
|
|
c16multaddVectRealComplex(filt16_ul_last, &ch, dl_ch, 16);
|
|
|
|
|
} else { // Treat middle pilots
|
|
|
|
|
c16multaddVectRealComplex(filt16_ul_middle, &ch, dl_ch, 16);
|
|
|
|
@@ -1156,9 +1169,11 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
|
|
|
|
|
|
|
|
|
|
// Revert delay
|
|
|
|
|
dl_ch = dl_ch0;
|
|
|
|
|
int nest_count = 0;
|
|
|
|
|
uint64_t noise_amp2 = 0;
|
|
|
|
|
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++) {
|
|
|
|
|
for (int k = 0; k < idx; k++) {
|
|
|
|
|
dl_ch[k] = c16mulShift(dl_ch[k], dl_inv_delay_table[k], 8);
|
|
|
|
|
noise_amp2 += c16amp2(c16sub(dl_ls_est[k], dl_ch[k]));
|
|
|
|
|
nest_count++;
|
|
|
|
@@ -1256,6 +1271,7 @@ void NFAPI_NR_DMRS_TYPE2_average_prb(NR_DL_FRAME_PARMS *frame_parms,
|
|
|
|
|
void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
|
|
|
|
const UE_nr_rxtx_proc_t *proc,
|
|
|
|
|
const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch,
|
|
|
|
|
const freq_alloc_bitmap_t *freq_alloc,
|
|
|
|
|
int nl,
|
|
|
|
|
unsigned short p,
|
|
|
|
|
unsigned char symbol,
|
|
|
|
@@ -1270,7 +1286,7 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
|
|
|
|
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
|
|
|
|
const int ch_offset = fp->ofdm_symbol_size * symbol;
|
|
|
|
|
const int symbol_offset = fp->ofdm_symbol_size * symbol;
|
|
|
|
|
int bwp_start_subcarrier = ue->frame_parms.first_carrier_offset + (dlsch->BWPStart + dlsch->start_rb) * 12;
|
|
|
|
|
int bwp_start_subcarrier = fp->first_carrier_offset + (dlsch->BWPStart + freq_alloc->start) * 12;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_PDSCH
|
|
|
|
|
printf(
|
|
|
|
@@ -1287,8 +1303,8 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
|
|
|
|
|
|
|
|
|
// generate pilot for gNB port number 1000+p
|
|
|
|
|
int config_type = dlsch->dmrsConfigType;
|
|
|
|
|
int rb_offset = dlsch->start_rb + (dlsch->refPoint ? 0 : dlsch->BWPStart);
|
|
|
|
|
int nb_rb_pdsch = dlsch->number_rbs;
|
|
|
|
|
int rb_offset = freq_alloc->start + (dlsch->refPoint ? 0 : dlsch->BWPStart);
|
|
|
|
|
int nb_rb_pdsch = freq_alloc->end - freq_alloc->start + 1;
|
|
|
|
|
int8_t delta = get_delta(p, config_type);
|
|
|
|
|
c16_t pilot[3280] __attribute__((aligned(16)));
|
|
|
|
|
// Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS
|
|
|
|
@@ -1311,7 +1327,8 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
|
|
|
|
memset(dl_ch, 0, sizeof(*dl_ch) * fp->ofdm_symbol_size);
|
|
|
|
|
|
|
|
|
|
if (config_type == NFAPI_NR_DMRS_TYPE1 && ue->chest_freq == 0) {
|
|
|
|
|
NFAPI_NR_DMRS_TYPE1_linear_interp(&ue->frame_parms,
|
|
|
|
|
NFAPI_NR_DMRS_TYPE1_linear_interp(fp,
|
|
|
|
|
freq_alloc,
|
|
|
|
|
rxF,
|
|
|
|
|
&pilot[6 * rb_offset],
|
|
|
|
|
dl_ch,
|
|
|
|
@@ -1322,6 +1339,7 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
|
|
|
|
|
|
|
|
|
} else if (config_type == NFAPI_NR_DMRS_TYPE2 && ue->chest_freq == 0) {
|
|
|
|
|
NFAPI_NR_DMRS_TYPE2_linear_interp(fp,
|
|
|
|
|
freq_alloc,
|
|
|
|
|
rxF,
|
|
|
|
|
&pilot[4 * rb_offset],
|
|
|
|
|
dl_ch,
|
|
|
|
@@ -1331,9 +1349,11 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
|
|
|
|
nvar);
|
|
|
|
|
|
|
|
|
|
} else if (config_type == NFAPI_NR_DMRS_TYPE1) {
|
|
|
|
|
AssertFatal(dlsch->resource_alloc == 1, "PRB average in channel estimation not supported for type0 DLSCH\n");
|
|
|
|
|
NFAPI_NR_DMRS_TYPE1_average_prb(fp, rxF, &pilot[6 * rb_offset], dl_ch, bwp_start_subcarrier, nb_rb_pdsch);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
AssertFatal(dlsch->resource_alloc == 1, "PRB average in channel estimation not supported for type0 DLSCH\n");
|
|
|
|
|
NFAPI_NR_DMRS_TYPE2_average_prb(fp, rxF, &pilot[4 * rb_offset], dl_ch, bwp_start_subcarrier, nb_rb_pdsch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|