ofdm_mod.c 11.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * 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
 */

22 23 24 25 26 27 28 29 30 31 32
/*
* @defgroup _PHY_MODULATION_
* @ingroup _physical_layer_ref_implementation_
* @{
\section _phy_modulation_ OFDM Modulation Blocks
This section deals with basic functions for OFDM Modulation.


*/

#include "PHY/defs.h"
Raymond Knopp's avatar
 
Raymond Knopp committed
33
#include "UTIL/LOG/log.h"
34
#include "UTIL/LOG/vcd_signal_dumper.h"
35

36 37 38 39 40
//static short temp2[2048*4] __attribute__((aligned(16)));

//#define DEBUG_OFDM_MOD


41 42
void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRAME_PARMS *frame_parms)
{
43

44
  uint8_t i;
45 46 47 48 49 50
  int short_offset=0;

  if ((2*nsymb) < frame_parms->symbols_per_tti)
    short_offset = 1;

  //  printf("nsymb %d\n",nsymb);
51
  for (i=0; i<((short_offset)+2*nsymb/frame_parms->symbols_per_tti); i++) {
52 53

#ifdef DEBUG_OFDM_MOD
54 55
    printf("slot i %d (txdata offset %d, txoutput %p)\n",i,(i*(frame_parms->samples_per_tti>>1)),
           txdata+(i*(frame_parms->samples_per_tti>>1)));
56
#endif
57

58
    PHY_ofdm_mod(txdataF+(i*frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti>>1),        // input
59
                 txdata+(i*frame_parms->samples_per_tti>>1),         // output
60
                 frame_parms->ofdm_symbol_size,                
61 62 63
                 1,                 // number of symbols
                 frame_parms->nb_prefix_samples0,               // number of prefix samples
                 CYCLIC_PREFIX);
64
#ifdef DEBUG_OFDM_MOD
65 66
    printf("slot i %d (txdata offset %d)\n",i,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(i*frame_parms->samples_per_tti>>1));
#endif
67

68
    PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size+(i*frame_parms->ofdm_symbol_size*(frame_parms->symbols_per_tti>>1)),        // input
69
                 txdata+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(i*(frame_parms->samples_per_tti>>1)),         // output
70
                 frame_parms->ofdm_symbol_size,                
71 72 73 74
                 (short_offset==1) ? 1 :(frame_parms->symbols_per_tti>>1)-1,//6,                 // number of symbols
                 frame_parms->nb_prefix_samples,               // number of prefix samples
                 CYCLIC_PREFIX);

75 76 77 78 79

  }
}

