Commit 4fe2d6d7 authored by Wilson W.K. Thong's avatar Wilson W.K. Thong

fix noise power calculation and downlink CQI reporting

see issue #177
parent 3bf8768d
......@@ -32,7 +32,8 @@
#define k1 ((long long int) 1000)
#define k2 ((long long int) (1024-k1))
//#define DEBUG_MEAS
//#define DEBUG_MEAS_RRC
//#define DEBUG_MEAS_UE
#ifdef USER_MODE
void print_shorts(char *s,short *x)
......@@ -165,23 +166,30 @@ int8_t set_RSRQ_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rs
}
void ue_rrc_measurements(PHY_VARS_UE *ue,
uint8_t subframe,
uint8_t abstraction_flag)
uint8_t slot,
uint8_t abstraction_flag)
{
int aarx,rb;
uint8_t subframe = slot>>1;
int aarx,rb,n;
int16_t *rxF,*rxF_pss,*rxF_sss;
uint16_t Nid_cell = ue->frame_parms.Nid_cell;
uint8_t eNB_offset,nu,l,nushift,k;
uint16_t off;
uint8_t isPss; // indicate if this is a slot for extracting PSS
uint8_t isSss; // indicate if this is a slot for extracting SSS
int32_t pss_ext[4][72]; // contain the extracted 6*12 REs for mapping the PSS
int32_t sss_ext[4][72]; // contain the extracted 6*12 REs for mapping the SSS
int32_t (*xss_ext)[72]; // point to either pss_ext or sss_ext for common calculation
int16_t *re,*im; // real and imag part of each 32-bit xss_ext[][] value
for (eNB_offset = 0; eNB_offset<1+ue->measurements.n_adj_cells; eNB_offset++) {
if (eNB_offset==0) {
ue->measurements.rssi = 0;
ue->measurements.n0_power_tot = 0;
//ue->measurements.n0_power_tot = 0;
if (abstraction_flag == 0) {
if ((ue->frame_parms.frame_type == FDD) &&
......@@ -225,16 +233,66 @@ void ue_rrc_measurements(PHY_VARS_UE *ue,
// ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63]));
// printf("pssm32 %d\n",ue->measurements.n0_power[aarx]);
ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]/12);
ue->measurements.n0_power_tot += ue->measurements.n0_power[aarx];
ue->measurements.n0_power_tot /*+=*/ = ue->measurements.n0_power[aarx];
}
ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot/(12*aarx));
ue->measurements.n0_power_tot_dBm = ue->measurements.n0_power_tot_dB - ue->rx_total_gain_dB - dB_fixed(ue->frame_parms.ofdm_symbol_size);
}
} else {
LOG_E(PHY, "Not yet implemented: noise power calculation when prefix length = EXTENDED\n");
}
}
else if ((ue->frame_parms.frame_type == TDD) &&
(subframe == 0)) { // TDD SSS, compute noise in DTX REs
else if ((ue->frame_parms.frame_type == TDD) &&
((slot == 2) || (slot == 12) || (slot == 1) || (slot == 11))) { // TDD PSS/SSS, compute noise in DTX REs // 2016-09-29 wilson fix incorrect noise power calculation
#if 1 // fixing REs extraction in noise power calculation
// check if this slot has a PSS or SSS sequence
if ((slot == 2) || (slot == 12)) {
isPss = 1;
} else {
isPss = 0;
}
if ((slot == 1) || (slot == 11)) {
isSss = 1;
} else {
isSss = 0;
}
if (isPss) {
pss_only_extract(ue, pss_ext);
xss_ext = pss_ext;
}
if (isSss) {
sss_only_extract(ue, sss_ext);
xss_ext = sss_ext;
}
// calculate noise power
int num_tot=0; // number of REs totally used in calculating noise power
for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
int num_per_rx=0; // number of REs used in caluclaing noise power for this RX antenna
ue->measurements.n0_power[aarx] = 0;
for (n=2; n<70; n++) { // skip the 2 REs next to PDSCH, i.e. n={0,1,70,71}
if (n==5) {n=67;}
re = (int16_t*)(&(xss_ext[aarx][n]));
im = re+1;
ue->measurements.n0_power[aarx] += (*re)*(*re) + (*im)*(*im);
num_per_rx++;
num_tot++;
}
ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]/(num_per_rx));
ue->measurements.n0_power_tot /*+=*/ = ue->measurements.n0_power[aarx];
}
ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot/(num_tot));
ue->measurements.n0_power_tot_dBm = ue->measurements.n0_power_tot_dB - ue->rx_total_gain_dB - dB_fixed(ue->frame_parms.ofdm_symbol_size);
#else
if (ue->frame_parms.Ncp==NORMAL) {
for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
......@@ -263,8 +321,9 @@ void ue_rrc_measurements(PHY_VARS_UE *ue,
ue->measurements.n0_power_tot_dBm = ue->measurements.n0_power_tot_dB - ue->rx_total_gain_dB - dB_fixed(ue->frame_parms.ofdm_symbol_size);
}
}
}
#endif
}
}
}
// recompute nushift with eNB_offset corresponding to adjacent eNB on which to perform channel estimation
......@@ -286,7 +345,7 @@ void ue_rrc_measurements(PHY_VARS_UE *ue,
for (l=0,nu=0; l<=(4-ue->frame_parms.Ncp); l+=(4-ue->frame_parms.Ncp),nu=3) {
k = (nu + nushift)%6;
#ifdef DEBUG_MEAS
#ifdef DEBUG_MEAS_RRC
LOG_I(PHY,"[UE %d] Frame %d subframe %d Doing ue_rrc_measurements rsrp/rssi (Nid_cell %d, nushift %d, eNB_offset %d, k %d, l %d)\n",ue->Mod_id,ue->proc.proc_rxtx[subframe&1].frame_rx,subframe,Nid_cell,nushift,
eNB_offset,k,l);
#endif
......@@ -364,7 +423,7 @@ void ue_rrc_measurements(PHY_VARS_UE *ue,
}
#ifdef DEBUG_MEAS
#ifdef DEBUG_MEAS_RRC
// if (slot == 0) {
......@@ -498,10 +557,14 @@ void lte_ue_measurements(PHY_VARS_UE *ue,
ue->measurements.wideband_cqi_tot[eNB_id] = dB_fixed2(ue->measurements.rx_power_tot[eNB_id],ue->measurements.n0_power_tot);
ue->measurements.wideband_cqi_avg[eNB_id] = dB_fixed2(ue->measurements.rx_power_avg[eNB_id],ue->measurements.n0_power_avg);
ue->measurements.rx_rssi_dBm[eNB_id] = ue->measurements.rx_power_avg_dB[eNB_id] - ue->rx_total_gain_dB;
#ifdef DEBUG_MEAS
LOG_I(PHY,"[eNB %d] lte_ue_measurements: RSSI %d dBm, RSSI (digital) %d dB\n",
eNB_id,ue->measurements.rx_rssi_dBm[eNB_id],
ue->measurements.rx_power_avg_dB[eNB_id]);
#ifdef DEBUG_MEAS_UE
LOG_D(PHY,"[eNB %d] RSSI %d dBm, RSSI (digital) %d dB, WBandCQI %d dB, rxPwrAvg %d, n0PwrAvg %d\n",
eNB_id,
ue->measurements.rx_rssi_dBm[eNB_id],
ue->measurements.rx_power_avg_dB[eNB_id],
ue->measurements.wideband_cqi_avg[eNB_id],
ue->measurements.rx_power_avg[eNB_id],
ue->measurements.n0_power_avg);
#endif
}
......
......@@ -5866,36 +5866,38 @@ uint8_t sinr2cqi(double sinr,uint8_t trans_mode)
{
// int flag_LA=0;
uint8_t retValue = 0;
if(flag_LA==0) {
// Ideal Channel Estimation
if (sinr<=-4.89)
return(0);
retValue = (0);
else if (sinr < -3.53)
return(3);
retValue = (3);
else if (sinr <= -1.93)
return(4);
retValue = (4);
else if (sinr <= -0.43)
return(5);
retValue = (5);
else if (sinr <= 1.11)
return(6);
retValue = (6);
else if (sinr <= 3.26)
return(7);
else if (sinr <= 5)
return(8);
else if (sinr <= 7)
return(9);
else if (sinr <= 9)
return(10);
else if (sinr <= 11)
return(11);
else if (sinr <= 13)
return(12);
retValue = (7);
else if (sinr <= 5.0)
retValue = (8);
else if (sinr <= 7.0)
retValue = (9);
else if (sinr <= 9.0)
retValue = (10);
else if (sinr <= 11.0)
retValue = (11);
else if (sinr <= 13.0)
retValue = (12);
else if (sinr <= 15.5)
return(13);
retValue = (13);
else if (sinr <= 17.5)
return(14);
else if (sinr > 19.5)
return(15);
retValue = (14);
else
retValue = (15);
} else {
int h=0;
int trans_mode_tmp;
......@@ -5909,11 +5911,12 @@ uint8_t sinr2cqi(double sinr,uint8_t trans_mode)
for(h=0; h<16; h++) {
if(sinr<=sinr_to_cqi[trans_mode_tmp][h])
return(h);
retValue = (h);
}
}
return(0);
LOG_D(PHY, "sinr=%f trans_mode=%d cqi=%d\n", sinr, trans_mode, retValue);
return retValue;
}
//uint32_t fill_subband_cqi(PHY_MEASUREMENTS *meas,uint8_t eNB_id) {
//
......
......@@ -88,7 +88,7 @@ int pbch_detection(PHY_VARS_UE *ue, runmode_t mode)
if (ue->frame_parms.frame_type == TDD) {
ue_rrc_measurements(ue,
1,
2,
0);
}
else {
......
......@@ -1194,6 +1194,33 @@ int32_t rx_pdcch(LTE_UE_COMMON *lte_ue_common_vars,
MIMO_mode_t mimo_mode,
uint32_t high_speed_flag,
uint8_t is_secondary_ue);
/*! \brief Extract PSS and SSS resource elements
@param phy_vars_ue Pointer to UE variables
@param[out] pss_ext contain the PSS signals after the extraction
@param[out] sss_ext contain the SSS signals after the extraction
@returns 0 on success
*/
int pss_sss_extract(PHY_VARS_UE *phy_vars_ue,
int32_t pss_ext[4][72],
int32_t sss_ext[4][72]);
/*! \brief Extract only PSS resource elements
@param phy_vars_ue Pointer to UE variables
@param[out] pss_ext contain the PSS signals after the extraction
@returns 0 on success
*/
int pss_only_extract(PHY_VARS_UE *phy_vars_ue,
int32_t pss_ext[4][72]);
/*! \brief Extract only SSS resource elements
@param phy_vars_ue Pointer to UE variables
@param[out] sss_ext contain the SSS signals after the extraction
@returns 0 on success
*/
int sss_only_extract(PHY_VARS_UE *phy_vars_ue,
int32_t sss_ext[4][72]);
/*! \brief Performs detection of SSS to find cell ID and other framing parameters (FDD/TDD, normal/extended prefix)
@param phy_vars_ue Pointer to UE variables
@param tot_metric Pointer to variable containing maximum metric under framing hypothesis (to be compared to other hypotheses
......
......@@ -146,9 +146,10 @@ int pss_ch_est(PHY_VARS_UE *ue,
}
int pss_sss_extract(PHY_VARS_UE *ue,
int _do_pss_sss_extract(PHY_VARS_UE *ue,
int32_t pss_ext[4][72],
int32_t sss_ext[4][72])
int32_t sss_ext[4][72],
uint8_t doPss, uint8_t doSss) // add flag to indicate extracting only PSS, only SSS, or both
{
......@@ -191,8 +192,8 @@ int pss_sss_extract(PHY_VARS_UE *ue,
}
for (i=0; i<12; i++) {
pss_rxF_ext[i]=pss_rxF[i];
sss_rxF_ext[i]=sss_rxF[i];
if (doPss) {pss_rxF_ext[i]=pss_rxF[i];}
if (doSss) {sss_rxF_ext[i]=sss_rxF[i];}
}
pss_rxF+=12;
......@@ -206,6 +207,28 @@ int pss_sss_extract(PHY_VARS_UE *ue,
return(0);
}
int pss_sss_extract(PHY_VARS_UE *phy_vars_ue,
int32_t pss_ext[4][72],
int32_t sss_ext[4][72])
{
return _do_pss_sss_extract(phy_vars_ue, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */);
}
int pss_only_extract(PHY_VARS_UE *phy_vars_ue,
int32_t pss_ext[4][72])
{
static int32_t dummy[4][72];
return _do_pss_sss_extract(phy_vars_ue, pss_ext, dummy, 1 /* doPss */, 0 /* doSss */);
}
int sss_only_extract(PHY_VARS_UE *phy_vars_ue,
int32_t sss_ext[4][72])
{
static int32_t dummy[4][72];
return _do_pss_sss_extract(phy_vars_ue, dummy, sss_ext, 0 /* doPss */, 1 /* doSss */);
}
int16_t phase_re[7] = {16383, 25101, 30791, 32767, 30791, 25101, 16383};
int16_t phase_im[7] = {-28378, -21063, -11208, 0, 11207, 21062, 28377};
......
......@@ -581,6 +581,7 @@ void print_CQI(void *o,UCI_format_t uci_format,unsigned char eNB_id,int N_RB_DL)
switch(uci_format) {
case wideband_cqi_rank1_2A:
#ifdef DEBUG_UCI
LOG_D(PHY,"[PRINT CQI] flat_LA %d\n", flag_LA);
switch(N_RB_DL) {
case 6:
LOG_I(PHY,"[PRINT CQI] wideband_cqi rank 1: eNB %d, cqi %d\n",eNB_id,
......
......@@ -260,6 +260,7 @@ uint32_t ulsch_encoding(uint8_t *a,
// fill CQI/PMI information
if (ulsch->O>0) {
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING_FILL_CQI, VCD_FUNCTION_IN);
rnti = ue->pdcch_vars[eNB_id]->crnti;
fill_CQI(ulsch,meas,0,harq_pid,ue->frame_parms.N_RB_DL,rnti, tmode,ue->sinr_eff);
......@@ -271,6 +272,7 @@ uint32_t ulsch_encoding(uint8_t *a,
//LOG_I(PHY,"XXX saving pmi for DL %x\n",pmi2hex_2Ar1(((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi));
dlsch[0]->pmi_alloc = ((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi;
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING_FILL_CQI, VCD_FUNCTION_OUT);
}
if (ulsch->O<=32) {
......
......@@ -2042,7 +2042,11 @@ void phy_procedures_UE_S_TX(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_f
}
}
void ue_measurement_procedures(uint16_t l, PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode)
void ue_measurement_procedures(
uint16_t l, // symbol index of each slot [0..6]
PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uint8_t eNB_id,
uint16_t slot, // slot index of each radio frame [0..19]
uint8_t abstraction_flag,runmode_t mode)
{
LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
......@@ -2074,7 +2078,7 @@ void ue_measurement_procedures(uint16_t l, PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, VCD_FUNCTION_IN);
ue_rrc_measurements(ue,
subframe_rx,
slot,
abstraction_flag);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS, VCD_FUNCTION_OUT);
......@@ -3379,7 +3383,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
stop_meas(&ue->ofdm_demod_stats);
}
ue_measurement_procedures(l-1,ue,proc,eNB_id,abstraction_flag,mode);
ue_measurement_procedures(l-1,ue,proc,eNB_id,(subframe_rx<<1),abstraction_flag,mode);
if ((l==pilot1) ||
((pmch_flag==1)&(l==l2))) {
LOG_D(PHY,"[UE %d] Frame %d: Calling pdcch procedures (eNB %d)\n",ue->Mod_id,frame_rx,eNB_id);
......@@ -3392,7 +3396,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
}
} // for l=1..l2
ue_measurement_procedures(l-1,ue,proc,eNB_id,abstraction_flag,mode);
ue_measurement_procedures(l-1,ue,proc,eNB_id,(subframe_rx<<1),abstraction_flag,mode);
// If this is PMCH, call procedures and return
if (pmch_flag == 1) {
......@@ -3483,7 +3487,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
stop_meas(&ue->ofdm_demod_stats);
}
ue_measurement_procedures(l-1,ue,proc,eNB_id,abstraction_flag,mode);
ue_measurement_procedures(l-1,ue,proc,eNB_id,1+(subframe_rx<<1),abstraction_flag,mode);
} // for l=1..l2
......
......@@ -283,6 +283,9 @@ const char* eurecomFunctionsNames[] = {
"phy_ue_generate_prach",
"phy_ue_ulsch_modulation",
"phy_ue_ulsch_encoding",
#if 1 // add for debugging losing PDSCH immediately before and after reporting CQI
"phy_ue_ulsch_encoding_fill_cqi",
#endif
"phy_ue_ulsch_scrambling",
"phy_eNB_dlsch_modulation",
"phy_eNB_dlsch_encoding",
......
......@@ -257,6 +257,9 @@ typedef enum {
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_MODULATION,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING,
#if 1 // add for debugging losing PDSCH immediately before and after reporting CQI
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING_FILL_CQI,
#endif
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_SCRAMBLING,
VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION,
VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING,
......
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