lte_ue_measurements.c 32.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
ghaddab's avatar
ghaddab committed
21

22 23 24 25 26 27
// this function fills the PHY_vars->PHY_measurement structure

#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
28
#include "log.h"
29
#include "PHY/sse_intrin.h"
30 31 32 33 34

//#define k1 1000
#define k1 ((long long int) 1000)
#define k2 ((long long int) (1024-k1))

35 36
//#define DEBUG_MEAS_RRC
//#define DEBUG_MEAS_UE
37 38

#ifdef USER_MODE
39
void print_shorts(char *s,short *x)
40
{
41 42 43


  printf("%s  : %d,%d,%d,%d,%d,%d,%d,%d\n",s,
44
         x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7]
45
        );
46 47

}
48
void print_ints(char *s,int *x)
49
{
50 51 52


  printf("%s  : %d,%d,%d,%d\n",s,
53
         x[0],x[1],x[2],x[3]
54
        );
55 56 57 58 59

}
#endif


60 61
int16_t get_PL(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
62

63
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
64
  /*
65
  int RSoffset;
66 67


68
  if (ue->frame_parms.mode1_flag == 1)
69 70 71
    RSoffset = 6;
  else
    RSoffset = 3;
72
  */
73

74
  LOG_D(PHY,"get_PL : Frame %d : rsrp %f dBm/RE (%f), eNB power %d dBm/RE\n", ue->proc.proc_rxtx[0].frame_rx,
75 76 77
        (1.0*dB_fixed_times10(ue->measurements.rsrp[eNB_index])-(10.0*ue->rx_total_gain_dB))/10.0,
        10*log10((double)ue->measurements.rsrp[eNB_index]),
        ue->frame_parms.pdsch_config_common.referenceSignalPower);
78

79 80 81 82
  return((int16_t)(((10*ue->rx_total_gain_dB) -
                    dB_fixed_times10(ue->measurements.rsrp[eNB_index])+
                    //        dB_fixed_times10(RSoffset*12*ue_g[Mod_id][CC_id]->frame_parms.N_RB_DL) +
                    (ue->frame_parms.pdsch_config_common.referenceSignalPower*10))/10));
83 84
}

85

86 87
uint8_t get_n_adj_cells (uint8_t Mod_id,uint8_t CC_id)
{
88

89
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
90

91 92
  if (ue)
    return ue->measurements.n_adj_cells;
93
  else
94 95 96
    return 0;
}

97 98
uint32_t get_rx_total_gain_dB (uint8_t Mod_id,uint8_t CC_id)
{
99

100
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
101

102 103
  if (ue)
    return ue->rx_total_gain_dB;
104

105
  return 0xFFFFFFFF;
106
}
107 108
uint32_t get_RSSI (uint8_t Mod_id,uint8_t CC_id)
{
109

110
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
111

112 113
  if (ue)
    return ue->measurements.rssi;
114

115
  return 0xFFFFFFFF;
116
}
117 118 119
uint32_t get_RSRP(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{

120
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
121

122 123
  if (ue)
    return ue->measurements.rsrp[eNB_index];
124

125
  return 0xFFFFFFFF;
126 127
}

128 129
uint32_t get_RSRQ(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
130

131
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
132

133 134
  if (ue)
    return ue->measurements.rsrq[eNB_index];
135

136
  return 0xFFFFFFFF;
137 138
}

139 140 141
int8_t set_RSRP_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrp)
{

142
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
143

144 145
  if (ue) {
    ue->measurements.rsrp_filtered[eNB_index]=rsrp;
146 147
    return 0;
  }
148

149 150 151 152
  LOG_W(PHY,"[UE%d] could not set the rsrp\n",Mod_id);
  return -1;
}

153 154
int8_t set_RSRQ_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrq)
{
155

156
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
157

158 159
  if (ue) {
    ue->measurements.rsrq_filtered[eNB_index]=rsrq;
160
    return 0;
161
  }
162

163 164
  LOG_W(PHY,"[UE%d] could not set the rsrq\n",Mod_id);
  return -1;
165

166
}
167

168
void ue_rrc_measurements(PHY_VARS_UE *ue,
169 170
    uint8_t slot,
    uint8_t abstraction_flag)
