Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wangjie
OpenXG-RAN
Commits
f71c2e08
Commit
f71c2e08
authored
May 14, 2019
by
Raymond Knopp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
initial commit of gNB prach processing
parent
2da6fb8e
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
674 additions
and
0 deletions
+674
-0
openair1/PHY/NR_TRANSPORT/nr_prach.c
openair1/PHY/NR_TRANSPORT/nr_prach.c
+674
-0
No files found.
openair1/PHY/NR_TRANSPORT/nr_prach.c
0 → 100644
View file @
f71c2e08
/*
* 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.1 (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
*/
/*! \file PHY/NR_TRANSPORT/nr_prach.c
* \brief Top-level routines for generating and decoding the PRACH physical channel V15.4 2018-12
* \author R. Knopp
* \date 2019
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
void
rx_nr_prach
(
PHY_VARS_gNB
*
gNB
,
RU_t
*
ru
,
uint16_t
*
max_preamble
,
uint16_t
*
max_preamble_energy
,
uint16_t
*
max_preamble_delay
,
uint16_t
Nf
,
uint8_t
tdd_mapindex
)
{
int
i
;
NR_DL_FRAME_PARMS
*
fp
;
lte_frame_type_t
frame_type
;
uint16_t
rootSequenceIndex
;
uint8_t
prach_ConfigIndex
;
uint8_t
Ncs_config
;
uint8_t
restricted_set
;
uint8_t
n_ra_prb
;
int
subframe
;
int16_t
*
prachF
=
NULL
;
int16_t
**
rxsigF
=
NULL
;
int
nb_rx
;
int16_t
*
prach2
;
uint8_t
preamble_index
;
uint16_t
NCS
,
NCS2
;
uint16_t
preamble_offset
=
0
,
preamble_offset_old
;
int16_t
preamble_shift
=
0
;
uint32_t
preamble_shift2
;
uint16_t
preamble_index0
=
0
,
n_shift_ra
=
0
,
n_shift_ra_bar
;
uint16_t
d_start
=
0
;
uint16_t
numshift
=
0
;
uint16_t
*
prach_root_sequence_map
;
uint8_t
not_found
;
int
k
=
0
;
uint16_t
u
;
int16_t
*
Xu
=
0
;
uint16_t
offset
;
int16_t
Ncp
;
uint16_t
first_nonzero_root_idx
=
0
;
uint8_t
new_dft
=
0
;
uint8_t
aa
;
int32_t
lev
;
int16_t
levdB
;
int
fft_size
,
log2_ifft_size
;
int16_t
prach_ifft_tmp
[
2048
*
2
]
__attribute__
((
aligned
(
32
)));
int32_t
*
prach_ifft
=
(
int32_t
*
)
NULL
;
int32_t
**
prach_ifftp
=
(
int32_t
**
)
NULL
;
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
int
prach_ifft_cnt
=
0
;
#endif
if
(
ru
)
{
fp
=
ru
->
frame_parms
;
nb_rx
=
ru
->
nb_rx
;
}
else
if
(
gNB
)
{
fp
=
&
gNB
->
frame_parms
;
nb_rx
=
fp
->
nb_antennas_rx
;
}
else
AssertFatal
(
1
==
0
,
"rx_prach called without valid RU or gNB descriptor
\n
"
);
frame_type
=
fp
->
frame_type
;
rootSequenceIndex
=
fp
->
prach_config_common
.
rootSequenceIndex
;
prach_ConfigIndex
=
fp
->
prach_config_common
.
prach_ConfigInfo
.
prach_ConfigIndex
;
Ncs_config
=
fp
->
prach_config_common
.
prach_ConfigInfo
.
zeroCorrelationZoneConfig
;
restricted_set
=
fp
->
prach_config_common
.
prach_ConfigInfo
.
highSpeedFlag
;
n_ra_prb
=
get_prach_prb_offset
(
fp
,
prach_ConfigIndex
,
fp
->
prach_config_common
.
prach_ConfigInfo
.
prach_FreqOffset
,
tdd_mapindex
,
Nf
);
int16_t
*
prach
[
nb_rx
];
uint8_t
prach_fmt
=
get_prach_fmt
(
prach_ConfigIndex
,
frame_type
);
uint16_t
N_ZC
=
(
prach_fmt
<
4
)
?
839
:
139
;
if
(
gNB
)
{
prach_ifftp
=
gNB
->
prach_vars
.
prach_ifft
[
0
];
subframe
=
gNB
->
proc
.
subframe_prach
;
prachF
=
gNB
->
prach_vars
.
prachF
;
rxsigF
=
gNB
->
prach_vars
.
rxsigF
[
0
];
if
(
LOG_DEBUGFLAG
(
PRACH
)){
if
(((
ru
->
proc
.
frame_prach
)
&
1023
)
<
20
)
LOG_I
(
PHY
,
"PRACH (gNB) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d , rootSequenceIndex %d
\n
"
,
subframe
,
fp
->
prach_config_common
.
prach_ConfigInfo
.
prach_FreqOffset
,
prach_ConfigIndex
,
rootSequenceIndex
);
}
}
else
{
subframe
=
ru
->
proc
.
subframe_prach
;
rxsigF
=
ru
->
prach_rxsigF
;
if
(
LOG_DEBUGFLAG
(
PRACH
)){
if
(((
ru
->
proc
.
frame_prach
)
&
1023
)
<
20
)
LOG_I
(
PHY
,
"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d
\n
"
,
subframe
,
fp
->
prach_config_common
.
prach_ConfigInfo
.
prach_FreqOffset
,
prach_ConfigIndex
);
}
}
AssertFatal
(
ru
!=
NULL
,
"ru is null
\n
"
);
for
(
aa
=
0
;
aa
<
nb_rx
;
aa
++
)
{
if
(
ru
->
if_south
==
LOCAL_RF
)
{
// set the time-domain signal if we have to use it in this node
// DJP - indexing below in subframe zero takes us off the beginning of the array???
prach
[
aa
]
=
(
int16_t
*
)
&
ru
->
common
.
rxdata
[
aa
][(
subframe
*
fp
->
samples_per_tti
)
-
ru
->
N_TA_offset
];
if
(
LOG_DUMPFLAG
(
PRACH
)){
int32_t
en0
=
signal_energy
((
int32_t
*
)
prach
[
aa
],
fp
->
samples_per_tti
);
int8_t
dbEn0
=
dB_fixed
(
en0
);
int8_t
rach_dBm
=
dbEn0
-
ru
->
rx_total_gain_dB
;
char
buffer
[
80
];
if
(
dbEn0
>
32
&&
prach
[
0
]
!=
NULL
)
{
static
int
counter
=
0
;
sprintf
(
buffer
,
"%s%d"
,
"/tmp/prach_rx"
,
counter
);
LOG_M
(
buffer
,
"prach_rx"
,
prach
[
0
],
fp
->
samples_per_tti
,
1
,
13
);
}
if
(
dB_fixed
(
en0
)
>
32
)
{
sprintf
(
buffer
,
"rach_dBm:%d"
,
rach_dBm
);
if
(
prach
[
0
]
!=
NULL
)
LOG_M
(
"prach_rx"
,
"prach_rx"
,
prach
[
0
],
fp
->
samples_per_tti
,
1
,
1
);
LOG_I
(
PHY
,
"RU %d, br_flag %d ce_level %d frame %d subframe %d per_tti:%d prach:%p (energy %d) TA:%d %s rxdata:%p index:%d
\n
"
,
ru
->
idx
,
br_flag
,
ce_level
,
ru
->
proc
.
frame_prach
,
subframe
,
fp
->
samples_per_tti
,
prach
[
aa
],
dbEn0
,
ru
->
N_TA_offset
,
buffer
,
ru
->
common
.
rxdata
[
aa
],
(
subframe
*
fp
->
samples_per_tti
)
-
ru
->
N_TA_offset
);
}
}
}
}
// First compute physical root sequence
if
(
restricted_set
==
0
)
{
AssertFatal
(
Ncs_config
<=
15
,
"Illegal Ncs_config for unrestricted format %d
\n
"
,
Ncs_config
);
NCS
=
NCS_unrestricted
[
Ncs_config
];
}
else
{
AssertFatal
(
Ncs_config
<=
14
,
"FATAL, Illegal Ncs_config for restricted format %d
\n
"
,
Ncs_config
);
NCS
=
NCS_restricted
[
Ncs_config
];
}
if
(
gNB
)
start_meas
(
&
gNB
->
rx_prach
);
prach_root_sequence_map
=
(
prach_fmt
<
4
)
?
prach_root_sequence_map0_3
:
prach_root_sequence_map4
;
// PDP is oversampled, e.g. 1024 sample instead of 839
// Adapt the NCS (zero-correlation zones) with oversampling factor e.g. 1024/839
NCS2
=
(
N_ZC
==
839
)
?
((
NCS
<<
10
)
/
839
)
:
((
NCS
<<
8
)
/
139
);
if
(
NCS2
==
0
)
NCS2
=
N_ZC
;
switch
(
prach_fmt
)
{
case
0
:
Ncp
=
3168
;
break
;
case
1
:
Ncp
=
21024
;
break
;
case
2
:
Ncp
=
4688
;
break
;
case
3
:
Ncp
=
3168
;
break
;
case
0xa1
:
Ncp
=
288
/
(
1
<<
mu
);
break
;
case
0xa2
:
Ncp
=
576
/
(
1
<<
mu
);
break
;
case
0xa3
:
Ncp
=
864
/
(
1
<<
mu
);
break
;
case
0xb1
:
Ncp
=
216
/
(
1
<<
mu
);
break
;
case
0xb2
:
Ncp
=
360
/
(
1
<<
mu
);
break
;
case
0xb3
:
Ncp
=
504
/
(
1
<<
mu
);
break
;
case
0xb4
:
Ncp
=
936
/
(
1
<<
mu
);
break
;
case
0xc0
:
Ncp
=
1240
/
(
1
<<
mu
);
break
;
case
0xc2
:
Ncp
=
2048
/
(
1
<<
mu
);
break
;
default:
Ncp
=
3168
;
break
;
}
// Note: Assumes PUSCH SCS @ 30 kHz, take values for formats 0-2 and adjust for others below
int
kbar
=
1
;
int
K
=
24
;
if
(
prach_fmt
==
3
)
{
K
=
4
;
kbar
=
10
;
}
else
if
(
prach_fmt
>
3
)
{
// Note: Assumes that PRACH SCS is same as PUSCH SCS
K
=
1
;
kbar
=
2
;
}
if
(((
gNB
!=
NULL
)
&&
(
ru
->
function
!=
NGFI_RAU_IF4p5
))
||
((
gNB
==
NULL
)
&&
(
ru
->
function
==
NGFI_RRU_IF4p5
)))
{
// compute the DFTs of the PRACH temporal resources
// Do forward transform
if
(
LOG_DEBUGFLAG
(
PRACH
))
{
LOG_D
(
PHY
,
"rx_prach: Doing FFT for N_RB_UL %d nb_rx:%d Ncp:%d
\n
"
,
fp
->
N_RB_UL
,
nb_rx
,
Ncp
);
}
for
(
aa
=
0
;
aa
<
nb_rx
;
aa
++
)
{
AssertFatal
(
prach
[
aa
]
!=
NULL
,
"prach[%d] is null
\n
"
,
aa
);
prach2
=
prach
[
aa
]
+
(
Ncp
<<
1
);
// do DFT
switch
(
fp
->
N_RB_UL
)
{
case
6
:
case
15
:
case
25
:
case
50
:
case
75
:
case
100
:
AssertFatal
(
1
==
0
,
"N_RB_UL %d not support for NR PRACH yet
\n
"
,
fp
->
N_RB_UL
);
break
;
case
106
:
case
136
:
if
(
fp
->
threequarter_fs
==
0
)
{
//40 MHz @ 61.44 Ms/s
//50 MHz @ 61.44 Ms/s
if
(
prach_fmt
==
0
||
prach_fmt
==
1
||
prach_fmt
==
2
)
dft24576
(
prach2
,
rxsigF
[
aa
],
1
);
if
(
prach_fmt
==
1
||
prach_fmt
==
2
)
dft24576
(
prach2
+
49152
,
rxsigF
[
aa
]
+
49152
,
1
);
if
(
prach_fmt
==
2
)
{
dft24576
(
prach2
+
(
49152
*
2
),
rxsigF
[
aa
]
+
(
49152
*
2
),
1
);
dft24576
(
prach2
+
(
49152
*
3
),
rxsigF
[
aa
]
+
(
49152
*
3
),
1
);
}
if
(
prach_fmt
==
3
)
for
(
int
i
=
0
;
i
<
4
;
i
++
)
dft6144
(
prach2
+
(
i
*
12288
),
rxsigF
[
aa
]
+
(
i
*
12288
),
1
);
if
(
prach_fmt
>
3
)
{
dft2048
(
prach2
,
rxsigF
[
aa
],
1
);
if
(
prach_fmt
!=
0xc0
)
dft2048
(
prach2
+
4096
,
rxsigF
[
aa
]
+
4096
,
1
);
}
if
(
prach_fmt
==
0xa2
||
prach_fmt
==
0xa3
||
prach_fmt
==
0xb2
||
prach_fmt
==
0xb3
||
prach_fmt
==
0xb4
||
prach_fmt
==
0xc2
)
{
dft2048
(
prach2
+
4096
*
2
,
rxsigF
[
aa
]
+
4096
*
2
,
1
);
dft2048
(
prach2
+
4096
*
3
,
rxsigF
[
aa
]
+
4096
*
3
,
1
);
}
if
(
prach_fmt
==
0xa3
||
prach_fmt
==
0xb3
||
prach_fmt
==
0xc2
)
{
dft2048
(
prach2
+
4096
*
4
,
rxsigF
[
aa
]
+
4096
*
4
,
1
);
dft2048
(
prach2
+
4096
*
5
,
rxsigF
[
aa
]
+
4096
*
5
,
1
);
}
if
(
prach_fmt
==
0xc2
)
for
(
int
i
=
6
;
i
<
11
;
i
++
)
dft2048
(
prach2
+
(
3072
*
i
),
rxsigF
[
aa
]
+
(
3072
*
i
),
1
);
}
else
{
// 40 MHz @ 46.08 Ms/s
AssertFatal
(
fp
->
N_RB_UL
==
106
,
"cannot do 136 PRBs with 3/4 sampling
\n
"
);
if
(
prach_fmt
==
0
||
prach_fmt
==
1
||
prach_fmt
==
2
)
dft18432
(
prach2
,
rxsigF
[
aa
],
1
);
if
(
prach_fmt
==
1
||
prach_fmt
==
2
)
dft18432
(
prach2
+
36864
,
rxsigF
[
aa
]
+
36864
,
1
);
if
(
prach_fmt
==
3
)
dft18432
(
prach2
+
(
2
*
36864
),
rxsigF
[
aa
]
+
(
2
*
36864
),
1
);
if
(
prach_fmt
>
3
)
{
dft1536
(
prach2
,
rxsigF
[
aa
],
1
);
if
(
prach_fmt
!=
0xc0
)
dft1536
(
prach2
+
3072
,
rxsigF
[
aa
]
+
3072
,
1
);
}
if
(
prach_fmt
==
0xa2
||
prach_fmt
==
0xa3
||
prach_fmt
==
0xb2
||
prach_fmt
==
0xb3
||
prach_fmt
==
0xb4
||
prach_fmt
==
0xc2
)
{
dft1536
(
prach2
+
3072
*
2
,
rxsigF
[
aa
]
+
3072
*
2
,
1
);
dft1536
(
prach2
+
3072
*
3
,
rxsigF
[
aa
]
+
3072
*
3
,
1
);
}
if
(
prach_fmt
==
0xa3
||
prach_fmt
==
0xb3
||
prach_fmt
==
c2
)
{
dft1536
(
prach2
+
3072
*
4
,
rxsigF
[
aa
]
+
3072
*
4
,
1
);
dft1536
(
prach2
+
3072
*
5
,
rxsigF
[
aa
]
+
3072
*
5
,
1
);
}
if
(
prach_fmt
==
0xc2
)
for
(
int
i
=
6
;
i
<
11
;
i
++
)
dft1536
(
prach2
+
(
3072
*
i
),
rxsigF
[
aa
]
+
(
3072
*
i
),
1
);
}
break
;
case
216
:
case
246
:
case
272
:
if
(
fp
->
threequarter_fs
==
0
)
{
//80,90,100 MHz @ 61.44 Ms/s
if
(
prach_fmt
==
0
||
prach_fmt
==
1
||
prach_fmt
==
2
)
dft49152
(
prach2
,
rxsigF
[
aa
],
1
);
if
(
prach_fmt
==
1
||
prach_fmt
==
2
)
dft49152
(
prach2
+
98304
,
rxsigF
[
aa
]
+
98304
,
1
);
if
(
prach_fmt
==
3
)
dft49152
(
prach2
+
(
2
*
98304
),
rxsigF
[
aa
]
+
(
2
*
98304
),
1
);
if
(
prach_fmt
>
3
)
{
dft4096
(
prach2
,
rxsigF
[
aa
],
1
);
if
(
prach_fmt
!=
0xc0
)
dft4096
(
prach2
+
8192
,
rxsigF
[
aa
]
+
8192
,
1
);
}
if
(
prach_fmt
==
0xa2
||
prach_fmt
==
0xa3
||
prach_fmt
==
0xb2
||
prach_fmt
==
0xb3
||
prach_fmt
==
0xb4
||
prach_fmt
==
0xc2
)
{
dft4096
(
prach2
+
8192
*
2
,
rxsigF
[
aa
]
+
8192
*
2
,
1
);
dft4096
(
prach2
+
8192
*
3
,
rxsigF
[
aa
]
+
8192
*
3
,
1
);
}
if
(
prach_fmt
==
0xa3
||
prach_fmt
==
0xb3
||
prach_fmt
==
c2
)
{
dft4096
(
prach2
+
8192
*
4
,
rxsigF
[
aa
]
+
8192
*
4
,
1
);
dft4096
(
prach2
+
8192
*
5
,
rxsigF
[
aa
]
+
8192
*
5
,
1
);
}
if
(
prach_fmt
==
0xc2
)
for
(
int
i
=
6
;
i
<
11
;
i
++
)
dft4096
(
prach2
+
(
8192
*
i
),
rxsigF
[
aa
]
+
(
8192
*
i
),
1
);
}
else
{
AssertFatal
(
fp
->
N_RB_UL
==
216
,
"cannot do 136 PRBs with 3/4 sampling
\n
"
);
// 80 MHz @ 46.08 Ms/s
AssertFatal
(
fp
->
N_RB_UL
==
136
,
"cannot do 136 PRBs with 3/4 sampling
\n
"
);
if
(
prach_fmt
==
0
||
prach_fmt
==
1
||
prach_fmt
==
2
)
dft36864
(
prach2
,
rxsigF
[
aa
],
1
);
if
(
prach_fmt
==
1
||
prach_fmt
==
2
)
dft36864
(
prach2
+
73728
,
rxsigF
[
aa
]
+
73728
,
1
);
if
(
prach_fmt
==
3
)
dft36864
(
prach2
+
(
2
*
73728
),
rxsigF
[
aa
]
+
(
2
*
73728
),
1
);
if
(
prach_fmt
>
3
)
{
dft3072
(
prach2
,
rxsigF
[
aa
],
1
);
if
(
prach_fmt
!=
0xc0
)
dft3072
(
prach2
+
6144
,
rxsigF
[
aa
]
+
6144
,
1
);
}
if
(
prach_fmt
==
0xa2
||
prach_fmt
==
0xa3
||
prach_fmt
==
0xb2
||
prach_fmt
==
0xb3
||
prach_fmt
==
0xb4
||
prach_fmt
==
0xc2
)
{
dft3072
(
prach2
+
6144
*
2
,
rxsigF
[
aa
]
+
6144
*
2
,
1
);
dft3072
(
prach2
+
6144
*
3
,
rxsigF
[
aa
]
+
6144
*
3
,
1
);
}
if
(
prach_fmt
==
0xa3
||
prach_fmt
==
0xb3
||
prach_fmt
==
c2
)
{
dft3072
(
prach2
+
6144
*
4
,
rxsigF
[
aa
]
+
6144
*
4
,
1
);
dft3072
(
prach2
+
6144
*
5
,
rxsigF
[
aa
]
+
6144
*
5
,
1
);
}
if
(
prach_fmt
==
0xc2
)
for
(
int
i
=
6
;
i
<
11
;
i
++
)
dft3072
(
prach2
+
(
6144
*
i
),
rxsigF
[
aa
]
+
(
6144
*
i
),
1
);
}
break
;
}
k
=
(
12
*
n_ra_prb
)
-
6
*
fp
->
N_RB_UL
;
if
(
k
<
0
)
{
k
+=
(
fp
->
ofdm_symbol_size
);
}
k
*=
K
;
k
+=
kbar
;
k
*=
2
;
int
dftsize_x2
=
fp
->
ofdm_symbol_size
*
24
;
//LOG_D(PHY,"Shifting prach_rxF from %d to 0\n",k);
if
((
k
+
(
839
*
2
))
>
dftsize_x2
)
{
// PRACH signal is split around DC
memmove
((
void
*
)
&
rxsigF
[
aa
][
dftsize_x2
-
k
],(
void
*
)
&
rxsigF
[
aa
][
0
],(
k
+
(
839
*
2
)
-
dftsize_x2
)
*
2
);
memmove
((
void
*
)
&
rxsigF
[
aa
][
0
],(
void
*
)(
&
rxsigF
[
aa
][
k
]),(
dftsize_x2
-
k
)
*
2
);
}
else
// PRACH signal is not split around DC
memmove
((
void
*
)
&
rxsigF
[
aa
][
0
],(
void
*
)(
&
rxsigF
[
aa
][
k
]),
839
*
4
);
}
}
if
((
eNB
==
NULL
)
&&
(
ru
!=
NULL
)
&&
ru
->
function
==
NGFI_RRU_IF4p5
)
{
/// **** send_IF4 of rxsigF to RAU **** ///
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
if
(
br_flag
==
1
)
send_IF4p5
(
ru
,
ru
->
proc
.
frame_prach
,
ru
->
proc
.
subframe_prach
,
IF4p5_PRACH
+
1
+
ce_level
);
else
#endif
send_IF4p5
(
ru
,
ru
->
proc
.
frame_prach
,
ru
->
proc
.
subframe_prach
,
IF4p5_PRACH
);
return
;
}
else
if
(
eNB
!=
NULL
)
{
if
(
LOG_DEBUGFLAG
(
PRACH
))
{
int
en
=
dB_fixed
(
signal_energy
((
int32_t
*
)
&
rxsigF
[
0
][
0
],
840
));
if
((
en
>
60
)
&&
(
br_flag
==
1
))
LOG_I
(
PHY
,
"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB
\n
"
,
br_flag
,
ce_level
,
n_ra_prb
,
k
,
eNB
->
proc
.
frame_rx
,
eNB
->
proc
.
subframe_rx
,
en
);
}
}
// in case of RAU and prach received rx_thread wakes up prach
// here onwards is for eNodeB_3GPP or NGFI_RAU_IF4p5
preamble_offset_old
=
99
;
uint8_t
update_TA
=
4
;
uint8_t
update_TA2
=
1
;
switch
(
eNB
->
frame_parms
.
N_RB_DL
)
{
case
6
:
update_TA
=
16
;
break
;
case
25
:
update_TA
=
4
;
break
;
case
50
:
update_TA
=
2
;
break
;
case
75
:
update_TA
=
3
;
update_TA2
=
2
;
case
100
:
update_TA
=
1
;
break
;
}
*
max_preamble_energy
=
0
;
for
(
preamble_index
=
0
;
preamble_index
<
64
;
preamble_index
++
)
{
if
(
LOG_DEBUGFLAG
(
PRACH
)){
int
en
=
dB_fixed
(
signal_energy
((
int32_t
*
)
&
rxsigF
[
0
][
0
],
840
));
if
(
en
>
60
)
LOG_I
(
PHY
,
"frame %d, subframe %d : Trying preamble %d (br_flag %d)
\n
"
,
ru
->
proc
.
frame_prach
,
subframe
,
preamble_index
,
br_flag
);
}
if
(
restricted_set
==
0
)
{
// This is the relative offset 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
)));
if
(
preamble_offset
!=
preamble_offset_old
)
{
preamble_offset_old
=
preamble_offset
;
new_dft
=
1
;
// This is the \nu corresponding to the preamble index
preamble_shift
=
0
;
}
else
{
preamble_shift
-=
NCS
;
if
(
preamble_shift
<
0
)
preamble_shift
+=
N_ZC
;
}
}
else
{
// This is the high-speed case
new_dft
=
0
;
// set preamble_offset to initial rootSequenceIndex and look if we need more root sequences for this
// preamble index and find the corresponding cyclic shift
// Check if all shifts for that root have been processed
if
(
preamble_index0
==
numshift
)
{
not_found
=
1
;
new_dft
=
1
;
preamble_index0
-=
numshift
;
(
preamble_offset
==
0
&&
numshift
==
0
)
?
(
preamble_offset
)
:
(
preamble_offset
++
);
while
(
not_found
==
1
)
{
// current root depending on rootSequenceIndex
int
index
=
(
rootSequenceIndex
+
preamble_offset
)
%
N_ZC
;
if
(
prach_fmt
<
4
)
{
// prach_root_sequence_map points to prach_root_sequence_map0_3
DevAssert
(
index
<
sizeof
(
prach_root_sequence_map0_3
)
/
sizeof
(
prach_root_sequence_map0_3
[
0
])
);
}
else
{
// prach_root_sequence_map points to prach_root_sequence_map4
DevAssert
(
index
<
sizeof
(
prach_root_sequence_map4
)
/
sizeof
(
prach_root_sequence_map4
[
0
])
);
}
u
=
prach_root_sequence_map
[
index
];
uint16_t
n_group_ra
=
0
;
if
(
(
du
[
u
]
<
(
N_ZC
/
3
))
&&
(
du
[
u
]
>=
NCS
)
)
{
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
;
}
// This is the number of cyclic shifts for the current root u
numshift
=
(
n_shift_ra
*
n_group_ra
)
+
n_shift_ra_bar
;
// skip to next root and recompute parameters if numshift==0
(
numshift
>
0
)
?
(
not_found
=
0
)
:
(
preamble_offset
++
);
}
}
if
(
n_shift_ra
>
0
)
preamble_shift
=
-
((
d_start
*
(
preamble_index0
/
n_shift_ra
))
+
((
preamble_index0
%
n_shift_ra
)
*
NCS
));
// minus because the channel is h(t -\tau + Cv)
else
preamble_shift
=
0
;
if
(
preamble_shift
<
0
)
preamble_shift
+=
N_ZC
;
preamble_index0
++
;
if
(
preamble_index
==
0
)
first_nonzero_root_idx
=
preamble_offset
;
}
// Compute DFT of RX signal (conjugate input, results in conjugate output) for each new rootSequenceIndex
if
(
LOG_DEBUGFLAG
(
PRACH
))
{
int
en
=
dB_fixed
(
signal_energy
((
int32_t
*
)
&
rxsigF
[
0
][
0
],
840
));
if
(
en
>
60
)
LOG_I
(
PHY
,
"frame %d, subframe %d : preamble index %d: offset %d, preamble shift %d (br_flag %d, en %d)
\n
"
,
ru
->
proc
.
frame_prach
,
subframe
,
preamble_index
,
preamble_offset
,
preamble_shift
,
br_flag
,
en
);
}
log2_ifft_size
=
10
;
fft_size
=
6144
;
if
(
new_dft
==
1
)
{
new_dft
=
0
;
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
if
(
br_flag
==
1
)
{
Xu
=
(
int16_t
*
)
eNB
->
X_u_br
[
ce_level
][
preamble_offset
-
first_nonzero_root_idx
];
prach_ifft
=
prach_ifftp
[
prach_ifft_cnt
++
];
if
(
eNB
->
prach_vars_br
.
repetition_number
[
ce_level
]
==
1
)
memset
(
prach_ifft
,
0
,((
N_ZC
==
839
)
?
2048
:
256
)
*
sizeof
(
int32_t
));
}
else
#endif
{
Xu
=
(
int16_t
*
)
eNB
->
X_u
[
preamble_offset
-
first_nonzero_root_idx
];
prach_ifft
=
prach_ifftp
[
0
];
memset
(
prach_ifft
,
0
,((
N_ZC
==
839
)
?
2048
:
256
)
*
sizeof
(
int32_t
));
}
memset
(
prachF
,
0
,
sizeof
(
int16_t
)
*
2
*
1024
);
if
(
LOG_DUMPFLAG
(
PRACH
))
{
if
(
prach
[
0
]
!=
NULL
)
LOG_M
(
"prach_rx0.m"
,
"prach_rx0"
,
prach
[
0
],
6144
+
792
,
1
,
1
);
LOG_M
(
"prach_rx1.m"
,
"prach_rx1"
,
prach
[
1
],
6144
+
792
,
1
,
1
);
LOG_M
(
"prach_rxF0.m"
,
"prach_rxF0"
,
rxsigF
[
0
],
24576
,
1
,
1
);
LOG_M
(
"prach_rxF1.m"
,
"prach_rxF1"
,
rxsigF
[
1
],
6144
,
1
,
1
);
}
for
(
aa
=
0
;
aa
<
nb_rx
;
aa
++
)
{
// Do componentwise product with Xu* on each antenna
k
=
0
;
for
(
offset
=
0
;
offset
<
(
N_ZC
<<
1
);
offset
+=
2
)
{
prachF
[
offset
]
=
(
int16_t
)(((
int32_t
)
Xu
[
offset
]
*
rxsigF
[
aa
][
k
]
+
(
int32_t
)
Xu
[
offset
+
1
]
*
rxsigF
[
aa
][
k
+
1
])
>>
15
);
prachF
[
offset
+
1
]
=
(
int16_t
)(((
int32_t
)
Xu
[
offset
]
*
rxsigF
[
aa
][
k
+
1
]
-
(
int32_t
)
Xu
[
offset
+
1
]
*
rxsigF
[
aa
][
k
])
>>
15
);
k
+=
2
;
if
(
k
==
(
12
*
2
*
fp
->
ofdm_symbol_size
))
k
=
0
;
}
// Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139)
if
(
N_ZC
==
839
)
{
log2_ifft_size
=
10
;
idft1024
(
prachF
,
prach_ifft_tmp
,
1
);
// compute energy and accumulate over receive antennas and repetitions for BR
for
(
i
=
0
;
i
<
2048
;
i
++
)
prach_ifft
[
i
]
+=
(
prach_ifft_tmp
[
i
<<
1
]
*
prach_ifft_tmp
[
i
<<
1
]
+
prach_ifft_tmp
[
1
+
(
i
<<
1
)]
*
prach_ifft_tmp
[
1
+
(
i
<<
1
)])
>>
10
;
}
else
{
idft256
(
prachF
,
prach_ifft_tmp
,
1
);
log2_ifft_size
=
8
;
// compute energy and accumulate over receive antennas and repetitions for BR
for
(
i
=
0
;
i
<
256
;
i
++
)
prach_ifft
[
i
]
+=
(
prach_ifft_tmp
[
i
<<
1
]
*
prach_ifft_tmp
[(
i
<<
1
)]
+
prach_ifft_tmp
[
1
+
(
i
<<
1
)]
*
prach_ifft_tmp
[
1
+
(
i
<<
1
)])
>>
10
;
}
if
(
LOG_DUMPFLAG
(
PRACH
))
{
if
(
aa
==
0
)
LOG_M
(
"prach_rxF_comp0.m"
,
"prach_rxF_comp0"
,
prachF
,
1024
,
1
,
1
);
if
(
aa
==
1
)
LOG_M
(
"prach_rxF_comp1.m"
,
"prach_rxF_comp1"
,
prachF
,
1024
,
1
,
1
);
}
}
// antennas_rx
}
// new dft
// check energy in nth time shift, for
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
if
((
br_flag
==
0
)
||
(
eNB
->
prach_vars_br
.
repetition_number
[
ce_level
]
==
eNB
->
frame_parms
.
prach_emtc_config_common
.
prach_ConfigInfo
.
prach_numRepetitionPerPreambleAttempt
[
ce_level
]))
#endif
{
if
(
LOG_DEBUGFLAG
(
PRACH
)){
int
en
=
dB_fixed
(
signal_energy
((
int32_t
*
)
&
rxsigF
[
0
][
0
],
840
));
if
(
en
>
60
)
LOG_I
(
PHY
,
"frame %d, subframe %d: Checking for peak in time-domain (br_flag %d, en %d)
\n
"
,
ru
->
proc
.
frame_prach
,
subframe
,
br_flag
,
en
);
}
preamble_shift2
=
((
preamble_shift
==
0
)
?
0
:
((
preamble_shift
<<
log2_ifft_size
)
/
N_ZC
));
for
(
i
=
0
;
i
<
NCS2
;
i
++
)
{
lev
=
(
int32_t
)
prach_ifft
[(
preamble_shift2
+
i
)];
levdB
=
dB_fixed_times10
(
lev
);
if
(
levdB
>*
max_preamble_energy
)
{
*
max_preamble_energy
=
levdB
;
*
max_preamble_delay
=
((
i
*
fft_size
)
>>
log2_ifft_size
)
*
update_TA
/
update_TA2
;
*
max_preamble
=
preamble_index
;
if
(
LOG_DEBUGFLAG
(
PRACH
)){
int
en
=
dB_fixed
(
signal_energy
((
int32_t
*
)
&
rxsigF
[
0
][
0
],
840
));
if
((
en
>
60
)
&&
(
br_flag
==
1
))
LOG_D
(
PHY
,
"frame %d, subframe %d : max_preamble_energy %d, max_preamble_delay %d, max_preamble %d (br_flag %d,ce_level %d, levdB %d, lev %d)
\n
"
,
ru
->
proc
.
frame_prach
,
subframe
,
*
max_preamble_energy
,
*
max_preamble_delay
,
*
max_preamble
,
br_flag
,
ce_level
,
levdB
,
lev
);
}
}
}
}
}
// preamble_index
if
(
LOG_DUMPFLAG
(
PRACH
))
{
int
en
=
dB_fixed
(
signal_energy
((
int32_t
*
)
&
rxsigF
[
0
][
0
],
840
));
if
(
en
>
60
)
{
k
=
(
12
*
n_ra_prb
)
-
6
*
fp
->
N_RB_UL
;
if
(
k
<
0
)
k
+=
fp
->
ofdm_symbol_size
;
k
*=
12
;
k
+=
13
;
k
*=
2
;
if
(
br_flag
==
0
)
{
LOG_M
(
"rxsigF.m"
,
"prach_rxF"
,
&
rxsigF
[
0
][
0
],
12288
,
1
,
1
);
LOG_M
(
"prach_rxF_comp0.m"
,
"prach_rxF_comp0"
,
prachF
,
1024
,
1
,
1
);
LOG_M
(
"Xu.m"
,
"xu"
,
Xu
,
N_ZC
,
1
,
1
);
LOG_M
(
"prach_ifft0.m"
,
"prach_t0"
,
prach_ifft
,
1024
,
1
,
1
);
}
else
{
LOG_E
(
PHY
,
"Dumping prach (br_flag %d), k = %d (n_ra_prb %d)
\n
"
,
br_flag
,
k
,
n_ra_prb
);
LOG_M
(
"rxsigF_br.m"
,
"prach_rxF_br"
,
&
rxsigF
[
0
][
0
],
12288
,
1
,
1
);
LOG_M
(
"prach_rxF_comp0_br.m"
,
"prach_rxF_comp0_br"
,
prachF
,
1024
,
1
,
1
);
LOG_M
(
"Xu_br.m"
,
"xu_br"
,
Xu
,
N_ZC
,
1
,
1
);
LOG_M
(
"prach_ifft0_br.m"
,
"prach_t0_br"
,
prach_ifft
,
1024
,
1
,
1
);
exit
(
-
1
);
}
}
}
/* LOG_DUMPFLAG(PRACH) */
if
(
eNB
)
stop_meas
(
&
eNB
->
rx_prach
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment