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

knopp's avatar
 
knopp committed
35
//#define DEBUG_MEAS
36 37

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


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

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


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

}
#endif


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

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


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

73
  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,
74 75 76
        (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);
77

78 79 80 81
  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));
82 83
}

84

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

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

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

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

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

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

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

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

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

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

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

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

124
  return 0xFFFFFFFF;
125 126
}

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

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

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

135
  return 0xFFFFFFFF;
136 137
}

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

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

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

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

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

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

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

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

165
}
166

167
void ue_rrc_measurements(PHY_VARS_UE *ue,
168
                         uint8_t subframe,
169 170
                         uint8_t abstraction_flag)
{
171

172
  int aarx,rb;
173
  int16_t *rxF,*rxF_pss,*rxF_sss;
174

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


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

182
    if (eNB_offset==0) {
183 184
      ue->measurements.rssi = 0;
      ue->measurements.n0_power_tot = 0;
185

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

190 191
          if (ue->frame_parms.Ncp==NORMAL) {
            for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
192

193 194
	      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)];
195
	      
196 197

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

200 201 202 203 204 205 206
	      //              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]);
207
              //+ve spectrum from SSS
208 209 210 211 212
	      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]);
213
              //+ve spectrum from PSS
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
              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);
              ue->measurements.n0_power_tot +=  ue->measurements.n0_power[aarx];
229 230
            }

231 232
	    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);
233
	  }
234
        }
235
	else if ((ue->frame_parms.frame_type == TDD) &&
236
		 (subframe == 0)) {  // TDD SSS, compute noise in DTX REs
237

238 239
          if (ue->frame_parms.Ncp==NORMAL) {
            for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
240

241
	      rxF_sss = (int16_t *)&ue->common_vars.rxdataF[aarx][(6*ue->frame_parms.ofdm_symbol_size)];
242 243
	      // 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
244
	      rxF_pss = (int16_t *)&ue->common_vars.rxdataF[aarx][(7*ue->frame_parms.ofdm_symbol_size)];
245 246
	      
	      //-ve spectrum from SSS
247 248 249 250 251
	      //              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]));
252
	      //+ve spectrum from SSS
253 254 255 256 257
	      //	      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]));
258
	      
259 260
	      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];	  
261
	    }	      
262 263
	    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);
264 265 266 267
	      
	    
	  }
	}
268 269
      }
    }
270
    // recompute nushift with eNB_offset corresponding to adjacent eNB on which to perform channel estimation
271
    //    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);
272
    if (eNB_offset > 0)
273
      Nid_cell = ue->measurements.adj_cell_id[eNB_offset-1];
274 275 276 277 278 279


    nushift =  Nid_cell%6;



280
    ue->measurements.rsrp[eNB_offset] = 0;
281 282 283


    if (abstraction_flag == 0) {
284

285 286
      // compute RSRP using symbols 0 and 4-frame_parms->Ncp

287
      for (l=0,nu=0; l<=(4-ue->frame_parms.Ncp); l+=(4-ue->frame_parms.Ncp),nu=3) {
288
        k = (nu + nushift)%6;
289
#ifdef DEBUG_MEAS
290
        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,
291
              eNB_offset,k,l);
292
#endif
293

294 295 296
        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;
297

298 299
          if (l==(4-ue->frame_parms.Ncp)) {
            for (rb=0; rb<ue->frame_parms.N_RB_DL; rb++) {
300 301 302

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

303
              ue->measurements.rsrp[eNB_offset] += (((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1]));
304
              //        printf("rb %d, off %d : %d\n",rb,off,((((int32_t)rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1])));
305
	      //	      if ((ue->frame_rx&0x3ff) == 0)
306
	      //                printf("rb %d, off %d : %d\n",rb,off,((rxF[off]*rxF[off])+(rxF[off+1]*rxF[off+1])));
307

308
              
309 310
              off+=12;

311
              if (off>=(ue->frame_parms.ofdm_symbol_size<<1))
312 313
                off = (1+k)<<1;

314
              ue->measurements.rsrp[eNB_offset] += (((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1]));
315 316
              //    printf("rb %d, off %d : %d\n",rb,off,(((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1])));
              /*
317
                if ((ue->frame_rx&0x3ff) == 0)
318 319 320 321
                printf("rb %d, off %d : %d\n",rb,off,((rxF[off]*rxF[off])+(rxF[off+1]*rxF[off+1])));
              */
              off+=12;

322
              if (off>=(ue->frame_parms.ofdm_symbol_size<<1))
323 324 325 326 327 328 329
                off = (1+k)<<1;

            }

            /*
            if ((eNB_offset==0)&&(l==0)) {
            for (i=0;i<6;i++,off2+=4)
330 331
            ue->measurements.rssi += ((rxF[off2]*rxF[off2])+(rxF[off2+1]*rxF[off2+1]));
            if (off2==(ue->frame_parms.ofdm_symbol_size<<2))
332 333
            off2=4;
            for (i=0;i<6;i++,off2+=4)
334
            ue->measurements.rssi += ((rxF[off2]*rxF[off2])+(rxF[off2+1]*rxF[off2+1]));
335 336
            }
            */
337
            //    printf("slot %d, rb %d => rsrp %d, rssi %d\n",slot,rb,ue->measurements.rsrp[eNB_offset],ue->measurements.rssi);
338 339
          }
        }