171
{
172

173 174
  uint8_t subframe = slot>>1;
  int aarx,rb,n;
175
  int16_t *rxF,*rxF_pss,*rxF_sss;
176

177
  uint16_t Nid_cell = ue->frame_parms.Nid_cell;
gauthier's avatar
gauthier committed
178 179
  uint8_t eNB_offset,nu,l,nushift,k;
  uint16_t off;
180

181 182 183 184 185 186
  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
187

188
  for (eNB_offset = 0; eNB_offset<1+ue->measurements.n_adj_cells; eNB_offset++) {
189

190
    if (eNB_offset==0) {
191
      ue->measurements.rssi = 0;
192
      //ue->measurements.n0_power_tot = 0;
193

knopp's avatar
 
knopp committed
194
      if (abstraction_flag == 0) {
195
        if ((ue->frame_parms.frame_type == FDD) &&
196
            ((subframe == 0) || (subframe == 5))) {  // FDD PSS/SSS, compute noise in DTX REs
197

198 199
          if (ue->frame_parms.Ncp==NORMAL) {
            for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
200

201 202
	      rxF_sss = (int16_t *)&ue->common_vars.rxdataF[aarx][(5*ue->frame_parms.ofdm_symbol_size)];
	      rxF_pss = (int16_t *)&ue->common_vars.rxdataF[aarx][(6*ue->frame_parms.ofdm_symbol_size)];
203
	      
204 205

              //-ve spectrum from SSS
206 207
	      //	      printf("slot %d: SSS DTX: %d,%d, non-DTX %d,%d\n",slot,rxF_pss[-72],rxF_pss[-71],rxF_pss[-36],rxF_pss[-35]);

208 209 210 211 212 213 214
	      //              ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71]));
	      //	      printf("sssn36 %d\n",ue->measurements.n0_power[aarx]);
              ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65]));
	      //              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63]));
	      //	      printf("sssm32 %d\n",ue->measurements.n0_power[aarx]);
215
              //+ve spectrum from SSS
216 217 218 219 220
	      ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+70]*rxF_sss[2+70])+((int32_t)rxF_sss[2+69]*rxF_sss[2+69]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+68]*rxF_sss[2+68])+((int32_t)rxF_sss[2+67]*rxF_sss[2+67]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+66]*rxF_sss[2+66])+((int32_t)rxF_sss[2+65]*rxF_sss[2+65]));
	      //	      ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+64]*rxF_sss[2+64])+((int32_t)rxF_sss[2+63]*rxF_sss[2+63]));
	      //	      printf("sssp32 %d\n",ue->measurements.n0_power[aarx]);
221
              //+ve spectrum from PSS
222 223 224 225 226 227 228 229 230 231 232 233 234 235
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+70]*rxF_pss[2+70])+((int32_t)rxF_pss[2+69]*rxF_pss[2+69]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+68]*rxF_pss[2+68])+((int32_t)rxF_pss[2+67]*rxF_pss[2+67]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+66]*rxF_pss[2+66])+((int32_t)rxF_pss[2+65]*rxF_pss[2+65]));
	      //              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[2+64]*rxF_pss[2+64])+((int32_t)rxF_pss[2+63]*rxF_pss[2+63]));
	      //	      printf("pss32 %d\n",ue->measurements.n0_power[aarx]);              //-ve spectrum from PSS
              rxF_pss = (int16_t *)&ue->common_vars.rxdataF[aarx][(7*ue->frame_parms.ofdm_symbol_size)];
	      //              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71]));
	      //	      printf("pssm36 %d\n",ue->measurements.n0_power[aarx]);
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65]));
	      //              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);
236
              ue->measurements.n0_power_tot /*+=*/ = ue->measurements.n0_power[aarx];
237 238
            }

239 240
	    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);
241 242 243
          } else {
            LOG_E(PHY, "Not yet implemented: noise power calculation when prefix length = EXTENDED\n");
          }
244
        }
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
        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++) {
275

276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
            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
296 297
          if (ue->frame_parms.Ncp==NORMAL) {
            for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
298

299
	      rxF_sss = (int16_t *)&ue->common_vars.rxdataF[aarx][(6*ue->frame_parms.ofdm_symbol_size)];
300 301
	      // note this is a dummy pointer, the pss is not really there!
	      // in FDD the pss is in the symbol after the sss, but not in TDD
302
	      rxF_pss = (int16_t *)&ue->common_vars.rxdataF[aarx][(7*ue->frame_parms.ofdm_symbol_size)];
303 304
	      
	      //-ve spectrum from SSS
305 306 307 308 309
	      //              ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-72]*rxF_pss[-72])+((int32_t)rxF_pss[-71]*rxF_pss[-71]));
              ue->measurements.n0_power[aarx] = (((int32_t)rxF_pss[-70]*rxF_pss[-70])+((int32_t)rxF_pss[-69]*rxF_pss[-69]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-68]*rxF_pss[-68])+((int32_t)rxF_pss[-67]*rxF_pss[-67]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-66]*rxF_pss[-66])+((int32_t)rxF_pss[-65]*rxF_pss[-65]));
	      //              ue->measurements.n0_power[aarx] += (((int32_t)rxF_pss[-64]*rxF_pss[-64])+((int32_t)rxF_pss[-63]*rxF_pss[-63]));
