mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Compare commits
1 Commits
ldpc_decod
...
NR_SL_PSBC
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5004132dd |
@@ -689,6 +689,7 @@ target_link_libraries(SCHED_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
|
||||
set(SCHED_SRC_NR_UE
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue_sl.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/fapi_nr_ue_l1.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/phy_frame_config_nr_ue.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/harq_nr.c
|
||||
@@ -1062,6 +1063,8 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
|
||||
@@ -2225,6 +2228,24 @@ target_link_libraries(nr_pbchsim PRIVATE
|
||||
)
|
||||
target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
add_executable(nr_psbchsim
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/psbchsim.c
|
||||
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
|
||||
${OPENAIR_DIR}/common/utils/nr/nr_common.c
|
||||
${OPENAIR_DIR}/executables/softmodem-common.c
|
||||
${OPENAIR2_DIR}/RRC/NAS/nas_config.c
|
||||
${NR_UE_RRC_DIR}/rrc_nsa.c
|
||||
${NFAPI_USER_DIR}/nfapi.c
|
||||
${NFAPI_USER_DIR}/gnb_ind_vars.c
|
||||
${PHY_INTERFACE_DIR}/queue_t.c
|
||||
${T_SOURCE}
|
||||
${SHLIB_LOADER_SOURCES}
|
||||
)
|
||||
target_link_libraries(nr_psbchsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl shlib_loader
|
||||
)
|
||||
target_link_libraries(nr_psbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
#PUCCH ---> Prashanth
|
||||
add_executable(nr_pucchsim
|
||||
|
||||
@@ -315,7 +315,7 @@ function main() {
|
||||
-P | --phy_simulators)
|
||||
SIMUS_PHY=1
|
||||
# TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim
|
||||
TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim"
|
||||
TARGET_LIST="$TARGET_LIST dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim nr_psbchsim"
|
||||
echo_info "Will compile dlsim, ulsim, ..."
|
||||
shift;;
|
||||
-s | --check)
|
||||
|
||||
@@ -304,6 +304,7 @@ void nr_polar_rm_interleaving_cb(void *in, void *out, uint16_t E)
|
||||
static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void *in,void *out) __attribute__((always_inline));
|
||||
|
||||
static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void *in,void *out) {
|
||||
int i = 0;
|
||||
|
||||
// handle rate matching with a single 128 bit word using bit shuffling
|
||||
// can be done with SIMD intrisics if needed
|
||||
@@ -343,15 +344,20 @@ static inline void polar_rate_matching(const t_nrPolar_params *polarParams,void
|
||||
}
|
||||
// These are based on LUTs for byte and short word groups
|
||||
else if (polarParams->groupsize == 8)
|
||||
for (int i=0; i<polarParams->encoderLength>>3; i++) ((uint8_t *)out)[i] = ((uint8_t *)in)[polarParams->rm_tab[i]];
|
||||
for (i=0; i<polarParams->encoderLength>>3; i++) ((uint8_t *)out)[i] = ((uint8_t *)in)[polarParams->rm_tab[i]];
|
||||
else // groupsize==16
|
||||
for (int i=0; i<polarParams->encoderLength>>4; i++) {
|
||||
for (i=0; i<polarParams->encoderLength>>4; i++) {
|
||||
((uint16_t *)out)[i] = ((uint16_t *)in)[polarParams->rm_tab[i]];
|
||||
}
|
||||
|
||||
if (polarParams->i_bil == 1) {
|
||||
nr_polar_rm_interleaving_cb(out, out, polarParams->encoderLength);
|
||||
}
|
||||
// handle remaining bits which do not fill a full group
|
||||
for(i=i*polarParams->groupsize; i<polarParams->encoderLength; i++) {
|
||||
uint8_t pi = polarParams->rate_matching_pattern[i];
|
||||
((uint8_t *)out)[i>>3] |= ( ((((uint8_t *)in)[pi >> 3] >> (pi & 7)) & 1) << (i&7));
|
||||
}
|
||||
}
|
||||
|
||||
void build_polar_tables(t_nrPolar_params *polarParams) {
|
||||
@@ -448,8 +454,8 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
|
||||
}
|
||||
#ifdef DEBUG_POLAR_ENCODER
|
||||
groupcnt++;
|
||||
#endif
|
||||
if ((ccnt+1)<mingroupsize) mingroupsize=ccnt+1;
|
||||
#endif
|
||||
//if ((ccnt+1)<mingroupsize) mingroupsize=ccnt+1;
|
||||
#ifdef DEBUG_POLAR_ENCODER
|
||||
printf("group %d (size %d): (%d:%d) => (%d:%d)\n",groupcnt,ccnt+1,
|
||||
firstingroup_in,firstingroup_in+ccnt,
|
||||
@@ -477,8 +483,7 @@ void build_polar_tables(t_nrPolar_params *polarParams) {
|
||||
break;
|
||||
}
|
||||
|
||||
polarParams->rm_tab = (int *)malloc(sizeof(int) * (polarParams->encoderLength >> shift));
|
||||
|
||||
polarParams->rm_tab=(int *)malloc(sizeof(int)*((polarParams->encoderLength+mingroupsize-1)/mingroupsize));
|
||||
// rerun again to create groups
|
||||
int tcnt = 0;
|
||||
for (int outpos = 0; outpos < polarParams->encoderLength; outpos += mingroupsize, tcnt++)
|
||||
@@ -707,7 +712,7 @@ void polar_encoder_fast(uint64_t *A,
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
memset((void*)out,0,polarParams->encoderLength>>3);
|
||||
memset((void*)out,0,(polarParams->encoderLength + 7)>>3);
|
||||
polar_rate_matching(polarParams,(void *)D, out);
|
||||
|
||||
#ifdef POLAR_CODING_DEBUG
|
||||
|
||||
57
openair1/PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
Normal file
57
openair1/PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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/CODING/nrPolar_tools/nr_polar_psbch_defs.h
|
||||
\brief Polar definitions required for Sidelink PSBCH
|
||||
\author
|
||||
\date
|
||||
\version
|
||||
\company: Fraunhofer
|
||||
\email:
|
||||
\note
|
||||
\warning
|
||||
*/
|
||||
|
||||
#ifndef __NR_POLAR_PSBCH_DEFS__H__
|
||||
#define __NR_POLAR_PSBCH_DEFS__H__
|
||||
|
||||
//PSBCH related polar parameters.
|
||||
|
||||
//PSBCH symbols sent in 11RBS, 9 symbols. 11*9*(12-3(for DMRS))*2bits = 1782 bits
|
||||
#define SL_NR_POLAR_PSBCH_E_NORMAL_CP 1782
|
||||
//PSBCH symbols sent in 11RBS, 7 symbols. 11*7*(12-3(for DMRS))*2bits = 1386 bits
|
||||
#define SL_NR_POLAR_PSBCH_E_EXT_CP 1386
|
||||
// SL_NR_POLAR_PSBCH_E_NORMAL_CP/32
|
||||
#define SL_NR_POLAR_PSBCH_E_DWORD 56
|
||||
|
||||
#define SL_NR_POLAR_PSBCH_MESSAGE_TYPE (NR_POLAR_UCI_PUCCH_MESSAGE_TYPE + 1)
|
||||
#define SL_NR_POLAR_PSBCH_PAYLOAD_BITS 32
|
||||
#define SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL 0
|
||||
#define SL_NR_POLAR_PSBCH_N_MAX 9
|
||||
#define SL_NR_POLAR_PSBCH_I_IL 1
|
||||
#define SL_NR_POLAR_PSBCH_I_SEG 0
|
||||
#define SL_NR_POLAR_PSBCH_N_PC 0
|
||||
#define SL_NR_POLAR_PSBCH_N_PC_WM 0
|
||||
#define SL_NR_POLAR_PSBCH_I_BIL 0
|
||||
#define SL_NR_POLAR_PSBCH_CRC_PARITY_BITS 24
|
||||
#define SL_NR_POLAR_PSBCH_CRC_ERROR_CORRECTION_BITS 3
|
||||
|
||||
#endif
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dci.h"
|
||||
#include "nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
|
||||
#define PolarKey ((messageType<<24)|(messageLength<<8)|aggregation_level)
|
||||
static t_nrPolar_params * PolarList=NULL;
|
||||
@@ -194,7 +195,19 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
|
||||
newPolarInitNode->payloadBits = messageLength;
|
||||
newPolarInitNode->crcCorrectionBits = NR_POLAR_PUCCH_CRC_ERROR_CORRECTION_BITS;
|
||||
//LOG_D(PHY,"New polar node, encoderLength %d, aggregation_level %d\n",newPolarInitNode->encoderLength,aggregation_level);
|
||||
|
||||
} else if (messageType == SL_NR_POLAR_PSBCH_MESSAGE_TYPE) { //PSBCH
|
||||
newPolarInitNode->n_max = SL_NR_POLAR_PSBCH_N_MAX;
|
||||
newPolarInitNode->i_il = SL_NR_POLAR_PSBCH_I_IL;
|
||||
newPolarInitNode->i_seg = SL_NR_POLAR_PSBCH_I_SEG;
|
||||
newPolarInitNode->n_pc = SL_NR_POLAR_PSBCH_N_PC;
|
||||
newPolarInitNode->n_pc_wm = SL_NR_POLAR_PSBCH_N_PC_WM;
|
||||
newPolarInitNode->i_bil = SL_NR_POLAR_PSBCH_I_BIL;
|
||||
newPolarInitNode->crcParityBits = SL_NR_POLAR_PSBCH_CRC_PARITY_BITS;
|
||||
newPolarInitNode->payloadBits = SL_NR_POLAR_PSBCH_PAYLOAD_BITS;
|
||||
newPolarInitNode->encoderLength = SL_NR_POLAR_PSBCH_E_NORMAL_CP;
|
||||
newPolarInitNode->crcCorrectionBits = SL_NR_POLAR_PSBCH_CRC_ERROR_CORRECTION_BITS;
|
||||
newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits);//G_P
|
||||
LOG_D(PHY,"SIDELINK: Initializing polar parameters for PSBCH (K %d, E %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength);
|
||||
} else {
|
||||
AssertFatal(1 == 0, "[nr_polar_init] Incorrect Message Type(%d)", messageType);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "openair2/COMMON/prs_nr_paramdef.h"
|
||||
#include "SCHED_NR_UE/harq_nr.h"
|
||||
#include "PHY/NR_REFSIG/nr_mod_table.h"
|
||||
|
||||
void RCconfig_nrUE_prs(void *cfg)
|
||||
{
|
||||
@@ -384,6 +385,15 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sl_ue_free(PHY_VARS_NR_UE *UE) {
|
||||
|
||||
if (UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation) {
|
||||
free_and_zero(UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[0]);
|
||||
free_and_zero(UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[1]);
|
||||
free_and_zero(UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation);
|
||||
}
|
||||
}
|
||||
|
||||
void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
{
|
||||
const NR_DL_FRAME_PARMS* fp = &ue->frame_parms;
|
||||
@@ -489,6 +499,8 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
|
||||
free_and_zero(ue->prs_vars[idx]);
|
||||
}
|
||||
|
||||
sl_ue_free(ue);
|
||||
}
|
||||
|
||||
void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb) {
|
||||
@@ -686,3 +698,248 @@ void phy_term_nr_top(void)
|
||||
free_ul_reference_signal_sequences();
|
||||
free_context_synchro_nr();
|
||||
}
|
||||
|
||||
static void sl_init_psbch_dmrs_gold_sequences(PHY_VARS_NR_UE *UE)
|
||||
{
|
||||
unsigned int x1, x2;
|
||||
uint16_t slss_id;
|
||||
uint8_t reset;
|
||||
|
||||
for (slss_id = 0; slss_id < SL_NR_NUM_SLSS_IDs; slss_id++) {
|
||||
|
||||
reset = 1;
|
||||
x2 = slss_id;
|
||||
|
||||
#ifdef SL_DEBUG_INIT
|
||||
printf("\nPSBCH DMRS GOLD SEQ for SLSSID :%d :\n", slss_id);
|
||||
#endif
|
||||
|
||||
for (uint8_t n=0; n<SL_NR_NUM_PSBCH_DMRS_RE_DWORD; n++) {
|
||||
UE->SL_UE_PHY_PARAMS.init_params.psbch_dmrs_gold_sequences[slss_id][n] = lte_gold_generic(&x1, &x2, reset);
|
||||
reset = 0;
|
||||
|
||||
#ifdef SL_DEBUG_INIT_DATA
|
||||
printf("%x\n",SL_UE_INIT_PARAMS.sl_psbch_dmrs_gold_sequences[slss_id][n]);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void sl_generate_psbch_dmrs_qpsk_sequences(PHY_VARS_NR_UE *UE,
|
||||
struct complex16 *modulated_dmrs_sym,
|
||||
uint16_t slss_id) {
|
||||
|
||||
uint8_t idx = 0;
|
||||
uint32_t *sl_dmrs_sequence = UE->SL_UE_PHY_PARAMS.init_params.psbch_dmrs_gold_sequences[slss_id];
|
||||
|
||||
#ifdef SL_DEBUG_INIT
|
||||
printf("SIDELINK INIT: PSBCH DMRS Generation with slss_id:%d\n", slss_id);
|
||||
#endif
|
||||
|
||||
/// QPSK modulation
|
||||
for (int m=0; m<SL_NR_NUM_PSBCH_DMRS_RE; m++) {
|
||||
|
||||
idx = (((sl_dmrs_sequence[(m<<1)>>5])>>((m<<1)&0x1f))&3);
|
||||
modulated_dmrs_sym[m].r = nr_qpsk_mod_table[2*idx];
|
||||
modulated_dmrs_sym[m].i = nr_qpsk_mod_table[(2*idx) + 1];
|
||||
|
||||
#ifdef SL_DEBUG_INIT_DATA
|
||||
printf("m:%d gold seq: %d b0-b1: %d-%d DMRS Symbols: %d %d\n", m, sl_dmrs_sequence[(m<<1)>>5], (((sl_dmrs_sequence[(m<<1)>>5])>>((m<<1)&0x1f))&1),
|
||||
(((sl_dmrs_sequence[((m<<1)+1)>>5])>>(((m<<1)+1)&0x1f))&1), modulated_dmrs_sym[m].r, modulated_dmrs_sym[m].i);
|
||||
printf("idx:%d, qpsk_table.r:%d, qpsk_table.i:%d\n", idx, nr_qpsk_mod_table[2*idx], nr_qpsk_mod_table[(2*idx) + 1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SL_DUMP_INIT_SAMPLES
|
||||
char filename[40], varname[25];
|
||||
sprintf(filename,"sl_psbch_dmrs_slssid_%d.m", slss_id);
|
||||
sprintf(varname,"sl_dmrs_id_%d.m", slss_id);
|
||||
LOG_M(filename, varname, (void*)modulated_dmrs_sym, SL_NR_NUM_PSBCH_DMRS_RE, 1, 1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void sl_generate_pss(SL_NR_UE_INIT_PARAMS_t *sl_init_params, uint8_t n_sl_id2, uint16_t scaling) {
|
||||
|
||||
int i = 0, m = 0;
|
||||
int16_t x[SL_NR_PSS_SEQUENCE_LENGTH];
|
||||
const int x_initial[7] = {0, 1, 1 , 0, 1, 1, 1};
|
||||
int16_t *sl_pss = sl_init_params->sl_pss[n_sl_id2];
|
||||
int16_t *sl_pss_for_sync = sl_init_params->sl_pss_for_sync[n_sl_id2];
|
||||
|
||||
LOG_D(PHY, "SIDELINK PSBCH INIT: PSS Generation with N_SL_id2:%d\n", n_sl_id2);
|
||||
|
||||
#ifdef SL_DEBUG_INIT
|
||||
printf("SIDELINK: PSS Generation with N_SL_id2:%d\n", n_sl_id2);
|
||||
#endif
|
||||
|
||||
/// Sequence generation
|
||||
for (i=0; i < 7; i++)
|
||||
x[i] = x_initial[i];
|
||||
|
||||
for (i=0; i < (SL_NR_PSS_SEQUENCE_LENGTH - 7); i++) {
|
||||
x[i+7] = (x[i + 4] + x[i]) %2;
|
||||
}
|
||||
|
||||
for (i=0; i < SL_NR_PSS_SEQUENCE_LENGTH; i++) {
|
||||
m = (i + 22 + 43*n_sl_id2) % SL_NR_PSS_SEQUENCE_LENGTH;
|
||||
sl_pss_for_sync[i] = (1 - 2*x[m]);
|
||||
sl_pss[i] = sl_pss_for_sync[i] * scaling;
|
||||
|
||||
#ifdef SL_DEBUG_INIT_DATA
|
||||
printf("m:%d, sl_pss[%d]:%d\n", m, i, sl_pss[i]);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef SL_DUMP_INIT_SAMPLES
|
||||
LOG_M("sl_pss_seq.m", "sl_pss", (void*)sl_pss, SL_NR_PSS_SEQUENCE_LENGTH, 1, 0);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void sl_generate_sss(SL_NR_UE_INIT_PARAMS_t *sl_init_params, uint16_t slss_id, uint16_t scaling) {
|
||||
|
||||
int i = 0;
|
||||
int m0, m1;
|
||||
int n_sl_id1, n_sl_id2;
|
||||
int16_t *sl_sss = sl_init_params->sl_sss[slss_id];
|
||||
int16_t *sl_sss_for_sync = sl_init_params->sl_sss_for_sync[slss_id];
|
||||
|
||||
int16_t x0[SL_NR_SSS_SEQUENCE_LENGTH], x1[SL_NR_SSS_SEQUENCE_LENGTH];
|
||||
const int x_initial[7] = { 1, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
n_sl_id1 = slss_id % 336;
|
||||
n_sl_id2 = slss_id / 336;
|
||||
|
||||
LOG_D(PHY, "SIDELINK INIT: SSS Generation with N_SL_id1:%d N_SL_id2:%d\n", n_sl_id1, n_sl_id2);
|
||||
|
||||
#ifdef SL_DEBUG_INIT
|
||||
printf("SIDELINK: SSS Generation with slss_id:%d, N_SL_id1:%d, N_SL_id2:%d\n", slss_id, n_sl_id1, n_sl_id2);
|
||||
#endif
|
||||
|
||||
for ( i=0 ; i < 7 ; i++) {
|
||||
x0[i] = x_initial[i];
|
||||
x1[i] = x_initial[i];
|
||||
}
|
||||
|
||||
for ( i=0 ; i < SL_NR_SSS_SEQUENCE_LENGTH - 7 ; i++) {
|
||||
x0[i+7] = (x0[i + 4] + x0[i]) % 2;
|
||||
x1[i+7] = (x1[i + 1] + x1[i]) % 2;
|
||||
}
|
||||
|
||||
m0 = 15*(n_sl_id1/112) + (5*n_sl_id2);
|
||||
m1 = n_sl_id1 % 112;
|
||||
|
||||
for (i = 0; i < SL_NR_SSS_SEQUENCE_LENGTH ; i++) {
|
||||
sl_sss_for_sync[i] = (1 - 2*x0[(i + m0) % SL_NR_SSS_SEQUENCE_LENGTH] ) * (1 - 2*x1[(i + m1) % SL_NR_SSS_SEQUENCE_LENGTH] );
|
||||
sl_sss[i] = sl_sss_for_sync[i] * scaling;
|
||||
|
||||
#ifdef SL_DEBUG_INIT_DATA
|
||||
printf("m0:%d, m1:%d, sl_sss_for_sync[%d]:%d, sl_sss[%d]:%d\n", m0, m1, i, sl_sss_for_sync[i], i, sl_sss[i]);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef SL_DUMP_PSBCH_TX_SAMPLES
|
||||
LOG_M("sl_sss_seq.m", "sl_sss", (void*)sl_sss, SL_NR_SSS_SEQUENCE_LENGTH, 1, 0);
|
||||
LOG_M("sl_sss_forsync_seq.m", "sl_sss_for_sync", (void*)sl_sss_for_sync, SL_NR_SSS_SEQUENCE_LENGTH, 1, 0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// This cannot be done at init time as ofdm symbol size, ssb start subcarrier depends on configuration
|
||||
// done at SLSS read time.
|
||||
static void sl_generate_pss_ifft_samples(sl_nr_ue_phy_params_t *sl_ue_params, SL_NR_UE_INIT_PARAMS_t *sl_init_params) {
|
||||
|
||||
uint8_t id2 = 0;
|
||||
int16_t *sl_pss = NULL;
|
||||
NR_DL_FRAME_PARMS *sl_fp = &sl_ue_params->sl_frame_params;
|
||||
int16_t scaling_factor = AMP;
|
||||
|
||||
int16_t *pss_F = NULL; // IQ samples in freq domain
|
||||
int32_t *pss_T = NULL;
|
||||
|
||||
uint16_t k = 0;
|
||||
|
||||
pss_F = malloc16_clear(2*sizeof(int16_t) * sl_fp->ofdm_symbol_size);
|
||||
|
||||
LOG_I(PHY, "SIDELINK INIT: Generation of PSS time domain samples. scaling_factor:%d\n", scaling_factor);
|
||||
|
||||
for (id2 = 0; id2 < SL_NR_NUM_IDs_IN_PSS; id2++) {
|
||||
|
||||
k = sl_fp->first_carrier_offset + sl_fp->ssb_start_subcarrier + 2; // PSS in from REs 2-129
|
||||
if (k >= sl_fp->ofdm_symbol_size) k -= sl_fp->ofdm_symbol_size;
|
||||
|
||||
pss_T = &sl_init_params->sl_pss_for_correlation[id2][0];
|
||||
sl_pss = sl_init_params->sl_pss[id2];
|
||||
|
||||
memset(pss_T, 0, sl_fp->ofdm_symbol_size * sizeof(pss_T[0]));
|
||||
memset(pss_F, 0, sl_fp->ofdm_symbol_size * 2 * sizeof(pss_F[0]));
|
||||
|
||||
for (int i=0; i < SL_NR_PSS_SEQUENCE_LENGTH; i++) {
|
||||
|
||||
pss_F[2*k] = (sl_pss[i] * scaling_factor) >> 15;
|
||||
//pss_F[2*k] = (sl_pss[i]/23170) * 4192;
|
||||
//pss_F[2*k+1] = 0;
|
||||
|
||||
#ifdef SL_DEBUG_INIT_DATA
|
||||
printf("id:%d, k:%d, pss_F[%d]:%d, sl_pss[%d]:%d\n", id2, k, 2*k, pss_F[2*k], i, sl_pss[i]);
|
||||
#endif
|
||||
|
||||
k++;
|
||||
if (k == sl_fp->ofdm_symbol_size) k=0;
|
||||
|
||||
}
|
||||
|
||||
idft((int16_t)get_idft(sl_fp->ofdm_symbol_size),
|
||||
pss_F, /* complex input */
|
||||
(int16_t *)&pss_T[0], /* complex output */
|
||||
1); /* scaling factor */
|
||||
|
||||
}
|
||||
|
||||
#ifdef SL_DUMP_PSBCH_TX_SAMPLES
|
||||
LOG_M("sl_pss_TD_id0.m", "pss_TD_0", (void*)sl_init_params->sl_pss_for_correlation[0], sl_fp->ofdm_symbol_size, 1, 1);
|
||||
LOG_M("sl_pss_TD_id1.m", "pss_TD_1", (void*)sl_init_params->sl_pss_for_correlation[1], sl_fp->ofdm_symbol_size, 1, 1);
|
||||
#endif
|
||||
|
||||
free(pss_F);
|
||||
|
||||
}
|
||||
|
||||
void sl_ue_phy_init(PHY_VARS_NR_UE *UE) {
|
||||
|
||||
uint16_t scaling_value = ONE_OVER_SQRT2_Q15;
|
||||
|
||||
NR_DL_FRAME_PARMS *sl_fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
if (!UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation) {
|
||||
UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation = (int32_t **)malloc16_clear(SL_NR_NUM_IDs_IN_PSS *sizeof(int32_t *) );
|
||||
UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[0] = (int32_t *)malloc16_clear( sizeof(int32_t)*sl_fp->ofdm_symbol_size);
|
||||
UE->SL_UE_PHY_PARAMS.init_params.sl_pss_for_correlation[1] = (int32_t *)malloc16_clear( sizeof(int32_t)*sl_fp->ofdm_symbol_size);
|
||||
}
|
||||
LOG_I(PHY, "SIDELINK INIT: GENERATE PSS, SSS, GOLD SEQUENCES AND PSBCH DMRS SEQUENCES FOR ALL possible SLSS IDs 0- 671\n");
|
||||
|
||||
// Generate PSS sequences for IDs 0,1 used in PSS
|
||||
sl_generate_pss(&UE->SL_UE_PHY_PARAMS.init_params,0, scaling_value);
|
||||
sl_generate_pss(&UE->SL_UE_PHY_PARAMS.init_params,1, scaling_value);
|
||||
|
||||
// Generate psbch dmrs Gold Sequences and modulated dmrs symbols
|
||||
sl_init_psbch_dmrs_gold_sequences(UE);
|
||||
for (int slss_id = 0; slss_id < SL_NR_NUM_SLSS_IDs; slss_id++) {
|
||||
sl_generate_psbch_dmrs_qpsk_sequences(UE, UE->SL_UE_PHY_PARAMS.init_params.psbch_dmrs_modsym[slss_id], slss_id);
|
||||
sl_generate_sss(&UE->SL_UE_PHY_PARAMS.init_params, slss_id, scaling_value);
|
||||
}
|
||||
|
||||
// Generate PSS time domain samples used for correlation during SLSS reception.
|
||||
sl_generate_pss_ifft_samples(&UE->SL_UE_PHY_PARAMS, &UE->SL_UE_PHY_PARAMS.init_params);
|
||||
|
||||
init_symbol_rotation(sl_fp);
|
||||
init_timeshift_rotation(sl_fp);
|
||||
}
|
||||
@@ -426,7 +426,8 @@ void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp)
|
||||
LOG_I(PHY,"fp->samples_per_frame=%d\n",fp->samples_per_frame);
|
||||
LOG_I(PHY,"fp->dl_CarrierFreq=%lu\n",fp->dl_CarrierFreq);
|
||||
LOG_I(PHY,"fp->ul_CarrierFreq=%lu\n",fp->ul_CarrierFreq);
|
||||
LOG_I(PHY,"fp->Nid_cell=%d\n",fp->Nid_cell);
|
||||
LOG_I(PHY,"fp->first_carrier_offset=%d\n",fp->first_carrier_offset);
|
||||
LOG_I(PHY,"fp->ssb_start_subcarrier=%d\n",fp->ssb_start_subcarrier);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -56,5 +56,7 @@ void free_nr_ue_ul_harq(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCESSES],
|
||||
|
||||
void phy_init_nr_top(PHY_VARS_NR_UE *ue);
|
||||
void phy_term_nr_top(void);
|
||||
void sl_ue_phy_init(PHY_VARS_NR_UE *UE);
|
||||
|
||||
void sl_ue_phy_init(PHY_VARS_NR_UE *UE);
|
||||
#endif
|
||||
|
||||
@@ -49,9 +49,11 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue,
|
||||
int reset_freq_est);
|
||||
|
||||
int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
|
||||
uint32_t linktype);
|
||||
|
||||
int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
|
||||
@@ -35,11 +35,13 @@
|
||||
#endif*/
|
||||
|
||||
int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
|
||||
uint32_t linktype)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
||||
|
||||
NR_UE_COMMON *common_vars = &ue->common_vars;
|
||||
int Ns = proc->nr_slot_rx;
|
||||
|
||||
@@ -98,7 +100,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
|
||||
apply_nr_rotation_RX(frame_parms,
|
||||
rxdataF[aa],
|
||||
frame_parms->symbol_rotation[0],
|
||||
frame_parms->symbol_rotation[linktype],
|
||||
Ns,
|
||||
frame_parms->N_RB_DL,
|
||||
0,
|
||||
|
||||
@@ -197,22 +197,30 @@ int nr_pdcch_dmrs_rx(PHY_VARS_NR_UE *ue,
|
||||
|
||||
int nr_pbch_dmrs_rx(int symbol,
|
||||
unsigned int *nr_gold_pbch,
|
||||
int32_t *output)
|
||||
int32_t *output,
|
||||
bool sidelink)
|
||||
{
|
||||
int m,m0,m1;
|
||||
uint8_t idx=0;
|
||||
AssertFatal(symbol>=0 && symbol <3,"illegal symbol %d\n",symbol);
|
||||
if (symbol == 0) {
|
||||
m0=0;
|
||||
m1=60;
|
||||
}
|
||||
else if (symbol == 1) {
|
||||
m0=60;
|
||||
m1=84;
|
||||
}
|
||||
else {
|
||||
m0=84;
|
||||
m1=144;
|
||||
if (sidelink) {
|
||||
AssertFatal(symbol== 0 || (symbol>=5 && symbol <=12),"illegal symbol %d\n",symbol);
|
||||
m0 = (symbol) ? (symbol - 4) * 33 : 0;
|
||||
m1 = (symbol) ? (symbol - 3) * 33 : 33;
|
||||
|
||||
} else {
|
||||
AssertFatal(symbol>=0 && symbol <3,"illegal symbol %d\n",symbol);
|
||||
if (symbol == 0) {
|
||||
m0=0;
|
||||
m1=60;
|
||||
}
|
||||
else if (symbol == 1) {
|
||||
m0=60;
|
||||
m1=84;
|
||||
}
|
||||
else {
|
||||
m0=84;
|
||||
m1=144;
|
||||
}
|
||||
}
|
||||
// printf("Generating pilots symbol %d, m0 %d, m1 %d\n",symbol,m0,m1);
|
||||
/// QPSK modulation
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
*/
|
||||
int nr_pbch_dmrs_rx(int dmrss,
|
||||
unsigned int *nr_gold_pbch,
|
||||
int32_t *output);
|
||||
int32_t *output,
|
||||
bool sidelink);
|
||||
|
||||
/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS.
|
||||
@param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
|
||||
|
||||
@@ -608,7 +608,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
#endif
|
||||
|
||||
// generate pilot
|
||||
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]);
|
||||
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0],0);
|
||||
|
||||
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
|
||||
@@ -729,15 +729,18 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time[][ue->frame_parms.ofdm_symbol_size],
|
||||
struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
uint8_t ssb_index,
|
||||
uint8_t n_hf,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
|
||||
c16_t rxdataF[][fp->samples_per_slot_wCP],
|
||||
bool sidelink,
|
||||
uint16_t Nid)
|
||||
{
|
||||
int Ns = proc->nr_slot_rx;
|
||||
int pilot[200] __attribute__((aligned(16)));
|
||||
@@ -748,25 +751,48 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int ch_offset,symbol_offset;
|
||||
//int slot_pbch;
|
||||
|
||||
uint8_t nushift;
|
||||
nushift = ue->frame_parms.Nid_cell%4;
|
||||
ue->frame_parms.nushift = nushift;
|
||||
unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier;
|
||||
if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size;
|
||||
uint8_t nushift = 0, lastsymbol = 0;
|
||||
|
||||
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
uint32_t *gold_seq = NULL;
|
||||
|
||||
AssertFatal(dmrss >= 0 && dmrss < 3,
|
||||
if (sidelink) {
|
||||
|
||||
AssertFatal(dmrss == 0 || (dmrss >= 5 && dmrss <= 12),
|
||||
"symbol %d is illegal for PSBCH DM-RS \n",
|
||||
dmrss);
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
|
||||
LOG_D(PHY,"PSBCH Channel Estimation SLSSID:%d\n", Nid);
|
||||
|
||||
gold_seq = sl_phy_params->init_params.psbch_dmrs_gold_sequences[Nid];
|
||||
lastsymbol = 12;
|
||||
|
||||
} else {
|
||||
|
||||
nushift = fp->Nid_cell%4;
|
||||
fp->nushift = nushift;
|
||||
|
||||
AssertFatal(dmrss >= 0 && dmrss < 3,
|
||||
"symbol %d is illegal for PBCH DM-RS \n",
|
||||
dmrss);
|
||||
|
||||
symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
|
||||
gold_seq = ue->nr_gold_pbch[n_hf][ssb_index];
|
||||
lastsymbol = 2;
|
||||
}
|
||||
|
||||
unsigned int ssb_offset = fp->first_carrier_offset + fp->ssb_start_subcarrier;
|
||||
if (ssb_offset>= fp->ofdm_symbol_size) ssb_offset-= fp->ofdm_symbol_size;
|
||||
|
||||
ch_offset = fp->ofdm_symbol_size*symbol;
|
||||
|
||||
symbol_offset = fp->ofdm_symbol_size*symbol;
|
||||
|
||||
|
||||
k = nushift;
|
||||
|
||||
#ifdef DEBUG_PBCH
|
||||
printf("PBCH Channel Estimation : gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n", proc->gNB_id, ch_offset, ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp, Ns, k, symbol);
|
||||
printf("PBCH Channel Estimation : gNB_id %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n", proc->gNB_id, ch_offset, fp->ofdm_symbol_size, fp->Ncp, Ns, k, symbol);
|
||||
#endif
|
||||
|
||||
switch (k) {
|
||||
@@ -802,7 +828,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
|
||||
idft_size_idx_t idftsizeidx;
|
||||
|
||||
switch (ue->frame_parms.ofdm_symbol_size) {
|
||||
switch (fp->ofdm_symbol_size) {
|
||||
case 128:
|
||||
idftsizeidx = IDFT_128;
|
||||
break;
|
||||
@@ -849,20 +875,20 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
// generate pilot
|
||||
nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]);
|
||||
nr_pbch_dmrs_rx(dmrss,gold_seq, &pilot[0], sidelink);
|
||||
|
||||
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
|
||||
for (int aarx=0; aarx<fp->nb_antennas_rx; aarx++) {
|
||||
|
||||
int re_offset = ssb_offset;
|
||||
pil = (int16_t *)&pilot[0];
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset];
|
||||
|
||||
memset(dl_ch,0,sizeof(struct complex16)*(ue->frame_parms.ofdm_symbol_size));
|
||||
memset(dl_ch,0,sizeof(struct complex16)*(fp->ofdm_symbol_size));
|
||||
|
||||
#ifdef DEBUG_PBCH
|
||||
printf("pbch ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL);
|
||||
printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset);
|
||||
printf("pbch ch est pilot addr %p RB_DL %d\n",&pilot[0], fp->N_RB_DL);
|
||||
printf("k %d, first_carrier %d\n",k,fp->first_carrier_offset);
|
||||
printf("rxF addr %p\n", rxF);
|
||||
printf("dl_ch addr %p\n",dl_ch);
|
||||
#endif
|
||||
@@ -881,7 +907,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
//for (int i= 0; i<8; i++)
|
||||
@@ -899,7 +925,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
@@ -914,7 +940,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch += 24;
|
||||
|
||||
@@ -926,7 +952,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
// in 2nd symbol, skip middle REs (48 with DMRS, 144 for SSS, and another 48 with DMRS)
|
||||
if (dmrss == 1 && pilot_cnt == 12) {
|
||||
pilot_cnt=48;
|
||||
re_offset = (re_offset+144) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+144) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch += 288;
|
||||
}
|
||||
@@ -945,7 +971,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
// printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i));
|
||||
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
|
||||
@@ -960,7 +986,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
|
||||
ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
|
||||
@@ -975,13 +1001,13 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
dl_ch,
|
||||
16);
|
||||
pil += 2;
|
||||
re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size;
|
||||
re_offset = (re_offset+4) % fp->ofdm_symbol_size;
|
||||
rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)];
|
||||
dl_ch += 24;
|
||||
|
||||
}
|
||||
|
||||
if( dmrss == 2) // update time statistics for last PBCH symbol
|
||||
if( dmrss == lastsymbol) // update time statistics for last PBCH symbol
|
||||
{
|
||||
// do ifft of channel estimate
|
||||
LOG_D(PHY,"Channel Impulse Computation Slot %d Symbol %d ch_offset %d\n", Ns, symbol, ch_offset);
|
||||
@@ -992,13 +1018,13 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
}
|
||||
|
||||
if (dmrss == 2)
|
||||
if (!sidelink && dmrss == lastsymbol)
|
||||
UEscopeCopy(ue,
|
||||
pbchDlChEstimateTime,
|
||||
(void *)dl_ch_estimates_time,
|
||||
sizeof(c16_t),
|
||||
ue->frame_parms.nb_antennas_rx,
|
||||
ue->frame_parms.ofdm_symbol_size,
|
||||
fp->nb_antennas_rx,
|
||||
fp->ofdm_symbol_size,
|
||||
0);
|
||||
|
||||
return(0);
|
||||
|
||||
@@ -68,15 +68,18 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time[][ue->frame_parms.ofdm_symbol_size],
|
||||
struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
uint8_t ssb_index,
|
||||
uint8_t n_hf,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
c16_t rxdataF[][fp->samples_per_slot_wCP],
|
||||
bool sidelink,
|
||||
uint16_t Nid);
|
||||
|
||||
int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
@@ -141,4 +144,9 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index);
|
||||
|
||||
|
||||
void nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
c16_t rxdataF[][fp->samples_per_slot_wCP],
|
||||
bool use_SSS);
|
||||
#endif
|
||||
|
||||
@@ -313,3 +313,56 @@ void nr_ue_rrc_measurements(PHY_VARS_NR_UE *ue,
|
||||
ue->measurements.n0_power_tot_dB + 30 - 10*log10(pow(2, 30)) - dB_fixed(ue->frame_parms.ofdm_symbol_size) - ((int)rx_gain - (int)rx_gain_offset));
|
||||
|
||||
}
|
||||
|
||||
//PSBCH RSRP calculations according to 38.215 section 5.1.22
|
||||
void nr_sl_psbch_rsrp_measurements(sl_nr_ue_phy_params_t *sl_phy_params,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
c16_t rxdataF[][fp->samples_per_slot_wCP],
|
||||
bool use_SSS)
|
||||
{
|
||||
|
||||
SL_NR_UE_PSBCH_t *psbch_rx = &sl_phy_params->psbch;
|
||||
uint8_t numsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP
|
||||
: SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
|
||||
uint32_t re_offset = fp->first_carrier_offset + fp->ssb_start_subcarrier;
|
||||
uint32_t rsrp = 0, num_re = 0;
|
||||
|
||||
LOG_D(PHY, "PSBCH RSRP MEAS: numsym:%d, re_offset:%d\n",numsym, re_offset);
|
||||
|
||||
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
|
||||
|
||||
//Calculate PSBCH RSRP based from DMRS REs
|
||||
for (uint8_t symbol=0; symbol<numsym;) {
|
||||
|
||||
struct complex16 *rxF = &rxdataF[aarx][symbol*fp->ofdm_symbol_size];
|
||||
|
||||
for (int re=0;re<SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL;re++) {
|
||||
|
||||
if (re%4 == 0) { //DMRS RE
|
||||
uint16_t offset = (re_offset + re) % fp->ofdm_symbol_size;
|
||||
|
||||
rsrp += rxF[offset].r*rxF[offset].r + rxF[offset].i*rxF[offset].i;
|
||||
num_re++;
|
||||
}
|
||||
}
|
||||
symbol = (symbol == 0) ? 5 : symbol+1;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_SSS) {
|
||||
//TBD...
|
||||
//UE can decide between using only PSBCH DMRS or PSBCH DMRS and SSS for PSBCH RSRP computation.
|
||||
//If needed this can be implemented. Reference Spec 38.215
|
||||
}
|
||||
|
||||
psbch_rx->rsrp_dB_per_RE = 10*log10(rsrp / num_re);
|
||||
psbch_rx->rsrp_dBm_per_RE = psbch_rx->rsrp_dB_per_RE +
|
||||
30 - 10*log10(pow(2,30)) -
|
||||
((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) -
|
||||
dB_fixed(fp->ofdm_symbol_size);
|
||||
|
||||
|
||||
LOG_I(PHY, "PSBCH RSRP (DMRS REs): numREs:%d RSRP :%d dB/RE ,RSRP:%d dBm/RE\n",
|
||||
num_re, psbch_rx->rsrp_dB_per_RE, psbch_rx->rsrp_dBm_per_RE);
|
||||
|
||||
}
|
||||
@@ -151,8 +151,8 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
|
||||
|
||||
for(int i=pbch_initial_symbol; i<pbch_initial_symbol+3;i++)
|
||||
nr_pbch_channel_estimation(ue,estimateSz, dl_ch_estimates, dl_ch_estimates_time,
|
||||
proc,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf,rxdataF);
|
||||
nr_pbch_channel_estimation(ue,&ue->frame_parms, estimateSz, dl_ch_estimates, dl_ch_estimates_time,
|
||||
proc,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf,rxdataF,false, frame_parms->Nid_cell);
|
||||
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
fapiPbch_t result = {0};
|
||||
|
||||
@@ -244,7 +244,7 @@ int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER
|
||||
return(avg2);
|
||||
}
|
||||
|
||||
static void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
int nb_re,
|
||||
struct complex16 rxdataF_comp[][PBCH_MAX_RE_PER_SYMBOL],
|
||||
@@ -300,7 +300,7 @@ void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
|
||||
#endif
|
||||
}
|
||||
|
||||
static void nr_pbch_unscrambling(int16_t *demod_pbch_e,
|
||||
void nr_pbch_unscrambling(int16_t *demod_pbch_e,
|
||||
uint16_t Nid,
|
||||
uint8_t nushift,
|
||||
uint16_t M,
|
||||
@@ -362,7 +362,7 @@ static void nr_pbch_unscrambling(int16_t *demod_pbch_e,
|
||||
}
|
||||
}
|
||||
|
||||
static void nr_pbch_quantize(int16_t *pbch_llr8,
|
||||
void nr_pbch_quantize(int16_t *pbch_llr8,
|
||||
int16_t *pbch_llr,
|
||||
uint16_t len) {
|
||||
for (int i=0; i<len; i++) {
|
||||
|
||||
269
openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c
Normal file
269
openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
|
||||
//#define DEBUG_PSBCH
|
||||
|
||||
//Reuse already existing PBCH functions
|
||||
extern int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int nb_re);
|
||||
extern void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
int nb_re,
|
||||
struct complex16 rxdataF_comp[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t output_shift);
|
||||
extern void nr_pbch_unscrambling(int16_t *demod_pbch_e,
|
||||
uint16_t Nid,
|
||||
uint8_t nushift,
|
||||
uint16_t M,
|
||||
uint16_t length,
|
||||
uint8_t bitwise,
|
||||
uint32_t unscrambling_mask,
|
||||
uint32_t pbch_a_prime,
|
||||
uint32_t *pbch_a_interleaved);
|
||||
extern void nr_pbch_quantize(int16_t *pbch_llr8,
|
||||
int16_t *pbch_llr,
|
||||
uint16_t len);
|
||||
|
||||
|
||||
static void nr_psbch_extract(uint32_t rxdataF_sz,
|
||||
c16_t rxdataF[][rxdataF_sz],
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 rxdataF_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
struct complex16 dl_ch_estimates_ext[][SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL],
|
||||
uint32_t symbol,
|
||||
NR_DL_FRAME_PARMS *frame_params)
|
||||
{
|
||||
uint16_t rb;
|
||||
uint8_t i,j,aarx;
|
||||
struct complex16 *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
|
||||
|
||||
const uint8_t nb_rb = SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL;
|
||||
|
||||
AssertFatal((symbol == 0 || symbol >= 5), "SIDELINK: PSBCH DMRS not contained in symbol %d \n", symbol);
|
||||
|
||||
for (aarx=0; aarx<frame_params->nb_antennas_rx; aarx++) {
|
||||
unsigned int rx_offset = frame_params->first_carrier_offset + frame_params->ssb_start_subcarrier;
|
||||
rx_offset = rx_offset % frame_params->ofdm_symbol_size;
|
||||
|
||||
rxF = &rxdataF[aarx][symbol*frame_params->ofdm_symbol_size];
|
||||
rxF_ext = &rxdataF_ext[aarx][0];
|
||||
|
||||
dl_ch0 = &dl_ch_estimates[aarx][symbol*frame_params->ofdm_symbol_size];
|
||||
dl_ch0_ext = &dl_ch_estimates_ext[aarx][0];
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(PHY, "extract_rbs: rx_offset=%d, symbol %u\n", (rx_offset + (symbol*frame_params->ofdm_symbol_size)),symbol);
|
||||
#endif
|
||||
|
||||
for (rb=0; rb<nb_rb; rb++) {
|
||||
j=0;
|
||||
|
||||
for (i=0; i<NR_NB_SC_PER_RB; i++) {
|
||||
|
||||
if (i%4 != 0) {
|
||||
|
||||
rxF_ext[j]=rxF[rx_offset];
|
||||
dl_ch0_ext[j]=dl_ch0[i];
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
|
||||
LOG_I(PHY,"rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",(9*rb) + j,
|
||||
((int16_t *)&rxF_ext[j])[0],
|
||||
((int16_t *)&rxF_ext[j])[1],
|
||||
rx_offset,
|
||||
((int16_t *)&rxF[rx_offset])[0],
|
||||
((int16_t *)&rxF[rx_offset])[1]);
|
||||
|
||||
LOG_I(PHY,"dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n", (9*rb) + j,
|
||||
((int16_t *)&dl_ch0_ext[j])[0],
|
||||
((int16_t *)&dl_ch0_ext[j])[1],
|
||||
i,
|
||||
((int16_t *)&dl_ch0[i])[0],
|
||||
((int16_t *)&dl_ch0[i])[1]);
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
rx_offset=(rx_offset+1)%(frame_params->ofdm_symbol_size);
|
||||
}
|
||||
|
||||
rxF_ext += SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB;
|
||||
dl_ch0_ext += SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB;
|
||||
dl_ch0 += NR_NB_SC_PER_RB;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
char filename[40], varname[25];
|
||||
sprintf(filename,"psbch_dlch_sym_%d.m", symbol);
|
||||
sprintf(varname,"psbch_dlch%d.m", symbol);
|
||||
LOG_M(filename, varname, (void*)dl_ch0, frame_params->ofdm_symbol_size, 1, 1);
|
||||
sprintf(filename,"psbch_dlchext_sym_%d.m", symbol);
|
||||
sprintf(varname,"psbch_dlchext%d.m", symbol);
|
||||
LOG_M(filename, varname, (void*)&dl_ch_estimates_ext[0][0], SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL , 1, 1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t *decoded_output,
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
|
||||
uint16_t slss_id)
|
||||
{
|
||||
|
||||
uint32_t decoderState=0;
|
||||
int psbch_e_rx_idx = 0;
|
||||
int16_t psbch_e_rx[SL_NR_POLAR_PSBCH_E_NORMAL_CP]= {0};
|
||||
int16_t psbch_unClipped[SL_NR_POLAR_PSBCH_E_NORMAL_CP]= {0};
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
write_output("psbch_rxdataF.m","psbchrxF",
|
||||
&rxdataF[0][0],frame_parms->ofdm_symbol_size*SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP,1,1);
|
||||
#endif
|
||||
// symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
|
||||
double log2_maxh = 0;
|
||||
|
||||
// 0 for Normal Cyclic Prefix and 1 for EXT CyclicPrefix
|
||||
const int numsym = (frame_parms->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP
|
||||
: SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
|
||||
|
||||
for (int symbol=0; symbol<numsym;) {
|
||||
const uint16_t nb_re = SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL;
|
||||
__attribute__ ((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][nb_re];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][nb_re];
|
||||
//memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext);
|
||||
nr_psbch_extract(frame_parms->samples_per_slot_wCP,
|
||||
rxdataF,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
symbol,
|
||||
frame_parms);
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(PHY,"PSBCH RX Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size );
|
||||
#endif
|
||||
|
||||
int max_h=0;
|
||||
if (symbol == 0) {
|
||||
max_h = nr_pbch_channel_level(dl_ch_estimates_ext,
|
||||
frame_parms,
|
||||
nb_re);
|
||||
//log2_maxh = 3+(log2_approx(max_h)/2);
|
||||
log2_maxh = 5 +(log2_approx(max_h)/2);// LLR32 crc error. LLR 16 CRC works
|
||||
|
||||
}
|
||||
#ifdef DEBUG_PSBCH
|
||||
LOG_I(PHY,"PSBCH RX log2_maxh = %f (%d)\n", log2_maxh, max_h);
|
||||
#endif
|
||||
|
||||
__attribute__ ((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][nb_re];
|
||||
nr_pbch_channel_compensation(rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
nb_re,
|
||||
rxdataF_comp,
|
||||
frame_parms,
|
||||
log2_maxh); // log2_maxh+I0_shift
|
||||
|
||||
nr_pbch_quantize(psbch_e_rx + psbch_e_rx_idx,
|
||||
(short *)rxdataF_comp[0],
|
||||
SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL);
|
||||
|
||||
//Unnecessary copy. Used only for SCOPE ... TBD... to remove this.
|
||||
memcpy(psbch_unClipped + psbch_e_rx_idx, rxdataF_comp[0], SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL*sizeof(int16_t));
|
||||
psbch_e_rx_idx += SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL;
|
||||
|
||||
//SKIP 2 SL-PSS AND 2 SL-SSS symbols
|
||||
//Symbols carrying PSBCH 0, 5-12
|
||||
symbol = (symbol == 0) ? 5 : symbol + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0 //ENABLE SCOPE LATER
|
||||
UEscopeCopy(ue, psbchRxdataF_comp, psbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, psbch_e_rx_idx/2);
|
||||
UEscopeCopy(ue, psbchLlr, psbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, psbch_e_rx_idx);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
write_output("psbch_rxdataFcomp.m","psbch_rxFcomp",psbch_unClipped,SL_NR_NUM_PSBCH_DATA_RE_IN_ALL_SYMBOLS,1,1);
|
||||
#endif
|
||||
|
||||
//un-scrambling
|
||||
LOG_D(PHY, "PSBCH RX POLAR DECODING: total PSBCH bits:%d, rx_slss_id:%d\n", psbch_e_rx_idx, slss_id);
|
||||
|
||||
nr_pbch_unscrambling(psbch_e_rx, slss_id, 0, 0, psbch_e_rx_idx,
|
||||
0, 0, 0, NULL);
|
||||
//polar decoding de-rate matching
|
||||
uint64_t tmp=0;
|
||||
decoderState = polar_decoder_int16(psbch_e_rx,(uint64_t *)&tmp,0,
|
||||
SL_NR_POLAR_PSBCH_MESSAGE_TYPE, SL_NR_POLAR_PSBCH_PAYLOAD_BITS, SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
||||
|
||||
|
||||
uint32_t psbch_payload = tmp;
|
||||
|
||||
if(decoderState) {
|
||||
LOG_E(PHY,"%d:%d PSBCH RX: NOK \n",proc->frame_rx, proc->nr_slot_rx);
|
||||
return(decoderState);
|
||||
}
|
||||
|
||||
// Decoder reversal
|
||||
uint32_t a_reversed=0;
|
||||
|
||||
for (int i=0; i<SL_NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
|
||||
a_reversed |= (((uint64_t)psbch_payload>>i)&1)<<(31-i);
|
||||
|
||||
psbch_payload = a_reversed;
|
||||
|
||||
*((uint32_t *)decoded_output) = psbch_payload;
|
||||
|
||||
#ifdef DEBUG_PSBCH
|
||||
for (int i=0; i<4; i++) {
|
||||
LOG_I(PHY, "decoded_output[%d]:%x\n", i, decoded_output[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
ue->symbol_offset = 0;
|
||||
|
||||
//retrieve DFN and slot number from SL-MIB
|
||||
uint32_t DFN = 0, slot_offset = 0;
|
||||
DFN = (((psbch_payload & 0x0700) >> 1) | ((psbch_payload & 0xFE0000) >> 17));
|
||||
slot_offset = (((psbch_payload & 0x010000) >> 10) | ((psbch_payload & 0xFC000000) >> 26));
|
||||
|
||||
LOG_D(PHY, "PSBCH RX SL-MIB:%x, decoded DFN:slot %d:%d, %x\n",psbch_payload, DFN, slot_offset, *(uint32_t *)decoded_output);
|
||||
|
||||
return 0;
|
||||
}
|
||||
381
openair1/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c
Normal file
381
openair1/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c
Normal file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/LTE_REFSIG/lte_refsig.h"
|
||||
#include "PHY/NR_REFSIG/nr_mod_table.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_psbch_defs.h"
|
||||
|
||||
/*
|
||||
This function performs PSBCH SCrambling as described in 38.211.
|
||||
Input parameter "output" is scrambled and the scrambled output is stored in this parameter.
|
||||
id - SLSS ID used for C_INIT
|
||||
length is the length of the buffer.
|
||||
*/
|
||||
|
||||
//#define SL_DEBUG
|
||||
|
||||
void sl_psbch_scrambling(uint32_t *output, uint32_t id, uint16_t length)
|
||||
{
|
||||
uint32_t x1, x2, s=0;
|
||||
// x1 is set in lte_gold_generic
|
||||
x2 = id; // C_INIT
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("SIDELINK: Function %s\n", __func__);
|
||||
printf("Scrambling params: length %d id %d \n", length, id);
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
for (int i=0; i<56;i++) {
|
||||
printf("\nBEFORE SCRAMBLING output[%d]:0x%x\n",i,output[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// get initial 32 scrambing bits
|
||||
s = lte_gold_generic(&x1, &x2, 1);
|
||||
#ifdef SL_DEBUG
|
||||
printf("s: %04x\t", s);
|
||||
#endif
|
||||
|
||||
// scramble in 32bit chunks
|
||||
int i = 0;
|
||||
while(i+32 <= length) {
|
||||
|
||||
output[i>>5] ^= s;
|
||||
|
||||
i += 32;
|
||||
s = lte_gold_generic(&x1, &x2, 0);
|
||||
#ifdef SL_DEBUG
|
||||
printf("s: %04x\t", s);
|
||||
#endif
|
||||
}
|
||||
|
||||
// scramble remaining bits
|
||||
for (; i < length; ++i) {
|
||||
output[i>>5] ^= ((s>>(i&0x1f)&1)<<(i&0x1f));
|
||||
}
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
for (int i=0; i<56;i++) {
|
||||
printf("\nAFTER SCRAMBLING output[%d]:0x%x\n",i,output[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This function RE MAPS PSS, SSS sequences as described in 38.211.
|
||||
txF is the data in frequency domain, sync_seq = PSS or SSS seq
|
||||
startsym = 1 for PSS, 3 for SSS
|
||||
re_offset = sample which points to first RE + SSB start RE
|
||||
scaling factor = scaling factor used for PSS, SSS (determined according to PSBCH pwr)
|
||||
symbol size = OFDM symbol size used for RE Mapping
|
||||
*/
|
||||
void sl_map_pss_or_sss(struct complex16 *txF, int16_t *sync_seq, uint16_t startsym,
|
||||
uint16_t re_offset, uint16_t scaling_factor, uint16_t symbol_size)
|
||||
{
|
||||
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("%s. DEBUG PSBCH TX: RE MAPPING of PSS/SSS \n", __func__);
|
||||
printf("Input Params - StartSYM:%d, NUMSYM:%d, RE_OFFSET:%d, num_REs:%d, scaling_factor:%d, symbol_size:%d\n",
|
||||
startsym, SL_NR_NUM_PSS_OR_SSS_SYMBOLS,re_offset, SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL, scaling_factor, symbol_size);
|
||||
#endif
|
||||
|
||||
// RE Mapping of SL-PSS, SL-SSS
|
||||
for (int l = startsym;l < (startsym + SL_NR_NUM_PSS_OR_SSS_SYMBOLS);l++) {
|
||||
|
||||
int k = re_offset % symbol_size;
|
||||
int index = 0, offset = 0;
|
||||
|
||||
for (int m = 0;m < SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL;m++) {
|
||||
|
||||
offset = l*symbol_size + k;
|
||||
if ((m < 2) || (m >= (SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL - 3))) {
|
||||
txF[offset].r = 0; //Set REs 0,1,129,130,131 = 0
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("sym:%d, RE:%d, txF[%d]:%d.%d \n", l, m, offset, txF[offset].r,txF[offset].i);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
txF[offset].r = (sync_seq[index] * scaling_factor) >> 15;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("sym:%d, RE:%d, txF[%d]:%d.%d, syncseq[%d]:%d \n", l, m, offset, txF[offset].r,txF[offset].i, index, sync_seq[index]);
|
||||
#endif
|
||||
|
||||
index++;
|
||||
}
|
||||
txF[offset].i = 0;
|
||||
k = (k + 1) % symbol_size;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This function Generates the PSBCH DATA Modulation symbols and RE MAPS PSBCH Modulated symbols
|
||||
and PSBCH DMRS sequences as described in 38.211.
|
||||
txF is the data in frequency domain
|
||||
payload is the PSBCH payload (SL-MIB given by higher layers)
|
||||
id - SLSS ID used for knowing which DMRS sequence to be used.
|
||||
Cp - NORMAL of extended Cyclic prefix
|
||||
startsym = 0 and then PSBCH is mapped from symbols 5-13 if normal , 5-11 if extended
|
||||
re_offset = sample which points to first RE + SSB start RE
|
||||
scaling factor = scaling factor used for PSS, SSS (determined according to PSBCH pwr)
|
||||
symbol size = OFDM symbol size used for RE Mapping
|
||||
*/
|
||||
|
||||
void sl_generate_and_map_psbch(struct complex16 *txF, uint32_t *payload, uint16_t id,
|
||||
uint16_t cp, uint16_t re_offset, uint16_t scaling_factor, uint16_t symbol_size,
|
||||
struct complex16 *psbch_dmrs)
|
||||
{
|
||||
|
||||
uint64_t psbch_a_reversed = 0;
|
||||
uint16_t num_psbch_modsym = 0, numsym = 0;
|
||||
uint8_t idx = 0;
|
||||
uint32_t encoder_output[SL_NR_POLAR_PSBCH_E_DWORD];
|
||||
struct complex16 psbch_modsym[SL_NR_NUM_PSBCH_MODULATED_SYMBOLS];
|
||||
|
||||
LOG_D(PHY, "PSBCH TX: Generation accg to 38.212, 38.211. SLSS id:%d\n", id);
|
||||
|
||||
// Encoder reversal
|
||||
for (int i=0; i<SL_NR_POLAR_PSBCH_PAYLOAD_BITS; i++)
|
||||
psbch_a_reversed |= (((uint64_t)*payload>>i)&1)<<(31-i);
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: 38.212 PSBCH CRC + Channel coding (POLAR) + Rate Matching:\n");
|
||||
printf("PSBCH payload:%x, Reversed Payload:%016lx\n",*payload, psbch_a_reversed);
|
||||
#endif
|
||||
|
||||
/// CRC, coding and rate matching
|
||||
polar_encoder_fast(&psbch_a_reversed, (void*)encoder_output, 0, 0,
|
||||
SL_NR_POLAR_PSBCH_MESSAGE_TYPE,
|
||||
SL_NR_POLAR_PSBCH_PAYLOAD_BITS,
|
||||
SL_NR_POLAR_PSBCH_AGGREGATION_LEVEL);
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
for (int i=0; i<SL_NR_POLAR_PSBCH_E_DWORD; i++)
|
||||
printf("encoderoutput[%d]: 0x%08x\t", i, encoder_output[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/// 38.211 Scrambling
|
||||
if (cp) { // EXT Cyclic prefix
|
||||
sl_psbch_scrambling(encoder_output, id, SL_NR_POLAR_PSBCH_E_EXT_CP); //for Extended Cyclic prefix
|
||||
num_psbch_modsym = SL_NR_POLAR_PSBCH_E_EXT_CP/2;
|
||||
numsym = SL_NR_NUM_SYMBOLS_SSB_EXT_CP;
|
||||
AssertFatal(1==0, "EXT CP is not yet supported\n");
|
||||
}
|
||||
else { // Normal CP
|
||||
sl_psbch_scrambling(encoder_output, id, SL_NR_POLAR_PSBCH_E_NORMAL_CP); //for Cyclic prefix
|
||||
num_psbch_modsym = SL_NR_POLAR_PSBCH_E_NORMAL_CP/2;
|
||||
numsym = SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
|
||||
}
|
||||
|
||||
LOG_D(PHY,"PSBCH TX: 38.211 Scrambling done. Number of bits:%d \n",
|
||||
SL_NR_POLAR_PSBCH_E_NORMAL_CP);
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("38211 STEP: PSBCH Scrambling \n");
|
||||
for (int i=0; i<SL_NR_POLAR_PSBCH_E_NORMAL_CP/32; i++)
|
||||
printf("Scrambleroutput[%d]: 0x%08x\t", i, encoder_output[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("SIDELINK PSBCH TX: 38211 STEP: QPSK Modulation of PSBCH symbols:%d, symbols in PSBCH:%d\n", num_psbch_modsym, numsym);
|
||||
#endif
|
||||
|
||||
/// 38.211 QPSK modulation
|
||||
for (int j=0; j<num_psbch_modsym; j++) {
|
||||
idx = ((encoder_output[(j<<1)>>5]>>((j<<1)&0x1f))&3);
|
||||
psbch_modsym[j].r = nr_qpsk_mod_table[2*idx];
|
||||
psbch_modsym[j].i = nr_qpsk_mod_table[(2*idx)+1];
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("idx %d, psbch_modsym[%d]-r:%d, i:%d\n", idx, j, psbch_modsym[j].r, psbch_modsym[j].i);
|
||||
#endif
|
||||
}
|
||||
|
||||
// RE MApping of PSBCH and PSBCH DMRS
|
||||
int index = 0, dmrs_index = 0;
|
||||
const int numre=SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
LOG_M("sl_psbch_data_symbols.m", "psbch_sym", (void*)psbch_modsym, num_psbch_modsym, 1, 1);
|
||||
LOG_M("sl_psbch_dmrs_symbols.m", "psbch_dmrs", (void*)psbch_dmrs, SL_NR_NUM_PSBCH_DMRS_RE, 1, 1);
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("\nMapping Sidelink PSBCH DMRS, PSBCH modulation symbols to 132 REs\n");
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("%s. DEBUG PSBCH TX: RE MAPPING of PSBCH DATA AND DMRS \n", __func__);
|
||||
printf("Input Params - StartSYM:%d, NUMSYM:%d, RE_OFFSET:%d, num_REs:%d, scaling_factor:%d, symbol_size:%d\n",
|
||||
0, numsym,re_offset, numre, scaling_factor, symbol_size);
|
||||
#endif
|
||||
|
||||
for (int l=0;l < numsym;) {
|
||||
|
||||
int k = re_offset % symbol_size;
|
||||
int symbol_offset = l*symbol_size;
|
||||
int offset = 0;
|
||||
|
||||
for (int m=0; m < numre;m++) {
|
||||
|
||||
// Maps PSBCH DMRS in every 4th RE ex:0,4,....128
|
||||
// Maps PSBCH in all other REs ex: 1,2,3,5,6,...127,129,130,131
|
||||
|
||||
offset = symbol_offset + k;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("symbol:%d, symbol_offset:%d, k:%d, re:%d, sampleoffset:%d ", l, symbol_offset, k, m, offset);
|
||||
#endif
|
||||
|
||||
if (m % 4 == 0) {
|
||||
txF[offset].r = (psbch_dmrs[dmrs_index].r * scaling_factor) >> 15;
|
||||
txF[offset].i = (psbch_dmrs[dmrs_index].i * scaling_factor) >> 15;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("txF[%d]:%d,%d, psbch_dmrs[%d]:%d,%d ", offset, txF[offset].r,
|
||||
txF[offset].i, dmrs_index, psbch_dmrs[dmrs_index].r, psbch_dmrs[dmrs_index].i);
|
||||
#endif
|
||||
|
||||
dmrs_index++;
|
||||
|
||||
} else {
|
||||
txF[offset].r = (psbch_modsym[index].r * scaling_factor) >> 15;
|
||||
txF[offset].i = (psbch_modsym[index].i * scaling_factor) >> 15;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("txF[%d]:%d,%d, psbch_modsym[%d]:%d,%d\n", offset, txF[offset].r,
|
||||
txF[offset].i, index ,psbch_modsym[index].r, psbch_modsym[index].i);
|
||||
#endif
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
k = (k + 1) % symbol_size;
|
||||
}
|
||||
|
||||
LOG_D(PHY, "PSBCH TX: 38211 STEP: RE MAPPING OF PSBCH, PSBCH DMRS DONE. symbol:%d, first RE offset:%d, Last RE offset:%d, Num PSBCH DATA REs:%d, Num PSBCH DMRS REs:%d\n",
|
||||
l, symbol_offset+re_offset, offset, index, dmrs_index);
|
||||
|
||||
l = (l == 0) ? 5: l+1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This function prepares the PSBCH block and RE MAPS PSS, SSS, PSBCH DATA, PSBCH DMRS into buffer txF.
|
||||
Called by the L1 Scheduler when MAC triggers PHY to send PSBCH
|
||||
UE is the UE context.
|
||||
frame, slot points to the TTI in which PSBCH TX will be transmitted
|
||||
*/
|
||||
void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx,
|
||||
uint32_t slot_tx,
|
||||
sl_nr_tx_config_psbch_pdu_t *psbch_vars,
|
||||
c16_t **txdataF)
|
||||
{
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_ue_phy_params = &UE->SL_UE_PHY_PARAMS;
|
||||
uint16_t slss_id = psbch_vars->tx_slss_id;
|
||||
NR_DL_FRAME_PARMS *sl_fp = &sl_ue_phy_params->sl_frame_params;
|
||||
uint32_t psbch_payload = *((uint32_t *)psbch_vars->psbch_payload);
|
||||
|
||||
LOG_D(PHY,"PSBCH TX: slss-id %d, psbch payload %x \n", slss_id, psbch_payload);
|
||||
|
||||
// Insert FN and Slot number into SL-MIB
|
||||
uint32_t mask = ~(0x700 | 0xFE0000 | 0x10000 | 0xFC000000);
|
||||
psbch_payload &= mask;
|
||||
psbch_payload |= ((frame_tx%1024)<<1) & 0x700;
|
||||
psbch_payload |= ((frame_tx%1024)<<17) & 0xFE0000;
|
||||
psbch_payload |= (slot_tx<<10) & 0x10000;
|
||||
psbch_payload |= (slot_tx<<26) & 0xFC000000;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: DFN, SLOT included. psbch_a :0x%08x, frame:%d, slot:%d\n",
|
||||
psbch_payload, frame_tx, slot_tx);
|
||||
#endif
|
||||
|
||||
LOG_D(PHY,"PSBCH TX: Frame.Slot %d.%d. Payload::0x%08x, slssid:%d\n",
|
||||
frame_tx, slot_tx, psbch_payload, slss_id);
|
||||
|
||||
// GENERATE Sidelink PSS,SSS Sequences, PSBCH DMRS Symbols, PSBCH Symbols
|
||||
int16_t *sl_pss = &sl_ue_phy_params->init_params.sl_pss[slss_id/336][0];
|
||||
int16_t *sl_sss = &sl_ue_phy_params->init_params.sl_sss[slss_id][0];
|
||||
|
||||
uint16_t re_offset = sl_fp->first_carrier_offset + sl_fp->ssb_start_subcarrier;
|
||||
uint16_t symbol_size = sl_fp->ofdm_symbol_size;
|
||||
// TBD: Need to be replaced by function which calculates scaling factor based on psbch tx power
|
||||
uint16_t scaling_factor = AMP;
|
||||
|
||||
struct complex16 *txF = &txdataF[0][0];
|
||||
uint16_t startsym = SL_NR_PSS_START_SYMBOL;
|
||||
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: MAP PSS. startsym:%d, PSS RE START:%d, scaling factor:%d\n",
|
||||
startsym, re_offset, scaling_factor);
|
||||
#endif
|
||||
sl_map_pss_or_sss(txF, sl_pss, startsym, re_offset, scaling_factor, symbol_size); // PSS
|
||||
|
||||
|
||||
startsym += SL_NR_NUM_PSS_SYMBOLS;
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: MAP SSS. startsym:%d, SSS RE START:%d, scaling factor:%d\n",
|
||||
startsym, re_offset, scaling_factor);
|
||||
#endif
|
||||
sl_map_pss_or_sss(txF, sl_sss, startsym, re_offset, scaling_factor, symbol_size); // SSS
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: MAP PSBCH DATA AND DMRS. cyclicPrefix:%d, PSS RE START:%d, scaling factor:%d\n",
|
||||
sl_fp->Ncp, re_offset, scaling_factor);
|
||||
#endif
|
||||
|
||||
struct complex16 *psbch_dmrs = &sl_ue_phy_params->init_params.psbch_dmrs_modsym[slss_id][0];
|
||||
|
||||
sl_generate_and_map_psbch(txF, &psbch_payload, slss_id,
|
||||
sl_fp->Ncp, re_offset, scaling_factor, symbol_size,
|
||||
psbch_dmrs);
|
||||
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("DEBUG PSBCH TX: txdataF Prepared\n");
|
||||
#endif
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
LOG_M("sl_psbch_block.m", "sl_txF", (void*)txdataF[0], symbol_size*14, 1, 1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -410,6 +410,19 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
|
||||
void dump_nrdlsch(PHY_VARS_NR_UE *ue,uint8_t gNB_id,uint8_t nr_slot_rx,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid);
|
||||
void nr_a_sum_b(c16_t *input_x, c16_t *input_y, unsigned short nb_rb);
|
||||
|
||||
int nr_rx_psbch(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t *decoded_output,
|
||||
c16_t rxdataF[][frame_parms->samples_per_slot_wCP],
|
||||
uint16_t slss_id);
|
||||
|
||||
void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx, uint32_t slot_tx,
|
||||
sl_nr_tx_config_psbch_pdu_t *psbch_vars,
|
||||
c16_t **txdataF);
|
||||
/**@}*/
|
||||
#endif
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "defs_nr_common.h"
|
||||
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "PHY/defs_nr_sl_UE.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -649,6 +650,10 @@ typedef struct {
|
||||
notifiedFIFO_t phy_config_ind;
|
||||
notifiedFIFO_t *tx_resume_ind_fifo[NR_MAX_SLOTS_PER_FRAME];
|
||||
int tx_wait_for_dlsch[NR_MAX_SLOTS_PER_FRAME];
|
||||
|
||||
//Sidelink parameters
|
||||
sl_nr_sidelink_mode_t sl_mode;
|
||||
sl_nr_ue_phy_params_t SL_UE_PHY_PARAMS;
|
||||
} PHY_VARS_NR_UE;
|
||||
|
||||
typedef struct {
|
||||
@@ -670,11 +675,20 @@ typedef struct {
|
||||
typedef struct nr_phy_data_tx_s {
|
||||
NR_UE_ULSCH_t ulsch;
|
||||
NR_UE_PUCCH pucch_vars;
|
||||
|
||||
//Sidelink Rx action decided by MAC
|
||||
sl_nr_tx_config_type_enum_t sl_tx_action;
|
||||
sl_nr_tx_config_psbch_pdu_t psbch_vars;
|
||||
|
||||
} nr_phy_data_tx_t;
|
||||
|
||||
typedef struct nr_phy_data_s {
|
||||
NR_UE_PDCCH_CONFIG phy_pdcch_config;
|
||||
NR_UE_DLSCH_t dlsch[2];
|
||||
|
||||
//Sidelink Rx action decided by MAC
|
||||
sl_nr_rx_config_type_enum_t sl_rx_action;
|
||||
|
||||
} nr_phy_data_t;
|
||||
/* this structure is used to pass both UE phy vars and
|
||||
* proc to the function UE_thread_rxn_txnp4
|
||||
|
||||
146
openair1/PHY/defs_nr_sl_UE.h
Normal file
146
openair1/PHY/defs_nr_sl_UE.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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/defs_nr_sl_UE.h
|
||||
\brief Top-level defines and structure definitions
|
||||
\author
|
||||
\date
|
||||
\version
|
||||
\company Fraunhofer
|
||||
\email:
|
||||
\note
|
||||
\warning
|
||||
*/
|
||||
|
||||
#ifndef _DEFS_NR_SL_UE_H_
|
||||
#define _DEFS_NR_SL_UE_H_
|
||||
|
||||
|
||||
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/sidelink_nr_ue_interface.h"
|
||||
#include "common/utils/time_meas.h"
|
||||
|
||||
|
||||
// (33*(13-4))
|
||||
// Normal CP - NUM_SSB_Symbols = 13. 4 symbols for PSS, SSS
|
||||
#define SL_NR_NUM_PSBCH_DMRS_RE 297
|
||||
//ceil(2(QPSK)*SL_NR_NUM_PSBCH_DMRS_RE/32)
|
||||
#define SL_NR_NUM_PSBCH_DMRS_RE_DWORD 20
|
||||
//11 RBs for PSBCH in one symbol * 12 REs
|
||||
#define SL_NR_NUM_PSBCH_RE_IN_ONE_SYMBOL 132
|
||||
//3 DMRS REs per RB * 11 RBS in one symbol
|
||||
#define SL_NR_NUM_PSBCH_DMRS_RE_IN_ONE_SYMBOL 33
|
||||
//9 PSBCH DATA REs * 11 RBS in one symbol
|
||||
#define SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_SYMBOL 99
|
||||
#define SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL 11
|
||||
// SL_NR_POLAR_PSBCH_E_NORMAL_CP/2 bits because QPSK used for PSBCH.
|
||||
// 11 * (12-3 DMRS REs) * 9 symbols for PSBCH
|
||||
#define SL_NR_NUM_PSBCH_MODULATED_SYMBOLS 891
|
||||
#define SL_NR_NUM_PSBCH_DATA_RE_IN_ONE_RB 9
|
||||
#define SL_NR_NUM_PSBCH_DMRS_RE_IN_ONE_RB 3
|
||||
// 11 * (12-3 DMRS REs) * 9 symbols for PSBCH
|
||||
#define SL_NR_NUM_PSBCH_DATA_RE_IN_ALL_SYMBOLS 891
|
||||
|
||||
|
||||
|
||||
#define SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP 13
|
||||
#define SL_NR_NUM_SYMBOLS_SSB_EXT_CP 11
|
||||
#define SL_NR_NUM_PSS_SYMBOLS 2
|
||||
#define SL_NR_NUM_SSS_SYMBOLS 2
|
||||
#define SL_NR_PSS_START_SYMBOL 1
|
||||
#define SL_NR_SSS_START_SYMBOL 3
|
||||
#define SL_NR_NUM_PSS_OR_SSS_SYMBOLS 2
|
||||
#define SL_NR_PSS_SEQUENCE_LENGTH 127
|
||||
#define SL_NR_SSS_SEQUENCE_LENGTH 127
|
||||
#define SL_NR_NUM_IDs_IN_PSS 2
|
||||
#define SL_NR_NUM_IDs_IN_SSS 336
|
||||
#define SL_NR_NUM_SLSS_IDs 672
|
||||
|
||||
typedef enum sl_nr_sidelink_mode {
|
||||
SL_NOT_SUPPORTED = 0,
|
||||
SL_MODE1_SUPPORTED,
|
||||
SL_MODE2_SUPPORTED
|
||||
} sl_nr_sidelink_mode_t;
|
||||
|
||||
//(11*(12-3 DMRS REs) * 2 (QPSK used)
|
||||
#define SL_NR_NUM_PSBCH_DATA_BITS_IN_ONE_SYMBOL 198
|
||||
|
||||
typedef struct SL_NR_UE_INIT_PARAMS {
|
||||
|
||||
//gold sequences for PSBCH DMRS
|
||||
uint32_t psbch_dmrs_gold_sequences[SL_NR_NUM_SLSS_IDs][SL_NR_NUM_PSBCH_DMRS_RE_DWORD]; // Gold sequences for PSBCH DMRS
|
||||
|
||||
//PSBCH DMRS QPSK modulated symbols for all possible SLSS Ids
|
||||
struct complex16 psbch_dmrs_modsym[SL_NR_NUM_SLSS_IDs][SL_NR_NUM_PSBCH_DMRS_RE];
|
||||
|
||||
// Scaled values
|
||||
int16_t sl_pss[SL_NR_NUM_IDs_IN_PSS][SL_NR_PSS_SEQUENCE_LENGTH];
|
||||
int16_t sl_sss[SL_NR_NUM_SLSS_IDs][SL_NR_SSS_SEQUENCE_LENGTH];
|
||||
|
||||
// Contains Not scaled values just the simple generated sequence
|
||||
int16_t sl_pss_for_sync[SL_NR_NUM_IDs_IN_PSS][SL_NR_PSS_SEQUENCE_LENGTH];
|
||||
int16_t sl_sss_for_sync[SL_NR_NUM_SLSS_IDs][SL_NR_SSS_SEQUENCE_LENGTH];
|
||||
|
||||
int32_t **sl_pss_for_correlation; // IFFT samples for correlation
|
||||
|
||||
} SL_NR_UE_INIT_PARAMS_t;
|
||||
|
||||
typedef struct SL_NR_UE_PSBCH {
|
||||
|
||||
// AVG POWER OF PSBCH DMRS in dB/RE
|
||||
int16_t rsrp_dB_per_RE;
|
||||
// AVG POWER OF PSBCH DMRS in dBm/RE
|
||||
int16_t rsrp_dBm_per_RE;
|
||||
|
||||
// STATS - CRC Errors observed during PSBCH reception
|
||||
uint16_t rx_errors;
|
||||
|
||||
// STATS - Receptions with CRC OK
|
||||
uint16_t rx_ok;
|
||||
|
||||
// STATS - transmissions of PSBCH by the UE
|
||||
uint16_t num_psbch_tx;
|
||||
|
||||
} SL_NR_UE_PSBCH_t;
|
||||
|
||||
typedef struct sl_nr_ue_phy_params {
|
||||
|
||||
SL_NR_UE_INIT_PARAMS_t init_params;
|
||||
|
||||
// Sidelink PHY PARAMETERS USED FOR PSBCH reception/Txn
|
||||
SL_NR_UE_PSBCH_t psbch;
|
||||
|
||||
//Configuration parameters from MAC
|
||||
sl_nr_phy_config_request_t sl_config;
|
||||
|
||||
NR_DL_FRAME_PARMS sl_frame_params;
|
||||
|
||||
time_stats_t phy_proc_sl_tx;
|
||||
time_stats_t phy_proc_sl_rx;
|
||||
time_stats_t channel_estimation_stats;
|
||||
time_stats_t ue_sl_indication_stats;
|
||||
|
||||
} sl_nr_ue_phy_params_t;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -191,5 +191,12 @@ int nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t r
|
||||
|
||||
void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
|
||||
void psbch_pscch_processing(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_t *phy_data);
|
||||
int phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_tx_t *phy_data);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -875,12 +875,15 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
for (int i=1; i<4; i++) {
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
(ssb_start_symbol+i)%(fp->symbols_per_slot),
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
link_type_dl);
|
||||
|
||||
start_meas(&ue->dlsch_channel_estimation_stats);
|
||||
nr_pbch_channel_estimation(ue,
|
||||
&ue->frame_parms,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
dl_ch_estimates_time,
|
||||
@@ -889,7 +892,9 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
i-1,
|
||||
ssb_index&7,
|
||||
ssb_slot_2 == nr_slot_rx,
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
false,
|
||||
fp->Nid_cell);
|
||||
stop_meas(&ue->dlsch_channel_estimation_stats);
|
||||
}
|
||||
|
||||
@@ -939,9 +944,11 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
for(int j = prs_config->SymbolStart; j < (prs_config->SymbolStart+prs_config->NumPRSSymbols); j++)
|
||||
{
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
(j%fp->symbols_per_slot),
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
link_type_dl);
|
||||
}
|
||||
nr_prs_channel_estimation(rsc_id,
|
||||
i,
|
||||
@@ -978,9 +985,11 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
start_meas(&ue->ofdm_demod_stats);
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
l,
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
link_type_dl);
|
||||
}
|
||||
|
||||
// Hold the channel estimates in frequency domain.
|
||||
@@ -1039,9 +1048,11 @@ void pdsch_processing(PHY_VARS_NR_UE *ue,
|
||||
|
||||
for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){
|
||||
nr_slot_fep(ue,
|
||||
&ue->frame_parms,
|
||||
proc,
|
||||
m, //to be updated from higher layer
|
||||
rxdataF);
|
||||
rxdataF,
|
||||
link_type_dl);
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT);
|
||||
|
||||
@@ -1116,7 +1127,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
l_csiim[symb_idx] = ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx];
|
||||
if(nr_slot_fep_done == false) {
|
||||
nr_slot_fep(ue, proc, ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx], rxdataF);
|
||||
nr_slot_fep(ue, &ue->frame_parms, proc, ue->csiim_vars[gNB_id]->csiim_config_pdu.l_csiim[symb_idx], rxdataF, link_type_dl);
|
||||
}
|
||||
}
|
||||
nr_ue_csi_im_procedures(ue, proc, rxdataF);
|
||||
@@ -1127,7 +1138,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue,
|
||||
if ((ue->csirs_vars[gNB_id]) && (ue->csirs_vars[gNB_id]->active == 1)) {
|
||||
for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) {
|
||||
if(is_csi_rs_in_symbol(ue->csirs_vars[gNB_id]->csirs_config_pdu,symb)) {
|
||||
nr_slot_fep(ue, proc, symb, rxdataF);
|
||||
nr_slot_fep(ue, &ue->frame_parms, proc, symb, rxdataF, link_type_dl);
|
||||
}
|
||||
}
|
||||
nr_ue_csi_rs_procedures(ue, proc, rxdataF);
|
||||
|
||||
325
openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c
Normal file
325
openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c
Normal file
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "UTIL/OPT/opt.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "T.h"
|
||||
#include "PHY/MODULATION/modulation_UE.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
|
||||
void nr_fill_sl_indication(nr_sidelink_indication_t *sl_ind,
|
||||
sl_nr_rx_indication_t *rx_ind,
|
||||
sl_nr_sci_indication_t *sci_ind,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
void *phy_data)
|
||||
{
|
||||
memset((void*)sl_ind, 0, sizeof(nr_sidelink_indication_t));
|
||||
|
||||
sl_ind->gNB_index = proc->gNB_id;
|
||||
sl_ind->module_id = ue->Mod_id;
|
||||
sl_ind->cc_id = ue->CC_id;
|
||||
sl_ind->frame_rx = proc->frame_rx;
|
||||
sl_ind->slot_rx = proc->nr_slot_rx;
|
||||
sl_ind->frame_tx = proc->frame_tx;
|
||||
sl_ind->slot_tx = proc->nr_slot_tx;
|
||||
sl_ind->phy_data = phy_data;
|
||||
|
||||
if (rx_ind) {
|
||||
sl_ind->rx_ind = rx_ind; // hang on rx_ind instance
|
||||
sl_ind->sci_ind = NULL;
|
||||
}
|
||||
if (sci_ind) {
|
||||
sl_ind->rx_ind = NULL;
|
||||
sl_ind->sci_ind = sci_ind;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_fill_sl_rx_indication(sl_nr_rx_indication_t *rx_ind,
|
||||
uint8_t pdu_type,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
uint16_t n_pdus,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
void *typeSpecific,
|
||||
uint16_t rx_slss_id)
|
||||
{
|
||||
|
||||
if (n_pdus > 1){
|
||||
LOG_E(PHY, "In %s: multiple number of SL PDUs not supported yet...\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
|
||||
switch (pdu_type){
|
||||
case SL_NR_RX_PDU_TYPE_SLSCH:
|
||||
break;
|
||||
case FAPI_NR_RX_PDU_TYPE_SSB: {
|
||||
sl_nr_ssb_pdu_t *ssb_pdu = &rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu;
|
||||
if(typeSpecific) {
|
||||
uint8_t *psbch_decoded_output = (uint8_t *)typeSpecific;
|
||||
memcpy(ssb_pdu->psbch_payload, psbch_decoded_output, sizeof(4));//4 bytes of PSBCH payload bytes
|
||||
ssb_pdu->rsrp_dbm = sl_phy_params->psbch.rsrp_dBm_per_RE;
|
||||
ssb_pdu->rx_slss_id = rx_slss_id;
|
||||
ssb_pdu->decode_status = true;
|
||||
LOG_D(PHY, "SL-IND: SSB to MAC. rsrp:%d, slssid:%d, payload:%x\n",
|
||||
ssb_pdu->rsrp_dbm,ssb_pdu->rx_slss_id,
|
||||
*((uint32_t *)(ssb_pdu->psbch_payload)) );
|
||||
}
|
||||
else
|
||||
ssb_pdu->decode_status = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rx_ind->rx_indication_body[n_pdus -1].pdu_type = pdu_type;
|
||||
rx_ind->number_pdus = n_pdus;
|
||||
|
||||
}
|
||||
|
||||
static int nr_ue_psbch_procedures(PHY_VARS_NR_UE *ue,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
nr_phy_data_t *phy_data,
|
||||
c16_t rxdataF[][fp->samples_per_slot_wCP])
|
||||
{
|
||||
|
||||
int ret = 0;
|
||||
DevAssert(ue);
|
||||
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
uint16_t rx_slss_id = sl_phy_params->sl_config.sl_sync_source.rx_slss_id;
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PSBCH_PROCEDURES, VCD_FUNCTION_IN);
|
||||
|
||||
LOG_D(PHY,"[UE %d] Frame %d Slot %d, Trying PSBCH (SLSS ID %d)\n",
|
||||
ue->Mod_id,frame_rx,nr_slot_rx,
|
||||
sl_phy_params->sl_config.sl_sync_source.rx_slss_id);
|
||||
|
||||
uint8_t decoded_pdu[4] = {0};
|
||||
ret = nr_rx_psbch(ue,
|
||||
proc,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
fp,
|
||||
decoded_pdu,
|
||||
rxdataF,
|
||||
sl_phy_params->sl_config.sl_sync_source.rx_slss_id);
|
||||
|
||||
nr_sidelink_indication_t sl_indication;
|
||||
sl_nr_rx_indication_t rx_ind = {0};
|
||||
uint16_t number_pdus = 1;
|
||||
|
||||
uint8_t *result = NULL;
|
||||
if (ret) sl_phy_params->psbch.rx_errors ++;
|
||||
else {
|
||||
result = decoded_pdu;
|
||||
sl_phy_params->psbch.rx_ok ++;
|
||||
}
|
||||
|
||||
nr_fill_sl_indication(&sl_indication, &rx_ind, NULL, proc, ue, phy_data);
|
||||
nr_fill_sl_rx_indication(&rx_ind, SL_NR_RX_PDU_TYPE_SSB, ue, number_pdus, proc, (void *)result, rx_slss_id);
|
||||
|
||||
if (ue->if_inst && ue->if_inst->sl_indication)
|
||||
ue->if_inst->sl_indication(&sl_indication);
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PSBCH_PROCEDURES, VCD_FUNCTION_OUT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void psbch_pscch_processing(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_t *phy_data) {
|
||||
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX_SL, VCD_FUNCTION_IN);
|
||||
start_meas(&sl_phy_params->phy_proc_sl_rx);
|
||||
|
||||
LOG_D(PHY," ****** Sidelink RX-Chain for Frame.Slot %d.%d ****** \n",
|
||||
frame_rx%1024, nr_slot_rx);
|
||||
|
||||
const uint32_t rxdataF_sz = fp->samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) c16_t rxdataF[fp->nb_antennas_rx][rxdataF_sz];
|
||||
|
||||
if (phy_data->sl_rx_action == SL_NR_CONFIG_TYPE_RX_PSBCH){
|
||||
|
||||
const int estimateSz = fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PSBCH, VCD_FUNCTION_IN);
|
||||
LOG_D(PHY," ----- PSBCH RX TTI: frame.slot %d.%d ------ \n",
|
||||
frame_rx%1024, nr_slot_rx);
|
||||
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[fp->nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[fp->nb_antennas_rx][fp->ofdm_symbol_size];
|
||||
|
||||
// 0 for Normal Cyclic Prefix and 1 for EXT CyclicPrefix
|
||||
const int numsym = (fp->Ncp) ? SL_NR_NUM_SYMBOLS_SSB_EXT_CP
|
||||
: SL_NR_NUM_SYMBOLS_SSB_NORMAL_CP;
|
||||
|
||||
for (int sym=0; sym<numsym;) {
|
||||
nr_slot_fep(ue,
|
||||
fp,
|
||||
proc,
|
||||
sym,
|
||||
rxdataF,
|
||||
link_type_ul);
|
||||
|
||||
start_meas(&sl_phy_params->channel_estimation_stats);
|
||||
nr_pbch_channel_estimation(ue,
|
||||
fp,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
dl_ch_estimates_time,
|
||||
proc,
|
||||
sym,
|
||||
sym,
|
||||
0,
|
||||
0,
|
||||
rxdataF,
|
||||
true,
|
||||
sl_phy_params->sl_config.sl_sync_source.rx_slss_id);
|
||||
stop_meas(&sl_phy_params->channel_estimation_stats);
|
||||
|
||||
//PSBCH present in symbols 0, 5-12 for normal cp
|
||||
sym = (sym == 0) ? 5 : sym + 1;
|
||||
}
|
||||
|
||||
nr_sl_psbch_rsrp_measurements(sl_phy_params,fp, rxdataF,false);
|
||||
|
||||
LOG_D(PHY," ------ Decode SL-MIB: frame.slot %d.%d ------ \n",
|
||||
frame_rx%1024, nr_slot_rx);
|
||||
|
||||
const int psbchSuccess = nr_ue_psbch_procedures(ue, fp, proc, estimateSz,
|
||||
dl_ch_estimates, phy_data, rxdataF);
|
||||
|
||||
if (ue->no_timing_correction==0 && psbchSuccess == 0) {
|
||||
LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
|
||||
nr_adjust_synch_ue(fp,
|
||||
ue,
|
||||
proc->gNB_id,
|
||||
fp->ofdm_symbol_size,
|
||||
dl_ch_estimates_time,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
0,
|
||||
16384);
|
||||
}
|
||||
ue->apply_timing_offset = true;
|
||||
|
||||
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
|
||||
// nr_ue_rrc_measurements(ue, proc, rxdataF);
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PSBCH, VCD_FUNCTION_OUT);
|
||||
|
||||
if (frame_rx%64 == 0) {
|
||||
LOG_I(NR_PHY,"============================================\n");
|
||||
|
||||
LOG_I(NR_PHY,"[UE%d] %d:%d PSBCH Stats: TX %d, RX ok %d, RX not ok %d\n",
|
||||
ue->Mod_id, frame_rx, nr_slot_rx,
|
||||
sl_phy_params->psbch.num_psbch_tx,
|
||||
sl_phy_params->psbch.rx_ok,
|
||||
sl_phy_params->psbch.rx_errors);
|
||||
|
||||
LOG_I(NR_PHY,"============================================\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
nr_phy_data_tx_t *phy_data)
|
||||
{
|
||||
|
||||
int slot_tx = proc->nr_slot_tx;
|
||||
int frame_tx = proc->frame_tx;
|
||||
int tx_action = 0;
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS;
|
||||
NR_DL_FRAME_PARMS *fp = &sl_phy_params->sl_frame_params;
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_SL,VCD_FUNCTION_IN);
|
||||
|
||||
const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * fp->ofdm_symbol_size;
|
||||
c16_t txdataF_buf[fp->nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32)));
|
||||
memset(txdataF_buf, 0, sizeof(txdataF_buf));
|
||||
c16_t *txdataF[fp->nb_antennas_tx]; /* workaround to be compatible with current txdataF usage in all tx procedures. */
|
||||
for(int i=0; i< fp->nb_antennas_tx; ++i)
|
||||
txdataF[i] = &txdataF_buf[i * samplesF_per_slot];
|
||||
|
||||
LOG_D(PHY,"****** start Sidelink TX-Chain for AbsSubframe %d.%d ******\n",
|
||||
frame_tx, slot_tx);
|
||||
|
||||
start_meas(&sl_phy_params->phy_proc_sl_tx);
|
||||
|
||||
if (phy_data->sl_tx_action == SL_NR_CONFIG_TYPE_TX_PSBCH) {
|
||||
sl_nr_tx_config_psbch_pdu_t *psbch_vars = &phy_data->psbch_vars;
|
||||
nr_tx_psbch(ue, frame_tx, slot_tx, psbch_vars, txdataF);
|
||||
sl_phy_params->psbch.num_psbch_tx ++;
|
||||
|
||||
if (frame_tx%64 == 0) {
|
||||
LOG_I(NR_PHY,"============================================\n");
|
||||
|
||||
LOG_I(NR_PHY,"[UE%d] %d:%d PSBCH Stats: TX %d, RX ok %d, RX not ok %d\n",
|
||||
ue->Mod_id, frame_tx, slot_tx,
|
||||
sl_phy_params->psbch.num_psbch_tx,
|
||||
sl_phy_params->psbch.rx_ok,
|
||||
sl_phy_params->psbch.rx_errors);
|
||||
|
||||
LOG_I(NR_PHY,"============================================\n");
|
||||
}
|
||||
tx_action = 1;
|
||||
}
|
||||
|
||||
if (tx_action) {
|
||||
LOG_D(PHY, "Sending Uplink data \n");
|
||||
nr_ue_pusch_common_procedures(ue,
|
||||
proc->nr_slot_tx,
|
||||
fp,
|
||||
fp->nb_antennas_tx,
|
||||
txdataF);
|
||||
}
|
||||
|
||||
LOG_D(PHY,"****** end Sidelink TX-Chain for AbsSubframe %d.%d ******\n",
|
||||
frame_tx, slot_tx);
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_SL, VCD_FUNCTION_OUT);
|
||||
stop_meas(&sl_phy_params->phy_proc_sl_tx);
|
||||
|
||||
return tx_action;
|
||||
}
|
||||
@@ -797,12 +797,13 @@ int main(int argc, char **argv)
|
||||
proc.gNB_id = 0;
|
||||
for (int i=UE->symbol_offset+1; i<UE->symbol_offset+4; i++) {
|
||||
nr_slot_fep(UE,
|
||||
frame_parms,
|
||||
&proc,
|
||||
i%frame_parms->symbols_per_slot,
|
||||
rxdataF);
|
||||
rxdataF, link_type_dl);
|
||||
|
||||
nr_pbch_channel_estimation(UE,estimateSz, dl_ch_estimates, dl_ch_estimates_time, &proc,
|
||||
i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf,rxdataF);
|
||||
nr_pbch_channel_estimation(UE,&UE->frame_parms, estimateSz, dl_ch_estimates, dl_ch_estimates_time, &proc,
|
||||
i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf,rxdataF,false,frame_parms->Nid_cell);
|
||||
|
||||
}
|
||||
fapiPbch_t result;
|
||||
|
||||
630
openair1/SIMULATION/NR_PHY/psbchsim.c
Normal file
630
openair1/SIMULATION/NR_PHY/psbchsim.c
Normal file
@@ -0,0 +1,630 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/phy_vars.h"
|
||||
#include "NR_MasterInformationBlockSidelink.h"
|
||||
#include "PHY/INIT/phy_init.h"
|
||||
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "openair1/SIMULATION/TOOLS/sim.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "openair2/RRC/NR/nr_rrc_extern.h"
|
||||
#include "openair2/RRC/LTE/rrc_vars.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "SIMULATION/RF/rf.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
void exit_function(const char* file, const char* function, const int line, const char* s, const int assert) {
|
||||
const char * msg= s==NULL ? "no comment": s;
|
||||
printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg);
|
||||
exit(-1);
|
||||
}
|
||||
int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) { return 1; }
|
||||
// to solve link errors
|
||||
double cpuf;
|
||||
//void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {}
|
||||
void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu,
|
||||
uint8_t *nb_dmrs_re_per_rb,
|
||||
uint16_t *number_dmrs_symbols){}
|
||||
uint64_t downlink_frequency[1][1];
|
||||
int32_t uplink_frequency_offset[1][1];
|
||||
THREAD_STRUCT thread_struct;
|
||||
instance_t DUuniqInstance=0;
|
||||
instance_t CUuniqInstance=0;
|
||||
openair0_config_t openair0_cfg[1];
|
||||
|
||||
RAN_CONTEXT_t RC;
|
||||
int oai_exit = 0;
|
||||
char *uecap_file;
|
||||
|
||||
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
|
||||
const int CC_id,
|
||||
const uint8_t gNB_id,
|
||||
const frame_t frameP,
|
||||
const rb_id_t Srb_id,
|
||||
uint8_t *buffer_pP)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nr_bler_struct nr_bler_data[NR_NUM_MCS];
|
||||
void get_nrUE_params(void) { return;}
|
||||
uint8_t check_if_ue_is_sl_syncsource() {return 0;}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static void prepare_mib_bits(uint8_t *buf, uint32_t frame_tx, uint32_t slot_tx) {
|
||||
|
||||
NR_MasterInformationBlockSidelink_t *sl_mib;
|
||||
asn_enc_rval_t enc_rval;
|
||||
|
||||
void *buffer = (void *)buf;
|
||||
|
||||
sl_mib = CALLOC(1, sizeof(NR_MasterInformationBlockSidelink_t));
|
||||
|
||||
sl_mib->inCoverage_r16 = 0;//TRUE;
|
||||
|
||||
// allocate buffer for 7 bits slotnumber
|
||||
sl_mib->slotIndex_r16.size = 1;
|
||||
sl_mib->slotIndex_r16.buf = CALLOC(1, sl_mib->slotIndex_r16.size);
|
||||
sl_mib->slotIndex_r16.bits_unused = sl_mib->slotIndex_r16.size*8 - 7;
|
||||
sl_mib->slotIndex_r16.buf[0] = slot_tx << sl_mib->slotIndex_r16.bits_unused;
|
||||
|
||||
sl_mib->directFrameNumber_r16.size = 2;
|
||||
sl_mib->directFrameNumber_r16.buf = CALLOC(1, sl_mib->directFrameNumber_r16.size);
|
||||
sl_mib->directFrameNumber_r16.bits_unused = sl_mib->directFrameNumber_r16.size*8 - 10;
|
||||
sl_mib->directFrameNumber_r16.buf[0] = frame_tx >> (8 - sl_mib->directFrameNumber_r16.bits_unused);
|
||||
sl_mib->directFrameNumber_r16.buf[1] = frame_tx << sl_mib->directFrameNumber_r16.bits_unused;
|
||||
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_MasterInformationBlockSidelink,
|
||||
NULL,
|
||||
(void *)sl_mib,
|
||||
buffer,
|
||||
100);
|
||||
|
||||
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
|
||||
asn_DEF_NR_MasterInformationBlockSidelink.op->free_struct(&asn_DEF_NR_MasterInformationBlockSidelink, sl_mib, ASFM_FREE_EVERYTHING);
|
||||
|
||||
}
|
||||
|
||||
static int test_rx_mib(uint8_t *decoded_output, uint16_t frame, uint16_t slot) {
|
||||
|
||||
uint32_t sl_mib = *(uint32_t *)decoded_output;
|
||||
|
||||
uint32_t fn = 0, sl = 0;
|
||||
fn = (((sl_mib & 0x0700) >> 1) | ((sl_mib & 0xFE0000) >> 17));
|
||||
sl = (((sl_mib & 0x010000) >> 10) | ((sl_mib & 0xFC000000) >> 26));
|
||||
|
||||
printf("decoded output:%x, TX %d:%d, timing decoded from sl-MIB %d:%d\n",
|
||||
*(uint32_t *)decoded_output, frame, slot, fn, sl);
|
||||
|
||||
if (frame == fn && slot == sl)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void configure_NR_UE(PHY_VARS_NR_UE *UE, int mu, int N_RB) {
|
||||
|
||||
fapi_nr_config_request_t config;
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
|
||||
config.ssb_config.scs_common = mu;
|
||||
config.cell_config.frame_duplex_type = TDD;
|
||||
config.carrier_config.dl_grid_size[mu] = N_RB;
|
||||
config.carrier_config.ul_grid_size[mu] = N_RB;
|
||||
config.carrier_config.dl_frequency = 0;
|
||||
config.carrier_config.uplink_frequency = 0;
|
||||
|
||||
int band;
|
||||
if (mu == 1) band = 78;
|
||||
if (mu == 0) band = 34;
|
||||
nr_init_frame_parms_ue(fp, &config, band);
|
||||
fp->ofdm_offset_divisor = 8;
|
||||
nr_dump_frame_parms(fp);
|
||||
|
||||
if (init_nr_ue_signal(UE, 1) != 0) {
|
||||
printf("Error at UE NR initialisation\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static void sl_init_frame_parameters(PHY_VARS_NR_UE *UE)
|
||||
{
|
||||
|
||||
NR_DL_FRAME_PARMS *nr_fp = &UE->frame_parms;
|
||||
NR_DL_FRAME_PARMS *sl_fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
memcpy(sl_fp, nr_fp, sizeof(NR_DL_FRAME_PARMS));
|
||||
sl_fp->ofdm_offset_divisor = 8; // What is this used for?
|
||||
|
||||
sl_fp->att_tx = 1;
|
||||
sl_fp->att_rx = 1;
|
||||
// band47 //UL freq will be set to Sidelink freq
|
||||
sl_fp->ul_CarrierFreq = 5880000000;
|
||||
|
||||
sl_fp->ssb_start_subcarrier = UE->SL_UE_PHY_PARAMS.sl_config.sl_bwp_config.sl_ssb_offset_point_a;
|
||||
sl_fp->Nid_cell = UE->SL_UE_PHY_PARAMS.sl_config.sl_sync_source.rx_slss_id;
|
||||
|
||||
#ifdef DEBUG_INIT
|
||||
LOG_I(PHY, "Dumping Sidelink Frame Parameters\n");
|
||||
nr_dump_frame_parms(sl_fp);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void configure_SL_UE(PHY_VARS_NR_UE *UE, int mu, int N_RB, int ssb_offset, int slss_id) {
|
||||
|
||||
sl_nr_phy_config_request_t *config = &UE->SL_UE_PHY_PARAMS.sl_config;
|
||||
NR_DL_FRAME_PARMS *fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
config->sl_bwp_config.sl_scs = mu;
|
||||
config->sl_bwp_config.sl_ssb_offset_point_a = ssb_offset;
|
||||
config->sl_carrier_config.sl_bandwidth = N_RB;
|
||||
config->sl_carrier_config.sl_grid_size = 106;
|
||||
config->sl_sync_source.rx_slss_id = slss_id;
|
||||
|
||||
sl_init_frame_parameters(UE);
|
||||
sl_ue_phy_init(UE);
|
||||
init_symbol_rotation(fp);
|
||||
init_timeshift_rotation(fp);
|
||||
LOG_I(PHY, "Dumping Sidelink Frame Parameters\n");
|
||||
nr_dump_frame_parms(fp);
|
||||
}
|
||||
|
||||
static int freq_domain_loopback(PHY_VARS_NR_UE *UE_tx, PHY_VARS_NR_UE *UE_rx,
|
||||
int frame, int slot,
|
||||
nr_phy_data_tx_t *phy_data) {
|
||||
|
||||
sl_nr_ue_phy_params_t *sl_ue1 = &UE_tx->SL_UE_PHY_PARAMS;
|
||||
sl_nr_ue_phy_params_t *sl_ue2 = &UE_rx->SL_UE_PHY_PARAMS;
|
||||
|
||||
printf("\nPSBCH SIM -F: %d:%d slss id TX UE:%d, RX UE:%d\n",
|
||||
frame, slot,phy_data->psbch_vars.tx_slss_id,
|
||||
sl_ue2->sl_config.sl_sync_source.rx_slss_id);
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &sl_ue1->sl_frame_params;
|
||||
const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * fp->ofdm_symbol_size;
|
||||
c16_t txdataF_buf[fp->nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32)));
|
||||
memset(txdataF_buf, 0, sizeof(txdataF_buf));
|
||||
c16_t *txdataF[fp->nb_antennas_tx]; /* workaround to be compatible with current txdataF usage in all tx procedures. */
|
||||
for(int i=0; i< fp->nb_antennas_tx; ++i)
|
||||
txdataF[i] = &txdataF_buf[i * samplesF_per_slot];
|
||||
|
||||
nr_tx_psbch(UE_tx,frame, slot, &phy_data->psbch_vars, txdataF);
|
||||
|
||||
int estimateSz = sl_ue2->sl_frame_params.samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) struct complex16 rxdataF[1][estimateSz];
|
||||
for (int i=0; i<sl_ue1->sl_frame_params.samples_per_slot_wCP; i++) {
|
||||
struct complex16 *txdataF_ptr = (struct complex16 *)&txdataF[0][i];
|
||||
struct complex16 *rxdataF_ptr = (struct complex16 *)&rxdataF[0][i];
|
||||
rxdataF_ptr->r = txdataF_ptr->r;
|
||||
rxdataF_ptr->i = txdataF_ptr->i;
|
||||
//printf("r,i TXDATAF[%d]- %d:%d, RXDATAF[%d]- %d:%d\n",
|
||||
// i, txdataF_ptr->r, txdataF_ptr->i, i, txdataF_ptr->r, txdataF_ptr->i);
|
||||
}
|
||||
|
||||
uint8_t err_status = 0;
|
||||
|
||||
UE_nr_rxtx_proc_t proc;
|
||||
proc.frame_rx = frame;
|
||||
proc.nr_slot_rx = slot;
|
||||
|
||||
struct complex16 dl_ch_estimates[1][estimateSz];
|
||||
uint8_t decoded_output[4] = {0};
|
||||
|
||||
LOG_I(PHY,"DEBUG: HIJACKING DL CHANNEL ESTIMATES.\n");
|
||||
for (int s=0; s<14; s++) {
|
||||
for (int j=0; j<sl_ue2->sl_frame_params.ofdm_symbol_size; j++) {
|
||||
struct complex16 *dlch = (struct complex16 *)(&dl_ch_estimates[0][s*sl_ue2->sl_frame_params.ofdm_symbol_size]);
|
||||
dlch[j].r = 128;
|
||||
dlch[j].i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
err_status = nr_rx_psbch(UE_rx,
|
||||
&proc,
|
||||
estimateSz,
|
||||
dl_ch_estimates,
|
||||
&sl_ue2->sl_frame_params,
|
||||
decoded_output,
|
||||
rxdataF,
|
||||
sl_ue2->sl_config.sl_sync_source.rx_slss_id);
|
||||
|
||||
|
||||
int error_payload = 0;
|
||||
error_payload = test_rx_mib(decoded_output, frame, slot);
|
||||
|
||||
if (err_status == 0 || error_payload == 0) {
|
||||
LOG_I(PHY,"---------PSBCH -F TEST OK.\n");
|
||||
return 0;
|
||||
}
|
||||
LOG_E(PHY, "--------PSBCH -F TEST NOK. FAIL.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PHY_VARS_NR_UE *UE_TX; // for tx
|
||||
PHY_VARS_NR_UE *UE_RX; // for rx
|
||||
double cpuf;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char c;
|
||||
int test_freqdomain_loopback = 0;
|
||||
int frame = 5, slot = 10, frame_tx = 0, slot_tx = 0;
|
||||
int loglvl = OAILOG_INFO;
|
||||
uint16_t slss_id = 336, ssb_offset = 0;
|
||||
double snr1 = 2.0, snr0 = 2.0, SNR;
|
||||
double sigma2 = 0.0, sigma2_dB = 0.0;
|
||||
double cfo=0, ip =0.0;
|
||||
|
||||
SCM_t channel_model=AWGN;//Rayleigh1_anticorr;
|
||||
int N_RB_DL=106,mu=1;
|
||||
|
||||
uint16_t errors = 0, n_trials = 1;
|
||||
|
||||
int frame_length_complex_samples;
|
||||
//int frame_length_complex_samples_no_prefix;
|
||||
NR_DL_FRAME_PARMS *frame_parms;
|
||||
|
||||
int seed = 0;
|
||||
|
||||
cpuf = get_cpu_freq_GHz();
|
||||
|
||||
if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0 ) {
|
||||
exit_fun("SIDELINK PSBCH SIM Error, configuration module init failed\n");
|
||||
}
|
||||
|
||||
randominit(0);
|
||||
|
||||
while ((c = getopt(argc, argv, "c:hn:o:s:FL:N:R:S:T:")) != -1) {
|
||||
|
||||
printf("SIDELINK PSBCH SIM: handling optarg %c\n",c);
|
||||
switch (c) {
|
||||
|
||||
case 'c':
|
||||
cfo = atof(optarg);
|
||||
printf("Setting CFO to %f Hz\n",cfo);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
switch((char)*optarg) {
|
||||
case 'A':
|
||||
channel_model=SCM_A;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
channel_model=SCM_B;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
channel_model=SCM_C;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
channel_model=SCM_D;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
channel_model=EPA;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
channel_model=EVA;
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
channel_model=ETU;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unsupported channel model! Exiting.\n");
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
n_trials = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
ssb_offset = atoi(optarg);
|
||||
printf("SIDELINK PSBCH SIM: ssb offset from pointA:%d\n",ssb_offset);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
slss_id = atoi(optarg);
|
||||
printf("SIDELINK PSBCH SIM: slss_id from arg:%d\n",slss_id);
|
||||
AssertFatal(slss_id >= 0 && slss_id <= 671,"SLSS ID not within Range 0-671\n");
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
test_freqdomain_loopback = 1;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
loglvl = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
snr0 = atoi(optarg);
|
||||
snr1 = snr0;
|
||||
printf("Setting SNR0 to %f. Test uses this SNR as target SNR\n",snr0);
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
N_RB_DL = atoi(optarg);
|
||||
printf("SIDELINK PSBCH SIM: N_RB_DL:%d\n",N_RB_DL);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
snr1 = atof(optarg);
|
||||
printf("Setting SNR1 to %f. Test will run until this SNR as target SNR\n",snr1);
|
||||
AssertFatal(snr1 <= snr0, "Test runs SNR down, set snr1 to a lower value than %f\n", snr0);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
frame = atoi(argv[2]);
|
||||
slot = atoi(argv[3]);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
default :
|
||||
printf("\n\nSIDELINK PSBCH SIM OPTIONS LIST - hus:FL:T:\n");
|
||||
printf("-h: HELP\n");
|
||||
printf("-c Carrier frequency offset in Hz\n");
|
||||
printf("-n Number of trials\n");
|
||||
printf("-o ssb offset from PointA - indicates ssb_start subcarrier\n");
|
||||
printf("-s: set Sidelink sync id slss_id. ex -s 100\n");
|
||||
printf("-F: Run PSBCH frequency domain loopback test of the samples\n");
|
||||
printf("-L: Set Log Level.\n");
|
||||
printf("-N: Test with Noise. target SNR0 eg -N 10\n");
|
||||
printf("-R N_RB_DL\n");
|
||||
printf("-S Ending SNR, runs from SNR0 to SNR1\n");
|
||||
printf("-T: Frame,Slot to be sent in sl-MIB eg -T 4 2\n");
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
randominit(seed);
|
||||
|
||||
logInit();
|
||||
set_glog(loglvl);
|
||||
T_stdout = 1;
|
||||
|
||||
double fs=0, eps;
|
||||
double scs = 30000;
|
||||
double bw = 100e6;
|
||||
|
||||
switch (mu) {
|
||||
case 1:
|
||||
scs = 30000;
|
||||
if (N_RB_DL == 217) {
|
||||
fs = 122.88e6;
|
||||
bw = 80e6;
|
||||
}
|
||||
else if (N_RB_DL == 245) {
|
||||
fs = 122.88e6;
|
||||
bw = 90e6;
|
||||
}
|
||||
else if (N_RB_DL == 273) {
|
||||
fs = 122.88e6;
|
||||
bw = 100e6;
|
||||
}
|
||||
else if (N_RB_DL == 106) {
|
||||
fs = 61.44e6;
|
||||
bw = 40e6;
|
||||
}
|
||||
else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);
|
||||
break;
|
||||
case 3:
|
||||
scs = 120000;
|
||||
if (N_RB_DL == 66) {
|
||||
fs = 122.88e6;
|
||||
bw = 100e6;
|
||||
}
|
||||
else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);
|
||||
break;
|
||||
}
|
||||
|
||||
// cfo with respect to sub-carrier spacing
|
||||
eps = cfo/scs;
|
||||
|
||||
// computation of integer and fractional FO to compare with estimation results
|
||||
int IFO;
|
||||
if(eps!=0.0){
|
||||
printf("Introducing a CFO of %lf relative to SCS of %d kHz\n",eps,(int)(scs/1000));
|
||||
if (eps>0)
|
||||
IFO=(int)(eps+0.5);
|
||||
else
|
||||
IFO=(int)(eps-0.5);
|
||||
printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO);
|
||||
}
|
||||
|
||||
channel_desc_t *UE2UE;
|
||||
int n_tx = 1, n_rx = 1;
|
||||
UE2UE = new_channel_desc_scm(n_tx,
|
||||
n_rx,
|
||||
channel_model,
|
||||
fs,
|
||||
0,
|
||||
bw,
|
||||
300e-9,
|
||||
0.0,
|
||||
CORR_LEVEL_LOW,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
|
||||
if (UE2UE==NULL) {
|
||||
printf("Problem generating channel model. Exiting.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*****configure UE *************************/
|
||||
UE_TX = calloc(1, sizeof(PHY_VARS_NR_UE));
|
||||
UE_RX = calloc(1, sizeof(PHY_VARS_NR_UE));
|
||||
LOG_I(PHY, "Configure UE-TX and sidelink UE-TX.\n");
|
||||
configure_NR_UE(UE_TX, mu, N_RB_DL);
|
||||
configure_SL_UE(UE_TX, mu, N_RB_DL,ssb_offset, 0xFFFF);
|
||||
|
||||
LOG_I(PHY, "Configure UE-RX and sidelink UE-RX.\n");
|
||||
configure_NR_UE(UE_RX, mu, N_RB_DL);
|
||||
configure_SL_UE(UE_RX, mu, N_RB_DL,ssb_offset, slss_id);
|
||||
/*****************************************/
|
||||
sl_nr_ue_phy_params_t *sl_uetx = &UE_TX->SL_UE_PHY_PARAMS;
|
||||
sl_nr_ue_phy_params_t *sl_uerx = &UE_RX->SL_UE_PHY_PARAMS;
|
||||
frame_parms = &sl_uetx->sl_frame_params;
|
||||
frame_tx = frame % 1024;
|
||||
slot_tx = slot % frame_parms->slots_per_frame;
|
||||
|
||||
frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
//frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP;
|
||||
|
||||
double **s_re,**s_im,**r_re,**r_im;
|
||||
s_re = malloc(2*sizeof(double*));
|
||||
s_im = malloc(2*sizeof(double*));
|
||||
r_re = malloc(2*sizeof(double*));
|
||||
r_im = malloc(2*sizeof(double*));
|
||||
|
||||
s_re[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
s_im[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
r_re[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
r_im[0] = malloc16_clear(frame_length_complex_samples*sizeof(double));
|
||||
|
||||
if(eps!=0.0)
|
||||
UE_RX->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation
|
||||
|
||||
UE_nr_rxtx_proc_t proc;
|
||||
proc.frame_tx = frame;
|
||||
proc.nr_slot_tx = slot;
|
||||
nr_phy_data_tx_t phy_data_tx;
|
||||
phy_data_tx.psbch_vars.tx_slss_id = slss_id;
|
||||
|
||||
uint8_t sl_mib[4] = {0};
|
||||
prepare_mib_bits(sl_mib,frame, slot);
|
||||
memcpy(phy_data_tx.psbch_vars.psbch_payload,sl_mib, 4);
|
||||
|
||||
phy_data_tx.sl_tx_action = SL_NR_CONFIG_TYPE_TX_PSBCH;
|
||||
proc.frame_rx = frame;
|
||||
proc.nr_slot_rx = slot;
|
||||
nr_phy_data_t phy_data_rx;
|
||||
phy_data_rx.sl_rx_action = SL_NR_CONFIG_TYPE_RX_PSBCH;
|
||||
|
||||
if (test_freqdomain_loopback) {
|
||||
errors += freq_domain_loopback(UE_TX, UE_RX, frame_tx, slot_tx, &phy_data_tx);
|
||||
}
|
||||
|
||||
printf("\nSidelink TX UE - Frame.Slot %d.%d SLSS id:%d\n",
|
||||
frame, slot,phy_data_tx.psbch_vars.tx_slss_id);
|
||||
printf("Sidelink RX UE - Frame.Slot %d.%d SLSS id:%d\n",
|
||||
proc.frame_rx, proc.nr_slot_rx,
|
||||
sl_uerx->sl_config.sl_sync_source.rx_slss_id);
|
||||
|
||||
phy_procedures_nrUE_SL_TX(UE_TX, &proc, &phy_data_tx);
|
||||
|
||||
for (SNR=snr0; SNR>=snr1; SNR-=1) {
|
||||
|
||||
for (int trial=0; trial<n_trials; trial++) {
|
||||
|
||||
for (int i=0; i<frame_length_complex_samples; i++) {
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
|
||||
struct complex16 *txdata_ptr = (struct complex16 *)&UE_TX->common_vars.txData[aa][i];
|
||||
r_re[aa][i] = (double)txdata_ptr->r;
|
||||
r_im[aa][i] = (double)txdata_ptr->i;
|
||||
}
|
||||
}
|
||||
|
||||
//AWGN
|
||||
sigma2_dB = 20*log10((double)AMP/4)-SNR;
|
||||
sigma2 = pow(10,sigma2_dB/10);
|
||||
//printf("sigma2 %f (%f dB), tx_lev %f (%f dB)\n",sigma2,sigma2_dB,txlev,10*log10((double)txlev));
|
||||
|
||||
if(eps!=0.0) {
|
||||
rf_rx(r_re, // real part of txdata
|
||||
r_im, // imag part of txdata
|
||||
NULL, // interference real part
|
||||
NULL, // interference imag part
|
||||
0, // interference power
|
||||
frame_parms->nb_antennas_rx, // number of rx antennas
|
||||
frame_length_complex_samples, // number of samples in frame
|
||||
1.0e9/fs, //sampling time (ns)
|
||||
cfo, // frequency offset in Hz
|
||||
0.0, // drift (not implemented)
|
||||
0.0, // noise figure (not implemented)
|
||||
0.0, // rx gain in dB ?
|
||||
200, // 3rd order non-linearity in dB ?
|
||||
&ip, // initial phase
|
||||
30.0e3, // phase noise cutoff in kHz
|
||||
-500.0, // phase noise amplitude in dBc
|
||||
0.0, // IQ imbalance (dB),
|
||||
0.0); // IQ phase imbalance (rad)
|
||||
}
|
||||
|
||||
for (int i=0; i<frame_length_complex_samples; i++) {
|
||||
for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
||||
UE_RX->common_vars.rxdata[aa][i].r = (short)(r_re[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0));
|
||||
UE_RX->common_vars.rxdata[aa][i].i = (short)(r_im[aa][i] + sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0));
|
||||
}
|
||||
}
|
||||
|
||||
psbch_pscch_processing(UE_RX,&proc,&phy_data_rx);
|
||||
|
||||
} //noise trials
|
||||
|
||||
printf("Runs:%d SNR %f: crc ERRORs = %d, OK = %d\n",
|
||||
n_trials, SNR,sl_uerx->psbch.rx_errors, sl_uerx->psbch.rx_ok);
|
||||
errors += sl_uerx->psbch.rx_errors;
|
||||
sl_uerx->psbch.rx_errors = 0;
|
||||
sl_uerx->psbch.rx_ok = 0;
|
||||
|
||||
} // NSR
|
||||
|
||||
if (errors == 0)
|
||||
printf("PSBCH test OK\n");
|
||||
else
|
||||
printf("PSBCH test NOT OK\n");
|
||||
|
||||
free_channel_desc_scm(UE2UE);
|
||||
|
||||
free(s_re[0]);
|
||||
free(s_im[0]);
|
||||
free(r_re[0]);
|
||||
free(r_im[0]);
|
||||
free(s_re);
|
||||
free(s_im);
|
||||
free(r_re);
|
||||
free(r_im);
|
||||
|
||||
term_nr_ue_signal(UE_TX, 1);
|
||||
term_nr_ue_signal(UE_RX, 1);
|
||||
|
||||
free(UE_TX);
|
||||
free(UE_RX);
|
||||
logTerm();
|
||||
loader_reset();
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ typedef struct {
|
||||
uint32_t gNB_index;
|
||||
/// component carrier id
|
||||
int cc_id;
|
||||
/// frame
|
||||
/// frame rx
|
||||
frame_t frame_rx;
|
||||
/// slot rx
|
||||
uint32_t slot_rx;
|
||||
|
||||
Reference in New Issue
Block a user