340 341
      }

342
      // 2 RE per PRB
343 344 345
      //      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]);
346
      if (eNB_offset == 0) {
347 348 349 350
        //  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);
351
      }
352

353 354
      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;
355
      else
356
        ue->measurements.rsrq[eNB_offset] = -12000;
357

358
      //((200*ue->measurements.rsrq[eNB_offset]) + ((1024-200)*100*ue->measurements.rsrp[eNB_offset]*ue->frame_parms.N_RB_DL/ue->measurements.rssi))>>10;
359
    } else { // Do abstraction of RSRP and RSRQ
360
      ue->measurements.rssi = ue->measurements.rx_power_avg[0];
361
      // dummay value for the moment
362 363
      ue->measurements.rsrp[eNB_offset] = -93 ;
      ue->measurements.rsrq[eNB_offset] = 3;
364 365

    }
366

367
#ifdef DEBUG_MEAS
368

369
    //    if (slot == 0) {
370

371
      if (eNB_offset == 0)
372 373
        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,
374 375 376
              10*log10(ue->measurements.rssi),
              ue->rx_total_gain_dB,
              ue->measurements.n0_power_tot_dBm);
377

378
      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",
379
            ue->Mod_id,
380
            ue->proc.proc_rxtx[subframe&1].frame_rx,subframe,eNB_offset,
381 382 383 384 385 386 387 388 389
            (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));
390

391
      //    }
392

393 394 395
#endif
  }

396 397
}

398
void lte_ue_measurements(PHY_VARS_UE *ue,
399 400 401 402 403 404
                         unsigned int subframe_offset,
                         unsigned char N0_symbol,
                         unsigned char abstraction_flag)
{


405
  int aarx,aatx,eNB_id=0; //,gain_offset=0;
406 407 408
  //int rx_power[NUMBER_OF_CONNECTED_eNB_MAX];
  int i;
  unsigned int limit,subband;
409
#if defined(__x86_64__) || defined(__i386__)
410
  __m128i *dl_ch0_128,*dl_ch1_128;
411 412 413
#elif defined(__arm__)
  int16x8_t *dl_ch0_128, *dl_ch1_128;
#endif
414
  int *dl_ch0,*dl_ch1;
415
  LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
  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
447
  for (eNB_id=0; eNB_id<ue->n_connected_eNB; eNB_id++) {
448
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
Xiwen JIANG's avatar
Xiwen JIANG committed
449
      for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
450 451
        ue->measurements.rx_spatial_power[eNB_id][aatx][aarx] =
          (signal_energy_nodc(&ue->common_vars.dl_ch_estimates[eNB_id][(aatx<<1) + aarx][0],
452
                              (N_RB_DL*12)));
453
        //- ue->measurements.n0_power[aarx];
454

455 456
        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];
457

458
        ue->measurements.rx_spatial_power_dB[eNB_id][aatx][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_spatial_power[eNB_id][aatx][aarx]);
459 460

        if (aatx==0)
461
          ue->measurements.rx_power[eNB_id][aarx] = ue->measurements.rx_spatial_power[eNB_id][aatx][aarx];
462
        else
463
          ue->measurements.rx_power[eNB_id][aarx] += ue->measurements.rx_spatial_power[eNB_id][aatx][aarx];
464 465
      } //aatx

466
      ue->measurements.rx_power_dB[eNB_id][aarx] = (unsigned short) dB_fixed(ue->measurements.rx_power[eNB_id][aarx]);
467 468

      if (aarx==0)
469
        ue->measurements.rx_power_tot[eNB_id] = ue->measurements.rx_power[eNB_id][aarx];
470
      else
471
        ue->measurements.rx_power_tot[eNB_id] += ue->measurements.rx_power[eNB_id][aarx];
472 473
    } //aarx

474
    ue->measurements.rx_power_tot_dB[eNB_id] = (unsigned short) dB_fixed(ue->measurements.rx_power_tot[eNB_id]);
475 476 477 478

  } //eNB_id

  // filter to remove jitter
479 480 481 482 483 484 485 486 487
  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);
488
  } else {
489 490
    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];
491

492 493
    ue->measurements.n0_power_avg = ue->measurements.n0_power_tot;
    ue->init_averaging = 0;
494 495
  }

496 497 498 499 500
  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;