310
	      //+ve spectrum from SSS
311 312 313 314 315
	      //	      ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+72]*rxF_sss[2+72])+((int32_t)rxF_sss[2+71]*rxF_sss[2+71]));
	      ue->measurements.n0_power[aarx] = (((int32_t)rxF_sss[2+70]*rxF_sss[2+70])+((int32_t)rxF_sss[2+69]*rxF_sss[2+69]));
	      ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+68]*rxF_sss[2+68])+((int32_t)rxF_sss[2+67]*rxF_sss[2+67]));
	      ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+66]*rxF_sss[2+66])+((int32_t)rxF_sss[2+65]*rxF_sss[2+65]));
	      //	      ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[2+64]*rxF_sss[2+64])+((int32_t)rxF_sss[2+63]*rxF_sss[2+63]));
316
	      
317 318
	      ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]/(6));
	      ue->measurements.n0_power_tot +=  ue->measurements.n0_power[aarx];	  
319
	    }	      
320 321
	    ue->measurements.n0_power_tot_dB = (unsigned short) dB_fixed(ue->measurements.n0_power_tot/(6*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);
322 323
	      
	    
324 325 326
          }
#endif
        }
327 328
      }
    }
329
    // recompute nushift with eNB_offset corresponding to adjacent eNB on which to perform channel estimation
330
    //    printf("[PHY][UE %d] Frame %d slot %d Doing ue_rrc_measurements rsrp/rssi (Nid_cell %d, Nid2 %d, nushift %d, eNB_offset %d)\n",ue->Mod_id,ue->frame,slot,Nid_cell,Nid2,nushift,eNB_offset);
331
    if (eNB_offset > 0)
332
      Nid_cell = ue->measurements.adj_cell_id[eNB_offset-1];
333 334 335 336 337 338


    nushift =  Nid_cell%6;



339
    ue->measurements.rsrp[eNB_offset] = 0;
340 341 342


    if (abstraction_flag == 0) {
343

344 345
      // compute RSRP using symbols 0 and 4-frame_parms->Ncp

346
      for (l=0,nu=0; l<=(4-ue->frame_parms.Ncp); l+=(4-ue->frame_parms.Ncp),nu=3) {
347
        k = (nu + nushift)%6;
348
#ifdef DEBUG_MEAS_RRC
349
        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,
350
              eNB_offset,k,l);
351
#endif
352

353 354 355
        for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
          rxF = (int16_t *)&ue->common_vars.rxdataF[aarx][(l*ue->frame_parms.ofdm_symbol_size)];
          off  = (ue->frame_parms.first_carrier_offset+k)<<1;
356

357 358
          if (l==(4-ue->frame_parms.Ncp)) {
            for (rb=0; rb<ue->frame_parms.N_RB_DL; rb++) {
359 360 361

              //    printf("rb %d, off %d, off2 %d\n",rb,off,off2);

362
              ue->measurements.rsrp[eNB_offset] += (((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1]));
363
              //        printf("rb %d, off %d : %d\n",rb,off,((((int32_t)rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1])));
364
	      //	      if ((ue->frame_rx&0x3ff) == 0)
365
	      //                printf("rb %d, off %d : %d\n",rb,off,((rxF[off]*rxF[off])+(rxF[off+1]*rxF[off+1])));
366

367
              
368 369
              off+=12;

370
              if (off>=(ue->frame_parms.ofdm_symbol_size<<1))
371 372
                off = (1+k)<<1;

373
              ue->measurements.rsrp[eNB_offset] += (((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1]));
374 375
              //    printf("rb %d, off %d : %d\n",rb,off,(((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1])));
              /*
376
                if ((ue->frame_rx&0x3ff) == 0)
377 378 379 380
                printf("rb %d, off %d : %d\n",rb,off,((rxF[off]*rxF[off])+(rxF[off+1]*rxF[off+1])));
              */
              off+=12;

381
              if (off>=(ue->frame_parms.ofdm_symbol_size<<1))
382 383 384 385 386 387 388
                off = (1+k)<<1;

            }

            /*
            if ((eNB_offset==0)&&(l==0)) {
            for (i=0;i<6;i++,off2+=4)
389 390
            ue->measurements.rssi += ((rxF[off2]*rxF[off2])+(rxF[off2+1]*rxF[off2+1]));
            if (off2==(ue->frame_parms.ofdm_symbol_size<<2))
391 392
            off2=4;
            for (i=0;i<6;i++,off2+=4)
393
            ue->measurements.rssi += ((rxF[off2]*rxF[off2])+(rxF[off2+1]*rxF[off2+1]));
394 395
            }
            */
396
            //    printf("slot %d, rb %d => rsrp %d, rssi %d\n",slot,rb,ue->measurements.rsrp[eNB_offset],ue->measurements.rssi);
397 398
          }
        }
