lte_ue_measurements.c 54.7 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))

Cedric Roux's avatar
Cedric Roux committed
35 36
//#define DEBUG_MEAS_RRC
//#define DEBUG_MEAS_UE
37
//#define DEBUG_RANK_EST
38

39 40
int16_t cond_num_threshold = 0;

41
#ifdef USER_MODE
42
void print_shorts(char *s,short *x)
43
{
44 45 46


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

}
51
void print_ints(char *s,int *x)
52
{
53 54 55


  printf("%s  : %d,%d,%d,%d\n",s,
56
         x[0],x[1],x[2],x[3]
57
        );
58 59 60 61 62

}
#endif


63 64
int16_t get_PL(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
65

66
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
67
  /*
68
  int RSoffset;
69 70


71
  if (ue->frame_parms.mode1_flag == 1)
72 73 74
    RSoffset = 6;
  else
    RSoffset = 3;
75
  */
76

77
  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,
78 79 80
        (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);
81

82 83 84 85
  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));
86 87
}

88

89 90
uint8_t get_n_adj_cells (uint8_t Mod_id,uint8_t CC_id)
{
91

92
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
93

94 95
  if (ue)
    return ue->measurements.n_adj_cells;
96
  else
97 98 99
    return 0;
}

100 101
uint32_t get_rx_total_gain_dB (uint8_t Mod_id,uint8_t CC_id)
{
102

103
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
104

105 106
  if (ue)
    return ue->rx_total_gain_dB;
107

108
  return 0xFFFFFFFF;
109
}
110 111
uint32_t get_RSSI (uint8_t Mod_id,uint8_t CC_id)
{
112

113
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
114

115 116
  if (ue)
    return ue->measurements.rssi;
117

118
  return 0xFFFFFFFF;
119
}
120 121 122
uint32_t get_RSRP(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{

123
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
124

125 126
  if (ue)
    return ue->measurements.rsrp[eNB_index];
127

128
  return 0xFFFFFFFF;
129 130
}

131 132
uint32_t get_RSRQ(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
133

134
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
135

136 137
  if (ue)
    return ue->measurements.rsrq[eNB_index];
138

139
  return 0xFFFFFFFF;
140 141
}

142 143 144
int8_t set_RSRP_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrp)
{

145
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
146

147 148
  if (ue) {
    ue->measurements.rsrp_filtered[eNB_index]=rsrp;
149 150
    return 0;
  }
151

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

156 157
int8_t set_RSRQ_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrq)
{
158

159
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
160

161 162
  if (ue) {
    ue->measurements.rsrq_filtered[eNB_index]=rsrq;
163
    return 0;
164
  }
165

166 167
  LOG_W(PHY,"[UE%d] could not set the rsrq\n",Mod_id);
  return -1;
168

169
}
170

171
void ue_rrc_measurements(PHY_VARS_UE *ue,
172 173
    uint8_t slot,
    uint8_t abstraction_flag)
174
{
175

176
  uint8_t subframe = slot>>1;
177
  int aarx,rb;
Bilel's avatar
Bilel committed
178 179 180 181
  uint8_t pss_symb;
  uint8_t sss_symb;

  int32_t **rxdataF;
182
  int16_t *rxF,*rxF_pss,*rxF_sss;
183

184
  uint16_t Nid_cell = ue->frame_parms.Nid_cell;
185 186
  uint8_t eNB_offset,nu,l,nushift,k;
  uint16_t off;
187

188 189 190 191 192 193
  //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
194

195
  //LOG_I(PHY,"UE RRC MEAS Start Subframe %d Frame Type %d slot %d \n",subframe,ue->frame_parms.frame_type,slot);
196
  for (eNB_offset = 0; eNB_offset<1+ue->measurements.n_adj_cells; eNB_offset++) {
197

198
    if (eNB_offset==0) {
199
      ue->measurements.rssi = 0;
200
      //ue->measurements.n0_power_tot = 0;
201

202
      if (abstraction_flag == 0) {
Bilel's avatar
Bilel committed
203 204 205 206
        if ( ((ue->frame_parms.frame_type == FDD) && ((subframe == 0) || (subframe == 5))) ||
             ((ue->frame_parms.frame_type == TDD) && ((subframe == 1) || (subframe == 6)))
                )
        {  // FDD PSS/SSS, compute noise in DTX REs
207

208 209
          if (ue->frame_parms.Ncp==NORMAL) {
            for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
210

Bilel's avatar
Bilel committed
211 212
          if(ue->frame_parms.frame_type == FDD)
          {
213 214
          rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(5*ue->frame_parms.ofdm_symbol_size)];
          rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(6*ue->frame_parms.ofdm_symbol_size)];
Bilel's avatar
Bilel committed
215 216 217 218 219 220
          }
          else
          {
              rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[(subframe+1)&0x1].rxdataF[aarx][(13*ue->frame_parms.ofdm_symbol_size)];
              rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(2*ue->frame_parms.ofdm_symbol_size)];
          }
221
              //-ve spectrum from SSS
222

223
              //+ve spectrum from SSS
224
              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]));
