tools_defs.h 22.7 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
 * 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 28 29 30
#ifndef __PHY_TOOLS_DEFS__H__
#define __PHY_TOOLS_DEFS__H__

/** @addtogroup _PHY_DSP_TOOLS_


* @{

*/
31

32
#include <stdio.h>
33
#include <stdint.h>
34
#include <assert.h>
35
#include "PHY/sse_intrin.h"
Laurent Thomas's avatar
Laurent Thomas committed
36
#include "common/utils/assertions.h"
37

38 39 40 41 42 43 44 45 46
#if defined(__x86_64__) || defined(__i386__)
#define simd_q15_t __m128i
#define simdshort_q15_t __m64
#define shiftright_int16(a,shift) _mm_srai_epi16(a,shift)
#define set1_int16(a) _mm_set1_epi16(a)
#define mulhi_int16(a,b) _mm_mulhrs_epi16 (a,b)
#define mulhi_s1_int16(a,b) _mm_slli_epi16(_mm_mulhi_epi16(a,b),2)
#define adds_int16(a,b) _mm_adds_epi16(a,b)
#define mullo_int16(a,b) _mm_mullo_epi16(a,b)
47
#elif defined(__arm__) || defined(__aarch64__)
48 49 50 51 52 53 54 55
#define simd_q15_t int16x8_t
#define simdshort_q15_t int16x4_t
#define shiftright_int16(a,shift) vshrq_n_s16(a,shift)
#define set1_int16(a) vdupq_n_s16(a)
#define mulhi_int16(a,b) vqdmulhq_s16(a,b)
#define mulhi_s1_int16(a,b) vshlq_n_s16(vqdmulhq_s16(a,b),1)
#define adds_int16(a,b) vqaddq_s16(a,b)
#define mullo_int16(a,b) vmulq_s16(a,b)
56
#define _mm_empty()
57 58 59 60 61 62 63
#define _m_empty()
#endif