399 400
      }

401
      // 2 RE per PRB
402 403 404
      //      ue->measurements.rsrp[eNB_offset]/=(24*ue->frame_parms.N_RB_DL);
      ue->measurements.rsrp[eNB_offset]/=(2*ue->frame_parms.N_RB_DL*ue->frame_parms.ofdm_symbol_size);
      //      LOG_I(PHY,"eNB: %d, RSRP: %d \n",eNB_offset,ue->measurements.rsrp[eNB_offset]);
405
      if (eNB_offset == 0) {
406 407 408 409
        //  ue->measurements.rssi/=(24*ue->frame_parms.N_RB_DL);
        //  ue->measurements.rssi*=rx_power_correction;
        //  ue->measurements.rssi=ue->measurements.rsrp[0]*24/2;
        ue->measurements.rssi=ue->measurements.rsrp[0]*(12*ue->frame_parms.N_RB_DL);
410
      }
411

412 413
      if (ue->measurements.rssi>0)
        ue->measurements.rsrq[eNB_offset] = 100*ue->measurements.rsrp[eNB_offset]*ue->frame_parms.N_RB_DL/ue->measurements.rssi;
414
      else
415
        ue->measurements.rsrq[eNB_offset] = -12000;
416

417
      //((200*ue->measurements.rsrq[eNB_offset]) + ((1024-200)*100*ue->measurements.rsrp[eNB_offset]*ue->frame_parms.N_RB_DL/ue->measurements.rssi))>>10;
418
    } else { // Do abstraction of RSRP and RSRQ
419
      ue->measurements.rssi = ue->measurements.rx_power_avg[0];
420
      // dummay value for the moment
421 422
      ue->measurements.rsrp[eNB_offset] = -93 ;
      ue->measurements.rsrq[eNB_offset] = 3;
423 424

    }
425

426
#ifdef DEBUG_MEAS_RRC
427

428
    //    if (slot == 0) {
429

430
      if (eNB_offset == 0)
431 432
        LOG_I(PHY,"[UE %d] Frame %d, subframe %d RRC Measurements => rssi %3.1f dBm (digital: %3.1f dB, gain %d), N0 %d dBm\n",ue->Mod_id,
              ue->proc.proc_rxtx[subframe&1].frame_rx,subframe,10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB,
433 434 435
              10*log10(ue->measurements.rssi),
              ue->rx_total_gain_dB,
              ue->measurements.n0_power_tot_dBm);
436

437
      LOG_I(PHY,"[UE %d] Frame %d, subframe %d RRC Measurements (idx %d, Cell id %d) => rsrp: %3.1f dBm/RE (%d), rsrq: %3.1f dB\n",
438
            ue->Mod_id,
439
            ue->proc.proc_rxtx[subframe&1].frame_rx,subframe,eNB_offset,
440 441 442 443 444 445 446 447 448
            (eNB_offset>0) ? ue->measurements.adj_cell_id[eNB_offset-1] : ue->frame_parms.Nid_cell,
            10*log10(ue->measurements.rsrp[eNB_offset])-ue->rx_total_gain_dB,
            ue->measurements.rsrp[eNB_offset],
            (10*log10(ue->measurements.rsrq[eNB_offset])));
      //LOG_D(PHY,"RSRP_total_dB: %3.2f \n",(dB_fixed_times10(ue->measurements.rsrp[eNB_offset])/10.0)-ue->rx_total_gain_dB-dB_fixed(ue->frame_parms.N_RB_DL*12));

      //LOG_D(PHY,"RSRP_dB: %3.2f \n",(dB_fixed_times10(ue->measurements.rsrp[eNB_offset])/10.0));
      //LOG_D(PHY,"gain_loss_dB: %d \n",ue->rx_total_gain_dB);
      //LOG_D(PHY,"gain_fixed_dB: %d \n",dB_fixed(ue->frame_parms.N_RB_DL*12));
