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
promise
OpenXG-RAN
Commits
d33269a8
Commit
d33269a8
authored
Jun 04, 2018
by
Hongzhi Wang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
UE adding nr initial_sync
parent
37e09437
Changes
5
Hide 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 @
d33269a8
...
...
@@ -1271,6 +1271,9 @@ set(PHY_SRC_UE
${
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/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_REFSIG/ul_ref_seq_nr.c
${
OPENAIR1_DIR
}
/PHY/TOOLS/file_output.c
...
...
openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
0 → 100644
View file @
d33269a8
/*
* 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 @
d33269a8
/*
* 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 @
d33269a8
...
...
@@ -142,6 +142,8 @@ typedef struct NR_DL_FRAME_PARMS {
uint8_t
nb_antenna_ports_eNB
;
/// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
lte_prefix_type_t
Ncp
;
/// shift of pilot position in one RB
uint8_t
nushift
;
/// SRS configuration from TS 38.331 RRC
SRS_NR
srs_nr
;
...
...
targets/RT/USER/nr-ue.c
View file @
d33269a8
...
...
@@ -354,7 +354,7 @@ static void *UE_thread_synch(void *arg) {
#else
LOG_I
(
PHY
,
"[UE thread Synch] Running Initial Synch (mode %d)
\n
"
,
UE
->
mode
);
#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
;
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