501
#ifdef DEBUG_MEAS
knopp's avatar
knopp committed
502
    LOG_I(PHY,"[eNB %d] lte_ue_measurements: RSSI %d dBm, RSSI (digital) %d dB\n",
503 504
          eNB_id,ue->measurements.rx_rssi_dBm[eNB_id],
          ue->measurements.rx_power_avg_dB[eNB_id]);
505
#endif
506 507
  }

508
  ue->measurements.n0_power_avg_dB = dB_fixed( ue->measurements.n0_power_avg);
509

510
  for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) {
511 512 513 514
    if (frame_parms->mode1_flag==0) {
      // cqi/pmi information

      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
515 516
        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];
517 518 519 520 521

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

          // cqi
          if (aarx==0)
522
            ue->measurements.subband_cqi_tot[eNB_id][subband]=0;
523 524 525 526 527

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

531 532
            if ( ue->measurements.subband_cqi[eNB_id][aarx][subband] < 0)
              ue->measurements.subband_cqi[eNB_id][aarx][subband]=0;
533 534 535

            /*
            else
536
            ue->measurements.subband_cqi[eNB_id][aarx][subband]-=ue->measurements.n0_power[aarx];
537 538
            */

539 540 541
            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]);
542 543 544
          } 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)]);
545 546 547 548 549
            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]);
550 551 552 553
          }

          dl_ch1+=subband_size;
          dl_ch0+=subband_size;
554
          //    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]);
555 556 557 558 559
        }

      }

      for (subband=0; subband<nb_subbands; subband++) {
560 561
        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);
562 563 564
      }

      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
565
        // 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)
566 567

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

570 571
        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];
572 573
#elif defined(__arm__)
        int32x4_t pmi128_re,pmi128_im,mmtmpPMI0,mmtmpPMI1,mmtmpPMI0b,mmtmpPMI1b;
574

575 576
        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];
577 578

#endif
579 580 581 582
        for (subband=0; subband<nb_subbands; subband++) {


          // pmi
583
#if defined(__x86_64__) || defined(__i386__)
584 585
          pmi128_re = _mm_setzero_si128();
          pmi128_im = _mm_setzero_si128();
586 587 588 589
#elif defined(__arm__)
          pmi128_re = vdupq_n_s32(0);
	  pmi128_im = vdupq_n_s32(0);
#endif
590 591 592 593 594 595 596 597 598 599 600
          // 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
601
#if defined(__x86_64__) || defined(__i386__)
602 603 604 605 606 607 608 609
            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);
610 611 612 613 614 615 616 617 618 619
#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
620 621 622 623
            dl_ch0_128++;
            dl_ch1_128++;
          }

624 625 626 627
          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];
628 629 630
        } // subband loop
      } // rx antenna loop
    }  // if frame_parms->mode1_flag == 0
631
    else {
632 633
      // cqi information only for mode 1
      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
634
        dl_ch0    = &ue->common_vars.dl_ch_estimates[eNB_id][aarx][4];
635 636 637 638 639

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

          // cqi
          if (aarx==0)
640
            ue->measurements.subband_cqi_tot[eNB_id][subband]=0;
641 642 643 644

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

648 649 650
            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]);
651 652 653
          } 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)]);
654 655 656 657
            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]);
658 659 660
          }

          dl_ch1+=48;
661
          //    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]);
662 663 664 665
        }
      }

      for (subband=0; subband<nb_subbands; subband++) {
666
        ue->measurements.subband_cqi_tot_dB[eNB_id][subband] = dB_fixed2(ue->measurements.subband_cqi_tot[eNB_id][subband],ue->measurements.n0_power_tot);
667
      }
668 669
    }

670
    ue->measurements.rank[eNB_id] = 0;
671 672

    for (i=0; i<nb_subbands; i++) {
673
      ue->measurements.selected_rx_antennas[eNB_id][i] = 0;
674 675

      if (frame_parms->nb_antennas_rx>1) {
676 677
        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;
678
        else
679
          ue->measurements.selected_rx_antennas[eNB_id][i] = 1;
680
      } else
681
        ue->measurements.selected_rx_antennas[eNB_id][i] = 0;
682 683
    }

684
    // if(eNB_id==0)
685
    // printf("in lte_ue_measurements: selected rx_antenna[eNB_id==0]:%u\n", ue->measurements.selected_rx_antennas[eNB_id][i]);
686
  }  // eNB_id loop
687

688
#if defined(__x86_64__) || defined(__i386__)
689 690
  _mm_empty();
  _m_empty();
691
#endif
692
}
693 694


695
void lte_ue_measurements_emul(PHY_VARS_UE *ue,uint8_t subframe,uint8_t eNB_id)
696
{
697

698
  msg("[PHY] EMUL UE lte_ue_measurements_emul subframe %d, eNB_id %d\n",subframe,eNB_id);
699
}
700