449

450
      //    }
451

452 453 454
#endif
  }

455 456
}

457
void lte_ue_measurements(PHY_VARS_UE *ue,
458 459 460 461 462 463
                         unsigned int subframe_offset,
                         unsigned char N0_symbol,
                         unsigned char abstraction_flag)
{


464
  int aarx,aatx,eNB_id=0; //,gain_offset=0;
465 466 467
  //int rx_power[NUMBER_OF_CONNECTED_eNB_MAX];
  int i;
  unsigned int limit,subband;
468
#if defined(__x86_64__) || defined(__i386__)
469
  __m128i *dl_ch0_128,*dl_ch1_128;
470 471 472
#elif defined(__arm__)
  int16x8_t *dl_ch0_128, *dl_ch1_128;
#endif
473
  int *dl_ch0,*dl_ch1;
474
  LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
  int nb_subbands,subband_size,last_subband_size;
  int N_RB_DL = frame_parms->N_RB_DL;

  switch (N_RB_DL) {
  case 6:
    nb_subbands = 6;
    subband_size = 12;
    last_subband_size = 0;
    break;

  default:
  case 25:
    nb_subbands = 7;
    subband_size = 4*12;
    last_subband_size = 12;
    break;

  case 50:
    nb_subbands = 9;
    subband_size = 6*12;
    last_subband_size = 2*12;
    break;

  case 100:
    nb_subbands = 13;
    subband_size = 8*12;
    last_subband_size = 4*12;
    break;
  }

  // signal measurements
506
  for (eNB_id=0; eNB_id<ue->n_connected_eNB; eNB_id++) {
507
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
Xiwen JIANG's avatar
Xiwen JIANG committed
508
      for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
509 510
        ue->measurements.rx_spatial_power[eNB_id][aatx][aarx] =
          (signal_energy_nodc(&ue->common_vars.dl_ch_estimates[eNB_id][(aatx<<1) + aarx][0],
511
                              (N_RB_DL*12)));
512
        //- ue->measurements.n0_power[aarx];
513

514 515
        if (ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]<0)
          ue->measurements.rx_spatial_power[eNB_id][aatx][aarx] = 0; //ue->measurements.n0_power[aarx];
516

517
        ue->measurements.rx_spatial_power_dB[eNB_id][aatx][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]);
518 519

        if (aatx==0)
520
          ue->measurements.rx_power[eNB_id][aarx] = ue->measurements.rx_spatial_power[eNB_id][aatx][aarx];
521
        else
522
          ue->measurements.rx_power[eNB_id][aarx] += ue->measurements.rx_spatial_power[eNB_id][aatx][aarx];
523 524
      } //aatx

525
      ue->measurements.rx_power_dB[eNB_id][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_power[eNB_id][aarx]);
526 527

      if (aarx==0)
528
        ue->measurements.rx_power_tot[eNB_id] = ue->measurements.rx_power[eNB_id][aarx];
529
      else
530
        ue->measurements.rx_power_tot[eNB_id] += ue->measurements.rx_power[eNB_id][aarx];
531 532
    } //aarx

533
    ue->measurements.rx_power_tot_dB[eNB_id] = (unsigned short) dB_fixed(ue->measurements.rx_power_tot[eNB_id]);
534 535 536 537

  } //eNB_id

  // filter to remove jitter
538 539 540 541 542 543 544 545 546
  if (ue->init_averaging == 0) {
    for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++)
      ue->measurements.rx_power_avg[eNB_id] = (int)
          (((k1*((long long int)(ue->measurements.rx_power_avg[eNB_id]))) +
            (k2*((long long int)(ue->measurements.rx_power_tot[eNB_id]))))>>10);

    ue->measurements.n0_power_avg = (int)
        (((k1*((long long int) (ue->measurements.n0_power_avg))) +
          (k2*((long long int) (ue->measurements.n0_power_tot))))>>10);
547
  } else {
548 549
    for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++)
      ue->measurements.rx_power_avg[eNB_id] = ue->measurements.rx_power_tot[eNB_id];
550