225 226
              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]));
227 228
              //              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]);
229
              //+ve spectrum from PSS
230 231 232
              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]));
233 234
          //              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
Bilel's avatar
Bilel committed
235 236 237 238 239 240 241 242 243 244
              if(ue->frame_parms.frame_type == FDD)
              {
                  rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(6*ue->frame_parms.ofdm_symbol_size)];
                  rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(7*ue->frame_parms.ofdm_symbol_size)];
              }
              else
              {
                  rxF_sss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[(subframe+1)&0x1].rxdataF[aarx][(14*ue->frame_parms.ofdm_symbol_size)];
                  rxF_pss = (int16_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[aarx][(3*ue->frame_parms.ofdm_symbol_size)];
              }
245 246
          //              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]);
247 248 249
              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]));
250

Bilel's avatar
Bilel committed
251 252 253 254
              ue->measurements.n0_power[aarx] = (((int32_t)rxF_sss[-70]*rxF_sss[-70])+((int32_t)rxF_sss[-69]*rxF_sss[-69]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[-68]*rxF_sss[-68])+((int32_t)rxF_sss[-67]*rxF_sss[-67]));
              ue->measurements.n0_power[aarx] += (((int32_t)rxF_sss[-66]*rxF_sss[-66])+((int32_t)rxF_sss[-65]*rxF_sss[-65]));

255 256
          //              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]);
257
              ue->measurements.n0_power_dB[aarx] = (unsigned short) dB_fixed(ue->measurements.n0_power[aarx]/12);
258
              ue->measurements.n0_power_tot /*+=*/ = ue->measurements.n0_power[aarx];
259
        }
260

261 262
            //LOG_I(PHY,"Subframe %d RRC UE MEAS Noise Level %d \n", subframe, ue->measurements.n0_power_tot);

263 264 265
        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 {
266
            LOG_E(PHY, "Not yet implemented: noise power calculation when prefix length = EXTENDED\n");
267
        }
268
        }
269
        else if ((ue->frame_parms.frame_type == TDD) &&
Bilel's avatar
Bilel committed
270
                 ((subframe == 1) || (subframe == 6))) {  // TDD PSS/SSS, compute noise in DTX REs // 2016-09-29 wilson fix incorrect noise power calculation
271 272


Bilel's avatar
Bilel committed
273 274
          pss_symb = 2;
          sss_symb = ue->frame_parms.symbols_per_tti-1;
275 276
          if (ue->frame_parms.Ncp==NORMAL) {
            for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
277

Bilel's avatar
Bilel committed
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
                rxdataF  =  ue->common_vars.common_vars_rx_data_per_thread[(subframe&0x1)].rxdataF;
                rxF_pss  = (int16_t *) &rxdataF[aarx][((pss_symb*(ue->frame_parms.ofdm_symbol_size)))];

                rxdataF  =  ue->common_vars.common_vars_rx_data_per_thread[(subframe+1)&0x1].rxdataF;
                rxF_sss  = (int16_t *) &rxdataF[aarx][((sss_symb*(ue->frame_parms.ofdm_symbol_size)))];

                //-ve spectrum from SSS
            //          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]);

            //              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]);
                //+ve spectrum from SSS
            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]);
                //+ve spectrum from PSS
                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.common_vars_rx_data_per_thread[subframe&0x1].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);
                ue->measurements.n0_power_tot /*+=*/ = ue->measurements.n0_power[aarx];
316
        }
317