void PHY_ofdm_mod(int *input,                       /// pointer to complex input
80
                  int *output,                      /// pointer to complex output
81
                  int fftsize,            /// FFT_SIZE
82 83 84 85 86
                  unsigned char nb_symbols,         /// number of OFDM symbols
                  unsigned short nb_prefix_samples,  /// cyclic prefix length
                  Extension_t etype                /// type of extension
                 )
{
87

88
  static short temp[2048*4] __attribute__((aligned(32)));
89 90 91 92 93 94 95 96
  unsigned short i,j;
  short k;

  volatile int *output_ptr=(int*)0;

  int *temp_ptr=(int*)0;
  void (*idft)(int16_t *,int16_t *, int);

97 98
  switch (fftsize) {
  case 128:
99 100
    idft = idft128;
    break;
101

102
  case 256:
103 104
    idft = idft256;
    break;
105

106
  case 512:
107 108
    idft = idft512;
    break;
109

110
  case 1024:
111 112
    idft = idft1024;
    break;
113

114 115 116 117 118
  case 1536:
    idft = idft1536;
    break;

  case 2048:
119 120
    idft = idft2048;
    break;
121

122 123 124 125 126 127
  default:
    idft = idft512;
    break;
  }

#ifdef DEBUG_OFDM_MOD
128 129
  printf("[PHY] OFDM mod (size %d,prefix %d) Symbols %d, input %p, output %p\n",
      fftsize,nb_prefix_samples,nb_symbols,input,output);
130 131 132
#endif


133 134

  for (i=0; i<nb_symbols; i++) {
135 136

#ifdef DEBUG_OFDM_MOD
137
    printf("[PHY] symbol %d/%d offset %d (%p,%p -> %p)\n",i,nb_symbols,i*fftsize+(i*nb_prefix_samples),input,&input[i*fftsize],&output[(i*fftsize) + ((i)*nb_prefix_samples)]);
138 139
#endif

140 141
#ifndef __AVX2__
    // handle 128-bit alignment for 128-bit SIMD (SSE4,NEON,AltiVEC)
Raymond Knopp's avatar
Raymond Knopp committed
142
    idft((int16_t *)&input[i*fftsize],
143
         (fftsize==128) ? (int16_t *)temp : (int16_t *)&output[(i*fftsize) + ((1+i)*nb_prefix_samples)],
144
         1);
145 146
#else
    // on AVX2 need 256-bit alignment
Raymond Knopp's avatar
Raymond Knopp committed
147
    idft((int16_t *)&input[i*fftsize],
148
         (fftsize<=512) ? (int16_t *)temp : (int16_t *)&output[(i*fftsize) + ((1+i)*nb_prefix_samples)],
149
         1);
150

151
#endif
152

153 154
    // Copy to frame buffer with Cyclic Extension
    // Note:  will have to adjust for synchronization offset!
155

156 157
    switch (etype) {
    case CYCLIC_PREFIX:
158
      output_ptr = &output[(i*fftsize) + ((1+i)*nb_prefix_samples)];
159
      temp_ptr = (int *)temp;
160

161 162 163

      //      msg("Doing cyclic prefix method\n");

164
#ifndef __AVX2__
165
      if (fftsize==128) 
166
#else
167
      if (fftsize<=512) 
168 169
#endif
      {
170
        for (j=0; j<fftsize ; j++) {
171 172
          output_ptr[j] = temp_ptr[j];
        }
173
      }
174

175
      j=fftsize;
176 177 178

      for (k=-1; k>=-nb_prefix_samples; k--) {
        output_ptr[k] = output_ptr[--j];
179
      }
180

181
      break;
182

183
    case CYCLIC_SUFFIX:
184 185


186
      output_ptr = &output[(i*fftsize)+ (i*nb_prefix_samples)];
187

188
      temp_ptr = (int *)temp;
189

190 191
      //      msg("Doing cyclic suffix method\n");

192
      for (j=0; j<fftsize ; j++) {
193
        output_ptr[j] = temp_ptr[2*j];
194
      }
195 196 197


      for (j=0; j<nb_prefix_samples; j++)
198
        output_ptr[fftsize+j] = output_ptr[j];
199

200 201 202 203 204 205 206 207 208
      break;

    case ZEROS:

      break;

    case NONE:

      //      msg("NO EXTENSION!\n");
209
      output_ptr = &output[fftsize];
210 211

      temp_ptr = (int *)temp;
212

213
      for (j=0; j<fftsize ; j++) {
214
        output_ptr[j] = temp_ptr[2*j];
215 216 217 218 219 220 221 222 223 224 225


      }

      break;

    default:
      break;

    }

226 227


228
  }
229

230

231 232
}

Raymond Knopp's avatar
 
Raymond Knopp committed
233

234
void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms)
235
{
Raymond Knopp's avatar
 
Raymond Knopp committed
236 237 238 239 240

  int aa, slot_offset, slot_offset_F;

  slot_offset_F = (next_slot)*(frame_parms->ofdm_symbol_size)*((frame_parms->Ncp==1) ? 6 : 7);
  slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1);
241

Raymond Knopp's avatar
 
Raymond Knopp committed
242
  for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
