PTRS DL extraction, estimation and compensation
- Added PTRS extraction and estimation for DL - Added processing for whole slot wrt PTRS estimates - DLSIM is updated to used -T flag to enable PTRS - DMRS compensated signal is further compensated with PTRS estimation
This commit is contained in:
@@ -604,6 +604,9 @@ void phy_init_nr_ue__PDSCH(NR_UE_PDSCH *const pdsch,
|
|||||||
//pdsch->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
|
//pdsch->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
|
||||||
pdsch->dl_ch_mag0 = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
|
pdsch->dl_ch_mag0 = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
|
||||||
pdsch->dl_ch_magb0 = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
|
pdsch->dl_ch_magb0 = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
|
||||||
|
pdsch->ptrs_phase_per_slot = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
|
||||||
|
pdsch->ptrs_re_per_slot = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
|
||||||
|
pdsch->dl_ch_ptrs_estimates_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
|
||||||
// the allocated memory size is fixed:
|
// the allocated memory size is fixed:
|
||||||
AssertFatal( fp->nb_antennas_rx <= 2, "nb_antennas_rx > 2" );
|
AssertFatal( fp->nb_antennas_rx <= 2, "nb_antennas_rx > 2" );
|
||||||
|
|
||||||
@@ -624,6 +627,9 @@ void phy_init_nr_ue__PDSCH(NR_UE_PDSCH *const pdsch,
|
|||||||
//pdsch->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
|
//pdsch->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
|
||||||
pdsch->dl_ch_mag0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
|
pdsch->dl_ch_mag0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
|
||||||
pdsch->dl_ch_magb0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
|
pdsch->dl_ch_magb0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
|
||||||
|
pdsch->ptrs_re_per_slot[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * 14);
|
||||||
|
pdsch->ptrs_phase_per_slot[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * 14 );
|
||||||
|
pdsch->dl_ch_ptrs_estimates_ext[idx]= (int32_t *)malloc16_clear( sizeof(int32_t) * num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "dmrs_nr.h"
|
#include "dmrs_nr.h"
|
||||||
#include "PHY/NR_REFSIG/ptrs_nr.h"
|
#include "PHY/NR_REFSIG/ptrs_nr.h"
|
||||||
|
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@@ -180,93 +180,265 @@ uint8_t is_ptrs_subcarrier(uint16_t k,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* return the total number of ptrs symbol in a slot */
|
||||||
/*
|
uint8_t get_ptrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t start_symb, uint16_t nb_symb)
|
||||||
int main(int argc, char const *argv[])
|
|
||||||
{
|
{
|
||||||
|
uint8_t tmp = 0;
|
||||||
dmrs_UplinkConfig_t dmrs_Uplink_Config;
|
for (int i = start_symb; i <= nb_symb; i++)
|
||||||
ptrs_UplinkConfig_t ptrs_Uplink_Config;
|
{
|
||||||
uint8_t resourceElementOffset;
|
tmp += (l_prime_mask >> i) & 0x01;
|
||||||
uint8_t dmrs_antenna_port;
|
|
||||||
uint8_t L_ptrs, K_ptrs;
|
|
||||||
int16_t k_RE_ref;
|
|
||||||
uint16_t N_RB, ptrs_symbols, ofdm_symbol_size, k;
|
|
||||||
uint8_t duration_in_symbols, I_mcs;
|
|
||||||
uint8_t start_symbol, l;
|
|
||||||
uint8_t ptrs_symbol_flag;
|
|
||||||
uint16_t n_rnti;
|
|
||||||
|
|
||||||
dmrs_Uplink_Config.pusch_dmrs_type = pusch_dmrs_type1;
|
|
||||||
dmrs_Uplink_Config.pusch_dmrs_AdditionalPosition = pusch_dmrs_pos1;
|
|
||||||
dmrs_Uplink_Config.pusch_maxLength = pusch_len2;
|
|
||||||
|
|
||||||
ptrs_Uplink_Config.timeDensity.ptrs_mcs1 = 0; // setting MCS values to 0 indicate abscence of time_density field in the configuration
|
|
||||||
ptrs_Uplink_Config.timeDensity.ptrs_mcs2 = 0;
|
|
||||||
ptrs_Uplink_Config.timeDensity.ptrs_mcs3 = 0;
|
|
||||||
ptrs_Uplink_Config.frequencyDensity.n_rb0 = 0; // setting N_RB values to 0 indicate abscence of frequency_density field in the configuration
|
|
||||||
ptrs_Uplink_Config.frequencyDensity.n_rb1 = 0;
|
|
||||||
ptrs_Uplink_Config.resourceElementOffset = 0;
|
|
||||||
|
|
||||||
n_rnti = 0x1234;
|
|
||||||
resourceElementOffset = 0;
|
|
||||||
ptrs_symbols = 0;
|
|
||||||
dmrs_antenna_port = 0;
|
|
||||||
N_RB = 50;
|
|
||||||
duration_in_symbols = 14;
|
|
||||||
ofdm_symbol_size = 2048;
|
|
||||||
I_mcs = 9;
|
|
||||||
start_symbol = 0;
|
|
||||||
ptrs_symbol_flag = 0;
|
|
||||||
|
|
||||||
k_RE_ref = get_kRE_ref(dmrs_antenna_port, dmrs_Uplink_Config.pusch_dmrs_type, resourceElementOffset);
|
|
||||||
|
|
||||||
K_ptrs = get_K_ptrs(&ptrs_Uplink_Config, N_RB);
|
|
||||||
|
|
||||||
L_ptrs = get_L_ptrs(&ptrs_Uplink_Config, I_mcs);
|
|
||||||
|
|
||||||
set_ptrs_symb_idx(&ptrs_symbols,
|
|
||||||
&ptrs_Uplink_Config,
|
|
||||||
&dmrs_Uplink_Config,
|
|
||||||
1,
|
|
||||||
duration_in_symbols,
|
|
||||||
start_symbol,
|
|
||||||
L_ptrs,
|
|
||||||
ofdm_symbol_size);
|
|
||||||
|
|
||||||
printf("PTRS OFDM symbol indicies: ");
|
|
||||||
|
|
||||||
for (l = start_symbol; l < start_symbol + duration_in_symbols; l++){
|
|
||||||
|
|
||||||
ptrs_symbol_flag = is_ptrs_symbol(l,
|
|
||||||
0,
|
|
||||||
n_rnti,
|
|
||||||
N_RB,
|
|
||||||
duration_in_symbols,
|
|
||||||
dmrs_antenna_port,
|
|
||||||
K_ptrs,
|
|
||||||
ptrs_symbols,
|
|
||||||
dmrs_Uplink_Config.pusch_dmrs_type,
|
|
||||||
&ptrs_Uplink_Config);
|
|
||||||
|
|
||||||
if (ptrs_symbol_flag == 1)
|
|
||||||
printf(" %d ", l);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n");
|
/* return the position of next ptrs symbol in a slot */
|
||||||
|
uint8_t get_next_ptrs_symbol_in_slot(uint16_t ptrs_symb_pos, uint8_t counter, uint8_t nb_symb)
|
||||||
printf("PTRS subcarrier indicies: ");
|
{
|
||||||
|
for(uint8_t symbol = counter; symbol < nb_symb; symbol++)
|
||||||
for (k = 0; k < N_RB*12; k++){
|
{
|
||||||
|
if((ptrs_symb_pos >>symbol)&0x01 )
|
||||||
if (is_ptrs_subcarrier(k, K_ptrs, n_rnti, N_RB, k_RE_ref) == 1)
|
{
|
||||||
printf(" %d ", k);
|
return symbol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
/* get the next nearest estimate from DMRS or PTRS */
|
||||||
|
uint8_t get_next_estimate_in_slot(uint16_t ptrsSymbPos,uint16_t dmrsSymbPos, uint8_t counter,uint8_t nb_symb)
|
||||||
|
{
|
||||||
|
uint8_t nextPtrs = get_next_ptrs_symbol_in_slot(ptrsSymbPos, counter,nb_symb);
|
||||||
|
uint8_t nextDmrs = get_next_dmrs_symbol_in_slot(dmrsSymbPos, counter,nb_symb);
|
||||||
|
if(nextDmrs == 0)
|
||||||
|
{
|
||||||
|
return nextPtrs;
|
||||||
|
}
|
||||||
|
return (nextPtrs > nextDmrs)?nextDmrs:nextPtrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
*
|
||||||
|
* NAME : nr_ptrs_cpe_estimation
|
||||||
|
*
|
||||||
|
* PARAMETERS : K_ptrs : K value for PTRS
|
||||||
|
* ptrsReOffset : RE offset for PTRS
|
||||||
|
* dmrsConfigType: DMRS configuration type
|
||||||
|
* nb_rb : No. of resource blocks
|
||||||
|
* rnti : RNTI
|
||||||
|
* ptrs_ch_p : pointer to ptrs channel structure
|
||||||
|
* Ns :
|
||||||
|
* symbol : OFDM symbol
|
||||||
|
* ofdm_symbol_size: OFDM Symbol Size
|
||||||
|
* rxF_comp : pointer to channel compensated signal
|
||||||
|
* gold_seq : Gold sequence pointer
|
||||||
|
* error_est : Estimated error output vector [Re Im]
|
||||||
|
* ptrs_sc : Total PTRS RE in a symbol
|
||||||
|
* RETURN : nothing
|
||||||
|
*
|
||||||
|
* DESCRIPTION :
|
||||||
|
* perform phase estimation from regenerated PTRS SC and channel compensated
|
||||||
|
* signal
|
||||||
|
*********************************************************************/
|
||||||
|
void nr_ptrs_cpe_estimation(uint8_t K_ptrs,
|
||||||
|
uint8_t ptrsReOffset,
|
||||||
|
uint8_t dmrsConfigType,
|
||||||
|
uint16_t nb_rb,
|
||||||
|
uint16_t rnti,
|
||||||
|
int16_t *ptrs_ch_p,
|
||||||
|
unsigned char Ns,
|
||||||
|
unsigned char symbol,
|
||||||
|
uint16_t ofdm_symbol_size,
|
||||||
|
int16_t *rxF_comp,
|
||||||
|
uint32_t *gold_seq,
|
||||||
|
int16_t *error_est,
|
||||||
|
int32_t *ptrs_sc)
|
||||||
|
{
|
||||||
|
//#define DEBUG_PTRS 1
|
||||||
|
uint8_t is_ptrs_re = 0;
|
||||||
|
uint16_t re_cnt = 0;
|
||||||
|
uint16_t cnt = 0;
|
||||||
|
unsigned short nb_re_pdsch = NR_NB_SC_PER_RB * nb_rb;
|
||||||
|
uint16_t sc_per_symbol = (nb_rb + K_ptrs - 1)/K_ptrs;
|
||||||
|
int16_t *ptrs_p = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol));
|
||||||
|
int16_t *dmrs_comp_p = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol));
|
||||||
|
double abs = 0.0;
|
||||||
|
double real = 0.0;
|
||||||
|
double imag = 0.0;
|
||||||
|
#ifdef DEBUG_PTRS
|
||||||
|
double alpha = 0;
|
||||||
|
#endif
|
||||||
|
/* generate PTRS RE for the symbol */
|
||||||
|
nr_gen_ref_conj_symbols(gold_seq,sc_per_symbol*2,ptrs_p, NR_MOD_TABLE_QPSK_OFFSET,2);// 2 for QPSK
|
||||||
|
|
||||||
|
/* loop over all sub carriers to get compensated RE on ptrs symbols*/
|
||||||
|
for (int re = 0; re < nb_re_pdsch; re++)
|
||||||
|
{
|
||||||
|
is_ptrs_re = is_ptrs_subcarrier(re,
|
||||||
|
rnti,
|
||||||
|
0,
|
||||||
|
dmrsConfigType,
|
||||||
|
K_ptrs,
|
||||||
|
nb_rb,
|
||||||
|
ptrsReOffset,
|
||||||
|
0,// start_re is 0 here
|
||||||
|
ofdm_symbol_size);
|
||||||
|
if(is_ptrs_re)
|
||||||
|
{
|
||||||
|
dmrs_comp_p[re_cnt*2] = rxF_comp[re *2];
|
||||||
|
dmrs_comp_p[(re_cnt*2)+1] = rxF_comp[(re *2)+1];
|
||||||
|
re_cnt++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Skip PTRS symbols and keep data in a continuous vector */
|
||||||
|
rxF_comp[cnt *2]= rxF_comp[re *2];
|
||||||
|
rxF_comp[(cnt *2)+1]= rxF_comp[(re *2)+1];
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}/* RE loop */
|
||||||
|
/* update the total ptrs RE in a symbol */
|
||||||
|
*ptrs_sc = re_cnt;
|
||||||
|
|
||||||
|
/*Multiple compensated data with conj of PTRS */
|
||||||
|
mult_cpx_vector(dmrs_comp_p, ptrs_p, ptrs_ch_p,(1 + sc_per_symbol/4)*4,15); // 2^15 shifted
|
||||||
|
|
||||||
|
/* loop over all ptrs sub carriers in a symbol */
|
||||||
|
/* sum the error vector */
|
||||||
|
for(int i = 0;i < sc_per_symbol; i++)
|
||||||
|
{
|
||||||
|
real+= ptrs_ch_p[(2*i)];
|
||||||
|
imag+= ptrs_ch_p[(2*i)+1];
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_PTRS
|
||||||
|
alpha = atan(imag/real);
|
||||||
|
printf("[PHY][PTRS]: Symbol %d atan(Im,real):= %f \n",symbol, alpha );
|
||||||
|
#endif
|
||||||
|
/* mean */
|
||||||
|
real /= sc_per_symbol;
|
||||||
|
imag /= sc_per_symbol;
|
||||||
|
/* absolute calculation */
|
||||||
|
abs = sqrt(((real * real) + (imag * imag)));
|
||||||
|
/* normalized error estimation */
|
||||||
|
error_est[0]= (real / abs)*(1<<15);
|
||||||
|
/* compensation in given by conjugate of estimated phase (e^-j*2*pi*fd*t)*/
|
||||||
|
error_est[1]= (-1)*(imag / abs)*(1<<15);
|
||||||
|
#ifdef DEBUG_PTRS
|
||||||
|
printf("[PHY][PTRS]: Estimated Symbol %d -> %d + j* %d \n",symbol, error_est[0], error_est[1] );
|
||||||
|
#endif
|
||||||
|
/* free vectors */
|
||||||
|
free(ptrs_p);
|
||||||
|
free(dmrs_comp_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
*
|
||||||
|
* NAME : nr_ptrs_process_slot
|
||||||
|
*
|
||||||
|
* PARAMETERS : dmrsSymbPos DMRS symbol index mask per slot
|
||||||
|
* ptrsSymbpos PTRS symbol index mask per slot
|
||||||
|
* estPerSymb Estimated CPE pointer
|
||||||
|
* startSymbIdx First symbol index in a slot
|
||||||
|
* noSymb total number of OFDM symbols in a slot
|
||||||
|
* RETURN : True if slot is process correctly
|
||||||
|
* DESCRIPTION :
|
||||||
|
* Process whole slot and interpolate or extrapolate estimation for the symbols
|
||||||
|
* where there is neither PTRS nor DMRS configured
|
||||||
|
*
|
||||||
|
*********************************************************************/
|
||||||
|
int8_t nr_ptrs_process_slot(uint16_t dmrsSymbPos,
|
||||||
|
uint16_t ptrsSymbPos,
|
||||||
|
int16_t *estPerSymb,
|
||||||
|
uint16_t startSymbIdx,
|
||||||
|
uint16_t noSymb)
|
||||||
|
{
|
||||||
|
int32_t slope = 0;
|
||||||
|
int16_t *slope_p = (int16_t*)&slope;
|
||||||
|
uint8_t symbInSlot = startSymbIdx + noSymb;
|
||||||
|
uint8_t rightRef = 0;
|
||||||
|
uint8_t leftRef = 0;
|
||||||
|
uint8_t tmp = 0;
|
||||||
|
for(uint8_t symb = startSymbIdx; symb <symbInSlot; symb ++)
|
||||||
|
{
|
||||||
|
/* set DMRS estimates to 0 angle with magnitude 1 */
|
||||||
|
if(is_dmrs_symbol(symb,dmrsSymbPos))
|
||||||
|
{
|
||||||
|
/* set DMRS estimation */
|
||||||
|
estPerSymb[symb*2]=(int16_t)((1<<15)-1); // 32767
|
||||||
|
estPerSymb[(symb*2)+1]= 0; // no angle
|
||||||
|
}
|
||||||
|
/* Update left and right reference from an estimated symbol */
|
||||||
|
if((is_ptrs_symbol(symb, ptrsSymbPos)) || (is_dmrs_symbol(symb,dmrsSymbPos)))
|
||||||
|
{
|
||||||
|
leftRef = symb;
|
||||||
|
rightRef = get_next_estimate_in_slot(ptrsSymbPos,dmrsSymbPos,symb+1,symbInSlot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The very first symbol must be a PTRS or DMRS */
|
||||||
|
if((symb == startSymbIdx) && (leftRef == 0) && (rightRef == 0))
|
||||||
|
{
|
||||||
|
printf("Wrong PTRS Setup, PTRS compensation will be skipped !");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* check for left side first */
|
||||||
|
/* right side a DMRS symbol then we need to left extrapolate */
|
||||||
|
if(is_dmrs_symbol(rightRef,dmrsSymbPos))
|
||||||
|
{
|
||||||
|
/* calculate slope from next valid estimates*/
|
||||||
|
tmp = get_next_estimate_in_slot(ptrsSymbPos,dmrsSymbPos,rightRef+1,symbInSlot);
|
||||||
|
get_slope_from_estimates(rightRef, tmp, estPerSymb, slope_p);
|
||||||
|
ptrs_estimate_from_slope(estPerSymb,slope_p,leftRef, rightRef);
|
||||||
|
symb = rightRef -1;
|
||||||
|
}
|
||||||
|
else if(is_ptrs_symbol(rightRef,ptrsSymbPos))
|
||||||
|
{
|
||||||
|
/* calculate slope from next valid estimates*/
|
||||||
|
get_slope_from_estimates(leftRef,rightRef,estPerSymb, slope_p);
|
||||||
|
ptrs_estimate_from_slope(estPerSymb,slope_p,leftRef, rightRef);
|
||||||
|
symb = rightRef -1;
|
||||||
|
}
|
||||||
|
else if((rightRef ==0) && (symb <symbInSlot))
|
||||||
|
{
|
||||||
|
// in right extrapolation use the last slope
|
||||||
|
#ifdef DEBUG_PTRS
|
||||||
|
printf("[PHY][PTRS]: Last Slop Reused :(%4d %4d)\n", slope_p[0],slope_p[1]);
|
||||||
|
#endif
|
||||||
|
ptrs_estimate_from_slope(estPerSymb,slope_p,symb-1,symbInSlot);
|
||||||
|
symb = symbInSlot;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Wrong PTRS Setup, PTRS compensation will be skipped !");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate slope from 2 reference points */
|
||||||
|
void get_slope_from_estimates(uint8_t start, uint8_t end, int16_t *est_p, int16_t *slope_p)
|
||||||
|
{
|
||||||
|
uint8_t distance = end - start;
|
||||||
|
slope_p[0] = (((double)(est_p[end*2]) - (double)(est_p[start*2])) /(double)distance);
|
||||||
|
slope_p[1] = (((double)(est_p[(end*2)+1]) - (double)(est_p[(start*2)+1])) /(double)distance);
|
||||||
|
#ifdef DEBUG_PTRS
|
||||||
|
printf("[PHY][PTRS]: Slop is :(%4d %4d) between Symbol %2d & Symbol %2d\n", slope_p[0],slope_p[1], start, end);
|
||||||
|
//printf("%d %d - %d %d\n",est_p[end*2],est_p[(end*2)+1],est_p[start*2],est_p[(start*2)+1]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* estimate from slope */
|
||||||
|
void ptrs_estimate_from_slope(int16_t *error_est, int16_t *slope_p, uint8_t start, uint8_t end)
|
||||||
|
{
|
||||||
|
for(uint8_t i = 1; i< (end -start);i++)
|
||||||
|
{
|
||||||
|
error_est[(start+i)*2] = 8 * (((double)(error_est[start*2]) * 0.125 ) + ((double)(0.125 * i * slope_p[0])));// real
|
||||||
|
error_est[((start +i)*2)+1] = 8 * (((double)(error_est[(start*2)+1]) * 0.125) + ((double)(0.125 * i * slope_p[1]))); //imag
|
||||||
|
#ifdef DEBUG_PTRS
|
||||||
|
printf("[PHY][PTRS]: Estimated Symbol %2d -> %4d %4d from Slope (%4d %4d)\n", start+i,error_est[(start+i)*2],error_est[((start +i)*2)+1],
|
||||||
|
slope_p[0],slope_p[1]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -80,6 +80,31 @@ uint8_t is_ptrs_subcarrier(uint16_t k,
|
|||||||
|
|
||||||
static inline uint8_t is_ptrs_symbol(uint8_t l, uint16_t ptrs_symbols) { return ((ptrs_symbols >> l) & 1); }
|
static inline uint8_t is_ptrs_symbol(uint8_t l, uint16_t ptrs_symbols) { return ((ptrs_symbols >> l) & 1); }
|
||||||
|
|
||||||
|
uint8_t get_ptrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t start_symb, uint16_t nb_symb);
|
||||||
|
uint8_t get_next_ptrs_symbol_in_slot(uint16_t ptrsSymbPos, uint8_t counter, uint8_t nb_symb);
|
||||||
|
uint8_t get_next_estimate_in_slot(uint16_t ptrsSymbPos,uint16_t dmrsSymbPos, uint8_t counter,uint8_t nb_symb);
|
||||||
|
void get_slope_from_estimates(uint8_t leftSide, uint8_t rightSide, int16_t *est_p, int16_t *slope_p);
|
||||||
|
int8_t nr_ptrs_process_slot(uint16_t dmrsSymbPos,
|
||||||
|
uint16_t ptrsSymbPos,
|
||||||
|
int16_t *estPerSymb,
|
||||||
|
uint16_t startSymbIdx,
|
||||||
|
uint16_t noSymb
|
||||||
|
);
|
||||||
|
/* general function to estimate common phase error based upon PTRS */
|
||||||
|
void nr_ptrs_cpe_estimation(uint8_t K_ptrs,
|
||||||
|
uint8_t ptrsReOffset,
|
||||||
|
uint8_t dmrsConfigType,
|
||||||
|
uint16_t nb_rb,
|
||||||
|
uint16_t rnti,
|
||||||
|
int16_t *ptrs_ch_p,
|
||||||
|
unsigned char Ns,
|
||||||
|
unsigned char symbol,
|
||||||
|
uint16_t ofdm_symbol_size,
|
||||||
|
int16_t *rxF_comp,
|
||||||
|
uint32_t *gold_seq,
|
||||||
|
int16_t *error_est,
|
||||||
|
int32_t *ptrs_sc);
|
||||||
|
|
||||||
|
void get_slope_from_estimates(uint8_t start, uint8_t end, int16_t *est_p, int16_t *slope_p);
|
||||||
|
void ptrs_estimate_from_slope(int16_t *error_est, int16_t *slope_p, uint8_t start, uint8_t end);
|
||||||
#endif /* PTRS_NR_H */
|
#endif /* PTRS_NR_H */
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
#include "SCHED_NR_UE/defs.h"
|
#include "SCHED_NR_UE/defs.h"
|
||||||
#include "nr_estimation.h"
|
#include "nr_estimation.h"
|
||||||
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
||||||
|
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||||
|
#include "PHY/NR_REFSIG/ptrs_nr.h"
|
||||||
#include "filt16a_32.h"
|
#include "filt16a_32.h"
|
||||||
|
|
||||||
//#define DEBUG_PDSCH
|
//#define DEBUG_PDSCH
|
||||||
@@ -937,3 +939,171 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
*
|
||||||
|
* NAME : nr_pdsch_ptrs_processing
|
||||||
|
*
|
||||||
|
* PARAMETERS : ue : ue data structure
|
||||||
|
* NR_UE_PDSCH : pdsch_vars pointer
|
||||||
|
* NR_DL_FRAME_PARMS : frame_parms pointer
|
||||||
|
* NR_DL_UE_HARQ_t : dlsch0_harq pointer
|
||||||
|
* NR_DL_UE_HARQ_t : dlsch1_harq pointer
|
||||||
|
* uint8_t : eNB_id,
|
||||||
|
* uint8_t : nr_tti_rx,
|
||||||
|
* unsigned char : symbol,
|
||||||
|
* uint32_t : nb_re_pdsch,
|
||||||
|
* unsigned char : harq_pid
|
||||||
|
* uint16_t : rnti
|
||||||
|
* RX_type_t : rx_type
|
||||||
|
* RETURN : Nothing
|
||||||
|
*
|
||||||
|
* DESCRIPTION :
|
||||||
|
* If ptrs is enabled process the symbol accordingly
|
||||||
|
* 1) Estimate common phase error per PTRS symbol
|
||||||
|
* 2) Interpolate PTRS estimated value in TD after all PTRS symbols
|
||||||
|
* 3) Compensate signal with PTRS estimation for slot
|
||||||
|
*********************************************************************/
|
||||||
|
void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
|
||||||
|
NR_UE_PDSCH **pdsch_vars,
|
||||||
|
NR_DL_FRAME_PARMS *frame_parms,
|
||||||
|
NR_DL_UE_HARQ_t *dlsch0_harq,
|
||||||
|
NR_DL_UE_HARQ_t *dlsch1_harq,
|
||||||
|
uint8_t eNB_id,
|
||||||
|
uint8_t nr_tti_rx,
|
||||||
|
unsigned char symbol,
|
||||||
|
uint32_t nb_re_pdsch,
|
||||||
|
unsigned char harq_pid,
|
||||||
|
uint16_t rnti,
|
||||||
|
RX_type_t rx_type)
|
||||||
|
{
|
||||||
|
//#define DEBUG_DL_PTRS 1
|
||||||
|
int16_t *phase_per_symbol = NULL;
|
||||||
|
int32_t *ptrs_re_symbol = NULL;
|
||||||
|
int8_t ret = 0;
|
||||||
|
/* harq specific variables */
|
||||||
|
uint8_t symbInSlot = 0;
|
||||||
|
uint16_t *startSymbIndex = NULL;
|
||||||
|
uint16_t *nbSymb = NULL;
|
||||||
|
uint8_t *L_ptrs = NULL;
|
||||||
|
uint8_t *K_ptrs = NULL;
|
||||||
|
uint16_t *dmrsSymbPos = NULL;
|
||||||
|
uint16_t *ptrsSymbPos = NULL;
|
||||||
|
uint8_t *ptrsSymbIdx = NULL;
|
||||||
|
uint8_t *ptrsReOffset = NULL;
|
||||||
|
uint8_t *dmrsConfigType = NULL;
|
||||||
|
uint16_t *nb_rb = NULL;
|
||||||
|
|
||||||
|
if(dlsch0_harq->status == ACTIVE)
|
||||||
|
{
|
||||||
|
symbInSlot = dlsch0_harq->start_symbol + dlsch0_harq->nb_symbols;
|
||||||
|
startSymbIndex = &dlsch0_harq->start_symbol;
|
||||||
|
nbSymb = &dlsch0_harq->nb_symbols;
|
||||||
|
L_ptrs = &dlsch0_harq->PTRSTimeDensity;
|
||||||
|
K_ptrs = &dlsch0_harq->PTRSFreqDensity;
|
||||||
|
dmrsSymbPos = &dlsch0_harq->dlDmrsSymbPos;
|
||||||
|
ptrsSymbPos = &dlsch0_harq->ptrs_symbols;
|
||||||
|
ptrsSymbIdx = &dlsch0_harq->ptrs_symbol_index;
|
||||||
|
ptrsReOffset = &dlsch0_harq->PTRSReOffset;
|
||||||
|
dmrsConfigType = &dlsch0_harq->ptrs_symbol_index;
|
||||||
|
nb_rb = &dlsch0_harq->nb_rb;
|
||||||
|
}
|
||||||
|
if(dlsch1_harq)
|
||||||
|
{
|
||||||
|
symbInSlot = dlsch1_harq->start_symbol + dlsch0_harq->nb_symbols;
|
||||||
|
startSymbIndex = &dlsch1_harq->start_symbol;
|
||||||
|
nbSymb = &dlsch1_harq->nb_symbols;
|
||||||
|
L_ptrs = &dlsch1_harq->PTRSTimeDensity;
|
||||||
|
K_ptrs = &dlsch1_harq->PTRSFreqDensity;
|
||||||
|
dmrsSymbPos = &dlsch1_harq->dlDmrsSymbPos;
|
||||||
|
ptrsSymbPos = &dlsch1_harq->ptrs_symbols;
|
||||||
|
ptrsSymbIdx = &dlsch1_harq->ptrs_symbol_index;
|
||||||
|
ptrsReOffset = &dlsch1_harq->PTRSReOffset;
|
||||||
|
dmrsConfigType = &dlsch1_harq->ptrs_symbol_index;
|
||||||
|
nb_rb = &dlsch1_harq->nb_rb;
|
||||||
|
}
|
||||||
|
/* loop over antennas */
|
||||||
|
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
|
||||||
|
{
|
||||||
|
phase_per_symbol = (int16_t*)pdsch_vars[eNB_id]->ptrs_phase_per_slot[aarx];
|
||||||
|
ptrs_re_symbol = (int32_t*)pdsch_vars[eNB_id]->ptrs_re_per_slot[aarx];
|
||||||
|
ptrs_re_symbol[symbol] = 0;
|
||||||
|
phase_per_symbol[2*symbol] = 0; // Real
|
||||||
|
phase_per_symbol[(2*symbol)+1] = 0; // Imag
|
||||||
|
if(dlsch0_harq->status == ACTIVE)
|
||||||
|
{
|
||||||
|
if(symbol == *startSymbIndex)
|
||||||
|
{
|
||||||
|
*ptrsSymbPos = 0;
|
||||||
|
set_ptrs_symb_idx(ptrsSymbPos,
|
||||||
|
*nbSymb,
|
||||||
|
*startSymbIndex,
|
||||||
|
1<< *L_ptrs,
|
||||||
|
*dmrsSymbPos);
|
||||||
|
}
|
||||||
|
/* if not PTRS symbol set current ptrs symbol index to zero*/
|
||||||
|
*ptrsSymbIdx = 0;
|
||||||
|
/* Check if current symbol contains PTRS */
|
||||||
|
if(is_ptrs_symbol(symbol, *ptrsSymbPos))
|
||||||
|
{
|
||||||
|
*ptrsSymbIdx = symbol;
|
||||||
|
/*------------------------------------------------------------------------------------------------------- */
|
||||||
|
/* 1) Estimate common phase error per PTRS symbol */
|
||||||
|
/*------------------------------------------------------------------------------------------------------- */
|
||||||
|
nr_ptrs_cpe_estimation(*K_ptrs,*ptrsReOffset,*dmrsConfigType,*nb_rb,
|
||||||
|
rnti,
|
||||||
|
(int16_t *)&pdsch_vars[eNB_id]->dl_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pdsch],
|
||||||
|
nr_tti_rx,
|
||||||
|
symbol,frame_parms->ofdm_symbol_size,
|
||||||
|
(int16_t*)&pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(symbol * nb_re_pdsch)],
|
||||||
|
ue->nr_gold_pdsch[eNB_id][nr_tti_rx][symbol],
|
||||||
|
&phase_per_symbol[2* symbol],
|
||||||
|
&ptrs_re_symbol[symbol]);
|
||||||
|
/* if very first symbol is PTRS then we need to undo conjugate done in estimation */
|
||||||
|
if(symbol == *startSymbIndex)
|
||||||
|
{
|
||||||
|
phase_per_symbol[(2* symbol)+1] = (-1) * phase_per_symbol[(2* symbol)+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}// HARQ 0
|
||||||
|
|
||||||
|
/* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/
|
||||||
|
if(symbol == (symbInSlot -1))
|
||||||
|
{
|
||||||
|
/*------------------------------------------------------------------------------------------------------- */
|
||||||
|
/* 2) Interpolate PTRS estimated value in TD */
|
||||||
|
/*------------------------------------------------------------------------------------------------------- */
|
||||||
|
/* If L-PTRS is > 0 then we need interpolation */
|
||||||
|
if(*L_ptrs > 0)
|
||||||
|
{
|
||||||
|
ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, phase_per_symbol, *startSymbIndex, *nbSymb);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_DL_PTRS
|
||||||
|
LOG_M("ptrsEst.m","est",pdsch_vars[eNB_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
|
||||||
|
LOG_M("rxdataF_bf_ptrs_comp.m","bf_ptrs_cmp",
|
||||||
|
&pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(*startSymbIndex) * NR_NB_SC_PER_RB * (*nb_rb) ],
|
||||||
|
(*nb_rb) * NR_NB_SC_PER_RB * (*nbSymb),1,1);
|
||||||
|
#endif
|
||||||
|
/*------------------------------------------------------------------------------------------------------- */
|
||||||
|
/* 3) Compensated DMRS based estimated signal with PTRS estimation */
|
||||||
|
/*--------------------------------------------------------------------------------------------------------*/
|
||||||
|
for(uint8_t i = *startSymbIndex; i< symbInSlot ;i++)
|
||||||
|
{
|
||||||
|
/* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
|
||||||
|
if(!is_dmrs_symbol(i,*dmrsSymbPos))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_DL_PTRS
|
||||||
|
printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]);
|
||||||
|
#endif
|
||||||
|
rotate_cpx_vector((int16_t*)&pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)],
|
||||||
|
&phase_per_symbol[2* i],
|
||||||
|
(int16_t*)&pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)],
|
||||||
|
((*nb_rb) * NR_NB_SC_PER_RB), 15);
|
||||||
|
}// if not DMRS Symbol
|
||||||
|
}// symbol loop
|
||||||
|
}// last symbol check
|
||||||
|
}//Antenna loop
|
||||||
|
}//main function
|
||||||
|
|||||||
@@ -93,5 +93,17 @@ void phy_adjust_gain_nr(PHY_VARS_NR_UE *ue,
|
|||||||
|
|
||||||
int16_t get_nr_PL(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index);
|
int16_t get_nr_PL(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index);
|
||||||
|
|
||||||
|
void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
|
||||||
|
NR_UE_PDSCH **pdsch_vars,
|
||||||
|
NR_DL_FRAME_PARMS *frame_parms,
|
||||||
|
NR_DL_UE_HARQ_t *dlsch0_harq,
|
||||||
|
NR_DL_UE_HARQ_t *dlsch1_harq,
|
||||||
|
uint8_t eNB_id,
|
||||||
|
uint8_t nr_tti_rx,
|
||||||
|
unsigned char symbol,
|
||||||
|
uint32_t nb_re_pdsch,
|
||||||
|
unsigned char harq_pid,
|
||||||
|
uint16_t rnti,
|
||||||
|
RX_type_t rx_type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
//#include "extern.h"
|
//#include "extern.h"
|
||||||
#include "PHY/sse_intrin.h"
|
#include "PHY/sse_intrin.h"
|
||||||
#include "T.h"
|
#include "T.h"
|
||||||
|
#include "openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||||
#include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h"
|
#include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||||
|
|
||||||
#ifndef USER_MODE
|
#ifndef USER_MODE
|
||||||
@@ -140,12 +141,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
|||||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||||
PHY_NR_MEASUREMENTS *measurements = &ue->measurements;
|
PHY_NR_MEASUREMENTS *measurements = &ue->measurements;
|
||||||
NR_UE_DLSCH_t **dlsch;
|
NR_UE_DLSCH_t **dlsch;
|
||||||
uint16_t startSymbIdx=0;
|
|
||||||
uint16_t nbSymb=0;
|
|
||||||
|
|
||||||
int avg[4];
|
int avg[4];
|
||||||
// int avg_0[2];
|
// int avg_0[2];
|
||||||
// int avg_1[2];
|
// int avg_1[2];
|
||||||
|
|
||||||
#if UE_TIMING_TRACE
|
#if UE_TIMING_TRACE
|
||||||
uint8_t slot = 0;
|
uint8_t slot = 0;
|
||||||
@@ -174,6 +173,9 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
|||||||
uint16_t n_tx=1, n_rx=1;
|
uint16_t n_tx=1, n_rx=1;
|
||||||
int32_t median[16];
|
int32_t median[16];
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
uint16_t startSymbIdx=0;
|
||||||
|
uint16_t nbSymb=0;
|
||||||
|
uint16_t pduBitmap=0x0;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SI_PDSCH:
|
case SI_PDSCH:
|
||||||
@@ -693,49 +695,56 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
|||||||
{
|
{
|
||||||
startSymbIdx = dlsch0_harq->start_symbol;
|
startSymbIdx = dlsch0_harq->start_symbol;
|
||||||
nbSymb = dlsch0_harq->nb_symbols;
|
nbSymb = dlsch0_harq->nb_symbols;
|
||||||
|
pduBitmap = dlsch0_harq->pduBitmap;
|
||||||
}
|
}
|
||||||
if(dlsch1_harq)
|
if(dlsch1_harq)
|
||||||
{
|
{
|
||||||
startSymbIdx = dlsch1_harq->start_symbol;
|
startSymbIdx = dlsch1_harq->start_symbol;
|
||||||
nbSymb = dlsch1_harq->nb_symbols;
|
nbSymb = dlsch1_harq->nb_symbols;
|
||||||
|
pduBitmap = dlsch1_harq->pduBitmap;
|
||||||
}
|
}
|
||||||
//printf("LLR dlsch0_harq->Qm %d rx_type %d cw0 %d cw1 %d symbol %d \n",dlsch0_harq->Qm,rx_type,codeword_TB0,codeword_TB1,symbol);
|
|
||||||
// compute LLRs
|
/* Check for PTRS bitmap and process it respectively */
|
||||||
// -> // compute @pointer where llrs should filled for this ofdm-symbol
|
if((pduBitmap & 0x1) && (type == PDSCH))
|
||||||
|
{
|
||||||
|
nr_pdsch_ptrs_processing(ue,
|
||||||
|
pdsch_vars,
|
||||||
|
frame_parms,
|
||||||
|
dlsch0_harq, dlsch1_harq,
|
||||||
|
eNB_id, nr_tti_rx,
|
||||||
|
symbol, (nb_rb*12),
|
||||||
|
harq_pid,
|
||||||
|
dlsch[0]->rnti,rx_type);
|
||||||
|
pdsch_vars[eNB_id]->dl_valid_re[symbol-1] -= pdsch_vars[eNB_id]->ptrs_re_per_slot[0][symbol];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* at last symbol in a slot calculate LLR's for whole slot */
|
||||||
if(symbol == (startSymbIdx + nbSymb -1))
|
if(symbol == (startSymbIdx + nbSymb -1))
|
||||||
{
|
{
|
||||||
for(uint8_t i =startSymbIdx; i <= nbSymb;i++)
|
for(uint8_t i =startSymbIdx; i <= nbSymb;i++)
|
||||||
{
|
{
|
||||||
/* re evaluating the first symbol flag as LLR's are done in symbol loop */
|
/* re evaluating the first symbol flag as LLR's are done in symbol loop */
|
||||||
if(i == startSymbIdx && i < 3)
|
if(i == startSymbIdx && i < 3)
|
||||||
{
|
{
|
||||||
first_symbol_flag =1;
|
first_symbol_flag =1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
first_symbol_flag=0;
|
first_symbol_flag=0;
|
||||||
}
|
}
|
||||||
/* Calculate LLR's for ech symbol */
|
/* Calculate LLR's for each symbol */
|
||||||
nr_dlsch_llr(pdsch_vars,
|
nr_dlsch_llr(pdsch_vars, frame_parms,
|
||||||
frame_parms,
|
rxdataF_comp_ptr, dl_ch_mag_ptr,
|
||||||
rxdataF_comp_ptr,
|
dlsch0_harq, dlsch1_harq,
|
||||||
dl_ch_mag_ptr,
|
rx_type, harq_pid,
|
||||||
dlsch0_harq,
|
eNB_id, eNB_id_i,
|
||||||
dlsch1_harq,
|
|
||||||
rx_type,
|
|
||||||
harq_pid,
|
|
||||||
eNB_id,
|
|
||||||
eNB_id_i,
|
|
||||||
first_symbol_flag,
|
first_symbol_flag,
|
||||||
i,
|
i, nb_rb, round,
|
||||||
nb_rb,
|
codeword_TB0, codeword_TB1,
|
||||||
round,
|
|
||||||
codeword_TB0,
|
|
||||||
codeword_TB1,
|
|
||||||
pdsch_vars[eNB_id]->dl_valid_re[i-1],
|
pdsch_vars[eNB_id]->dl_valid_re[i-1],
|
||||||
nr_tti_rx,
|
nr_tti_rx, beamforming_mode);
|
||||||
beamforming_mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//nr_dlsch_deinterleaving(symbol,bundle_L,(int16_t*)pllr_symbol_cw0,(int16_t*)pllr_symbol_cw0_deint, nb_rb_pdsch);
|
//nr_dlsch_deinterleaving(symbol,bundle_L,(int16_t*)pllr_symbol_cw0,(int16_t*)pllr_symbol_cw0_deint, nb_rb_pdsch);
|
||||||
if (rx_type==rx_IC_dual_stream) {
|
if (rx_type==rx_IC_dual_stream) {
|
||||||
nr_dlsch_layer_demapping(pdsch_vars[eNB_id]->llr,
|
nr_dlsch_layer_demapping(pdsch_vars[eNB_id]->llr,
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
#include "openair1/SIMULATION/TOOLS/sim.h"
|
#include "openair1/SIMULATION/TOOLS/sim.h"
|
||||||
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
|
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
|
||||||
//#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
|
//#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
|
||||||
|
#include "PHY/NR_REFSIG/ptrs_nr.h"
|
||||||
#include "NR_RRCReconfiguration.h"
|
#include "NR_RRCReconfiguration.h"
|
||||||
#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0))
|
#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0))
|
||||||
#include "SIMULATION/LTE_PHY/common_sim.h"
|
#include "SIMULATION/LTE_PHY/common_sim.h"
|
||||||
@@ -143,8 +143,7 @@ int generate_dlsch_header(unsigned char *mac_header,
|
|||||||
// needed for some functions
|
// needed for some functions
|
||||||
openair0_config_t openair0_cfg[MAX_CARDS];
|
openair0_config_t openair0_cfg[MAX_CARDS];
|
||||||
|
|
||||||
|
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, uint8_t *K_ptrs, uint8_t *L_ptrs);
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -214,6 +213,16 @@ int main(int argc, char **argv)
|
|||||||
int css_flag=0;
|
int css_flag=0;
|
||||||
|
|
||||||
cpuf = get_cpu_freq_GHz();
|
cpuf = get_cpu_freq_GHz();
|
||||||
|
int enable_ptrs = 0;
|
||||||
|
|
||||||
|
/* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */
|
||||||
|
uint8_t ptrs_arg[2] = {-1,-1};// Invalid values
|
||||||
|
uint16_t ptrsRePerSymb = 0;
|
||||||
|
uint16_t pdu_bit_map = 0x0;
|
||||||
|
uint16_t dlPtrsSymPos = 0;
|
||||||
|
uint16_t ptrsSymbPerSlot = 0;
|
||||||
|
uint16_t rbSize = 106;
|
||||||
|
uint8_t mcsIndex = 9;
|
||||||
|
|
||||||
if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
|
if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
|
||||||
exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
|
exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
|
||||||
@@ -226,7 +235,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
FILE *scg_fd=NULL;
|
FILE *scg_fd=NULL;
|
||||||
|
|
||||||
while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:e:m:w")) != -1) {
|
while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:e:m:w:T:")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'f':
|
case 'f':
|
||||||
scg_fd = fopen(optarg,"r");
|
scg_fd = fopen(optarg,"r");
|
||||||
@@ -409,9 +418,16 @@ int main(int argc, char **argv)
|
|||||||
eff_tp_check = (float)atoi(optarg)/100;
|
eff_tp_check = (float)atoi(optarg)/100;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case 'w':
|
||||||
output_fd = fopen("txdata.dat", "w+");
|
output_fd = fopen("txdata.dat", "w+");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
enable_ptrs=1;
|
||||||
|
for(i=0; i < atoi(optarg); i++){
|
||||||
|
ptrs_arg[i] = atoi(argv[optind++]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case 'h':
|
case 'h':
|
||||||
@@ -443,6 +459,7 @@ int main(int argc, char **argv)
|
|||||||
printf("-j Number of symbols for PDSCH (fixed for now)\n");
|
printf("-j Number of symbols for PDSCH (fixed for now)\n");
|
||||||
printf("-e MSC index\n");
|
printf("-e MSC index\n");
|
||||||
printf("-t Acceptable effective throughput (in percentage)\n");
|
printf("-t Acceptable effective throughput (in percentage)\n");
|
||||||
|
printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n");
|
||||||
printf("-P Print DLSCH performances\n");
|
printf("-P Print DLSCH performances\n");
|
||||||
printf("-w Write txdata to binary file (one frame)\n");
|
printf("-w Write txdata to binary file (one frame)\n");
|
||||||
exit (-1);
|
exit (-1);
|
||||||
@@ -539,7 +556,14 @@ int main(int argc, char **argv)
|
|||||||
0);
|
0);
|
||||||
fix_scc(scc,ssb_bitmap);
|
fix_scc(scc,ssb_bitmap);
|
||||||
|
|
||||||
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
|
/* -T option enable PTRS */
|
||||||
|
if(enable_ptrs)
|
||||||
|
{
|
||||||
|
printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<<ptrs_arg[0], ptrs_arg[1] );
|
||||||
|
update_ptrs_config(secondaryCellGroup, &rbSize, &mcsIndex, &ptrs_arg[1], &ptrs_arg[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
|
||||||
|
|
||||||
AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface");
|
AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface");
|
||||||
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||||
@@ -792,7 +816,22 @@ int main(int argc, char **argv)
|
|||||||
Sched_INFO.UL_dci_req = NULL;
|
Sched_INFO.UL_dci_req = NULL;
|
||||||
Sched_INFO.TX_req = &gNB_mac->TX_req[0];
|
Sched_INFO.TX_req = &gNB_mac->TX_req[0];
|
||||||
nr_schedule_response(&Sched_INFO);
|
nr_schedule_response(&Sched_INFO);
|
||||||
|
|
||||||
|
/* PTRS values for DLSIM calculations */
|
||||||
|
nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[Sched_INFO.CC_id].dl_tti_request_body;
|
||||||
|
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1];
|
||||||
|
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
|
||||||
|
pdu_bit_map = pdsch_pdu_rel15->pduBitmap;
|
||||||
|
if(pdu_bit_map & 0x1){
|
||||||
|
set_ptrs_symb_idx(&dlPtrsSymPos,
|
||||||
|
pdsch_pdu_rel15->NrOfSymbols,
|
||||||
|
pdsch_pdu_rel15->StartSymbolIndex,
|
||||||
|
1<<pdsch_pdu_rel15->PTRSTimeDensity,
|
||||||
|
pdsch_pdu_rel15->dlDmrsSymbPos);
|
||||||
|
ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, pdsch_pdu_rel15->StartSymbolIndex, pdsch_pdu_rel15->NrOfSymbols);
|
||||||
|
ptrsRePerSymb = ((rel15->rbSize + rel15->PTRSFreqDensity - 1)/rel15->PTRSFreqDensity);
|
||||||
|
printf("[DLSIM] PTRS Symbols in a slot: %2d, RE per Symbol: %3d, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb );
|
||||||
|
}
|
||||||
if (run_initial_sync)
|
if (run_initial_sync)
|
||||||
nr_common_signal_procedures(gNB,frame,slot);
|
nr_common_signal_procedures(gNB,frame,slot);
|
||||||
else
|
else
|
||||||
@@ -876,7 +915,7 @@ int main(int argc, char **argv)
|
|||||||
r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
|
r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size);
|
||||||
//AWGN
|
//AWGN
|
||||||
sigma2_dB = 10 * log10((double)txlev * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
|
sigma2_dB = 10 * log10((double)txlev * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
|
||||||
sigma2 = pow(10, sigma2_dB/10);
|
sigma2 = pow(10, sigma2_dB/10);
|
||||||
@@ -889,6 +928,12 @@ int main(int argc, char **argv)
|
|||||||
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||||
((short*) UE->common_vars.rxdata[aa])[2*i] = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
|
((short*) UE->common_vars.rxdata[aa])[2*i] = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
|
||||||
((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
|
((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
|
||||||
|
/* Add phase noise if enabled */
|
||||||
|
if (pdu_bit_map & 0x1)
|
||||||
|
{
|
||||||
|
phase_noise(ts, &((short*) UE->common_vars.rxdata[aa])[2*i],
|
||||||
|
&((short*) UE->common_vars.rxdata[aa])[2*i+1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -923,6 +968,11 @@ int main(int argc, char **argv)
|
|||||||
uint8_t nb_symb_sch = rel15->NrOfSymbols;
|
uint8_t nb_symb_sch = rel15->NrOfSymbols;
|
||||||
|
|
||||||
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers);
|
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers);
|
||||||
|
if(pdu_bit_map & 0x1)
|
||||||
|
{
|
||||||
|
available_bits-= (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2);
|
||||||
|
printf("[DLSIM][PTRS] Available bits are: %5d, removed PTRS bits are: %5d \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2) );
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < available_bits; i++) {
|
for (i = 0; i < available_bits; i++) {
|
||||||
|
|
||||||
@@ -1084,3 +1134,57 @@ int main(int argc, char **argv)
|
|||||||
return(n_errors);
|
return(n_errors);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, uint8_t *K_ptrs, uint8_t *L_ptrs)
|
||||||
|
{
|
||||||
|
NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
|
||||||
|
int *ptrsFreqDenst = calloc(2, sizeof(long));
|
||||||
|
ptrsFreqDenst[0]= 25;
|
||||||
|
ptrsFreqDenst[1]= 115;
|
||||||
|
int *ptrsTimeDenst = calloc(3, sizeof(long));
|
||||||
|
ptrsTimeDenst[0]= 2;
|
||||||
|
ptrsTimeDenst[1]= 4;
|
||||||
|
ptrsTimeDenst[2]= 10;
|
||||||
|
|
||||||
|
int epre_Ratio = 0;
|
||||||
|
int reOffset = 0;
|
||||||
|
|
||||||
|
if(*L_ptrs ==0)
|
||||||
|
{
|
||||||
|
ptrsTimeDenst[2]= *mcsIndex -1;
|
||||||
|
}
|
||||||
|
else if(*L_ptrs == 1)
|
||||||
|
{
|
||||||
|
ptrsTimeDenst[1]= *mcsIndex - 1;
|
||||||
|
ptrsTimeDenst[2]= *mcsIndex + 1;
|
||||||
|
}
|
||||||
|
else if(*L_ptrs ==2)
|
||||||
|
{
|
||||||
|
ptrsTimeDenst[0]= *mcsIndex - 1;
|
||||||
|
ptrsTimeDenst[1]= *mcsIndex + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("[DLSIM] Wrong L_PTRS value, using default values 1\n");
|
||||||
|
}
|
||||||
|
/* L = 4 if Imcs < MCS4 */
|
||||||
|
if(*K_ptrs ==2)
|
||||||
|
{
|
||||||
|
ptrsFreqDenst[0]= *rbSize - 1;
|
||||||
|
ptrsFreqDenst[1]= *rbSize + 1;
|
||||||
|
}
|
||||||
|
else if(*K_ptrs == 4)
|
||||||
|
{
|
||||||
|
ptrsFreqDenst[1]= *rbSize - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("[DLSIM] Wrong K_PTRS value, using default values 2\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* overwrite the values */
|
||||||
|
rrc_config_dl_ptrs_params(bwp, ptrsFreqDenst, ptrsTimeDenst, &epre_Ratio, &reOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user