Bilel's avatar
Bilel committed
318 319
        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);
320

321
        //LOG_I(PHY,"Subframe %d RRC UE MEAS Noise Level %d \n", subframe, ue->measurements.n0_power_tot);
322

323 324
          }
        }
325 326
      }
    }
327
    // recompute nushift with eNB_offset corresponding to adjacent eNB on which to perform channel estimation
328
    //    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);
329
    if (eNB_offset > 0)
330
      Nid_cell = ue->measurements.adj_cell_id[eNB_offset-1];
331 332 333 334 335 336


    nushift =  Nid_cell%6;



337
    ue->measurements.rsrp[eNB_offset] = 0;
338 339 340


    if (abstraction_flag == 0) {
341

342 343
      // compute RSRP using symbols 0 and 4-frame_parms->Ncp

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

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

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

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

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

365

366 367
              off+=12;

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

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

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

            }

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

399
      // 2 RE per PRB
400 401 402
      //      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]);
403
      if (eNB_offset == 0) {
404 405 406 407
        //  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);
408
      }
409

410 411
      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;
412
      else
413
        ue->measurements.rsrq[eNB_offset] = -12000;
414

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

    }
423

424
#ifdef DEBUG_MEAS_RRC
425

426
    //    if (slot == 0) {
427

428
      if (eNB_offset == 0)
Elena Lukashova's avatar
Elena Lukashova committed
429
       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,
430
              ue->proc.proc_rxtx[subframe&1].frame_rx,subframe,10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB,
431 432 433
              10*log10(ue->measurements.rssi),
              ue->rx_total_gain_dB,
              ue->measurements.n0_power_tot_dBm);
434

435
      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",
436
            ue->Mod_id,
437
            ue->proc.proc_rxtx[subframe&1].frame_rx,subframe,eNB_offset,
438 439 440 441 442 443 444 445 446
            (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));
447

448
      //    }
449

450 451 452
#endif
  }

453 454
}

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


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
#elif defined(__arm__)
  int16x8_t *dl_ch0_128, *dl_ch1_128;
472
#endif
473
  int *dl_ch0,*dl_ch1;
474

475
  LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
476 477
  int nb_subbands,subband_size,last_subband_size;
  int N_RB_DL = frame_parms->N_RB_DL;
478 479


480
  int rank_tm3_tm4;
481 482


483
  ue->measurements.nb_antennas_rx = frame_parms->nb_antennas_rx;
484

485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511

  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;
  }
512

513
  // signal measurements
514
  for (eNB_id=0; eNB_id<ue->n_connected_eNB; eNB_id++) {
515
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
Xiwen JIANG's avatar
Xiwen JIANG committed
516
      for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
517
        ue->measurements.rx_spatial_power[eNB_id][aatx][aarx] =
518
          (signal_energy_nodc(&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][(aatx<<1) + aarx][0],
519
                              (N_RB_DL*12)));
520
        //- ue->measurements.n0_power[aarx];
521

522 523
        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];
524

525
        ue->measurements.rx_spatial_power_dB[eNB_id][aatx][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]);
526 527

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

533
      ue->measurements.rx_power_dB[eNB_id][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_power[eNB_id][aarx]);
534 535

      if (aarx==0)
536
        ue->measurements.rx_power_tot[eNB_id] = ue->measurements.rx_power[eNB_id][aarx];
537
      else
538
        ue->measurements.rx_power_tot[eNB_id] += ue->measurements.rx_power[eNB_id][aarx];
539 540
    } //aarx

541
    ue->measurements.rx_power_tot_dB[eNB_id] = (unsigned short) dB_fixed(ue->measurements.rx_power_tot[eNB_id]);
542 543 544

  } //eNB_id

545
  eNB_id=0;
546
  if (ue->transmission_mode[0]==4 || ue->transmission_mode[0]==3){
547 548 549 550 551 552 553 554
    if (rank_adaptation == 1)
      rank_tm3_tm4 = rank_estimation_tm3_tm4(&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][0][4],
                                             &ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][2][4],
                                             &ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][1][4],
                                             &ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][3][4],
                                             N_RB_DL);
    else
      rank_tm3_tm4=1;
555
#ifdef DEBUG_RANK_EST
Elena Lukashova's avatar
Elena Lukashova committed
556
  printf("rank tm3 or tm4 %d\n", rank_tm3_tm4);