243
    if (is_pmch_subframe(frame,next_slot>>1,frame_parms)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
244
      if ((next_slot%2)==0) {
245 246 247
        LOG_D(PHY,"Frame %d, subframe %d: Doing MBSFN modulation (slot_offset %d)\n",frame,next_slot>>1,slot_offset);
        PHY_ofdm_mod(&txdataF[aa][slot_offset_F],        // input
                     &txdata[aa][slot_offset],         // output
248
                     frame_parms->ofdm_symbol_size,                
249 250 251 252 253 254 255
                     12,                 // number of symbols
                     frame_parms->ofdm_symbol_size>>2,               // number of prefix samples
                     CYCLIC_PREFIX);

        if (frame_parms->Ncp == EXTENDED)
          PHY_ofdm_mod(&txdataF[aa][slot_offset_F],        // input
                       &txdata[aa][slot_offset],         // output
256
                       frame_parms->ofdm_symbol_size,                
257 258 259 260 261 262 263 264 265 266
                       2,                 // number of symbols
                       frame_parms->nb_prefix_samples,               // number of prefix samples
                       CYCLIC_PREFIX);
        else {
          LOG_D(PHY,"Frame %d, subframe %d: Doing PDCCH modulation\n",frame,next_slot>>1);
          normal_prefix_mod(&txdataF[aa][slot_offset_F],
                            &txdata[aa][slot_offset],
                            2,
                            frame_parms);
        }
Raymond Knopp's avatar
 
Raymond Knopp committed
267
      }
268
    } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
269
      if (frame_parms->Ncp == EXTENDED)
270 271
        PHY_ofdm_mod(&txdataF[aa][slot_offset_F],        // input
                     &txdata[aa][slot_offset],         // output
272
                     frame_parms->ofdm_symbol_size,                
273 274 275
                     6,                 // number of symbols
                     frame_parms->nb_prefix_samples,               // number of prefix samples
                     CYCLIC_PREFIX);
Raymond Knopp's avatar
 
Raymond Knopp committed
276
      else {
277 278 279 280
        normal_prefix_mod(&txdataF[aa][slot_offset_F],
                          &txdata[aa][slot_offset],
                          7,
                          frame_parms);
Raymond Knopp's avatar
 
Raymond Knopp committed
281
      }
282
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
283
  }
284

Raymond Knopp's avatar
 
Raymond Knopp committed
285 286
}

287
// OFDM modulation for each symbol
288
void do_OFDM_mod_symbol(LTE_eNB_COMMON *eNB_common_vars, int eNB_id, uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms,int do_precoding)
289 290
{

291
  int aa, l, slot_offset;
292
  int32_t **txdataF = eNB_common_vars->txdataF[eNB_id];
293
  int32_t **txdataF_BF = (do_precoding==1)?eNB_common_vars->txdataF_BF[eNB_id]:txdataF;
294 295 296 297
  int32_t **txdata = eNB_common_vars->txdata[eNB_id];

  slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1);

298
  //printf("Thread %d starting ... aa %d (%llu)\n",omp_get_thread_num(),aa,rdtsc());
299 300 301 302
  for (l=0; l<frame_parms->symbols_per_tti>>1; l++) {
  
    for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {

303 304
      //printf("do_OFDM_mod_l, slot=%d, l=%d, NUMBER_OF_OFDM_CARRIERS=%d,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES=%d\n",next_slot, l,NUMBER_OF_OFDM_CARRIERS,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES);
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,1);
305
      if (do_precoding==1) beam_precoding(txdataF,txdataF_BF,frame_parms,eNB_common_vars->beam_weights[eNB_id],next_slot,l,aa);
306 307
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,0);

308 309
      //PMCH case not implemented... 

310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
      if (frame_parms->Ncp == 1)
        PHY_ofdm_mod(txdataF_BF[aa],         // input
                     &txdata[aa][slot_offset+l*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],            // output
                     frame_parms->ofdm_symbol_size,       
                     1,                                   // number of symbols
                     frame_parms->nb_prefix_samples,      // number of prefix samples
                     CYCLIC_PREFIX);
      else {
        if (l==0) {
          PHY_ofdm_mod(txdataF_BF[aa],        // input
                       &txdata[aa][slot_offset],           // output
                       frame_parms->ofdm_symbol_size,      
                       1,                                  // number of symbols
                       frame_parms->nb_prefix_samples0,    // number of prefix samples
                       CYCLIC_PREFIX);
           
        } else {
          PHY_ofdm_mod(txdataF_BF[aa],        // input
                       &txdata[aa][slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],           // output
                       frame_parms->ofdm_symbol_size,      
                       1,                                  // number of symbols
                       frame_parms->nb_prefix_samples,     // number of prefix samples
                       CYCLIC_PREFIX);
333

334 335
          /* printf("txdata[%d][%d]=%d\n",aa,slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES,txdata[aa][slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES]);
 * */
336 337 338 339 340 341
        }
      }
    }
  }

}