ofdm_mod.c 10.9 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * 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
/*
* @defgroup _PHY_MODULATION_
* @ingroup _physical_layer_ref_implementation_
* @{
\section _phy_modulation_ OFDM Modulation Blocks
This section deals with basic functions for OFDM Modulation.


30

31 32
*/

33
#include "PHY/defs_eNB.h"
34
#include "PHY/defs_gNB.h"
35
#include "PHY/impl_defs_top.h"
36 37
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
38
#include "modulation_common.h"
39
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
Raymond Knopp's avatar
Raymond Knopp committed
40
//#define DEBUG_OFDM_MOD
41 42


43 44
void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRAME_PARMS *frame_parms)
{
45 46


47 48 49 50
  
  PHY_ofdm_mod(txdataF,        // input
	       txdata,         // output
	       frame_parms->ofdm_symbol_size,                
51

52 53 54 55 56 57 58 59 60 61 62 63
	       1,                 // number of symbols
	       frame_parms->nb_prefix_samples0,               // number of prefix samples
	       CYCLIC_PREFIX);
  PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size,        // input
	       txdata+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0,         // output
	       frame_parms->ofdm_symbol_size,                
	       nsymb-1,
	       frame_parms->nb_prefix_samples,               // number of prefix samples
	       CYCLIC_PREFIX);
  

  
64 65
}

66
void nr_normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,NR_DL_FRAME_PARMS *frame_parms, uint32_t slot)
Guy De Souza's avatar
Guy De Souza committed
67
{
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
  // This function works only slot wise. For more generic symbol generation refer nr_feptx0()
  if (frame_parms->numerology_index != 0) { // case where numerology != 0
    if (!(slot%(frame_parms->slots_per_subframe/2))) {
      PHY_ofdm_mod(txdataF,
             txdata,
             frame_parms->ofdm_symbol_size,
             1,
             frame_parms->nb_prefix_samples0,
             CYCLIC_PREFIX);
      PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size,
             txdata + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0,
             frame_parms->ofdm_symbol_size,
             nsymb - 1,
             frame_parms->nb_prefix_samples,
             CYCLIC_PREFIX);
    }
    else {
      PHY_ofdm_mod(txdataF,
             txdata,
             frame_parms->ofdm_symbol_size,
             nsymb,
             frame_parms->nb_prefix_samples,
             CYCLIC_PREFIX);
    }
  }
  else { // numerology = 0, longer CP for every 7th symbol
      PHY_ofdm_mod(txdataF,
             txdata,
             frame_parms->ofdm_symbol_size,
             1,
             frame_parms->nb_prefix_samples0,
             CYCLIC_PREFIX);
      PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size,
             txdata + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0,
             frame_parms->ofdm_symbol_size,
             6,
             frame_parms->nb_prefix_samples,
             CYCLIC_PREFIX);
      PHY_ofdm_mod(txdataF + 7*frame_parms->ofdm_symbol_size,
             txdata + 6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples) +
                    frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0,
             frame_parms->ofdm_symbol_size,
             1,
             frame_parms->nb_prefix_samples0,
             CYCLIC_PREFIX);
      PHY_ofdm_mod(txdataF + 8*frame_parms->ofdm_symbol_size,
             txdata + 6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples) +
                    2*(frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0),
             frame_parms->ofdm_symbol_size,
             6,
             frame_parms->nb_prefix_samples,
             CYCLIC_PREFIX);
  }

Guy De Souza's avatar
Guy De Souza committed
122 123
}

124
void PHY_ofdm_mod(int *input,                       /// pointer to complex input
125
                  int *output,                      /// pointer to complex output
126
                  int fftsize,            /// FFT_SIZE
127 128 129 130 131
                  unsigned char nb_symbols,         /// number of OFDM symbols
                  unsigned short nb_prefix_samples,  /// cyclic prefix length
                  Extension_t etype                /// type of extension
                 )
{
132

133 134
  if(nb_symbols == 0) return;

135 136
  int16_t temp[2*2*6144*4] __attribute__((aligned(32)));
  int i,j;
137 138 139 140

  volatile int *output_ptr=(int*)0;

  int *temp_ptr=(int*)0;
frtabu's avatar
frtabu committed
141
  idft_size_idx_t idftsize;
142

143 144
  switch (fftsize) {
  case 128:
frtabu's avatar
frtabu committed
145
    idftsize = IDFT_128;
146
    break;
147

148
  case 256:
frtabu's avatar
frtabu committed
149
    idftsize = IDFT_256;
150
    break;
151

152
  case 512:
frtabu's avatar
frtabu committed
153
    idftsize = IDFT_512;
154
    break;
155

156
  case 1024:
frtabu's avatar
frtabu committed
157
    idftsize = IDFT_1024;
158
    break;
159

160
  case 1536:
frtabu's avatar
frtabu committed
161
    idftsize = IDFT_1536;
162 163 164
    break;

  case 2048:
frtabu's avatar
frtabu committed
165
    idftsize = IDFT_2048;
166
    break;
167

168
  case 3072:
frtabu's avatar
frtabu committed
169
    idftsize = IDFT_3072;
Raymond Knopp's avatar
Raymond Knopp committed
170
    break;
Javier Morgade's avatar
Javier Morgade committed
171

172
  case 4096:
frtabu's avatar
frtabu committed
173
    idftsize = IDFT_4096;
Raymond Knopp's avatar
Raymond Knopp committed
174
    break;
Javier Morgade's avatar
Javier Morgade committed
175 176 177 178 179 180 181 182 183 184 185 186 187

  case 6144:
    idftsize= IDFT_6144;
    break;

 case 12288:
    idftsize= IDFT_12288;
    break;

 case 24576:
    idftsize= IDFT_24576;
    break;

188
  default:
frtabu's avatar
frtabu committed
189
    idftsize = IDFT_512;
190 191 192 193
    break;
  }

#ifdef DEBUG_OFDM_MOD
194 195
  printf("[PHY] OFDM mod (size %d,prefix %d) Symbols %d, input %p, output %p\n",
      fftsize,nb_prefix_samples,nb_symbols,input,output);
196 197 198
#endif


199 200

  for (i=0; i<nb_symbols; i++) {
201 202

#ifdef DEBUG_OFDM_MOD
203
    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)]);
