Merge branch 'nr_initialsync' of https://gitlab.eurecom.fr/oai/openairinterface5g into nr_initialsync

This commit is contained in:
Guy De Souza
2018-05-30 15:33:46 +02:00
26 changed files with 10812 additions and 6 deletions
+76
View File
@@ -1267,6 +1267,12 @@ set(PHY_SRC_UE
# actual source
${OPENAIR1_DIR}/PHY/MODULATION/slot_fep.c
${OPENAIR1_DIR}/PHY/INIT/nr_parms.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pss_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dmrs_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c
${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c
${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c
@@ -2153,6 +2159,76 @@ target_link_libraries (nr-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRY
target_link_libraries (nr-softmodem ${LIB_LMS_LIBRARIES})
target_link_libraries (nr-softmodem ${T_LIB})
# nr-uesoftmodem is UE implementation
#######################################
add_executable(nr-uesoftmodem
${rrc_h}
${s1ap_h}
${OPENAIR_BIN_DIR}/messages_xml.h
${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
${OPENAIR_TARGETS}/RT/USER/nr-ue.c
${OPENAIR_TARGETS}/RT/USER/nr-uesoftmodem.c
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${XFORMS_SOURCE}
${XFORMS_SOURCE_SOFTMODEM}
${T_SOURCE}
${CONFIG_SOURCES}
${SHLIB_LOADER_SOURCES}
)
target_link_libraries (nr-uesoftmodem
-Wl,--start-group
RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_NR_UE PHY_COMMON PHY_UE PHY_RU LFDS L2_UE
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7
-Wl,--end-group z dl)
target_link_libraries (nr-uesoftmodem ${LIBXML2_LIBRARIES})
target_link_libraries (nr-uesoftmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
target_link_libraries (nr-uesoftmodem ${LIB_LMS_LIBRARIES})
target_link_libraries (nr-uesoftmodem ${T_LIB})
# nr-uesoftmodem is UE implementation
#######################################
add_executable(nr-uesoftmodem-nos1
${rrc_h}
${s1ap_h}
# ${OPENAIR_BIN_DIR}/messages_xml.h
${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
${OPENAIR_TARGETS}/RT/USER/nr-ue.c
${OPENAIR_TARGETS}/RT/USER/nr-uesoftmodem.c
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${XFORMS_SOURCE}
${XFORMS_SOURCE_SOFTMODEM}
${T_SOURCE}
${CONFIG_SOURCES}
${SHLIB_LOADER_SOURCES}
)
target_link_libraries (nr-uesoftmodem-nos1
-Wl,--start-group
RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_NR_UE PHY_COMMON PHY_UE PHY_RU LFDS L2_UE
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7
-Wl,--end-group z dl)
target_link_libraries (nr-uesoftmodem-nos1 ${LIBXML2_LIBRARIES})
target_link_libraries (nr-uesoftmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
target_link_libraries (nr-uesoftmodem-nos1 ${LIB_LMS_LIBRARIES})
target_link_libraries (nr-uesoftmodem-nos1 ${T_LIB})
# USIM process
#################
#add_executable(usim
+9
View File
@@ -23,6 +23,8 @@
#define __MODULATION_DEFS__H__
#include "PHY/defs_common.h"
#include "modulation_common.h"
#include "PHY/defs_UE.h"
#include "PHY/defs_nr_UE.h"
/** @addtogroup _PHY_MODULATION_
* @{
*/
@@ -46,6 +48,13 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue,
int no_prefix,
int reset_freq_est);
int slot_fep_pbch(PHY_VARS_NR_UE *phy_vars_ue,
unsigned char l,
unsigned char Ns,
int sample_offset,
int no_prefix,
int reset_freq_est);
int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue,
unsigned char l,
int subframe,
+202
View File
@@ -20,6 +20,7 @@
*/
#include "PHY/defs_UE.h"
#include "PHY/defs_nr_UE.h"
#include "modulation_UE.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
@@ -27,6 +28,207 @@
#define SOFFSET 0
int slot_fep_pbch(PHY_VARS_NR_UE *ue,
unsigned char l,
unsigned char Ns,
int sample_offset,
int no_prefix,
int reset_freq_est)
{
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
NR_UE_COMMON *common_vars = &ue->common_vars;
uint8_t eNB_id = 0;//ue_common_vars->eNb_id;
unsigned char aa;
unsigned char symbol = l+((7-frame_parms->Ncp)*(Ns&1)); ///symbol within sub-frame
unsigned int nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples);
unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0);
unsigned int subframe_offset;//,subframe_offset_F;
unsigned int slot_offset;
int i;
unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10;
unsigned int rx_offset;
/*LTE_UE_DLSCH_t **dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id];
unsigned char harq_pid = dlsch_ue[0]->current_harq_pid;
LTE_DL_UE_HARQ_t *dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid];
int uespec_pilot[9][1200];*/
void (*dft)(int16_t *,int16_t *, int);
int tmp_dft_in[2048] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs
switch (frame_parms->ofdm_symbol_size) {
case 128:
dft = dft128;
break;
case 256:
dft = dft256;
break;
case 512:
dft = dft512;
break;
case 1024:
dft = dft1024;
break;
case 1536:
dft = dft1536;
break;
case 2048:
dft = dft2048;
break;
default:
dft = dft512;
break;
}
if (no_prefix) {
subframe_offset = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_tti * (Ns>>1);
slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_tti>>1) * (Ns%2);
} else {
subframe_offset = frame_parms->samples_per_tti * (Ns>>1);
slot_offset = (frame_parms->samples_per_tti>>1) * (Ns%2);
}
if (l<0 || l>=7-frame_parms->Ncp) {
printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp);
return(-1);
}
if (Ns<0 || Ns>=20) {
printf("slot_fep: Ns must be between 0 and 19\n");
return(-1);
}
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
memset(&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int));
rx_offset = sample_offset + slot_offset + nb_prefix_samples0 + subframe_offset - SOFFSET;
// Align with 256 bit
// rx_offset = rx_offset&0xfffffff8;
if (l==0) {
if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size))
memcpy((short *)&common_vars->rxdata[aa][frame_length_samples],
(short *)&common_vars->rxdata[aa][0],
frame_parms->ofdm_symbol_size*sizeof(int));
if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs
memcpy((void *)tmp_dft_in,
(void *)&common_vars->rxdata[aa][rx_offset % frame_length_samples],
frame_parms->ofdm_symbol_size*sizeof(int));
dft((int16_t *)tmp_dft_in,
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
} else { // use dft input from RX buffer directly
#if UE_TIMING_TRACE
start_meas(&ue->rx_dft_stats);
#endif
dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
#if UE_TIMING_TRACE
stop_meas(&ue->rx_dft_stats);
#endif
}
} else {
rx_offset += (frame_parms->ofdm_symbol_size+nb_prefix_samples)*l;// +
// (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1);
#ifdef DEBUG_FEP
// if (ue->frame <100)
LOG_I(PHY,"slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol,
nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples);
#endif
if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size))
memcpy((void *)&common_vars->rxdata[aa][frame_length_samples],
(void *)&common_vars->rxdata[aa][0],
frame_parms->ofdm_symbol_size*sizeof(int));
#if UE_TIMING_TRACE
start_meas(&ue->rx_dft_stats);
#endif
if ((rx_offset&7)!=0) { // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs
memcpy((void *)tmp_dft_in,
(void *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
frame_parms->ofdm_symbol_size*sizeof(int));
dft((int16_t *)tmp_dft_in,
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
} else { // use dft input from RX buffer directly
dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
(int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
}
#if UE_TIMING_TRACE
stop_meas(&ue->rx_dft_stats);
#endif
}
#ifdef DEBUG_FEP
// if (ue->frame <100)
printf("slot_fep: frame %d: symbol %d rx_offset %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx, symbol,rx_offset);
#endif
}
if (ue->perfect_ce == 0) {
if ((l==0) || (l==(4-frame_parms->Ncp))) {
for (aa=0; aa<frame_parms->nb_antenna_ports_eNB; aa++) {
#ifdef DEBUG_FEP
printf("Channel estimation eNB %d, aatx %d, slot %d, symbol %d\n",eNB_id,aa,Ns,l);
#endif
#if UE_TIMING_TRACE
start_meas(&ue->dlsch_channel_estimation_stats);
#endif
/* nr_pbch_channel_estimation(ue,eNB_id,0,
Ns,
aa,
l,
symbol);*/
}
// do frequency offset estimation here!
// use channel estimates from current symbol (=ch_t) and last symbol (ch_{t-1})
#ifdef DEBUG_FEP
printf("Frequency offset estimation\n");
#endif
if (l==(4-frame_parms->Ncp)) {
#if UE_TIMING_TRACE
start_meas(&ue->dlsch_freq_offset_estimation_stats);
#endif
/*lte_est_freq_offset(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[0],
frame_parms,
l,
&common_vars->freq_offset,
reset_freq_est);*/
#if UE_TIMING_TRACE
stop_meas(&ue->dlsch_freq_offset_estimation_stats);
#endif
}
}
}
#ifdef DEBUG_FEP
printf("slot_fep: done\n");
#endif
return(0);
}
int slot_fep(PHY_VARS_UE *ue,
unsigned char l,
+234
View File
@@ -0,0 +1,234 @@
/*
* 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
*/
/***********************************************************************
*
* FILENAME : ul_ref_seq_nr.c
*
* MODULE : generation of uplink reference sequence for nr
*
* DESCRIPTION : function to generate uplink reference sequences
* see 3GPP TS 38.211 5.2.2 Low-PAPR sequence generation
*
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "defs.h"
#define DEFINE_VARIABLES_LOWPAPR_SEQUENCES_NR_H
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
#undef DEFINE_VARIABLES_LOWPAPR_SEQUENCES_NR_H
/*******************************************************************
*
* NAME : base_sequence_less_3_RB
*
* PARAMETERS : M_ZC length of Zadoff Chu sequence
* u sequence group number
* scaling to apply
*
* RETURN : pointer to generated sequence
*
* DESCRIPTION : base sequence generation of less than 36 elements
* see TS 38.211 5.2.2.2 Base sequences of length less than 36
*
*********************************************************************/
int16_t *base_sequence_less_than_36(unsigned int M_ZC, unsigned int u, unsigned int scaling)
{
char *phi_table;
int16_t *rv_overbar;
double x;
unsigned int n;
switch(M_ZC) {
case 6:
phi_table = (char *)phi_M_ZC_6;
break;
case 12:
phi_table = (char *)phi_M_ZC_12;
break;
case 18:
phi_table = (char *)phi_M_ZC_18;
break;
case 24:
phi_table = (char *)phi_M_ZC_24;
break;
case 30:
break;
default:
printf("function base_sequence_less_than 36_: unsupported base sequence size : %d \n", M_ZC);
assert(0);
break;
}
rv_overbar = malloc16(IQ_SIZE*M_ZC);
if (rv_overbar == NULL) {
msg("Fatal memory allocation problem \n");
assert(0);
}
if (M_ZC == 30) {
for (n=0; n<M_ZC; n++) {
x = -(M_PI * (u + 1) * (n + 1) * (n + 2))/(double)31;
rv_overbar[2*n] =(int16_t)(floor(scaling*cos(x)));
rv_overbar[2*n+1] =(int16_t)(floor(scaling*sin(x)));
}
}
else {
for (n=0; n<M_ZC; n++) {
x = (double)phi_table[n + u*M_ZC] * (M_PI/4);
rv_overbar[2*n] = (int16_t)(floor(scaling*cos(x)));
rv_overbar[2*n+1] = (int16_t)(floor(scaling*sin(x)));
}
}
return rv_overbar;
}
/*******************************************************************
*
* NAME : base_sequence_36_or_larger
*
* PARAMETERS : M_ZC length of Zadoff chu sequence
* u sequence group number
* scaling to apply
*
* RETURN : pointer to generated sequence
*
* DESCRIPTION : base sequence generation of less than 36 elements
* 5.2.2.1 Base sequences of length 36 or larger
*
*********************************************************************/
int16_t *base_sequence_36_or_larger(unsigned int Msc_RS, unsigned int u, unsigned int v, unsigned int scaling)
{
int16_t *rv_overbar;
unsigned int N_ZC;
double q_overbar, x;
unsigned int q,m,n;
unsigned int M_ZC = ul_allocated_re[Msc_RS];
rv_overbar = malloc16(IQ_SIZE*M_ZC);
if (rv_overbar == NULL) {
msg("Fatal memory allocation problem \n");
assert(0);
}
N_ZC = ref_ul_primes[Msc_RS]; /* The length N_ZC is given by the largest prime number such that N_ZC < M_ZC */
q_overbar = N_ZC * (u+1)/(double)31;
/* q = (q_overbar + 1/2) + v.(-1)^(2q_overbar) */
if ((((int)floor(2*q_overbar))&1) == 0)
q = (int)(floor(q_overbar+.5)) - v;
else
q = (int)(floor(q_overbar+.5)) + v;
for (n = 0; n < M_ZC; n++) {
m=n%N_ZC;
x = (double)q * m * (m+1)/N_ZC;
rv_overbar[2*n] = (int16_t)(floor(scaling*cos(M_PI*x))); /* cos(-x) = cos(x) */
rv_overbar[2*n+1] = -(int16_t)(floor(scaling*sin(M_PI*x))); /* sin(-x) = -sin(x) */
}
return rv_overbar;
}
/*******************************************************************
*
* NAME : generate_ul_srs_sequences
*
* PARAMETERS : scaling to apply
*
* RETURN : none
*
* DESCRIPTION : uplink reference signal sequences generation
* which are Low-PAPR base sequences
* see TS 38.211 5.2.2 Low-PAPR sequence generation
*
*********************************************************************/
void generate_ul_reference_signal_sequences(unsigned int scaling)
{
unsigned int u,v,Msc_RS;
#if 0
char output_file[255];
char sequence_name[255];
#endif
for (Msc_RS=0; Msc_RS <= INDEX_SB_LESS_32; Msc_RS++) {
v = 0;
for (u=0; u < U_GROUP_NUMBER; u++) {
rv_ul_ref_sig[u][v][Msc_RS] = base_sequence_less_than_36(ul_allocated_re[Msc_RS], u, scaling);
#if 0
sprintf(output_file, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]);
sprintf(sequence_name, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]);
printf("u %d Msc_RS %d allocate memory %x of size %d \n", u, Msc_RS, rv_ul_ref_sig[u][v][Msc_RS], (IQ_SIZE* ul_allocated_re[Msc_RS]));
write_output(output_file, sequence_name, rv_ul_ref_sig[u][v][Msc_RS], ul_allocated_re[Msc_RS], 1, 1);
#endif
}
}
for (Msc_RS=INDEX_SB_LESS_32+1; Msc_RS < SRS_SB_CONF; Msc_RS++) {
for (u=0; u < U_GROUP_NUMBER; u++) {
for (v=0; v < V_BASE_SEQUENCE_NUMBER; v++) {
rv_ul_ref_sig[u][v][Msc_RS] = base_sequence_36_or_larger(Msc_RS, u, v, scaling);
#if 0
sprintf(output_file, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]);
sprintf(sequence_name, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]);
printf("u %d Msc_RS %d allocate memory %x of size %d \n", u, Msc_RS, rv_ul_ref_sig[u][v][Msc_RS], (IQ_SIZE* ul_allocated_re[Msc_RS]));
write_output(output_file, sequence_name, rv_ul_ref_sig[u][v][Msc_RS], ul_allocated_re[Msc_RS], 1, 1);
#endif
}
}
}
}
/*******************************************************************
*
* NAME : free_ul_reference_signal_sequences
*
* PARAMETERS : none
*
* RETURN : none
*
* DESCRIPTION : free of uplink reference signal sequences
*
*********************************************************************/
void free_ul_reference_signal_sequences(void)
{
unsigned int u,v,Msc_RS;
for (Msc_RS=0; Msc_RS < SRS_SB_CONF; Msc_RS++) {
for (u=0; u < U_GROUP_NUMBER; u++) {
for (v=0; v < V_BASE_SEQUENCE_NUMBER; v++) {
if (rv_ul_ref_sig[u][v][Msc_RS])
free16(rv_ul_ref_sig[u][v][Msc_RS],2*sizeof(int16_t)*ul_allocated_re[Msc_RS]);
}
}
}
}
+271
View File
@@ -0,0 +1,271 @@
/*
* 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
*/
/***********************************************************************
*
* FILENAME : ul_ref_seq_nr.hh
*
* MODULE : generation of uplink reference sequence for nr
*
* DESCRIPTION : variables to generate sequences with low peak to average power
* see 3GPP TS 38.211 5.2.2 Low-PAPR sequence generation
*
************************************************************************/
#ifndef LOWPAPR_SEQUENCES_NR_H
#define LOWPAPR_SEQUENCES_NR_H
#include "PHY/defs_nr_UE.h"
#include "PHY/types.h"
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
#ifdef DEFINE_VARIABLES_LOWPAPR_SEQUENCES_NR_H
#define EXTERN
#define INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
#else
#define EXTERN extern
#endif
/************** DEFINE ********************************************/
#define U_GROUP_NUMBER (30) /* maximum number of sequence-group */
#define V_BASE_SEQUENCE_NUMBER (2) /* maximum number of base sequences */
#define SRS_SB_CONF (71) /* maximum number of configuration for srs subcarrier allocation */
/************** VARIABLES *****************************************/
#define INDEX_SB_LESS_32 (4) /* index of dftsizes array for which subcarrier number is less than 36 */
const uint16_t ul_allocated_re[SRS_SB_CONF] /* number of uplink allocated resource elements */
/* this table is derivated from TS 38.211 Table 6.4.1.4.3-1: SRS bandwidth configuration which gives m_SRS_b then all possible values of sequence length is */
/* M_sc_b_SRS = m_SRS_b * N_SC_RB/K_TC with K_TC = 2 or K_TC = 4 as specified in TS 38.211 6.4.1.4.3 */
#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
= { /*
K_TC 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
m_SRS_b 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 */
6, 12, 18, 24, 30, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, 168, 180, 192, 204, 216, 228, 240,
/*
K_TC 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 6 3 3
m_SRS_b 84 88 92 96 100 104 108 112 116 120 128 132 136 144 152 160 168 176 184 192 100 208 216 */
252, 264, 276, 288, 300, 312, 324, 336, 348, 360, 384, 396, 408, 432, 456, 480, 504, 528, 552, 576, 600, 624, 648,
/*
K_TC 3 6 3 3 3 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6
m_SRS_b 224 116, 240 256 264 272 144 152 160 168 176 184 192 208 216 224 240 256 264 272 */
672, 696, 720, 768, 792, 816, 864, 912, 960, 1008, 1056, 1104, 1152, 1248, 1296, 1344, 1440, 1536, 1584, 1632,
/* below numbers have been added just to include all possible lengths already used for lte */
540, 900, 972, 1080, 1200,
}
#endif
;
/* table of largest prime number lower than uplink allocated resource elements "ul_allocated_re" */
const uint16_t ref_ul_primes[SRS_SB_CONF]
#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
= {
/* 6, 12, 18, 24, 30, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, 168, 180, 192, 204, 216, 228, 240, */
5, 11, 17, 23, 29, 31, 47, 59, 71, 83, 89, 107, 113, 127, 139, 151, 167, 179, 191, 199, 211, 227, 239,
/* 252, 264, 276, 288, 300, 312, 324, 336, 348, 360, 384, 396, 408, 432, 456, 480, 504, 528, 552, 576, 600, 624, 648, */
251, 263, 271, 283, 293, 311, 317, 331, 347, 359, 383, 389, 401, 431, 449, 479, 503, 523, 547, 571, 599, 619, 647,
/* 672, 696, 720, 768, 792, 816, 864, 912, 960, 1008, 1056, 1104, 1152, 1248, 1296, 1344, 1440, 1536, 1584, 1632, */
661, 691, 719, 761, 787, 811, 863, 911, 953, 997, 1051, 1103, 1151, 1237, 1291, 1327, 1439, 1531, 1583, 1627,
/* 540, 900, 972, 1080, 1200, */
523, 887, 971, 1069, 1193,
}
#endif
;
/* Low-PAPR base sequence; see TS 38.211 clause 5.2.2 */
int16_t *rv_ul_ref_sig[U_GROUP_NUMBER][V_BASE_SEQUENCE_NUMBER][SRS_SB_CONF];
/* 38.211 table Table 5.2.2.2-1: Definition of phi(n) for M_ZC = 6 */
const char phi_M_ZC_6[6*U_GROUP_NUMBER]
#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
= {
/* 0 1 2 3 4 5 */
/* 0 */ -3, -1, 3, 3, -1, -3,
/* 1 */ -3, 3, -1, -1, 3, -3,
/* 2 */ -3, -3, -3, 3, 1, -3,
/* 3 */ 1, 1, 1, 3, -1, -3,
/* 4 */ 1, 1, 1, -3, -1, 3,
/* 5 */ -3, 1, -1, -3, -3, -3,
/* 6 */ -3, 1, 3, -3, -3, -3,
/* 7 */ -3, -1, 1, -3, 1, -1,
/* 8 */ -3, -1, -3, 1, -3, -3,
/* 9 */ -3, -3, 1, -3, 3, -3,
/* 10 */ -3, 1, 3, 1, -3, -3,
/* 11 */ -3, -1, -3, 1, 1, -3,
/* 12 */ 1, 1, 3, -1, -3, 3,
/* 13 */ 1, 1, 3, 3, -1, 3,
/* 14 */ 1, 1, 1, -3, 3, -1,
/* 15 */ -1, 1, 1, -1, 3, -3,
/* 16 */ -3, -1, -1, -1, 3, -1,
/* 17 */ -3, -3, -1, 1, -1, -3,
/* 18 */ -3, -3, -3, 1, -3, -1,
/* 19 */ -3, 1, 1, -3, -1, -3,
/* 20 */ -3, 3, -3, 1, 1, -3,
/* 21 */ -3, 1, -3, -3, -3, -1,
/* 22 */ 1, 1, -3, 3, 1, 3,
/* 23 */ 1, 1, -3, -3, 1, -3,
/* 24 */ 1, 1, 3, -1, 3, 3,
/* 25 */ 1, 1, -3, 1, 3, 3,
/* 26 */ 1, 1, -1, -1, 3, -1,
/* 27 */ 1, 1, -1, 3, -1, -1,
/* 28 */ 1, 1, -1, 3, -3, -1,
/* 29 */ 1, 1, -3, 1, -1, -1,
}
#endif
;
/* Table 5.2.2.2-2: Definition of phi ( n ) for M ZC = 12 */
const char phi_M_ZC_12[12*U_GROUP_NUMBER]
#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
= {
/* 0 1 2 3 4 5 6 7 8 9 10 11 */
/* 0 */ 1, -1, 3, 1, 1, -1, -1, -1, 1, 3, -3, 1,
/* 1 */ -1, -1, -1, -1, 1, -3, -1, 3, 3, -1, -3, 1,
/* 2 */ -3, 1, -3, -3, -3, 3, -3, -1, 1, 1, 1, -3,
/* 3 */ -3, 3, 1, 3, -3, 1, 1, 1, 1, 3, -3, 3,
/* 4 */ -3, 1, 3, -1, -1, -3, -3, -1, -1, 3, 1, -3,
/* 5 */ -1, 1, 1, -1, 1, 3, 3, -1, -1, -3, 1, -3,
/* 6 */ -3, -3, -1, 3, 3, 3, -3, 3, -3, 1, -1, -3,
/* 7 */ -3, 3, -3, 3, 3, -3, -1, -1, 3, 3, 1, -3,
/* 8 */ -3, -1, -3, -1, -1, -3, 3, 3, -1, -1, 1, -3,
/* 9 */ -3, 3, 3, 3, -1, -3, -3, -1, -3, 1, 3, -3,
/* 10 */ 1, 3, -3, 1, 3, 3, 3, 1, -1, 1, -1, 3,
/* 11 */ -1, -3, 3, -1, -3, -3, -3, -1, 1, -1, 1, -3,
/* 12 */ 3, 1, 3, 1, 3, -3, -1, 1, 3, 1, -1, -3,
/* 13 */ -3, -3, 3, 3, 3, -3, -1, 1, -3, 3, 1, -3,
/* 14 */ -3, -1, 1, -3, 1, 3, 3, 3, -1, -3, 3, 3,
/* 15 */ -3, -3, 3, 1, -3, -3, -3, -1, 3, -1, 1, 3,
/* 16 */ -1, 1, 3, -3, 1, -1, 1, -1, -1, -3, 1, -1,
/* 17 */ -3, -1, -1, 1, 3, 1, 1, -1, 1, -1, -3, 1,
/* 18 */ -3, -1, 3, -3, -3, -1, -3, 1, -1, -3, 3, 3,
/* 19 */ -3, -3, 3, -3, -1, 3, 3, 3, -1, -3, 1, -3,
/* 20 */ -3, 1, -1, -1, 3, 3, -3, -1, -1, -3, -1, -3,
/* 21 */ -3, 1, 3, 3, -1, -1, -3, 3, 3, -3, 3, -3,
/* 22 */ -3, -1, -1, -3, -3, -1, -3, 3, 1, 3, -1, -3,
/* 23 */ -3, -1, 3, 1, -3, -1, -3, 3, 1, 3, 3, 1,
/* 24 */ -3, 3, 3, 1, -3, 3, -1, 1, 3, -3, 3, -3,
/* 25 */ 3, -1, -3, 3, -3, -1, 3, 3, 3, -3, -1, -3,
/* 26 */ 1, -1, 3, -1, -1, -1, -3, -1, 1, 1, 1, -3,
/* 27 */ -3, 3, 1, -3, 1, 3, -1, -1, 1, 3, 3, 3,
/* 28 */ -3, 3, -3, 3, -3, -3, 3, -1, -1, 1, 3, -3,
/* 29 */ -3, 3, 1, -1, 3, 3, -3, 1, -1, 1, -1, 1,
}
#endif
;
/* Table 5.2.2.2-3: Definition of phi (n ) for M_ZC = 18 */
const char phi_M_ZC_18[18*U_GROUP_NUMBER]
#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
= {
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 */
/* 0 */ 3, -3, 3, -1, 1, 3, -3, -1, -3, -3, -1, -3, 3, 1, -1, 3, -3, 3,
/* 1 */ 3, -3, 1, 1, 3, -1, 1, -1, -1, -3, 1, 1, -1, 3, 3, -3, 3, -1,
/* 2 */ -3, 3, -1, -3, -1, -3, 1, 1, -3, -3, -1, -1, 3, -3, 1, 3, 1, 1,
/* 3 */ 1, 1, -1, -1, -3, -1, 1, -3, -3, -3, 1, -3, -1, -1, 1, -1, 3, 1,
/* 4 */ 1, 1, -3, 3, 3, 1, 3, -3, 3, -1, 1, 1, -1, 1, -3, -3, -1, 3,
/* 5 */ -3, -3, 1, -3, 3, 3, 3, -1, 3, 1, 1, -3, -3, -3, 3, -3, -1, -1,
/* 6 */ -1, 3, -1, -3, 3, 1, -3, -1, 3, -3, -1, -1, 1, 1, 1, -1, -1, -1,
/* 7 */ -3, 1, -3, -3, 1, -3, -3, 3, 1, -3, -1, -3, -3, -3, -1, 1, 1, 3,
/* 8 */ 1, -3, -1, -3, 3, 3, -1, -3, 1, -3, -3, -1, -3, -1, 1, 3, 3, 3,
/* 9 */ -3, 3, 1, -1, -1, -1, -1, 1, -1, 3, 3, -3, -1, 1, 3, -1, 3, -1,
/* 10 */ -3, -3, 1, -1, -1, 1, 1, -3, -1, 3, 3, 3, 3, -1, 3, 1, 3, 1,
/* 11 */ -3, -3, 3, 3, -3, 1, 3, -1, -3, 1, -1, -3, 3, -3, -1, -1, -1, 3,
/* 12 */ -3, -3, 3, 3, 3, 1, -3, 1, 3, 3, 1, -3, -3, 3, -1, -3, -1, 1,
/* 13 */ -3, 3, -1, 1, 3, 1, -3, -1, 1, 1, -3, 1, 3, 3, -1, -3, -3, -3,
/* 14 */ -3, 1, -3, -1, -1, 3, 1, -3, -3, -3, -1, -3, -3, 1, 1, 1, -1, -1,
/* 15 */ -3, -3, 3, 3, 3, -1, -1, -3, -1, -1, -1, 3, 1, -3, -3, -1, 3, -1,
/* 16 */ -3, -1, 3, 3, -1, 3, -1, -3, -1, 1, -1, -3, -1, -1, -1, 3, 3, 1,
/* 17 */ -3, -1, -3, -1, -3, 1, 3, -3, -1, 3, 3, 3, 1, -1, -3, 3, -1, -3,
/* 18 */ -3, 3, 1, -1, -1, 3, -3, -1, 1, 1, 1, 1, 1, -1, 3, -1, -3, -1,
/* 19 */ 3, -1, -3, 1, -3, -3, -3, 3, 3, -1, 1, -3, -1, 3, 1, 1, 3, 3,
/* 20 */ 3, 3, 3, -3, -1, -3, -1, 3, -1, 1, -1, -3, 1, -3, -3, -1, 3, 3,
/* 21 */ 3, -1, 3, 1, -3, -3, -1, 1, -3, -3, 3, 3, 3, 1, 3, -3, 3, -3,
/* 22 */ -3, 1, 1, -3, 1, 1, 3, -3, -1, -3, -1, 3, -3, 3, -1, -1, -1, -3,
/* 23 */ -3, -1, -1, -3, 1, -3, 3, -1, -1, -3, 3, 3, -3, -1, 3, -1, -1, -1,
/* 24 */ -3, -3, -3, 1, -3, 3, 1, 1, 3, -3, -3, 1, 3, -1, 3, -3, -3, 3,
/* 25 */ 1, 1, -3, -3, -3, -3, 1, 3, -3, 3, 3, 1, -3, -1, 3, -1, -3, 1,
/* 26 */ 3, -1, -1, 1, -3, -1, -3, -1, -3, -3, -1, -3, 1, 1, 1, -3, -3, 3,
/* 27 */ 3, 1, -3, 1, -3, 3, 3, -1, -3, -3, -1, -3, -3, 3, -3, -1, 1, 3,
/* 28 */ -1, -3, 1, -3, -3, -3, 1, 1, 3, 3, -3, 3, 3, -3, -1, 3, -3, 1,
/* 29 */ -3, -1, -3, -3, 1, 1, -1, -3, -1, -3, -1, -1, 3, 3, -1, 3, 1, 3,
}
#endif
;
/* Table 5.2.2.2-4: Definition of phi (n ) for M_ZC = 24 */
const char phi_M_ZC_24[24*U_GROUP_NUMBER]
#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
= {
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 */
/* 0 */ -1, -3, 3, 1, 1, -3, 1, -3, -3, 1, -3, -1, -1, 3, -3, 3, 3, 3, -3, 1, 3, 3, -3, -3,
/* 1 */ -1, -3, 3, -1, 3, 1, 3, -1, 1, -3, -1, -3, -1, 1, 3, -3, -1, -3, 3, 3, 3, -3, -3, -3,
/* 2 */ -3, 3, 1, 3, -1, 1, -3, 1, -3, 1, -1, -3, -1, -3, -3, -3, -3, -1, -1, -1, 1, 1, -3, -3,
/* 3 */ 3, -1, 3, -1, 1, -3, 1, 1, -3, -3, 3, -3, -1, -1, -1, -1, -1, -3, -3, -1, 1, 1, -3, -3,
/* 4 */ 1, -3, 3, -1, -3, -1, 3, 3, 1, -1, 1, 1, 3, -3, -1, -3, -3, -3, -1, 3, -3, -1, -3, -3,
/* 5 */ 3, -1, 1, -1, 3, -3, 1, 1, 3, -1, -3, 3, 1, -3, 3, -1, -1, -1, -1, 1, -3, -3, -3, -3,
/* 6 */ -3, 3, -1, 3, 1, -1, -1, -1, 3, 3, 1, 1, 1, 3, 3, 1, -3, -3, -1, 1, -3, 1, 3, -3,
/* 7 */ -3, -1, 1, -3, -3, 1, 1, -3, 3, -1, -1, -3, 1, 3, 1, -1, -3, -1, -3, 1, -3, -3, -3, -3,
/* 8 */ -3, 1, -3, 1, -3, -3, 1, -3, 1, -3, -3, -3, -3, -3, 1, -3, -3, 1, 1, -3, 1, 1, -3, -3,
/* 9 */ 3, -3, -3, -1, 3, 3, -3, -1, 3, 1, 1, 1, 3, -1, 3, -3, -1, 3, -1, 3, 1, -1, -3, -3,
/* 10 */ -3, -3, -1, -1, -1, -3, 1, -1, -3, -1, 3, -3, 1, -3, 3, -3, 3, 3, 1, -1, -1, 1, -3, -3,
/* 11 */ -3, -3, 3, 3, 1, -1, -1, -1, 1, -3, -1, 1, -1, 3, -3, -1, -3, -1, -1, 1, -3, 3, -1, -3,
/* 12 */ -3, -3, 1, -1, 3, 3, -3, -1, 1, -1, -1, 1, 1, -1, -1, 3, -3, 1, -3, 1, -1, -1, -1, -3,
/* 13 */ -3, 1, -3, 3, -1, -1, -1, -3, 3, 1, -1, -3, -1, 1, 3, -1, 1, -1, 1, -3, -3, -3, -3, -3,
/* 14 */ -3, -3, -3, -1, 3, -3, 3, 1, 3, 1, -3, -1, -1, -3, 1, 1, 3, 1, -1, -3, 3, 1, 3, -3,
/* 15 */ 1, 1, -1, -3, -1, 1, 1, -3, 1, -1, 1, -3, 3, -3, -3, 3, -1, -3, 1, 3, -3, 1, -3, -3,
/* 16 */ -3, 3, -1, 3, -1, 3, 3, 1, 1, -3, 1, 3, -3, 3, -3, -3, -1, 1, 3, -3, -1, -1, -3, -3,
/* 17 */ -1, -3, -3, 1, -1, -1, -3, 1, 3, -1, -3, -1, -1, -3, 1, 1, 3, 1, -3, -1, -1, 3, -3, -3,
/* 18 */ -3, 1, -3, 1, -3, 1, 1, 3, 1, -3, -3, -1, 1, 3, -1, -3, 3, 1, -1, -3, -3, -3, -3, -3,
/* 19 */ 3, -3, 3, -1, -3, 1, 3, 1, -1, -1, -3, -1, 3, -3, 3, -1, -1, 3, 3, -3, -3, 3, -3, -3,
/* 20 */ -1, 3, -3, -3, -1, 3, -1, -1, 1, 3, 1, 3, -1, -1, -3, 1, 3, 1, -1, -3, 1, -1, -3, -3,
/* 21 */ -3, 1, -3, -1, -1, 3, 1, 3, -3, 1, -1, 3, 3, -1, -3, 3, -3, -1, -1, -3, -3, -3, 3, -3,
/* 22 */ -3, -1, -1, -3, 1, -3, -3, -1, -1, 3, -1, 1, -1, 3, 1, -3, -1, 3, 1, 1, -1, -1, -3, -3,
/* 23 */ -3, 1, -3, 3, -3, 1, -3, 3, 1, -1, -3, -1, -3, -3, -3, -3, 1, 3, -1, 1, 3, 3, 3, -3,
/* 24 */ -3, -1, 1, -3, -1, -1, 1, 1, 1, 3, 3, -1, 1, -1, 1, -1, -1, -3, -3, -3, 3, 1, -1, -3,
/* 25 */ 3, -3, -1, 1, 3, -1, -1, -3, -1, 3, -1, -3, -1, -3, 3, -1, 3, 1, 1, -3, 3, -3, -3, -3,
/* 26 */ -3, 1, 3, -1, 1, -1, 3, -3, 3, -1, -3, -1, -3, 3, -1, -1, -1, -3, -1, -1, -3, 3, 3, -3,
/* 27 */ -3, 3, -1, -3, -1, -1, -1, 3, -1, -1, 3, -3, -1, 3, -3, 3, -3, -1, 3, 1, 1, -1, -3, -3,
/* 28 */ -3, 1, -1, -3, -3, -1, 1, -3, -1, -3, 1, 1, -1, 1, 1, 3, 3, 3, -1, 1, -1, 1, -1, -3,
/* 29 */ -1, 3, -1, -1, 3, 3, -1, -1, -1, 3, -1, -3, 1, 3, 1, 1, -3, -3, -3, -1, -3, -1, -3, -3,
}
#endif
;
/************** FUNCTION ******************************************/
int16_t *base_sequence_36_or_larger(unsigned int M_ZC, unsigned int u, unsigned int v, unsigned int scaling);
int16_t *base_sequence_less_than_36(unsigned int M_ZC, unsigned int u, unsigned int scaling);
/*!
\brief This function generate the sounding reference symbol (SRS) for the uplink.
@param tables of srs
@param scaling amplitude of the reference signal
*/
void generate_ul_reference_signal_sequences(unsigned int scaling);
void free_ul_reference_signal_sequences(void);
#undef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
#undef EXTERN
#endif /* SSS_NR_H */
@@ -0,0 +1,578 @@
/*
* 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
*/
/**********************************************************************
*
* FILENAME : cic_filter_nr.c
*
* MODULE : generic functions for cic filters
*
* DESCRIPTION : generic functions useful for decimation based on cascaded integrator comb filter
*
************************************************************************/
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <math.h>
#include "PHY/defs_nr_UE.h"
#define DEFINE_VARIABLES_CIC_FILTER_NR_H
#include "PHY/NR_UE_TRANSPORT/cic_filter_nr.h"
#undef DEFINE_VARIABLES_CIC_FILTER_NR_H
/*******************************************************************
*
* NAME : integrator_stage
*
* PARAMETERS : pointer to input complex data
* pointer to output complex data
*
* RETURN :
*
* DESCRIPTION : single stage of an integrator
*
* It is a single-pole IIR filter with a unity feedback coefficient
*
* y(n) = y(n-1) +x(n)*
*
*********************************************************************/
void integrator_stage(int32_t *input, int32_t *output, int length)
{
/* first sample is just copied */
for (int i = 0; i < 1; i++) {
output[2*i] = input[2*i];
output[2*i+1] = input[2*i+1];
}
/* then process all other samples */
for (int i = 1; i < length; i++) {
output[2*i] = output[2*(i-1)] + input[2*i];
output[2*i+1] = output[2*(i-1)+1] + input[2*i+1];
#ifdef DBG_CIC_FILTER_NR
if (i < 20) {
printf("output[%d] = output[%d] + input[%d] \n", (2*i), 2*(i-1), 2*i);
printf("%d = %d + %d \n", output[2*i], output[2*(i-1)], input[2*i]);
}
#endif
}
}
/*******************************************************************
*
* NAME : comb_stage
*
* PARAMETERS : pointer to input complex data
* pointer to output complex data
*
* RETURN :
*
* DESCRIPTION : single stage of a comb filter which is an odd-symetric FIR filter
*
* y(n) = x(n) - x(n - M)
*
* M is called the differential delay. It can take any positive
* integer but it is usually limited to 1 or 2.
*
*********************************************************************/
void comb_stage(int32_t *input, int32_t *output, int length, int differential_delay)
{
/* first sample is just copied */
for (int i = 0; i < differential_delay; i++) {
output[2*i] = input[2*i];
output[2*i+1] = input[2*i+1];
}
/* then process all other samples */
for (int i = differential_delay; i < length; i++) {
output[2*i] = input[2*i] - input[2*(i-differential_delay)];
output[2*i+1] = input[2*i+1] - input[2*(i-differential_delay)+1];
#ifdef DBG_CIC_FILTER_NR
if (i < 20) {
printf("output[%d] = input[%d] - input[%d] \n", (2*i), (2*i), 2*(i-differential_delay));
printf("%d = %d - %d \n", output[2*i], input[2*i], input[2*(i-differential_delay)]);
}
#endif
}
}
/*******************************************************************
*
* NAME : rate_change_stage
*
* PARAMETERS : pointer to input complex data
* pointer to output complex data
*
* RETURN : none
*
* DESCRIPTION : change sampling rate by a factor of R
* just copy one samples over R from input to output buffer
*
*********************************************************************/
void rate_change_stage(int32_t *input, int32_t *output, int length, int rate_change)
{
for (int i = 0; (i*rate_change) < length; i++) {
output[2*i] = input[2*i*rate_change];
output[2*i+1] = input[(2*i*rate_change)+1];
#ifdef DBG_CIC_FILTER_NR
if (i < 20) {
printf("input[%d] : %d \n", 2*i*rate_change, input[2*i*rate_change]);
printf("output[%d] : %d \n", 2*i, output[2*i]);
}
#endif
}
}
/*******************************************************************
*
* NAME : fir_filter
*
* PARAMETERS : pointer to input complex data
* pointer to output complex data
*
* RETURN : none
*
* DESCRIPTION : implement a fir filter with taps from an array
*
*********************************************************************/
void fir_filter_init(fir_filter_t* f, int taps_fir_number, int32_t *filter_taps) {
int i;
for(i = 0; i < taps_fir_number; ++i)
f->history[i] = 0;
f->last_index = 0;
if (taps_fir_number > MAX_SAMPLEFILTER_TAP_NUM) {
printf("Number of taps of this FIR filter %d exceeds maximum value %d \n", taps_fir_number, MAX_SAMPLEFILTER_TAP_NUM);
assert(0);
}
f->filter_tap_number = taps_fir_number;
f->filter_taps = filter_taps;
}
void fir_filter_put(fir_filter_t* f, int32_t input) {
f->history[f->last_index++] = input;
if(f->last_index == f->filter_tap_number)
f->last_index = 0;
}
int32_t fir_filter_get(fir_filter_t* f, int scaling_shift) {
long long acc = 0;
int index = f->last_index, i;
for(i = 0; i < f->filter_tap_number; ++i) {
index = index != 0 ? index-1 : f->filter_tap_number-1;
acc += (long long)f->history[index] * f->filter_taps[i];
};
return acc >> scaling_shift;
}
void fir_filter_basic(int32_t *input, int32_t *output, int length, int taps_fir_number, int32_t *filter_taps, int scaling_shift)
{
fir_filter_t filter;
for (int j = 0; j < 2; j++) {
fir_filter_init(&filter, taps_fir_number, filter_taps);
for (int i = 0; i < length; i++) {
fir_filter_put(&filter, input[2*i+j]);
output[2*i+j] = fir_filter_get(&filter, scaling_shift);
//printf("i %d input %d output %d ", 2*i+j, input[2*i+j], output[2*i + j]);
}
}
}
/*******************************************************************
*
* NAME : fir_filter
*
* PARAMETERS : pointer to input complex data
* pointer to output complex data
*
* RETURN :
*
* DESCRIPTION : single stage of a fir filter which is an odd-symetric FIR filter
*
* y(n) = SUM ( bi * x(n - i) )
*
* bi are tags of FIR filter
*
*********************************************************************/
void fir_filter(int32_t *input, int32_t *output, int length, int taps_fir_number, int *taps_fir, int scaling_shift)
{
int32_t current;
/* taps start from 1 to taps_fir_number */
for (int i = 0; i < taps_fir_number; i++) {
for (int j=0; j<2 ; j++) {
current = 0;
for (int taps_number = 0; taps_number < taps_fir_number; taps_number++) {
if (i >= taps_number) {
current += taps_fir[taps_number]*input[2*(i-taps_number)+j];
#ifdef DBG_CIC_FILTER_NR
printf("current[%d] %d = taps[%d] : %d x input[%d] : %d \n", (2*i+j), current, taps_number, taps_fir[taps_number], (2*(i-taps_number)+j), input[2*(i-taps_number)+j]);
#endif
}
}
output[2*i+j] = current >> scaling_shift;
}
}
for (int i = taps_fir_number; i < length; i++) {
for (int j=0; j<2 ; j++) {
current = 0;
for (int taps_number = 0; taps_number < taps_fir_number; taps_number++) {
current += taps_fir[taps_number]*input[2*(i-taps_number)+j];
#ifdef DBG_CIC_FILTER_NR
if (i < taps_fir_number + 16) {
printf("current[%d] %d = taps[%d] : %d x input[%d] : %d \n", (2*i+j), current, taps_number, taps_fir[taps_number], (2*(i-taps_number)+j), input[2*(i-taps_number)+j]);
}
#endif
}
output[2*i+j] = current >> scaling_shift; // SHARPENED_FIR_SCALING_ACC;
}
}
}
/*******************************************************************
*
* NAME : cic_decimator
*
* PARAMETERS : pointer to input complex data
* pointer to output complex data
* length size of input buffer
* decimation by a factor of R
*
* RETURN : result of decimator is the output buffer
*
* DESCRIPTION : Cascaded integrator-comb filter
* rate change by a factor of R
*
* CIC filter with N stages is composed of:
* - N cascaded integrator filters clocked at high sampling rate fs
* - N cascaded comb stage running at fs/R
*
* +-----------+ +----------+ +----------+ +----+ +----------+ +----------+ +----------+ +--------------+
* | Integrator| |Integrator| |Integrator| | R | | Comb | | Comb | | Comb | | Compensation |
* input --->| stage |->| stage |->| stage |->| |->| stage |->| stage |->| stage |-------->| FIR Filter |---> output
* +-----------+ +----------+ +----------+ +----+ +----------+ +----------+ +----------+ +--------------+
* <----------------------------------------> | <-------------------------------------->
* N cascaded integrator filters | N cascaded comb stage running at fs/R
* clocked at high sampling rate fs V
* downsampling
* from fs to fs/R
*
* In order that cic filter works properly, some caution should be taken for getting good accuracy.
* Firstly data should be in fixed point in order to balance integrator and comb stages. If does not work with data in floating point.
*
* k1 is the number of significant bits for input
* k2 is the number of significant bits for output
* m = k2 - k2 > N * log2(RM - 1) N number of stage, M differential delay and R rate change factor
* for example with R=16 N=4 and M=1 with input data on 16 bits
* output data should be on k2 = m + k1 > 31
*
* Additionally there is a bit growth so processing has a gain of
* G = (RM)power(N)
* For example with R=16 N=4 M=1 G=(16*1)power(4)=65536
*
* It gives size of output data with number of significant bit Bout = (N x log2(R x M)) + Bin
* With R=16 N=4 M=1 Bin=16 => Bout = (4 x log2(16 x 1)) + 16 = (4 x 4) + 16 = 32 so output significant bits should be 32.
* As a consequence, all computations are done with 32 bits up to the last stage (no rounding or truncation).
* Except for the final result which can be casted from 32 bits to 16 bits.
*
*********************************************************************/
void cic_decimator(int16_t *input_buffer, int16_t *output_buffer, int length, int rate_change, int number_cic_stage, int set_scaling_factor, int fir_rate_change)
{
int32_t *buffer_one;
int32_t *buffer_two;
int32_t *input;
int32_t *output;
int32_t *tmp;
int new_length;
int current_rate_change;
/* for cic decimator, gain g of the output depends on rate change R, differential delay M and number of stage N */
/* g = power(R x M, N) / power(2 , log2 (R x M) */
/* so a scale factor should be applied to output in order to get a unity DC gain */
int scaling_factor = 0; // pow(2, log2(rate_change * M_DIFFERENTIAL_DELAY))/pow((rate_change * M_DIFFERENTIAL_DELAY), number_cic_stage);
if (set_scaling_factor != 0) {
scaling_factor = set_scaling_factor;
printf("Decimation with rate change of %d with set gain of %d \n", rate_change, scaling_factor);
}
/* get working buffers */
buffer_one = malloc(length*sizeof(int32_t) * 2); /* for i&q samples */
if (buffer_one == NULL) {
msg("Fatal memory allocation problem \n");
assert(0);
}
buffer_two = malloc(length*sizeof(int32_t) * 2); /* for i&q samples */
if (buffer_two == NULL) {
msg("Fatal memory allocation problem \n");
assert(0);
}
/* copy of input buffer from int16 to int32 */
for (int i = 0; i < length; i++) {
buffer_one[2*i] = input_buffer[2*i];
buffer_one[2*i + 1] = input_buffer[2*i + 1];
#ifdef DBG_CIC_FILTER_NR
if (i < 10) {
printf("buffer_one[%d] : %d %d \n", i, buffer_one[2*i], buffer_one[2*i + 1]);
}
#endif
}
input = buffer_one;
output = buffer_two;
/* call of integrator stages running at Fs */
for (int stage = 0; stage < number_cic_stage; stage++)
{
integrator_stage(input, output, length);
/* swap between output and input */
tmp = input;
input = output;
output = tmp;
#if 0
char output_file[255];
char sequence_name[255];
sprintf(output_file, "int_seq_%d.m", stage);
sprintf(sequence_name, "int_seq_%d", stage);
printf("file %s signal %s\n", output_file, sequence_name);
write_output(output_file, sequence_name, input, length, 1, 3); /* format = 3 is for int32_t */
#endif
}
/* a sharpened Fir filter can be added which can provide also a rate change */
current_rate_change = rate_change/fir_rate_change;
/* rate change from sampling frequency Fs to Fs/R */
rate_change_stage(input, output, length, current_rate_change);
/* new length of samples should be computed based on the rate change factor R */
new_length = length/current_rate_change;
/* swap between output and input */
tmp = input;
input = output;
output = tmp;
/* call of comb stages running at Fs/R */
for (int stage = 0; stage < number_cic_stage; stage++)
{
comb_stage(input, output, new_length, M_DIFFERENTIAL_DELAY);
/* swap between output and input */
tmp = input;
input = output;
output = tmp;
#if 0
char output_file[255];
char sequence_name[255];
sprintf(output_file, "comb_seq_%d.m", stage);
sprintf(sequence_name, "comb_seq_%d", stage);
printf("file %s signal %s\n", output_file, sequence_name);
write_output(output_file, sequence_name, input, new_length, 1, 3); /* format = 3 for int32_t */
#endif
}
#if 1
if (fir_rate_change > 1)
{
#define FIR_TAPS_SCALING (10000)
/* convert float taps of fir filter to int32 taps */
int32_t *filter_taps_fixed_point = malloc(FIR_TAPS_NUMBER*sizeof(int32_t));
if (filter_taps_fixed_point == NULL) {
msg("Fatal memory allocation problem \n");
assert(0);
}
for (int i = 0; i < FIR_TAPS_NUMBER; i++) {
filter_taps_fixed_point[i] = (int32_t)(sharpened_fir_taps[i] * FIR_TAPS_SCALING);
}
#if 1
/* compensation filter for equalizing the passband drop and perform a low rate change */
fir_filter(input, output, new_length, FIR_TAPS_NUMBER, filter_taps_fixed_point, FIR_FITER_SCALING_ACC);
#else
fir_filter_basic(input, output, new_length, FIR_TAPS_NUMBER, filter_taps, SHARPENED_FIR_SCALING_ACC);
#endif
}
else
{
output = input;
}
/* new length of samples should be computed based on the rate change */
current_rate_change = fir_rate_change;
new_length = new_length/current_rate_change;
/* filter has created a delay on the signal which can be compensated */
//int delay = FIR_TAPS_NUMBER;
int delay = 0;
for (int i = 0; (i*fir_rate_change) < new_length; i++) {
output_buffer[2*i] = output[(2*i+delay)*current_rate_change]>> scaling_factor;
output_buffer[2*i+1] = output[((2*i+delay)*current_rate_change)+1]>> scaling_factor;
#ifdef DBG_CIC_FILTER_NR
if (i < 10) {
printf("output_buffer[%d] = output[%d] >> scaling_factor \n", (2*i), ((2*i+delay)*current_rate_change));
printf(" %d = %d >> %d \n", output_buffer[2*i], output[((2*i+delay)*current_rate_change)], scaling_factor);
}
#endif
}
#else
scaling_factor = 0;
/* copy of final result from int32 to int16 with a scaling factor and a rate change */
for (int i = 0; i < new_length; i++) {
output_buffer[2*i] = input[2*i] >> scaling_factor;
output_buffer[2*i + 1] = input[2*i + 1] >> scaling_factor;
#ifdef DBG_CIC_FILTER_NR
if (i < 10) {
printf("output_buffer[%d] : %d \n", (2*i), output_buffer[2*i]);
printf("input[%d] : %d \n", 2*i, input[2*i] >> scaling_factor);
}
#endif
}
#endif
#if 1
/* clear till end of the buffer */
for (int i = new_length; i < length; i++) {
output_buffer[2*i] = 0;
output_buffer[2*i + 1] = 0;
}
#endif
}
/*******************************************************************
*
* NAME : fir_decimator
*
* PARAMETERS : pointer to input complex data
* pointer to output complex data
* length size of input buffer
* decimation by a factor of R
*
* RETURN : result of decimator is the output buffer
*
* DESCRIPTION : fir filter
* rate change by a factor of R
*
*
*********************************************************************/
void fir_decimator(int16_t *input_buffer, int16_t *output_buffer, int length, int rate_change, int scaling_factor)
{
int32_t *buffer_one;
int32_t *buffer_two;
int32_t *input;
int32_t *output;
int new_length;
/* get working buffers */
buffer_one = malloc(length*sizeof(int32_t) * 2); /* for i&q samples */
if (buffer_one == NULL) {
msg("Fatal memory allocation problem \n");
assert(0);
}
buffer_two = malloc(length*sizeof(int32_t) * 2); /* for i&q samples */
if (buffer_two == NULL) {
msg("Fatal memory allocation problem \n");
assert(0);
}
/* copy of input buffer from int16 to int32 */
for (int i = 0; i < length; i++) {
buffer_one[2*i] = input_buffer[2*i];
buffer_one[2*i + 1] = input_buffer[2*i + 1];
}
input = buffer_one;
output = buffer_two;
#if 1
fir_filter(input, output, length, SAMPLEFILTER_TAP_NUM, filter_taps, FIR_SCALING_ACC);
#else
fir_filter_basic(input, output, length, SAMPLEFILTER_TAP_NUM, filter_taps, FIR_SCALING_ACC);
#endif
/* rate change from sampling frequency Fs to Fs/R */
rate_change_stage(output, input, length, rate_change);
new_length = length/rate_change;
/* copy of final result from int32 to int16 with a scaling factor and a rate change */
for (int i = 0; i < new_length; i++) {
output_buffer[2*i] = input[2*i] >> scaling_factor;
output_buffer[2*i + 1] = input[2*i + 1] >> scaling_factor;
}
#if 1
/* clear till end of the buffer */
for (int i = new_length; i < length; i++) {
output_buffer[2*i] = 0;
output_buffer[2*i + 1] = 0;
}
#endif
}
@@ -0,0 +1,207 @@
/*
* 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
*/
/**********************************************************************
*
* FILENAME : cic_filter_nr.h
*
* MODULE : synchronisation signal
*
* DESCRIPTION : function related to nr synchronisation
* It provides filters for sampling decimation
*
************************************************************************/
#ifndef CIC_FILTER_NR_H
#define CIC_FILTER_NR_H
#include "PHY/defs_nr_UE.h"
#include "PHY/types.h"
#ifdef DEFINE_VARIABLES_CIC_FILTER_NR_H
#define EXTERN
#define INIT_VARIABLES_CIC_FILTER_NR_H
#else
#define EXTERN extern
#endif
/************** DEFINE ********************************************/
#define M_DIFFERENTIAL_DELAY (1)
#define FIR_RATE_CHANGE (2)
/************** VARIABLES *****************************************/
#define FIR_TAPS_NUMBER (20)
#define FIR_FITER_SCALING_ACC (14)
EXTERN double sharpened_fir_taps[FIR_TAPS_NUMBER]
#ifdef INIT_VARIABLES_CIC_FILTER_NR_H
= {
/*
cic filter and compensation FIR have been designed based on cic design tools provided at
http://www.tsdconseil.fr/tutos/index.html
-->cfir = cic_comp_design(4,4,1,30720000,2,1650000,20);
R = 4.00, Fin = 30720000.00 Hz, Fout = 7680000.00 Hz.
Attenuation for f > fout/2 : -14.82 dB.
Attenuation at 1650000.00 Hz: -0.15 dB.
Attenuation max. between 0 et 1650000.00 Hz: -0.15 dB.
E.g. in linear scale : * 0.983
Number of additionnal bits needed for implementation: 7.
Fout = 7680000.00 Hz.
index = 1026 / 4096.
Correction Fint ?
Filtre global :
-->cfir
cfir =
*/
- 0.0059900,
- 0.0056191,
0.0107582,
0.0266043,
0.0130358,
- 0.0331228,
- 0.0680440,
- 0.0278570,
0.1106335,
0.2897060,
0.3607857,
0.2607354,
0.0983409,
- 0.0243749,
- 0.0583235,
- 0.0276023,
0.0104286,
0.0199533,
0.0071721,
- 0.0028096,
}
#endif
;
#define MAX_SAMPLEFILTER_TAP_NUM (100)
#define FIR_SCALING_ACC (15)
typedef struct {
int32_t history[MAX_SAMPLEFILTER_TAP_NUM];
int last_index;
int filter_tap_number;
int32_t *filter_taps;
} fir_filter_t;
#define SAMPLEFILTER_TAP_NUM (59)
/*
* This low pass filter was designed based on the tool at http://t-filter.engineerjs.com/
* with below parameters
* sampling frequency 30.72 MHz
* from to gain ripple/att.
* 0 Hz 1.9 MHz 1 0.5 dB
* 2 MHz 15 MHz 0 -20 dB
*/
EXTERN int filter_taps[SAMPLEFILTER_TAP_NUM]
#ifdef INIT_VARIABLES_CIC_FILTER_NR_H
= {
-1572,
65,
-132,
197,
26,
393,
194,
536,
250,
514,
105,
279,
-234,
-105,
-646,
-466,
-924,
-583,
-856,
-279,
-321,
492,
639,
1601,
1812,
2766,
2872,
3650,
3503,
3976,
3503,
3650,
2872,
2766,
1812,
1601,
639,
492,
-321,
-279,
-856,
-583,
-924,
-466,
-646,
-105,
-234,
279,
105,
514,
250,
536,
194,
393,
26,
197,
-132,
65,
-1572
}
#endif
;
/************** FUNCTION ******************************************/
void integrator_stage(int32_t *input, int32_t *output, int length);
void comb_stage(int32_t *input, int32_t *output, int length, int differential_delay);
void rate_change_stage(int32_t *input, int32_t *output, int length, int rate_change);
void fir_filter(int32_t *input, int32_t *output, int length, int taps_fir_number, int32_t *taps_fir, int scaling_shift);
void cic_decimator(int16_t *input_buffer, int16_t *output_buffer, int length, int rate_change, int number_cic_stage, int set_scaling_factor, int fir_rate_change);
void fir_decimator(int16_t *input_buffer, int16_t *output_buffer, int length, int rate_change, int scaling_factor);
#undef EXTERN
#undef INIT_VARIABLES_CIC_FILTER_NR_H
#endif /* CIC_FILTER_NR_H */
+311
View File
@@ -0,0 +1,311 @@
/*
* 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
*/
/**********************************************************************
*
* FILENAME : dmrs_nr.c
*
* MODULE : demodulation reference signals
*
* DESCRIPTION : generation of dmrs sequences
* 3GPP TS 38.211
*
************************************************************************/
//#include "PHY/LTE_REFSIG/defs.h"
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
#include "PHY/NR_REFSIG/dmrs_nr.h"
/*******************************************************************
*
* NAME : pseudo_random_gold_sequence
*
* PARAMETERS :
*
* RETURN : generate pseudo-random sequence which is a length-31 Gold sequence
*
* DESCRIPTION : 3GPP TS 38.211 5.2.1 Pseudo-random sequence generation
* Sequence generation is a length-31 Gold sequence
*
*********************************************************************/
#define NC (1600)
#define GOLD_SEQUENCE_LENGTH (31)
int pseudo_random_sequence(int M_PN, uint32_t *c, uint32_t cinit)
{
int n;
int size_x = NC + GOLD_SEQUENCE_LENGTH + M_PN;
uint32_t *x1;
uint32_t *x2;
x1 = calloc(size_x, sizeof(uint32_t));
if (x1 == NULL) {
msg("Fatal error: memory allocation problem \n");
assert(0);
}
x2 = calloc(size_x, sizeof(uint32_t));
if (x2 == NULL) {
free(x1);
msg("Fatal error: memory allocation problem \n");
assert(0);
}
x1[0] = 1; /* init first m sequence */
/* cinit allows to initialise second m-sequence x2 */
for (n = 0; n < GOLD_SEQUENCE_LENGTH; n++) {
x2[n] = (cinit >> n) & 0x1;
}
for (n = 0; n < (NC + M_PN); n++) {
x1[n+31] = (x1[n+3] + x1[n])%2;
x2[n+31] = (x2[n+3] + x2[n+2] + x2[n+1] + x2[n])%2;
}
for (int n = 0; n < M_PN; n++) {
c[n] = (x1[n+NC] + x2[n+NC])%2;
}
free(x1);
free(x2);
return 0;
}
/*******************************************************************
*
* NAME : pseudo_random_sequence_optimised
*
* PARAMETERS :
*
* RETURN : generate pseudo-random sequence which is a length-31 Gold sequence
*
* DESCRIPTION : 3GPP TS 38.211 5.2.1 Pseudo-random sequence generation
* Sequence generation is a length-31 Gold sequence
* This is an optimized function based on bitmap variables
*
* x1(0)=1,x1(1)=0,...x1(30)=0,x1(31)=1
* x2 <=> cinit, x2(31) = x2(3)+x2(2)+x2(1)+x2(0)
* x2 <=> cinit = sum_{i=0}^{30} x2(i)2^i
* c(n) = x1(n+Nc) + x2(n+Nc) mod 2
*
* equivalent to
* x1(n+31) = (x1(n+3)+x1(n))mod 2 <=> x1(n) = x1(n-28) + x1(n-31)
* x2(n+31) = (x2(n+3)+x2(n+2)+x2(n+1)+x2(n))mod 2 <=> x2(n) = x2(n-28) + x2(n-29) + x2(n-30) + x2(n-31)
*
*********************************************************************/
void pseudo_random_sequence_optimised(unsigned int size, uint32_t *c, uint32_t cinit)
{
unsigned int n,x1,x2;
/* init of m-sequences */
x1 = 1+ (1<<31);
x2 = cinit;
x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
/* skip first 50 double words of uint32_t (1600 bits) */
for (n=1; n<50; n++) {
x1 = (x1>>1) ^ (x1>>4);
x1 = x1 ^ (x1<<31) ^ (x1<<28);
x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
}
for (n=0; n<size; n++) {
x1 = (x1>>1) ^ (x1>>4);
x1 = x1 ^ (x1<<31) ^ (x1<<28);
x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
c[n] = x1^x2;
}
}
/*******************************************************************
*
* NAME : lte_gold_new
*
* PARAMETERS :
*
* RETURN : generate pseudo-random sequence which is a length-31 Gold sequence
*
* DESCRIPTION : This function is the same as "lte_gold" function in file lte_gold.c
* It allows checking that optimization works fine.
* generated sequence is given in an array as a bit map.
*
*********************************************************************/
#define CELL_DMRS_LENGTH (224*2)
#define CHECK_GOLD_SEQUENCE
void lte_gold_new(LTE_DL_FRAME_PARMS *frame_parms, uint32_t lte_gold_table[20][2][14], uint16_t Nid_cell)
{
unsigned char ns,l,Ncp=1-frame_parms->Ncp;
uint32_t cinit;
#ifdef CHECK_GOLD_SEQUENCE
uint32_t dmrs_bitmap[20][2][14];
uint32_t *dmrs_sequence = calloc(CELL_DMRS_LENGTH, sizeof(uint32_t));
if (dmrs_sequence == NULL) {
msg("Fatal error: memory allocation problem \n");
assert(0);
}
else
{
printf("Check of demodulation reference signal of pbch sequence \n");
}
#endif
/* for each slot number */
for (ns=0; ns<20; ns++) {
/* for each ofdm position */
for (l=0; l<2; l++) {
cinit = Ncp +
(Nid_cell<<1) +
(((1+(Nid_cell<<1))*(1 + (((frame_parms->Ncp==0)?4:3)*l) + (7*(1+ns))))<<10);
pseudo_random_sequence_optimised(14, &(lte_gold_table[ns][l][0]), cinit);
#ifdef CHECK_GOLD_SEQUENCE
pseudo_random_sequence(CELL_DMRS_LENGTH, dmrs_sequence, cinit);
int j = 0;
int k = 0;
/* format for getting bitmap from uint32_t */
for (int i=0; i<14; i++) {
dmrs_bitmap[ns][l][i] = 0;
for (; j < k + 32; j++) {
dmrs_bitmap[ns][l][i] |= (dmrs_sequence[j]<<j);
}
k = j;
}
for (int i=0; i<14; i++) {
if (lte_gold_table[ns][l][i] != dmrs_bitmap[ns][l][i]) {
printf("Error in gold sequence computation for ns %d l %d and index %i : 0x%x 0x%x \n", ns, l, i, lte_gold_table[ns][l][i], dmrs_bitmap[ns][l][i]);
assert(0);
}
}
#endif
}
}
#ifdef CHECK_GOLD_SEQUENCE
free(dmrs_sequence);
#endif
}
/*******************************************************************
*
* NAME : get_dmrs_pbch
*
* PARAMETERS : i_ssb : index of ssb/pbch beam
* n_hf : number of the half frame in which PBCH is transmitted in frame
*
* RETURN : demodulation reference signal for PBCH
*
* DESCRIPTION : see TS 38.211 7.4.1.4 Demodulation reference signals for PBCH
*
*********************************************************************/
#define CHECK_DMRS_PBCH_SEQUENCE
void generate_dmrs_pbch(uint32_t dmrs_pbch_bitmap[DMRS_PBCH_I_SSB][DMRS_PBCH_N_HF][DMRS_BITMAP_SIZE], uint16_t Nid_cell)
{
uint32_t cinit;
int i_ssb;
int n_hf;
int _i_ssb;
#ifdef CHECK_DMRS_PBCH_SEQUENCE
uint32_t dmrs_bitmap[DMRS_PBCH_I_SSB][DMRS_PBCH_N_HF][DMRS_BITMAP_SIZE];
uint32_t *dmrs_sequence = calloc(CELL_DMRS_LENGTH, sizeof(uint32_t));
if (dmrs_sequence == NULL) {
msg("Fatal error: memory allocation problem \n");
assert(0);
}
else
{
printf("Check of demodulation reference signal of pbch sequence \n");
}
#endif
/* for each slot number */
for (i_ssb = 0; i_ssb<DMRS_PBCH_I_SSB; i_ssb++) {
/* for each ofdm position */
for (n_hf=0; n_hf<DMRS_PBCH_N_HF; n_hf++) {
_i_ssb = i_ssb + 4*n_hf;
cinit = (((_i_ssb + 1)*((Nid_cell>>4) + 1))<<11) + ((_i_ssb + 1)<<6) + (Nid_cell%4);
pseudo_random_sequence_optimised(DMRS_BITMAP_SIZE, &(dmrs_pbch_bitmap[i_ssb][n_hf][0]), cinit);
#ifdef CHECK_DMRS_PBCH_SEQUENCE
/* it allows checking generated with standard generation code */
pseudo_random_sequence(DMRS_BITMAP_SIZE*sizeof(uint32_t), dmrs_sequence, cinit);
int j = 0;
int k = 0;
/* format for getting bitmap from uint32_t */
for (int i=0; i<DMRS_BITMAP_SIZE; i++) {
dmrs_bitmap[i_ssb][n_hf][i] = 0;
/* convert to bitmap */
for (; j < k + 32; j++) {
dmrs_bitmap[i_ssb][n_hf][i] |= (dmrs_sequence[j]<<j);
}
k = j;
}
for (int i=0; i<DMRS_BITMAP_SIZE; i++) {
if (dmrs_pbch_bitmap[i_ssb][n_hf][i] != dmrs_bitmap[i_ssb][n_hf][i]) {
printf("Error in gold sequence computation for ns %d l %d and index %i : 0x%x 0x%x \n", i_ssb, n_hf, i, dmrs_pbch_bitmap[i_ssb][n_hf][i], dmrs_bitmap[i_ssb][n_hf][i]);
assert(0);
}
}
#endif
}
}
#ifdef CHECK_DMRS_PBCH_SEQUENCE
free(dmrs_sequence);
#endif
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,335 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/NR_TRANSPORT/defs.h
* \brief data structures for PDSCH/DLSCH/PUSCH/ULSCH physical and transport channel descriptors (TX/RX)
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: raymond.knopp@eurecom.fr, florian.kaltenberger@eurecom.fr, oscar.tonelli@yahoo.it
* \note
* \warning
*/
#ifndef __NR_TRANSPORT_UE__H__
#define __NR_TRANSPORT_UE__H__
#include "PHY/defs_nr_UE.h"
//#include "../LTE_TRANSPORT/dci.h"
//#include "../LTE_TRANSPORT/mdci.h"
//#include "../LTE_TRANSPORT/uci_common.h"
//#include "../LTE_TRANSPORT/transport_common.h"
#ifndef STANDALONE_COMPILE
#include "UTIL/LISTS/list.h"
#endif
//#include "../LTE_TRANSPORT/transport_common.h"
// structures below implement 36-211 and 36-212
/** @addtogroup _PHY_TRANSPORT_
* @{
*/
#define SHRT_MAX 32767
typedef struct {
/// Indicator of first transmission
uint8_t first_tx;
/// Last Ndi received for this process on DCI (used for C-RNTI only)
uint8_t DCINdi;
/// Flag indicating that this ULSCH has a new packet (start of new round)
// uint8_t Ndi;
/// Status Flag indicating for this ULSCH (idle,active,disabled)
SCH_status_t status;
/// Subframe scheduling indicator (i.e. Transmission opportunity indicator)
uint8_t subframe_scheduling_flag;
/// Subframe cba scheduling indicator (i.e. Transmission opportunity indicator)
uint8_t subframe_cba_scheduling_flag;
/// First Allocated RB
uint16_t first_rb;
/// Current Number of RBs
uint16_t nb_rb;
/// Last TPC command
uint8_t TPC;
/// Transport block size
uint32_t TBS;
/// The payload + CRC size in bits, "B" from 36-212
uint32_t B;
/// Length of ACK information (bits)
uint8_t O_ACK;
/// Pointer to the payload
uint8_t *b;
/// Pointers to transport block segments
uint8_t *c[MAX_NUM_ULSCH_SEGMENTS];
/// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15)
uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS];
/// Index of current HARQ round for this ULSCH
uint8_t round;
/// MCS format of this ULSCH
uint8_t mcs;
/// Redundancy-version of the current sub-frame
uint8_t rvidx;
/// Turbo-code outputs (36-212 V8.6 2009-03, p.12
uint8_t d[MAX_NUM_ULSCH_SEGMENTS][(96+3+(3*6144))];
/// Sub-block interleaver outputs (36-212 V8.6 2009-03, p.16-17)
uint8_t w[MAX_NUM_ULSCH_SEGMENTS][3*6144];
/// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9)
uint32_t C;
/// Number of "small" code segments (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t Cminus;
/// Number of "large" code segments (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t Cplus;
/// Number of bits in "small" code segments (<6144) (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t Kminus;
/// Number of bits in "large" code segments (<6144) (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t Kplus;
/// Total number of bits across all segments
uint32_t sumKr;
/// Number of "Filler" bits (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t F;
/// Msc_initial, Initial number of subcarriers for ULSCH (36-212, v8.6 2009-03, p.26-27)
uint16_t Msc_initial;
/// Nsymb_initial, Initial number of symbols for ULSCH (36-212, v8.6 2009-03, p.26-27)
uint8_t Nsymb_initial;
/// n_DMRS for cyclic shift of DMRS (36.213 Table 9.1.2-2)
uint8_t n_DMRS;
/// n_DMRS2 for cyclic shift of DMRS (36.211 Table 5.5.1.1.-1)
uint8_t n_DMRS2;
/// Flag to indicate that this is a control only ULSCH (i.e. no MAC SDU)
uint8_t control_only;
/// Flag to indicate that this is a calibration ULSCH (i.e. no MAC SDU and filled with TDD calibration information)
// int calibration_flag;
/// Number of soft channel bits
uint32_t G;
// decode phich
uint8_t decode_phich;
} NR_UL_UE_HARQ_t;
typedef struct {
/// Current Number of Symbols
uint8_t Nsymb_pusch;
/// SRS active flag
uint8_t srs_active;
/// Pointers to 8 HARQ processes for the ULSCH
NR_UL_UE_HARQ_t *harq_processes[8];
/// Pointer to CQI data (+1 for 8 bits crc)
uint8_t o[1+MAX_CQI_BYTES];
/// Length of CQI data (bits)
uint8_t O;
/// Format of CQI data
UCI_format_t uci_format;
/// Rank information
uint8_t o_RI[2];
/// Length of rank information (bits)
uint8_t O_RI;
/// Pointer to ACK
uint8_t o_ACK[4];
/// Minimum number of CQI bits for PUSCH (36-212 r8.6, Sec 5.2.4.1 p. 37)
uint8_t O_CQI_MIN;
/// ACK/NAK Bundling flag
uint8_t bundling;
/// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
uint8_t e[MAX_NUM_CHANNEL_BITS];
/// Interleaved "h"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
uint8_t h[MAX_NUM_CHANNEL_BITS];
/// Scrambled "b"-sequences (for definition see 36-211 V8.6 2009-03, p.14)
uint8_t b_tilde[MAX_NUM_CHANNEL_BITS];
/// Modulated "d"-sequences (for definition see 36-211 V8.6 2009-03, p.14)
int32_t d[MAX_NUM_RE];
/// Transform-coded "z"-sequences (for definition see 36-211 V8.6 2009-03, p.14-15)
int32_t z[MAX_NUM_RE];
/// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27)
uint8_t q[MAX_CQI_PAYLOAD];
/// coded and interleaved CQI bits
uint8_t o_w[(MAX_CQI_BITS+8)*3];
/// coded CQI bits
uint8_t o_d[96+((MAX_CQI_BITS+8)*3)];
/// coded ACK bits
uint8_t q_ACK[MAX_ACK_PAYLOAD];
/// coded RI bits
uint8_t q_RI[MAX_RI_PAYLOAD];
/// beta_offset_cqi times 8
uint16_t beta_offset_cqi_times8;
/// beta_offset_ri times 8
uint16_t beta_offset_ri_times8;
/// beta_offset_harqack times 8
uint16_t beta_offset_harqack_times8;
/// power_offset
uint8_t power_offset;
// for cooperative communication
uint8_t cooperation_flag;
/// RNTI attributed to this ULSCH
uint16_t rnti;
/// f_PUSCH parameter for PUSCH power control
int16_t f_pusch;
/// Po_PUSCH - target output power for PUSCH
int16_t Po_PUSCH;
/// PHR - current power headroom (based on last PUSCH transmission)
int16_t PHR;
/// Po_SRS - target output power for SRS
int16_t Po_SRS;
/// num active cba group
uint8_t num_active_cba_groups;
/// num dci found for cba
uint8_t num_cba_dci[10];
/// allocated CBA RNTI
uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP];
/// UL max-harq-retransmission
uint8_t Mlimit;
} NR_UE_ULSCH_t;
typedef struct {
/// Indicator of first transmission
uint8_t first_tx;
/// Last Ndi received for this process on DCI (used for C-RNTI only)
uint8_t DCINdi;
/// DLSCH status flag indicating
SCH_status_t status;
/// Transport block size
uint32_t TBS;
/// The payload + CRC size in bits
uint32_t B;
/// Pointer to the payload
uint8_t *b;
/// Pointers to transport block segments
uint8_t *c[MAX_NUM_DLSCH_SEGMENTS];
/// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15)
uint32_t RTC[MAX_NUM_DLSCH_SEGMENTS];
/// Index of current HARQ round for this DLSCH
uint8_t round;
/// MCS format for this DLSCH
uint8_t mcs;
/// Qm (modulation order) for this DLSCH
uint8_t Qm;
/// Redundancy-version of the current sub-frame
uint8_t rvidx;
/// MIMO mode for this DLSCH
MIMO_mode_t mimo_mode;
/// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
int16_t w[MAX_NUM_DLSCH_SEGMENTS][3*(6144+64)];
/// for abstraction soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
double w_abs[MAX_NUM_DLSCH_SEGMENTS][3*(6144+64)];
/// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
int16_t *d[MAX_NUM_DLSCH_SEGMENTS];
/// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9)
uint32_t C;
/// Number of "small" code segments (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t Cminus;
/// Number of "large" code segments (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t Cplus;
/// Number of bits in "small" code segments (<6144) (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t Kminus;
/// Number of bits in "large" code segments (<6144) (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t Kplus;
/// Number of "Filler" bits (for definition see 36-212 V8.6 2009-03, p.10)
uint32_t F;
/// Number of MIMO layers (streams) (for definition see 36-212 V8.6 2009-03, p.17)
uint8_t Nl;
/// current delta_pucch
int8_t delta_PUCCH;
/// Number of soft channel bits
uint32_t G;
/// Current Number of RBs
uint16_t nb_rb;
/// Current subband PMI allocation
uint16_t pmi_alloc;
/// Current RB allocation (even slots)
uint32_t rb_alloc_even[4];
/// Current RB allocation (odd slots)
uint32_t rb_alloc_odd[4];
/// distributed/localized flag
vrb_t vrb_type;
/// downlink power offset field
uint8_t dl_power_off;
/// trials per round statistics
uint32_t trials[8];
/// error statistics per round
uint32_t errors[8];
/// codeword this transport block is mapped to
uint8_t codeword;
} NR_DL_UE_HARQ_t;
typedef struct {
/// HARQ process id
uint8_t harq_id;
/// ACK bits (after decoding) 0:NACK / 1:ACK / 2:DTX
uint8_t ack;
/// send status (for PUCCH)
uint8_t send_harq_status;
/// nCCE (for PUCCH)
uint8_t nCCE;
/// DAI value detected from DCI1/1a/1b/1d/2/2a/2b/2c. 0xff indicates not touched
uint8_t vDAI_DL;
/// DAI value detected from DCI0/4. 0xff indicates not touched
uint8_t vDAI_UL;
} nr_harq_status_t;
typedef struct {
/// RNTI
uint16_t rnti;
/// Active flag for DLSCH demodulation
uint8_t active;
/// Transmission mode
uint8_t mode1_flag;
/// amplitude of PDSCH (compared to RS) in symbols without pilots
int16_t sqrt_rho_a;
/// amplitude of PDSCH (compared to RS) in symbols containing pilots
int16_t sqrt_rho_b;
/// Current HARQ process id threadRx Odd and threadRx Even
uint8_t current_harq_pid;
/// Current subband antenna selection
uint32_t antenna_alloc;
/// Current subband RI allocation
uint32_t ri_alloc;
/// Current subband CQI1 allocation
uint32_t cqi_alloc1;
/// Current subband CQI2 allocation
uint32_t cqi_alloc2;
/// saved subband PMI allocation from last PUSCH/PUCCH report
uint16_t pmi_alloc;
/// HARQ-ACKs
nr_harq_status_t harq_ack[10];
/// Pointers to up to 8 HARQ processes
NR_DL_UE_HARQ_t *harq_processes[8];
/// Maximum number of HARQ processes(for definition see 36-212 V8.6 2009-03, p.17
uint8_t Mdlharq;
/// MIMO transmission mode indicator for this sub-frame (for definition see 36-212 V8.6 2009-03, p.17)
uint8_t Kmimo;
/// Nsoft parameter related to UE Category
uint32_t Nsoft;
/// Maximum number of Turbo iterations
uint8_t max_turbo_iterations;
/// number of iterations used in last turbo decoding
uint8_t last_iteration_cnt;
/// accumulated tx power adjustment for PUCCH
int8_t g_pucch;
} NR_UE_DLSCH_t;
/**@}*/
#endif
+100
View File
@@ -0,0 +1,100 @@
/*
* 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
*/
/**********************************************************************
*
* FILENAME : pbch_nr.c
*
* MODULE : broacast channel
*
* DESCRIPTION : generation of pbch
* 3GPP TS 38.211 7.3.3 Physical broadcast channel
*
************************************************************************/
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include "PHY/defs.h"
#define DEFINE_VARIABLES_PBCH_NR_H
#include "PHY/NR_REFSIG/pbch_nr.h"
#undef DEFINE_VARIABLES_PBCH_NR_H
/*******************************************************************
*
* NAME : pseudo_random_gold_sequence
*
* PARAMETERS :
*
* RETURN : generate pseudo-random sequence which is a length-31 Gold sequence
*
* DESCRIPTION : 3GPP TS 38.211 5.2.1 Pseudo-random sequence generation
* Sequence generation
*
*********************************************************************/
#define NC (1600)
#define GOLD_LENGTH (31)
uint32_t *pseudo_random_gold_sequence(length M_PN, uint32_t cinit)
{
int size = M_PN * sizeof(uint32_t);
int size_x = (sizeof(int)*M_PN + size;
int *x1 = malloc(size_x);
int *x2 = malloc(size_x);
if ((x1 == NULL) || (x2 == NULL)) {
msg("Fatal memory allocation problem \n");
assert(0);
}
else {
bzero(x1, size_x);
bzero(x2, size_x);
}
x1[0] = 1;
for (n = 0; n < 31; n++) {
x2[n] = (cinit >> n) & 0x1;
}
for (int n = 0; n < (NC+M_PN); n++) {
x1(n+31) = (x1(n+3) + x1(n))%2;
x2(n+31) = (x2(n+3) + x2(n+2) + x2(n+1) + x2(n))%2;
}
int *c = calloc(size);
if (c != NULL) {
bzero(c, size);
}
else {
msg("Fatal memory allocation problem \n");
assert(0);
}
for (int n = 0; n < M_PN; n++) {
c(i) = (x1(n+NC) + x2(n+NC))%2;
}
return c;
}
+873
View File
@@ -0,0 +1,873 @@
/*
* 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
*/
/**********************************************************************
*
* FILENAME : pss_nr.c
*
* MODULE : synchronisation signal
*
* DESCRIPTION : generation of pss
* 3GPP TS 38.211 7.4.2.2 Primary synchronisation signal
*
************************************************************************/
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include "PHY/defs_nr_UE.h"
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
#define DEFINE_VARIABLES_PSS_NR_H
#include "PHY/NR_REFSIG/pss_nr.h"
#undef DEFINE_VARIABLES_PSS_NR_H
#include "PHY/NR_REFSIG/sss_nr.h"
#include "PHY/NR_UE_TRANSPORT/cic_filter_nr.h"
/*******************************************************************
*
* NAME : get_idft
*
* PARAMETERS : size of ofdm symbol
*
* RETURN : function idft
*
* DESCRIPTION : get idft function depending of ofdm size
*
*********************************************************************/
void *get_idft(int ofdm_symbol_size)
{
void (*idft)(int16_t *,int16_t *, int);
switch (ofdm_symbol_size) {
case 128:
idft = idft128;
break;
case 256:
idft = idft256;
break;
case 512:
idft = idft512;
break;
case 1024:
idft = idft1024;
break;
case 1536:
idft = idft1536;
break;
case 2048:
idft = idft2048;
break;
default:
printf("function get_idft : unsupported ofdm symbol size \n");
assert(0);
break;
}
return idft;
}
/*******************************************************************
*
* NAME : get_dft
*
* PARAMETERS : size of ofdm symbol
*
* RETURN : function for discrete fourier transform
*
* DESCRIPTION : get dft function depending of ofdm size
*
*********************************************************************/
void *get_dft(int ofdm_symbol_size)
{
void (*dft)(int16_t *,int16_t *, int);
switch (ofdm_symbol_size) {
case 128:
dft = dft128;
break;
case 256:
dft = dft256;
break;
case 512:
dft = dft512;
break;
case 1024:
dft = dft1024;
break;
case 1536:
dft = dft1536;
break;
case 2048:
dft = dft2048;
break;
default:
printf("function get_dft : unsupported ofdm symbol size \n");
assert(0);
break;
}
return dft;
}
/*******************************************************************
*
* NAME : generate_pss_nr
*
* PARAMETERS : N_ID_2 : element 2 of physical layer cell identity
* value : { 0, 1, 2}
*
* RETURN : generate binary pss sequence (this is a m-sequence)
*
* DESCRIPTION : 3GPP TS 38.211 7.4.2.2 Primary synchronisation signal
* Sequence generation
*
*********************************************************************/
void generate_pss_nr(int N_ID_2, int ofdm_symbol_size)
{
int16_t d_pss[LENGTH_PSS_NR];
int16_t x[LENGTH_PSS_NR];
int16_t *primary_synchro_time = primary_synchro_time_nr[N_ID_2];
unsigned int length = ofdm_symbol_size;
unsigned int size = length * IQ_SIZE; /* i & q */
int16_t *primary_synchro = primary_synchro_nr[N_ID_2]; /* pss in complex with alternatively i then q */
void (*idft)(int16_t *,int16_t *, int);
#define INITIAL_PSS_NR (7)
const int x_initial[INITIAL_PSS_NR] = {0, 1, 1 , 0, 1, 1, 1};
assert(N_ID_2 < NUMBER_PSS_SEQUENCE);
assert(size <= SYNCF_TMP_SIZE);
assert(size <= SYNC_TMP_SIZE);
bzero(synchroF_tmp, size);
bzero(synchro_tmp, size);
for (int i=0; i < INITIAL_PSS_NR; i++) {
x[i] = x_initial[i];
}
for (int i=0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++) {
x[i+INITIAL_PSS_NR] = (x[i + 4] + x[i])%(2);
}
for (int n=0; n < LENGTH_PSS_NR; n++) {
int m = (n + 43*N_ID_2)%(LENGTH_PSS_NR);
d_pss[n] = 1 - 2*x[m];
}
/* PSS is directly mapped to subcarrier without modulation 38.211 */
for (int i=0; i < LENGTH_PSS_NR; i++) {
#if 1
primary_synchro[2*i] = (d_pss[i] * SHRT_MAX)>>SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */
primary_synchro[2*i+1] = 0;
#else
primary_synchro[2*i] = d_pss[i] * AMP;
primary_synchro[2*i+1] = 0;
#endif
}
#ifdef DBG_PSS_NR
if (N_ID_2 == 0) {
char output_file[255];
char sequence_name[255];
sprintf(output_file, "pss_seq_%d_%d.m", N_ID_2, length);
sprintf(sequence_name, "pss_seq_%d_%d", N_ID_2, length);
printf("file %s sequence %s\n", output_file, sequence_name);
write_output(output_file, sequence_name, primary_synchro, LENGTH_PSS_NR, 1, 1);
}
#endif
/* call of IDFT should be done with ordered input as below
*
* n input samples
* <------------------------------------------------>
* 0 n
* are written into input buffer for IFFT
* -------------------------------------------------
* |xxxxxxx N/2 xxxxxxxx|
* --------------------------------------------------
* ^ ^ ^ ^ ^
* | | | | |
* n/2 end of n=0 start of n/2-1
* pss pss
*
* Frequencies
* positives negatives
* 0 (+N/2)(-N/2)
* |-----------------------><-------------------------|
*
* sample 0 is for continuous frequency which is used here
*/
unsigned int k = length - (LENGTH_PSS_NR/2+1);
for (int i=0; i < LENGTH_PSS_NR; i++) {
synchroF_tmp[2*k] = primary_synchro[2*i];
synchroF_tmp[2*k+1] = primary_synchro[2*i+1];
k++;
if (k >= length) {
k++;
k-=length;
}
}
/* IFFT will give temporal signal of Pss */
idft = get_idft(length);
idft(synchroF_tmp, /* complex input */
synchro_tmp, /* complex output */
1); /* scaling factor */
/* then get final pss in time */
for (unsigned int i=0; i<length; i++) {
((int32_t *)primary_synchro_time)[i] = ((int32_t *)synchro_tmp)[i];
}
#ifdef DBG_PSS_NR
if (N_ID_2 == 0) {
char output_file[255];
char sequence_name[255];
sprintf(output_file, "%s%d_%d%s","pss_seq_t_", N_ID_2, length, ".m");
sprintf(sequence_name, "%s%d_%d","pss_seq_t_", N_ID_2, length);
printf("file %s sequence %s\n", output_file, sequence_name);
write_output(output_file, sequence_name, primary_synchro_time, length, 1, 1);
}
#endif
#if 0
/* it allows checking that process of idft on a signal and then dft gives same signal with limited errors */
if ((N_ID_2 == 0) && (length == 256)) {
write_output("pss_f00.m","pss_f00",synchro_tmp,length,1,1);
bzero(synchroF_tmp, size);
void (*dft)(int16_t *,int16_t *, int) = get_dft(length);
/* get pss in the time domain by applying an inverse FFT */
dft(synchro_tmp, /* complex input */
synchroF_tmp, /* complex output */
1); /* scaling factor */
if ((N_ID_2 == 0) && (length == 256)) {
write_output("pss_f_0.m","pss_f_0",synchroF_tmp,length,1,1);
}
/* check Pss */
k = length - (LENGTH_PSS_NR/2);
#define LIMIT_ERROR_FFT (10)
for (int i=0; i < LENGTH_PSS_NR; i++) {
if (abs(synchroF_tmp[2*k] - primary_synchro[2*i]) > LIMIT_ERROR_FFT) {
printf("Pss Error[%d] Compute %d Reference %d \n", k, synchroF_tmp[2*k], primary_synchro[2*i]);
}
if (abs(synchroF_tmp[2*k+1] - primary_synchro[2*i+1]) > LIMIT_ERROR_FFT) {
printf("Pss Error[%d] Compute %d Reference %d\n", (2*k+1), synchroF_tmp[2*k+1], primary_synchro[2*i+1]);
}
k++;
if (k >= length) {
k-=length;
}
}
}
#endif
}
/*******************************************************************
*
* NAME : init_context_pss_nr
*
* PARAMETERS : structure NR_DL_FRAME_PARMS give frame parameters
*
* RETURN : generate binary pss sequences (this is a m-sequence)
*
* DESCRIPTION : 3GPP TS 38.211 7.4.2.2 Primary synchronisation signal
* Sequence generation
*
*********************************************************************/
void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
{
int ofdm_symbol_size = frame_parms_ue->ofdm_symbol_size;
int sizePss = LENGTH_PSS_NR * IQ_SIZE; /* complex value i & q signed 16 bits */
int size = ofdm_symbol_size * IQ_SIZE; /* i and q samples signed 16 bits */
int16_t *p = NULL;
int *q = NULL;
for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
p = malloc16(sizePss); /* pss in complex with alternatively i then q */
if (p != NULL) {
primary_synchro_nr[i] = p;
bzero( primary_synchro_nr[i], sizePss);
}
else {
msg("Fatal memory allocation problem \n");
assert(0);
}
p = malloc16(size);
if (p != NULL) {
primary_synchro_time_nr[i] = p;
bzero( primary_synchro_time_nr[i], size);
}
else {
msg("Fatal memory allocation problem \n");
assert(0);
}
size = LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms_ue->samples_per_subframe;
q = malloc16(size);
if (q != NULL) {
pss_corr_ue[i] = q;
bzero( pss_corr_ue[i], size);
}
else {
msg("Fatal memory allocation problem \n");
assert(0);
}
generate_pss_nr(i, ofdm_symbol_size);
}
}
/*******************************************************************
*
* NAME : free_context_pss_nr
*
* PARAMETERS : none
*
* RETURN : none
*
* DESCRIPTION : free context related to pss
*
*********************************************************************/
void free_context_pss_nr(void)
{
for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
if (primary_synchro_time_nr[i] != NULL) {
free(primary_synchro_time_nr[i]);
primary_synchro_time_nr[i] = NULL;
}
else {
msg("Fatal memory deallocation problem \n");
assert(0);
}
if (primary_synchro_nr[i] != NULL) {
free(primary_synchro_nr[i]);
primary_synchro_nr[i] = NULL;
}
else {
msg("Fatal memory deallocation problem \n");
assert(0);
}
if (pss_corr_ue[i] != NULL) {
free(pss_corr_ue[i]);
pss_corr_ue[i] = NULL;
}
else {
msg("Fatal memory deallocation problem \n");
assert(0);
}
}
}
/*******************************************************************
*
* NAME : init_context_synchro_nr
*
* PARAMETERS : none
*
* RETURN : generate context for pss and sss
*
* DESCRIPTION : initialise contexts and buffers for synchronisation
*
*********************************************************************/
void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
{
#ifndef STATIC_SYNC_BUFFER
/* initialise global buffers for synchronisation */
synchroF_tmp = malloc16(SYNCF_TMP_SIZE);
if (synchroF_tmp == NULL) {
msg("Fatal memory allocation problem \n");
assert(0);
}
synchro_tmp = malloc16(SYNC_TMP_SIZE);
if (synchro_tmp == NULL) {
msg("Fatal memory allocation problem \n");
assert(0);
}
#endif
init_context_pss_nr(frame_parms_ue);
init_context_sss_nr(AMP);
}
/*******************************************************************
*
* NAME : free_context_synchro_nr
*
* PARAMETERS : none
*
* RETURN : free context for pss and sss
*
* DESCRIPTION : deallocate memory of synchronisation
*
*********************************************************************/
void free_context_synchro_nr(void)
{
#ifndef STATIC_SYNC_BUFFER
if (synchroF_tmp != NULL) {
free(synchroF_tmp);
synchroF_tmp = NULL;
}
else {
msg("Fatal memory deallocation problem \n");
assert(0);
}
if (synchro_tmp != NULL) {
free(synchro_tmp);
synchro_tmp = NULL;
}
else {
msg("Fatal memory deallocation problem \n");
assert(0);
}
#endif
free_context_pss_nr();
}
/*******************************************************************
*
* NAME : set_frame_context_pss_nr
*
* PARAMETERS : configuration for UE with new FFT size
*
* RETURN : 0 if OK else error
*
* DESCRIPTION : initialisation of UE contexts
*
*********************************************************************/
void set_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change)
{
/* set new value according to rate_change */
frame_parms_ue->ofdm_symbol_size = (frame_parms_ue->ofdm_symbol_size / rate_change);
frame_parms_ue->samples_per_tti = (frame_parms_ue->samples_per_tti / rate_change);
frame_parms_ue->samples_per_subframe = (frame_parms_ue->samples_per_subframe / rate_change);
free_context_pss_nr();
/* pss reference have to be rebuild with new parameters ie ofdm symbol size */
init_context_synchro_nr(frame_parms_ue);
#ifdef SYNCHRO_DECIMAT
set_pss_nr(frame_parms_ue->ofdm_symbol_size);
#endif
}
/*******************************************************************
*
* NAME : restore_frame_context_pss_nr
*
* PARAMETERS : configuration for UE and eNB with new FFT size
*
* RETURN : 0 if OK else error
*
* DESCRIPTION : initialisation of UE and eNode contexts
*
*********************************************************************/
void restore_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change)
{
frame_parms_ue->ofdm_symbol_size = frame_parms_ue->ofdm_symbol_size * rate_change;
frame_parms_ue->samples_per_tti = frame_parms_ue->samples_per_tti * rate_change;
frame_parms_ue->samples_per_subframe = frame_parms_ue->samples_per_subframe * rate_change;
free_context_pss_nr();
/* pss reference have to be rebuild with new parameters ie ofdm symbol size */
init_context_synchro_nr(frame_parms_ue);
#ifdef SYNCHRO_DECIMAT
set_pss_nr(frame_parms_ue->ofdm_symbol_size);
#endif
}
/********************************************************************
*
* NAME : decimation_synchro_nr
*
* INPUT : UE context
* for first and second pss sequence
* - position of pss in the received UE buffer
* - number of pss sequence
*
* RETURN : 0 if OK else error
*
* DESCRIPTION : detect pss sequences in the received UE buffer
*
********************************************************************/
void decimation_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change, int **rxdata)
{
NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms);
int samples_for_frame = LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti;
#if TEST_SYNCHRO_TIMING_PSS
opp_enabled = 1;
start_meas(&generic_time[TIME_RATE_CHANGE]);
#endif
/* build with cic filter does not work properly. Performances are significantly deteriorated */
#ifdef CIC_DECIMATOR
cic_decimator((int16_t *)&(PHY_vars_UE->common_vars.rxdata[0][0]), (int16_t *)&(rxdata[0][0]),
samples_for_frame, rate_change, CIC_FILTER_STAGE_NUMBER, 0, FIR_RATE_CHANGE);
#else
fir_decimator((int16_t *)&(PHY_vars_UE->common_vars.rxdata[0][0]), (int16_t *)&(rxdata[0][0]),
samples_for_frame, rate_change, 0);
#endif
set_frame_context_pss_nr(frame_parms, rate_change);
#if TEST_SYNCHRO_TIMING_PSS
stop_meas(&generic_time[TIME_RATE_CHANGE]);
printf("Rate change execution duration %5.2f \n", generic_time[TIME_RATE_CHANGE].p_time/(cpuf*1000.0));
#endif
}
/*******************************************************************
*
* NAME : pss_synchro_nr
*
* PARAMETERS : int rate_change
*
* RETURN : position of detected pss
*
* DESCRIPTION : pss search can be done with sampling decimation.*
*
*********************************************************************/
int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change)
{
NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms);
int synchro_position;
int **rxdata = NULL;
#ifdef DBG_PSS_NR
int samples_for_frame = frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME;
write_output("rxdata0_rand.m","rxd0_rand", &PHY_vars_UE->common_vars.rxdata[0][0], samples_for_frame, 1, 1);
#endif
if (rate_change != 1) {
rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
for (int aa=0; aa < frame_parms->nb_antennas_rx; aa++) {
rxdata[aa] = (int32_t*) malloc16_clear( (frame_parms->samples_per_subframe*10+2048)*sizeof(int32_t));
}
#ifdef SYNCHRO_DECIMAT
decimation_synchro_nr(PHY_vars_UE, rate_change, rxdata);
#endif
}
else {
rxdata = PHY_vars_UE->common_vars.rxdata;
}
#ifdef DBG_PSS_NR
write_output("rxdata0_des.m","rxd0_des", &rxdata[0][0], samples_for_frame,1,1);
#endif
#if TEST_SYNCHRO_TIMING_PSS
opp_enabled = 1;
start_meas(&generic_time[TIME_PSS]);
#endif
#if 1
synchro_position = pss_search_time_nr(rxdata,
frame_parms,
(int *)&PHY_vars_UE->common_vars.eNb_id);
#else
synchro_position = lte_sync_time(rxdata,
frame_parms,
(int *)&PHY_vars_UE->common_vars.eNb_id);
#endif
#if TEST_SYNCHRO_TIMING_PSS
stop_meas(&generic_time[TIME_PSS]);
printf("PSS execution duration %5.2f \n", generic_time[TIME_PSS].p_time/(cpuf*1000.0));
#endif
#ifdef SYNCHRO_DECIMAT
if (rate_change != 1) {
if (rxdata[0] != NULL) {
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
free(rxdata[aa]);
}
free(rxdata);
}
restore_frame_context_pss_nr(frame_parms, rate_change);
}
#endif
return synchro_position;
}
static inline int abs32(int x)
{
return (((int)((short*)&x)[0])*((int)((short*)&x)[0]) + ((int)((short*)&x)[1])*((int)((short*)&x)[1]));
}
/*******************************************************************
*
* NAME : pss_search_time_nr
*
* PARAMETERS : received buffer
* frame parameters
*
* RETURN : position of detected pss
*
* DESCRIPTION : Synchronisation on pss sequence is based on a time domain correlation between received samples and pss sequence
* A maximum likelihood detector finds the timing offset (position) that corresponds to the maximum correlation
* Length of received buffer should be a minimum of 2 frames (see TS 38.213 4.1 Cell search)
* Search pss in the received buffer is done each 4 samples which ensures a memory alignment to 128 bits (32 bits x 4).
* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors
* Correlation computation is based on a a dot product which is realized thank to SIMS extensions
*
* (x frames)
* <--------------------------------------------------------------------------->
*
*
* -----------------------------------------------------------------------------
* | Received UE data buffer |
* ----------------------------------------------------------------------------
* -------------
* <--------->| pss |
* position -------------
* ^
* |
* peak position
* given by maximum of correlation result
* position matches beginning of first ofdm symbol of pss sequence
*
* Remark: memory position should be aligned on a multiple of 4 due to I & Q samples of int16
* An OFDM symbol is composed of x number of received samples depending of Rf front end sample rate.
*
* I & Q storage in memory
*
* First samples Second samples
* ------------------------- ------------------------- ...
* | I1 | Q1 | I2 | Q2 |
* --------------------------------------------------- ...
* ^ 16 bits 16 bits ^
* | |
* --------------------------------------------------- ...
* | sample 1 | sample 2 |
* ---------------------------------------------------- ...
* ^
*
*********************************************************************/
#define DOT_PRODUCT_SCALING_SHIFT (17)
int pss_search_time_nr(int **rxdata, ///rx data in time domain
NR_DL_FRAME_PARMS *frame_parms,
int *eNB_id)
{
unsigned int n, ar, peak_position, peak_value, pss_source;
int result;
int synchro_out;
unsigned int tmp[NUMBER_PSS_SEQUENCE];
unsigned int length = (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->ttis_per_subframe*frame_parms->samples_per_tti); /* 1 frame for now, it should be 2 TODO_NR */
for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
tmp[i] = 0;
if (pss_corr_ue[i] == NULL) {
msg("[SYNC TIME] pss_corr_ue[%d] not yet allocated! Exiting.\n", i);
return(-1);
}
}
peak_value = 0;
peak_position = 0;
pss_source = 0;
/* Search pss in the received buffer each 4 samples which ensures a memory alignment on 128 bits (32 bits x 4 ) */
/* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors. */
/* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */
for (n=0; n < length; n+=4) {
#ifdef RTAI_ENABLED
// This is necessary since the sync takes a long time and it seems to block all other threads thus screwing up RTAI. If we pause it for a little while during its execution we give RTAI a chance to catch up with its other tasks.
if ((n%frame_parms->samples_per_subframe == 0) && (n>0) && (openair_daq_vars.sync_state==0)) {
#ifdef DEBUG_PHY
msg("[SYNC TIME] pausing for 1000ns, n=%d\n",n);
#endif
rt_sleep(nano2count(1000));
}
#endif
for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) {
pss_corr_ue[pss_index][n] = 0; /* clean correlation for position n */
synchro_out = 0;
if ( n < (length - frame_parms->ofdm_symbol_size)) {
/* calculate dot product of primary_synchro_time_nr and rxdata[ar][n] (ar=0..nb_ant_rx) and store the sum in temp[n]; */
for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) {
/* perform correlation of rx data and pss sequence ie it is a dot product */
result = dot_product((short*)primary_synchro_time_nr[pss_index], (short*) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, DOT_PRODUCT_SCALING_SHIFT);
((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0]; /* real part */
((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */
((short*)&synchro_out)[0] += ((short*) &result)[0]; /* real part */
((short*)&synchro_out)[1] += ((short*) &result)[1]; /* imaginary part */
}
}
pss_corr_ue[pss_index][n] = abs32(pss_corr_ue[pss_index][n]);
/* calculate the absolute value of sync_corr[n] */
tmp[pss_index] = (abs32(synchro_out)) ;
if (tmp[pss_index] > peak_value) {
peak_value = tmp[pss_index];
peak_position = n;
pss_source = pss_index;
//printf("pss_index %d: n %6d peak_value %10d, synchro_out (% 6d,% 6d) \n", pss_index, n, abs32(synchro_out),((int16_t*)&synchro_out)[0],((int16_t*)&synchro_out)[1]);
}
}
}
*eNB_id = pss_source;
LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %d (%d dB)\n", pss_source, peak_position, peak_value, dB_fixed(peak_value)/2);
#ifdef DEBUG_PSS_NR
#define PSS_DETECTION_FLOOR_NR (31)
if ((dB_fixed(peak_value)/2) > PSS_DETECTION_FLOOR_NR) {
printf("[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %d (%d dB)\n", pss_source, peak_position, peak_value,dB_fixed(peak_value)/2);
}
#endif
#ifdef DEBUG_PHY
if (debug_cnt == 0) {
write_output("pss_corr_ue0.m","pss_corr_ue0",pss_corr_ue[0],length,1,2);
write_output("pss_corr_ue1.m","pss_corr_ue1",pss_corr_ue[1],length,1,2);
write_output("pss_corr_ue2.m","pss_corr_ue2",pss_corr_ue[2],length,1,2);
write_output("rxdata0.m","rxd0",rxdata[0],length,1,1);
} else {
debug_cnt++;
}
#endif
return(peak_position);
}
@@ -0,0 +1,488 @@
/*
* 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
*/
/***********************************************************************
*
* FILENAME : srs_modulation_nr_nr.c
*
* MODULE :
*
* DESCRIPTION : function to set uplink reference symbols
* see TS 38211 6.4.1.4 Sounding reference signal
*
************************************************************************/
#include <stdio.h>
#include <math.h>
#define DEFINE_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
#include "PHY/impl_defs_nr.h"
#undef DEFINE_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
#include "PHY/defs_nr_UE.h"
//#include "extern.h"
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
#include "PHY/NR_REFSIG/dmrs_nr.h"
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
#define DEFINE_VARIABLES_SRS_MODULATION_NR_H
#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h"
#undef DEFINE_VARIABLES_SRS_MODULATION_NR_H
/*******************************************************************
*
* NAME : generate_srs
*
* PARAMETERS : pointer to resource set
* pointer to transmit buffer
* amplitude scaling for this physical signal
* slot number of transmission
* RETURN : 0 if srs sequence has been successfully generated
* -1 if sequence can not be properly generated
*
* DESCRIPTION : generate/map srs symbol into transmit buffer
* see TS 38211 6.4.1.4 Sounding reference signal
*
* FFS_TODO_NR
* Current supported configuration:
* - single resource per resource set
* - single port antenna
* - 1 symbol for SRS
* - no symbol offset
* - periodic mode
* - no hopping
* - no carrier switching
* - no antenna switching*
*
*********************************************************************/
int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
NR_DL_FRAME_PARMS *frame_parms,
int32_t *txptr,
int16_t amp,
UE_nr_rxtx_proc_t *proc)
{
uint8_t n_SRS_cs_max;
uint8_t u, v_nu;
uint32_t f_gh = 0;
SRS_Resource_t *p_SRS_Resource;
int frame_number = proc->frame_tx;
int slot_number = proc->nr_tti_tx;
uint16_t n_SRS, n_SRS_cs_i;
double alpha_i;
uint8_t K_TC_p;
uint16_t n_b[B_SRS_NUMBER], F_b, subcarrier;
uint8_t N_b, k_0_overbar_p;
if (p_srs_resource_set->p_srs_ResourceList[0] == NULL) {
LOG_E(PHY,"generate_srs: No resource associated with the SRS resource set!\n");
return (-1);
}
else {
if (p_srs_resource_set->number_srs_Resource <= MAX_NR_OF_SRS_RESOURCES_PER_SET) {
p_SRS_Resource = p_srs_resource_set->p_srs_ResourceList[0];
}
else {
LOG_E(PHY,"generate_srs: resource number of this resource set %d exceeds maximum supported value %d!\n", p_srs_resource_set->number_srs_Resource, MAX_NR_OF_SRS_RESOURCES_PER_SET);
return (-1);
}
}
if (p_srs_resource_set->resourceType != periodic) {
LOG_E(PHY,"generate_srs: only SRS periodic is supported up to now!\n");
return (-1);
}
/* get parameters from SRS resource configuration */
uint8_t B_SRS = p_SRS_Resource->freqHopping_b_SRS;
uint8_t C_SRS = p_SRS_Resource->freqHopping_c_SRS;
uint8_t b_hop = p_SRS_Resource->freqHopping_b_hop;
uint8_t K_TC = p_SRS_Resource->transmissionComb;
uint8_t K_TC_overbar = p_SRS_Resource->combOffset; /* FFS_TODO_NR is this parameter for K_TC_overbar ?? */
uint8_t n_SRS_cs = p_SRS_Resource->cyclicShift;
uint8_t n_ID_SRS = p_SRS_Resource->sequenceId;
uint8_t n_shift = p_SRS_Resource->freqDomainPosition; /* it adjusts the SRS allocation to align with the common resource block grid in multiples of four */
uint8_t n_RRC = p_SRS_Resource->freqDomainShift;
uint8_t groupOrSequenceHopping = p_SRS_Resource->groupOrSequenceHopping;
uint8_t l_offset = p_SRS_Resource->resourceMapping_startPosition;
uint16_t T_SRS = srs_period[p_SRS_Resource->SRS_Periodicity];
uint16_t T_offset = p_SRS_Resource->SRS_Offset;; /* FFS_TODO_NR to check interface with RRC */
uint8_t R = p_SRS_Resource->resourceMapping_repetitionFactor;
/* TS 38.211 6.4.1.4.1 SRS resource */
uint8_t N_ap = (uint8_t)p_SRS_Resource->nrof_SrsPorts; /* antenna port for transmission */
uint8_t N_symb_SRS = p_SRS_Resource->resourceMapping_nrofSymbols; /* consecutive OFDM symbols */
uint8_t l0 = N_SYMB_SLOT - 1 - l_offset; /* starting position in the time domain */
uint8_t k_0_p; /* frequency domain starting position */
if (N_ap != port1) {
LOG_E(PHY, "generate_srs: this number of antenna ports %d is not yet supported!\n", N_ap);
return (-1);
}
if (N_symb_SRS != 1) {
LOG_E(PHY, "generate_srs: this number of srs symbol %d is not yet supported!\n", N_symb_SRS);
return (-1);
}
if (groupOrSequenceHopping != neitherHopping) {
LOG_E(PHY, "generate_srs: sequence hopping is not yet supported!\n");
return (-1);
}
if (R == 0) {
LOG_E(PHY, "generate_srs: this parameter repetition factor %d is not consistent !\n", R);
return (-1);
}
else if (R > N_symb_SRS) {
LOG_E(PHY, "generate_srs: R %d can not be greater than N_symb_SRS %d !\n", R, N_symb_SRS);
return (-1);
}
/* see 38211 6.4.1.4.2 Sequence generation */
if (K_TC == 4) {
n_SRS_cs_max = 12;
// delta = 2; /* delta = log2(K_TC) */
}
else if (K_TC == 2) {
n_SRS_cs_max = 8;
// delta = 1; /* delta = log2(K_TC) */
}
else {
LOG_E(PHY, "generate_srs: SRS unknown value for K_TC %d !\n", K_TC);
return (-1);
}
if (n_SRS_cs >= n_SRS_cs_max) {
LOG_E(PHY, "generate_srs: inconsistent parameter n_SRS_cs %d >= n_SRS_cs_max %d !\n", n_SRS_cs, n_SRS_cs_max);
return (-1);
}
if (T_SRS == 0) {
LOG_E(PHY, "generate_srs: inconsistent parameter T_SRS %d can not be equal to zero !\n", T_SRS);
return (-1);
}
else
{
int index = 0;
while (srs_periodicity[index] != T_SRS) {
index++;
if (index == SRS_PERIODICITY) {
LOG_E(PHY, "generate_srs: inconsistent parameter T_SRS %d not specified !\n", T_SRS);
return (-1);
}
}
}
uint16_t m_SRS_b = srs_bandwidth_config[C_SRS][B_SRS][0]; /* m_SRS_b is given by TS 38211 clause 6.4.1.4.3 */
uint16_t M_sc_b_SRS = m_SRS_b * N_SC_RB/K_TC; /* length of the sounding reference signal sequence */
/* for each antenna ports for transmission */
for (int p_index = 0; p_index < N_ap; p_index++) {
/* see TS 38.211 6.4.1.4.2 Sequence generation */
n_SRS_cs_i = (n_SRS_cs + (n_SRS_cs_max * (SRS_antenna_port[p_index] - 1000)/N_ap))%n_SRS_cs_max;
alpha_i = 2 * M_PI * ((double)n_SRS_cs_i / (double)n_SRS_cs_max);
/* for each SRS symbol which should be managed by SRS configuration */
/* from TS 38.214 6.2.1.1 UE SRS frequency hopping procedure */
/* A UE may be configured to transmit an SRS resource on adjacent symbols within the last six symbols of a slot, */
/* where all antenna ports of the SRS resource are mapped to each symbol of the resource */
uint8_t l = p_index;
if (l >= N_symb_SRS) {
LOG_E(PHY, "generate_srs: number of antenna ports %d and number of srs symbols %d are different !\n", N_ap, N_symb_SRS);
}
switch(groupOrSequenceHopping) {
case neitherHopping:
{
f_gh = 0;
v_nu = 0;
break;
}
case groupHopping:
{
uint8_t c_last_index = 8 * (slot_number * N_SYMB_SLOT + l0 + l) + 7; /* compute maximum value of the random sequence */
uint32_t *c_sequence = calloc(c_last_index+1, sizeof(uint32_t));
uint32_t cinit = n_ID_SRS/30;
pseudo_random_sequence(c_last_index+1, c_sequence, cinit);
for (int m = 0; m < 8; m++) {
f_gh += c_sequence[8 * (slot_number * N_SYMB_SLOT + l0 + l) + m]<<m;
}
free(c_sequence);
f_gh = f_gh%30;
v_nu = 0;
break;
}
case sequenceHopping:
{
f_gh = 0;
if (M_sc_b_SRS > 6 * N_SC_RB) {
uint8_t c_last_index = (slot_number * N_SYMB_SLOT + l0 + l); /* compute maximum value of the random sequence */
uint32_t *c_sequence = calloc(c_last_index+1, sizeof(uint32_t));
uint32_t cinit = n_ID_SRS;
pseudo_random_sequence(c_last_index+1, c_sequence, cinit);
v_nu = c_sequence[c_last_index];
free(c_sequence);
}
else {
v_nu = 0;
}
break;
}
default:
{
LOG_E(PHY, "generate_srs: unknown hopping setting %d !\n", groupOrSequenceHopping);
return (-1);
}
}
/* u is the sequence-group number defined in section 6.4.1.4.1 */
u = (f_gh + n_ID_SRS)%U_GROUP_NUMBER; /* 30 */
/* TS 38.211 6.4.1.4.3 Mapping to physical resources */
if((n_SRS_cs >= n_SRS_cs_max/2)&&(n_SRS_cs < n_SRS_cs_max)&&(N_ap == 4) && ((SRS_antenna_port[p_index] == 1001) || (SRS_antenna_port[p_index] == 1003))) {
K_TC_p = (K_TC_overbar + K_TC/2)%K_TC;
}
else {
K_TC_p = K_TC_overbar;
}
for (int b = 0; b <= B_SRS; b++) {
N_b = srs_bandwidth_config[C_SRS][b][1];
if (b_hop >= B_SRS) {
n_b[b] = (4 * n_RRC/m_SRS_b)%N_b; /* frequency hopping is disabled and the frequency position index n_b remains constant */
}
else {
if (b == b_hop) {
N_b = 1;
}
/* periodicity and offset */
if (p_srs_resource_set->resourceType == aperiodic) {
n_SRS = l/R;
}
else {
int8_t N_slot_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME * frame_parms->ttis_per_subframe;
n_SRS = ((N_slot_frame*frame_number + slot_number - T_offset)/T_SRS)*(N_symb_SRS/R)+(l/R);
}
uint16_t product_N_b = 1; /* for b_hop to b-1 */
for (unsigned int b_prime = b_hop; b_prime < B_SRS; b_prime++) { /* product for b_hop to b-1 */
if (b_prime != b_hop) {
product_N_b *= srs_bandwidth_config[C_SRS][b_prime][1];
}
}
if (N_b & 1) { /* Nb odd */
F_b = (N_b/2)*(n_SRS/product_N_b);
}
else { /* Nb even */
uint16_t product_N_b_B_SRS = product_N_b;
product_N_b_B_SRS *= srs_bandwidth_config[C_SRS][B_SRS][1]; /* product for b_hop to b */
F_b = (N_b/2)*((n_SRS%product_N_b_B_SRS)/product_N_b) + ((n_SRS%product_N_b_B_SRS)/2*product_N_b);
}
if (b <= b_hop) {
n_b[b] = (4 * n_RRC/m_SRS_b)%N_b;
}
else {
n_b[b] = (F_b + (4 * n_RRC/m_SRS_b))%N_b;
}
}
}
k_0_overbar_p = n_shift * N_SC_RB + K_TC_p;
k_0_p = k_0_overbar_p; /* it is the frequency-domain starting position */
for (int b = 0; b <= B_SRS; b++) {
k_0_p += K_TC * M_sc_b_SRS * n_b[b];
}
subcarrier = (frame_parms->first_carrier_offset) + k_0_p;
if (subcarrier>frame_parms->ofdm_symbol_size) {
subcarrier -= frame_parms->ofdm_symbol_size;
}
/* find index of table which is for this srs length */
unsigned int M_sc_b_SRS_index = 0;
while((ul_allocated_re[M_sc_b_SRS_index] != M_sc_b_SRS) && (M_sc_b_SRS_index < SRS_SB_CONF)){
M_sc_b_SRS_index++;
}
if (ul_allocated_re[M_sc_b_SRS_index] != M_sc_b_SRS) {
LOG_E(PHY, "generate_srs: srs uplink allocation %d can not be found! \n", M_sc_b_SRS);
return (-1);
}
#if 0
char output_file[255];
char sequence_name[255];
sprintf(output_file, "rv_seq_%d_%d_%d.m", u, v_nu, ul_allocated_re[M_sc_b_SRS_index]);
sprintf(sequence_name, "rv_seq_%d_%d_%d", u, v_nu, ul_allocated_re[M_sc_b_SRS_index]);
write_output(output_file, sequence_name, rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index], ul_allocated_re[M_sc_b_SRS_index], 1, 1);
#endif
for (int k=0; k < M_sc_b_SRS; k++) {
double real_shift = cos(alpha_i*k);
double imag_shift = sin(alpha_i*k);
/* cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */
double real = ((real_shift*rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k]) - (imag_shift*rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k+1]))/sqrt(N_ap);
/* sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */
double imag = ((imag_shift*rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k]) + (real_shift*rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k+1]))/sqrt(N_ap);
int32_t real_amp = ((int32_t)round((double) amp * real)) >> 15;
int32_t imag_amp = ((int32_t)round((double) amp * imag)) >> 15;
#if 0
printf("subcarrier %5d srs[%3d] r: %4d i: %4d reference[%d][%d][%d] r: %6d i: %6d\n", subcarrier, k, real_amp, imag_amp,
u, v_nu, M_sc_b_SRS_index,
rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k],
rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k+1]);
#endif
txptr[subcarrier] = (real_amp & 0xFFFF) + ((imag_amp<<16)&0xFFFF0000);
subcarrier += (K_TC); /* subcarrier increment */
if (subcarrier >= frame_parms->ofdm_symbol_size)
subcarrier=subcarrier-frame_parms->ofdm_symbol_size;
}
/* process next symbol */
txptr = txptr + frame_parms->ofdm_symbol_size;
}
return (0);
}
/*******************************************************************
*
* NAME : is_srs_period_nr
*
* PARAMETERS : pointer to resource set
* pointer to transmit buffer
* amplitude scaling for this physical signal
* slot number of transmission
* RETURN : 0 if it is a valid slot for transmitting srs
* -1 if srs should not be transmitted
*
* DESCRIPTION : for periodic,
*
*********************************************************************/
int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource, NR_DL_FRAME_PARMS *frame_parms, int frame_tx, int slot_tx)
{
uint16_t T_SRS = srs_period[p_SRS_Resource->SRS_Periodicity];
uint16_t T_offset = p_SRS_Resource->SRS_Offset; /* FFS_TODO_NR to check interface */
if (T_offset > T_SRS) {
LOG_E(PHY,"is_srs_occasion_nr: T_offset %d is greater than T_SRS %d!\n", T_offset, T_SRS);
return (-1);
}
int16_t N_slot_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME * frame_parms->ttis_per_subframe;
if ((N_slot_frame*frame_tx + slot_tx - T_offset)%T_SRS == 0) {
return (0);
}
else {
return (-1);
}
}
/*******************************************************************
*
* NAME : ue_srs_procedure_nr
*
* PARAMETERS : pointer to ue context
* pointer to rxtx context*
*
* RETURN : 0 if it is a valid slot for transmitting srs
* -1 if srs should not be transmitted
*
* DESCRIPTION : ue srs procedure
* send srs according to current configuration
*
*********************************************************************/
int ue_srs_procedure_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_id)
{
NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms);
SRS_NR *p_srs_nr = &(ue->frame_parms.srs_nr);
SRS_ResourceSet_t *p_srs_resource_set = frame_parms->srs_nr.p_SRS_ResourceSetList[p_srs_nr->active_srs_Resource_Set];
int generate_srs = 0;
/* is there any resource set which has been configurated ? */
if (p_srs_nr->number_srs_Resource_Set != 0) {
/* what is the current active resource set ? */
if (p_srs_nr->active_srs_Resource_Set > MAX_NR_OF_SRS_RESOURCE_SET) {
LOG_W(PHY,"phy_procedures_UE_TX: srs active %d greater than maximum %d!\n", p_srs_nr->active_srs_Resource_Set, MAX_NR_OF_SRS_RESOURCE_SET);
}
else {
/* SRS resource set configurated ? */
if (p_srs_resource_set != NULL) {
SRS_Resource_t *p_srs_resource = frame_parms->srs_nr.p_SRS_ResourceSetList[p_srs_nr->active_srs_Resource_Set]->p_srs_ResourceList[0];
/* SRS resource configurated ? */
if (p_srs_resource != NULL) {
if (p_srs_resource_set->resourceType == periodic) {
if (is_srs_period_nr(p_srs_resource, frame_parms, proc->frame_tx, proc->nr_tti_tx) == 0) {
generate_srs = 1;
}
}
}
else {
LOG_W(PHY,"phy_procedures_UE_TX: no configurated srs resource!\n");
}
}
}
}
if (generate_srs == 1) {
int16_t txptr = AMP;
uint16_t nsymb = (ue->frame_parms.Ncp==0) ? 14:12;
uint16_t symbol_offset = (int)ue->frame_parms.ofdm_symbol_size*((proc->nr_tti_tx*nsymb)+(nsymb-1));
if (generate_srs_nr(p_srs_resource_set, frame_parms, &ue->common_vars.txdataF[eNB_id][symbol_offset], txptr, proc) == 0) {
return 0;
}
else
{
return (-1);
}
}
else {
return (-1);
}
}
@@ -0,0 +1,169 @@
/*
* 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
*/
/***********************************************************************
*
* FILENAME : srs_modulation_nr.h
*
* MODULE :
*
* DESCRIPTION : function to generate uplink reference sequences
* see 3GPP TS 38.211 6.4.1.4 Sounding reference signal
*
************************************************************************/
#ifndef SRS_MODULATION_NR_H
#define SRS_MODULATION_NR_H
#ifdef DEFINE_VARIABLES_SRS_MODULATION_NR_H
#define EXTERN
#define INIT_VARIABLES_SRS_MODULATION_NR_H
#else
#define EXTERN extern
#undef INIT_VARIABLES_SRS_MODULATION_NR_H
#endif
/************** DEFINE ********************************************/
#define C_SRS_NUMBER (64)
#define B_SRS_NUMBER (4)
/************** VARIABLES *****************************************/
/* TS 38.211 Table 6.4.1.4.3-1: SRS bandwidth configuration */
EXTERN const unsigned short srs_bandwidth_config[C_SRS_NUMBER][B_SRS_NUMBER][2]
#ifdef INIT_VARIABLES_SRS_MODULATION_NR_H
= {
/* B_SRS = 0 B_SRS = 1 B_SRS = 2 B_SRS = 3 */
/* C SRS m_srs0 N_0 m_srs1 N_1 m_srs2 N_2 m_srs3 N_3 */
/* 0 */ { { 4, 1 },{ 4, 1 },{ 4, 1 },{ 4, 1 } },
/* 1 */ { { 8, 1 },{ 4, 2 },{ 4, 1 },{ 4, 1 } },
/* 2 */ { { 12, 1 },{ 4, 3 },{ 4, 1 },{ 4, 1 } },
/* 3 */ { { 16, 1 },{ 4, 4 },{ 4, 1 },{ 4, 1 } },
/* 4 */ { { 16, 1 },{ 8, 2 },{ 4, 2 },{ 4, 1 } },
/* 5 */ { { 20, 1 },{ 4, 5 },{ 4, 1 },{ 4, 1 } },
/* 6 */ { { 24, 1 },{ 4, 6 },{ 4, 1 },{ 4, 1 } },
/* 7 */ { { 24, 1 },{ 12, 2 },{ 4, 3 },{ 4, 1 } },
/* 8 */ { { 28, 1 },{ 4, 7 },{ 4, 1 },{ 4, 1 } },
/* 9 */ { { 32, 1 },{ 16, 2 },{ 8, 2 },{ 4, 2 } },
/* 10 */ { { 36, 1 },{ 12, 3 },{ 4, 3 },{ 4, 1 } },
/* 11 */ { { 40, 1 },{ 20, 2 },{ 4, 5 },{ 4, 1 } },
/* 12 */ { { 48, 1 },{ 16, 3 },{ 8, 2 },{ 4, 2 } },
/* 13 */ { { 48, 1 },{ 24, 2 },{ 12, 2 },{ 4, 3 } },
/* 14 */ { { 52, 1 },{ 4, 13 },{ 4, 1 },{ 4, 1 } },
/* 15 */ { { 56, 1 },{ 28, 2 },{ 4, 7 },{ 4, 1 } },
/* 16 */ { { 60, 1 },{ 20, 3 },{ 4, 5 },{ 4, 1 } },
/* 17 */ { { 64, 1 },{ 32, 2 },{ 16, 2 },{ 4, 4 } },
/* 18 */ { { 72, 1 },{ 24, 3 },{ 12, 2 },{ 4, 3 } },
/* 19 */ { { 72, 1 },{ 36, 2 },{ 12, 3 },{ 4, 3 } },
/* 20 */ { { 76, 1 },{ 4, 19 },{ 4, 1 },{ 4, 1 } },
/* 21 */ { { 80, 1 },{ 40, 2 },{ 20, 2 },{ 4, 5 } },
/* 22 */ { { 88, 1 },{ 44, 2 },{ 4, 11 },{ 4, 1 } },
/* 23 */ { { 96, 1 },{ 32, 3 },{ 16, 2 },{ 4, 4 } },
/* 24 */ { { 96, 1 },{ 48, 2 },{ 24, 2 },{ 4, 6 } },
/* 25 */ { { 104, 1 },{ 52, 2 },{ 4, 13 },{ 4, 1 } },
/* 26 */ { { 112, 1 },{ 56, 2 },{ 28, 2 },{ 4, 7 } },
/* 27 */ { { 120, 1 },{ 60, 2 },{ 20, 3 },{ 4, 5 } },
/* 28 */ { { 120, 1 },{ 40, 3 },{ 8, 5 },{ 4, 2 } },
/* 29 */ { { 120, 1 },{ 24, 5 },{ 12, 2 },{ 4, 3 } },
/* 30 */ { { 128, 1 },{ 64, 2 },{ 32, 2 },{ 4, 8 } },
/* 31 */ { { 128, 1 },{ 64, 2 },{ 16, 4 },{ 4, 4 } },
/* 32 */ { { 128, 1 },{ 16, 8 },{ 8, 2 },{ 4, 2 } },
/* 33 */ { { 132, 1 },{ 44, 3 },{ 4, 11 },{ 4, 1 } },
/* 34 */ { { 136, 1 },{ 68, 2 },{ 4, 17 },{ 4, 1 } },
/* 35 */ { { 144, 1 },{ 72, 2 },{ 36, 2 },{ 4, 9 } },
/* 36 */ { { 144, 1 },{ 48, 3 },{ 24, 2 },{ 12, 2 } },
/* 37 */ { { 144, 1 },{ 48, 3 },{ 16, 3 },{ 4, 4 } },
/* 38 */ { { 144, 1 },{ 16, 9 },{ 8, 2 },{ 4, 2 } },
/* 39 */ { { 152, 1 },{ 76, 2 },{ 4, 19 },{ 4, 1 } },
/* 40 */ { { 160, 1 },{ 80, 2 },{ 40, 2 },{ 4, 10 } },
/* 41 */ { { 160, 1 },{ 80, 2 },{ 20, 4 },{ 4, 5 } },
/* 42 */ { { 160, 1 },{ 32, 5 },{ 16, 2 },{ 4, 4 } },
/* 43 */ { { 168, 1 },{ 84, 2 },{ 28, 3 },{ 4, 7 } },
/* 44 */ { { 176, 1 },{ 88, 2 },{ 44, 2 },{ 4, 11 } },
/* 45 */ { { 184, 1 },{ 92, 2 },{ 4, 23 },{ 4, 1 } },
/* 46 */ { { 192, 1 },{ 96, 2 },{ 48, 2 },{ 4, 12 } },
/* 47 */ { { 192, 1 },{ 96, 2 },{ 24, 4 },{ 4, 6 } },
/* 48 */ { { 192, 1 },{ 64, 3 },{ 16, 4 },{ 4, 4 } },
/* 49 */ { { 192, 1 },{ 24, 8 },{ 8, 3 },{ 4, 2 } },
/* 50 */ { { 208, 1 },{ 104, 2 },{ 52, 2 },{ 4, 13 } },
/* 51 */ { { 216, 1 },{ 108, 2 },{ 36, 3 },{ 4, 9 } },
/* 52 */ { { 224, 1 },{ 112, 2 },{ 56, 2 },{ 4, 14 } },
/* 53 */ { { 240, 1 },{ 120, 2 },{ 60, 2 },{ 4, 15 } },
/* 54 */ { { 240, 1 },{ 80, 3 },{ 20, 4 },{ 4, 5 } },
/* 55 */ { { 240, 1 },{ 48, 5 },{ 16, 3 },{ 8, 2 } },
/* 56 */ { { 240, 1 },{ 24, 10 },{ 12, 2 },{ 4, 3 } },
/* 57 */ { { 256, 1 },{ 128, 2 },{ 64, 2 },{ 4, 16 } },
/* 58 */ { { 256, 1 },{ 128, 2 },{ 32, 4 },{ 4, 8 } },
/* 59 */ { { 256, 1 },{ 16, 16 },{ 8, 2 },{ 4, 2 } },
/* 60 */ { { 264, 1 },{ 132, 2 },{ 44, 3 },{ 4, 11 } },
/* 61 */ { { 272, 1 },{ 136, 2 },{ 68, 2 },{ 4, 17 } },
/* 62 */ { { 272, 1 },{ 68, 4 },{ 4, 17 },{ 4, 1 } },
/* 63 */ { { 272, 1 },{ 16, 17 },{ 8, 2 },{ 4, 2 } },
}
#endif
;
#define SRS_PERIODICITY (17)
EXTERN const uint16_t srs_periodicity[SRS_PERIODICITY]
#ifdef INIT_VARIABLES_SRS_MODULATION_NR_H
= { 1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}
#endif
;
/*************** FUNCTIONS *****************************************/
/** \brief This function generates the sounding reference symbol (SRS) for the uplink according to 38.211 6.4.1.4 Sounding reference signal
@param frame_parms NR DL Frame parameters
@param txdataF pointer to the frequency domain TX signal
@param amp amplitude of generated signal
@param proc pointer to the transmit parameters
@returns 0 on success -1 on error with message */
int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
NR_DL_FRAME_PARMS *frame_parms,
int32_t *txptr,
int16_t amp,
UE_nr_rxtx_proc_t *proc);
/** \brief This function checks for periodic srs if srs should be transmitted in this slot
* @param p_SRS_Resource pointer to active resource
@param frame_parms NR DL Frame parameters
@param txdataF pointer to the frequency domain TX signal
@returns 0 if srs should be transmitted -1 on error with message */
int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource,
NR_DL_FRAME_PARMS *frame_parms,
int frame_tx, int slot_tx);
/** \brief This function processes srs configuration
* @param ue context
@param rxtx context
@param current eNB identifier
@returns 0 if srs is transmitted -1 otherwise */
int ue_srs_procedure_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_id);
#undef EXTERN
#undef INIT_VARIABLES_SRS_MODULATION_NR_H
#endif /* SRS_MODULATION_NR_H */
+603
View File
@@ -0,0 +1,603 @@
/*
* 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
*/
/**********************************************************************
*
* FILENAME : sss_nr.c
*
* MODULE : Functions for secundary synchronisation signal
*
* DESCRIPTION : generation of sss
* 3GPP TS 38.211 7.4.2.3 Secondary synchronisation signal
*
************************************************************************/
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include "PHY/defs_nr_UE.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/NR_REFSIG/ss_pbch_nr.h"
#define DEFINE_VARIABLES_SSS_NR_H
#include "PHY/NR_REFSIG/sss_nr.h"
#undef DEFINE_VARIABLES_SSS_NR_H
/*******************************************************************
*
* NAME : init_context_sss_nr
*
* PARAMETERS : N_ID_2 : element 2 of physical layer cell identity
* value : { 0, 1, 2 }
*
* RETURN : generate binary sss sequence (this is a m-sequence)
* d_sss is a third dimension array depending on
* Cell identity elements:
* - N_ID_1 : value from 0 to 335
* - N_ID_2 : value from 0 to 2
*
* DESCRIPTION : 3GPP TS 38.211 7.4.2.3 Secundary synchronisation signal
* Sequence generation
*
*********************************************************************/
#define INITIAL_SSS_NR (7)
void init_context_sss_nr(int amp)
{
int16_t x0[LENGTH_SSS_NR];
int16_t x1[LENGTH_SSS_NR];
int16_t dss_current;
int m0, m1;
const int x0_initial[INITIAL_SSS_NR] = { 1, 0, 0, 0, 0, 0, 0 };
const int x1_initial[INITIAL_SSS_NR] = { 1, 0, 0, 0, 0, 0, 0 };
for (int i=0; i < INITIAL_SSS_NR; i++) {
x0[i] = x0_initial[i];
x1[i] = x1_initial[i];
}
for (int i=0; i < (LENGTH_SSS_NR - INITIAL_SSS_NR); i++) {
x0[i+7] = (x0[i + 4] + x0[i])%(2);
x1[i+7] = (x1[i + 1] + x1[i])%(2);
}
for (int N_ID_2 = 0; N_ID_2 < N_ID_2_NUMBER; N_ID_2++) {
for (int N_ID_1 = 0; N_ID_1 < N_ID_1_NUMBER; N_ID_1++) {
m0 = 15*(N_ID_1/112) + (5*N_ID_2);
m1 = N_ID_1%112;
for (int n = 0; n < LENGTH_SSS_NR; n++) {
dss_current = (1 - 2*x0[(n + m0)%(LENGTH_SSS_NR)])*(1 - 2*x1[(n + m1)%(LENGTH_SSS_NR)]);
/* Modulation of SSS is a BPSK TS 36.211 chapter 5.1.2 BPSK */
#if 1
d_sss[N_ID_2][N_ID_1][n] = dss_current * amp;
#else
(void) amp;
d_sss[N_ID_2][N_ID_1][n] = (dss_current * SHRT_MAX)>>SCALING_PSS_NR;
#endif
}
}
}
#if 0
for (int i = 0; i < LENGTH_SSS_NR; i++) {
printf("sss ref[%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
}
#endif
}
/*******************************************************************
*
* NAME : insert_sss_nr
*
* PARAMETERS : pointer to input buffer for which sss in inserted
* amp amplitude applied to input
* frame parameters for cell identity
*
* RETURN : none
*
* DESCRIPTION : Allow to generate a reference sss sequence according to cell identity
*
*********************************************************************/
void insert_sss_nr(int16_t *sss_time,
NR_DL_FRAME_PARMS *frame_parms)
{
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
unsigned int size = ofdm_symbol_size * IQ_SIZE; /* i & q */
assert(size <= SYNCF_TMP_SIZE);
assert(size <= SYNC_TMP_SIZE);
bzero(synchroF_tmp, size);
bzero(synchro_tmp, size);
int Nid2 = GET_NID2(frame_parms->Nid_cell);
int Nid1 = GET_NID1(frame_parms->Nid_cell);
/* call of IDFT should be done with ordered input as below
*
* n input samples
* <------------------------------------------------>
* 0 n
* are written into input buffer for IFFT in this order
* -------------------------------------------------
* |xxxxxxx N/2 xxxxxxxx|
* --------------------------------------------------
* ^ ^ ^ ^ ^
* | | | | |
* n/2 end of n=0 start of n/2-1
* sss sss
*
* Frequencies
* positives negatives
* 0 (+N/2)(-N/2)
* |-----------------------><-------------------------|
*
* sample 0 is for continuous frequency which is not used here
*/
unsigned int k = ofdm_symbol_size - ((LENGTH_SSS_NR/2)+1);
/* SSS is directly mapped to subcarrier */
for (int i=0; i<LENGTH_SSS_NR; i++) {
synchroF_tmp[2*k] = d_sss[Nid2][Nid1][i];
synchroF_tmp[2*k+1] = 0;
k++;
if (k >= ofdm_symbol_size) {
k++;
k-=ofdm_symbol_size;
}
}
/* get sss in the frequency domain by applying an inverse FFT */
idft2048(synchroF_tmp, /* complex input */
synchro_tmp, /* complex output */
1); /* scaling factor */
/* then get final sss in time */
for (unsigned int i=0; i<ofdm_symbol_size; i++) {
((int32_t *)sss_time)[i] = ((int32_t *)synchro_tmp)[i];
}
}
/*******************************************************************
*
* NAME : pss_ch_est
*
* PARAMETERS : none
*
* RETURN : none
*
* DESCRIPTION : pss channel estimation
*
*********************************************************************/
int pss_ch_est_nr(PHY_VARS_NR_UE *ue,
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR])
{
int16_t *pss;
int16_t *pss_ext2,*sss_ext2,*sss_ext3,tmp_re,tmp_im,tmp_re2,tmp_im2;
uint8_t aarx,i;
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
pss = primary_synchro_nr[ue->common_vars.eNb_id];
sss_ext3 = (int16_t*)&sss_ext[0][0];
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
sss_ext2 = (int16_t*)&sss_ext[aarx][0];
pss_ext2 = (int16_t*)&pss_ext[aarx][0];
#if 0
int16_t *p = pss;
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" pss ref [%d] %d %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]);
printf(" pss ext [%d] %d %d at address %p\n", i, pss_ext2[2*i], pss_ext2[2*i+1], &pss_ext2[2*i]);
}
#endif
#if 0
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" sss ext 2 [%d] %d %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1], &sss_ext2[2*i]);
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]);
}
#endif
for (i = 0; i < LENGTH_PSS_NR; i++) {
// This is H*(PSS) = R* \cdot PSS
tmp_re = (int16_t)(((pss_ext2[i*2] * (int32_t)pss[i*2])>>SCALING_CE_PSS_NR) + ((pss_ext2[i*2+1] * (int32_t)pss[i*2+1])>>SCALING_CE_PSS_NR));
tmp_im = (int16_t)(((pss_ext2[i*2] * (int32_t)pss[i*2+1])>>SCALING_CE_PSS_NR) - ((pss_ext2[i*2+1] * (int32_t)pss[i*2])>>SCALING_CE_PSS_NR));
//printf("H*(%d,%d) : (%d,%d)\n",aarx,i,tmp_re,tmp_im);
//printf("pss(%d,%d) : (%d,%d)\n",aarx,i,pss[2*i],pss[2*i+1]);
//printf("pss_ext(%d,%d) : (%d,%d)\n",aarx,i,pss_ext2[2*i],pss_ext2[2*i+1]);
// This is R(SSS) \cdot H*(PSS)
tmp_re2 = (int16_t)(((tmp_re * (int32_t)sss_ext2[i*2])>>SCALING_CE_PSS_NR) - ((tmp_im * (int32_t)sss_ext2[i*2+1]>>SCALING_CE_PSS_NR)));
tmp_im2 = (int16_t)(((tmp_re * (int32_t)sss_ext2[i*2+1])>>SCALING_CE_PSS_NR) + ((tmp_im * (int32_t)sss_ext2[i*2]>>SCALING_CE_PSS_NR)));
// printf("SSSi(%d,%d) : (%d,%d)\n",aarx,i,sss_ext2[i<<1],sss_ext2[1+(i<<1)]);
// printf("SSSo(%d,%d) : (%d,%d)\n",aarx,i,tmp_re2,tmp_im2);
// MRC on RX antennas
if (aarx==0) {
sss_ext3[i<<1] = tmp_re2;
sss_ext3[1+(i<<1)] = tmp_im2;
} else {
sss_ext3[i<<1] += tmp_re2;
sss_ext3[1+(i<<1)] += tmp_im2;
}
}
}
#if 0
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" sss ext 2 [%d] %d %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1]);
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i]);
printf(" sss ext 3 [%d] %d %d at address %p\n", i, sss_ext3[2*i], sss_ext3[2*i+1]);
}
#endif
// sss_ext now contains the compensated SSS
return(0);
}
/*******************************************************************
*
* NAME : do_pss_sss_extract
*
* PARAMETERS : none
*
* RETURN : none
*
* DESCRIPTION : it allows extracting sss from samples buffer
*
*********************************************************************/
int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue,
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
uint8_t doPss, uint8_t doSss,
uint8_t subframe) // add flag to indicate extracting only PSS, only SSS, or both
{
uint8_t aarx;
int32_t *pss_rxF,*pss_rxF_ext;
int32_t *sss_rxF,*sss_rxF_ext;
uint8_t pss_symbol, sss_symbol;
int32_t **rxdataF;
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
#if 1
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
pss_symbol = PSS_SYMBOL_NB; /* symbol position */
sss_symbol = SSS_SYMBOL_NB;
rxdataF = ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF;
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
pss_rxF = &rxdataF[aarx][pss_symbol*ofdm_symbol_size];
sss_rxF = &rxdataF[aarx][sss_symbol*ofdm_symbol_size];
pss_rxF_ext = &pss_ext[aarx][0];
sss_rxF_ext = &sss_ext[aarx][0];
unsigned int k = ofdm_symbol_size - ((LENGTH_PSS_NR/2)+1);
for (int i=0; i < LENGTH_PSS_NR; i++) {
if (doPss) {
pss_rxF_ext[i] = pss_rxF[k];
}
if (doSss) {
sss_rxF_ext[i] = sss_rxF[k];
}
k++;
if (k >= ofdm_symbol_size) {
k++;
k-=ofdm_symbol_size;
}
}
}
#if 0
int16_t *p = (int16_t *)sss_rxF_ext;
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" sss ext 2 [%d] %d %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]);
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]);
}
#endif
#if 0
int16_t *p2 = (int16_t *)pss_rxF_ext;
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" pss_rxF_ext [%d] %d %d at address %p\n", i, p2[2*i], p2[2*i+1], &p2[2*i]);
}
#endif
#else
/* same method as LTE implementation */
uint16_t rb,nb_rb = N_RB_SS_PBCH_BLOCK;
int rx_offset = frame_parms->ofdm_symbol_size - (LENGTH_SSS_NR/2);
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
pss_symbol = PSS_SYMBOL_NB;
sss_symbol = SSS_SYMBOL_NB;
rxdataF = ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF;
pss_rxF = &rxdataF[aarx][(rx_offset + (pss_symbol*(frame_parms->ofdm_symbol_size)))];
sss_rxF = &rxdataF[aarx][(rx_offset + (sss_symbol*(frame_parms->ofdm_symbol_size)))];
//printf("extract_rbs: symbol_mod=%d, rx_offset=%d, ch_offset=%d\n",symbol_mod,
// (rx_offset + (symbol*(frame_parms->ofdm_symbol_size)))*2,
// LTE_CE_OFFSET+ch_offset+(symbol_mod*(frame_parms->ofdm_symbol_size)));
pss_rxF_ext = &pss_ext[aarx][0];
sss_rxF_ext = &sss_ext[aarx][0];
for (rb=0; rb<nb_rb; rb++) {
for (int i=0; i<N_SC_RB; i++) {
if (doPss) {pss_rxF_ext[i] = pss_rxF[i];}
if (doSss) {sss_rxF_ext[i] = sss_rxF[i];}
}
pss_rxF += N_SC_RB;
sss_rxF += N_SC_RB;
pss_rxF_ext += N_SC_RB;
sss_rxF_ext += N_SC_RB;
}
}
#endif
return(0);
}
/*******************************************************************
*
* NAME : rx_sss_nr
*
* PARAMETERS : none
*
* RETURN : none
*
* DESCRIPTION :
*
*********************************************************************/
int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue,
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
uint8_t subframe)
{
return do_pss_sss_extract_nr(phy_vars_ue, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, subframe);
}
/*******************************************************************
*
* NAME : rx_sss_nr
*
* PARAMETERS : none
*
* RETURN : Set Nid_cell in ue context
*
* DESCRIPTION : Determine element Nid1 of cell identity
* so Nid_cell in ue context is set according to Nid1 & Nid2
*
*********************************************************************/
int rx_sss_nr(PHY_VARS_NR_UE *ue, int32_t *tot_metric,uint8_t *phase_max)
{
uint8_t i;
int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR];
uint8_t Nid2 = GET_NID2(ue->common_vars.eNb_id);
uint16_t Nid1;
uint8_t phase;
int16_t *sss;
NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
int32_t metric, metric_re;
int16_t *d;
/* slop_fep function works for lte and takes into account begining of frame with prefix for subframe 0 */
/* for NR this is not the case but slot_fep is still used for computing FFT of samples */
/* in order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */
/* symbol number are from beginning of SS/PBCH blocks as below: */
/* Signal PSS PBCH SSS PBCH */
/* symbol number 0 1 2 3 */
/* time samples in buffer rxdata are used as input of FFT -> FFT results are stored in the frequency buffer rxdataF */
/* rxdataF stores SS/PBCH from beginning of buffers in the same symbol order as in time domain */
int nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
frame_parms->nb_prefix_samples0 = 0;
// Do FFTs for SSS/PSS
// SSS
slot_fep_pbch(ue,
SSS_SYMBOL_NB, // symbol number
0, // Ns slot number
ue->rx_offset, // sample_offset of int16_t
0, // no_prefix
1); // reset frequency estimation
// PSS
slot_fep_pbch(ue,
PSS_SYMBOL_NB,
0,
ue->rx_offset,
0,
1);
frame_parms->nb_prefix_samples0 = nb_prefix_samples0;
// pss sss extraction
pss_sss_extract_nr(ue,
pss_ext,
sss_ext,
0); /* subframe */
#ifdef DEBUG_PLOT_SSS
write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_tti,1,1);
write_output("rxdataF0.m","rxF0",&ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[0]].rxdataF[0],frame_parms->ofdm_symbol_size,2,1);
write_output("pss_ext.m","pss_ext",pss_ext,LENGTH_PSS_NR,1,1);
#endif
#if 0
write_output("sss_ext.m","sss_ext",sss_ext,LENGTH_SSS_NR,1,1);
write_output("sss_ref.m","sss_ref", d_sss,LENGTH_SSS_NR,1,1);
#endif
#if 0
int16_t *p = (int16_t *)sss_ext[0];
int16_t *p2 = (int16_t *)pss_ext[0];
for (int i = 0; i < LENGTH_SSS_NR; i++) {
printf("sss ref [%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
printf("sss ext [%i] : %d %d \n", i, p[2*i], p[2*i+1]);
printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr[0][2*i], primary_synchro_nr[0][2*i+1]);
printf("pss ext [%i] : %d %d \n", i, p2[2*i], p2[2*i+1]);
}
#endif
// get conjugated channel estimate from PSS, H* = R* \cdot PSS
// and do channel estimation and compensation based on PSS
pss_ch_est_nr(ue,
pss_ext,
sss_ext);
// now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.h
*tot_metric = INT_MIN;
sss = (int16_t*)&sss_ext[0][0];
#if 0
/* simulate of a phase shift on the signal */
int phase_shift_index = 0;
phase_shift_samples(sss, LENGTH_SSS_NR, phase_re_nr[phase_shift_index], phase_im_nr[phase_shift_index]);
#endif
#if 0
int16_t *ps = (int16_t *)pss_ext;
for (int i = 0; i < LENGTH_SSS_NR; i++) {
printf("sss ref [%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
printf("sss ext [%i] : %d %d \n", i, sss[2*i], sss[2*i+1]);
printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr[0][2*i], primary_synchro_nr[0][2*i+1]);
printf("pss ext [%i] : %d %d \n", i, ps[2*i], ps[2*i+1]);
}
#endif
/* for phase evaluation, one uses an array of possible phase shifts */
/* then a correlation is done between received signal with a shift pĥase and the reference signal */
/* Computation of signal with shift phase is based on below formula */
/* cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */
/* sinus sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */
for (phase=0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS
for (Nid1 = 0 ; Nid1 < N_ID_1_NUMBER; Nid1++) { // all possible Nid1 values
metric = 0;
metric_re = 0;
d = (int16_t *)&d_sss[Nid2][Nid1];
// This is the inner product using one particular value of each unknown parameter
for (i=0; i < LENGTH_SSS_NR; i++) {
metric_re += d[i]*(((phase_re_nr[phase]*sss[2*i])>>SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase]*sss[2*i+1])>>SCALING_METRIC_SSS_NR))
+ d[i]*(((phase_im_nr[phase]*sss[2*i])>>SCALING_METRIC_SSS_NR) + ((phase_re_nr[phase]*sss[2*i+1])>>SCALING_METRIC_SSS_NR));
}
metric = metric_re;
// if the current metric is better than the last save it
if (metric > *tot_metric) {
*tot_metric = metric;
ue->frame_parms.Nid_cell = Nid2+(3*Nid1);
*phase_max = phase;
#ifdef DEBUG_SSS_NR
printf("(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max);
#endif
}
}
}
#ifdef DEBUG_SSS_NR
#define SSS_METRIC_FLOOR_NR (30000)
if (*tot_metric > SSS_METRIC_FLOOR_NR) {
Nid2 = GET_NID2(frame_parms->Nid_cell);
Nid1 = GET_NID1(frame_parms->Nid_cell);
printf("Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
}
#endif
return(0);
}
+1016 -5
View File
File diff suppressed because it is too large Load Diff
+48 -1
View File
@@ -34,6 +34,7 @@
#define __PHY_DEFS_NR_COMMON__H__
#include "defs_common.h"
#include "impl_defs_nr.h"
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
#define nr_subframe_t lte_subframe_t
@@ -73,6 +74,14 @@ typedef enum{
} nr_ssb_type_e;
typedef struct NR_DL_FRAME_PARMS {
/// Number of resource blocks (RB) in DL
uint8_t N_RB_DL;
/// Number of resource blocks (RB) in UL
uint8_t N_RB_UL;
/// total Number of Resource Block Groups: this is ceil(N_PRB/P)
uint8_t N_RBG;
/// Total Number of Resource Block Groups SubSets: this is P
uint8_t N_RBGS;
/// EUTRA Band
uint8_t eutra_band;
/// DL carrier frequency
@@ -84,6 +93,13 @@ typedef struct NR_DL_FRAME_PARMS {
/// RX attenuation
uint32_t att_rx;
/// total Number of Resource Block Groups: this is ceil(N_PRB/P)
/// Frame type (0 FDD, 1 TDD)
lte_frame_type_t frame_type;
/// TDD subframe assignment (0-7) (default = 3) (254=RX only, 255=TX only)
uint8_t tdd_config;
/// TDD S-subframe configuration (0-9)
/// Cell ID
uint16_t Nid_cell;
uint32_t subcarrier_spacing;
/// 3/4 sampling
uint8_t threequarter_fs;
@@ -101,14 +117,45 @@ typedef struct NR_DL_FRAME_PARMS {
uint16_t slots_per_subframe;
/// Number of samples in a subframe
uint32_t samples_per_subframe;
/// Number of OFDM/SC-FDMA symbols in one subframe (to be modified to account for potential different in UL/DL)
uint16_t symbols_per_tti;
/// Number of samples in a radio frame
uint32_t samples_per_frame;
/// Number of samples in a subframe without CP
uint32_t samples_per_subframe_wCP;
/// Number of samples in a radio frame without CP
uint32_t samples_per_frame_wCP;
/// Number of samples in a tti (same as subrame in LTE, depending on numerology in NR)
uint32_t samples_per_tti;
/// NR numerology index [0..5] as specified in 38.211 Section 4 (mu). 0=15khZ SCS, 1=30khZ, 2=60kHz, etc
uint8_t numerology_index;
/// NR number of ttis per subframe deduced from numerology (cf 38.211): 1, 2, 4, 8(not supported),16(not supported),32(not supported)
uint8_t ttis_per_subframe;
/// NR number of slots per tti . Assumption only 2 Slot per TTI is supported (Slot Config 1 in 38.211)
uint8_t slots_per_tti;
//#endif
/// Number of Physical transmit antennas in node
uint8_t nb_antennas_tx;
/// Number of Receive antennas in node
uint8_t nb_antennas_rx;
/// Number of common transmit antenna ports in eNodeB (1 or 2)
uint8_t nb_antenna_ports_eNB;
/// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
lte_prefix_type_t Ncp;
/// SRS configuration from TS 38.331 RRC
SRS_NR srs_nr;
//SSB related params
/// for NR TDD management
TDD_UL_DL_configCommon_t *p_tdd_UL_DL_Configuration;
TDD_UL_DL_configCommon_t *p_tdd_UL_DL_ConfigurationCommon2;
TDD_UL_DL_SlotConfig_t *p_TDD_UL_DL_ConfigDedicated;
/// TDD configuration
uint16_t tdd_uplink_nr[MAX_NR_OF_SLOTS]; /* this is a bitmap of symbol of each slot given for 2 frames */
//SSB related params
/// Start in Subcarrier index of the SSB block
uint16_t ssb_start_subcarrier;
/// SSB type
+345
View File
@@ -0,0 +1,345 @@
/*
* 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
*/
/***********************************************************************
*
* FILENAME : impl_defs_nr.h
*
* MODULE :
*
* DESCRIPTION : NR Physical channel configuration and variable structure definitions
* This is an interface between ue physical layer and RRC message from network
* see TS 38.336 Radio Resource Control (RRC) protocol specification
*
************************************************************************/
#ifndef PHY_IMPL_DEFS_NR_H
#define PHY_IMPL_DEFS_NR_H
#include "types.h"
#ifdef DEFINE_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
#define EXTERN
#define INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
#else
#define EXTERN extern
#undef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
#endif
#ifdef PHY_DBG_DEV_TST
#define PHY_DBG_DEV_TST_PRINTF(...) printf(__VA_ARGS__)
#else
#define PHY_DBG_DEV_TST_PRINTF(...)
#endif
/* to set for UE capabilities */
#define MAX_NR_OF_SRS_RESOURCE_SET (1)
#define MAX_NR_OF_SRS_RESOURCES_PER_SET (1)
#define NR_NUMBER_OF_SUBFRAMES_PER_FRAME (10)
#define MAX_NROFSRS_PORTS (4)
/* TS 38.211 Table 4.3.2-1: Number of OFDM symbols per slot, slots per frame, and slots per subframe for normal cyclic prefix */
#define MU_NUMBER (5)
EXTERN const uint8_t N_slot_subframe[MU_NUMBER]
#ifdef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
= { 1, 2, 4, 8, 16}
#endif
;
/***********************************************************************
*
* FUNCTIONALITY : Time Division Duplex
*
* DESCRIPTION : interface for FDD/TDD configuration
*
************************************************************************/
#define MAX_NR_OF_SLOTS (320) /* maximum number of slots for tdd configuration which is periodic */
#define NR_TDD_DOWNLINK_SLOT (0x0000)
#define NR_TDD_UPLINK_SLOT (0x3FFF) /* uplink bitmap for each symbol, there are 14 symbols per slots */
#define NR_TDD_SET_ALL_SYMBOLS (0x3FFF)
#define FRAME_DURATION_MICRO_SEC (10000) /* frame duration in microsecond */
typedef enum {
SLOT_DL = 0,
SLOT_UL = 1,
} nr_slot_t;
typedef enum {
ms0p5 = 500, /* duration is given in microsecond */
ms0p625 = 625,
ms1 = 1000,
ms1p25 = 1250,
ms2 = 2000,
ms2p5 = 2500,
ms5 = 5000,
ms10 = 10000,
} dl_UL_TransmissionPeriodicity_t;
typedef struct {
/// Reference SCS used to determine the time domain boundaries in the UL-DL pattern which must be common across all subcarrier specific
/// virtual carriers, i.e., independent of the actual subcarrier spacing using for data transmission.
/// Only the values 15 or 30 kHz (<6GHz), 60 or 120 kHz (>6GHz) are applicable.
/// Corresponds to L1 parameter 'reference-SCS' (see 38.211, section FFS_Section)
/// \ subcarrier spacing
uint8_t referenceSubcarrierSpacing;
/// \ Periodicity of the DL-UL pattern. Corresponds to L1 parameter 'DL-UL-transmission-periodicity' (see 38.211, section FFS_Section)
dl_UL_TransmissionPeriodicity_t dl_UL_TransmissionPeriodicity;
/// \ Number of consecutive full DL slots at the beginning of each DL-UL pattern.
/// Corresponds to L1 parameter 'number-of-DL-slots' (see 38.211, Table 4.3.2-1)
uint8_t nrofDownlinkSlots;
/// \ Number of consecutive DL symbols in the beginning of the slot following the last full DL slot (as derived from nrofDownlinkSlots).
/// If the field is absent or released, there is no partial-downlink slot.
/// Corresponds to L1 parameter 'number-of-DL-symbols-common' (see 38.211, section FFS_Section).
uint8_t nrofDownlinkSymbols;
/// \ Number of consecutive full UL slots at the end of each DL-UL pattern.
/// Corresponds to L1 parameter 'number-of-UL-slots' (see 38.211, Table 4.3.2-1)
uint8_t nrofUplinkSlots;
/// \ Number of consecutive UL symbols in the end of the slot preceding the first full UL slot (as derived from nrofUplinkSlots).
/// If the field is absent or released, there is no partial-uplink slot.
/// Corresponds to L1 parameter 'number-of-UL-symbols-common' (see 38.211, section FFS_Section)
uint8_t nrofUplinkSymbols;
/// \ for setting a sequence
struct TDD_UL_DL_configCommon_t *p_next_TDD_UL_DL_configCommon_t;
} TDD_UL_DL_configCommon_t;
typedef struct {
/// \ Identifies a slot within a dl-UL-TransmissionPeriodicity (given in tdd-UL-DL-configurationCommon)
uint16_t slotIndex;
/// \ The direction (downlink or uplink) for the symbols in this slot. "allDownlink" indicates that all symbols in this slot are used
/// for downlink; "allUplink" indicates that all symbols in this slot are used for uplink; "explicit" indicates explicitly how many symbols
/// in the beginning and end of this slot are allocated to downlink and uplink, respectively.
/// Number of consecutive DL symbols in the beginning of the slot identified by slotIndex.
/// If the field is absent the UE assumes that there are no leading DL symbols.
/// Corresponds to L1 parameter 'number-of-DL-symbols-dedicated' (see 38.211, section FFS_Section)
uint16_t nrofDownlinkSymbols;
/// Number of consecutive UL symbols in the end of the slot identified by slotIndex.
/// If the field is absent the UE assumes that there are no trailing UL symbols.
/// Corresponds to L1 parameter 'number-of-UL-symbols-dedicated' (see 38.211, section FFS_Section)
uint16_t nrofUplinkSymbols;
/// \ for setting a sequence
struct TDD_UL_DL_SlotConfig_t *p_next_TDD_UL_DL_SlotConfig;
} TDD_UL_DL_SlotConfig_t;
/***********************************************************************
*
* FUNCTIONALITY : Sounding Reference Signal
*
* DESCRIPTION : interface description for managing uplink SRS signals from UE
* SRS are generated by UE and transmit to network
* depending on configuration
*
************************************************************************/
EXTERN const int16_t SRS_antenna_port[MAX_NROFSRS_PORTS]
#ifdef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
= { 1000, 1001, 1002, 1003 }
#endif
;
typedef enum {
port1 = 1,
port2 = 2,
port4 = 4
} nrof_Srs_Ports_t;
typedef enum {
neitherHopping = 0,
groupHopping = 1,
sequenceHopping = 2
} groupOrSequenceHopping_t;
typedef enum {
aperiodic = 0,
semi_persistent = 1,
periodic = 2
} resourceType_t;
typedef enum {
sl1 = 0,
sl2 = 1,
sl4 = 2,
sl5 = 3,
sl8 = 4,
sl10 = 5,
sl16 = 6,
sl20 = 7,
sl32 = 8,
sl40 = 9,
sl64 = 10,
sl80 = 11,
sl160 = 12,
sl320 = 13,
sl640 = 14,
sl1280 = 15,
sl2560 = 16
} SRS_Periodicity_t;
#define NB_SRS_PERIOD (17)
const uint16_t srs_period[NB_SRS_PERIOD]
#ifdef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
= { 1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}
#endif
;
/// SRS_Resource of SRS_Config information element from 38.331 RRC specifications
typedef struct {
/// \brief srs resource identity.
uint8_t srs_ResourceId;
/// \brief number of srs ports.
nrof_Srs_Ports_t nrof_SrsPorts;
/// \brief index of prts port index.
uint8_t ptrs_PortIndex;
/// \brief srs transmission comb see parameter SRS-TransmissionComb 38.214 section &6.2.1.
uint8_t transmissionComb;
/// \brief comb offset.
uint8_t combOffset;
/// \brief cyclic shift configuration - see parameter SRS-CyclicShiftConfig 38.214 &6.2.1.
uint8_t cyclicShift;
/// \brief OFDM symbol location of the SRS resource within a slot.
// Corresponds to L1 parameter 'SRS-ResourceMapping' (see 38.214, section 6.2.1 and 38.211, section 6.4.1.4).
// startPosition (SRSSymbolStartPosition = 0..5; "0" refers to the last symbol, "1" refers to the second last symbol.
uint8_t resourceMapping_startPosition;
/// \brief number of OFDM symbols (N = 1, 2 or 4 per SRS resource).
uint8_t resourceMapping_nrofSymbols;
/// \brief RepetitionFactor (r = 1, 2 or 4).
uint8_t resourceMapping_repetitionFactor;
/// \brief Parameter(s) defining frequency domain position and configurable shift to align SRS allocation to 4 PRB grid.
// Corresponds to L1 parameter 'SRS-FreqDomainPosition' (see 38.214, section 6.2.1)
uint8_t freqDomainPosition; // INTEGER (0..67),
uint16_t freqDomainShift; // INTEGER (0..268),
/// \brief Includes parameters capturing SRS frequency hopping
// Corresponds to L1 parameter 'SRS-FreqHopping' (see 38.214, section 6.2.1)
uint8_t freqHopping_c_SRS; // INTEGER (0..63),
uint8_t freqHopping_b_SRS; // INTEGER (0..3),
uint8_t freqHopping_b_hop; // INTEGER (0..3)
// Parameter(s) for configuring group or sequence hopping
// Corresponds to L1 parameter 'SRS-GroupSequenceHopping' see 38.211
groupOrSequenceHopping_t groupOrSequenceHopping;
/// \brief Time domain behavior of SRS resource configuration.
// Corresponds to L1 parameter 'SRS-ResourceConfigType' (see 38.214, section 6.2.1).
// For codebook based uplink transmission, the network configures SRS resources in the same resource set with the same
// time domain behavior on periodic, aperiodic and semi-persistent SRS
SRS_Periodicity_t SRS_Periodicity;
uint16_t SRS_Offset;
/// \brief Sequence ID used to initialize psedo random group and sequence hopping.
// Corresponds to L1 parameter 'SRS-SequenceId' (see 38.214, section 6.2.1).
uint16_t sequenceId; // BIT STRING (SIZE (10))
/// \brief Configuration of the spatial relation between a reference RS and the target SRS. Reference RS can be SSB/CSI-RS/SRS.
// Corresponds to L1 parameter 'SRS-SpatialRelationInfo' (see 38.214, section 6.2.1)
uint8_t spatialRelationInfo_ssb_Index; // SSB-Index,
uint8_t spatialRelationInfo_csi_RS_Index; // NZP-CSI-RS-ResourceId,
uint8_t spatialRelationInfo_srs_Id; // SRS-ResourceId
} SRS_Resource_t;
typedef enum {
beamManagement = 0,
codebook = 1,
nonCodebook = 2,
antennaSwitching = 3,
} SRS_resourceSet_usage_t;
typedef enum {
sameAsFci2 = 0,
separateClosedLoop = 1
} srs_PowerControlAdjustmentStates_t;
typedef enum {
ssb_Index = 0,
csi_RS_Index = 1,
} pathlossReferenceRS_t;
// SRS_Config information element from 38.331 RRC specifications from 38.331 RRC specifications.
typedef struct {
/// \brief The ID of this resource set. It is unique in the context of the BWP in which the parent SRS-Config is defined.
uint8_t srs_ResourceSetId;
/// \brief number of resources in the resource set
uint8_t number_srs_Resource;
/// \brief The IDs of the SRS-Resources used in this SRS-ResourceSet.
/// in fact this is an array of pointers to resource structures
SRS_Resource_t *p_srs_ResourceList[MAX_NR_OF_SRS_RESOURCES_PER_SET];
resourceType_t resourceType;
/// \brief The DCI "code point" upon which the UE shall transmit SRS according to this SRS resource set configuration.
// Corresponds to L1 parameter 'AperiodicSRS-ResourceTrigger' (see 38.214, section 6.1.1.2)
uint8_t aperiodicSRS_ResourceTrigger; // INTEGER (0..maxNrofSRS-TriggerStates-1) : [0:3]
/// \brief ID of CSI-RS resource associated with this SRS resource set. (see 38.214, section 6.1.1.2).
uint8_t NZP_CSI_RS_ResourceId;
/// \brief An offset in number of slots between the triggering DCI and the actual transmission of this SRS-ResourceSet.
// If the field is absent the UE applies no offset (value 0)
uint8_t aperiodic_slotOffset; // INTEGER (1..8)
/// \brief Indicates if the SRS resource set is used for beam management vs. used for either codebook based or non-codebook based transmission.
// Corresponds to L1 parameter 'SRS-SetUse' (see 38.214, section 6.2.1)
// FFS_CHECK: Isn't codebook/noncodebook already known from the ulTxConfig in the SRS-Config? If so, isn't the only distinction
// in the set between BeamManagement, AtennaSwitching and "Other”? Or what happens if SRS-Config=Codebook but a Set=NonCodebook?
SRS_resourceSet_usage_t usage;
/// \brief alpha value for SRS power control. Corresponds to L1 parameter 'alpha-srs' (see 38.213, section 7.3).
// When the field is absent the UE applies the value 1
uint8_t alpha;
/// \brief P0 value for SRS power control. The value is in dBm. Only even values (step size 2) are allowed.
// Corresponds to L1 parameter 'p0-srs' (see 38.213, section 7.3)
int8_t p0; // INTEGER (-202..24)
/// \brief A reference signal (e.g. a CSI-RS config or a SSblock) to be used for SRS path loss estimation.
/// Corresponds to L1 parameter 'srs-pathlossReference-rs-config' (see 38.213, section 7.3)
pathlossReferenceRS_t pathlossReferenceRS_t;
uint8_t path_loss_SSB_Index;
uint8_t path_loss_NZP_CSI_RS_ResourceId;
/// \brief Indicates whether hsrs,c(i) = fc(i,1) or hsrs,c(i) = fc(i,2) (if twoPUSCH-PC-AdjustmentStates are configured)
/// or separate close loop is configured for SRS. This parameter is applicable only for Uls on which UE also transmits PUSCH.
/// If absent or release, the UE applies the value sameAs-Fci1
/// Corresponds to L1 parameter 'srs-pcadjustment-state-config' (see 38.213, section 7.3)
srs_PowerControlAdjustmentStates_t srs_PowerControlAdjustmentStates;
} SRS_ResourceSet_t;
typedef struct {
uint8_t active_srs_Resource_Set; /* ue implementation specific */
uint8_t number_srs_Resource_Set; /* ue implementation specific */
SRS_ResourceSet_t *p_SRS_ResourceSetList[MAX_NR_OF_SRS_RESOURCE_SET]; /* ue implementation specific */
} SRS_NR;
//#define RX_NB_TH_MAX 3
//#define RX_NB_TH 3
#define LTE_SLOTS_PER_SUBFRAME 2
#define LTE_NUMBER_OF_SUBFRAMES_PER_FRAME 10
#define LTE_SLOTS_PER_FRAME 20
#define LTE_CE_FILTER_LENGTH 5
#define LTE_CE_OFFSET LTE_CE_FILTER_LENGTH
#define TX_RX_SWITCH_SYMBOL (NUMBER_OF_SYMBOLS_PER_FRAME>>1)
#define PBCH_PDU_SIZE 3 //bytes
#define PRACH_SYMBOL 3 //position of the UL PSS wrt 2nd slot of special subframe
#define NUMBER_OF_FREQUENCY_GROUPS (lte_frame_parms->N_RB_DL)
#define SSS_AMP 1148
#define MAX_NUM_PHICH_GROUPS 56 //110 RBs Ng=2, p.60 36-212, Sec. 6.9
#define MAX_MBSFN_AREA 8
#undef EXTERN
#undef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
#endif /* PHY_IMPL_DEFS_NR_H */
+124
View File
@@ -0,0 +1,124 @@
/*
* 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
*/
#ifndef __PHY_EXTERN_UE__H__
#define __PHY_EXTERN_UE__H__
#include "PHY/defs_nr_UE.h"
#include "common/ran_context.h"
extern char* namepointer_chMag ;
extern char* namepointer_log2;
extern char fmageren_name2[512];
extern unsigned int RX_DMA_BUFFER[4][NB_ANTENNAS_RX];
extern unsigned int TX_DMA_BUFFER[4][NB_ANTENNAS_TX];
#include "PHY/LTE_TRANSPORT/transport_extern.h"
extern int number_of_cards;
#ifndef OCP_FRAMEWORK
extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
extern NR_DL_FRAME_PARMS *lte_frame_parms_g;
#else
#define MAX_UE 10
#define MAX_eNB 20
extern PHY_VARS_NR_UE * PHY_vars_UE_g[MAX_UE][MAX_NUM_CCs];
#endif
extern short primary_synch0[144];
extern short primary_synch1[144];
extern short primary_synch2[144];
extern unsigned char primary_synch0_tab[72];
extern unsigned char primary_synch1_tab[72];
extern unsigned char primary_synch2_tab[72];
extern int16_t *primary_synch0_time; //!< index: [0..ofdm_symbol_size*2[
extern int16_t *primary_synch1_time; //!< index: [0..ofdm_symbol_size*2[
extern int16_t *primary_synch2_time; //!< index: [0..ofdm_symbol_size*2[
extern int *sync_corr_ue0; //!< index [0..10*samples_per_tti[
extern int *sync_corr_ue1; //!< index [0..10*samples_per_tti[
extern int *sync_corr_ue2; //!< index [0..10*samples_per_tti[
extern int flagMag;
//extern short **txdataF_rep_tmp;
extern char mode_string[4][20];
extern unsigned char NB_RU;
#ifndef OPENAIR2
extern unsigned char NB_eNB_INST;
extern unsigned char NB_UE_INST;
extern unsigned char NB_RN_INST;
#endif
extern unsigned int ULSCH_max_consecutive_errors;
extern int flag_LA;
extern double sinr_bler_map[MCS_COUNT][2][MCS_TABLE_LENGTH_MAX];
extern double sinr_bler_map_up[MCS_COUNT][2][16];
extern int table_length[MCS_COUNT];
extern double sinr_to_cqi[4][16];
extern int cqi_to_mcs[16];
//for MU-MIMO abstraction using MIESM
//this 2D arrarays contains SINR, MI and RBIR in rows 1, 2, and 3 respectively
extern double MI_map_4qam[3][162];
extern double MI_map_16qam[3][197];
extern double MI_map_64qam[3][227];
extern double beta1_dlsch_MI[6][MCS_COUNT];
extern double beta2_dlsch_MI[6][MCS_COUNT];
extern double q_qpsk[8];
extern double q_qam16[8];
extern double q_qam64[8];
extern double p_qpsk[8];
extern double p_qam16[8];
extern double p_qam64[8];
extern double beta1_dlsch[6][MCS_COUNT];
extern double beta2_dlsch[6][MCS_COUNT];
extern char eNB_functions[6][20];
extern char eNB_timing[2][20];
extern char ru_if_types[MAX_RU_IF_TYPES][20];
extern int16_t unscrambling_lut[65536*16];
extern uint8_t scrambling_lut[65536*16];
extern unsigned short msrsb_6_40[8][4];
extern unsigned short msrsb_41_60[8][4];
extern unsigned short msrsb_61_80[8][4];
extern unsigned short msrsb_81_110[8][4];
extern unsigned short Nb_6_40[8][4];
extern unsigned short Nb_41_60[8][4];
extern unsigned short Nb_61_80[8][4];
extern unsigned short Nb_81_110[8][4];
extern uint16_t hundred_times_log10_NPRB[100];
extern uint8_t alpha_lut[8];
extern uint8_t max_turbo_iterations;
#endif /*__PHY_EXTERN_H__ */
+150
View File
@@ -0,0 +1,150 @@
/*
* 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
*/
#ifndef __PHY_VARS_NR_H__
#define __PHY_VARS_NR_H__
#include "PHY/types.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/phy_vars_nr_ue.h"
#include "common/ran_context.h"
char* namepointer_chMag ;
char fmageren_name2[512];
char* namepointer_log2;
#include "PHY/LTE_REFSIG/primary_synch.h"
int16_t *primary_synch0_time;
int16_t *primary_synch1_time;
int16_t *primary_synch2_time;
#include "PHY/CODING/coding_vars.h"
//PHY_VARS *PHY_vars;
#ifndef OCP_FRAMEWORK
PHY_VARS_NR_UE ***PHY_vars_UE_g;
LTE_DL_FRAME_PARMS *lte_frame_parms_g;
#else
PHY_VARS_NR_UE * PHY_vars_UE_g[MAX_UE][MAX_NUM_CCs]={NULL};
#endif
unsigned short rev[2048],rev_times4[8192],rev_half[1024];
unsigned short rev256[256],rev512[512],rev1024[1024],rev4096[4096],rev2048[2048],rev8192[8192];
char mode_string[4][20] = {"NOT SYNCHED","PRACH","RAR","PUSCH"};
#include "SIMULATION/ETH_TRANSPORT/vars.h"
unsigned char NB_RU=0;
#ifndef OPENAIR2
unsigned char NB_eNB_INST=0;
unsigned char NB_UE_INST=0;
unsigned char NB_RN_INST=0;
unsigned char NB_INST=0;
#endif
unsigned int ULSCH_max_consecutive_errors = 20;
int number_of_cards;
int flag_LA=0;
int flagMag;
//extern channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX];
//extern double ABS_SINR_eff_BLER_table[MCS_COUNT][9][9];
//extern double ABS_beta[MCS_COUNT];odi
double sinr_bler_map[MCS_COUNT][2][MCS_TABLE_LENGTH_MAX];
int table_length[MCS_COUNT];
//double sinr_bler_map_up[MCS_COUNT][2][16];
//for MU-MIMO abstraction using MIESM
//this 2D arrarays contains SINR, MI and RBIR in rows 1, 2, and 3 respectively
double MI_map_4qam[3][162];
double MI_map_16qam[3][197];
double MI_map_64qam[3][227];
// here the first index is for transmission mode 1, 2, 5 and 6 whereas the second index is for the 16 sinr vaues corresponding to 16 CQIs
double sinr_to_cqi[4][16]= { {-2.5051, -2.5051, -1.7451, -0.3655, 1.0812, 2.4012, 3.6849, 6.6754, 8.3885, 8.7970, 12.0437, 14.4709, 15.7281, 17.2424, 17.2424, 17.2424},
{-2.2360, -2.2360, -1.3919, -0.0218, 1.5319, 2.9574, 4.3234, 6.3387, 8.9879, 9.5096, 12.6609, 14.0116, 16.4984, 18.1572, 18.1572, 18.1572},
{-1, -1.0000, -0.4198, -0.0140, 1.0362, 2.3520, 3.5793, 6.1136, 8.4836, 9.0858, 12.4723, 13.9128, 16.2054, 17.7392, 17.7392, 17.7392},
{ -4.1057, -4.1057, -3.3768, -2.2916, -1.1392, 0.1236, 1.2849, 3.1933, 5.9298, 6.4052, 9.6245, 10.9414, 13.5166, 14.9545, 14.9545, 14.9545}
};
//int cqi_to_mcs[16]={0, 0, 1, 3, 5, 7, 9, 13, 15, 16, 20, 23, 25, 27, 27, 27};
int cqi_to_mcs[16]= {0, 0, 1, 2, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 27, 28};
//for SNR to MI conversion 7 th order Polynomial coeff
double q_qam16[8]= {3.21151853033897e-10,5.55435952230651e-09,-2.30760065362117e-07,-6.25587743817859e-06,4.62251036452795e-06,0.00224150813158937,0.0393723140344367,0.245486379182639};
double q_qpsk[8]= {1.94491167814437e-09,8.40494123817774e-08,4.75527131198034e-07,-2.48946285301621e-05,-0.000347614016158364,0.00209252225437100,0.0742986115462510,0.488297879889425};
double q_qam64[8]= {2.25934026232206e-11,-1.45992206328306e-10,-3.70861183071900e-08,-1.22206071019319e-06,6.49115500399637e-06,0.00129828997837433,0.0259669554914859,0.166602901214898};
//for MI to SNR conversion 7 th order Polynomial coeff
double p_qpsk[8]= {5982.42405670359,-21568.1135917693,31293.9987036905,-23394.6795043871,9608.34750585489,-2158.15802349899,267.731968719036,-20.6145324295965};
double p_qam16[8]= {7862.12690694170,-28510.3207048338,41542.2150287122,-31088.3036957379,12690.1982361016,-2785.66604739984,326.595462489375,-18.9911849872089};
double p_qam64[8]= {8832.57933013696,-32119.1802555952,46914.2578990397,-35163.8150557183,14343.7419388853,-3126.61025510092,360.954930562237,-18.0358548533343};
// ideal CE MIESM
double beta1_dlsch_MI[6][MCS_COUNT] = { {1.1188, 0.3720, 0.3755, 0.9453, 0.5799, 0.5256, 0.5485, 0.5340, 0.5165, 0.5300, 0.6594, 0.5962, 0.4884, 0.4927, 0.3687, 0.4614, 0.4081, 0.2639,0.2935,0.2520,0.3709,0.2906,0.2612,0.2390}, {0.7138, 0.5533, 0.5533, 0.4828, 0.4998, 0.4843, 0.4942, 0.5323, 0.5142, 0.4756, 0.5792, 0.4167, 0.4445, 0.3942, 0.3789, 0.2756, 0.4456, 0.1650, 0.2254, 0.2353, 0.2097,0.2517,0.3242,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1},{1.808065416202085, 1.754544945430673,1.902272019362616, 1.790054645392961, 1.563204092967629, 1.585258289348813, 1.579349443720310, 1.570650121437345, 1.545055626608596, 1.362229442426877, 1.85, 1.79, 1.65, 1.54, 1.46, 1.39, 1.33, 1,1,1,1,1,1,1},{0.7146, 0.4789, 0.5392, 0.5556, 0.4975, 0.4847, 0.4691, 0.5261, 0.5278, 0.4962, 0.4468, 0.4113, 0.4622, 0.4609, 0.3946, 0.3991, 0.3532, 0.2439, 0.1898, 0.2929, 0.2712, 0.3367, 0.3591, 0.2571}};
double beta2_dlsch_MI[6][MCS_COUNT] = { {1.1293, 0.3707, 0.3722, 0.9310, 0.5808, 0.5265, 0.5404, 0.5279, 0.5210, 0.5226, 0.6438, 0.5827, 0.4804, 0.4830, 0.3638, 0.4506, 0.4107, 0.2547, 0.2797, 0.2413, 0.3351, 0.2750, 0.2568, 0.2273}, {0.7028, 0.5503, 0.5503, 0.4815, 0.5006, 0.4764, 0.4810, 0.5124, 0.4964, 0.4485, 0.5497, 0.3971, 0.4239, 0.3701, 0.3494, 0.2630, 0.4053, 0.1505, 0.2001,0.2024,0.1788,0.2124,0.2668,1}, {1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1},{1.079518113138858, 1.105622953570353, 1.031337449900606, 1.073342032668810, 1.242636589110353, 1.255054927783647, 1.291463834317768, 1.317048698347491, 1.354485054187984, 0.338534029291017, 1.85, 1.79, 1.65, 1.54, 1.46, 1.39, 1.33,1, 1,1,1,1,1,1},{0.6980, 0.4694, 0.5379, 0.5483, 0.4982, 0.4737, 0.4611, 0.5051, 0.5020, 0.4672, 0.4357, 0.3957, 0.4389, 0.4344, 0.3645, 0.3661, 0.3301, 0.2179, 0.1730, 0.2536, 0.2389,0.2884,0.2936,0.2226}};
//real CE MIESM
/*
double beta1_dlsch_MI[6][MCS_COUNT] = { {1.32955, 0.59522, 0.54024, 0.98698, 0.81305, 0.76976, 0.69258, 0.69713, 0.70546, 0.69111, 0.81904, 0.72664, 0.79491, 0.72562, 0.53980, 0.33134, 0.50550, 0.40602,0.40281,0.47012,0.50510,0.23540,0.32045,1}, {0.59632, 1.08475, 1.02431, 1.07020, 0.90170, 0.97719, 0.95464, 0.92764, 0.86721, 0.85986, 0.64558, 0.80631, 0.82673, 0.82888, 0.87122, 0.77245, 0.29771, 0.43477, 0.55321, 0.61027, 0.56111, 0.57292, 0.39737,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1},{1.808065416202085, 1.754544945430673,1.902272019362616, 1.790054645392961, 1.563204092967629, 1.585258289348813, 1.579349443720310, 1.570650121437345, 1.545055626608596, 1.362229442426877, 1.85, 1.79, 1.65, 1.54, 1.46, 1.39, 1.33, 1,1,1,1,1,1,1},{0.77532, 1.07544, 1.10571, 1.04099, 0.91638, 0.88644, 0.96405, 0.86709, 0.94066, 0.84430, 1.24478, 1.09665, 1.42604, 0.79541, 0.71847, 0.71604, 0.74561, 0.36431, 0.41536, 0.52175, 0.47096, 0.49977, 0.59728,1}};
double beta2_dlsch_MI[6][MCS_COUNT] = { {1.36875, 0.59304, 0.53870, 0.98239, 0.81637, 0.76847, 0.69842, 0.69885, 0.69967, 0.69826, 0.82660, 0.70559, 0.78404, 0.70670, 0.55393, 0.36893, 0.52225, 0.39752, 0.40494, 0.46239, 0.49247,0.26900,0.34504,1}, {0.43775, 0.78208, 0.72875, 0.77458, 0.64485, 0.69174, 0.66097, 0.63289, 0.59652, 0.61175, 0.44551, 0.56047, 0.57314, 0.57553, 0.58849, 0.52159, 0.21241, 0.30139, 0.37373, 0.32029, 0.37067, 0.36706, 0.27118,1}, {1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1},{1.079518113138858, 1.105622953570353, 1.031337449900606, 1.073342032668810, 1.242636589110353, 1.255054927783647, 1.291463834317768, 1.317048698347491, 1.354485054187984, 0.338534029291017, 1.85, 1.79, 1.65, 1.54, 1.46, 1.39, 1.33,1, 1,1,1,1,1,1},{0.54448, 0.73731, 0.79165, 0.74407, 0.68042, 0.64906, 0.71349, 0.62109, 0.65815, 0.60940, 0.90549, 0.78708, 1.03176, 0.58431, 0.53379, 0.51224, 0.52767, 0.26848, 0.29642, 0.36879, 0.34148, 0.35279,0.40633,1}};
*/
//ideal channel estimation values
//double beta1_dlsch[6][MCS_COUNT] = { {2.3814, 0.4956, 0.5273, 1.1708, 0.8014, 0.7889, 0.8111, 0.8139, 0.8124, 0.8479, 1.9280, 1.9664, 2.3857, 2.5147, 2.4511, 3.0158, 2.8643, 5.3013, 5.8594, 6.5372, 7.8073, 7.8030, 7.5295, 7.1320}, {0.5146, 0.5549, 0.7405, 0.6913, 0.7349, 0.7000, 0.7539, 0.7955, 0.8074, 0.7760, 1.8150, 1.6561, 1.9280, 2.3563, 2.6699, 2.3086, 3.1601, 4.5316, 5.2870, 6.0983, 6.5635, 7.7024, 9.9592, 6.6173}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {1.79358, 1.17908, 2.02600, 1.72040, 1.58618, 1.59039, 1.68111, 1.67062, 1.64911, 1.33274, 4.87800, 3.58797, 3.72338, 5.35700, 2.81752, 1.93472, 2.23259, 1,1,1,1,1,1,1}, {0.4445, 0.5918, 0.7118, 0.7115, 0.7284, 0.7202, 0.7117, 0.8111, 0.8239, 0.7907, 1.8456, 1.8144, 2.3830, 2.6634, 2.6129, 2.8127, 2.7372, 4.9424, 4.8763, 6.8413, 7.1493, 9.4180, 10.1230, 8.9613}};
//double beta2_dlsch[6][MCS_COUNT] = { {2.3639, 0.4952, 0.5207, 1.1572, 0.8026, 0.7864, 0.7996, 0.8034, 0.8200, 0.8367, 1.8701, 1.9212, 2.2947, 2.4472, 2.4091, 2.9479, 2.8973, 5.0591, 5.5134, 6.1483, 7.2166, 7.5177, 7.5704, 7.2248}, {0.5113, 0.5600, 0.7359, 0.6860, 0.7344, 0.6902, 0.7315, 0.7660, 0.7817, 0.7315, 1.7268, 1.5912, 1.8519, 2.2115, 2.4580, 2.1879, 2.9015, 4.1543, 4.6986, 5.3193, 5.6319, 6.5640, 8.2421, 5.6393}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {0.79479, 0.52872, 0.90005, 0.77170, 0.73220, 0.72060, 0.75433, 0.75451, 0.75989, 0.67655, 1.68525, 1.31100, 1.46573, 1.99843, 1.57293, 1.62852, 2.10636, 1,1,1,1,1,1,1}, {0.4398, 0.5823, 0.7094, 0.7043, 0.7282, 0.7041, 0.6979, 0.7762, 0.7871, 0.7469, 1.7752, 1.7443, 2.2266, 2.4767, 2.4146, 2.6040, 2.5708, 4.4488, 4.4944, 5.9630, 6.3740, 8.1097, 8.4210, 7.8027}};
double beta1_dlsch[6][MCS_COUNT] = { {1.199175, 1.085656, 0.983872, 0.843789, 0.816093, 0.853078, 0.899236, 0.919665, 0.888673, 0.924181, 0.814176, 0.794108, 0.770653, 0.826266, 0.982043, 0.979621, 0.985176, 0.901741, 0.870311, 0.911303, 0.898923, 1.003359, 0.988535, 1.030639, 1.151038, 1.116939, 1.214118, 1.219148}, {0.5146, 0.5549, 0.7405, 0.6913, 0.7349, 0.7000, 0.7539, 0.7955, 0.8074, 0.7760, 1.8150, 1.6561, 1.9280, 2.3563, 2.6699, 2.3086, 3.1601, 4.5316, 5.2870, 6.0983, 6.5635, 7.7024, 9.9592, 6.6173}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {1.79358, 1.17908, 2.02600, 1.72040, 1.58618, 1.59039, 1.68111, 1.67062, 1.64911, 1.33274, 4.87800, 3.58797, 3.72338, 5.35700, 2.81752, 1.93472, 2.23259, 1,1,1,1,1,1,1}, {0.4445, 0.5918, 0.7118, 0.7115, 0.7284, 0.7202, 0.7117, 0.8111, 0.8239, 0.7907, 1.8456, 1.8144, 2.3830, 2.6634, 2.6129, 2.8127, 2.7372, 4.9424, 4.8763, 6.8413, 7.1493, 9.4180, 10.1230, 8.9613}};
double beta2_dlsch[6][MCS_COUNT] = { {0.534622, 0.596561, 0.500838, 0.471721, 0.548218, 0.547974, 0.924245, 0.836484, 0.776917, 0.879691, 0.875722, 0.666933, 0.666393, 0.755377, 1.074985, 1.080290, 1.010914, 0.790892, 0.793435, 0.860249, 0.901508, 0.967060, 0.951372, 1.011493, 1.106151, 1.117076, 1.209397, 1.227790}, {0.5113, 0.5600, 0.7359, 0.6860, 0.7344, 0.6902, 0.7315, 0.7660, 0.7817, 0.7315, 1.7268, 1.5912, 1.8519, 2.2115, 2.4580, 2.1879, 2.9015, 4.1543, 4.6986, 5.3193, 5.6319, 6.5640, 8.2421, 5.6393}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {0.79479, 0.52872, 0.90005, 0.77170, 0.73220, 0.72060, 0.75433, 0.75451, 0.75989, 0.67655, 1.68525, 1.31100, 1.46573, 1.99843, 1.57293, 1.62852, 2.10636, 1,1,1,1,1,1,1}, {0.4398, 0.5823, 0.7094, 0.7043, 0.7282, 0.7041, 0.6979, 0.7762, 0.7871, 0.7469, 1.7752, 1.7443, 2.2266, 2.4767, 2.4146, 2.6040, 2.5708, 4.4488, 4.4944, 5.9630, 6.3740, 8.1097, 8.4210, 7.8027}};
//real channel estimation valus
/*
double beta1_dlsch[6][MCS_COUNT] = { {2.50200, 0.84047, 0.78195, 1.37929, 1.16871, 1.11906, 1.06303, 1.07447, 1.11403, 1.09223, 2.82502, 2.87556, 3.51254, 3.62920, 3.53638, 2.35980, 3.74126, 8.66532, 7.31772, 9.86882, 10.64939, 6.75208, 9.50664, 13.63057}, {0.92257, 1, 1.80445, 1.43175, 1.42093, 1.37381, 1.45392, 1.47255, 1.47451, 1.41235, 3.9079, 3.38557, 4.13059, 4.93355, 4.97277, 6.04951, 5.88896, 8.68076, 10.23746, 12.37069, 5.50538, 17.29612, 17.95050, 13.27095}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {1.79255, 1.88213, 4.44226, 2.25150, 1.93710, 2.18504, 2.57389, 1.94322, 1.78515, 2.09265, 2.37459, 1.74442, 1.74346, 1.19705, 1.56149, 1.59604, 1.6, 1,1,1,1,1,1,1}, {0.93374, 1.40389, 1.36670, 1.38679, 1.35707, 1.26353, 1.32360, 1.40164, 1.51843, 1.34863, 3.45839, 3.13726, 3.94768, 4.21966, 4.60750, 4.97894, 5.40755, 8.12814, 10.59221, 12.96427, 13.37323, 14.27206, 16.61779, 17.19656}};
double beta2_dlsch[6][MCS_COUNT] = { {2.52163, 0.83231, 0.77472, 1.36536, 1.16829, 1.11186, 1.06287, 1.07292, 1.09946, 1.10650, 2.79174, 2.75655, 3.36651, 3.49011, 3.60903, 2.73517, 3.84009, 8.20312, 7.41739, 9.64081, 10.40911, 8.11765, 10.41923, 9.34300}, {0.67252, 0.8600, 1.28633, 1.01624, 1.03066, 0.97590, 1.02560, 1.01840, 1.00547, 0.97093, 2.72573, 2.33283, 2.86181, 3.40452, 3.47957, 4.08916, 3.97628, 6.14541, 7.11017, 8.42369, 4.04812, 11.42082, 11.57171, 9.28462}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {0.85784, 0.90361, 2.09766, 1.08385, 0.96300, 1.04432, 1.22763, 0.99249, 0.95544, 1.12333, 1.37924, 1.12913, 1.30644, 1.19253, 1.75488, 2.13813, 2.10636, 1,1,1,1,1,1,1}, {0.66288, 0.96402, 0.98545, 0.99386, 0.99981, 0.92678, 0.98978, 0.99600, 1.05538, 0.97777, 2.52504, 2.29338, 2.89631, 3.10812, 3.41916, 3.58671, 3.84166, 6.05254, 7.45821, 9.15812, 9.66330, 10.17852, 11.50519, 11.16299}};
*/
#ifdef OCP_FRAMEWORK
#include <enums.h>
#else
char eNB_functions[6][20]={"eNodeB_3GPP","eNodeB_3GPP_BBU","NGFI_RAU_IF4p5","NGFI_RRU_IF5","NGFI_RRU_IF4p5",};
char eNB_timing[2][20]={"synch_to_ext_device","synch_to_other"};
char ru_if_types[MAX_RU_IF_TYPES][20]={"local RF","IF5 RRU","IF5 Mobipass","IF4p5 RRU","IF1pp RRU"};
#endif
/// lookup table for unscrambling in RX
int16_t unscrambling_lut[65536*16] __attribute__((aligned(32)));
/// lookup table for scrambling in TX
uint8_t scrambling_lut[65536*16] __attribute__((aligned(32)));
uint8_t max_turbo_iterations=4;
#endif /*__PHY_VARS_H__ */
+96
View File
@@ -0,0 +1,96 @@
/*
* 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
*/
/***********************************************************************
*
* FILENAME : phy_frame_configuration_nr.h
*
* DESCRIPTION : functions related to FDD/TDD configuration for NR
* see TS 38.213 11.1 Slot configuration
* and TS 38.331 for RRC configuration
*
************************************************************************/
#ifndef PHY_FRAME_CONFIG_NR_H
#define PHY_FRAME_CONFIG_NR_H
/************** DEFINE ********************************************/
#define TDD_CONFIG_NB_FRAMES (2)
/*************** FUNCTIONS *****************************************/
/** \brief This function processes tdd dedicated configuration for nr
* @param frame_parms NR DL Frame parameters
* @param dl_UL_TransmissionPeriodicity periodicity
* @param nrofDownlinkSlots number of downlink slots
* @param nrofDownlinkSymbols number of downlink symbols
* @param nrofUplinkSlots number of uplink slots
* @param nrofUplinkSymbols number of uplink symbols
@returns 0 if tdd dedicated configuration has been properly set or -1 on error with message */
int set_tdd_config_nr(NR_DL_FRAME_PARMS *frame_parms, int dl_UL_TransmissionPeriodicity,
int nrofDownlinkSlots, int nrofDownlinkSymbols,
int nrofUplinkSlots, int nrofUplinkSymbols);
/** \brief This function adds a slot configuration to current dedicated configuration for nr
* @param frame_parms NR DL Frame parameters
* @param slotIndex
* @param nrofDownlinkSymbols
* @param nrofUplinkSymbols
@returns none */
void add_tdd_dedicated_configuration_nr(NR_DL_FRAME_PARMS *frame_parms, int slotIndex,
int nrofDownlinkSymbols, int nrofUplinkSymbols);
/** \brief This function processes tdd dedicated configuration for nr
* @param frame_parms nr frame parameters
* @param dl_UL_TransmissionPeriodicity periodicity
* @param nrofDownlinkSlots number of downlink slots
* @param nrofDownlinkSymbols number of downlink symbols
* @param nrofUplinkSlots number of uplink slots
* @param nrofUplinkSymbols number of uplink symbols
@returns 0 if tdd dedicated configuration has been properly set or -1 on error with message */
int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms);
/** \brief This function checks nr slot direction : downlink or uplink
* @param frame_parms NR DL Frame parameters
* @param nr_frame : frame number
* @param nr_tti : slot number
@returns nr_slot_t : downlink or uplink */
nr_slot_t slot_select_nr(NR_DL_FRAME_PARMS *frame_parms, int nr_frame, int nr_tti);
/** \brief This function frees tdd configuration for nr
* @param frame_parms NR DL Frame parameters
@returns none */
void free_tdd_configuration_nr(NR_DL_FRAME_PARMS *frame_parms);
/** \brief This function frees tdd dedicated configuration for nr
* @param frame_parms NR DL Frame parameters
@returns none */
void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms);
#endif /* PHY_FRAME_CONFIG_NR_H */
+8
View File
@@ -211,6 +211,14 @@ typedef struct {
int iq_rxrescale;
//! Configuration file for LMS7002M
char *configFilename;
//! remote IP/MAC addr for Ethernet interface
char *remote_addr;
//! remote port number for Ethernet interface
unsigned int remote_port;
//! local IP/MAC addr for Ethernet interface (eNB/BBU, UE)
char *my_addr;
//! local port number for Ethernet interface (eNB/BBU, UE)
unsigned int my_port;
#if defined(USRP_REC_PLAY)
unsigned short sf_mode; // 1=record, 2=replay
char sf_filename[1024]; // subframes file path
+6
View File
@@ -9,6 +9,12 @@ typedef struct threads_s {
int slot1_proc_one;
int slot1_proc_two;
int slot1_proc_three;
int dlsch_td_one;
int dlsch_td_two;
int dlsch_td_three;
int dlsch_td1_one;
int dlsch_td1_two;
int dlsch_td1_three;
} threads_t;
#endif /* _THREADS_T_H_ */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+83
View File
@@ -0,0 +1,83 @@
#ifndef NR_UESOFTMODEM_H
#define NR_UESOFTMODEM_H
#define _GNU_SOURCE
#include <execinfo.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/sched.h>
#include "rt_wrapper.h"
#include <sched.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syscall.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include "rt_wrapper.h"
#include "../../ARCH/COMMON/common_lib.h"
#undef MALLOC
#include "assertions.h"
#include "msc.h"
#include "PHY/types.h"
#include "PHY/defs_nr_UE.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
#if defined(ENABLE_ITTI)
#if defined(ENABLE_USE_MME)
#include "s1ap_eNB.h"
#ifdef PDCP_USE_NETLINK
#include "SIMULATION/ETH_TRANSPORT/proto.h"
#endif
#endif
#endif
extern pthread_cond_t sync_cond;
extern pthread_mutex_t sync_mutex;
extern int sync_var;
extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
extern int rx_input_level_dBm;
extern uint8_t exit_missed_slots;
extern uint64_t num_missed_slots; // counter for the number of missed slots
extern int oaisim_flag;
extern volatile int oai_exit;
extern openair0_config_t openair0_cfg[MAX_CARDS];
extern pthread_cond_t sync_cond;
extern pthread_mutex_t sync_mutex;
extern int sync_var;
extern int transmission_mode;
extern double cpuf;
#if defined(ENABLE_ITTI)
extern volatile int start_eNB;
extern volatile int start_UE;
#endif
#include "threads_t.h"
extern threads_t threads;
extern void exit_fun(const char* s);
// In nr-ue.c
extern int setup_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
extern void fill_ue_band_info(void);
extern void init_UE(int);
extern void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char * name);
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
#endif