551 552
    ue->measurements.n0_power_avg = ue->measurements.n0_power_tot;
    ue->init_averaging = 0;
553 554
  }

555 556 557 558 559
  for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) {
    ue->measurements.rx_power_avg_dB[eNB_id] = dB_fixed( ue->measurements.rx_power_avg[eNB_id]);
    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;
560 561 562 563 564 565 566 567
#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);
568
#endif
569 570
  }

571
  ue->measurements.n0_power_avg_dB = dB_fixed( ue->measurements.n0_power_avg);
572

573
  for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) {
574 575 576 577
    if (frame_parms->mode1_flag==0) {
      // cqi/pmi information

      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
578 579
        dl_ch0    = &ue->common_vars.dl_ch_estimates[eNB_id][aarx][4];
        dl_ch1    = &ue->common_vars.dl_ch_estimates[eNB_id][2+aarx][4];
580 581 582 583 584

        for (subband=0; subband<nb_subbands; subband++) {

          // cqi
          if (aarx==0)
585
            ue->measurements.subband_cqi_tot[eNB_id][subband]=0;
586 587 588 589 590

          if ((subband<(nb_subbands-1))||(N_RB_DL==6)) {
            /*for (i=0;i<48;i++)
            msg("subband %d (%d) : %d,%d\n",subband,i,((short *)dl_ch0)[2*i],((short *)dl_ch0)[1+(2*i)]);
            */
591
            ue->measurements.subband_cqi[eNB_id][aarx][subband] =
592 593
              (signal_energy_nodc(dl_ch0,subband_size) + signal_energy_nodc(dl_ch1,subband_size));

594 595
            if ( ue->measurements.subband_cqi[eNB_id][aarx][subband] < 0)
              ue->measurements.subband_cqi[eNB_id][aarx][subband]=0;
596 597 598

            /*
            else
599
            ue->measurements.subband_cqi[eNB_id][aarx][subband]-=ue->measurements.n0_power[aarx];
600 601
            */

602 603 604
            ue->measurements.subband_cqi_tot[eNB_id][subband] += ue->measurements.subband_cqi[eNB_id][aarx][subband];
            ue->measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(ue->measurements.subband_cqi[eNB_id][aarx][subband],
                ue->measurements.n0_power[aarx]);
605 606 607
          } else { // this is for the last subband which is smaller in size
            //      for (i=0;i<12;i++)
            //        printf("subband %d (%d) : %d,%d\n",subband,i,((short *)dl_ch0)[2*i],((short *)dl_ch0)[1+(2*i)]);
608 609 610 611 612
            ue->measurements.subband_cqi[eNB_id][aarx][subband] = (signal_energy_nodc(dl_ch0,last_subband_size) +
                signal_energy_nodc(dl_ch1,last_subband_size)); // - ue->measurements.n0_power[aarx];
            ue->measurements.subband_cqi_tot[eNB_id][subband] += ue->measurements.subband_cqi[eNB_id][aarx][subband];
            ue->measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(ue->measurements.subband_cqi[eNB_id][aarx][subband],
                ue->measurements.n0_power[aarx]);
613 614 615 616
          }

          dl_ch1+=subband_size;
          dl_ch0+=subband_size;
617
          //    msg("subband_cqi[%d][%d][%d] => %d (%d dB)\n",eNB_id,aarx,subband,ue->measurements.subband_cqi[eNB_id][aarx][subband],ue->measurements.subband_cqi_dB[eNB_id][aarx][subband]);
618 619 620 621 622
        }

      }

      for (subband=0; subband<nb_subbands; subband++) {
623 624
        ue->measurements.subband_cqi_tot_dB[eNB_id][subband] = dB_fixed2(ue->measurements.subband_cqi_tot[eNB_id][subband],ue->measurements.n0_power_tot);
        //    msg("subband_cqi_tot[%d][%d] => %d dB (n0 %d)\n",eNB_id,subband,ue->measurements.subband_cqi_tot_dB[eNB_id][subband],ue->measurements.n0_power_tot);
625 626 627
      }

      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
628
        // skip the first 4 RE due to interpolation filter length of 5 (not possible to skip 5 due to 128i alignment, must be multiple of 128bit)
629 630

#if defined(__x86_64__) || defined(__i386__)
631
       __m128i pmi128_re,pmi128_im,mmtmpPMI0,mmtmpPMI1 /* ,mmtmpPMI2,mmtmpPMI3 */ ;
632

633 634
        dl_ch0_128    = (__m128i *)&ue->common_vars.dl_ch_estimates[eNB_id][aarx][4];
        dl_ch1_128    = (__m128i *)&ue->common_vars.dl_ch_estimates[eNB_id][2+aarx][4];
635 636
#elif defined(__arm__)
        int32x4_t pmi128_re,pmi128_im,mmtmpPMI0,mmtmpPMI1,mmtmpPMI0b,mmtmpPMI1b;
637

638 639
        dl_ch0_128    = (int16x8_t *)&ue->common_vars.dl_ch_estimates[eNB_id][aarx][4];
        dl_ch1_128    = (int16x8_t *)&ue->common_vars.dl_ch_estimates[eNB_id][2+aarx][4];
640 641

#endif
642 643 644 645
        for (subband=0; subband<nb_subbands; subband++) {


          // pmi
646
#if defined(__x86_64__) || defined(__i386__)
647 648
          pmi128_re = _mm_setzero_si128();
          pmi128_im = _mm_setzero_si128();
649 650 651 652
#elif defined(__arm__)
          pmi128_re = vdupq_n_s32(0);
	  pmi128_im = vdupq_n_s32(0);
#endif
653 654 655 656 657 658 659 660 661 662 663
          // limit is the number of groups of 4 REs in a subband (12 = 4 RBs, 3 = 1 RB)
          // for 5 MHz channelization, there are 7 subbands, 6 of size 4 RBs and 1 of size 1 RB
          if ((N_RB_DL==6) || (subband<(nb_subbands-1)))
            limit = subband_size>>2;
          else
            limit = last_subband_size>>2;

          for (i=0; i<limit; i++) {

            // For each RE in subband perform ch0 * conj(ch1)
            // multiply by conjugated channel
664
#if defined(__x86_64__) || defined(__i386__)
665 666 667 668 669 670 671 672
            mmtmpPMI1 = _mm_shufflelo_epi16(dl_ch1_128[0],_MM_SHUFFLE(2,3,0,1));//_MM_SHUFFLE(2,3,0,1)
            mmtmpPMI1 = _mm_shufflehi_epi16(mmtmpPMI1,_MM_SHUFFLE(2,3,0,1));
            mmtmpPMI1 = _mm_sign_epi16(mmtmpPMI1,*(__m128i*)&conjugate[0]);
            mmtmpPMI1 = _mm_madd_epi16(mmtmpPMI1,dl_ch0_128[0]);
            // mmtmpPMI1 contains imag part of 4 consecutive outputs (32-bit)

            pmi128_re = _mm_add_epi32(pmi128_re,mmtmpPMI0);
            pmi128_im = _mm_add_epi32(pmi128_im,mmtmpPMI1);
673 674 675 676 677 678 679 680 681 682
#elif defined(__arm__)
            mmtmpPMI0 = vmull_s16(((int16x4_t*)dl_ch0_128)[0], ((int16x4_t*)dl_ch1_128)[0]);
            mmtmpPMI1 = vmull_s16(((int16x4_t*)dl_ch0_128)[1], ((int16x4_t*)dl_ch1_128)[1]);
            pmi128_re = vqaddq_s32(pmi128_re,vcombine_s32(vpadd_s32(vget_low_s32(mmtmpPMI0),vget_high_s32(mmtmpPMI0)),vpadd_s32(vget_low_s32(mmtmpPMI1),vget_high_s32(mmtmpPMI1))));

            mmtmpPMI0b = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)dl_ch0_128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)dl_ch1_128)[0]);
            mmtmpPMI1b = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)dl_ch0_128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)dl_ch1_128)[1]);
            pmi128_im = vqaddq_s32(pmi128_im,vcombine_s32(vpadd_s32(vget_low_s32(mmtmpPMI0b),vget_high_s32(mmtmpPMI0b)),vpadd_s32(vget_low_s32(mmtmpPMI1b),vget_high_s32(mmtmpPMI1b))));

