prach.c 62.4 KB
Newer Older
1
/*******************************************************************************
2
    OpenAirInterface
ghaddab's avatar
ghaddab committed
3
    Copyright(c) 1999 - 2014 Eurecom
4

ghaddab's avatar
ghaddab committed
5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


ghaddab's avatar
ghaddab committed
11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

ghaddab's avatar
ghaddab committed
16
    You should have received a copy of the GNU General Public License
17 18
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
ghaddab's avatar
ghaddab committed
19
   see <http://www.gnu.org/licenses/>.
20 21

  Contact Information
ghaddab's avatar
ghaddab committed
22 23 24
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

ghaddab's avatar
ghaddab committed
28
 *******************************************************************************/
29 30 31 32 33 34 35 36 37 38 39

/*! \file PHY/LTE_TRANSPORT/prach.c
 * \brief Top-level routines for generating and decoding the PRACH physical channel V8.6 2009-03
 * \author R. Knopp
 * \date 2011
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr
 * \note
 * \warning
 */
40
#include "PHY/sse_intrin.h"
41 42 43 44 45 46 47
#include "PHY/defs.h"
#include "PHY/extern.h"
//#include "prach.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
#include "UTIL/LOG/vcd_signal_dumper.h"

48
//#define PRACH_DEBUG 1
49

50 51 52
uint16_t NCS_unrestricted[16] = {0,13,15,18,22,26,32,38,46,59,76,93,119,167,279,419};
uint16_t NCS_restricted[15]   = {15,18,22,26,32,38,46,55,68,82,100,128,158,202,237}; // high-speed case
uint16_t NCS_4[7]             = {2,4,6,8,10,12,15};
53

54 55 56
int16_t ru[2*839]; // quantized roots of unity
uint32_t ZC_inv[839]; // multiplicative inverse for roots u
uint16_t du[838];
57 58

typedef struct {
59 60 61 62
  uint8_t f_ra;
  uint8_t t0_ra;
  uint8_t t1_ra;
  uint8_t t2_ra;
63 64
} PRACH_TDD_PREAMBLE_MAP_elem;
typedef struct {
65
  uint8_t num_prach;
66 67 68 69
  PRACH_TDD_PREAMBLE_MAP_elem map[6];
} PRACH_TDD_PREAMBLE_MAP;

// This is table 5.7.1-4 from 36.211
70
PRACH_TDD_PREAMBLE_MAP tdd_preamble_map[64][7] = {
71 72 73 74 75 76 77 78 79 80 81
  // TDD Configuration Index 0
  { {1,{{0,1,0,2}}},{1,{{0,1,0,1}}}, {1,{{0,1,0,0}}}, {1,{{0,1,0,2}}}, {1,{{0,1,0,1}}}, {1,{{0,1,0,0}}}, {1,{{0,1,0,2}}}},
  // TDD Configuration Index 1
  { {1,{{0,2,0,2}}},{1,{{0,2,0,1}}}, {1,{{0,2,0,0}}}, {1,{{0,2,0,2}}}, {1,{{0,2,0,1}}}, {1,{{0,2,0,0}}}, {1,{{0,2,0,2}}}},
  // TDD Configuration Index 2
  { {1,{{0,1,1,2}}},{1,{{0,1,1,1}}}, {1,{{0,1,1,0}}}, {1,{{0,1,0,1}}}, {1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,1,1}}}},
  // TDD Configuration Index 3
  { {1,{{0,0,0,2}}},{1,{{0,0,0,1}}}, {1,{{0,0,0,0}}}, {1,{{0,0,0,2}}}, {1,{{0,0,0,1}}}, {1,{{0,0,0,0}}}, {1,{{0,0,0,2}}}},
  // TDD Configuration Index 4
  { {1,{{0,0,1,2}}},{1,{{0,0,1,1}}}, {1,{{0,0,1,0}}}, {1,{{0,0,0,1}}}, {1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,1,1}}}},
  // TDD Configuration Index 5
82
  { {1,{{0,0,0,1}}},{1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,1}}}},
83 84 85
  // TDD Configuration Index 6
  { {2,{{0,0,0,2},{0,0,1,2}}}, {2,{{0,0,0,1},{0,0,1,1}}}, {2,{{0,0,0,0},{0,0,1,0}}}, {2,{{0,0,0,1},{0,0,0,2}}}, {2,{{0,0,0,0},{0,0,0,1}}}, {2,{{0,0,0,0},{1,0,0,0}}}, {2,{{0,0,0,2},{0,0,1,1}}}},
  // TDD Configuration Index 7
86
  { {2,{{0,0,0,1},{0,0,1,1}}}, {2,{{0,0,0,0},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,0},{0,0,0,2}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,1},{0,0,1,0}}}},
87 88 89 90 91 92 93
  // TDD Configuration Index 8
  { {2,{{0,0,0,0},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,0},{0,0,0,1}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,0},{0,0,1,1}}}},
  // TDD Configuration Index 9
  { {3,{{0,0,0,1},{0,0,0,2},{0,0,1,2}}}, {3,{{0,0,0,0},{0,0,0,1},{0,0,1,1}}}, {3,{{0,0,0,0},{0,0,1,0},{1,0,0,0}}}, {3,{{0,0,0,0},{0,0,0,1},{0,0,0,2}}}, {3,{{0,0,0,0},{0,0,0,1},{1,0,0,1}}}, {3,{{0,0,0,0},{1,0,0,0},{2,0,0,0}}}, {3,{{0,0,0,1},{0,0,0,2},{0,0,1,1}}}},
  // TDD Configuration Index 10
  { {3,{{0,0,0,0},{0,0,1,0},{0,0,1,1}}}, {3,{{0,0,0,1},{0,0,1,0},{0,0,1,1}}}, {3,{{0,0,0,0},{0,0,1,0},{1,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,0},{0,0,0,1},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,0},{0,0,0,2},{0,0,1,0}}}},
  // TDD Configuration Index 11
94
  { {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,0},{0,0,0,1},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,1},{0,0,1,0},{0,0,1,1}}}},
95
  // TDD Configuration Index 12