204 205
#endif

206 207
#ifndef __AVX2__
    // handle 128-bit alignment for 128-bit SIMD (SSE4,NEON,AltiVEC)
frtabu's avatar
frtabu committed
208
    idft(idftsize,(int16_t *)&input[i*fftsize],
209
         (fftsize==128) ? (int16_t *)temp : (int16_t *)&output[(i*fftsize) + ((1+i)*nb_prefix_samples)],
210
         1);
211 212
#else
    // on AVX2 need 256-bit alignment
frtabu's avatar
frtabu committed
213
    idft(idftsize,(int16_t *)&input[i*fftsize],
214
         (int16_t *)temp,
215
         1);
216

217
#endif
218

219 220
    // Copy to frame buffer with Cyclic Extension
    // Note:  will have to adjust for synchronization offset!
221

222 223
    switch (etype) {
    case CYCLIC_PREFIX:
224
      output_ptr = &output[(i*fftsize) + ((1+i)*nb_prefix_samples)];
225
      temp_ptr = (int *)temp;
226

227 228 229

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

230
#ifndef __AVX2__
231
      if (fftsize==128) 
232 233
#endif
      {
234
        memcpy((void*)output_ptr,(void*)temp_ptr,fftsize<<2);
235
      }
236
      memcpy((void*)&output_ptr[-nb_prefix_samples],(void*)&output_ptr[fftsize-nb_prefix_samples],nb_prefix_samples<<2);
237
      break;
238

239
    case CYCLIC_SUFFIX:
240 241


242
      output_ptr = &output[(i*fftsize)+ (i*nb_prefix_samples)];
243

244
      temp_ptr = (int *)temp;
245

246 247
      //      msg("Doing cyclic suffix method\n");

248
      for (j=0; j<fftsize ; j++) {
249
        output_ptr[j] = temp_ptr[2*j];
250
      }
251 252 253


      for (j=0; j<nb_prefix_samples; j++)
254
        output_ptr[fftsize+j] = output_ptr[j];
255

256 257 258 259 260 261 262 263 264
      break;

    case ZEROS:

      break;

    case NONE:

      //      msg("NO EXTENSION!\n");
265
      output_ptr = &output[fftsize];
266 267

      temp_ptr = (int *)temp;
268

269
      for (j=0; j<fftsize ; j++) {
270
        output_ptr[j] = temp_ptr[2*j];
271 272 273 274 275 276 277 278 279 280 281


      }

      break;

    default:
      break;

    }

282 283


284
  }
285

286

287 288
}

Raymond Knopp's avatar
 
Raymond Knopp committed
289

290
void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms)
291
{
Raymond Knopp's avatar
 
Raymond Knopp committed
292 293 294 295 296

  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);
297

Raymond Knopp's avatar
 
Raymond Knopp committed
298
  for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
299
    if (is_pmch_subframe(frame,next_slot>>1,frame_parms)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
300
      if ((next_slot%2)==0) {
301 302 303
        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
304
                     frame_parms->ofdm_symbol_size,                
305 306 307 308 309 310 311
                     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
312
                       frame_parms->ofdm_symbol_size,                
313 314 315 316 317 318 319 320 321 322
                       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
323
      }
324
    } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
325
      if (frame_parms->Ncp == EXTENDED)
326 327
        PHY_ofdm_mod(&txdataF[aa][slot_offset_F],        // input
                     &txdata[aa][slot_offset],         // output
328
                     frame_parms->ofdm_symbol_size,                
329 330 331
                     6,                 // number of symbols
                     frame_parms->nb_prefix_samples,               // number of prefix samples
                     CYCLIC_PREFIX);
Raymond Knopp's avatar
 
Raymond Knopp committed
332
      else {
333 334 335 336
        normal_prefix_mod(&txdataF[aa][slot_offset_F],
                          &txdata[aa][slot_offset],
                          7,
                          frame_parms);
Raymond Knopp's avatar
 
Raymond Knopp committed
337
      }
338
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
339
  }
340

Raymond Knopp's avatar
 
Raymond Knopp committed
341 342
}

343 344 345 346 347 348 349 350
void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
		       int16_t* trxdata,
		       int slot,
		       int first_symbol,
		       int nsymb,
		       int length) {
  int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot;

351 352
  int16_t *symbol_rotation = fp->symbol_rotation[0];

353
  for (int sidx=0;sidx<nsymb;sidx++) {
354

355
    LOG_D(PHY,"Rotating symbol %d, slot %d, symbol_subframe_index %d, length %d (%d,%d)\n",
356 357 358 359 360 361 362 363 364 365 366 367
      first_symbol + sidx,
      slot,
      sidx + first_symbol + symb_offset,
      length,
      symbol_rotation[2 * (sidx + first_symbol + symb_offset)],
      symbol_rotation[1 + 2 * (sidx + first_symbol + symb_offset)]);

    rotate_cpx_vector(trxdata + (sidx * length * 2),
                      &symbol_rotation[2 * (sidx + first_symbol + symb_offset)],
                      trxdata + (sidx * length * 2),
                      length,
                      15);
368 369
  }
}
370