Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG UE
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
Michael Black
OpenXG UE
Commits
dc23765d
Commit
dc23765d
authored
Jun 04, 2018
by
Hongzhi Wang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
UE adding nr initial_sync
parent
84a0efe5
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1181 additions
and
1 deletion
+1181
-1
cmake_targets/CMakeLists.txt
cmake_targets/CMakeLists.txt
+3
-0
openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
+451
-0
openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
+724
-0
openair1/PHY/defs_nr_common.h
openair1/PHY/defs_nr_common.h
+2
-0
targets/RT/USER/nr-ue.c
targets/RT/USER/nr-ue.c
+1
-1
No files found.
cmake_targets/CMakeLists.txt
View file @
dc23765d
...
@@ -1271,6 +1271,9 @@ set(PHY_SRC_UE
...
@@ -1271,6 +1271,9 @@ set(PHY_SRC_UE
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/sss_nr.c
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/sss_nr.c
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/dmrs_nr.c
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/dmrs_nr.c
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/nr_pbch.c
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
${
OPENAIR1_DIR
}
/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
${
OPENAIR1_DIR
}
/PHY/NR_REFSIG/ul_ref_seq_nr.c
${
OPENAIR1_DIR
}
/PHY/NR_REFSIG/ul_ref_seq_nr.c
${
OPENAIR1_DIR
}
/PHY/TOOLS/file_output.c
${
OPENAIR1_DIR
}
/PHY/TOOLS/file_output.c
...
...
openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
0 → 100644
View file @
dc23765d
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/LTE_TRANSPORT/initial_sync.c
* \brief Routines for initial UE synchronization procedure (PSS,SSS,PBCH and frame format detection)
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,kaltenberger@eurecom.fr
* \note
* \warning
*/
#include "PHY/types.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/phy_extern_nr_ue.h"
//#include "SCHED/defs.h"
//#include "SCHED/extern.h"
//#include "defs.h"
//#include "extern.h"
#include "common_lib.h"
#include "PHY/NR_REFSIG/pss_nr.h"
#include "PHY/NR_REFSIG/sss_nr.h"
extern
openair0_config_t
openair0_cfg
[];
//#define DEBUG_INITIAL_SYNCH
int
pbch_detection
(
PHY_VARS_NR_UE
*
ue
,
runmode_t
mode
)
{
uint8_t
l
,
pbch_decoded
,
frame_mod4
,
pbch_tx_ant
,
dummy
;
NR_DL_FRAME_PARMS
*
frame_parms
=&
ue
->
frame_parms
;
char
phich_resource
[
6
];
#ifdef DEBUG_INITIAL_SYNCH
LOG_I
(
PHY
,
"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)
\n
"
,
ue
->
Mod_id
,
ue
->
rx_offset
);
#endif
//symbol 1
slot_fep_pbch
(
ue
,
1
,
0
,
ue
->
rx_offset
,
0
,
1
);
//symbol 2
slot_fep_pbch
(
ue
,
2
,
0
,
ue
->
rx_offset
,
0
,
1
);
//symbol 3
slot_fep_pbch
(
ue
,
3
,
0
,
ue
->
rx_offset
,
0
,
1
);
pbch_decoded
=
0
;
//for (frame_mod4=0; frame_mod4<4; frame_mod4++) {
pbch_tx_ant
=
nr_rx_pbch
(
ue
,
&
ue
->
proc
.
proc_rxtx
[
0
],
ue
->
pbch_vars
[
0
],
frame_parms
,
0
,
SISO
,
ue
->
high_speed_flag
,
frame_mod4
);
if
((
pbch_tx_ant
>
0
)
&&
(
pbch_tx_ant
<=
2
))
{
pbch_decoded
=
1
;
// break;
}
//}
if
(
pbch_decoded
)
{
frame_parms
->
nb_antenna_ports_eNB
=
pbch_tx_ant
;
// set initial transmission mode to 1 or 2 depending on number of detected TX antennas
//frame_parms->mode1_flag = (pbch_tx_ant==1);
// openair_daq_vars.dlsch_transmission_mode = (pbch_tx_ant>1) ? 2 : 1;
// flip byte endian on 24-bits for MIB
// dummy = ue->pbch_vars[0]->decoded_output[0];
// ue->pbch_vars[0]->decoded_output[0] = ue->pbch_vars[0]->decoded_output[2];
// ue->pbch_vars[0]->decoded_output[2] = dummy;
// now check for Bandwidth of Cell
dummy
=
(
ue
->
pbch_vars
[
0
]
->
decoded_output
[
2
]
>>
5
)
&
7
;
switch
(
dummy
)
{
case
0
:
frame_parms
->
N_RB_DL
=
6
;
break
;
case
1
:
frame_parms
->
N_RB_DL
=
15
;
break
;
case
2
:
frame_parms
->
N_RB_DL
=
25
;
break
;
case
3
:
frame_parms
->
N_RB_DL
=
50
;
break
;
case
4
:
frame_parms
->
N_RB_DL
=
75
;
break
;
case
5
:
frame_parms
->
N_RB_DL
=
100
;
break
;
default:
LOG_E
(
PHY
,
"[UE%d] Initial sync: PBCH decoding: Unknown N_RB_DL
\n
"
,
ue
->
Mod_id
);
return
-
1
;
break
;
}
for
(
int
i
=
0
;
i
<
RX_NB_TH
;
i
++
)
{
ue
->
proc
.
proc_rxtx
[
i
].
frame_rx
=
(((
ue
->
pbch_vars
[
0
]
->
decoded_output
[
2
]
&
3
)
<<
6
)
+
(
ue
->
pbch_vars
[
0
]
->
decoded_output
[
1
]
>>
2
))
<<
2
;
ue
->
proc
.
proc_rxtx
[
i
].
frame_rx
=
(((
ue
->
pbch_vars
[
0
]
->
decoded_output
[
2
]
&
3
)
<<
6
)
+
(
ue
->
pbch_vars
[
0
]
->
decoded_output
[
1
]
>>
2
))
<<
2
;
#ifndef USER_MODE
// one frame delay
ue
->
proc
.
proc_rxtx
[
i
].
frame_rx
++
;
#endif
ue
->
proc
.
proc_rxtx
[
i
].
frame_tx
=
ue
->
proc
.
proc_rxtx
[
0
].
frame_rx
;
}
#ifdef DEBUG_INITIAL_SYNCH
LOG_I
(
PHY
,
"[UE%d] Initial sync: pbch decoded sucessfully mode1_flag %d, tx_ant %d, frame %d, N_RB_DL %d, phich_duration %d, phich_resource %s!
\n
"
,
ue
->
Mod_id
,
frame_parms
->
mode1_flag
,
pbch_tx_ant
,
ue
->
proc
.
proc_rxtx
[
0
].
frame_rx
,
frame_parms
->
N_RB_DL
,
frame_parms
->
phich_config_common
.
phich_duration
,
phich_resource
);
//frame_parms->phich_config_common.phich_resource);
#endif
return
(
0
);
}
else
{
return
(
-
1
);
}
}
char
phich_string
[
13
][
4
]
=
{
""
,
"1/6"
,
""
,
"1/2"
,
""
,
""
,
"one"
,
""
,
""
,
""
,
""
,
""
,
"two"
};
char
duplex_string
[
2
][
4
]
=
{
"FDD"
,
"TDD"
};
char
prefix_string
[
2
][
9
]
=
{
"NORMAL"
,
"EXTENDED"
};
int
nr_initial_sync
(
PHY_VARS_NR_UE
*
ue
,
runmode_t
mode
)
{
int32_t
sync_pos
,
sync_pos2
,
k_ssb
,
N_ssb_crb
;
int32_t
metric_fdd_ncp
=
0
;
uint8_t
phase_fdd_ncp
;
NR_DL_FRAME_PARMS
*
frame_parms
=
&
ue
->
frame_parms
;
int
ret
=-
1
;
int
aarx
,
rx_power
=
0
;
/*offset parameters to be updated from higher layer */
k_ssb
=
0
;
N_ssb_crb
=
0
;
/*#ifdef OAI_USRP
__m128i *rxdata128;
#endif*/
// LOG_I(PHY,"**************************************************************\n");
// First try FDD normal prefix
frame_parms
->
Ncp
=
NORMAL
;
frame_parms
->
frame_type
=
FDD
;
init_frame_parms
(
frame_parms
,
1
);
/*
write_output("rxdata0.m","rxd0",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
exit(-1);
*/
/* Initial synchronisation
*
* 1 radio frame = 10 ms
* <--------------------------------------------------------------------------->
* -----------------------------------------------------------------------------
* | Received UE data buffer |
* ----------------------------------------------------------------------------
* --------------------------
* <-------------->| pss | pbch | sss | pbch |
* --------------------------
* sync_pos SS/PBCH block
*/
/* process pss search on received buffer */
sync_pos
=
pss_synchro_nr
(
ue
,
NO_RATE_CHANGE
);
/* offset is used by sss serach as it is returned from pss search */
ue
->
rx_offset
=
sync_pos
;
// write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
#ifdef DEBUG_INITIAL_SYNCH
LOG_I
(
PHY
,
"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d
\n
"
,
ue
->
Mod_id
,
sync_pos
,
ue
->
common_vars
.
eNb_id
);
#endif
/* check that SSS/PBCH block is continuous inside the received buffer */
if
(
sync_pos
<
(
LTE_NUMBER_OF_SUBFRAMES_PER_FRAME
*
frame_parms
->
ttis_per_subframe
*
frame_parms
->
samples_per_tti
-
(
NB_SYMBOLS_PBCH
*
frame_parms
->
ofdm_symbol_size
)))
{
#ifdef DEBUG_INITIAL_SYNCH
LOG_I
(
PHY
,
"Calling sss detection (normal CP)
\n
"
);
#endif
rx_sss_nr
(
ue
,
&
metric_fdd_ncp
,
&
phase_fdd_ncp
);
init_frame_parms
(
&
ue
->
frame_parms
,
1
);
//generate_dmrs_pbch(ue->dmrs_pbch_bitmap_nr, frame_parms->Nid_cell);
ret
=
pbch_detection
(
ue
,
mode
);
// write_output("rxdata2.m","rxd2",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
#ifdef DEBUG_INITIAL_SYNCH
LOG_I
(
PHY
,
"FDD Normal prefix: CellId %d metric %d, phase %d, flip %d, pbch %d
\n
"
,
frame_parms
->
Nid_cell
,
metric_fdd_ncp
,
phase_fdd_ncp
,
flip_fdd_ncp
,
ret
);
#endif
}
else
{
#ifdef DEBUG_INITIAL_SYNCH
LOG_I
(
PHY
,
"FDD Normal prefix: SSS error condition: sync_pos %d, sync_pos_slot %d
\n
"
,
sync_pos
,
sync_pos_slot
);
#endif
}
/* Consider this is a false detection if the offset is > 1000 Hz */
if
(
(
abs
(
ue
->
common_vars
.
freq_offset
)
>
150
)
&&
(
ret
==
0
)
)
{
ret
=-
1
;
#if DISABLE_LOG_X
printf
(
"Ignore MIB with high freq offset [%d Hz] estimation
\n
"
,
ue
->
common_vars
.
freq_offset
);
#else
LOG_E
(
HW
,
"Ignore MIB with high freq offset [%d Hz] estimation
\n
"
,
ue
->
common_vars
.
freq_offset
);
#endif
}
if
(
ret
==
0
)
{
// PBCH found so indicate sync to higher layers and configure frame parameters
//#ifdef DEBUG_INITIAL_SYNCH
#if DISABLE_LOG_X
printf
(
"[UE%d] In synch, rx_offset %d samples
\n
"
,
ue
->
Mod_id
,
ue
->
rx_offset
);
#else
LOG_I
(
PHY
,
"[UE%d] In synch, rx_offset %d samples
\n
"
,
ue
->
Mod_id
,
ue
->
rx_offset
);
#endif
//#endif
if
(
ue
->
UE_scan_carrier
==
0
)
{
#if UE_AUTOTEST_TRACE
LOG_I
(
PHY
,
"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d
\n
"
,
ue
->
Mod_id
,
ue
->
proc
.
proc_rxtx
[
0
].
frame_rx
,
ue
->
rx_offset
,
ue
->
common_vars
.
freq_offset
);
#endif
// send sync status to higher layers later when timing offset converge to target timing
#if OAISIM
if
(
ue
->
mac_enabled
==
1
)
{
LOG_I
(
PHY
,
"[UE%d] Sending synch status to higher layers
\n
"
,
ue
->
Mod_id
);
//mac_resynch();
mac_xface
->
dl_phy_sync_success
(
ue
->
Mod_id
,
ue
->
proc
.
proc_rxtx
[
0
].
frame_rx
,
0
,
1
);
//ue->common_vars.eNb_id);
ue
->
UE_mode
[
0
]
=
PRACH
;
}
else
{
ue
->
UE_mode
[
0
]
=
PUSCH
;
}
#endif
generate_pcfich_reg_mapping
(
frame_parms
);
generate_phich_reg_mapping
(
frame_parms
);
ue
->
pbch_vars
[
0
]
->
pdu_errors_conseq
=
0
;
}
#if DISABLE_LOG_X
printf
(
"[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB
\n
"
,
ue
->
Mod_id
,
ue
->
proc
.
proc_rxtx
[
0
].
frame_rx
,
10
*
log10
(
ue
->
measurements
.
rssi
)
-
ue
->
rx_total_gain_dB
,
10
*
log10
(
ue
->
measurements
.
rssi
),
ue
->
rx_total_gain_dB
,
ue
->
measurements
.
n0_power_tot_dBm
,
10
*
log10
(
ue
->
measurements
.
rsrp
[
0
])
-
ue
->
rx_total_gain_dB
,
(
10
*
log10
(
ue
->
measurements
.
rsrq
[
0
])));
printf
(
"[UE %d] Frame %d MIB Information => %s, %s, NidCell %d, N_RB_DL %d, PHICH DURATION %d, PHICH RESOURCE %s, TX_ANT %d
\n
"
,
ue
->
Mod_id
,
ue
->
proc
.
proc_rxtx
[
0
].
frame_rx
,
duplex_string
[
ue
->
frame_parms
.
frame_type
],
prefix_string
[
ue
->
frame_parms
.
Ncp
],
ue
->
frame_parms
.
Nid_cell
,
ue
->
frame_parms
.
N_RB_DL
,
ue
->
frame_parms
.
phich_config_common
.
phich_duration
,
phich_string
[
ue
->
frame_parms
.
phich_config_common
.
phich_resource
],
ue
->
frame_parms
.
nb_antenna_ports_eNB
);
#else
LOG_I
(
PHY
,
"[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB
\n
"
,
ue
->
Mod_id
,
ue
->
proc
.
proc_rxtx
[
0
].
frame_rx
,
10
*
log10
(
ue
->
measurements
.
rssi
)
-
ue
->
rx_total_gain_dB
,
10
*
log10
(
ue
->
measurements
.
rssi
),
ue
->
rx_total_gain_dB
,
ue
->
measurements
.
n0_power_tot_dBm
,
10
*
log10
(
ue
->
measurements
.
rsrp
[
0
])
-
ue
->
rx_total_gain_dB
,
(
10
*
log10
(
ue
->
measurements
.
rsrq
[
0
])));
/* LOG_I(PHY, "[UE %d] Frame %d MIB Information => %s, %s, NidCell %d, N_RB_DL %d, PHICH DURATION %d, PHICH RESOURCE %s, TX_ANT %d\n",
ue->Mod_id,
ue->proc.proc_rxtx[0].frame_rx,
duplex_string[ue->frame_parms.frame_type],
prefix_string[ue->frame_parms.Ncp],
ue->frame_parms.Nid_cell,
ue->frame_parms.N_RB_DL,
ue->frame_parms.phich_config_common.phich_duration,
phich_string[ue->frame_parms.phich_config_common.phich_resource],
ue->frame_parms.nb_antenna_ports_eNB);*/
#endif
#if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)
# if DISABLE_LOG_X
printf
(
"[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)
\n
"
,
ue
->
Mod_id
,
ue
->
proc
.
proc_rxtx
[
0
].
frame_rx
,
openair0_cfg
[
0
].
rx_freq
[
0
]
-
ue
->
common_vars
.
freq_offset
,
ue
->
common_vars
.
freq_offset
);
# else
LOG_I
(
PHY
,
"[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)
\n
"
,
ue
->
Mod_id
,
ue
->
proc
.
proc_rxtx
[
0
].
frame_rx
,
openair0_cfg
[
0
].
rx_freq
[
0
]
-
ue
->
common_vars
.
freq_offset
,
ue
->
common_vars
.
freq_offset
);
# endif
#endif
}
else
{
#ifdef DEBUG_INITIAL_SYNC
LOG_I
(
PHY
,
"[UE%d] Initial sync : PBCH not ok
\n
"
,
ue
->
Mod_id
);
LOG_I
(
PHY
,
"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d
\n
"
,
ue
->
Mod_id
,
sync_pos
,
ue
->
common_vars
.
eNb_id
);
/* LOG_I(PHY,"[UE%d] Initial sync: (metric fdd_ncp %d (%d), metric fdd_ecp %d (%d), metric_tdd_ncp %d (%d), metric_tdd_ecp %d (%d))\n",
ue->Mod_id,
metric_fdd_ncp,Nid_cell_fdd_ncp,
metric_fdd_ecp,Nid_cell_fdd_ecp,
metric_tdd_ncp,Nid_cell_tdd_ncp,
metric_tdd_ecp,Nid_cell_tdd_ecp);*/
LOG_I
(
PHY
,
"[UE%d] Initial sync : Estimated Nid_cell %d, Frame_type %d
\n
"
,
ue
->
Mod_id
,
frame_parms
->
Nid_cell
,
frame_parms
->
frame_type
);
#endif
ue
->
UE_mode
[
0
]
=
NOT_SYNCHED
;
ue
->
pbch_vars
[
0
]
->
pdu_errors_last
=
ue
->
pbch_vars
[
0
]
->
pdu_errors
;
ue
->
pbch_vars
[
0
]
->
pdu_errors
++
;
ue
->
pbch_vars
[
0
]
->
pdu_errors_conseq
++
;
}
// gain control
if
(
ret
!=
0
)
{
//we are not synched, so we cannot use rssi measurement (which is based on channel estimates)
rx_power
=
0
;
// do a measurement on the best guess of the PSS
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
rx_power
+=
signal_energy
(
&
ue
->
common_vars
.
rxdata
[
aarx
][
sync_pos2
],
frame_parms
->
ofdm_symbol_size
+
frame_parms
->
nb_prefix_samples
);
/*
// do a measurement on the full frame
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0],
frame_parms->samples_per_subframe*10);
*/
// we might add a low-pass filter here later
ue
->
measurements
.
rx_power_avg
[
0
]
=
rx_power
/
frame_parms
->
nb_antennas_rx
;
ue
->
measurements
.
rx_power_avg_dB
[
0
]
=
dB_fixed
(
ue
->
measurements
.
rx_power_avg
[
0
]);
#ifdef DEBUG_INITIAL_SYNCH
LOG_I
(
PHY
,
"[UE%d] Initial sync : Estimated power: %d dB
\n
"
,
ue
->
Mod_id
,
ue
->
measurements
.
rx_power_avg_dB
[
0
]
);
#endif
#ifndef OAI_USRP
#ifndef OAI_BLADERF
#ifndef OAI_LMSSDR
#ifndef OAI_ADRV9371_ZC706
phy_adjust_gain
(
ue
,
ue
->
measurements
.
rx_power_avg_dB
[
0
],
0
);
#endif
#endif
#endif
#endif
}
else
{
#ifndef OAI_USRP
#ifndef OAI_BLADERF
#ifndef OAI_LMSSDR
#ifndef OAI_ADRV9371_ZC706
phy_adjust_gain
(
ue
,
dB_fixed
(
ue
->
measurements
.
rssi
),
0
);
#endif
#endif
#endif
#endif
}
// exit_fun("debug exit");
return
ret
;
}
openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
0 → 100644
View file @
dc23765d
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/LTE_TRANSPORT/pbch.c
* \brief Top-level routines for generating and decoding the PBCH/BCH physical/transport channel V8.6 2009-03
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger.fr
* \note
* \warning
*/
#include "PHY/defs_nr_UE.h"
#include "PHY/CODING/coding_extern.h"
#include "PHY/CODING/lte_interleaver_inline.h"
//#include "defs.h"
//#include "extern.h"
#include "PHY/phy_extern_nr_ue.h"
#include "PHY/sse_intrin.h"
#ifdef PHY_ABSTRACTION
#include "SIMULATION/TOOLS/defs.h"
#endif
//#define DEBUG_PBCH 1
//#define DEBUG_PBCH_ENCODING
//#define INTERFERENCE_MITIGATION 1
#ifdef OPENAIR2
//#include "PHY_INTERFACE/defs.h"
#endif
#define PBCH_A 24
uint16_t
nr_pbch_extract
(
int
**
rxdataF
,
int
**
dl_ch_estimates
,
int
**
rxdataF_ext
,
int
**
dl_ch_estimates_ext
,
uint32_t
symbol
,
uint32_t
high_speed_flag
,
NR_DL_FRAME_PARMS
*
frame_parms
)
{
uint16_t
rb
;
uint8_t
i
,
j
,
aarx
,
aatx
;
int
*
dl_ch0
,
*
dl_ch0_ext
,
*
rxF
,
*
rxF_ext
;
int
rx_offset
=
frame_parms
->
ofdm_symbol_size
-
3
*
12
;
int
ch_offset
=
frame_parms
->
N_RB_DL
*
6
-
3
*
12
;
int
nushiftmod4
=
frame_parms
->
nushift
%
4
;
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
{
/*
printf("extract_rbs (nushift %d): symbol_mod=%d, rx_offset=%d, ch_offset=%d\n",frame_parms->nushift,symbol_mod,
(rx_offset + (symbol*(frame_parms->ofdm_symbol_size)))*2,
LTE_CE_OFFSET+ch_offset+(symbol_mod*(frame_parms->ofdm_symbol_size)));
*/
rxF
=
&
rxdataF
[
aarx
][(
rx_offset
+
(
symbol
*
(
frame_parms
->
ofdm_symbol_size
)))];
rxF_ext
=
&
rxdataF_ext
[
aarx
][
symbol
*
(
20
*
12
)];
for
(
rb
=
0
;
rb
<
20
;
rb
++
)
{
// skip DC carrier
if
(
rb
==
10
)
{
rxF
=
&
rxdataF
[
aarx
][(
1
+
(
symbol
*
(
frame_parms
->
ofdm_symbol_size
)))];
}
if
((
symbol
==
1
)
||
(
symbol
==
3
))
{
j
=
0
;
for
(
i
=
0
;
i
<
12
;
i
++
)
{
if
((
i
!=
nushiftmod4
)
&&
(
i
!=
(
nushiftmod4
+
4
))
&&
(
i
!=
(
nushiftmod4
+
8
)))
{
rxF_ext
[
j
++
]
=
rxF
[
i
];
}
}
rxF
+=
12
;
rxF_ext
+=
8
;
}
else
{
//symbol 2
if
((
rb
<
4
)
&&
(
rb
>
15
)){
for
(
i
=
0
;
i
<
12
;
i
++
)
{
if
((
i
!=
nushiftmod4
)
&&
(
i
!=
(
nushiftmod4
+
4
))
&&
(
i
!=
(
nushiftmod4
+
8
)))
{
rxF_ext
[
j
++
]
=
rxF
[
i
];
}
}
}
rxF
+=
12
;
rxF_ext
+=
8
;
}
}
for
(
aatx
=
0
;
aatx
<
4
;
aatx
++
)
{
//frame_parms->nb_antenna_ports_eNB;aatx++) {
if
(
high_speed_flag
==
1
)
dl_ch0
=
&
dl_ch_estimates
[(
aatx
<<
1
)
+
aarx
][
LTE_CE_OFFSET
+
ch_offset
+
(
symbol
*
(
frame_parms
->
ofdm_symbol_size
))];
else
dl_ch0
=
&
dl_ch_estimates
[(
aatx
<<
1
)
+
aarx
][
LTE_CE_OFFSET
+
ch_offset
];
dl_ch0_ext
=
&
dl_ch_estimates_ext
[(
aatx
<<
1
)
+
aarx
][
symbol
*
(
20
*
12
)];
for
(
rb
=
0
;
rb
<
20
;
rb
++
)
{
// skip DC carrier
// if (rb==3) dl_ch0++;
memcpy
(
dl_ch0_ext
,
dl_ch0
,
12
*
sizeof
(
int
));
if
((
symbol
==
1
)
||
(
symbol
==
3
))
{
j
=
0
;
for
(
i
=
0
;
i
<
12
;
i
++
)
{
if
((
i
!=
nushiftmod4
)
&&
(
i
!=
(
nushiftmod4
+
4
))
&&
(
i
!=
(
nushiftmod4
+
8
)))
{
rxF_ext
[
j
++
]
=
rxF
[
i
];
}
}
dl_ch0
+=
12
;
dl_ch0_ext
+=
8
;
}
else
{
//symbol 2
if
((
rb
<
4
)
&&
(
rb
>
15
)){
for
(
i
=
0
;
i
<
12
;
i
++
)
{
if
((
i
!=
nushiftmod4
)
&&
(
i
!=
(
nushiftmod4
+
4
))
&&
(
i
!=
(
nushiftmod4
+
8
)))
{
dl_ch0_ext
[
j
++
]
=
dl_ch0
[
i
];
}
}
}
dl_ch0
+=
12
;
dl_ch0_ext
+=
8
;
}
}
}
//tx antenna loop
}
return
(
0
);
}
//__m128i avg128;
//compute average channel_level on each (TX,RX) antenna pair
int
nr_pbch_channel_level
(
int
**
dl_ch_estimates_ext
,
NR_DL_FRAME_PARMS
*
frame_parms
,
uint32_t
symbol
)
{
int16_t
rb
,
nb_rb
=
6
;
uint8_t
aatx
,
aarx
;
#if defined(__x86_64__) || defined(__i386__)
__m128i
avg128
;
__m128i
*
dl_ch128
;
#elif defined(__arm__)
int32x4_t
avg128
;
int16x8_t
*
dl_ch128
;
#endif
int
avg1
=
0
,
avg2
=
0
;
uint32_t
nsymb
=
(
frame_parms
->
Ncp
==
0
)
?
7
:
6
;
uint32_t
symbol_mod
=
symbol
%
nsymb
;
for
(
aatx
=
0
;
aatx
<
4
;
aatx
++
)
//frame_parms->nb_antenna_ports_eNB;aatx++)
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
{
//clear average level
#if defined(__x86_64__) || defined(__i386__)
avg128
=
_mm_setzero_si128
();
dl_ch128
=
(
__m128i
*
)
&
dl_ch_estimates_ext
[(
aatx
<<
1
)
+
aarx
][
symbol_mod
*
6
*
12
];
#elif defined(__arm__)
avg128
=
vdupq_n_s32
(
0
);
dl_ch128
=
(
int16x8_t
*
)
&
dl_ch_estimates_ext
[(
aatx
<<
1
)
+
aarx
][
symbol_mod
*
6
*
12
];
#endif
for
(
rb
=
0
;
rb
<
nb_rb
;
rb
++
)
{
#if defined(__x86_64__) || defined(__i386__)
avg128
=
_mm_add_epi32
(
avg128
,
_mm_madd_epi16
(
dl_ch128
[
0
],
dl_ch128
[
0
]));
avg128
=
_mm_add_epi32
(
avg128
,
_mm_madd_epi16
(
dl_ch128
[
1
],
dl_ch128
[
1
]));
avg128
=
_mm_add_epi32
(
avg128
,
_mm_madd_epi16
(
dl_ch128
[
2
],
dl_ch128
[
2
]));
#elif defined(__arm__)
// to be filled in
#endif
dl_ch128
+=
3
;
/*
if (rb==0) {
print_shorts("dl_ch128",&dl_ch128[0]);
print_shorts("dl_ch128",&dl_ch128[1]);
print_shorts("dl_ch128",&dl_ch128[2]);
}
*/
}
avg1
=
(((
int
*
)
&
avg128
)[
0
]
+
((
int
*
)
&
avg128
)[
1
]
+
((
int
*
)
&
avg128
)[
2
]
+
((
int
*
)
&
avg128
)[
3
])
/
(
nb_rb
*
12
);
if
(
avg1
>
avg2
)
avg2
=
avg1
;
//msg("Channel level : %d, %d\n",avg1, avg2);
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
return
(
avg2
);
}
#if defined(__x86_64__) || defined(__i386__)
__m128i
mmtmpP0
,
mmtmpP1
,
mmtmpP2
,
mmtmpP3
;
#elif defined(__arm__)
int16x8_t
mmtmpP0
,
mmtmpP1
,
mmtmpP2
,
mmtmpP3
;
#endif
void
nr_pbch_channel_compensation
(
int
**
rxdataF_ext
,
int
**
dl_ch_estimates_ext
,
int
**
rxdataF_comp
,
NR_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
symbol
,
uint8_t
output_shift
)
{
uint16_t
rb
,
nb_rb
=
6
;
uint8_t
aatx
,
aarx
,
symbol_mod
;
#if defined(__x86_64__) || defined(__i386__)
__m128i
*
dl_ch128
,
*
rxdataF128
,
*
rxdataF_comp128
;
#elif defined(__arm__)
#endif
symbol_mod
=
(
symbol
>=
(
7
-
frame_parms
->
Ncp
))
?
symbol
-
(
7
-
frame_parms
->
Ncp
)
:
symbol
;
for
(
aatx
=
0
;
aatx
<
4
;
aatx
++
)
//frame_parms->nb_antenna_ports_eNB;aatx++)
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
{
#if defined(__x86_64__) || defined(__i386__)
dl_ch128
=
(
__m128i
*
)
&
dl_ch_estimates_ext
[(
aatx
<<
1
)
+
aarx
][
symbol_mod
*
6
*
12
];
rxdataF128
=
(
__m128i
*
)
&
rxdataF_ext
[
aarx
][
symbol_mod
*
6
*
12
];
rxdataF_comp128
=
(
__m128i
*
)
&
rxdataF_comp
[(
aatx
<<
1
)
+
aarx
][
symbol_mod
*
6
*
12
];
#elif defined(__arm__)
// to be filled in
#endif
for
(
rb
=
0
;
rb
<
nb_rb
;
rb
++
)
{
//printf("rb %d\n",rb);
#if defined(__x86_64__) || defined(__i386__)
// multiply by conjugated channel
mmtmpP0
=
_mm_madd_epi16
(
dl_ch128
[
0
],
rxdataF128
[
0
]);
// print_ints("re",&mmtmpP0);
// mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
mmtmpP1
=
_mm_shufflelo_epi16
(
dl_ch128
[
0
],
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_shufflehi_epi16
(
mmtmpP1
,
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_sign_epi16
(
mmtmpP1
,
*
(
__m128i
*
)
&
conjugate
[
0
]);
// print_ints("im",&mmtmpP1);
mmtmpP1
=
_mm_madd_epi16
(
mmtmpP1
,
rxdataF128
[
0
]);
// mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpP0
=
_mm_srai_epi32
(
mmtmpP0
,
output_shift
);
// print_ints("re(shift)",&mmtmpP0);
mmtmpP1
=
_mm_srai_epi32
(
mmtmpP1
,
output_shift
);
// print_ints("im(shift)",&mmtmpP1);
mmtmpP2
=
_mm_unpacklo_epi32
(
mmtmpP0
,
mmtmpP1
);
mmtmpP3
=
_mm_unpackhi_epi32
(
mmtmpP0
,
mmtmpP1
);
// print_ints("c0",&mmtmpP2);
// print_ints("c1",&mmtmpP3);
rxdataF_comp128
[
0
]
=
_mm_packs_epi32
(
mmtmpP2
,
mmtmpP3
);
// print_shorts("rx:",rxdataF128);
// print_shorts("ch:",dl_ch128);
// print_shorts("pack:",rxdataF_comp128);
// multiply by conjugated channel
mmtmpP0
=
_mm_madd_epi16
(
dl_ch128
[
1
],
rxdataF128
[
1
]);
// mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
mmtmpP1
=
_mm_shufflelo_epi16
(
dl_ch128
[
1
],
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_shufflehi_epi16
(
mmtmpP1
,
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_sign_epi16
(
mmtmpP1
,
*
(
__m128i
*
)
&
conjugate
[
0
]);
mmtmpP1
=
_mm_madd_epi16
(
mmtmpP1
,
rxdataF128
[
1
]);
// mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpP0
=
_mm_srai_epi32
(
mmtmpP0
,
output_shift
);
mmtmpP1
=
_mm_srai_epi32
(
mmtmpP1
,
output_shift
);
mmtmpP2
=
_mm_unpacklo_epi32
(
mmtmpP0
,
mmtmpP1
);
mmtmpP3
=
_mm_unpackhi_epi32
(
mmtmpP0
,
mmtmpP1
);
rxdataF_comp128
[
1
]
=
_mm_packs_epi32
(
mmtmpP2
,
mmtmpP3
);
// print_shorts("rx:",rxdataF128+1);
// print_shorts("ch:",dl_ch128+1);
// print_shorts("pack:",rxdataF_comp128+1);
if
(
symbol_mod
>
1
)
{
// multiply by conjugated channel
mmtmpP0
=
_mm_madd_epi16
(
dl_ch128
[
2
],
rxdataF128
[
2
]);
// mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
mmtmpP1
=
_mm_shufflelo_epi16
(
dl_ch128
[
2
],
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_shufflehi_epi16
(
mmtmpP1
,
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_sign_epi16
(
mmtmpP1
,
*
(
__m128i
*
)
&
conjugate
[
0
]);
mmtmpP1
=
_mm_madd_epi16
(
mmtmpP1
,
rxdataF128
[
2
]);
// mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpP0
=
_mm_srai_epi32
(
mmtmpP0
,
output_shift
);
mmtmpP1
=
_mm_srai_epi32
(
mmtmpP1
,
output_shift
);
mmtmpP2
=
_mm_unpacklo_epi32
(
mmtmpP0
,
mmtmpP1
);
mmtmpP3
=
_mm_unpackhi_epi32
(
mmtmpP0
,
mmtmpP1
);
rxdataF_comp128
[
2
]
=
_mm_packs_epi32
(
mmtmpP2
,
mmtmpP3
);
// print_shorts("rx:",rxdataF128+2);
// print_shorts("ch:",dl_ch128+2);
// print_shorts("pack:",rxdataF_comp128+2);
dl_ch128
+=
3
;
rxdataF128
+=
3
;
rxdataF_comp128
+=
3
;
}
else
{
dl_ch128
+=
2
;
rxdataF128
+=
2
;
rxdataF_comp128
+=
2
;
}
#elif defined(__arm__)
// to be filled in
#endif
}
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
void
nr_pbch_detection_mrc
(
NR_DL_FRAME_PARMS
*
frame_parms
,
int
**
rxdataF_comp
,
uint8_t
symbol
)
{
uint8_t
aatx
,
symbol_mod
;
int
i
,
nb_rb
=
6
;
#if defined(__x86_64__) || defined(__i386__)
__m128i
*
rxdataF_comp128_0
,
*
rxdataF_comp128_1
;
#elif defined(__arm__)
int16x8_t
*
rxdataF_comp128_0
,
*
rxdataF_comp128_1
;
#endif
symbol_mod
=
(
symbol
>=
(
7
-
frame_parms
->
Ncp
))
?
symbol
-
(
7
-
frame_parms
->
Ncp
)
:
symbol
;
if
(
frame_parms
->
nb_antennas_rx
>
1
)
{
for
(
aatx
=
0
;
aatx
<
4
;
aatx
++
)
{
//frame_parms->nb_antenna_ports_eNB;aatx++) {
#if defined(__x86_64__) || defined(__i386__)
rxdataF_comp128_0
=
(
__m128i
*
)
&
rxdataF_comp
[(
aatx
<<
1
)][
symbol_mod
*
6
*
12
];
rxdataF_comp128_1
=
(
__m128i
*
)
&
rxdataF_comp
[(
aatx
<<
1
)
+
1
][
symbol_mod
*
6
*
12
];
#elif defined(__arm__)
rxdataF_comp128_0
=
(
int16x8_t
*
)
&
rxdataF_comp
[(
aatx
<<
1
)][
symbol_mod
*
6
*
12
];
rxdataF_comp128_1
=
(
int16x8_t
*
)
&
rxdataF_comp
[(
aatx
<<
1
)
+
1
][
symbol_mod
*
6
*
12
];
#endif
// MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation)
for
(
i
=
0
;
i
<
nb_rb
*
3
;
i
++
)
{
#if defined(__x86_64__) || defined(__i386__)
rxdataF_comp128_0
[
i
]
=
_mm_adds_epi16
(
_mm_srai_epi16
(
rxdataF_comp128_0
[
i
],
1
),
_mm_srai_epi16
(
rxdataF_comp128_1
[
i
],
1
));
#elif defined(__arm__)
rxdataF_comp128_0
[
i
]
=
vhaddq_s16
(
rxdataF_comp128_0
[
i
],
rxdataF_comp128_1
[
i
]);
#endif
}
}
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
void
nr_pbch_scrambling
(
NR_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
*
pbch_e
,
uint32_t
length
)
{
int
i
;
uint8_t
reset
;
uint32_t
x1
,
x2
,
s
=
0
;
reset
=
1
;
// x1 is set in lte_gold_generic
x2
=
frame_parms
->
Nid_cell
;
//this is c_init in 36.211 Sec 6.6.1
// msg("pbch_scrambling: Nid_cell = %d\n",x2);
for
(
i
=
0
;
i
<
length
;
i
++
)
{
if
((
i
&
0x1f
)
==
0
)
{
s
=
lte_gold_generic
(
&
x1
,
&
x2
,
reset
);
// printf("lte_gold[%d]=%x\n",i,s);
reset
=
0
;
}
pbch_e
[
i
]
=
(
pbch_e
[
i
]
&
1
)
^
((
s
>>
(
i
&
0x1f
))
&
1
);
}
}
void
nr_pbch_unscrambling
(
NR_DL_FRAME_PARMS
*
frame_parms
,
int8_t
*
llr
,
uint32_t
length
,
uint8_t
frame_mod4
)
{
int
i
;
uint8_t
reset
;
uint32_t
x1
,
x2
,
s
=
0
;
reset
=
1
;
// x1 is set in first call to lte_gold_generic
x2
=
frame_parms
->
Nid_cell
;
//this is c_init in 36.211 Sec 6.6.1
// msg("pbch_unscrambling: Nid_cell = %d\n",x2);
for
(
i
=
0
;
i
<
length
;
i
++
)
{
if
(
i
%
32
==
0
)
{
s
=
lte_gold_generic
(
&
x1
,
&
x2
,
reset
);
// printf("lte_gold[%d]=%x\n",i,s);
reset
=
0
;
}
// take the quarter of the PBCH that corresponds to this frame
if
((
i
>=
(
frame_mod4
*
(
length
>>
2
)))
&&
(
i
<
((
1
+
frame_mod4
)
*
(
length
>>
2
))))
{
// if (((s>>(i%32))&1)==1)
if
(((
s
>>
(
i
%
32
))
&
1
)
==
0
)
llr
[
i
]
=
-
llr
[
i
];
}
}
}
void
nr_pbch_alamouti
(
NR_DL_FRAME_PARMS
*
frame_parms
,
int
**
rxdataF_comp
,
uint8_t
symbol
)
{
int16_t
*
rxF0
,
*
rxF1
;
// __m128i *ch_mag0,*ch_mag1,*ch_mag0b,*ch_mag1b;
uint8_t
rb
,
re
,
symbol_mod
;
int
jj
;
// printf("Doing alamouti\n");
symbol_mod
=
(
symbol
>=
(
7
-
frame_parms
->
Ncp
))
?
symbol
-
(
7
-
frame_parms
->
Ncp
)
:
symbol
;
jj
=
(
symbol_mod
*
6
*
12
);
rxF0
=
(
int16_t
*
)
&
rxdataF_comp
[
0
][
jj
];
//tx antenna 0 h0*y
rxF1
=
(
int16_t
*
)
&
rxdataF_comp
[
2
][
jj
];
//tx antenna 1 h1*y
for
(
rb
=
0
;
rb
<
6
;
rb
++
)
{
for
(
re
=
0
;
re
<
12
;
re
+=
2
)
{
// Alamouti RX combining
rxF0
[
0
]
=
rxF0
[
0
]
+
rxF1
[
2
];
rxF0
[
1
]
=
rxF0
[
1
]
-
rxF1
[
3
];
rxF0
[
2
]
=
rxF0
[
2
]
-
rxF1
[
0
];
rxF0
[
3
]
=
rxF0
[
3
]
+
rxF1
[
1
];
rxF0
+=
4
;
rxF1
+=
4
;
}
}
}
void
nr_pbch_quantize
(
int8_t
*
pbch_llr8
,
int16_t
*
pbch_llr
,
uint16_t
len
)
{
uint16_t
i
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
pbch_llr
[
i
]
>
7
)
pbch_llr8
[
i
]
=
7
;
else
if
(
pbch_llr
[
i
]
<-
8
)
pbch_llr8
[
i
]
=-
8
;
else
pbch_llr8
[
i
]
=
(
char
)(
pbch_llr
[
i
]);
}
}
static
unsigned
char
dummy_w_rx
[
3
*
3
*
(
16
+
PBCH_A
)];
static
int8_t
pbch_w_rx
[
3
*
3
*
(
16
+
PBCH_A
)],
pbch_d_rx
[
96
+
(
3
*
(
16
+
PBCH_A
))];
uint16_t
nr_rx_pbch
(
PHY_VARS_NR_UE
*
ue
,
UE_nr_rxtx_proc_t
*
proc
,
NR_UE_PBCH
*
nr_ue_pbch_vars
,
NR_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
eNB_id
,
MIMO_mode_t
mimo_mode
,
uint32_t
high_speed_flag
,
uint8_t
frame_mod4
)
{
NR_UE_COMMON
*
nr_ue_common_vars
=
&
ue
->
common_vars
;
uint8_t
log2_maxh
;
//,aatx,aarx;
int
max_h
=
0
;
int
symbol
,
i
;
uint32_t
nsymb
=
(
frame_parms
->
Ncp
==
0
)
?
14
:
12
;
uint16_t
pbch_E
;
uint8_t
pbch_a
[
8
];
uint8_t
RCC
;
int8_t
*
pbch_e_rx
;
uint8_t
*
decoded_output
=
nr_ue_pbch_vars
->
decoded_output
;
uint16_t
crc
;
int
subframe_rx
=
proc
->
subframe_rx
;
// pbch_D = 16+PBCH_A;
pbch_E
=
(
frame_parms
->
Ncp
==
0
)
?
1920
:
1728
;
//RE/RB * #RB * bits/RB (QPSK)
pbch_e_rx
=
&
nr_ue_pbch_vars
->
llr
[
frame_mod4
*
(
pbch_E
>>
2
)];
#ifdef DEBUG_PBCH
msg
(
"[PBCH] starting symbol loop (Ncp %d, frame_mod4 %d,mimo_mode %d
\n
"
,
frame_parms
->
Ncp
,
frame_mod4
,
mimo_mode
);
#endif
// clear LLR buffer
memset
(
nr_ue_pbch_vars
->
llr
,
0
,
pbch_E
);
for
(
symbol
=
1
;
symbol
<
4
;
symbol
++
)
{
#ifdef DEBUG_PBCH
msg
(
"[PBCH] starting extract
\n
"
);
#endif
nr_pbch_extract
(
nr_ue_common_vars
->
common_vars_rx_data_per_thread
[
ue
->
current_thread_id
[
subframe_rx
]].
rxdataF
,
nr_ue_common_vars
->
common_vars_rx_data_per_thread
[
ue
->
current_thread_id
[
subframe_rx
]].
dl_ch_estimates
[
eNB_id
],
nr_ue_pbch_vars
->
rxdataF_ext
,
nr_ue_pbch_vars
->
dl_ch_estimates_ext
,
symbol
,
high_speed_flag
,
frame_parms
);
#ifdef DEBUG_PBCH
msg
(
"[PHY] PBCH Symbol %d
\n
"
,
symbol
);
msg
(
"[PHY] PBCH starting channel_level
\n
"
);
#endif
max_h
=
nr_pbch_channel_level
(
nr_ue_pbch_vars
->
dl_ch_estimates_ext
,
frame_parms
,
symbol
);
log2_maxh
=
3
+
(
log2_approx
(
max_h
)
/
2
);
#ifdef DEBUG_PBCH
msg
(
"[PHY] PBCH log2_maxh = %d (%d)
\n
"
,
log2_maxh
,
max_h
);
#endif
nr_pbch_channel_compensation
(
nr_ue_pbch_vars
->
rxdataF_ext
,
nr_ue_pbch_vars
->
dl_ch_estimates_ext
,
nr_ue_pbch_vars
->
rxdataF_comp
,
frame_parms
,
symbol
,
log2_maxh
);
// log2_maxh+I0_shift
/*if (frame_parms->nb_antennas_rx > 1)
pbch_detection_mrc(frame_parms,
nr_ue_pbch_vars->rxdataF_comp,
symbol);*/
if
(
mimo_mode
==
ALAMOUTI
)
{
nr_pbch_alamouti
(
frame_parms
,
nr_ue_pbch_vars
->
rxdataF_comp
,
symbol
);
// msg("[PBCH][RX] Alamouti receiver not yet implemented!\n");
// return(-1);
}
else
if
(
mimo_mode
!=
SISO
)
{
msg
(
"[PBCH][RX] Unsupported MIMO mode
\n
"
);
return
(
-
1
);
}
if
(
symbol
>
(
nsymb
>>
1
)
+
1
)
{
nr_pbch_quantize
(
pbch_e_rx
,
(
short
*
)
&
(
nr_ue_pbch_vars
->
rxdataF_comp
[
0
][(
symbol
%
(
nsymb
>>
1
))
*
72
]),
144
);
pbch_e_rx
+=
144
;
}
else
{
nr_pbch_quantize
(
pbch_e_rx
,
(
short
*
)
&
(
nr_ue_pbch_vars
->
rxdataF_comp
[
0
][(
symbol
%
(
nsymb
>>
1
))
*
72
]),
96
);
pbch_e_rx
+=
96
;
}
}
pbch_e_rx
=
nr_ue_pbch_vars
->
llr
;
//un-scrambling
#ifdef DEBUG_PBCH
msg
(
"[PBCH] doing unscrambling
\n
"
);
#endif
nr_pbch_unscrambling
(
frame_parms
,
pbch_e_rx
,
pbch_E
,
frame_mod4
);
//un-rate matching
#ifdef DEBUG_PBCH
msg
(
"[PBCH] doing un-rate-matching
\n
"
);
#endif
memset
(
dummy_w_rx
,
0
,
3
*
3
*
(
16
+
PBCH_A
));
RCC
=
generate_dummy_w_cc
(
16
+
PBCH_A
,
dummy_w_rx
);
lte_rate_matching_cc_rx
(
RCC
,
pbch_E
,
pbch_w_rx
,
dummy_w_rx
,
pbch_e_rx
);
sub_block_deinterleaving_cc
((
unsigned
int
)(
PBCH_A
+
16
),
&
pbch_d_rx
[
96
],
&
pbch_w_rx
[
0
]);
memset
(
pbch_a
,
0
,((
16
+
PBCH_A
)
>>
3
));
phy_viterbi_lte_sse2
(
pbch_d_rx
+
96
,
pbch_a
,
16
+
PBCH_A
);
// Fix byte endian of PBCH (bit 23 goes in first)
for
(
i
=
0
;
i
<
(
PBCH_A
>>
3
);
i
++
)
decoded_output
[(
PBCH_A
>>
3
)
-
i
-
1
]
=
pbch_a
[
i
];
#ifdef DEBUG_PBCH
for
(
i
=
0
;
i
<
(
PBCH_A
>>
3
);
i
++
)
msg
(
"[PBCH] pbch_a[%d] = %x
\n
"
,
i
,
decoded_output
[
i
]);
#endif //DEBUG_PBCH
#ifdef DEBUG_PBCH
msg
(
"PBCH CRC %x : %x
\n
"
,
crc16
(
pbch_a
,
PBCH_A
),
((
uint16_t
)
pbch_a
[
PBCH_A
>>
3
]
<<
8
)
+
pbch_a
[(
PBCH_A
>>
3
)
+
1
]);
#endif
crc
=
(
crc16
(
pbch_a
,
PBCH_A
)
>>
16
)
^
(((
uint16_t
)
pbch_a
[
PBCH_A
>>
3
]
<<
8
)
+
pbch_a
[(
PBCH_A
>>
3
)
+
1
]);
if
(
crc
==
0x0000
)
return
(
1
);
else
if
(
crc
==
0xffff
)
return
(
2
);
else
if
(
crc
==
0x5555
)
return
(
4
);
else
return
(
-
1
);
}
#ifdef PHY_ABSTRACTION
uint16_t
rx_pbch_emul
(
PHY_VARS_UE
*
phy_vars_ue
,
uint8_t
eNB_id
,
uint8_t
pbch_phase
)
{
double
bler
=
0
.
0
;
//, x=0.0;
double
sinr
=
0
.
0
;
uint16_t
nb_rb
=
phy_vars_ue
->
frame_parms
.
N_RB_DL
;
int16_t
f
;
uint8_t
CC_id
=
phy_vars_ue
->
CC_id
;
int
frame_rx
=
phy_vars_ue
->
proc
.
proc_rxtx
[
0
].
frame_rx
;
// compute effective sinr
// TODO: adapt this to varible bandwidth
for
(
f
=
(
nb_rb
*
6
-
3
*
12
);
f
<
(
nb_rb
*
6
+
3
*
12
);
f
++
)
{
if
(
f
!=
0
)
//skip DC
sinr
+=
pow
(
10
,
0
.
1
*
(
phy_vars_ue
->
sinr_dB
[
f
]));
}
sinr
=
10
*
log10
(
sinr
/
(
6
*
12
));
bler
=
pbch_bler
(
sinr
);
LOG_D
(
PHY
,
"EMUL UE rx_pbch_emul: eNB_id %d, pbch_phase %d, sinr %f dB, bler %f
\n
"
,
eNB_id
,
pbch_phase
,
sinr
,
bler
);
if
(
pbch_phase
==
(
frame_rx
%
4
))
{
if
(
uniformrandom
()
>=
bler
)
{
memcpy
(
phy_vars_ue
->
pbch_vars
[
eNB_id
]
->
decoded_output
,
PHY_vars_eNB_g
[
eNB_id
][
CC_id
]
->
pbch_pdu
,
PBCH_PDU_SIZE
);
return
(
PHY_vars_eNB_g
[
eNB_id
][
CC_id
]
->
frame_parms
.
nb_antenna_ports_eNB
);
}
else
return
(
-
1
);
}
else
return
(
-
1
);
}
#endif
openair1/PHY/defs_nr_common.h
View file @
dc23765d
...
@@ -142,6 +142,8 @@ typedef struct NR_DL_FRAME_PARMS {
...
@@ -142,6 +142,8 @@ typedef struct NR_DL_FRAME_PARMS {
uint8_t
nb_antenna_ports_eNB
;
uint8_t
nb_antenna_ports_eNB
;
/// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
/// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
lte_prefix_type_t
Ncp
;
lte_prefix_type_t
Ncp
;
/// shift of pilot position in one RB
uint8_t
nushift
;
/// SRS configuration from TS 38.331 RRC
/// SRS configuration from TS 38.331 RRC
SRS_NR
srs_nr
;
SRS_NR
srs_nr
;
...
...
targets/RT/USER/nr-ue.c
View file @
dc23765d
...
@@ -354,7 +354,7 @@ static void *UE_thread_synch(void *arg) {
...
@@ -354,7 +354,7 @@ static void *UE_thread_synch(void *arg) {
#else
#else
LOG_I
(
PHY
,
"[UE thread Synch] Running Initial Synch (mode %d)
\n
"
,
UE
->
mode
);
LOG_I
(
PHY
,
"[UE thread Synch] Running Initial Synch (mode %d)
\n
"
,
UE
->
mode
);
#endif
#endif
if
(
initial_sync
(
UE
,
UE
->
mode
)
==
0
)
{
if
(
nr_
initial_sync
(
UE
,
UE
->
mode
)
==
0
)
{
hw_slot_offset
=
(
UE
->
rx_offset
<<
1
)
/
UE
->
frame_parms
.
samples_per_tti
;
hw_slot_offset
=
(
UE
->
rx_offset
<<
1
)
/
UE
->
frame_parms
.
samples_per_tti
;
printf
(
"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d
\n
"
,
printf
(
"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d
\n
"
,
...
...
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