96
  { {4,{{0,0,0,1},{0,0,0,2},{0,0,1,1},{0,0,1,2}}}, {4,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1}}},
97 98 99 100 101 102 103
    {4,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0}}},
    {4,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,2}}},
    {4,{{0,0,0,0},{0,0,0,1},{1,0,0,0},{1,0,0,1}}},
    {4,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0}}},
    {4,{{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1}}}
  },
  // TDD Configuration Index 13
104
  { {4,{{0,0,0,0},{0,0,0,2},{0,0,1,0},{0,0,1,2}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
105 106 107 108 109 110 111
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {4,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,1}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {4,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,1}}}
  },
  // TDD Configuration Index 14
112
  { {4,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
113 114 115 116 117 118 119
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {4,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {4,{{0,0,0,0},{0,0,0,2},{0,0,1,0},{0,0,1,1}}}
  },
  // TDD Configuration Index 15
120
  { {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,1},{0,0,1,2}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{1,0,0,1}}},
121 122 123 124 125
    {5,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,1},{1,0,0,2}}},
    {5,{{0,0,0,0},{0,0,0,1},{1,0,0,0},{1,0,0,1},{2,0,0,1}}}, {5,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0}}},
    {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1}}}
  },
  // TDD Configuration Index 16
126
  { {5,{{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1},{0,0,1,2}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{1,0,1,1}}},
127 128 129 130 131
    {5,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,1,0}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,0},{1,0,0,2}}},
    {5,{{0,0,0,0},{0,0,0,1},{1,0,0,0},{1,0,0,1},{2,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}
  },
  // TDD Configuration Index 17
132
  { {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,2}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{1,0,0,0}}},
133 134 135 136 137
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {5,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,0},{1,0,0,1}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}
  },
  // TDD Configuration Index 18
138
  { {6,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1},{0,0,1,2}}},
139 140 141 142 143 144 145 146
    {6,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{1,0,0,1},{1,0,1,1}}},
    {6,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0},{2,0,1,0}}},
    {6,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{1,0,0,0},{1,0,0,1},{1,0,0,2}}},
    {6,{{0,0,0,0},{0,0,0,1},{1,0,0,0},{1,0,0,1},{2,0,0,0},{2,0,0,1}}},
    {6,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0},{5,0,0,0}}},
    {6,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1},{1,0,0,2}}}
  },
  // TDD Configuration Index 19
147
  { {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
148 149 150 151 152 153 154 155
    {6,{{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{1,0,0,0},{1,0,1,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {6,{{0,0,0,0},{0,0,0,1},{0,0,0,2},{0,0,1,0},{0,0,1,1},{1,0,1,1}}}
  },
  // TDD Configuration Index 20
156
  { {1,{{0,1,0,1}}},{1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,1}}}, {1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,1}}}},
157
  // TDD Configuration Index 21
158 159
  { {1,{{0,2,0,1}}},{1,{{0,2,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,1}}}, {1,{{0,2,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,1}}}},

160
  // TDD Configuration Index 22
161 162
  { {1,{{0,1,1,1}}},{1,{{0,1,1,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,1,0}}}},

163
  // TDD Configuration Index 23
164 165
  { {1,{{0,0,0,1}}},{1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,1}}}, {1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,1}}}},

166
  // TDD Configuration Index 24
167 168 169 170 171
  { {1,{{0,0,1,1}}},{1,{{0,0,1,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,1,0}}}},

  // TDD Configuration Index 25
  { {2,{{0,0,0,1},{0,0,1,1}}}, {2,{{0,0,0,0},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,1},{1,0,0,1}}}, {2,{{0,0,0,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,1},{0,0,1,0}}}},

172
  // TDD Configuration Index 26
173 174
  { {3,{{0,0,0,1},{0,0,1,1},{1,0,0,1}}}, {3,{{0,0,0,0},{0,0,1,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,1},{1,0,0,1},{2,0,0,1}}}, {3,{{0,0,0,0},{1,0,0,0},{2,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,1},{0,0,1,0},{1,0,0,1}}}},

175
  // TDD Configuration Index 27
176
  { {4,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1}}}, {4,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0}}},
177 178 179 180 181 182 183 184
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {4,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1}}},
    {4,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {4,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0}}}
  },

  // TDD Configuration Index 28
185
  { {5,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1},{2,0,0,1}}}, {5,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0}}},
186 187 188 189
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {5,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1},{4,0,0,1}}},
    {5,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {5,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0},{2,0,0,1}}}
  },
190

191
  // TDD Configuration Index 29
192
  { {6,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1},{2,0,0,1},{2,0,1,1}}},
193 194 195 196 197 198 199
    {6,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0},{2,0,1,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {6,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1},{4,0,0,1},{5,0,0,1}}},
    {6,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0},{5,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {6,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0},{2,0,0,1},{2,0,1,0}}}
  },
200 201


202
  // TDD Configuration Index 30
203 204
  { {1,{{0,1,0,1}}},{1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,1}}}, {1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,1}}}},

205
  // TDD Configuration Index 31
206 207
  { {1,{{0,2,0,1}}},{1,{{0,2,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,1}}}, {1,{{0,2,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,1}}}},

208
  // TDD Configuration Index 32
209 210
  { {1,{{0,1,1,1}}},{1,{{0,1,1,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,1,0}}}},

211
  // TDD Configuration Index 33
212 213
  { {1,{{0,0,0,1}}},{1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,1}}}, {1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,1}}}},

214
  // TDD Configuration Index 34
215 216
  { {1,{{0,0,1,1}}},{1,{{0,0,1,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,1,0}}}},

217
  // TDD Configuration Index 35
218 219
  { {2,{{0,0,0,1},{0,0,1,1}}}, {2,{{0,0,0,0},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,1},{1,0,0,1}}}, {2,{{0,0,0,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,1},{0,0,1,0}}}},

220
  // TDD Configuration Index 36
221 222
  { {3,{{0,0,0,1},{0,0,1,1},{1,0,0,1}}}, {3,{{0,0,0,0},{0,0,1,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,1},{1,0,0,1},{2,0,0,1}}}, {3,{{0,0,0,0},{1,0,0,0},{2,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,1},{0,0,1,0},{1,0,0,1}}}},

