PSBCH RX TX and SLSS search procedures

- RX/TX Phy processing accg to 38.211, 38.212 Rel16
	- PSBCH simulator used to validate TX/RX phy processing
	- PSBCH SLSS Search procedures
	- PSBCH SIM also tests SLSS SEARCH
This commit is contained in:
Raghavendra Dinavahi
2024-04-12 16:07:00 +02:00
committed by Robert Schmidt
parent 1244c9a278
commit 94b23d1eb0
35 changed files with 3069 additions and 113 deletions
@@ -657,7 +657,7 @@ c32_t nr_pbch_dmrs_correlation(const PHY_VARS_NR_UE *ue,
// generate pilot
// Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS
c16_t pilot[200] __attribute__((aligned(16)));
nr_pbch_dmrs_rx(dmrss, nr_gold_pbch, pilot);
nr_pbch_dmrs_rx(dmrss, (uint32_t *)nr_gold_pbch, pilot, false);
c32_t computed_val = {0};
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
@@ -717,42 +717,70 @@ c32_t nr_pbch_dmrs_correlation(const PHY_VARS_NR_UE *ue,
}
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
NR_DL_FRAME_PARMS *fp,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
struct complex16 dl_ch_estimates_time[][ue->frame_parms.ofdm_symbol_size],
struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size],
const UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
int dmrss,
uint8_t ssb_index,
uint8_t n_hf,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
c16_t rxdataF[][fp->samples_per_slot_wCP],
bool sidelink,
uint16_t Nid)
{
int Ns = proc->nr_slot_rx;
c16_t pilot[200] __attribute__((aligned(16)));
//int slot_pbch;
const int nushift = ue->frame_parms.Nid_cell % 4;
unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier;
if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size;
uint8_t nushift = 0, lastsymbol = 0, num_rbs = 0;
uint32_t *gold_seq = NULL;
const int ch_offset = ue->frame_parms.ofdm_symbol_size * symbol;
if (sidelink) {
AssertFatal(dmrss >= 0 && dmrss < 3,
AssertFatal(dmrss == 0 || (dmrss >= 5 && dmrss <= 12),
"symbol %d is illegal for PSBCH DM-RS \n",
dmrss);
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
LOG_D(PHY,"PSBCH Channel Estimation SLSSID:%d\n", Nid);
gold_seq = sl_phy_params->init_params.psbch_dmrs_gold_sequences[Nid];
lastsymbol = 12;
num_rbs = SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL;
} else {
nushift = fp->Nid_cell%4;
AssertFatal(dmrss >= 0 && dmrss < 3,
"symbol %d is illegal for PBCH DM-RS \n",
dmrss);
const int symbol_offset = ue->frame_parms.ofdm_symbol_size * symbol;
gold_seq = ue->nr_gold_pbch[n_hf][ssb_index];
lastsymbol = 2;
num_rbs = 20;
}
unsigned int ssb_offset = fp->first_carrier_offset + fp->ssb_start_subcarrier;
if (ssb_offset>= fp->ofdm_symbol_size) ssb_offset-= fp->ofdm_symbol_size;
const int ch_offset = fp->ofdm_symbol_size*symbol;
const int symbol_offset = fp->ofdm_symbol_size*symbol;
const int k = nushift;
const c16_t *fl, *fm, *fr;
DEBUG_PBCH("PBCH Channel Estimation : gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",
proc->gNB_id,
ch_offset,
ue->frame_parms.ofdm_symbol_size,
ue->frame_parms.Ncp,
Ns,
k,
symbol);
proc->gNB_id,
ch_offset,
fp->ofdm_symbol_size,
fp->Ncp,
Ns,
k,
symbol);
const c16_t *fl, *fm, *fr;
switch (k) {
case 0:
@@ -787,7 +815,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
idft_size_idx_t idftsizeidx;
switch (ue->frame_parms.ofdm_symbol_size) {
switch (fp->ofdm_symbol_size) {
case 128:
idftsizeidx = IDFT_128;
break;
@@ -835,19 +863,19 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
// generate pilot
// Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS
nr_pbch_dmrs_rx(dmrss, ue->nr_gold_pbch[n_hf][ssb_index], pilot);
nr_pbch_dmrs_rx(dmrss,gold_seq, &pilot[0], sidelink);
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
for (int aarx=0; aarx<fp->nb_antennas_rx; aarx++) {
int re_offset = ssb_offset;
c16_t *pil = pilot;
c16_t *rxF = &rxdataF[aarx][symbol_offset + k];
c16_t *dl_ch = &dl_ch_estimates[aarx][ch_offset];
memset(dl_ch, 0, sizeof(c16_t) * ue->frame_parms.ofdm_symbol_size);
memset(dl_ch, 0, sizeof(c16_t) * fp->ofdm_symbol_size);
DEBUG_PBCH("pbch ch est pilot RB_DL %d\n", ue->frame_parms.N_RB_DL);
DEBUG_PBCH("k %d, first_carrier %d\n", k, ue->frame_parms.first_carrier_offset);
DEBUG_PBCH("pbch ch est pilot RB_DL %d\n", fp->N_RB_DL);
DEBUG_PBCH("k %d, first_carrier %d\n", k, fp->first_carrier_offset);
// Treat first 2 pilots specially (left edge)
c16_t ch;
@@ -855,31 +883,31 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
DEBUG_PBCH("pilot 0: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n", rxF[re_offset].r, rxF[re_offset].i, ch.r, ch.i, pil->r, pil->i);
multaddRealVectorComplexScalar(fl, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot 1: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n", rxF[re_offset].r, rxF[re_offset].i, ch.r, ch.i, pil->r, pil->i);
multaddRealVectorComplexScalar(fm, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot 2: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n", rxF[re_offset].r, rxF[re_offset].i, ch.r, ch.i, pil->r, pil->i);
multaddRealVectorComplexScalar(fr, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
dl_ch += 24;
for (int pilot_cnt = 3; pilot_cnt < (3 * 20); pilot_cnt += 3) {
for (int pilot_cnt = 3; pilot_cnt < (3 * num_rbs); pilot_cnt += 3) {
// if (pilot_cnt == 30)
// rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k)];
// in 2nd symbol, skip middle REs (48 with DMRS, 144 for SSS, and another 48 with DMRS)
if (dmrss == 1 && pilot_cnt == 12) {
pilot_cnt=48;
re_offset = (re_offset + 144) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset + 144) % fp->ofdm_symbol_size;
dl_ch += 288;
}
ch = c16mulShift(*pil, rxF[re_offset], 15);
@@ -894,7 +922,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
multaddRealVectorComplexScalar(fl, ch, dl_ch, 16);
pil++;
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot %u: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n",
pilot_cnt + 1,
@@ -906,7 +934,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
pil->i);
multaddRealVectorComplexScalar(fm, ch, dl_ch, 16);
pil++;
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
ch = c16mulShift(*pil, rxF[re_offset], 15);
DEBUG_PBCH("pilot %u: rxF= (%d,%d), ch= (%d,%d), pil=(%d,%d)\n",
pilot_cnt + 2,
@@ -918,11 +946,11 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
pil->i);
multaddRealVectorComplexScalar(fr, ch, dl_ch, 16);
pil++;
re_offset = (re_offset + 4) % ue->frame_parms.ofdm_symbol_size;
re_offset = (re_offset + 4) % fp->ofdm_symbol_size;
dl_ch += 12;
}
if( dmrss == 2) // update time statistics for last PBCH symbol
if( dmrss == lastsymbol) // update time statistics for last PBCH symbol
{
// do ifft of channel estimate
LOG_D(PHY,"Channel Impulse Computation Slot %d Symbol %d ch_offset %d\n", Ns, symbol, ch_offset);
@@ -933,13 +961,13 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
}
}
if (dmrss == 2)
if (!sidelink && dmrss == lastsymbol)
UEscopeCopy(ue,
pbchDlChEstimateTime,
(void *)dl_ch_estimates_time,
sizeof(c16_t),
ue->frame_parms.nb_antennas_rx,
ue->frame_parms.ofdm_symbol_size,
fp->nb_antennas_rx,
fp->ofdm_symbol_size,
0);
return(0);
+10 -2
View File
@@ -65,15 +65,18 @@ c32_t nr_pbch_dmrs_correlation(const PHY_VARS_NR_UE *ue,
const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
NR_DL_FRAME_PARMS *fp,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
struct complex16 dl_ch_estimates_time[][ue->frame_parms.ofdm_symbol_size],
struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size],
const UE_nr_rxtx_proc_t *proc,
unsigned char symbol,
int dmrss,
uint8_t ssb_index,
uint8_t n_hf,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
c16_t rxdataF[][fp->samples_per_slot_wCP],
bool sidelink,
uint16_t Nid);
int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
@@ -137,5 +140,10 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
NR_UE_DLSCH_t dlsch[2]);
float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index);
void nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params,
NR_DL_FRAME_PARMS *fp,
c16_t rxdataF[][fp->samples_per_slot_wCP],
bool use_SSS);
/** @}*/
#endif
@@ -309,3 +309,57 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
ue->measurements.n0_power_tot_dB + 30 - 10 * log10(pow(2, 30)) - dB_fixed(ue->frame_parms.ofdm_symbol_size)
- ((int)rx_gain - (int)rx_gain_offset));
}
//PSBCH RSRP calculations according to 38.215 section 5.1.22
void nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params,
NR_DL_FRAME_PARMS *fp,
c16_t rxdataF[][fp->samples_per_slot_wCP],
bool use_SSS)
{
SL_NR_UE_PSBCH_t *psbch_rx = &sl_phy_params->psbch;
uint8_t numsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP
: SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
uint32_t re_offset = fp->first_carrier_offset + fp->ssb_start_subcarrier;
uint32_t rsrp = 0, num_re = 0;
LOG_D(PHY, "PSBCH RSRP MEAS: numsym:%d, re_offset:%d\n",numsym, re_offset);
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
//Calculate PSBCH RSRP based from DMRS REs
for (uint8_t symbol=0; symbol<numsym;) {
struct complex16 *rxF = &rxdataF[aarx][symbol*fp->ofdm_symbol_size];
for (int re=0;re<SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL;re++) {
if (re%4 == 0) { //DMRS RE
uint16_t offset = (re_offset + re) % fp->ofdm_symbol_size;
rsrp += c16amp2(rxF[offset]);
num_re++;
}
}
symbol = (symbol == 0) ? 5 : symbol+1;
}
}
if (use_SSS) {
//TBD...
//UE can decide between using only PSBCH DMRS or PSBCH DMRS and SSS for PSBCH RSRP computation.
//If needed this can be implemented. Reference Spec 38.215
}
psbch_rx->rsrp_dB_per_RE = 10*log10(rsrp / num_re);
psbch_rx->rsrp_dBm_per_RE = psbch_rx->rsrp_dB_per_RE +
30 - 10*log10(pow(2,30)) -
((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) -
dB_fixed(fp->ofdm_symbol_size);
LOG_I(PHY, "PSBCH RSRP (DMRS REs): numREs:%d RSRP :%d dB/RE ,RSRP:%d dBm/RE\n",
num_re, psbch_rx->rsrp_dB_per_RE, psbch_rx->rsrp_dBm_per_RE);
}