557
#endif
558
  }
559

560 561 562 563 564 565 566
  if (ue->transmission_mode[eNB_id]!=4 && ue->transmission_mode[eNB_id]!=3)
    ue->measurements.rank[eNB_id] = 0;
  else
    ue->measurements.rank[eNB_id] = rank_tm3_tm4;
  //  printf ("tx mode %d\n", ue->transmission_mode[eNB_id]);
  //  printf ("rank %d\n", ue->PHY_measurements.rank[eNB_id]);

567
  // filter to remove jitter
568 569 570 571 572 573
  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);

574
    //LOG_I(PHY,"Noise Power Computation: k1 %d k2 %d n0 avg %d n0 tot %d\n", k1, k2, ue->measurements.n0_power_avg,
575
    //    ue->measurements.n0_power_tot);
576 577 578
    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);
579
  } else {
580 581
    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];
582

583 584
    ue->measurements.n0_power_avg = ue->measurements.n0_power_tot;
    ue->init_averaging = 0;
585 586
  }

587 588 589 590 591
  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;
592
#ifdef DEBUG_MEAS_UE
Bilel's avatar
Bilel committed
593
      LOG_I(PHY,"[eNB %d] Subframe %d, RSSI %d dBm, RSSI (digital) %d dB, WBandCQI %d dB, rxPwrAvg %d, n0PwrAvg %d\n",
594
            eNB_id,
595
            subframe,
596 597 598 599
            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],
600
            ue->measurements.n0_power_tot);
601
#endif
602 603
  }

604
  ue->measurements.n0_power_avg_dB = dB_fixed( ue->measurements.n0_power_avg);
605

606
  for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) {
607 608 609 610
    if (frame_parms->mode1_flag==0) {
      // cqi/pmi information

      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
611 612
        dl_ch0    = &ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][aarx][4];
        dl_ch1    = &ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][2+aarx][4];
613 614 615 616 617

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

          // cqi
          if (aarx==0)
618
            ue->measurements.subband_cqi_tot[eNB_id][subband]=0;
619 620 621 622 623

          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)]);
            */
624
            ue->measurements.subband_cqi[eNB_id][aarx][subband] =
625 626
              (signal_energy_nodc(dl_ch0,subband_size) + signal_energy_nodc(dl_ch1,subband_size));

627 628
            if ( ue->measurements.subband_cqi[eNB_id][aarx][subband] < 0)
              ue->measurements.subband_cqi[eNB_id][aarx][subband]=0;
629 630 631

            /*
            else
632
            ue->measurements.subband_cqi[eNB_id][aarx][subband]-=ue->measurements.n0_power[aarx];
633 634
            */

635 636 637
            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]);
638 639 640
          } 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)]);
641 642 643 644 645
            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]);
646 647 648 649
          }

          dl_ch1+=subband_size;
          dl_ch0+=subband_size;
650
          //    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]);
651 652 653 654 655
        }

      }

      for (subband=0; subband<nb_subbands; subband++) {
656 657
        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);
658 659 660
      }

      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
661
        //printf("aarx=%d", aarx);
662
        // 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)
663 664

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

667 668
        dl_ch0_128    = (__m128i *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][aarx][4];
        dl_ch1_128    = (__m128i *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][2+aarx][4];
669 670
#elif defined(__arm__)
        int32x4_t pmi128_re,pmi128_im,mmtmpPMI0,mmtmpPMI1,mmtmpPMI0b,mmtmpPMI1b;
671

672 673
        dl_ch0_128    = (int16x8_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][aarx][4];
        dl_ch1_128    = (int16x8_t *)&ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][2+aarx][4];
674 675