#ifdef __cplusplus
extern "C" {
#endif

Guy De Souza's avatar
Guy De Souza committed
64 65
#define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
66

67 68 69 70 71 72 73 74 75 76
  typedef struct complexd {
    double r;
    double i;
  } cd_t;

  typedef struct complexf {
    float r;
    float i;
  } cf_t;

77 78 79 80 81
  typedef struct complex8 {
    int8_t r;
    int8_t i;
  } c8_t;

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
  typedef struct complex16 {
    int16_t r;
    int16_t i;
  } c16_t;

  typedef struct complex32 {
    int32_t r;
    int32_t i;
  } c32_t;

  typedef struct complex64 {
    int64_t r;
    int64_t i;
  } c64_t;

#define squaredMod(a) ((a).r*(a).r + (a).i*(a).i)
#define csum(res, i1, i2) (res).r = (i1).r + (i2).r ; (res).i = (i1).i + (i2).i

  __attribute__((always_inline)) inline c16_t c16mulShift(const c16_t a, const c16_t b, const int Shift) {
    return (c16_t) {
      .r = (int16_t)((a.r * b.r - a.i * b.i) >> Shift),
      .i = (int16_t)((a.r * b.i + a.i * b.r) >> Shift)
    };
  }
106

107 108 109 110 111 112
  __attribute__((always_inline)) inline c16_t c16divShift(const c16_t a, const c16_t b, const int Shift) {
    return (c16_t) {
      .r = (int16_t)((a.r * b.r + a.i * b.i) >> Shift),
      .i = (int16_t)((a.r * b.i - a.i * b.r) >> Shift)
    };
  }
113

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
  __attribute__((always_inline)) inline c16_t c16maddShift(const c16_t a, const c16_t b, c16_t c, const int Shift) {
    return (c16_t) {
      .r = (int16_t)(((a.r * b.r - a.i * b.i ) >> Shift) + c.r),
      .i = (int16_t)(((a.r * b.i + a.i * b.r ) >> Shift) + c.i)
    };
  }

  __attribute__((always_inline)) inline c32_t c32x16mulShift(const c16_t a, const c16_t b, const int Shift) {
    return (c32_t) {
      .r = (a.r * b.r - a.i * b.i) >> Shift,
      .i = (a.r * b.i + a.i * b.r) >> Shift
    };
  }

  __attribute__((always_inline)) inline c32_t c32x16maddShift(const c16_t a, const c16_t b, const c32_t c, const int Shift) {
    return (c32_t) {
      .r = ((a.r * b.r - a.i * b.i) >> Shift) + c.r,
      .i = ((a.r * b.i + a.i * b.r) >> Shift) + c.i
    };
  }

  __attribute__((always_inline)) inline c16_t c16x32div(const c32_t a, const int div) {
    return (c16_t) {
      .r = (int16_t)(a.r / div),
      .i = (int16_t)(a.i / div)
    };
  }

142 143 144 145 146 147 148
  __attribute__((always_inline)) inline cd_t cdMul(const cd_t a, const cd_t b)
  {
    return (cd_t) {
        .r = a.r * b.r - a.i * b.i,
        .i = a.r * b.i + a.i * b.r
    };
  }
149 150

  // On N complex numbers
151 152
  //   y.r += (x * alpha.r) >> 14
  //   y.i += (x * alpha.i) >> 14
153
  // See regular C implementation at the end
154
  static __attribute__((always_inline)) inline void c16multaddVectRealComplex(const int16_t *x,
155 156 157
                                                                       const c16_t *alpha,
                                                                       c16_t *y,
                                                                       const int N) {
158 159
#if defined(__x86_64__) || defined(__i386__)
    // Default implementation for x86
160 161 162 163 164 165 166 167 168 169
    const int8_t makePairs[32] __attribute__((aligned(32)))={
      0,1,0+16,1+16,
      2,3,2+16,3+16,
      4,5,4+16,5+16,
      6,7,6+16,7+16,
      8,9,8+16,9+16,
      10,11,10+16,11+16,
      12,13,12+16,13+16,
      14,15,14+16,15+16};
    
170
    __m256i alpha256= simde_mm256_set1_epi32(*(int32_t *)alpha);
171 172 173 174
    __m128i *x128=(__m128i *)x;
    __m128i *y128=(__m128i *)y;
    AssertFatal(N%8==0,"Not implemented\n");
    for (int i=0; i<N/8; i++) {
175 176 177
      const __m256i xduplicate=simde_mm256_broadcastsi128_si256(*x128);
      const __m256i x_duplicate_ordered=simde_mm256_shuffle_epi8(xduplicate,*(__m256i*)makePairs);
      const __m256i x_mul_alpha_shift15 =simde_mm256_mulhrs_epi16(alpha256, x_duplicate_ordered);
178
      // Existing multiplication normalization is weird, constant table in alpha need to be doubled
179 180
      const __m256i x_mul_alpha_x2= simde_mm256_adds_epi16(x_mul_alpha_shift15,x_mul_alpha_shift15);
      *y128= _mm_adds_epi16(simde_mm256_extracti128_si256(x_mul_alpha_x2,0),*y128);
181
      y128++;
182
      *y128= _mm_adds_epi16(simde_mm256_extracti128_si256(x_mul_alpha_x2,1),*y128);
183 184 185 186
      y128++;
      x128++;
    } 
    
187 188
#elif defined(__arm__) || defined(__aarch64__)
    // Default implementation for ARM
189
    uint32_t i;
190

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
    // do 8 multiplications at a time
    simd_q15_t alpha_r_128,alpha_i_128,yr,yi,*x_128=(simd_q15_t*)x,*y_128=(simd_q15_t*)y;
    int j;

    //  printf("alpha = %d,%d\n",alpha[0],alpha[1]);
    alpha_r_128 = set1_int16(alpha->r);
    alpha_i_128 = set1_int16(alpha->i);

    j=0;

    for (i=0; i<N>>3; i++) {

      yr     = mulhi_s1_int16(alpha_r_128,x_128[i]);
      yi     = mulhi_s1_int16(alpha_i_128,x_128[i]);
      int16x8x2_t yint;
      yint = vzipq_s16(yr,yi);
      y_128[j]   = adds_int16(y_128[j],yint.val[0]);
      j++;
      y_128[j]   = adds_int16(y_128[j],yint.val[1]);
210

211 212 213
      j++;
    }
#else
214
    // Almost dead code (BMC)
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
    for (int i=0; i<N; i++) {
      int tmpr=y[i].r+((x[i]*alpha->r)>>14);
      if (tmpr>INT16_MAX)
        tmpr=INT16_MAX;
      if (tmpr<INT16_MIN)
        tmpr=INT16_MIN;
      int tmpi=y[i].i+((x[i]*alpha->i)>>14);
      if (tmpi>INT16_MAX)
        tmpi=INT16_MAX;
      if (tmpi<INT16_MIN)
        tmpi=INT16_MIN;
      y[i].r=(int16_t)tmpr;
      y[i].i=(int16_t)tmpi;
    }
#endif
  }
231 232
//cmult_sv.h

233
/*!\fn void multadd_real_vector_complex_scalar(int16_t *x,int16_t *alpha,int16_t *y,uint32_t N)
234
This function performs componentwise multiplication and accumulation of a complex scalar and a real vector.
235
@param x Vector input (Q1.15)
236 237 238 239 240 241
@param alpha Scalar input (Q1.15) in the format  |Re0 Im0|
@param y Output (Q1.15) in the format  |Re0  Im0 Re1 Im1|,......,|Re(N-1)  Im(N-1) Re(N-1) Im(N-1)|
@param N Length of x WARNING: N>=8

The function implemented is : \f$\mathbf{y} = y + \alpha\mathbf{x}\f$
*/
242
void multadd_real_vector_complex_scalar(int16_t *x,
243 244
                                        int16_t *alpha,
                                        int16_t *y,
yilmazt's avatar
yilmazt committed
245
                                        uint32_t N);
246

247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
__attribute__((always_inline)) inline void multadd_real_four_symbols_vector_complex_scalar(int16_t *x,
                                                                                           c16_t *alpha,
                                                                                           c16_t *y)
{

  // do 8 multiplications at a time
  simd_q15_t alpha_r_128,alpha_i_128,yr,yi,*x_128=(simd_q15_t*)x;
  simd_q15_t y_128;
  y_128 = _mm_loadu_si128((simd_q15_t*)y);

  alpha_r_128 = set1_int16(alpha->r);
  alpha_i_128 = set1_int16(alpha->i);


  yr     = mulhi_s1_int16(alpha_r_128,x_128[0]);
  yi     = mulhi_s1_int16(alpha_i_128,x_128[0]);
  y_128   = _mm_adds_epi16(y_128,_mm_unpacklo_epi16(yr,yi));
  y_128   = _mm_adds_epi16(y_128,_mm_unpackhi_epi16(yr,yi));
265

266 267 268
  _mm_storeu_si128((simd_q15_t*)y, y_128);

}
269

270
/*!\fn void multadd_complex_vector_real_scalar(int16_t *x,int16_t alpha,int16_t *y,uint8_t zero_flag,uint32_t N)
271
This function performs componentwise multiplication and accumulation of a real scalar and a complex vector.
272
@param x Vector input (Q1.15) in the format |Re0 Im0|Re1 Im 1| ...
273 274 275 276 277 278 279
@param alpha Scalar input (Q1.15) in the format  |Re0|
@param y Output (Q1.15) in the format  |Re0  Im0 Re1 Im1|,......,|Re(N-1)  Im(N-1) Re(N-1) Im(N-1)|
@param zero_flag Set output (y) to zero prior to accumulation
@param N Length of x WARNING: N>=8

The function implemented is : \f$\mathbf{y} = y + \alpha\mathbf{x}\f$
*/
280
void multadd_complex_vector_real_scalar(int16_t *x,
281 282 283 284
                                        int16_t alpha,
                                        int16_t *y,
                                        uint8_t zero_flag,
                                        uint32_t N);
285

286
/*!\fn void init_fft(uint16_t size,uint8_t logsize,uint16_t *rev)
287 288 289 290 291 292
\brief Initialize the FFT engine for a given size
@param size Size of the FFT
@param logsize log2(size)
@param rev Pointer to bit-reversal permutation array
*/

293 294
//cmult_vv.c
/*!
295
  Multiply elementwise the complex conjugate of x1 with x2.
296 297 298 299 300 301 302
  @param x1       - input 1    in the format  |Re0 Im0 Re1 Im1|,......,|Re(N-2)  Im(N-2) Re(N-1) Im(N-1)|
              We assume x1 with a dinamic of 15 bit maximum
  @param x2       - input 2    in the format  |Re0 Im0 Re1 Im1|,......,|Re(N-2)  Im(N-2) Re(N-1) Im(N-1)|
              We assume x2 with a dinamic of 14 bit maximum
  @param y        - output     in the format  |Re0 Im0 Re1 Im1|,......,|Re(N-2)  Im(N-2) Re(N-1) Im(N-1)|
  @param N        - the size f the vectors (this function does N cpx mpy. WARNING: N>=4;
  @param output_shift  - shift to be applied to generate output
303
  @param madd - if not zero result is added to output
304 305 306 307 308 309
*/

int mult_cpx_conj_vector(int16_t *x1,
                         int16_t *x2,
                         int16_t *y,
                         uint32_t N,
310
                         int output_shift,
yilmazt's avatar
yilmazt committed
311
                         int madd);
312

313 314 315 316 317 318 319 320 321 322 323 324 325
/*!
  Element-wise multiplication and accumulation of two complex vectors x1 and x2.
  @param x1       - input 1    in the format  |Re0 Im0 Re1 Im1|,......,|Re(N-2)  Im(N-2) Re(N-1) Im(N-1)|
              We assume x1 with a dinamic of 15 bit maximum
  @param x2       - input 2    in the format  |Re0 Im0 Re1 Im1|,......,|Re(N-2)  Im(N-2) Re(N-1) Im(N-1)|
              We assume x2 with a dinamic of 14 bit maximum
  @param y        - output     in the format  |Re0 Im0 Re1 Im1|,......,|Re(N-2)  Im(N-2) Re(N-1) Im(N-1)|
  @param zero_flag Set output (y) to zero prior to accumulation
  @param N        - the size f the vectors (this function does N cpx mpy. WARNING: N>=4;
  @param output_shift  - shift to be applied to generate output
*/

int multadd_cpx_vector(int16_t *x1,
yilmazt's avatar
yilmazt committed
326 327 328 329 330
                       int16_t *x2,
                       int16_t *y,
                       uint8_t zero_flag,
                       uint32_t N,
                       int output_shift);
331

lukashov's avatar
lukashov committed
332 333 334 335 336 337
int mult_cpx_vector(int16_t *x1,
                    int16_t  *x2,
                    int16_t *y,
                    uint32_t N,
                    int output_shift);

338
// lte_dfts.c
339
void init_fft(uint16_t size,
340 341
              uint8_t logsize,
              uint16_t *rev);
342

343
/*!\fn void fft(int16_t *x,int16_t *y,int16_t *twiddle,uint16_t *rev,uint8_t log2size,uint8_t scale,uint8_t input_fmt)
344 345 346 347 348 349 350 351 352
This function performs optimized fixed-point radix-2 FFT/IFFT.
@param x Input
@param y Output in format: [Re0,Im0,Re0,Im0, Re1,Im1,Re1,Im1, ....., Re(N-1),Im(N-1),Re(N-1),Im(N-1)]
@param twiddle Twiddle factors
@param rev bit-reversed permutation
@param log2size Base-2 logarithm of FFT size
@param scale Total number of shifts (should be log2size/2 for normalized FFT)
@param input_fmt (0 - input is in complex Q1.15 format, 1 - input is in complex redundant Q1.15 format)
*/
353
/*void fft(int16_t *x,
354 355 356 357 358 359 360
         int16_t *y,
         int16_t *twiddle,
         uint16_t *rev,
         uint8_t log2size,
         uint8_t scale,
         uint8_t input_fmt
        );
361
*/
362

Laurent THOMAS's avatar
Laurent THOMAS committed
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
#define FOREACH_DFTSZ(SZ_DEF) \
  SZ_DEF(12) \
  SZ_DEF(24) \
  SZ_DEF(36) \
  SZ_DEF(48) \
  SZ_DEF(60) \
  SZ_DEF(64) \
  SZ_DEF(72) \
  SZ_DEF(96) \
  SZ_DEF(108) \
  SZ_DEF(120) \
  SZ_DEF(128) \
  SZ_DEF(144) \
  SZ_DEF(180) \
  SZ_DEF(192) \
  SZ_DEF(216) \
  SZ_DEF(240) \
  SZ_DEF(256) \
  SZ_DEF(288) \
  SZ_DEF(300) \
  SZ_DEF(324) \
  SZ_DEF(360) \
  SZ_DEF(384) \
  SZ_DEF(432) \
  SZ_DEF(480) \
  SZ_DEF(512) \
  SZ_DEF(540) \
  SZ_DEF(576) \
  SZ_DEF(600) \
  SZ_DEF(648) \
  SZ_DEF(720) \
  SZ_DEF(768) \
  SZ_DEF(864) \
  SZ_DEF(900) \
  SZ_DEF(960) \
  SZ_DEF(972) \
  SZ_DEF(1024) \
  SZ_DEF(1080) \
  SZ_DEF(1152) \
  SZ_DEF(1200) \
  SZ_DEF(1296) \
  SZ_DEF(1440) \
  SZ_DEF(1500) \
  SZ_DEF(1536) \
  SZ_DEF(1620) \
  SZ_DEF(1728) \
  SZ_DEF(1800) \
  SZ_DEF(1920) \
  SZ_DEF(1944) \
  SZ_DEF(2048) \
  SZ_DEF(2160) \
  SZ_DEF(2304) \
  SZ_DEF(2400) \
  SZ_DEF(2592) \
  SZ_DEF(2700) \
  SZ_DEF(2880) \
  SZ_DEF(2916) \
  SZ_DEF(3000) \
  SZ_DEF(3072) \
  SZ_DEF(3240) \
  SZ_DEF(4096) \
  SZ_DEF(6144) \
  SZ_DEF(8192) \
  SZ_DEF(9216) \
  SZ_DEF(12288) \
  SZ_DEF(18432) \
  SZ_DEF(24576) \
  SZ_DEF(36864) \
  SZ_DEF(49152) \
  SZ_DEF(73728) \
  SZ_DEF(98304)

435
#define FOREACH_IDFTSZ(SZ_DEF)\
Laurent THOMAS's avatar
Laurent THOMAS committed
436 437 438 439
  SZ_DEF(64) \
  SZ_DEF(128) \
  SZ_DEF(256) \
  SZ_DEF(512) \
440
  SZ_DEF(768) \
Laurent THOMAS's avatar
Laurent THOMAS committed
441 442 443 444 445 446 447 448 449
  SZ_DEF(1024) \
  SZ_DEF(1536) \
  SZ_DEF(2048) \
  SZ_DEF(3072) \
  SZ_DEF(4096) \
  SZ_DEF(6144) \
  SZ_DEF(8192) \
  SZ_DEF(9216) \
  SZ_DEF(12288) \
450
  SZ_DEF(16384) \
Laurent THOMAS's avatar
Laurent THOMAS committed
451 452
  SZ_DEF(18432) \
  SZ_DEF(24576) \
453
  SZ_DEF(32768) \
Laurent THOMAS's avatar
Laurent THOMAS committed
454 455
  SZ_DEF(36864) \
  SZ_DEF(49152) \
456
  SZ_DEF(65536) \
Laurent THOMAS's avatar
Laurent THOMAS committed
457
  SZ_DEF(73728) \
Laurent THOMAS's avatar
Laurent THOMAS committed
458
  SZ_DEF(98304)
459

frtabu's avatar
frtabu committed
460
#ifdef OAIDFTS_MAIN
Laurent THOMAS's avatar
Laurent THOMAS committed
461 462
typedef  void(*adftfunc_t)(int16_t *sigF,int16_t *sig,unsigned char scale_flag);
typedef  void(*aidftfunc_t)(int16_t *sigF,int16_t *sig,unsigned char scale_flag);
463

Laurent THOMAS's avatar
Laurent THOMAS committed
464
#define SZ_FUNC(Sz) void dft ## Sz(int16_t *x,int16_t *y,uint8_t scale_flag);
frtabu's avatar
frtabu committed
465

Laurent THOMAS's avatar
Laurent THOMAS committed
466
FOREACH_DFTSZ(SZ_FUNC)
frtabu's avatar
frtabu committed
467

Laurent THOMAS's avatar
Laurent THOMAS committed
468
#define SZ_iFUNC(Sz) void idft ## Sz(int16_t *x,int16_t *y,uint8_t scale_flag);
frtabu's avatar
frtabu committed
469

Laurent THOMAS's avatar
Laurent THOMAS committed
470
FOREACH_IDFTSZ(SZ_iFUNC)
frtabu's avatar
frtabu committed
471 472

#else
Laurent THOMAS's avatar
Laurent THOMAS committed
473 474
typedef  void(*dftfunc_t)(uint8_t sizeidx,int16_t *sigF,int16_t *sig,unsigned char scale_flag);
typedef  void(*idftfunc_t)(uint8_t sizeidx,int16_t *sigF,int16_t *sig,unsigned char scale_flag);
frtabu's avatar
frtabu committed
475
#  ifdef OAIDFTS_LOADER
Laurent THOMAS's avatar
Laurent THOMAS committed
476 477
dftfunc_t dft;
idftfunc_t idft;
frtabu's avatar
frtabu committed
478
#  else
Laurent THOMAS's avatar
Laurent THOMAS committed
479 480 481
extern dftfunc_t dft;
extern idftfunc_t idft;
extern int load_dftslib(void);
frtabu's avatar
frtabu committed
482
#  endif
frtabu's avatar
frtabu committed
483
#endif
484

Laurent THOMAS's avatar
Laurent THOMAS committed
485
#define SZ_ENUM(Sz) DFT_ ## Sz,
frtabu's avatar
frtabu committed
486

Laurent THOMAS's avatar
Laurent THOMAS committed
487 488 489
typedef enum dft_size_idx {
  FOREACH_DFTSZ(SZ_ENUM)
  DFT_SIZE_IDXTABLESIZE
Laurent THOMAS's avatar
Laurent THOMAS committed
490
}  dft_size_idx_t;
Laurent THOMAS's avatar
Laurent THOMAS committed
491

Laurent THOMAS's avatar
Laurent THOMAS committed
492
#define SZ_iENUM(Sz) IDFT_ ## Sz,
493

494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
/*******************************************************************
*
* NAME :         get_dft
*
* PARAMETERS :   size of ofdm symbol
*
* RETURN :       function for discrete fourier transform
*
* DESCRIPTION :  get dft function depending of ofdm size
*
*********************************************************************/
static inline
dft_size_idx_t get_dft(int ofdm_symbol_size)
{
  switch (ofdm_symbol_size) {
    case 128:
      return DFT_128;
    case 256:
      return DFT_256;
    case 512:
      return DFT_512;
515 516
    case 768:
      return DFT_768;
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
    case 1024:
      return DFT_1024;
    case 1536:
      return DFT_1536;
    case 2048:
      return DFT_2048;
    case 3072:
      return DFT_3072;
    case 4096:
      return DFT_4096;
    case 6144:
      return DFT_6144;
    case 8192:
      return DFT_8192;
    case 9216:
      return DFT_9216;
    case 12288:
      return DFT_12288;
    case 18432:
      return DFT_18432;
    case 24576:
      return DFT_24576;
    case 36864:
      return DFT_36864;
    case 49152:
      return DFT_49152;
    case 73728:
      return DFT_73728;
    case 98304:
      return DFT_98304;
    default:
      printf("function get_dft : unsupported ofdm symbol size \n");
      assert(0);
      break;
551 552
  }
  return DFT_SIZE_IDXTABLESIZE; // never reached and will trigger assertion in idft function;
553 554
}

frtabu's avatar
frtabu committed
555
typedef enum idft_size_idx {
Laurent THOMAS's avatar
Laurent THOMAS committed
556 557 558
  FOREACH_IDFTSZ(SZ_iENUM)
  IDFT_SIZE_IDXTABLESIZE
}  idft_size_idx_t;
Laurent THOMAS's avatar
Laurent THOMAS committed
559

frtabu's avatar
frtabu committed
560
#ifdef OAIDFTS_MAIN
Laurent THOMAS's avatar
Laurent THOMAS committed
561

Laurent THOMAS's avatar
Laurent THOMAS committed
562
#define SZ_PTR(Sz) {dft ## Sz,Sz},
Laurent THOMAS's avatar
Laurent THOMAS committed
563 564 565 566 567
struct {
  adftfunc_t func;
  int size;
} dft_ftab[]= {
  FOREACH_DFTSZ(SZ_PTR)
frtabu's avatar
frtabu committed
568
};
Laurent THOMAS's avatar
Laurent THOMAS committed
569 570

#define SZ_iPTR(Sz)  {idft ## Sz,Sz},
Laurent THOMAS's avatar
Laurent THOMAS committed
571 572 573 574 575
struct {
  adftfunc_t func;
  int size;
} idft_ftab[]= {
  FOREACH_IDFTSZ(SZ_iPTR)
frtabu's avatar
frtabu committed
576
};
577

frtabu's avatar
frtabu committed
578
#endif
579

580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
/*******************************************************************
*
* NAME :         get_idft
*
* PARAMETERS :   size of ofdm symbol
*
* RETURN :       index pointing to the dft func in the dft library
*
* DESCRIPTION :  get idft function depending of ofdm size
*
*********************************************************************/
static inline
idft_size_idx_t get_idft(int ofdm_symbol_size)
{
  switch (ofdm_symbol_size) {
    case 128:
      return IDFT_128;
    case 256:
      return IDFT_256;
    case 512:
      return IDFT_512;
601 602
    case 768:
      return IDFT_768;
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
    case 1024:
      return IDFT_1024;
    case 1536:
      return IDFT_1536;
    case 2048:
      return IDFT_2048;
    case 3072:
      return IDFT_3072;
    case 4096:
      return IDFT_4096;
    case 6144:
      return IDFT_6144;
    case 8192:
      return IDFT_8192;
    case 9216:
      return IDFT_9216;
    case 12288:
      return IDFT_12288;
    case 18432:
      return IDFT_18432;
    case 24576:
      return IDFT_24576;
    case 36864:
      return IDFT_36864;
    case 49152:
      return IDFT_49152;
    case 73728:
      return IDFT_73728;
    case 98304:
      return IDFT_98304;
    default:
      printf("function get_idft : unsupported ofdm symbol size \n");
      assert(0);
      break;
637 638
  }
  return IDFT_SIZE_IDXTABLESIZE; // never reached and will trigger assertion in idft function
639
}
640

641

642
/*!\fn int32_t rotate_cpx_vector(c16_t *x,c16_t *alpha,c16_t *y,uint32_t N,uint16_t output_shift)
643
This function performs componentwise multiplication of a vector with a complex scalar.
644
@param x Vector input (Q1.15)  in the format  |Re0  Im0|,......,|Re(N-1) Im(N-1)|
645
@param alpha Scalar input (Q1.15) in the format  |Re0 Im0|
646
@param y Output (Q1.15) in the format  |Re0  Im0|,......,|Re(N-1) Im(N-1)|
647 648 649 650 651
@param N Length of x WARNING: N>=4
@param output_shift Number of bits to shift output down to Q1.15 (should be 15 for Q1.15 inputs) WARNING: log2_amp>0 can cause overflow!!

The function implemented is : \f$\mathbf{y} = \alpha\mathbf{x}\f$
*/
652
void rotate_cpx_vector(c16_t *x,
laurent's avatar
laurent committed
653 654 655 656
                       c16_t *alpha,
                       c16_t *y,
                       uint32_t N,
                       uint16_t output_shift);
657 658


659
//cadd_sv.c
660

661
/*!\fn int32_t add_cpx_vector(int16_t *x,int16_t *alpha,int16_t *y,uint32_t N)
662
This function performs componentwise addition of a vector with a complex scalar.
663
@param x Vector input (Q1.15)  in the format  |Re0  Im0 Re1 Im1|,......,|Re(N-2)  Im(N-2) Re(N-1) Im(N-1)|
664
@param alpha Scalar input (Q1.15) in the format  |Re0 Im0|
665
@param y Output (Q1.15) in the format  |Re0  Im0 Re1 Im1|,......,|Re(N-2)  Im(N-2) Re(N-1) Im(N-1)|
666 667 668 669
@param N Length of x WARNING: N>=4

The function implemented is : \f$\mathbf{y} = \alpha + \mathbf{x}\f$
*/
670
int32_t add_cpx_vector(int16_t *x,
671 672 673
                       int16_t *alpha,
                       int16_t *y,
                       uint32_t N);
674

lukashov's avatar
lukashov committed
675
int32_t sub_cpx_vector16(int16_t *x,
yilmazt's avatar
yilmazt committed
676 677 678
                         int16_t *y,
                         int16_t *z,
                         uint32_t N);
lukashov's avatar
lukashov committed
679

680
/*!\fn int32_t signal_energy(int *,uint32_t);
681 682
\brief Computes the signal energy per subcarrier
*/
683
int32_t signal_energy(int32_t *,uint32_t);
684

685 686 687 688 689 690 691
/*!\fn int32_t signal_energy_fixed_p9(int *input, uint32_t length);
\brief Computes the signal energy per subcarrier
\ the input signal has a fixed point representation of AMP_SHIFT bits
\ the ouput energy has a fixed point representation of AMP_SHIFT bits
*/
int32_t signal_energy_amp_shift(int32_t *input, uint32_t length);

692 693 694 695
#ifdef LOCALIZATION
/*!\fn int32_t signal_energy(int *,uint32_t);
\brief Computes the signal energy per subcarrier
*/
Laurent THOMAS's avatar
Laurent THOMAS committed
696
int32_t subcarrier_energy(int32_t *,uint32_t, int32_t *subcarrier_energy, uint16_t rx_power_correction);
697 698
#endif

699
/*!\fn int32_t signal_energy_nodc(int32_t *,uint32_t);
700 701
\brief Computes the signal energy per subcarrier, without DC removal
*/
702
int32_t signal_energy_nodc(int32_t *,uint32_t);
703

704 705 706
int32_t signal_power(int32_t *,uint32_t);
int32_t interference_power(int32_t *,uint32_t);

707
/*!\fn double signal_energy_fp(double *s_re[2], double *s_im[2],uint32_t, uint32_t,uint32_t);
708 709
\brief Computes the signal energy per subcarrier
*/
710
double signal_energy_fp(double *s_re[2], double *s_im[2], uint32_t nb_antennas, uint32_t length,uint32_t offset);
711

712
/*!\fn double signal_energy_fp2(struct complex *, uint32_t);
713 714
\brief Computes the signal energy per subcarrier
*/
715
double signal_energy_fp2(struct complexd *s, uint32_t length);
716 717


718 719 720 721 722
int32_t iSqrt(int32_t value);
uint8_t log2_approx(uint32_t);
uint8_t log2_approx64(unsigned long long int x);
int16_t invSqrt(int16_t x);
uint32_t angle(struct complex16 perrror);
723

724 725 726
/// computes the number of factors 2 in x
unsigned char factor2(unsigned int x);

727
/*!\fn int32_t phy_phase_compensation_top (uint32_t pilot_type, uint32_t initial_pilot,
728
        uint32_t last_pilot, int32_t ignore_prefix);
729 730 731 732 733 734 735 736 737
Compensate the phase rotation of the RF. WARNING: This function is currently unused. It has not been tested!
@param pilot_type indicates whether it is a CHBCH (=0) or a SCH (=1) pilot
@param initial_pilot index of the first pilot (which serves as reference)
@param last_pilot index of the last pilot in the range of pilots to correct the phase
@param ignore_prefix set to 1 if cyclic prefix has not been removed (by the hardware)

*/


738
int8_t dB_fixed(uint32_t x);
739

740
uint8_t dB_fixed64(uint64_t x);
741

742
int8_t dB_fixed2(uint32_t x,uint32_t y);
743

744
int16_t dB_fixed_times10(uint32_t x);
745
int16_t dB_fixed_x10(uint32_t x);
746

yilmazt's avatar
yilmazt committed
747 748 749 750
int32_t phy_phase_compensation_top(uint32_t pilot_type,
                                   uint32_t initial_pilot,
                                   uint32_t last_pilot,
                                   int32_t ignore_prefix);
751

laurent's avatar
laurent committed
752 753 754 755
c32_t dot_product(const c16_t *x,
                  const c16_t *y,
                  const uint32_t N, // must be a multiple of 8
                  const int output_shift);
756

757
/** @} */
758 759


760 761
double interp(double x, double *xs, double *ys, int count);

Guy De Souza's avatar
Guy De Souza committed
762

763 764 765 766
#ifdef __cplusplus
}
#endif

767
#endif //__PHY_TOOLS_DEFS__H__