223
  // TDD Configuration Index 37
224
  { {4,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1}}}, {4,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0}}},
225 226 227 228 229 230 231 232
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {4,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1}}},
    {4,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {4,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0}}}
  },

  // TDD Configuration Index 38
233
  { {5,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1},{2,0,0,1}}}, {5,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0}}},
234 235 236 237
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {5,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1},{4,0,0,1}}},
    {5,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {5,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0},{2,0,0,1}}}
  },
238

239
  // TDD Configuration Index 39
240
  { {6,{{0,0,0,1},{0,0,1,1},{1,0,0,1},{1,0,1,1},{2,0,0,1},{2,0,1,1}}},
241 242 243 244 245 246 247 248 249
    {6,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0},{2,0,0,0},{2,0,1,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {6,{{0,0,0,1},{1,0,0,1},{2,0,0,1},{3,0,0,1},{4,0,0,1},{5,0,0,1}}},
    {6,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0},{4,0,0,0},{5,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {6,{{0,0,0,1},{0,0,1,0},{1,0,0,1},{1,0,1,0},{2,0,0,1},{2,0,1,0}}}
  },

  // TDD Configuration Index 40
250
  { {1,{{0,1,0,0}}},{0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,1,0,0}}}},
251
  // TDD Configuration Index 41
252 253
  { {1,{{0,2,0,0}}},{0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,2,0,0}}}},

254
  // TDD Configuration Index 42
255 256
  { {1,{{0,1,1,0}}},{0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}},

257
  // TDD Configuration Index 43