#endif
676 677 678 679
        for (subband=0; subband<nb_subbands; subband++) {


          // pmi
680
#if defined(__x86_64__) || defined(__i386__)
681

682
          pmi128_re = _mm_xor_si128(pmi128_re,pmi128_re);
Elena Lukashova's avatar
Elena Lukashova committed
683
          pmi128_im = _mm_xor_si128(pmi128_im,pmi128_im);
684
#elif defined(__arm__)
Elena Lukashova's avatar
Elena Lukashova committed
685

686
          pmi128_re = vdupq_n_s32(0);
687
          pmi128_im = vdupq_n_s32(0);
688
#endif
689 690 691 692 693 694 695 696
          // 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++) {
697 698

#if defined(__x86_64__) || defined(__i386__)
699
              mmtmpPMI0 = _mm_xor_si128(mmtmpPMI0,mmtmpPMI0);
700
              mmtmpPMI1 = _mm_xor_si128(mmtmpPMI1,mmtmpPMI1);
701 702 703

            // For each RE in subband perform ch0 * conj(ch1)
            // multiply by conjugated channel
704 705
                //  print_ints("ch0",&dl_ch0_128[0]);
                //  print_ints("ch1",&dl_ch1_128[0]);
Elena Lukashova's avatar
Elena Lukashova committed
706

707 708
            mmtmpPMI0 = _mm_madd_epi16(dl_ch0_128[0],dl_ch1_128[0]);
                 //  print_ints("re",&mmtmpPMI0);
Elena Lukashova's avatar
Elena Lukashova committed
709 710
            mmtmpPMI1 = _mm_shufflelo_epi16(dl_ch1_128[0],_MM_SHUFFLE(2,3,0,1));
              //  print_ints("_mm_shufflelo_epi16",&mmtmpPMI1);
711
            mmtmpPMI1 = _mm_shufflehi_epi16(mmtmpPMI1,_MM_SHUFFLE(2,3,0,1));
712
                //  print_ints("_mm_shufflehi_epi16",&mmtmpPMI1);
713
            mmtmpPMI1 = _mm_sign_epi16(mmtmpPMI1,*(__m128i*)&conjugate[0]);
714
               //  print_ints("_mm_sign_epi16",&mmtmpPMI1);
715
            mmtmpPMI1 = _mm_madd_epi16(mmtmpPMI1,dl_ch0_128[0]);
716
               //   print_ints("mm_madd_epi16",&mmtmpPMI1);
717 718
            // mmtmpPMI1 contains imag part of 4 consecutive outputs (32-bit)
            pmi128_re = _mm_add_epi32(pmi128_re,mmtmpPMI0);
719
             //   print_ints(" pmi128_re 0",&pmi128_re);
720
            pmi128_im = _mm_add_epi32(pmi128_im,mmtmpPMI1);
721
               //   print_ints(" pmi128_im 0 ",&pmi128_im);
722

723
          /*  mmtmpPMI0 = _mm_xor_si128(mmtmpPMI0,mmtmpPMI0);
724
            mmtmpPMI1 = _mm_xor_si128(mmtmpPMI1,mmtmpPMI1);
725

726 727
            mmtmpPMI0 = _mm_madd_epi16(dl_ch0_128[1],dl_ch1_128[1]);
                 //  print_ints("re",&mmtmpPMI0);
728 729 730
            mmtmpPMI1 = _mm_shufflelo_epi16(dl_ch1_128[1],_MM_SHUFFLE(2,3,0,1));
              //  print_ints("_mm_shufflelo_epi16",&mmtmpPMI1);
            mmtmpPMI1 = _mm_shufflehi_epi16(mmtmpPMI1,_MM_SHUFFLE(2,3,0,1));
731
                //  print_ints("_mm_shufflehi_epi16",&mmtmpPMI1);
732
            mmtmpPMI1 = _mm_sign_epi16(mmtmpPMI1,*(__m128i*)&conjugate);
733
               //  print_ints("_mm_sign_epi16",&mmtmpPMI1);
734
            mmtmpPMI1 = _mm_madd_epi16(mmtmpPMI1,dl_ch0_128[1]);
735
               //   print_ints("mm_madd_epi16",&mmtmpPMI1);
736 737
            // mmtmpPMI1 contains imag part of 4 consecutive outputs (32-bit)
            pmi128_re = _mm_add_epi32(pmi128_re,mmtmpPMI0);
738
                //  print_ints(" pmi128_re 1",&pmi128_re);
739
            pmi128_im = _mm_add_epi32(pmi128_im,mmtmpPMI1);
740
            //print_ints(" pmi128_im 1 ",&pmi128_im);*/
741

742
#elif defined(__arm__)
Elena Lukashova's avatar
Elena Lukashova committed
743

744 745 746 747 748 749 750 751 752
            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
753 754 755 756
            dl_ch0_128++;
            dl_ch1_128++;
          }