#endif
683 684 685 686
            dl_ch0_128++;
            dl_ch1_128++;
          }

687 688 689 690
          ue->measurements.subband_pmi_re[eNB_id][subband][aarx] = (((int *)&pmi128_re)[0] + ((int *)&pmi128_re)[1] + ((int *)&pmi128_re)[2] + ((int *)&pmi128_re)[3])>>2;
          ue->measurements.subband_pmi_im[eNB_id][subband][aarx] = (((int *)&pmi128_im)[0] + ((int *)&pmi128_im)[1] + ((int *)&pmi128_im)[2] + ((int *)&pmi128_im)[3])>>2;
          ue->measurements.wideband_pmi_re[eNB_id][aarx] += ue->measurements.subband_pmi_re[eNB_id][subband][aarx];
          ue->measurements.wideband_pmi_im[eNB_id][aarx] += ue->measurements.subband_pmi_im[eNB_id][subband][aarx];
691 692 693
        } // subband loop
      } // rx antenna loop
    }  // if frame_parms->mode1_flag == 0
694
    else {
695 696
      // cqi information only for mode 1
      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
697
        dl_ch0    = &ue->common_vars.dl_ch_estimates[eNB_id][aarx][4];
698 699 700 701 702

        for (subband=0; subband<7; subband++) {

          // cqi
          if (aarx==0)
703
            ue->measurements.subband_cqi_tot[eNB_id][subband]=0;
704 705 706 707

          if (subband<6) {
            //      for (i=0;i<48;i++)
            //        printf("subband %d (%d) : %d,%d\n",subband,i,((short *)dl_ch0)[2*i],((short *)dl_ch0)[1+(2*i)]);
708 709
            ue->measurements.subband_cqi[eNB_id][aarx][subband] =
              (signal_energy_nodc(dl_ch0,48) ) - ue->measurements.n0_power[aarx];
710

711 712 713
            ue->measurements.subband_cqi_tot[eNB_id][subband] += ue->measurements.subband_cqi[eNB_id][aarx][subband];
            ue->measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(ue->measurements.subband_cqi[eNB_id][aarx][subband],
                ue->measurements.n0_power[aarx]);
714 715 716
          } else {
            //      for (i=0;i<12;i++)
            //        printf("subband %d (%d) : %d,%d\n",subband,i,((short *)dl_ch0)[2*i],((short *)dl_ch0)[1+(2*i)]);
717 718 719 720
            ue->measurements.subband_cqi[eNB_id][aarx][subband] = (signal_energy_nodc(dl_ch0,12) ) - ue->measurements.n0_power[aarx];
            ue->measurements.subband_cqi_tot[eNB_id][subband] += ue->measurements.subband_cqi[eNB_id][aarx][subband];
            ue->measurements.subband_cqi_dB[eNB_id][aarx][subband] = dB_fixed2(ue->measurements.subband_cqi[eNB_id][aarx][subband],
                ue->measurements.n0_power[aarx]);
721 722 723
          }

          dl_ch1+=48;
724
          //    msg("subband_cqi[%d][%d][%d] => %d (%d dB)\n",eNB_id,aarx,subband,ue->measurements.subband_cqi[eNB_id][aarx][subband],ue->measurements.subband_cqi_dB[eNB_id][aarx][subband]);
725 726 727 728
        }
      }

      for (subband=0; subband<nb_subbands; subband++) {
729
        ue->measurements.subband_cqi_tot_dB[eNB_id][subband] = dB_fixed2(ue->measurements.subband_cqi_tot[eNB_id][subband],ue->measurements.n0_power_tot);
730
      }