258 259
  { {1,{{0,0,0,0}}},{0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {1,{{0,0,0,0}}}},

260
  // TDD Configuration Index 44
261 262
  { {1,{{0,0,1,0}}},{0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}, {0,{{0,0,0,0}}}},

263
  // TDD Configuration Index 45
264 265
  { {2,{{0,0,0,0},{0,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0}}}, {2,{{0,0,0,0},{1,0,0,0}}}},

266
  // TDD Configuration Index 46
267 268
  { {3,{{0,0,0,0},{0,0,1,0},{1,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,0},{1,0,0,0},{2,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0}}}, {3,{{0,0,0,0},{1,0,0,0},{2,0,0,0}}}},

269
  // TDD Configuration Index 47
270
  { {4,{{0,0,0,0},{0,0,1,0},{1,0,0,0},{1,0,1,0}}}, {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
271 272 273 274 275 276
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {4,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
    {4,{{0,0,0,0},{1,0,0,0},{2,0,0,0},{3,0,0,0}}}
  }
277 278
};

279 280


281
uint16_t prach_root_sequence_map0_3[838] = { 129, 710, 140, 699, 120, 719, 210, 629, 168, 671, 84, 755, 105, 734, 93, 746, 70, 769, 60, 779,
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 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
                                             2, 837, 1, 838,
                                             56, 783, 112, 727, 148, 691,
                                             80, 759, 42, 797, 40, 799,
                                             35, 804, 73, 766, 146, 693,
                                             31, 808, 28, 811, 30, 809, 27, 812, 29, 810,
                                             24, 815, 48, 791, 68, 771, 74, 765, 178, 661, 136, 703,
                                             86, 753, 78, 761, 43, 796, 39, 800, 20, 819, 21, 818,
                                             95, 744, 202, 637, 190, 649, 181, 658, 137, 702, 125, 714, 151, 688,
                                             217, 622, 128, 711, 142, 697, 122, 717, 203, 636, 118, 721, 110, 729, 89, 750, 103, 736, 61,
                                             778, 55, 784, 15, 824, 14, 825,
                                             12, 827, 23, 816, 34, 805, 37, 802, 46, 793, 207, 632, 179, 660, 145, 694, 130, 709, 223, 616,
                                             228, 611, 227, 612, 132, 707, 133, 706, 143, 696, 135, 704, 161, 678, 201, 638, 173, 666, 106,
                                             733, 83, 756, 91, 748, 66, 773, 53, 786, 10, 829, 9, 830,
                                             7, 832, 8, 831, 16, 823, 47, 792, 64, 775, 57, 782, 104, 735, 101, 738, 108, 731, 208, 631, 184,
                                             655, 197, 642, 191, 648, 121, 718, 141, 698, 149, 690, 216, 623, 218, 621,
                                             152, 687, 144, 695, 134, 705, 138, 701, 199, 640, 162, 677, 176, 663, 119, 720, 158, 681, 164,
                                             675, 174, 665, 171, 668, 170, 669, 87, 752, 169, 670, 88, 751, 107, 732, 81, 758, 82, 757, 100,
                                             739, 98, 741, 71, 768, 59, 780, 65, 774, 50, 789, 49, 790, 26, 813, 17, 822, 13, 826, 6, 833,
                                             5, 834, 33, 806, 51, 788, 75, 764, 99, 740, 96, 743, 97, 742, 166, 673, 172, 667, 175, 664, 187,
                                             652, 163, 676, 185, 654, 200, 639, 114, 725, 189, 650, 115, 724, 194, 645, 195, 644, 192, 647,
                                             182, 657, 157, 682, 156, 683, 211, 628, 154, 685, 123, 716, 139, 700, 212, 627, 153, 686, 213,
                                             626, 215, 624, 150, 689,
                                             225, 614, 224, 615, 221, 618, 220, 619, 127, 712, 147, 692, 124, 715, 193, 646, 205, 634, 206,
                                             633, 116, 723, 160, 679, 186, 653, 167, 672, 79, 760, 85, 754, 77, 762, 92, 747, 58, 781, 62,
                                             777, 69, 770, 54, 785, 36, 803, 32, 807, 25, 814, 18, 821, 11, 828, 4, 835,
                                             3, 836, 19, 820, 22, 817, 41, 798, 38, 801, 44, 795, 52, 787, 45, 794, 63, 776, 67, 772, 72,
                                             767, 76, 763, 94, 745, 102, 737, 90, 749, 109, 730, 165, 674, 111, 728, 209, 630, 204, 635, 117,
                                             722, 188, 651, 159, 680, 198, 641, 113, 726, 183, 656, 180, 659, 177, 662, 196, 643, 155, 684,
                                             214, 625, 126, 713, 131, 708, 219, 620, 222, 617, 226, 613,
                                             230, 609, 232, 607, 262, 577, 252, 587, 418, 421, 416, 423, 413, 426, 411, 428, 376, 463, 395,
                                             444, 283, 556, 285, 554, 379, 460, 390, 449, 363, 476, 384, 455, 388, 451, 386, 453, 361, 478,
                                             387, 452, 360, 479, 310, 529, 354, 485, 328, 511, 315, 524, 337, 502, 349, 490, 335, 504, 324,
                                             515,
                                             323, 516, 320, 519, 334, 505, 359, 480, 295, 544, 385, 454, 292, 547, 291, 548, 381, 458, 399,
                                             440, 380, 459, 397, 442, 369, 470, 377, 462, 410, 429, 407, 432, 281, 558, 414, 425, 247, 592,
                                             277, 562, 271, 568, 272, 567, 264, 575, 259, 580,
                                             237, 602, 239, 600, 244, 595, 243, 596, 275, 564, 278, 561, 250, 589, 246, 593, 417, 422, 248,
                                             591, 394, 445, 393, 446, 370, 469, 365, 474, 300, 539, 299, 540, 364, 475, 362, 477, 298, 541,
                                             312, 527, 313, 526, 314, 525, 353, 486, 352, 487, 343, 496, 327, 512, 350, 489, 326, 513, 319,
                                             520, 332, 507, 333, 506, 348, 491, 347, 492, 322, 517,
                                             330, 509, 338, 501, 341, 498, 340, 499, 342, 497, 301, 538, 366, 473, 401, 438, 371, 468, 408,
                                             431, 375, 464, 249, 590, 269, 570, 238, 601, 234, 605,
                                             257, 582, 273, 566, 255, 584, 254, 585, 245, 594, 251, 588, 412, 427, 372, 467, 282, 557, 403,
                                             436, 396, 443, 392, 447, 391, 448, 382, 457, 389, 450, 294, 545, 297, 542, 311, 528, 344, 495,
                                             345, 494, 318, 521, 331, 508, 325, 514, 321, 518,
                                             346, 493, 339, 500, 351, 488, 306, 533, 289, 550, 400, 439, 378, 461, 374, 465, 415, 424, 270,
                                             569, 241, 598,
                                             231, 608, 260, 579, 268, 571, 276, 563, 409, 430, 398, 441, 290, 549, 304, 535, 308, 531, 358,
                                             481, 316, 523,
                                             293, 546, 288, 551, 284, 555, 368, 471, 253, 586, 256, 583, 263, 576,
                                             242, 597, 274, 565, 402, 437, 383, 456, 357, 482, 329, 510,
                                             317, 522, 307, 532, 286, 553, 287, 552, 266, 573, 261, 578,
                                             236, 603, 303, 536, 356, 483,
                                             355, 484, 405, 434, 404, 435, 406, 433,
                                             235, 604, 267, 572, 302, 537,
                                             309, 530, 265, 574, 233, 606,
                                             367, 472, 296, 543,
                                             336, 503, 305, 534, 373, 466, 280, 559, 279, 560, 419, 420, 240, 599, 258, 581, 229, 610
                                           };
341

342
uint16_t prach_root_sequence_map4[138] = {  1,138,2,137,3,136,4,135,5,134,6,133,7,132,8,131,9,130,10,129,
343 344 345 346 347 348 349
                                            11,128,12,127,13,126,14,125,15,124,16,123,17,122,18,121,19,120,20,119,
                                            21,118,22,117,23,116,24,115,25,114,26,113,27,112,28,111,29,110,30,109,
                                            31,108,32,107,33,106,34,105,35,104,36,103,37,102,38,101,39,100,40,99,
                                            41,98,42,97,43,96,44,95,45,94,46,93,47,92,48,91,49,90,50,89,
                                            51,88,52,87,53,86,54,85,55,84,56,83,57,82,58,81,59,80,60,79,
                                            61,78,62,77,63,76,64,75,65,74,66,73,67,72,68,71,69,70
                                         };
350 351

#ifdef USER_MODE
352 353
void dump_prach_config(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe)
{
354 355 356 357 358 359 360

  FILE *fd;

  fd = fopen("prach_config.txt","w");
  fprintf(fd,"prach_config: subframe          = %d\n",subframe);
  fprintf(fd,"prach_config: N_RB_UL           = %d\n",frame_parms->N_RB_UL);
  fprintf(fd,"prach_config: frame_type        = %s\n",(frame_parms->frame_type==1) ? "TDD":"FDD");
361

362
  if(frame_parms->frame_type==1) fprintf(fd,"prach_config: tdd_config        = %d\n",frame_parms->tdd_config);
363 364 365

  fprintf(fd,"prach_config: rootSequenceIndex = %d\n",frame_parms->prach_config_common.rootSequenceIndex);
  fprintf(fd,"prach_config: prach_ConfigIndex = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex);
366 367 368 369 370 371 372 373 374
  fprintf(fd,"prach_config: Ncs_config        = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig);
  fprintf(fd,"prach_config: highSpeedFlag     = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.highSpeedFlag);
  fprintf(fd,"prach_config: n_ra_prboffset    = %d\n",frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset);
  fclose(fd);

}
#endif

// This function computes the du
375 376
void fill_du(uint8_t prach_fmt)
{
377

378 379 380
  uint16_t iu,u,p;
  uint16_t N_ZC;
  uint16_t *prach_root_sequence_map;
381 382 383 384

  if (prach_fmt<4) {
    N_ZC = 839;
    prach_root_sequence_map = prach_root_sequence_map0_3;
385
  } else {
386 387 388 389
    N_ZC = 139;
    prach_root_sequence_map = prach_root_sequence_map4;
  }

390
  for (iu=0; iu<(N_ZC-1); iu++) {
391 392 393

    u=prach_root_sequence_map[iu];
    p=1;
394

395 396
    while (((u*p)%N_ZC)!=1)
      p++;
397

398 399
    du[u] = ((p<(N_ZC>>1)) ? p : (N_ZC-p));
  }
400

401 402
}

403 404
uint8_t get_num_prach_tdd(LTE_DL_FRAME_PARMS *frame_parms)
{
405 406 407 408

  return(tdd_preamble_map[frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex][frame_parms->tdd_config].num_prach);
}

409 410
uint8_t get_fid_prach_tdd(LTE_DL_FRAME_PARMS *frame_parms,uint8_t tdd_map_index)
{
411 412 413 414

  return(tdd_preamble_map[frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex][frame_parms->tdd_config].map[tdd_map_index].f_ra);
}

415 416
uint8_t get_prach_fmt(uint8_t prach_ConfigIndex,lte_frame_type_t frame_type)
{
417 418 419 420 421 422 423

  if (frame_type == FDD) // FDD
    return(prach_ConfigIndex>>4);

  else {
    if (prach_ConfigIndex < 20)
      return (0);
424

425 426
    if (prach_ConfigIndex < 30)
      return (1);
427

428 429
    if (prach_ConfigIndex < 40)
      return (2);
430

431 432 433 434 435 436 437 438
    if (prach_ConfigIndex < 48)
      return (3);
    else
      return (4);
  }
}


439 440
int is_prach_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame, uint8_t subframe)
{
441

442 443
  uint8_t prach_ConfigIndex  = frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
  uint8_t tdd_config         = frame_parms->tdd_config;
444 445 446
  uint8_t t0_ra;
  uint8_t t1_ra;
  uint8_t t2_ra;
447

448

449 450 451
  if (frame_parms->frame_type == FDD) { //FDD
    //implement Table 5.7.1-2 from 36.211 (Rel-10, p.41)
    if ((((frame&1) == 1) && (subframe < 9)) ||
452
        (((frame&1) == 0) && (subframe == 9)))  // This is an odd frame, ignore even-only PRACH frames
453
      if (((prach_ConfigIndex&0xf)<3) || // 0,1,2,16,17,18,32,33,34,48,49,50
454 455 456
          ((prach_ConfigIndex&0x1f)==18) || // 18,50
          ((prach_ConfigIndex&0xf)==15))   // 15,47
        return(0);
457 458 459 460 461 462

    switch (prach_ConfigIndex&0x1f) {
    case 0:
    case 3:
      return(subframe==1);
      break;
463

464 465 466 467
    case 1:
    case 4:
      return(subframe==4);
      break;
468

469 470 471 472
    case 2:
    case 5:
      return(subframe==7);
      break;
473

474 475 476
    case 6:
      return((subframe==1) || (subframe==6));
      break;
477

478 479 480
    case 7:
      return((subframe==2) || (subframe==7));
      break;
481

482 483 484
    case 8:
      return((subframe==3) || (subframe==8));
      break;
485

486 487 488
    case 9:
      return((subframe==1) || (subframe==4) || (subframe==7));
      break;
489

490 491 492
    case 10:
      return((subframe==2) || (subframe==5) || (subframe==8));
      break;
493

494 495 496
    case 11:
      return((subframe==3) || (subframe==6) || (subframe==9));
      break;
497

498 499 500
    case 12:
      return((subframe&1)==0);
      break;
501

502 503 504
    case 13:
      return((subframe&1)==1);
      break;
505

506 507 508
    case 14:
      return(1==1);
      break;
509

510 511 512 513
    case 15:
      return(subframe==9);
      break;
    }
514
  } else { // TDD
515 516 517 518 519 520 521 522 523

    if (prach_ConfigIndex>=64) {
      LOG_E(PHY,"[PHY] Illegal prach_ConfigIndex %d for ",prach_ConfigIndex);
      return(0);
    }

    if (tdd_preamble_map[prach_ConfigIndex][tdd_config].num_prach==0) {
      LOG_E(PHY,"[PHY] Illegal prach_ConfigIndex %d for ",prach_ConfigIndex);
      return(0);
524
    }
525 526 527 528

    t0_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t0_ra;
    t1_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t1_ra;
    t2_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t2_ra;
529
#ifdef PRACH_DEBUG
530
    LOG_D(PHY,"[PRACH] Checking for PRACH format (ConfigIndex %d) in TDD subframe %d (%d,%d,%d)\n",
531 532 533 534 535
          prach_ConfigIndex,
          subframe,
          t0_ra,t1_ra,t2_ra);
#endif

536
    if ((((t0_ra == 1) && ((frame &1)==0))||  // frame is even and PRACH is in even frames
537 538 539 540 541 542
         ((t0_ra == 2) && ((frame &1)==1))||  // frame is odd and PRACH is in odd frames
         (t0_ra == 0)) &&                                // PRACH is in all frames
        (((subframe<5)&&(t1_ra==0)) ||                   // PRACH is in 1st half-frame
         (((subframe>4)&&(t1_ra==1))))) {                // PRACH is in 2nd half-frame
      if (prach_ConfigIndex<48)                          // PRACH only in normal UL subframe
        return((((subframe%5)-2)==t2_ra));
543
      else                                               // PRACH can be in UpPTS
544 545
        return((((subframe%5)-1)==t2_ra));
    } else
546 547
      return(1==2);
  }
548

549 550 551 552 553 554
  // shouldn't get here!
  return(2==1);
}

static short prach_tmp[45600*2] __attribute__((aligned(16)));

555 556 557
int32_t generate_prach(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe, uint16_t Nf)
{

558
  lte_frame_type_t frame_type         = phy_vars_ue->lte_frame_parms.frame_type;
559
  uint8_t tdd_config         = phy_vars_ue->lte_frame_parms.tdd_config;
560 561
  uint16_t rootSequenceIndex = phy_vars_ue->lte_frame_parms.prach_config_common.rootSequenceIndex;
  uint8_t prach_ConfigIndex  = phy_vars_ue->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
  uint8_t Ncs_config         = phy_vars_ue->lte_frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig;
  uint8_t restricted_set     = phy_vars_ue->lte_frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag;
  uint8_t n_ra_prboffset     = phy_vars_ue->lte_frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset;
  uint8_t preamble_index     = phy_vars_ue->prach_resources[eNB_id]->ra_PreambleIndex;
  uint8_t tdd_mapindex       = phy_vars_ue->prach_resources[eNB_id]->ra_TDD_map_index;
  int16_t *prachF           = phy_vars_ue->lte_ue_prach_vars[eNB_id]->prachF;
  int16_t *prach            = (int16_t*)prach_tmp;
  int16_t *prach2;
  int16_t amp               = phy_vars_ue->lte_ue_prach_vars[eNB_id]->amp;
  int16_t Ncp;
  uint8_t n_ra_prb;
  uint16_t NCS;
  uint16_t *prach_root_sequence_map;
  uint16_t preamble_offset,preamble_shift;
  uint16_t preamble_index0,n_shift_ra,n_shift_ra_bar;
  uint16_t d_start,n_group_ra,numshift;

  uint8_t prach_fmt = get_prach_fmt(prach_ConfigIndex,frame_type);
  uint8_t Nsp=2;
  uint8_t f_ra,t1_ra;
  uint16_t N_ZC = (prach_fmt<4)?839:139;
  uint8_t not_found;
584
  int k;
585 586 587 588
  int16_t *Xu;
  uint16_t u;
  int32_t Xu_re,Xu_im;
  uint16_t offset,offset2;
589 590 591 592 593
  int prach_start;
#ifdef EXMIMO
  int overflow,j;
#endif
  int i, prach_len;
594
  uint16_t first_nonzero_root_idx=0;
595 596 597 598

  //LOG_I(PHY,"[PRACH] prach_start=%d\n",prach_start);

#ifdef BIT8_TX
599
  prach_start = ((subframe*phy_vars_ue->lte_frame_parms.samples_per_tti)<<1)-phy_vars_ue->N_TA_offset;
600 601
#else
#ifdef EXMIMO
602
  prach_start =  (phy_vars_ue->rx_offset+subframe*phy_vars_ue->lte_frame_parms.samples_per_tti-openair_daq_vars.timing_advance-phy_vars_ue->N_TA_offset);
603

604 605
  if (prach_start<0)
    prach_start+=(phy_vars_ue->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME);
606

607 608
  if (prach_start>=(phy_vars_ue->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME))
    prach_start-=(phy_vars_ue->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME);
609

610
#else //normal case (simulation)
611
  prach_start = subframe*phy_vars_ue->lte_frame_parms.samples_per_tti-phy_vars_ue->N_TA_offset;
612 613 614 615 616 617 618
#endif
#endif

  // First compute physical root sequence
  if (restricted_set == 0) {
    if (Ncs_config>15) {
      LOG_E(PHY,"[PHY] FATAL, Illegal Ncs_config for unrestricted format %d\n",Ncs_config);
gauthier's avatar
gauthier committed
619
      mac_xface->macphy_exit("PRACH: Illegal Ncs_config for unrestricted format");
620
      return 0; // not reached
621
    }
622 623 624

    NCS = NCS_unrestricted[Ncs_config];
  } else {
625 626
    if (Ncs_config>14) {
      LOG_E(PHY,"[PHY] FATAL, Illegal Ncs_config for restricted format %d\n",Ncs_config);
gauthier's avatar
gauthier committed
627
      mac_xface->macphy_exit("PRACH: Illegal Ncs_config for restricted format");
628
      return 0; // not reached
629
    }
630

631 632 633 634 635
    NCS = NCS_restricted[Ncs_config];
  }

  n_ra_prb = n_ra_prboffset;
  prach_root_sequence_map = (prach_fmt<4) ? prach_root_sequence_map0_3 : prach_root_sequence_map4;
636

637 638 639 640
  if (frame_type == TDD) { // TDD

    if (tdd_preamble_map[prach_ConfigIndex][tdd_config].num_prach==0) {
      LOG_E(PHY,"[PHY][UE %d] Illegal prach_ConfigIndex %d for ",phy_vars_ue->Mod_id,prach_ConfigIndex);
641
    }
642 643 644

    // adjust n_ra_prboffset for frequency multiplexing (p.36 36.211)
    f_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[tdd_mapindex].f_ra;
645

646 647
    if (prach_fmt < 4) {
      if ((f_ra&1) == 0) {
648 649 650
        n_ra_prb = n_ra_prboffset + 6*(f_ra>>1);
      } else {
        n_ra_prb = phy_vars_ue->lte_frame_parms.N_RB_UL - 6 - n_ra_prboffset + 6*(f_ra>>1);
651
      }
652 653 654 655
    } else {
      if ((tdd_config >2) && (tdd_config<6))
        Nsp = 2;

656
      t1_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t1_ra;
657

658
      if ((((Nf&1)*(2-Nsp)+t1_ra)&1) == 0) {
659 660 661
        n_ra_prb = 6*f_ra;
      } else {
        n_ra_prb = phy_vars_ue->lte_frame_parms.N_RB_UL - 6*(f_ra+1);
662 663 664 665 666 667
      }
    }
  }

  // This is the relative offset (for unrestricted case) in the root sequence table (5.7.2-4 from 36.211) for the given preamble index
  preamble_offset = ((NCS==0)? preamble_index : (preamble_index/(N_ZC/NCS)));
668

669
  if (restricted_set == 0) {
670
    // This is the \nu corresponding to the preamble index
671
    preamble_shift  = (NCS==0)? 0 : (preamble_index % (N_ZC/NCS));
672 673
    preamble_shift *= NCS;
  } else { // This is the high-speed case
674 675 676 677 678 679 680 681 682 683

#ifdef PRACH_DEBUG
    LOG_D(PHY,"[UE %d] High-speed mode, NCS_config %d\n",phy_vars_ue->Mod_id,Ncs_config);
#endif

    not_found = 1;
    preamble_index0 = preamble_index;
    // set preamble_offset to initial rootSequenceIndex and look if we need more root sequences for this
    // preamble index and find the corresponding cyclic shift
    preamble_offset = 0; // relative rootSequenceIndex;
684

685 686
    while (not_found == 1) {
      // current root depending on rootSequenceIndex and preamble_offset
687
      int index = (rootSequenceIndex + preamble_offset) % N_ZC;
688

689
      if (prach_fmt<4) {
690
        // prach_root_sequence_map points to prach_root_sequence_map0_3
691
        DevAssert( index < sizeof(prach_root_sequence_map0_3) / sizeof(prach_root_sequence_map0_3[0]) );
692
      } else {
693
        // prach_root_sequence_map points to prach_root_sequence_map4
694
        DevAssert( index < sizeof(prach_root_sequence_map4) / sizeof(prach_root_sequence_map4[0]) );
695
      }
696

697
      u = prach_root_sequence_map[index];
698

699
      if ( (du[u]<(N_ZC/3)) && (du[u]>=NCS) ) {
700 701 702 703 704 705 706 707 708 709 710 711
        n_shift_ra     = du[u]/NCS;
        d_start        = (du[u]<<1) + (n_shift_ra * NCS);
        n_group_ra     = N_ZC/d_start;
        n_shift_ra_bar = max(0,(N_ZC-(du[u]<<1)-(n_group_ra*d_start))/N_ZC);
      } else if  ( (du[u]>=(N_ZC/3)) && (du[u]<=((N_ZC - NCS)>>1)) ) {
        n_shift_ra     = (N_ZC - (du[u]<<1))/NCS;
        d_start        = N_ZC - (du[u]<<1) + (n_shift_ra * NCS);
        n_group_ra     = du[u]/d_start;
        n_shift_ra_bar = min(n_shift_ra,max(0,(du[u]- (n_group_ra*d_start))/NCS));
      } else {
        n_shift_ra     = 0;
        n_shift_ra_bar = 0;
712
      }
713

714 715 716 717
      // This is the number of cyclic shifts for the current root u
      numshift = (n_shift_ra*n_group_ra) + n_shift_ra_bar;

      if (numshift>0 && preamble_index0==preamble_index)
718
        first_nonzero_root_idx = preamble_offset;
719 720

      if (preamble_index0 < numshift) {
721 722 723 724 725 726
        not_found      = 0;
        preamble_shift = (d_start * (preamble_index0/n_shift_ra)) + ((preamble_index0%n_shift_ra)*NCS);

      } else { // skip to next rootSequenceIndex and recompute parameters
        preamble_offset++;
        preamble_index0 -= numshift;
727 728 729
      }
    }
  }
730

731 732
  // now generate PRACH signal
#ifdef PRACH_DEBUG
733

734 735
  if (NCS>0)
    LOG_D(PHY,"Generate PRACH for RootSeqIndex %d, Preamble Index %d, NCS %d (NCS_config %d, N_ZC/NCS %d) n_ra_prb %d: Preamble_offset %d, Preamble_shift %d\n",
736 737 738
          rootSequenceIndex,preamble_index,NCS,Ncs_config,N_ZC/NCS,n_ra_prb,
          preamble_offset,preamble_shift);

739 740 741 742
#endif

  //  nsymb = (frame_parms->Ncp==0) ? 14:12;
  //  subframe_offset = (unsigned int)frame_parms->ofdm_symbol_size*subframe*nsymb;
743

744
  k = (12*n_ra_prb) - 6*phy_vars_ue->lte_frame_parms.N_RB_UL;
745

746 747
  if (k<0)
    k+=phy_vars_ue->lte_frame_parms.ofdm_symbol_size;
748

749 750 751
  k*=12;
  k+=13;

752
  Xu = (int16_t*)phy_vars_ue->X_u[preamble_offset-first_nonzero_root_idx];
753 754 755 756 757 758 759

  /*
    k+=(12*phy_vars_ue->lte_frame_parms.first_carrier_offset);
    if (k>(12*phy_vars_ue->lte_frame_parms.ofdm_symbol_size))
    k-=(12*phy_vars_ue->lte_frame_parms.ofdm_symbol_size);
  */
  k*=2;
760

761 762 763 764
  switch (phy_vars_ue->lte_frame_parms.N_RB_UL) {
  case 6:
    memset((void*)prachF,0,4*1536);
    break;
765

766 767 768
  case 15:
    memset((void*)prachF,0,4*3072);
    break;
769

770 771 772
  case 25:
    memset((void*)prachF,0,4*6144);
    break;
773

774 775 776
  case 50:
    memset((void*)prachF,0,4*12288);
    break;
777

778 779 780
  case 75:
    memset((void*)prachF,0,4*19432);
    break;
781

782 783 784 785 786
  case 100:
    memset((void*)prachF,0,4*24576);
    break;
  }

787
  for (offset=0,offset2=0; offset<N_ZC; offset++,offset2+=preamble_shift) {
788 789 790 791

    if (offset2 >= N_ZC)
      offset2 -= N_ZC;

792 793
    Xu_re = (((int32_t)Xu[offset<<1]*amp)>>15);
    Xu_im = (((int32_t)Xu[1+(offset<<1)]*amp)>>15);
794 795 796 797 798 799 800 801 802 803 804
    prachF[k++]= ((Xu_re*ru[offset2<<1]) - (Xu_im*ru[1+(offset2<<1)]))>>15;
    prachF[k++]= ((Xu_im*ru[offset2<<1]) + (Xu_re*ru[1+(offset2<<1)]))>>15;

    if (k==(12*2*phy_vars_ue->lte_frame_parms.ofdm_symbol_size))
      k=0;
  }

  switch (prach_fmt) {
  case 0:
    Ncp = 3168;
    break;
805

806 807 808 809
  case 1:
  case 3:
    Ncp = 21024;
    break;
810

811 812 813
  case 2:
    Ncp = 6240;
    break;
814

815 816 817
  case 4:
    Ncp = 448;
    break;
818

819 820 821 822 823 824 825 826 827 828
  default:
    Ncp = 3168;
    break;
  }

  switch (phy_vars_ue->lte_frame_parms.N_RB_UL) {
  case 6:
    Ncp>>=4;
    prach+=4; // makes prach2 aligned to 128-bit
    break;
829

830 831 832
  case 15:
    Ncp>>=3;
    break;
833

834 835 836
  case 25:
    Ncp>>=2;
    break;
837

838 839 840
  case 50:
    Ncp>>=1;
    break;
841

842 843 844 845 846 847 848
  case 75:
    Ncp=(Ncp*3)>>2;
    break;
  }


  prach2 = prach+(Ncp<<1);
849

850 851 852 853 854 855 856 857
  // do IDFT
  switch (phy_vars_ue->lte_frame_parms.N_RB_UL) {
  case 6:
    if (prach_fmt == 4) {
      fft(prachF,prach2,twiddle_ifft256,rev256,8,4,0);
      //TODO: account for repeated format in fft output
      memcpy((void*)prach,(void*)(prach+512),Ncp<<2);
      prach_len=256+Ncp;
858
    } else {
859 860 861
      ifft1536(prachF,prach2);
      memcpy((void*)prach,(void*)(prach+3072),Ncp<<2);
      prach_len = 1536+Ncp;
862

863
      if (prach_fmt>1) {
864 865
        memcpy((void*)(prach2+3072),(void*)prach2,6144);
        prach_len = 2*1536+Ncp;
866 867
      }
    }
868

869
    break;
870

871 872 873 874 875 876
  case 15:
    if (prach_fmt == 4) {
      fft(prachF,prach2,twiddle_ifft512,rev512,9,4,0);
      //TODO: account for repeated format in fft output
      memcpy((void*)prach,(void*)(prach+1024),Ncp<<2);
      prach_len = 512+Ncp;
877
    } else {
878 879 880
      ifft3072(prachF,prach2);
      memcpy((void*)prach,(void*)(prach+6144),Ncp<<2);
      prach_len = 3072+Ncp;
881

882
      if (prach_fmt>1) {
883 884
        memcpy((void*)(prach2+6144),(void*)prach2,12288);
        prach_len = 2*3072+Ncp;
885 886
      }
    }
887

888
    break;
889

890 891 892 893 894 895 896
  case 25:
  default:
    if (prach_fmt == 4) {
      fft(prachF,prach2,twiddle_ifft1024,rev1024,10,5,0);
      //TODO: account for repeated format in fft output
      memcpy((void*)prach,(void*)(prach+2048),Ncp<<2);
      prach_len = 1024+Ncp;
897
    } else {
898 899
      ifft6144(prachF,prach2);
      /*for (i=0;i<6144*2;i++)
900
      prach2[i]<<=1;*/
901 902
      memcpy((void*)prach,(void*)(prach+12288),Ncp<<2);
      prach_len = 6144+Ncp;
903 904 905 906

      if (prach_fmt>1) {
        memcpy((void*)(prach2+12288),(void*)prach2,24576);
        prach_len = 2*6144+Ncp;
907 908
      }
    }
909

910
    break;
911

912 913 914 915 916 917
  case 50:
    if (prach_fmt == 4) {
      fft(prachF,prach2,twiddle_ifft2048,rev2048,11,5,0);
      //TODO: account for repeated format in fft output
      memcpy((void*)prach,(void*)(prach+4096),Ncp<<2);
      prach_len = 2048+Ncp;
918
    } else {
919 920 921
      ifft12288(prachF,prach2);
      memcpy((void*)prach,(void*)(prach+24576),Ncp<<2);
      prach_len = 12288+Ncp;
922

923
      if (prach_fmt>1) {
924 925
        memcpy((void*)(prach2+24576),(void*)prach2,49152);
        prach_len = 2*12288+Ncp;
926 927
      }
    }
928

929
    break;
930

931 932 933 934 935 936
  case 75:
    if (prach_fmt == 4) {
      ifft3072(prachF,prach2);
      //TODO: account for repeated format in fft output
      memcpy((void*)prach,(void*)(prach+6144),Ncp<<2);
      prach_len = 3072+Ncp;
937
    } else {
938 939 940
      ifft18432(prachF,prach2);
      memcpy((void*)prach,(void*)(prach+36864),Ncp<<2);
      prach_len = 18432+Ncp;
941

942
      if (prach_fmt>1) {
943 944
        memmove(prach2+36834,prach2,73728);
        prach_len = 2*18432+Ncp;
945 946
      }
    }
947

948
    break;
949

950 951 952 953 954 955
  case 100:
    if (prach_fmt == 4) {
      fft(prachF,prach2,twiddle_ifft4096,rev4096,12,6,0);
      //TODO: account for repeated format in fft output
      memcpy((void*)prach,(void*)(prach+8192),Ncp<<2);
      prach_len = 4096+Ncp;
956
    } else {
957 958 959
      ifft24576(prachF,prach2);
      memcpy((void*)prach,(void*)(prach+49152),Ncp<<2);
      prach_len = 24576+Ncp;
960

961
      if (prach_fmt>1) {
962 963
        memcpy((void*)(prach2+49152),(void*)prach2,98304);
        prach_len = 2* 24576+Ncp;
964
      }
965 966
    }

967 968 969 970
    break;
  }

  //LOG_D(PHY,"prach_len=%d\n",prach_len);
971

972 973 974
  if (prach_fmt==4) {
    //TODO: account for repeated format in fft output
    LOG_E(PHY,"prach_fmt4 not fully implemented");
gauthier's avatar
gauthier committed
975
    mac_xface->macphy_exit("prach_fmt4 not fully implemented");
976
    return 0; // not reached
977
  } else {
978
#ifdef BIT8_TX
979

980
    for (i=0; i<prach_len; i++) {
981 982
      ((int8_t*)(&phy_vars_ue->lte_ue_common_vars.txdata[aa][prach_start]))[2*i] = (int8_t)(prach[2*i]);
      ((int8_t*)(&phy_vars_ue->lte_ue_common_vars.txdata[aa][prach_start]))[2*i+1] = (int8_t)(prach[2*i+1]);
983
    }
984

985 986 987 988
#else