757 758 759 760
          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];
761 762 763
        } // subband loop
      } // rx antenna loop
    }  // if frame_parms->mode1_flag == 0
764
    else {
765 766
      // cqi information only for mode 1
      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
767
        dl_ch0    = &ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][aarx][4];
768 769 770 771 772

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

          // cqi
          if (aarx==0)
773
            ue->measurements.subband_cqi_tot[eNB_id][subband]=0;
774 775 776 777

          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)]);
778 779
            ue->measurements.subband_cqi[eNB_id][aarx][subband] =
              (signal_energy_nodc(dl_ch0,48) ) - ue->measurements.n0_power[aarx];
780

781 782 783
            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]);
784 785 786
          } 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)]);
787 788 789 790
            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]);
791 792 793
          }

          dl_ch1+=48;
794
          //    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]);
795
        }
796 797
      }

798
      for (subband=0; subband<nb_subbands; subband++) {
799
        ue->measurements.subband_cqi_tot_dB[eNB_id][subband] = dB_fixed2(ue->measurements.subband_cqi_tot[eNB_id][subband],ue->measurements.n0_power_tot);
800 801 802
      }
    }

803
    //ue->measurements.rank[eNB_id] = 0;
804

805
    for (i=0; i<nb_subbands; i++) {
806
      ue->measurements.selected_rx_antennas[eNB_id][i] = 0;
807

808
      if (frame_parms->nb_antennas_rx>1) {
809 810
        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;
811
        else
812
          ue->measurements.selected_rx_antennas[eNB_id][i] = 1;
813
      } else
814
        ue->measurements.selected_rx_antennas[eNB_id][i] = 0;
815 816
    }

817
    // if(eNB_id==0)
818
    // printf("in lte_ue_measurements: selected rx_antenna[eNB_id==0]:%u\n", ue->measurements.selected_rx_antennas[eNB_id][i]);
819
  }  // eNB_id loop
820

821
#if defined(__x86_64__) || defined(__i386__)
822 823
  _mm_empty();
  _m_empty();
824
#endif
825
}
826 827


828
void lte_ue_measurements_emul(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id)
829
{
830

831
  msg("[PHY] EMUL UE lte_ue_measurements_emul subframe %d, eNB_id %d\n",subframe,eNB_id);
832
}
833

834

835 836 837 838
uint8_t rank_estimation_tm3_tm4 (int *dl_ch_estimates_00, // please respect the order of channel estimates
                                 int *dl_ch_estimates_01,
                                 int *dl_ch_estimates_10,
                                 int *dl_ch_estimates_11,
Elena Lukashova's avatar
Elena Lukashova committed
839 840
                                 unsigned short nb_rb)
{
841 842

  int i=0;
843
  int rank=0;
844 845 846 847 848 849 850 851 852
  int N_RB=nb_rb;
  int *ch00_rank, *ch01_rank, *ch10_rank, *ch11_rank;

  int32_t shift;
  int avg_0[2];
  int avg_1[2];

  int count=0;

853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876
  /* we need at least alignment to 16 bytes, let's put 32 to be sure
   * (maybe not necessary but doesn't hurt)
   */
  int32_t conjch00_ch01[12*N_RB] __attribute__((aligned(32)));
  int32_t conjch01_ch00[12*N_RB] __attribute__((aligned(32)));
  int32_t conjch10_ch11[12*N_RB] __attribute__((aligned(32)));
  int32_t conjch11_ch10[12*N_RB] __attribute__((aligned(32)));
  int32_t conjch00_ch00[12*N_RB] __attribute__((aligned(32)));
  int32_t conjch01_ch01[12*N_RB] __attribute__((aligned(32)));
  int32_t conjch10_ch10[12*N_RB] __attribute__((aligned(32)));
  int32_t conjch11_ch11[12*N_RB] __attribute__((aligned(32)));
  int32_t af_mf_00[12*N_RB] __attribute__((aligned(32)));
  int32_t af_mf_00_sq[12*N_RB] __attribute__((aligned(32)));
  int32_t af_mf_01_sq[12*N_RB] __attribute__((aligned(32)));
  int32_t af_mf_10_sq[12*N_RB] __attribute__((aligned(32)));
  int32_t af_mf_11_sq