731 732
    }

733
    ue->measurements.rank[eNB_id] = 0;
734 735

    for (i=0; i<nb_subbands; i++) {
736
      ue->measurements.selected_rx_antennas[eNB_id][i] = 0;
737 738

      if (frame_parms->nb_antennas_rx>1) {
739 740
        if (ue->measurements.subband_cqi_dB[eNB_id][0][i] >= ue->measurements.subband_cqi_dB[eNB_id][1][i])
          ue->measurements.selected_rx_antennas[eNB_id][i] = 0;
741
        else
742
          ue->measurements.selected_rx_antennas[eNB_id][i] = 1;
743
      } else
744
        ue->measurements.selected_rx_antennas[eNB_id][i] = 0;
745 746
    }

747
    // if(eNB_id==0)
748
    // printf("in lte_ue_measurements: selected rx_antenna[eNB_id==0]:%u\n", ue->measurements.selected_rx_antennas[eNB_id][i]);
749
  }  // eNB_id loop
750

751
#if defined(__x86_64__) || defined(__i386__)
752 753
  _mm_empty();
  _m_empty();
754
#endif
755
}
756 757


758
void lte_ue_measurements_emul(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id)
759
{
760

761
  msg("[PHY] EMUL UE lte_ue_measurements_emul subframe %d, eNB_id %d\n",subframe,eNB_id);
762
}
763