Commit 6c215de9 authored by Nick Ho's avatar Nick Ho

Top level (Procedure part) for TX

parent 3a002e2c
......@@ -1060,6 +1060,16 @@ set(SCHED_SRC
add_library(SCHED_LIB ${SCHED_SRC})
add_dependencies(SCHED_LIB rrc_flag)
# Physical Channel Procedures Scheduling for NB-IoT
################################"
set(SCHED_SRC_NB_IoT
#${OPENAIR1_DIR}/SCHED_NBIOT/fapi_l1.c
${OPENAIR1_DIR}/SCHED_NBIOT/phy_procedures_lte_eNb_NB_IoT.c
#${OPENAIR1_DIR}/SCHED/phy_procedures_lte_common.c
)
add_library(SCHED_NB_IoT_LIB ${SCHED_SRC_NB_IoT})
add_dependencies(SCHED_NB_IoT_LIB rrc_flag)
set(SCHED_SRC_RU
${OPENAIR1_DIR}/SCHED/ru_procedures.c
${OPENAIR1_DIR}/SCHED/prach_procedures.c
......@@ -1146,6 +1156,7 @@ set(PHY_TURBOIF
add_library(coding MODULE ${PHY_TURBOSRC} )
set(PHY_SRC_COMMON
${OPENAIR1_DIR}/PHY/NBIoT_TRANSPORT/SIB_NB_IoT.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c
# ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/slss.c
......
/* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/LTE_TRANSPORT/SIB_NB_IoT.c
* \Fucntions for the generation of SIB information for NB_IoT, TS 36-212, V13.4.0 2017-02
* \author M. KANJ
* \date 2018
* \version 0.0
* \company bcom
* \email: matthieu.kanj@b-com.com
* \note
* \warning
*/
#include "PHY/NBIoT_TRANSPORT/defs_NB_IoT.h"
#include "PHY/NBIoT_TRANSPORT/proto_NB_IoT.h"
//#include "PHY/CODING/defs_NB_IoT.h"
//#include "PHY/LTE_REFSIG/defs_NB_IoT.h"
//#include "PHY/impl_defs_lte_NB_IoT.h"
//#include "PHY/impl_defs_top_NB_IoT.h"
#include "PHY/impl_defs_lte.h"
/////////////////////////////////////////////////////////////////////////////////////////
int generate_SIB1(NB_IoT_eNB_NDLSCH_t *sib1_struct,
int32_t **txdataF,
int16_t amp,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint32_t subframe,
int RB_IoT_ID,
uint8_t operation_mode,
uint8_t release_v13_5_0)
{
int done=0;
uint8_t *sib1_pdu = sib1_struct->harq_process->pdu;
uint8_t opr_mode = 3;
if(operation_mode>=2)
{
opr_mode =0;
}
uint8_t tmp =0;
uint8_t rep_val = 0;
uint8_t start_frame = get_start_frame_SIB1_NB_IoT(frame_parms, get_rep_num_SIB1_NB_IoT(sib1_struct->repetition_number_SIB1));
switch( get_rep_num_SIB1_NB_IoT(sib1_struct->repetition_number_SIB1) )
{
case 4:
rep_val = 64;
break;
case 8:
rep_val = 32;
break;
case 16:
rep_val = 16;
break;
default:
printf("Error in SIB1");
}
uint8_t var = 0;
if(start_frame == 1)
{
var =1;
}
if(start_frame>=16)
{
tmp = 1;
}
uint8_t born_inf = 0 + start_frame*tmp;
uint8_t born_sup = 16 + start_frame*tmp;
if((subframe == 4) && (frame%2 == var) && (born_inf<= frame % rep_val) && (frame % rep_val < born_sup ))
{
LOG_D(PHY,"[%3d][%2d] Generating SIB1\n",frame,subframe);
int G = get_G_SIB1_NB_IoT(frame_parms,operation_mode);
if( frame % rep_val == var )
{
dlsch_encoding_NB_IoT(sib1_pdu,
sib1_struct,
8, ///// number_of_subframes_required
G); //// this vallue is fixed, should take into account in future the case of stand-alone & guard-band
dlsch_scrambling_Gen_NB_IoT(frame_parms,
sib1_struct,
8*G,
frame,
subframe*2,
sib1_struct->rnti,
release_v13_5_0,
1);
}
dlsch_modulation_NB_IoT(txdataF,
amp,
frame_parms,
opr_mode, // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
sib1_struct,
G, // number of bits per subframe
((frame%16)/2),
4,
RB_IoT_ID);
done =1;
frame_parms->flag_free_sf =1;
}
return(done);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
int generate_SIB23(NB_IoT_eNB_NDLSCH_t *SIB23,
int32_t **txdataF,
int16_t amp,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint32_t subframe,
int RB_IoT_ID,
uint8_t release_v13_5_0)
{
int done=0;
if( SIB23->active == 1 )
{
//LOG_I(PHY,"[Frame: %d][Subframe: %d]sent SIB23\n",frame,subframe);
uint8_t *SIB23_pdu = SIB23->harq_process->pdu;
uint32_t rep = SIB23->resource_assignment;
uint8_t eutra_control_region = 3;
uint32_t counter_rep = SIB23->counter_repetition_number;
uint32_t pointer_to_sf = SIB23->pointer_to_subframe; /// to identify wich encoded subframe to transmit
int G = get_G_NB_IoT(frame_parms);
uint8_t Nsf = SIB23->resource_assignment; //value 2 or 8
if(counter_rep == rep)
{
dlsch_encoding_NB_IoT(SIB23_pdu,
SIB23,
Nsf, ///// number_of_subframes_required
G); //// this vallue is fixed, should take into account in future the case of stand-alone & guard-band
dlsch_scrambling_Gen_NB_IoT(frame_parms,
SIB23,
Nsf*G,
frame,
subframe*2,
SIB23->rnti,
release_v13_5_0,
1);
}
dlsch_modulation_NB_IoT(txdataF,
amp,
frame_parms,
eutra_control_region, //should be replace by start_symbole // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
SIB23,
G, // number of bits per subframe
pointer_to_sf,
subframe,
RB_IoT_ID);
SIB23->counter_repetition_number--;
SIB23->pointer_to_subframe++;
frame_parms->flag_free_sf =1;
if(SIB23->counter_repetition_number == 0)
{
SIB23->active = 0;
}
done =1;
}
return(done);
}
////////////////////////////////////////////////////////////////////////
int generate_NDLSCH_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
NB_IoT_eNB_NDLSCH_t *RAR,
int32_t **txdataF,
int16_t amp,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint32_t subframe,
int RB_IoT_ID,
uint8_t release_v13_5_0)
{
int done = 0;
if( RAR->active == 1 )
{
uint8_t *RAR_pdu = RAR->harq_process->pdu;
if(RAR->active_msg2 == 1 && RAR_pdu!=NULL)
{
uint8_t one_byte = RAR_pdu[2]>>3;
uint8_t subcarrier_spacing = one_byte & 0x01;
eNB->ulsch_NB_IoT[0]->harq_process->subcarrier_spacing = subcarrier_spacing;
}
// make different between RAR data and NPDSCH data // add a flag in NPDSCH to switch between RA and normal data transmission
uint32_t rep = RAR->repetition_number;
uint8_t eutra_control_region = 3;
uint32_t counter_rep = RAR->counter_repetition_number;
uint32_t counter_sf_rep = RAR->counter_current_sf_repetition; /// for identifiying when to trigger new scrambling
uint32_t pointer_to_sf = RAR->pointer_to_subframe; /// to identify wich encoded subframe to transmit
int G = get_G_NB_IoT(frame_parms);
uint8_t Nsf = RAR->number_of_subframes_for_resource_assignment;
//LOG_I(PHY,"[Frame: %d][Subframe: %d]sent RAR, rep : %d, counter_rep:%d, Num_res:%d\n",frame,subframe,rep,counter_rep,Nsf);
if( (counter_rep == rep) && (counter_sf_rep == 0) && (pointer_to_sf == 0) )
{
dlsch_encoding_NB_IoT(RAR_pdu,
RAR,
Nsf, ///// number_of_subframes_required
G); //// this vallue is fixed, should take into account in future the case of stand-alone & guard-band
dlsch_scrambling_Gen_NB_IoT(frame_parms,
RAR,
Nsf*G,
frame,
subframe*2,
RAR->rnti,
release_v13_5_0,
0);
}
if( (counter_rep != rep) && (counter_sf_rep == 0) && (pointer_to_sf == 0) )
{
dlsch_scrambling_Gen_NB_IoT(frame_parms,
RAR,
Nsf*G,
frame,
subframe*2,
RAR->rnti,
release_v13_5_0,
0);
}
if( rep > 4)
{
RAR->counter_current_sf_repetition++;
dlsch_modulation_NB_IoT(txdataF,
amp,
frame_parms,
eutra_control_region, //should be replace by start_symbole // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
RAR,
G, // number of bits per subframe
pointer_to_sf,
subframe,
RB_IoT_ID);
if(RAR->counter_current_sf_repetition == 4)
{
RAR->pointer_to_subframe++;
RAR->counter_current_sf_repetition =0;
if (Nsf == RAR->pointer_to_subframe && (RAR->counter_repetition_number > 4))
{
RAR->counter_repetition_number = RAR->counter_repetition_number-4;
RAR->pointer_to_subframe =0;
RAR->counter_current_sf_repetition =0;
} else {
RAR->active = 0;
RAR->active_msg2 = 0;
done =1;
}
}
} else {
RAR->counter_current_sf_repetition++;
dlsch_modulation_NB_IoT(txdataF,
amp,
frame_parms,
eutra_control_region, //should be replace by start_symbole // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
RAR,
G, // number of bits per subframe
pointer_to_sf,
subframe,
RB_IoT_ID);
if(RAR->counter_current_sf_repetition == rep)
{
RAR->pointer_to_subframe++;
RAR->counter_current_sf_repetition =0;
if (Nsf == RAR->pointer_to_subframe)
{
RAR->active = 0;
RAR->active_msg2 = 0;
done =1;
}
}
}
}
return(done);
}
/////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
int generate_NPDCCH_NB_IoT(NB_IoT_eNB_NPDCCH_t *DCI_1,
int32_t **txdataF,
int16_t amp,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint32_t subframe,
int RB_IoT_ID)
{
int done=0;
for(int i=0; i<2; i++)
{
uint8_t ncce_index = 0; /// = DCI->ncce_index[i];
uint8_t agr_level = 2; /// = DCI->aggregation_level[i];
if( DCI_1->active[i] == 1)
{
//LOG_I(PHY,"[Frame: %d][Subframe: %d]sent DCI\n",frame,subframe);
uint8_t *DCI_pdu = DCI_1->pdu[i];
uint32_t rep = DCI_1->dci_repetitions[i]; /// repetition number
uint8_t eutra_control_region = 3;
uint8_t num_bits_of_DCI =DCI_1->A[i]; //DCI->dci_bits_length; /// value to be passed through nfapi when filling the PHY structures
uint32_t counter_rep = DCI_1->counter_repetition_number[i]; ////// Buffer for repetitions
int G = get_G_NB_IoT(frame_parms);
//////////// uint8_t Nsf = DCI->number_of_subframes_for_resource_assignment;
if( counter_rep == rep)
{
dci_encoding_NB_IoT(DCI_pdu, // Array of two DCI pdus, even if one DCI is to transmit , the number of DCI is indicated in dci_number
DCI_1, ////uint8_t *e[2], // *e should be e[2][G]
num_bits_of_DCI, //////A = number of bits of the DCI
G,
ncce_index,
agr_level);
npdcch_scrambling_NB_IoT(frame_parms,
DCI_1, // Input data
G, // Total number of bits to transmit in one subframe(case of DCI = G)
subframe*2, //XXX we pass the subframe // Slot number (0..19)
ncce_index,
agr_level);
}
if( ((counter_rep %4)== 0) && (counter_rep != rep) )
{
npdcch_scrambling_NB_IoT(frame_parms,
DCI_1, // Input data
G, // Total number of bits to transmit in one subframe(case of DCI = G)
subframe*2, //XXX we pass the subframe // Slot number (0..19)
ncce_index,
agr_level);
}
dci_modulation_NB_IoT(txdataF,
amp,
frame_parms,
eutra_control_region, // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
DCI_1,
0, // npdsch_data_subframe, // subframe index of the data table of npdsch channel (G*Nsf) , values are between 0..Nsf
agr_level,
ncce_index,
subframe,
RB_IoT_ID);
DCI_1->counter_repetition_number[i]--;
if(DCI_1->counter_repetition_number[i] == 0)
{
//printf("DCI REP done\n");
DCI_1->active[i] = 0;
done =1;
}
}
}
return(done);
}
////////////////////////////////////////////////// backup ///////////////////////////
//////////////////////////////////////////////////// SIB23 ////////////////////////////////////////////////////////////////////////
/* if( (subframe >0) && (subframe !=5) && (With_NSSS == 0) && (frame%2==1) && (frame%64<16) ) ////if((subframe != 0) && (subframe != 4) && (subframe != 9) )
{
if( subframe == 1 )
{
dlsch_encoding_NB_IoT(sib23_pdu,
sib23,
8, ///// number_of_subframes_required
236); //////////// G*2
dlsch_scrambling_Gen_NB_IoT(fp, // is called only in subframe 4
sib23,
1888, ////// total_bits
frame,
subframe*2,
eNB->ndlsch_SIB23->rnti);
}
if( subframe < 5 )
{
dlsch_modulation_NB_IoT(txdataF,
AMP,
fp,
3, // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
sib23,
236, // number of bits per subframe
(subframe-1), ///npdsch_data_subframe, data per subframe//subframe index of the data table of npdsch channel (G*Nsf) ((frame%32)/2),values are between 0..Nsf
subframe,
RB_IoT_ID);
} else {
dlsch_modulation_NB_IoT(txdataF,
AMP,
fp,
3, // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
sib23,
236, // number of bits per subframe
(subframe-2),///npdsch_data_subframe, data per subframe//subframe index of the data table of npdsch channel (G*Nsf) ((frame%32)/2),values are between 0..Nsf
subframe,
RB_IoT_ID);
}
}
*/
\ No newline at end of file
......@@ -51,7 +51,7 @@ void init_unscrambling_lut_NB_IoT(void);
int generate_npss_NB_IoT(int32_t **txdataF,
short amp,
LTE_DL_FRAME_PARMS *frame_parms,
NB_IoT_DL_FRAME_PARMS *frame_parms,
unsigned short symbol_offset, // symbol_offset should equal to 3 for NB-IoT
unsigned short slot_offset,
......@@ -62,7 +62,7 @@ int generate_npss_NB_IoT(int32_t **txdataF,
int generate_sss_NB_IoT(int32_t **txdataF,
int16_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint16_t symbol_offset, // symbol_offset = 3 for NB-IoT
uint16_t slot_offset,
unsigned short frame_number, // new attribute (Get value from higher layer), it does not exist for LTE
......@@ -81,7 +81,7 @@ int nsss_extract_NB_IoT(PHY_VARS_UE_NB_IoT *ue,
//NRS
void generate_pilots_NB_IoT(PHY_VARS_eNB *phy_vars_eNB,
void generate_pilots_NB_IoT(PHY_VARS_eNB_NB_IoT *phy_vars_eNB,
int32_t **txdataF,
int16_t amp,
......@@ -93,7 +93,7 @@ void generate_pilots_NB_IoT(PHY_VARS_eNB *phy_vars_eNB,
//NPBCH
int allocate_npbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
int allocate_npbch_REs_in_RB(NB_IoT_DL_FRAME_PARMS *frame_parms,
int32_t **txdataF,
uint32_t *jj,
......@@ -106,7 +106,7 @@ int allocate_npbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
// NPDSCH
int allocate_REs_in_RB_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,
int allocate_REs_in_RB_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,
int32_t **txdataF,
uint32_t *jj,
uint32_t symbol_offset,
......@@ -121,7 +121,7 @@ int generate_NDLSCH_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
NB_IoT_eNB_NDLSCH_t *RAR,
int32_t **txdataF,
int16_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint32_t subframe,
int RB_IoT_ID,
......@@ -130,7 +130,7 @@ int generate_NDLSCH_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
int generate_NPDCCH_NB_IoT(NB_IoT_eNB_NPDCCH_t *DCI_1,
int32_t **txdataF,
int16_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint32_t subframe,
int RB_IoT_ID);
......@@ -138,7 +138,7 @@ int generate_NPDCCH_NB_IoT(NB_IoT_eNB_NPDCCH_t *DCI_1,
int generate_SIB23(NB_IoT_eNB_NDLSCH_t *SIB23,
int32_t **txdataF,
int16_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint32_t subframe,
int RB_IoT_ID,
......@@ -147,7 +147,7 @@ int generate_SIB23(NB_IoT_eNB_NDLSCH_t *SIB23,
int generate_SIB1(NB_IoT_eNB_NDLSCH_t *sib1_struct,
int32_t **txdataF,
int16_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint32_t subframe,
int RB_IoT_ID,
......@@ -159,19 +159,19 @@ int generate_npbch(NB_IoT_eNB_NPBCH_t *eNB_npbch,
int32_t **txdataF,
int amp,
LTE_DL_FRAME_PARMS *frame_parms,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint8_t *npbch_pdu,
uint8_t frame_mod64,
unsigned short NB_IoT_RB_ID,
uint8_t release_v13_5_0);
void npbch_scrambling(LTE_DL_FRAME_PARMS *frame_parms,
void npbch_scrambling(NB_IoT_DL_FRAME_PARMS *frame_parms,
uint8_t *npbch_e,
uint32_t length);
void dlsch_scrambling_Gen_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,
void dlsch_scrambling_Gen_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,
NB_IoT_eNB_NDLSCH_t *dlsch,
int tot_bits, // total number of bits to transmit
uint16_t Nf, // Nf is the frame number (0..9)
......@@ -180,9 +180,9 @@ void dlsch_scrambling_Gen_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t release_v13_5_0,
uint8_t SIB);
NB_IoT_eNB_NDLSCH_t *new_eNB_dlsch_NB_IoT(uint8_t length, LTE_DL_FRAME_PARMS* frame_parms);
NB_IoT_eNB_NDLSCH_t *new_eNB_dlsch_NB_IoT(uint8_t length, NB_IoT_DL_FRAME_PARMS* frame_parms);
NB_IoT_eNB_NPDCCH_t *new_eNB_dlcch_NB_IoT(LTE_DL_FRAME_PARMS* frame_parms);
NB_IoT_eNB_NPDCCH_t *new_eNB_dlcch_NB_IoT(NB_IoT_DL_FRAME_PARMS* frame_parms);
/*void dlsch_scrambling_Gen_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,
NB_IoT_eNB_NDLSCH_t *dlsch,
......@@ -221,7 +221,7 @@ void add_dci_NB_IoT(DCI_PDU_NB_IoT *DCI_pdu,
/*Use the UL DCI Information to configure PHY and also Pack the DCI*/
int generate_eNB_ulsch_params_from_dci_NB_IoT(PHY_VARS_eNB *eNB,
int generate_eNB_ulsch_params_from_dci_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
int frame,
uint8_t subframe,
DCI_CONTENT *DCI_Content,
......@@ -233,7 +233,7 @@ int generate_eNB_ulsch_params_from_dci_NB_IoT(PHY_VARS_eNB *eNB,
/*Use the DL DCI Information to configure PHY and also Pack the DCI*/
int generate_eNB_dlsch_params_from_dci_NB_IoT(PHY_VARS_eNB *eNB,
int generate_eNB_dlsch_params_from_dci_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
int frame,
uint8_t subframe,
......@@ -291,7 +291,7 @@ int ulsch_decoding_data_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
uint8_t subframe2harq_pid_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t subframe);
uint8_t subframe2harq_pid_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t subframe);
......@@ -329,7 +329,7 @@ uint8_t subframe2harq_pid_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame,
int dci_modulation_NB_IoT(int32_t **txdataF,
int16_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint8_t control_region_size,
NB_IoT_eNB_NPDCCH_t *dlcch,
unsigned int npdsch_data_subframe,
......@@ -338,7 +338,7 @@ int dci_modulation_NB_IoT(int32_t **txdataF,
unsigned int subframe,
unsigned short NB_IoT_RB_ID);
int dci_allocate_REs_in_RB_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,
int dci_allocate_REs_in_RB_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,
int32_t **txdataF,
uint32_t *jj,
uint32_t symbol_offset,
......@@ -360,7 +360,7 @@ void dci_encoding_NB_IoT(uint8_t *a,
uint8_t agr_level);
void npdcch_scrambling_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,
void npdcch_scrambling_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,
NB_IoT_eNB_NPDCCH_t *dlcch, // Input data
int G, // Total number of bits to transmit in one subframe(case of DCI = G)
uint8_t Ns, //XXX we pass the subframe // Slot number (0..19)
......@@ -370,7 +370,7 @@ void npdcch_scrambling_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,
int dlsch_modulation_NB_IoT(int32_t **txdataF,
int16_t amp,
LTE_DL_FRAME_PARMS *frame_parms,
NB_IoT_DL_FRAME_PARMS *frame_parms,
uint8_t control_region_size, // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
NB_IoT_eNB_NDLSCH_t *dlsch0, //NB_IoT_eNB_NDLSCH_t
int G, // number of bits per subframe
......@@ -398,7 +398,7 @@ int32_t dlsch_encoding_NB_IoT(unsigned char *a,
void get_pilots_position(uint8_t npusch_format,uint8_t subcarrier_spacing,uint8_t *pilot_pos1,uint8_t *pilot_pos2,uint8_t *pilots_slot);
void UL_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
LTE_DL_FRAME_PARMS *fp,
NB_IoT_DL_FRAME_PARMS *fp,
uint16_t UL_RB_ID_NB_IoT,
uint16_t Nsc_RU,
uint8_t pilot_pos1,
......@@ -409,7 +409,7 @@ void UL_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
uint8_t rx_subframe);
void get_llr_per_sf_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
LTE_DL_FRAME_PARMS *fp,
NB_IoT_DL_FRAME_PARMS *fp,
uint8_t npusch_format,
uint8_t counter_sf,
uint16_t N_SF_per_word,
......@@ -418,7 +418,7 @@ void get_llr_per_sf_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
uint16_t ul_sc_start,
uint16_t Nsc_RU);
void descrambling_NPUSCH_data_NB_IoT(LTE_DL_FRAME_PARMS *fp,
void descrambling_NPUSCH_data_NB_IoT(NB_IoT_DL_FRAME_PARMS *fp,
int16_t *ulsch_llr,
int16_t *y,
uint8_t Qm,
......@@ -427,7 +427,7 @@ void descrambling_NPUSCH_data_NB_IoT(LTE_DL_FRAME_PARMS *fp,
uint8_t rx_subframe,
uint32_t rx_frame);
void descrambling_NPUSCH_ack_NB_IoT(LTE_DL_FRAME_PARMS *fp,
void descrambling_NPUSCH_ack_NB_IoT(NB_IoT_DL_FRAME_PARMS *fp,
int32_t *y_msg5,
int32_t *llr_msg5,
uint32_t rnti_tmp,
......@@ -693,13 +693,13 @@ int ul_chequal_tmp_NB_IoT(int32_t **rxdataF_ext,
////////////////////////////NB-IoT testing ///////////////////////////////
void clean_eNb_ulsch_NB_IoT(NB_IoT_eNB_NULSCH_t *ulsch);
int get_G_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms);
int get_G_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms);
int get_G_SIB1_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms, uint8_t operation_mode_info);
int get_G_SIB1_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms, uint8_t operation_mode_info);
int get_rep_num_SIB1_NB_IoT(uint8_t scheduling_info_sib1);
int get_start_frame_SIB1_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,uint8_t repetition);
int get_start_frame_SIB1_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,uint8_t repetition);
NB_IoT_eNB_NULSCH_t *new_eNB_ulsch_NB_IoT(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag);
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/defs.h
\brief Top-level defines and structure definitions
\author R. Knopp, F. Kaltenberger
\date 2011
\version 0.1
\company Eurecom
\email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
\note
\warning
*/
#ifndef __PHY_DEFS_COMMON_H__
#define __PHY_DEFS_COMMON_H__
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <linux/sched.h>
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
#include <sys/sysinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <math.h>
#include "common_lib.h"
#include "msc.h"
#include <common/utils/LOG/log.h>
#include "assertions.h"
//#include <complex.h>
#include "PHY/TOOLS/time_meas.h"
#include "platform_types.h"
#define MAX_NUM_RU_PER_eNB 64
#include <pthread.h>
#include "targets/COMMON/openairinterface5g_limits.h"
#include "types.h"
#include "nfapi_interface.h"
//#include "defs.h"
#define RX_NB_TH_MAX 2
#define RX_NB_TH 2
#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
#define NB_RX_ANTENNAS_MAX 64
#ifdef OCP_FRAMEWORK
#include "enums.h"
#else
typedef enum {TDD=1,FDD=0} lte_frame_type_t;
typedef enum {EXTENDED=1,NORMAL=0} lte_prefix_type_t;
typedef enum {LOCALIZED=0,DISTRIBUTED=1} vrb_t;
/// Enumeration for parameter PHICH-Duration \ref PHICH_CONFIG_COMMON::phich_duration.
typedef enum {
normal=0,
extended=1
} PHICH_DURATION_t;
/// Enumeration for parameter Ng \ref PHICH_CONFIG_COMMON::phich_resource.
typedef enum {
oneSixth=1,
half=3,
one=6,
two=12
} PHICH_RESOURCE_t;
#endif
/// PHICH-Config from 36.331 RRC spec
typedef struct {
/// Parameter: PHICH-Duration, see TS 36.211 (Table 6.9.3-1).
PHICH_DURATION_t phich_duration;
/// Parameter: Ng, see TS 36.211 (6.9). \details Value oneSixth corresponds to 1/6, half corresponds to 1/2 and so on.
PHICH_RESOURCE_t phich_resource;
} PHICH_CONFIG_COMMON;
/// PRACH-ConfigInfo from 36.331 RRC spec
typedef struct {
/// Parameter: prach-ConfigurationIndex, see TS 36.211 (5.7.1). \vr{[0..63]}
uint8_t prach_ConfigIndex;
/// Parameter: High-speed-flag, see TS 36.211 (5.7.2). \vr{[0..1]} 1 corresponds to Restricted set and 0 to Unrestricted set.
uint8_t highSpeedFlag;
/// Parameter: \f$N_\text{CS}\f$, see TS 36.211 (5.7.2). \vr{[0..15]}\n Refer to table 5.7.2-2 for preamble format 0..3 and to table 5.7.2-3 for preamble format 4.
uint8_t zeroCorrelationZoneConfig;
/// Parameter: prach-FrequencyOffset, see TS 36.211 (5.7.1). \vr{[0..94]}\n For TDD the value range is dependent on the value of \ref prach_ConfigIndex.
uint8_t prach_FreqOffset;
} PRACH_CONFIG_INFO;
/// PRACH-ConfigSIB or PRACH-Config from 36.331 RRC spec
typedef struct {
/// Parameter: RACH_ROOT_SEQUENCE, see TS 36.211 (5.7.1). \vr{[0..837]}
uint16_t rootSequenceIndex;
/// prach_Config_enabled=1 means enabled. \vr{[0..1]}
uint8_t prach_Config_enabled;
/// PRACH Configuration Information
PRACH_CONFIG_INFO prach_ConfigInfo;
} PRACH_CONFIG_COMMON;
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
/// PRACH-eMTC-Config from 36.331 RRC spec
typedef struct {
/// Parameter: High-speed-flag, see TS 36.211 (5.7.2). \vr{[0..1]} 1 corresponds to Restricted set and 0 to Unrestricted set.
uint8_t highSpeedFlag;
/// Parameter: \f$N_\text{CS}\f$, see TS 36.211 (5.7.2). \vr{[0..15]}\n Refer to table 5.7.2-2 for preamble format 0..3 and to table 5.7.2-3 for preamble format 4.
uint8_t zeroCorrelationZoneConfig;
/// Parameter: prach-FrequencyOffset, see TS 36.211 (5.7.1). \vr{[0..94]}\n For TDD the value range is dependent on the value of \ref prach_ConfigIndex.
/// PRACH starting subframe periodicity, expressed in number of subframes available for preamble transmission (PRACH opportunities), see TS 36.211. Value 2 corresponds to 2 subframes, 4 corresponds to 4 subframes and so on. EUTRAN configures the PRACH starting subframe periodicity larger than or equal to the Number of PRACH repetitions per attempt for each CE level (numRepetitionPerPreambleAttempt).
uint8_t prach_starting_subframe_periodicity[4];
/// number of repetitions per preamble attempt per CE level
uint8_t prach_numRepetitionPerPreambleAttempt[4];
/// prach configuration index for each CE level
uint8_t prach_ConfigIndex[4];
/// indicator for CE level activation
uint8_t prach_CElevel_enable[4];
/// prach frequency offset for each CE level
uint8_t prach_FreqOffset[4];
/// indicator for CE level hopping activation
uint8_t prach_hopping_enable[4];
/// indicator for CE level hopping activation
uint8_t prach_hopping_offset[4];
} PRACH_eMTC_CONFIG_INFO;
/// PRACH-ConfigSIB or PRACH-Config from 36.331 RRC spec
typedef struct {
/// Parameter: RACH_ROOT_SEQUENCE, see TS 36.211 (5.7.1). \vr{[0..837]}
uint16_t rootSequenceIndex;
/// prach_Config_enabled=1 means enabled. \vr{[0..1]}
uint8_t prach_Config_enabled;
/// PRACH Configuration Information
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
PRACH_eMTC_CONFIG_INFO prach_ConfigInfo;
#endif
} PRACH_eMTC_CONFIG_COMMON;
#endif
/// Enumeration for parameter \f$N_\text{ANRep}\f$ \ref PUCCH_CONFIG_DEDICATED::repetitionFactor.
typedef enum {
n2=0,
n4,
n6
} ACKNAKREP_t;
/// Enumeration for \ref PUCCH_CONFIG_DEDICATED::tdd_AckNackFeedbackMode.
typedef enum {
bundling=0,
multiplexing
} ANFBmode_t;
/// PUCCH-ConfigDedicated from 36.331 RRC spec
typedef struct {
/// Flag to indicate ACK NAK repetition activation, see TS 36.213 (10.1). \vr{[0..1]}
uint8_t ackNackRepetition;
/// Parameter: \f$N_\text{ANRep}\f$, see TS 36.213 (10.1).
ACKNAKREP_t repetitionFactor;
/// Parameter: \f$n^{(1)}_\text{PUCCH,ANRep}\f$, see TS 36.213 (10.1). \vr{[0..2047]}
uint16_t n1PUCCH_AN_Rep;
/// Feedback mode, see TS 36.213 (7.3). \details Applied to both PUCCH and PUSCH feedback. For TDD, should always be set to bundling.
ANFBmode_t tdd_AckNackFeedbackMode;
} PUCCH_CONFIG_DEDICATED;
/// PUCCH-ConfigCommon from 36.331 RRC spec
typedef struct {
/// Parameter: \f$\Delta^\text{PUCCH}_\text{shift}\f$, see TS 36.211 (5.4.1). \vr{[1..3]} \note the specification sais it is an enumerated value.
uint8_t deltaPUCCH_Shift;
/// Parameter: \f$N^{(2)}_\text{RB}\f$, see TS 36.211 (5.4). \vr{[0..98]}
uint8_t nRB_CQI;
/// Parameter: \f$N^{(1)}_\text{CS}\f$, see TS 36.211 (5.4). \vr{[0..7]}
uint8_t nCS_AN;
/// Parameter: \f$N^{(1)}_\text{PUCCH}\f$ see TS 36.213 (10.1). \vr{[0..2047]}
uint16_t n1PUCCH_AN;
/// group hopping sequence for DRS \note not part of offical UL-PUCCH_CONFIG_COMMON ASN1 specification.
uint8_t grouphop[20];
/// sequence hopping sequence for DRS \note not part of offical UL-PUCCH_CONFIG_COMMON ASN1 specification.
uint8_t seqhop[20];
} PUCCH_CONFIG_COMMON;
/// UL-ReferenceSignalsPUSCH from 36.331 RRC spec
typedef struct {
/// Parameter: Group-hopping-enabled, see TS 36.211 (5.5.1.3). \vr{[0..1]}
uint8_t groupHoppingEnabled;
/// Parameter: \f$\Delta SS\f$, see TS 36.211 (5.5.1.3). \vr{[0..29]}
uint8_t groupAssignmentPUSCH;
/// Parameter: Sequence-hopping-enabled, see TS 36.211 (5.5.1.4). \vr{[0..1]}
uint8_t sequenceHoppingEnabled;
/// Parameter: cyclicShift, see TS 36.211 (Table 5.5.2.1.1-2). \vr{[0..7]}
uint8_t cyclicShift;
/// nPRS for cyclic shift of DRS \note not part of offical UL-ReferenceSignalsPUSCH ASN1 specification.
uint8_t nPRS[20];
/// group hopping sequence for DRS \note not part of offical UL-ReferenceSignalsPUSCH ASN1 specification.
uint8_t grouphop[20];
/// sequence hopping sequence for DRS \note not part of offical UL-ReferenceSignalsPUSCH ASN1 specification.
uint8_t seqhop[20];
} UL_REFERENCE_SIGNALS_PUSCH_t;
/// Enumeration for parameter Hopping-mode \ref PUSCH_CONFIG_COMMON::hoppingMode.
#ifndef OCP_FRAMEWORK
typedef enum {
interSubFrame=0,
intraAndInterSubFrame=1
} PUSCH_HOPPING_t;
#endif
/// PUSCH-ConfigCommon from 36.331 RRC spec.
typedef struct {
/// Parameter: \f$N_{sb}\f$, see TS 36.211 (5.3.4). \vr{[1..4]}
uint8_t n_SB;
/// Parameter: Hopping-mode, see TS 36.211 (5.3.4).
PUSCH_HOPPING_t hoppingMode;
/// Parameter: \f$N^{HO}_{RB}\f$, see TS 36.211 (5.3.4). \vr{[0..98]}
uint8_t pusch_HoppingOffset;
/// See TS 36.213 (8.6.1). \vr{[0..1]} 1 indicates 64QAM is allowed, 0 not allowed.
uint8_t enable64QAM;
/// Ref signals configuration
UL_REFERENCE_SIGNALS_PUSCH_t ul_ReferenceSignalsPUSCH;
} PUSCH_CONFIG_COMMON;
/// UE specific PUSCH configuration.
typedef struct {
/// Parameter: \f$I^\text{HARQ-ACK}_\text{offset}\f$, see TS 36.213 (Table 8.6.3-1). \vr{[0..15]}
uint16_t betaOffset_ACK_Index;
/// Parameter: \f$I^{RI}_\text{offset}\f$, see TS 36.213 (Table 8.6.3-2). \vr{[0..15]}
uint16_t betaOffset_RI_Index;
/// Parameter: \f$I^{CQI}_\text{offset}\f$, see TS 36.213 (Table 8.6.3-3). \vr{[0..15]}
uint16_t betaOffset_CQI_Index;
} PUSCH_CONFIG_DEDICATED;
/// lola CBA information
typedef struct {
///
uint16_t betaOffset_CA_Index;
///
uint16_t cShift;
} PUSCH_CA_CONFIG_DEDICATED;
/// PDSCH-ConfigCommon from 36.331 RRC spec
typedef struct {
/// Parameter: Reference-signal power, see TS 36.213 (5.2). \vr{[-60..50]}\n Provides the downlink reference-signal EPRE. The actual value in dBm.
int8_t referenceSignalPower;
/// Parameter: \f$P_B\f$, see TS 36.213 (Table 5.2-1). \vr{[0..3]}
uint8_t p_b;
} PDSCH_CONFIG_COMMON;
/// Enumeration for Parameter \f$P_A\f$ \ref PDSCH_CONFIG_DEDICATED::p_a.
typedef enum {
dBm6=0, ///< (dB-6) corresponds to -6 dB
dBm477, ///< (dB-4dot77) corresponds to -4.77 dB
dBm3, ///< (dB-3) corresponds to -3 dB
dBm177, ///< (dB-1dot77) corresponds to -1.77 dB
dB0, ///< corresponds to 0 dB
dB1, ///< corresponds to 1 dB
dB2, ///< corresponds to 2 dB
dB3 ///< corresponds to 3 dB
} PA_t;
/// PDSCH-ConfigDedicated from 36.331 RRC spec
typedef struct {
/// Parameter: \f$P_A\f$, see TS 36.213 (5.2).
PA_t p_a;
} PDSCH_CONFIG_DEDICATED;
/// SoundingRS-UL-ConfigCommon Information Element from 36.331 RRC spec
typedef struct {
/// enabled flag=1 means SRS is enabled. \vr{[0..1]}
uint8_t enabled_flag;
/// Parameter: SRS Bandwidth Configuration, see TS 36.211 (table 5.5.3.2-1, 5.5.3.2-2, 5.5.3.2-3 and 5.5.3.2-4). \vr{[0..7]}\n Actual configuration depends on UL bandwidth. \note the specification sais it is an enumerated value.
uint8_t srs_BandwidthConfig;
/// Parameter: SRS SubframeConfiguration, see TS 36.211 (table 5.5.3.3-1 for FDD, table 5.5.3.3-2 for TDD). \vr{[0..15]} \note the specification sais it is an enumerated value.
uint8_t srs_SubframeConfig;
/// Parameter: Simultaneous-AN-and-SRS, see TS 36.213 (8.2). \vr{[0..1]}
uint8_t ackNackSRS_SimultaneousTransmission;
/// Parameter: srsMaxUpPts, see TS 36.211 (5.5.3.2). \details If this field is present, reconfiguration of \f$m^\text{max}_\text{SRS,0}\f$ applies for UpPts, otherwise reconfiguration does not apply.
uint8_t srs_MaxUpPts;
} SOUNDINGRS_UL_CONFIG_COMMON;
/// \note UNUSED
typedef enum {
ulpc_al0=0,
ulpc_al04=1,
ulpc_al05=2,
ulpc_al06=3,
ulpc_al07=4,
ulpc_al08=5,
ulpc_al09=6,
ulpc_al11=7
} UL_POWER_CONTROL_COMMON_alpha_t;
/// Enumeration for \ref deltaFList_PUCCH_t::deltaF_PUCCH_Format1.
typedef enum {
deltaF_PUCCH_Format1_deltaF_2 = 0,
deltaF_PUCCH_Format1_deltaF0 = 1,
deltaF_PUCCH_Format1_deltaF2 = 2
} deltaF_PUCCH_Format1_t;
/// Enumeration for \ref deltaFList_PUCCH_t::deltaF_PUCCH_Format1b.
typedef enum {
deltaF_PUCCH_Format1b_deltaF1 = 0,
deltaF_PUCCH_Format1b_deltaF3 = 1,
deltaF_PUCCH_Format1b_deltaF5 = 2
} deltaF_PUCCH_Format1b_t;
/// Enumeration for \ref deltaFList_PUCCH_t::deltaF_PUCCH_Format2.
typedef enum {
deltaF_PUCCH_Format2_deltaF_2 = 0,
deltaF_PUCCH_Format2_deltaF0 = 1,
deltaF_PUCCH_Format2_deltaF1 = 2,
deltaF_PUCCH_Format2_deltaF2 = 3
} deltaF_PUCCH_Format2_t;
/// Enumeration for \ref deltaFList_PUCCH_t::deltaF_PUCCH_Format2a.
typedef enum {
deltaF_PUCCH_Format2a_deltaF_2 = 0,
deltaF_PUCCH_Format2a_deltaF0 = 1,
deltaF_PUCCH_Format2a_deltaF2 = 2
} deltaF_PUCCH_Format2a_t;
/// Enumeration for \ref deltaFList_PUCCH_t::deltaF_PUCCH_Format2b.
typedef enum {
deltaF_PUCCH_Format2b_deltaF_2 = 0,
deltaF_PUCCH_Format2b_deltaF0 = 1,
deltaF_PUCCH_Format2b_deltaF2 = 2
} deltaF_PUCCH_Format2b_t;
/// DeltaFList-PUCCH from 36.331 RRC spec
typedef struct {
deltaF_PUCCH_Format1_t deltaF_PUCCH_Format1;
deltaF_PUCCH_Format1b_t deltaF_PUCCH_Format1b;
deltaF_PUCCH_Format2_t deltaF_PUCCH_Format2;
deltaF_PUCCH_Format2a_t deltaF_PUCCH_Format2a;
deltaF_PUCCH_Format2b_t deltaF_PUCCH_Format2b;
} deltaFList_PUCCH_t;
/// SoundingRS-UL-ConfigDedicated Information Element from 36.331 RRC spec
typedef struct {
/// This descriptor is active
uint8_t active;
/// This descriptor's frame
uint16_t frame;
/// This descriptor's subframe
uint8_t subframe;
/// rnti
uint16_t rnti;
/// Parameter: \f$B_\text{SRS}\f$, see TS 36.211 (table 5.5.3.2-1, 5.5.3.2-2, 5.5.3.2-3 and 5.5.3.2-4). \vr{[0..3]} \note the specification sais it is an enumerated value.
uint8_t srs_Bandwidth;
/// Parameter: SRS hopping bandwidth \f$b_\text{hop}\in\{0,1,2,3\}\f$, see TS 36.211 (5.5.3.2) \vr{[0..3]} \note the specification sais it is an enumerated value.
uint8_t srs_HoppingBandwidth;
/// Parameter: \f$n_\text{RRC}\f$, see TS 36.211 (5.5.3.2). \vr{[0..23]}
uint8_t freqDomainPosition;
/// Parameter: Duration, see TS 36.213 (8.2). \vr{[0..1]} 0 corresponds to "single" and 1 to "indefinite".
uint8_t duration;
/// Parameter: \f$k_\text{TC}\in\{0,1\}\f$, see TS 36.211 (5.5.3.2). \vr{[0..1]}
uint8_t transmissionComb;
/// Parameter: \f$I_\text{SRS}\f$, see TS 36.213 (table 8.2-1). \vr{[0..1023]}
uint16_t srs_ConfigIndex;
/// Parameter: \f$n^\text{CS}_\text{SRS}\f$. See TS 36.211 (5.5.3.1). \vr{[0..7]} \note the specification sais it is an enumerated value.
uint8_t cyclicShift;
// Parameter: internal implementation: UE SRS configured
uint8_t srsConfigDedicatedSetup;
// Parameter: cell srs subframe for internal implementation
uint8_t srsCellSubframe;
// Parameter: ue srs subframe for internal implementation
uint8_t srsUeSubframe;
} SOUNDINGRS_UL_CONFIG_DEDICATED;
/// UplinkPowerControlDedicated Information Element from 36.331 RRC spec
typedef struct {
/// Parameter: \f$P_\text{0\_UE\_PUSCH}(1)\f$, see TS 36.213 (5.1.1.1), unit dB. \vr{[-8..7]}\n This field is applicable for non-persistent scheduling, only.
int8_t p0_UE_PUSCH;
/// Parameter: Ks, see TS 36.213 (5.1.1.1). \vr{[0..1]}\n en0 corresponds to value 0 corresponding to state “disabled”. en1 corresponds to value 1.25 corresponding to “enabled”. \note the specification sais it is an enumerated value. \warning the enumeration values do not correspond to the given values in the specification (en1 should be 1.25).
uint8_t deltaMCS_Enabled;
/// Parameter: Accumulation-enabled, see TS 36.213 (5.1.1.1). \vr{[0..1]} 1 corresponds to "enabled" whereas 0 corresponds to "disabled".
uint8_t accumulationEnabled;
/// Parameter: \f$P_\text{0\_UE\_PUCCH}(1)\f$, see TS 36.213 (5.1.2.1), unit dB. \vr{[-8..7]}
int8_t p0_UE_PUCCH;
/// Parameter: \f$P_\text{SRS\_OFFSET}\f$, see TS 36.213 (5.1.3.1). \vr{[0..15]}\n For Ks=1.25 (\ref deltaMCS_Enabled), the actual parameter value is pSRS_Offset value - 3. For Ks=0, the actual parameter value is -10.5 + 1.5*pSRS_Offset value.
int8_t pSRS_Offset;
/// Specifies the filtering coefficient for RSRP measurements used to calculate path loss, as specified in TS 36.213 (5.1.1.1).\details The same filtering mechanism applies as for quantityConfig described in 5.5.3.2. \note the specification sais it is an enumerated value.
uint8_t filterCoefficient;
} UL_POWER_CONTROL_DEDICATED;
#ifndef OCP_FRAMEWORK
/// Enumeration for parameter \f$\alpha\f$ \ref UL_POWER_CONTROL_CONFIG_COMMON::alpha.
typedef enum {
al0=0,
al04=1,
al05=2,
al06=3,
al07=4,
al08=5,
al09=6,
al1=7
} PUSCH_alpha_t;
#endif
/// \note UNUSED
typedef enum {
deltaFm2=0,
deltaF0,
deltaF1,
deltaF2,
deltaF3,
deltaF5
} deltaF_PUCCH_t;
/// UplinkPowerControlCommon Information Element from 36.331 RRC spec \note this structure does not currently make use of \ref deltaFList_PUCCH_t.
typedef struct {
/// Parameter: \f$P_\text{0\_NOMINAL\_PUSCH}(1)\f$, see TS 36.213 (5.1.1.1), unit dBm. \vr{[-126..24]}\n This field is applicable for non-persistent scheduling, only.
int8_t p0_NominalPUSCH;
/// Parameter: \f$\alpha\f$, see TS 36.213 (5.1.1.1) \warning the enumeration values do not correspond to the given values in the specification (al04 should be 0.4, ...)!
PUSCH_alpha_t alpha;
/// Parameter: \f$P_\text{0\_NOMINAL\_PUCCH}\f$ See TS 36.213 (5.1.2.1), unit dBm. \vr{[-127..-96]}
int8_t p0_NominalPUCCH;
/// Parameter: \f$\Delta_\text{PREAMBLE\_Msg3}\f$ see TS 36.213 (5.1.1.1). \vr{[-1..6]}\n Actual value = IE value * 2 [dB].
int8_t deltaPreambleMsg3;
/// Parameter: \f$\Delta_\text{F\_PUCCH}(F)\f$ for the PUCCH format 1, see TS 36.213 (5.1.2). \vr{[0..2]} \warning check value range, why is this a long? \note the specification sais it is an enumerated value.
long deltaF_PUCCH_Format1;
/// Parameter: \f$\Delta_\text{F\_PUCCH}(F)\f$ for the PUCCH format 1a, see TS 36.213 (5.1.2). \vr{[0..2]} \warning check value range, why is this a long? \note the specification sais it is an enumerated value.
long deltaF_PUCCH_Format1a;
/// Parameter: \f$\Delta_\text{F\_PUCCH}(F)\f$ for the PUCCH format 1b, see TS 36.213 (5.1.2). \vr{[0..2]} \warning check value range, why is this a long? \note the specification sais it is an enumerated value.
long deltaF_PUCCH_Format1b;
/// Parameter: \f$\Delta_\text{F\_PUCCH}(F)\f$ for the PUCCH format 2, see TS 36.213 (5.1.2). \vr{[0..3]} \warning check value range, why is this a long? \note the specification sais it is an enumerated value.
long deltaF_PUCCH_Format2;
/// Parameter: \f$\Delta_\text{F\_PUCCH}(F)\f$ for the PUCCH format 2a, see TS 36.213 (5.1.2). \vr{[0..2]} \warning check value range, why is this a long? \note the specification sais it is an enumerated value.
long deltaF_PUCCH_Format2a;
/// Parameter: \f$\Delta_\text{F\_PUCCH}(F)\f$ for the PUCCH format 2b, see TS 36.213 (5.1.2). \vr{[0..2]} \warning check value range, why is this a long? \note the specification sais it is an enumerated value.
long deltaF_PUCCH_Format2b;
} UL_POWER_CONTROL_CONFIG_COMMON;
/// Union for \ref TPC_PDCCH_CONFIG::tpc_Index.
typedef union {
/// Index of N when DCI format 3 is used. See TS 36.212 (5.3.3.1.6). \vr{[1..15]}
uint8_t indexOfFormat3;
/// Index of M when DCI format 3A is used. See TS 36.212 (5.3.3.1.7). \vr{[1..31]}
uint8_t indexOfFormat3A;
} TPC_INDEX_t;
/// TPC-PDCCH-Config Information Element from 36.331 RRC spec
typedef struct {
/// RNTI for power control using DCI format 3/3A, see TS 36.212. \vr{[0..65535]}
uint16_t rnti;
/// Index of N or M, see TS 36.212 (5.3.3.1.6 and 5.3.3.1.7), where N or M is dependent on the used DCI format (i.e. format 3 or 3a).
TPC_INDEX_t tpc_Index;
} TPC_PDCCH_CONFIG;
/// Enumeration for parameter SR transmission \ref SCHEDULING_REQUEST_CONFIG::dsr_TransMax.
typedef enum {
sr_n4=0,
sr_n8=1,
sr_n16=2,
sr_n32=3,
sr_n64=4
} DSR_TRANSMAX_t;
/// SchedulingRequestConfig Information Element from 36.331 RRC spec
typedef struct {
/// Parameter: \f$n^{(1)}_\text{PUCCH,SRI}\f$, see TS 36.213 (10.1). \vr{[0..2047]}
uint16_t sr_PUCCH_ResourceIndex;
/// Parameter: \f$I_\text{SR}\f$, see TS 36.213 (10.1). \vr{[0..155]}
uint8_t sr_ConfigIndex;
/// Parameter for SR transmission in TS 36.321 (5.4.4). \details The value n4 corresponds to 4 transmissions, n8 corresponds to 8 transmissions and so on.
DSR_TRANSMAX_t dsr_TransMax;
} SCHEDULING_REQUEST_CONFIG;
/// CQI-ReportPeriodic
typedef struct {
/// Parameter: \f$n^{(2)}_\text{PUCCH}\f$, see TS 36.213 (7.2). \vr{[0..1185]}, -1 indicates inactivity
int16_t cqi_PUCCH_ResourceIndex;
/// Parameter: CQI/PMI Periodicity and Offset Configuration Index \f$I_\text{CQI/PMI}\f$, see TS 36.213 (tables 7.2.2-1A and 7.2.2-1C). \vr{[0..1023]}
int16_t cqi_PMI_ConfigIndex;
/// Parameter: K, see 36.213 (4.2.2). \vr{[1..4]}
uint8_t K;
/// Parameter: RI Config Index \f$I_\text{RI}\f$, see TS 36.213 (7.2.2-1B). \vr{[0..1023]}, -1 indicates inactivity
int16_t ri_ConfigIndex;
/// Parameter: Simultaneous-AN-and-CQI, see TS 36.213 (10.1). \vr{[0..1]} 1 indicates that simultaneous transmission of ACK/NACK and CQI is allowed.
uint8_t simultaneousAckNackAndCQI;
/// parameter computed from Tables 7.2.2-1A and 7.2.2-1C
uint16_t Npd;
/// parameter computed from Tables 7.2.2-1A and 7.2.2-1C
uint16_t N_OFFSET_CQI;
} CQI_REPORTPERIODIC;
/// Enumeration for parameter reporting mode \ref CQI_REPORT_CONFIG::cqi_ReportModeAperiodic.
typedef enum {
rm12=0,
rm20=1,
rm22=2,
rm30=3,
rm31=4
} CQI_REPORTMODEAPERIODIC;
/// CQI-ReportConfig Information Element from 36.331 RRC spec
typedef struct {
/// Parameter: reporting mode. Value rm12 corresponds to Mode 1-2, rm20 corresponds to Mode 2-0, rm22 corresponds to Mode 2-2 etc. PUSCH reporting modes are described in TS 36.213 [23, 7.2.1].
CQI_REPORTMODEAPERIODIC cqi_ReportModeAperiodic;
/// Parameter: \f$\Delta_\text{offset}\f$, see TS 36.213 (7.2.3). \vr{[-1..6]}\n Actual value = IE value * 2 [dB].
int8_t nomPDSCH_RS_EPRE_Offset;
CQI_REPORTPERIODIC CQI_ReportPeriodic;
} CQI_REPORT_CONFIG;
/// MBSFN-SubframeConfig Information Element from 36.331 RRC spec \note deviates from specification.
typedef struct {
/// MBSFN subframe occurance. \details Radio-frames that contain MBSFN subframes occur when equation SFN mod radioFrameAllocationPeriod = radioFrameAllocationOffset is satisfied. When fourFrames is used for subframeAllocation, the equation defines the first radio frame referred to in the description below. Values n1 and n2 are not applicable when fourFrames is used. \note the specification sais it is an enumerated value {n1, n2, n4, n8, n16, n32}.
int radioframeAllocationPeriod;
/// MBSFN subframe occurance. \vr{[0..7]}\n Radio-frames that contain MBSFN subframes occur when equation SFN mod radioFrameAllocationPeriod = radioFrameAllocationOffset is satisfied. When fourFrames is used for subframeAllocation, the equation defines the first radio frame referred to in the description below. Values n1 and n2 are not applicable when fourFrames is used.
int radioframeAllocationOffset;
/// oneFrame or fourFrames. \vr{[0..1]}
int fourFrames_flag;
/// Subframe configuration. \vr{[0..63]} (\ref fourFrames_flag == 0) or \vr{[0..16777215]} (\ref fourFrames_flag == 1)
/// \par fourFrames_flag == 0
/// "1" denotes that the corresponding subframe is allocated for MBSFN. The following mapping applies:\n FDD: The first/leftmost bit defines the MBSFN allocation for subframe #1, the second bit for #2, third bit for #3 , fourth bit for #6, fifth bit for #7, sixth bit for #8.\n TDD: The first/leftmost bit defines the allocation for subframe #3, the second bit for #4, third bit for #7, fourth bit for #8, fifth bit for #9. Uplink subframes are not allocated. The last bit is not used.
/// \par fourFrames_flag == 1
/// A bit-map indicating MBSFN subframe allocation in four consecutive radio frames, "1" denotes that the corresponding subframe is allocated for MBSFN. The bitmap is interpreted as follows:\n FDD: Starting from the first radioframe and from the first/leftmost bit in the bitmap, the allocation applies to subframes #1, #2, #3 , #6, #7, and #8 in the sequence of the four radio-frames.\n TDD: Starting from the first radioframe and from the first/leftmost bit in the bitmap, the allocation applies to subframes #3, #4, #7, #8, and #9 in the sequence of the four radio-frames. The last four bits are not used. Uplink subframes are not allocated.
int mbsfn_SubframeConfig;
} MBSFN_config_t;
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
typedef struct {
int radioframeAllocationPeriod;
int radioframeAllocationOffset;
int non_mbsfn_SubframeConfig;
} NonMBSFN_config_t;
#endif
typedef struct {
/// Number of resource blocks (RB) in DL
uint8_t N_RB_DL;
/// Number of resource blocks (RB) in UL
uint8_t N_RB_UL;
/// EUTRA Band
uint8_t eutra_band;
/// DL carrier frequency
uint32_t dl_CarrierFreq;
/// UL carrier frequency
uint32_t ul_CarrierFreq;
/// TX attenuation
uint32_t att_tx;
/// RX attenuation
uint32_t att_rx;
/// 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;
/// Cell ID
uint16_t Nid_cell;
/// MBSFN Area ID
uint16_t Nid_cell_mbsfn;
/// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
lte_prefix_type_t Ncp;
/// Cyclic Prefix for UL (0=Normal CP, 1=Extended CP)
lte_prefix_type_t Ncp_UL;
/// shift of pilot position in one RB
uint8_t nushift;
/// 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)
uint8_t tdd_config_S;
/// srs extra symbol flag for TDD
uint8_t srsX;
/// indicates if node is a UE (NODE=2) or eNB (PRIMARY_CH=0).
uint8_t node_id;
/// Indicator that 20 MHz channel uses 3/4 sampling frequency
uint8_t threequarter_fs;
/// Size of FFT
uint16_t ofdm_symbol_size;
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
uint8_t FeMBMS_active;
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
/// Size of FFT
uint16_t ofdm_symbol_size_khz_1dot25;
#endif
/// Number of prefix samples in all but first symbol of slot
uint16_t nb_prefix_samples;
/// Number of prefix samples in first symbol of slot
uint16_t nb_prefix_samples0;
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
/// Number of prefix samples in all but first symbol of slot
uint16_t nb_prefix_samples_khz_1dot25;
/// Number of prefix samples in first symbol of slot
uint16_t nb_prefix_samples0_khz_1dot25;
#endif
/// Carrier offset in FFT buffer for first RE in PRB0
uint16_t first_carrier_offset;
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
/// Carrier offset in FFT buffer for first RE in PRB0 (FeMBMS
uint16_t first_carrier_offset_khz_1dot25;
#endif
/// Number of samples in a subframe
uint32_t samples_per_tti;
/// 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 OFDM symbols in DL portion of S-subframe
uint16_t dl_symbols_in_S_subframe;
/// Number of SC-FDMA symbols in UL portion of S-subframe
uint16_t ul_symbols_in_S_subframe;
/// 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;
/// PRACH_CONFIG
PRACH_CONFIG_COMMON prach_config_common;
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
/// PRACH_eMTC_CONFIG
PRACH_eMTC_CONFIG_COMMON prach_emtc_config_common;
#endif
/// PUCCH Config Common (from 36-331 RRC spec)
PUCCH_CONFIG_COMMON pucch_config_common;
/// PDSCH Config Common (from 36-331 RRC spec)
PDSCH_CONFIG_COMMON pdsch_config_common;
/// PUSCH Config Common (from 36-331 RRC spec)
PUSCH_CONFIG_COMMON pusch_config_common;
/// PHICH Config (from 36-331 RRC spec)
PHICH_CONFIG_COMMON phich_config_common;
/// SRS Config (from 36-331 RRC spec)
SOUNDINGRS_UL_CONFIG_COMMON soundingrs_ul_config_common;
/// UL Power Control (from 36-331 RRC spec)
UL_POWER_CONTROL_CONFIG_COMMON ul_power_control_config_common;
/// Number of MBSFN Configurations
int num_MBSFN_config;
/// Array of MBSFN Configurations (max 8 (maxMBSFN-Allocations) elements as per 36.331)
MBSFN_config_t MBSFN_config[8];
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
uint8_t NonMBSFN_config_flag;
NonMBSFN_config_t NonMBSFN_config;
#endif
/// Maximum Number of Retransmissions of RRCConnectionRequest (from 36-331 RRC Spec)
uint8_t maxHARQ_Msg3Tx;
/// Size of SI windows used for repetition of one SI message (in frames)
uint8_t SIwindowsize;
/// Period of SI windows used for repetition of one SI message (in frames)
uint16_t SIPeriod;
/// REGs assigned to PCFICH
uint16_t pcfich_reg[4];
/// Index of first REG assigned to PCFICH
uint8_t pcfich_first_reg_idx;
/// REGs assigned to PHICH
uint16_t phich_reg[MAX_NUM_PHICH_GROUPS][3];
struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[MAX_MBSFN_AREA];
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
struct NonMBSFN_SubframeConfig *non_mbsfn_SubframeConfig;
#endif
/// for fair RR scheduler
uint32_t ue_multiple_max;
} LTE_DL_FRAME_PARMS;
typedef enum {
/// TM1
SISO=0,
/// TM2
ALAMOUTI=1,
/// TM3
LARGE_CDD=2,
/// the next 6 entries are for TM5
UNIFORM_PRECODING11=3,
UNIFORM_PRECODING1m1=4,
UNIFORM_PRECODING1j=5,
UNIFORM_PRECODING1mj=6,
PUSCH_PRECODING0=7,
PUSCH_PRECODING1=8,
/// the next 3 entries are for TM4
DUALSTREAM_UNIFORM_PRECODING1=9,
DUALSTREAM_UNIFORM_PRECODINGj=10,
DUALSTREAM_PUSCH_PRECODING=11,
TM7=12,
TM8=13,
TM9_10=14
} MIMO_mode_t;
typedef enum {
/// MRT
MRT=0,
/// ZF
ZF=1,
/// MMSE
MMSE=2
} PRECODE_TYPE_t;
typedef enum {format0,
format1,
format1A,
format1B,
format1C,
format1D,
format1E_2A_M10PRB,
format2,
format2A,
format2B,
format2C,
format2D,
format3,
format3A,
format4,
format5,
format6_0A,
format6_0B,
format6_1A,
format6_1B,
format6_2
} DCI_format_t;
typedef struct {
/// Length of DCI in bits
uint8_t dci_length;
/// Aggregation level
uint8_t L;
/// Position of first CCE of the dci
int firstCCE;
/// flag to indicate that this is a RA response
boolean_t ra_flag;
/// rnti
rnti_t rnti;
/// harq_pid
rnti_t harq_pid;
/// Format
DCI_format_t format;
/// DCI pdu
uint8_t dci_pdu[8];
} DCI_ALLOC_t;
#define MAX_EPDCCH_PRB 8
typedef struct {
/// Length of DCI in bits
uint8_t dci_length;
/// Aggregation level
uint8_t L;
/// Position of first CCE of the dci
int firstCCE;
/// flag to indicate that this is a RA response
boolean_t ra_flag;
/// rnti
rnti_t rnti;
/// Format
DCI_format_t format;
/// epdcch resource assignment (0=localized,1=distributed)
uint8_t epdcch_resource_assignment_flag;
/// epdcch index
uint16_t epdcch_id;
/// epdcch start symbol
uint8_t epdcch_start_symbol;
/// epdcch number of PRBs in set
uint8_t epdcch_num_prb;
/// vector of prb ids for set
uint8_t epdcch_prb_index[MAX_EPDCCH_PRB];
/// LBT parameter for frame configuration
uint8_t dwpts_symbols;
/// LBT parameter for frame configuration
uint8_t initial_lbt_sf;
/// DCI pdu
uint8_t dci_pdu[8];
} eDCI_ALLOC_t;
typedef struct {
/// Length of DCI in bits
uint8_t dci_length;
/// Aggregation level
uint8_t L;
/// Position of first CCE of the dci
int firstCCE;
/// flag to indicate that this is a RA response
boolean_t ra_flag;
/// rnti
rnti_t rnti;
/// Format
DCI_format_t format;
/// harq process index
uint8_t harq_pid;
/// Narrowband index
uint8_t narrowband;
/// number of mdpcch repetitions
uint16_t reps;
/// number of PRB pairs for MPDCCH
uint8_t number_of_prb_pairs;
/// mpdcch resource assignment (combinatorial index r)
uint8_t resource_block_assignment;
/// transmission type (0=localized,1=distributed)
uint8_t transmission_type;
/// mpdcch start symbol
uint8_t start_symbol;
/// CE mode (1=ModeA,2=ModeB)
uint8_t ce_mode;
/// 0-503 n_EPDCCHid_i
uint16_t dmrs_scrambling_init;
/// Absolute subframe of the initial transmission (0-10239)
uint16_t i0;
/// current absolute subframe number
uint16_t absSF;
/// DCI pdu
uint8_t dci_pdu[8];
} mDCI_ALLOC_t;
typedef struct {
/// Preamble index for PRACH (0-63)
uint8_t ra_PreambleIndex;
/// RACH MaskIndex
uint8_t ra_RACH_MaskIndex;
/// Target received power at eNB (-120 ... -82 dBm)
int8_t ra_PREAMBLE_RECEIVED_TARGET_POWER;
/// PRACH index for TDD (0 ... 6) depending on TDD configuration and prachConfigIndex
uint8_t ra_TDD_map_index;
/// Corresponding RA-RNTI for UL-grant
uint16_t ra_RNTI;
/// Pointer to Msg3 payload for UL-grant
uint8_t *Msg3;
} PRACH_RESOURCES_t;
typedef struct {
/// Downlink Power offset field
uint8_t dl_pow_off;
///Subband resource allocation field
uint8_t rballoc_sub[50];
///Total number of PRBs indicator
uint8_t pre_nb_available_rbs;
} MU_MIMO_mode;
typedef enum {
NOT_SYNCHED=0,
PRACH=1,
RA_RESPONSE=2,
PUSCH=3,
RESYNCH=4
} UE_MODE_t;
#define FOREACH_PARALLEL(GEN) \
GEN(PARALLEL_SINGLE_THREAD) \
GEN(PARALLEL_RU_L1_SPLIT) \
GEN(PARALLEL_RU_L1_TRX_SPLIT)
#define GENERATE_ENUM(N) N,
#define GENERATE_ENUMTXT(N) {(char*)#N, N},
typedef enum {
FOREACH_PARALLEL(GENERATE_ENUM)
} PARALLEL_CONF_t;
#define FOREACH_WORKER(GEN) GEN(WORKER_DISABLE) GEN(WORKER_ENABLE)
typedef enum {
FOREACH_WORKER(GENERATE_ENUM)
}WORKER_CONF_t;
typedef struct THREAD_STRUCT_s {
PARALLEL_CONF_t parallel_conf;
WORKER_CONF_t worker_conf;
} THREAD_STRUCT;
extern THREAD_STRUCT thread_struct;
static inline void set_parallel_conf(char *parallel_conf) {
mapping config[]= {
FOREACH_PARALLEL(GENERATE_ENUMTXT)
{NULL,-1}
};
thread_struct.parallel_conf = (PARALLEL_CONF_t)map_str_to_int(config, parallel_conf);
if (thread_struct.parallel_conf == -1 ) {
LOG_E(ENB_APP,"Impossible value: %s\n", parallel_conf);
thread_struct.parallel_conf = PARALLEL_SINGLE_THREAD;
}
}
static inline void set_worker_conf(char *worker_conf) {
mapping config[]={
FOREACH_WORKER(GENERATE_ENUMTXT)
{NULL, -1}
};
thread_struct.worker_conf = (WORKER_CONF_t)map_str_to_int(config, worker_conf);
if (thread_struct.worker_conf == -1 ) {
LOG_E(ENB_APP,"Impossible value: %s\n", worker_conf);
thread_struct.worker_conf = WORKER_DISABLE ;
}
}
static inline PARALLEL_CONF_t get_thread_parallel_conf(void) {
return thread_struct.parallel_conf;
}
static inline WORKER_CONF_t get_thread_worker_conf(void) {
return thread_struct.worker_conf;
}
typedef enum {SF_DL, SF_UL, SF_S} lte_subframe_t;
#define NUMBER_OF_SUBBANDS_MAX 13
#define NUMBER_OF_HARQ_PID_MAX 8
#define MAX_FRAME_NUMBER 0x400
#define NUMBER_OF_RN_MAX 3
typedef enum {no_relay=1,unicast_relay_type1,unicast_relay_type2, multicast_relay} relaying_type_t;
#define MCS_COUNT 28
#define MCS_TABLE_LENGTH_MAX 64
#define NUM_DCI_MAX 32
#define NUMBER_OF_eNB_SECTORS_MAX 3
#define NB_BANDS_MAX 8
#define MAX_BANDS_PER_RRU 4
#ifdef OCP_FRAMEWORK
#include <enums.h>
#else
typedef enum {normal_txrx=0,rx_calib_ue=1,rx_calib_ue_med=2,rx_calib_ue_byp=3,debug_prach=4,no_L2_connect=5,calib_prach_tx=6,rx_dump_frame=7,loop_through_memory=8} runmode_t;
/*! \brief Extension Type */
typedef enum {
CYCLIC_PREFIX,
CYCLIC_SUFFIX,
ZEROS,
NONE
} Extension_t;
enum transmission_access_mode {
NO_ACCESS=0,
POSTPONED_ACCESS,
CANCELED_ACCESS,
UNKNOWN_ACCESS,
SCHEDULED_ACCESS,
CBA_ACCESS};
typedef enum {
eNodeB_3GPP=0, // classical eNodeB function
NGFI_RAU_IF5, // RAU with NGFI IF5
NGFI_RAU_IF4p5, // RAU with NFGI IF4p5
NGFI_RRU_IF5, // NGFI_RRU (NGFI remote radio-unit,IF5)
NGFI_RRU_IF4p5, // NGFI_RRU (NGFI remote radio-unit,IF4p5)
MBP_RRU_IF5 // Mobipass RRU
} node_function_t;
typedef enum {
synch_to_ext_device=0, // synch to RF or Ethernet device
synch_to_other, // synch to another source_(timer, other RU)
synch_to_mobipass_standalone // special case for mobipass in standalone mode
} node_timing_t;
#endif
#include "common/utils/LOG/log_extern.h"
extern pthread_cond_t sync_cond;
extern pthread_mutex_t sync_mutex;
extern int sync_var;
#define MODE_DECODE_NONE 0
#define MODE_DECODE_SSE 1
#define MODE_DECODE_C 2
#define MODE_DECODE_AVX2 3
#define DECODE_INITTD8_SSE_FPTRIDX 0
#define DECODE_INITTD16_SSE_FPTRIDX 1
#define DECODE_INITTD_AVX2_FPTRIDX 2
#define DECODE_TD8_SSE_FPTRIDX 3
#define DECODE_TD16_SSE_FPTRIDX 4
#define DECODE_TD_C_FPTRIDX 5
#define DECODE_TD16_AVX2_FPTRIDX 6
#define DECODE_FREETD8_FPTRIDX 7
#define DECODE_FREETD16_FPTRIDX 8
#define DECODE_FREETD_AVX2_FPTRIDX 9
#define ENCODE_SSE_FPTRIDX 10
#define ENCODE_C_FPTRIDX 11
#define ENCODE_INIT_SSE_FPTRIDX 12
#define DECODE_NUM_FPTR 13
typedef uint8_t(decoder_if_t)(int16_t *y,
int16_t *y2,
uint8_t *decoded_bytes,
uint8_t *decoded_bytes2,
uint16_t n,
uint8_t max_iterations,
uint8_t crc_type,
uint8_t F,
time_stats_t *init_stats,
time_stats_t *alpha_stats,
time_stats_t *beta_stats,
time_stats_t *gamma_stats,
time_stats_t *ext_stats,
time_stats_t *intl1_stats,
time_stats_t *intl2_stats);
typedef uint8_t(encoder_if_t)(uint8_t *input,
uint16_t input_length_bytes,
uint8_t *output,
uint8_t F);
static inline void wait_sync(char *thread_name) {
int rc;
printf( "waiting for sync (%s,%d/%p,%p,%p)\n",thread_name,sync_var,&sync_var,&sync_cond,&sync_mutex);
AssertFatal((rc = pthread_mutex_lock( &sync_mutex ))==0,"sync mutex lock error");
while (sync_var<0)
pthread_cond_wait( &sync_cond, &sync_mutex );
AssertFatal((rc = pthread_mutex_unlock( &sync_mutex ))==0,"sync mutex unlock error");
printf( "got sync (%s)\n", thread_name);
/*
* Raphael Defosseux: added for CI to get faster the got sync message.
*/
fflush(stdout);
fflush(stderr);
}
static inline int wakeup_thread(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name, int sleeptime,int sleep_cnt_max) {
int rc;
int sleep_cnt=0;
AssertFatal((rc = pthread_mutex_lock(mutex))==0,"wakeup_thread(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
while (*instance_cnt == 0) {
AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
sleep_cnt++;
if (sleep_cnt>sleep_cnt_max) return(-1);
usleep(sleeptime);
AssertFatal((rc = pthread_mutex_lock(mutex))==0,"wakeup_thread(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
}
*instance_cnt = *instance_cnt + 1;
AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
// the thread can now be woken up
if (pthread_cond_signal(cond) != 0) {
LOG_E( PHY, "ERROR pthread_cond_signal\n");
exit_fun( "ERROR pthread_cond_signal" );
return(-1);
}
AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
return(0);
}
static inline int timedwait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name,uint32_t time_ns) {
int rc;
int waitret=0;
struct timespec now,abstime;
AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] timedwait_on_condition(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
clock_gettime(CLOCK_REALTIME,&now);
while (*instance_cnt < 0) {
// most of the time the thread is waiting here
// proc->instance_cnt_rxtx is -1
abstime.tv_sec=now.tv_sec;
abstime.tv_nsec = now.tv_nsec + time_ns;
if (abstime.tv_nsec >= 1000*1000*1000)
{
abstime.tv_nsec -= 1000*1000*1000;
abstime.tv_sec += 1;
}
if ((waitret = pthread_cond_timedwait(cond,mutex,&abstime)) == 0) break; // this unlocks mutex_rxtx while waiting and then locks it again
}
AssertFatal((rc = pthread_mutex_unlock(mutex)) == 0,"[SCHED][eNB] timedwait_on_condition(): error unlocking mutex return %d for %s\n", rc, name);
return(0);
}
static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
int rc;
AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] wait_on_condition(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
while (*instance_cnt < 0) {
// most of the time the thread is waiting here
// proc->instance_cnt_rxtx is -1
pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again
}
AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] wait_on_condition(): error unlocking mutex return %d for %s\n", rc, name);
return(0);
}
static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
int rc;
AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] wait_on_busy_condition(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
while (*instance_cnt == 0) {
// most of the time the thread will skip this
// waits only if proc->instance_cnt_rxtx is 0
pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again
}
AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] wait_on_busy_condition(): error unlocking mutex return %d for %s\n", rc, name);
return(0);
}
static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) {
int rc;
AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] release_thread(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
*instance_cnt=*instance_cnt-1;
AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] release_thread(): error unlocking mutex return %d for %s\n", rc, name);
return(0);
}
#endif // __PHY_DEFS__H__
......@@ -629,6 +629,12 @@ typedef struct {
*/
uint8_t subcarrier_spacing;
uint8_t nb_antennas_tx_NB_IoT; // to replace with NB_IoT_frame_params
uint8_t flag_free_sf; // flag to indicate for NPDSCH and NPDCCH process if the current SF already used
} NB_IoT_DL_FRAME_PARMS;
typedef struct {
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file phy_procedures_lte_eNB_NB_IoT.c
* \brief Implementation of eNB procedures from 36.213 NB-IoT R13 specifications
* \author M. KANJ, Nick Ho
* \date 2019
* \version 1.0
* \company B-COM, NTUST
* \email:
* \note
* \warning
*/
#include "PHY/defs_eNB.h"
#include "PHY/defs_L1_NB_IoT.h"
#include "PHY/extern.h"
#include "PHY/LTE_ESTIMATION/defs_NB_IoT.h"
#include "PHY/NBIoT_TRANSPORT/defs_NB_IoT.h"
#include "PHY/NBIoT_TRANSPORT/proto_NB_IoT.h"
//#include "PHY/extern_NB_IoT.h" //where we get the global Sched_Rsp_t structure filled
//#include "SCHED/defs.h"
#include "SCHED_NBIOT/sched_common_extern_NB_IoT.h"
#include "SIMULATION/TOOLS/sim.h" // purpose: included for taus() function
// for NB-IoT
#include "SCHED_NBIOT/defs_NB_IoT.h"
#include "openair2/RRC/NBIOT/proto_NB_IoT.h"
#include "openair2/RRC/NBIOT/extern_NB_IoT.h"
#include "RRC/LITE/MESSAGES/asn1_msg_NB_IoT.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "T.h"
#include "assertions.h"
#include "msc.h"
#include <time.h>
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
int npdsch_rep_to_array[3] = {4,8,16}; //TS 36.213 Table 16.4.1.3-3
int sib1_startFrame_to_array[4] = {0,16,32,48};//TS 36.213 Table 16.4.1.3-4
//New----------------------------------------------------
//return -1 whenever no SIB1-NB transmission occur.
//return sib1_startFrame when transmission occur in the current frame
uint32_t is_SIB1_NB_IoT(const frame_t frameP,
long schedulingInfoSIB1, //from the mib
int physCellId, //by configuration
NB_IoT_eNB_NDLSCH_t *ndlsch_SIB1
)
{
uint8_t nb_rep=0; // number of sib1-nb repetitions within the 256 radio frames
uint32_t sib1_startFrame;
uint32_t sib1_period_NB_IoT = 256;//from specs TS 36.331 (rf)
uint8_t index;
int offset;
int period_nb; // the number of the actual period over the 1024 frames
if(schedulingInfoSIB1 > 11 || schedulingInfoSIB1 < 0){
LOG_E(RRC, "is_SIB1_NB_IoT: schedulingInfoSIB1 value not allowed");
return 0;
}
//SIB1-NB period number
period_nb = (int) frameP/sib1_period_NB_IoT;
//number of repetitions
nb_rep = npdsch_rep_to_array[schedulingInfoSIB1%3];
//based on number of rep. and the physical cell id we derive the starting radio frame (TS 36.213 Table 16.4.1.3-3/4)
switch(nb_rep)
{
case 4:
//physCellId%4 possible value are 0,1,2,3
sib1_startFrame = sib1_startFrame_to_array[physCellId%4];
break;
case 8:
//physCellId%2possible value are 0,1
sib1_startFrame = sib1_startFrame_to_array[physCellId%2];
break;
case 16:
//physCellId%2 possible value are 0,1
if(physCellId%2 == 0)
sib1_startFrame = 0;
else
sib1_startFrame = 1; // the only case in which the starting frame is odd
break;
default:
LOG_E(RRC, "Number of repetitions %d not allowed", nb_rep);
return -1;
}
//check the actual frame w.r.t SIB1-NB starting frame
if(frameP < sib1_startFrame + period_nb*256){
LOG_T(RRC, "the actual frame %d is before the SIB1-NB starting frame %d of the period--> bcch_sdu_legnth = 0", frameP, sib1_startFrame + period_nb*256);
return -1;
}
//calculate offset between SIB1-NB repetitions (repetitions are equally spaced)
offset = (sib1_period_NB_IoT-(16*nb_rep))/nb_rep;
//loop over the SIB1-NB period
for( int i = 0; i < nb_rep; i++)
{
//find the correct sib1-nb repetition interval in which the actual frame is
//this is the start frame of a repetition
index = sib1_startFrame+ i*(16+offset) + period_nb*256;
//the actual frame is in a gap between two consecutive repetitions
if(frameP < index)
{
ndlsch_SIB1->sib1_rep_start = 0;
ndlsch_SIB1->relative_sib1_frame = 0;
return -1;
}
//this is needed for ndlsch_procedure
else if(frameP == index)
{
//the actual frame is the start of a new repetition (SIB1-NB should be retransmitted)
ndlsch_SIB1->sib1_rep_start = 1;
ndlsch_SIB1->relative_sib1_frame = 1;
return sib1_startFrame;
}
else
ndlsch_SIB1->sib1_rep_start = 0;
//check in the current SIB1_NB repetition
if(frameP>= index && frameP <= (index+15))
{
//find if the actual frame is one of the "every other frame in 16 continuous frame" in which SIB1-NB is transmitted
for(int y = 0; y < 16; y += 2) //every other frame (increment by 2)
{
if(frameP == index + y)
{
//this flag tell which is the number of the current frame w.r.t the 8th (over the continuous 16) in a repetition
ndlsch_SIB1->relative_sib1_frame = y/2 + 1; //1st, 2nd, 3rd,...
return sib1_startFrame;
}
}
//if we are here means that the frame was inside the repetition interval but not considered for SIB1-NB transmission
ndlsch_SIB1->relative_sib1_frame = 0;
return -1;
}
}
return -1;
}
/* For NB-IoT, we put NPBCH in later part, since it would be scheduled by MAC scheduler
* It generates NRS/NPSS/NSSS
* Actually phy_procedures_eNB_TX here
*/
void common_signal_procedures_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_IoT_t *proc)
{
//LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms_NB_IoT;
NB_IoT_DL_FRAME_PARMS *fp = &eNB->frame_parms_NB_IoT;
NB_IoT_eNB_NPBCH_t *broadcast_str = &eNB->npbch;
//NB_IoT_eNB_NDLSCH_t *sib1 = &eNB->ndlsch_SIB;
//NB_IoT_eNB_NDLSCH_t *ndlsch = &eNB->ndlsch_SIB1;
NB_IoT_eNB_NDLSCH_t *sib1 = eNB->ndlsch_SIB1;
NB_IoT_eNB_NDLSCH_t *sib23 = eNB->ndlsch_SIB23;
uint8_t *npbch_pdu = broadcast_str->pdu;
int **txdataF = eNB->common_vars.txdataF[0];
uint32_t subframe = proc->subframe_tx;
uint32_t frame = proc->frame_tx;
//uint16_t Ntti = 10; //ntti = 10
int RB_IoT_ID=22; // XXX should be initialized (RB reserved for NB-IoT, PRB index)
int With_NSSS=0; // With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
uint8_t release_v13_5_0 = 0;
uint32_t hyper_frame=proc->HFN;
fp->flag_free_sf =0;
////////////////////////////////////////////////////////////////////////////////////
/*
rrc_eNB_carrier_data_NB_IoT_t *carrier = &eNB_rrc_inst_NB_IoT->carrier[0];
if(frame%64==0 && subframe ==0)
{//printf("dooooo MIB");
do_MIB_NB_IoT(carrier,1,frame,hyper_frame);
}
if(frame%64==1 && subframe ==0)
{
do_SIB1_NB_IoT_x(0,0,carrier,208,92,1,3584,28,2,hyper_frame);
}
*/
/////////////////////////////////////////////////////////////////////////////////
//uint8_t *control_region_size = get_NB_IoT_SIB1_eutracontrolregionsize();
//int G=0;
//NSSS only happened in the even frame
int nsss_state = 0;
if(frame%2==0)
{
With_NSSS = 1;
} else {
With_NSSS = 0;
}
/////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// NPSS && NSSS //////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
if(subframe == 5)
{
generate_npss_NB_IoT(txdataF,
AMP,
fp,
3,
10,
RB_IoT_ID);
}
else if((subframe == 9) && (With_NSSS == 1))
{
generate_sss_NB_IoT(txdataF,
AMP,
fp,
3,
18,
frame,
RB_IoT_ID);
nsss_state = 1;
}
/////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// MIB //////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
if(subframe == 0)
{
generate_npbch(broadcast_str,
txdataF,
AMP,
fp,
npbch_pdu,
frame%64,
RB_IoT_ID,
release_v13_5_0);
}
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////// SIB1 ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
int sib1_state = 0;
if(subframe == 4)
{
sib1_state = generate_SIB1(sib1,
txdataF,
AMP,
fp,
frame,
subframe,
RB_IoT_ID,
0,
release_v13_5_0);
}
/////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// SIB23 ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
if( (subframe != 0) && (subframe != 5) && (sib1_state != 1) && (nsss_state != 1))
{
generate_SIB23(sib23,
txdataF,
AMP,
fp,
frame,
subframe,
RB_IoT_ID,
release_v13_5_0);
}
if( (subframe != 0) && (subframe != 5) && (nsss_state != 1) && (fp->flag_free_sf == 0) )
{
NB_IoT_eNB_NPDCCH_t *npdcch_str = eNB->npdcch_DCI;
NB_IoT_eNB_NDLSCH_t *RAR = eNB->ndlsch_RAR;
NB_IoT_eNB_NDLSCH_t *data = eNB->ndlsch[0];
/////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// NPDCCH ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
generate_NPDCCH_NB_IoT(npdcch_str,
txdataF,
AMP,
fp,
frame,
subframe,
RB_IoT_ID);
/////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// NPDSCH ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
if(eNB->ndlsch_RAR != NULL && RAR->active_msg2 == 1)
{
generate_NDLSCH_NB_IoT(eNB,
RAR,
txdataF,
AMP,
fp,
frame,
subframe,
RB_IoT_ID,
release_v13_5_0);
} else if(eNB->ndlsch[0] != NULL) {
generate_NDLSCH_NB_IoT(eNB,
data,
txdataF,
AMP,
fp,
frame,
subframe,
RB_IoT_ID,
release_v13_5_0);
}
///////////////////////////////////////////////////////////////////////////////////
}
generate_pilots_NB_IoT(eNB,
txdataF,
AMP,
subframe,
RB_IoT_ID,
With_NSSS);
if(proc->frame_rx==1023 && proc->subframe_rx==9)
{
//printf("%d",hyper_frame);
if(proc->HFN==1023)
{
proc->HFN=0;
}else{
proc->HFN++;
//printf("Update HFN:%d when frame:%d subframe:%d\n",proc->HFN,proc->frame_rx,proc->subframe_rx);
}
}
}
void npusch_procedures(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_IoT_t *proc)
{
uint32_t i;
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
NB_IoT_eNB_NULSCH_t *nulsch;
NB_IoT_UL_eNB_HARQ_t *nulsch_harq;
nulsch = eNB->ulsch_NB_IoT[0];
nulsch_harq = nulsch->harq_process;
const int rx_subframe = proc->subframe_rx;
const int rx_frame = proc->frame_rx;
int RB_IoT_ID = 22;
//for (i=0; i<NUMBER_OF_UE_MAX; i++)
for (i=0; i<1; i++)
{
//ulsch_NB_IoT = eNB->ulsch_NB_IoT[i];
//ulsch_harq = ulsch_NB_IoT->harq_process;
// if eNB is ready to receive UL data
// define a flag to trigger on or off the decoding process
rx_ulsch_Gen_NB_IoT(eNB,
proc,
0, // this is the effective sector id
0,
RB_IoT_ID, // 22 , to be included in // to be replaced by NB_IoT_start ??
rx_subframe, // first received subframe
rx_frame); // first received frame
} // for UE loop
}
void phy_procedures_eNB_uespec_RX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_IoT_t *proc) //UL_IND_NB_IoT_t *UL_INFO)
{
//RX processing for ue-specific resources (i
//NB_IoT_DL_FRAME_PARMS *fp=&eNB->frame_parms_NB_IoT;
const int subframe = proc->subframe_rx;
const int frame = proc->frame_rx;
npusch_procedures(eNB,proc);
//pthread_mutex_lock(&eNB->UL_INFO_mutex);
// Fix me here, these should be locked
//eNB->UL_INFO.RX_NPUSCH.number_of_pdus = 0;
// eNB->UL_INFO.crc_ind.number_of_crcs = 0;
// pthread_mutex_unlock(&eNB->UL_INFO_mutex);
// if (nfapi_mode == 0 || nfapi_mode == 1) { // If PNF or monolithic
//}
}
// the function called by l1 IF-Module
void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_IOT_t * proc,nfapi_dl_config_request_pdu_t *dl_config_pdu)
{
int UE_id = -1;
NB_IoT_DL_FRAME_PARMS *fp = &eNB->frame_parms_NB_IoT;
int frame = proc->frame_tx;
int subframe = proc->subframe_tx;
DCI_CONTENT *DCI_Content;
DCI_format_NB_IoT_t DCI_format;
NB_IoT_eNB_NDLSCH_t *ndlsch;
NB_IoT_eNB_NPDCCH_t *npdcch;
eNB->DCI_pdu = (DCI_PDU_NB_IoT*)malloc(sizeof(DCI_PDU_NB_IoT));
DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
// check DCI format is N1 (format 0)
if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 0)
{
//check DCI format N1 is for RAR rnti_type in FAPI specs table 4-45
if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type == 1)
{
//mapping the fapi parameters to the oai parameters
DCI_format = DCIFormatN1_RAR;
//DCI format N1 to RAR
DCI_Content->DCIN1_RAR.type = 1;
DCI_Content->DCIN1_RAR.orderIndicator = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.npdcch_order_indication;
DCI_Content->DCIN1_RAR.Scheddly = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.scheduling_delay;
DCI_Content->DCIN1_RAR.ResAssign = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment;
DCI_Content->DCIN1_RAR.mcs = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.mcs;
DCI_Content->DCIN1_RAR.RepNum = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
DCI_Content->DCIN1_RAR.ndi = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.new_data_indicator;
DCI_Content->DCIN1_RAR.HARQackRes = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource;
DCI_Content->DCIN1_RAR.DCIRep = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number;
//TODO calculate the number of common repetitions
//fp->nprach_config_common.number_repetition_RA = see TS 36.213 Table 16.1-3
// fill the dlsch_ra_NB structure for RAR, and packed the DCI PDU
ndlsch = eNB->ndlsch_RAR;
ndlsch->ndlsch_type = RAR;
ndlsch->rnti = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti;
npdcch = eNB->npdcch_DCI;
LOG_D(PHY,"Generating pdcch params for DCIN1 RAR and packing DCI\n");
//LOG_I(PHY,"Rep of DCI is : %d\n",DCI_Content->DCIN1_RAR.RepNum);
//LOG_I(PHY,"Generating dlsch params for RA_RNTI and packing DCI\n");
generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
frame,
subframe,
DCI_Content,
dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
DCI_format,
npdcch,
fp,
dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol,
dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.ncce_index);
//printf("PHY_vars_eNB_g[0][0]->ndlsch_RAR->rnti = %d\n",PHY_vars_eNB_g[0][0]->ndlsch_RAR->rnti);
//eNB->dlsch_ra_NB->nCCE[subframe] = eNB->DCI_pdu->dci_alloc.firstCCE;
}
else
{ //managing data
LOG_I(PHY,"Handling the DCI for ue-spec data or MSG4!\n");
// Temp: Add UE id when Msg4 trigger
eNB->ndlsch[0]= (NB_IoT_eNB_NDLSCH_t*) malloc(sizeof(NB_IoT_eNB_NDLSCH_t));
eNB->ndlsch[0]->harq_process = (NB_IoT_DL_eNB_HARQ_t*)malloc(sizeof(NB_IoT_DL_eNB_HARQ_t));
eNB->ndlsch[0]->rnti=dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti;
//TODO target/SIMU/USER?init_lte/init_lte_eNB we should allocate the ndlsch structures
UE_id = find_ue_NB_IoT(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti, eNB);
AssertFatal(UE_id != -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n");
//mapping the fapi parameters to the oai parameters
DCI_format = DCIFormatN1;
//DCI format N1 to DLSCH
DCI_Content->DCIN1.type = 1;
DCI_Content->DCIN1.orderIndicator = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.npdcch_order_indication;
DCI_Content->DCIN1.Scheddly = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.scheduling_delay;
DCI_Content->DCIN1.ResAssign = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment;
DCI_Content->DCIN1.mcs = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.mcs;
DCI_Content->DCIN1.RepNum = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
DCI_Content->DCIN1.ndi = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.new_data_indicator;
DCI_Content->DCIN1.HARQackRes = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource;
DCI_Content->DCIN1.DCIRep = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number;
npdcch = eNB->npdcch_DCI;
//eNB->npdcch[(uint8_t)UE_id] = (NB_IoT_eNB_NPDCCH_t *) malloc(sizeof(NB_IoT_eNB_NPDCCH_t));
//set the NPDCCH UE-specific structure (calculate R)
//npdcch=eNB->npdcch[(uint8_t)UE_id];
//AssertFatal(npdcch != NULL, "NPDCCH structure for UE specific is not exist\n");
//npdcch->repetition_idx[(uint8_t)UE_id] = 0; //this is used for the encoding mechanism to understand that is the first transmission
//if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level) //whenever aggregation level is =1 we have only 1 repetition for USS
// npdcch->repetition_number[(uint8_t)UE_id] = 1;
//else
//{
//see TS 36.213 Table 16.1-1
//}
//fill the ndlsch structure for UE and packed the DCI PD
ndlsch = eNB->ndlsch[(uint8_t)UE_id]; //in the old implementation they also consider UE_id = 1;
ndlsch->ndlsch_type = UE_Data;
//parameters we don't consider pdsch config dedicated since not calling the phy config dedicated step2
LOG_I(PHY,"Generating dlsch params for DCIN1 data and packing DCI, res: %d\n",DCI_Content->DCIN1.ResAssign);
generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
frame,
subframe,
DCI_Content,
dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
DCI_format,
npdcch,
fp,
dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol,
dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.ncce_index);
//eNB->ndlsch[(uint8_t)UE_id]->nCCE[subframe] = eNB->DCI_pdu->dci_alloc[i].firstCCE;
}
}
else if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 1)
{
DCI_format = DCIFormatN2;
LOG_D(PHY,"Paging procedure not implemented\n");
}
else
LOG_E(PHY,"unknown DCI format for NB-IoT DL\n");
}
void generate_eNB_ulsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_IoT_t *proc,nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu) {
//int UE_id = -1;
//int harq_pid = 0;
int frame = proc->frame_tx;
int subframe = proc->subframe_tx;
DCI_CONTENT *DCI_Content;
DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
NB_IoT_eNB_NPDCCH_t *npdcch;
//mapping the fapi parameters to the OAI parameters
DCI_Content->DCIN0.type = 0;
DCI_Content->DCIN0.scind = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.subcarrier_indication;
DCI_Content->DCIN0.ResAssign = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.resource_assignment;
DCI_Content->DCIN0.mcs = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.mcs;
DCI_Content->DCIN0.ndi = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.new_data_indicator;
DCI_Content->DCIN0.Scheddly = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.scheduling_delay;
DCI_Content->DCIN0.RepNum = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.repetition_number;
DCI_Content->DCIN0.rv = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.redudancy_version;
DCI_Content->DCIN0.DCIRep = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.dci_subframe_repetition_number;
npdcch = eNB->npdcch_DCI;
/*Log for generate ULSCH DCI*/
LOG_I(PHY,"packing DCI N0\n");
LOG_I(PHY,"Dump DCI N0 : scind: %d, ResAssign: %d, mcs: %d, ndi: %d, Scheddly: %d, RepNum: %d, rv: %d, DCIRep: %d\n",DCI_Content->DCIN0.scind,DCI_Content->DCIN0.ResAssign,DCI_Content->DCIN0.mcs,DCI_Content->DCIN0.ndi,DCI_Content->DCIN0.Scheddly,DCI_Content->DCIN0.RepNum,DCI_Content->DCIN0.rv,DCI_Content->DCIN0.DCIRep);
generate_eNB_ulsch_params_from_dci_NB_IoT(eNB,
frame,
subframe,
DCI_Content,
hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti,
npdcch,
hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.aggregation_level,
hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.start_symbol,
hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.ncce_index
);
}
/*
* for NB-IoT ndlsch procedure
* this function is called by the PHy procedure TX in 3 possible occasion:
* 1) we manage BCCH pdu (SI)
* 2) we manage RA dlsch pdu
* 3) UE-specific dlsch pdu
* ** we need to know if exist and which value has the eutracontrolRegionSize (TS 36.213 ch 16.4.1.4) whenever we are in In-band mode
* ** CQI and PMI are not present in NB-IoT
* ** redundancy version exist only in UL for NB-IoT and not in DL
*/
void npdsch_procedures(PHY_VARS_eNB_NB_IoT *eNB,
eNB_rxtx_proc_NB_IoT_t *proc, //Context data structure for RX/TX portion of subframe processing
NB_IoT_eNB_NDLSCH_t *ndlsch,
//int num_pdcch_symbols, //(BCOM says are not needed
uint8_t *pdu
)
{
int frame = proc->frame_tx;
int subframe = proc->subframe_tx;
NB_IoT_DL_eNB_HARQ_t *ndlsch_harq = ndlsch->harq_process;
int input_buffer_length = ndlsch_harq->TBS/8; // get in byte //the TBS is set in generate_dlsch_param
NB_IoT_DL_FRAME_PARMS *fp = &eNB->frame_parms_NB_IoT;
int G;
uint8_t *DLSCH_pdu = NULL;
uint8_t DLSCH_pdu_tmp[input_buffer_length+4]; //[768*8];
//uint8_t DLSCH_pdu_rar[256];
int i;
LOG_D(PHY,
"[eNB %"PRIu8"][PDSCH rnti%"PRIx16"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", mcs %"PRIu8"(round %"PRIu8")\n",
eNB->Mod_id,
ndlsch->rnti,
frame, subframe, input_buffer_length,
ndlsch_harq->mcs,
ndlsch_harq->round
);
if(ndlsch_harq->round == 0) { //first transmission so we encode... because we generate the sequence
if (eNB->mac_enabled == 1) { // set in lte-softmodem/main line 1646
DLSCH_pdu = pdu;
/*
* we don't need to manage the RAR here since should be managed in the MAC layer for two reasons:
* 1)we should receive directly the pdu containing the RAR from the MAC in the schedule_response
* 2)all the parameters for getting the MSG3 should be given by the UL_CONFIG.request (all inside the next schedule_response function)
*
*/
//fill_rar shouduld be in the MAC
//cancel ra procedure should be in the mac
//scheduling request not implemented in NB-IoT
//nulsch_param configuration for MSG3 should be considered in handling UL_Config.request
//(in particular the nulsch structure for RAR is distinguished based on the harq_process->rar_alloc and the particular subframe in which we should have Msg3)
}
else { //XXX we should change taus function???
DLSCH_pdu = DLSCH_pdu_tmp;
for (i=0; i<input_buffer_length; i++)
DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
}
}
else {
//We are doing a retransmission (harq round > 0
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
#endif
#endif
}
if (eNB->abstraction_flag==0) { // used for simulation of the PHY??
//we can distinguish among the different kind of NDLSCH structure (example)
switch(ndlsch->ndlsch_type)
{
case SIB1:
break;
case SI_Message:
break;
case RAR: //maybe not needed
break;
case UE_Data: //maybe not needed
break;
}
/*
* in any case inside the encoding procedure is re-checked if this is round 0 or no
* in the case of harq_process round = 0 --> generate the sequence and put it into the parameter *c[r]
* otherwise do nothing(only rate maching)
*/
/*
* REASONING:
* Encoding procedure will generate a Table with encoded data ( in ndlsch structure)
* The table will go in input to the scrambling
* --we should take care if there are repetitions of data or not because scrambling should be called at the first frame and subframe in which each repetition
* begin (see params Nf, Ns)
*/
// 36-212
//encoding---------------------------
/*
*
* REASONING:
* Encoding procedure will generate a Table with encoded data ( in ndlsch structure)
* The table will go in input to the scrambling
* --we should take care if there are repetitions of data or not because scrambling should be called at the first frame and subframe in which each repetition
* begin (see params Nf, Ns)
*
* we should have as an iput parameter also G for the encoding based on the switch/case over eutracontrolRegionSize (if exist) and operationModeInfo if defined
* NB: switch case of G is the same for npdsch and npdcch
*
* npdsch_start symbol index
* -refers to TS 36.213 ch 16.4.1.4:
* -if subframe k is a subframe for receiving the SIB1-NB
* -- if operationModeInfo set to 00 or 01 (in band) --> npdsch_start_sysmbol = 3
* -- otherwise --> npdsch_start_symbol = 0
* -if the k subframe is not for SIB1-NB
* --npdsch_start_symbol = eutracontrolregionsize (defined for in-band operating mode (mode 0,1 for FAPI specs) and take values 1,2,3 [units in number of OFDM symbol])
* - otherwise --> npdsch_start_symbol = 0
* (is the starting OFDM for the NPDSCH transmission in the first slot in a subframe k)
* FAPI style:
* npdsch_start symbol is stored in the ndlsch structure from the reception of the NPDLSCH PDU in the DL_CONFIG.request (so should be set by the MAC and put inside the schedule response)
* Nsf needed as an input (number of subframe)-->inside harq_process of ndlsch
*/
switch(ndlsch->npdsch_start_symbol)
{
case 0:
G = 304;
break;
case 1:
G = 240;
break;
case 2:
G = 224;
break;
case 3:
G =200;
break;
default:
LOG_E (PHY,"npdsch_start_index has unwanted value\n");
break;
}
//start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
LOG_I(PHY, "NB-IoT Encoding step\n");
// eNB->te(eNB,
// DLSCH_pdu,
// num_pdcch_symbols,
// dlsch,
// frame,subframe,
// &eNB->dlsch_rate_matching_stats,
// &eNB->dlsch_turbo_encoding_stats,
// &eNB->dlsch_interleaving_stats);
// stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
// 36-211
//scrambling-------------------------------------------
// start_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
LOG_I(PHY, "NB-IoT Scrambling step\n");
/*
* SOME RELEVANT FACTS:
*
*
*/
// dlsch_scrambling(fp,
// 0,
// dlsch,
// get_G(fp,
// dlsch_harq->nb_rb,
// dlsch_harq->rb_alloc,
// get_Qm(dlsch_harq->mcs),
// dlsch_harq->Nl,
// num_pdcch_symbols,
// frame,subframe,
// 0),
// 0,
// subframe<<1);
//stop_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
//modulation-------------------------------------------
//start_meas_NB_IoT(&eNB->dlsch_modulation_stats);
LOG_I(PHY, "NB-IoT Modulation step\n");
// dlsch_modulation(eNB,
// eNB->common_vars.txdataF[0],
// AMP,
// subframe,
// num_pdcch_symbols,
// dlsch,
// dlsch1);
//stop_meas_NB_IoT(&eNB->dlsch_modulation_stats);
}
#ifdef PHY_ABSTRACTION
else {
//start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
//dlsch_encoding_emul(eNB,
//DLSCH_pdu,
//dlsch);
// stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
}
#endif
ndlsch->active = 0;
}
extern int oai_exit;
/*
* ASSUMPTION
*
* The MAC schedule the schedule_response in a SUBFRAME BASE (at least because otherwise we have problem with our assumptions on SI transmission)
*
*Since in FAPI specs seems to not manage the information for the sceduling of system information:
* Assume that the MAC layer manage the scheduling for the System information (SI messages) transmission while MIB and SIB1 are done directly at PHY layer
* This means that the MAC scheduler will send to the PHY the NDLSCH PDU and MIB PDU (DL_CONFIG.request)each time they should be transmitted. In particular:
***MIB-NB
*schedule_response containing a n-BCH PDU is transmitted only at the beginning of the MIB period, then repetitions are made directly by the PHY layer (see FAPI specs pag 94 N-BCH 3.2.4.2)
*if no new N-BCH PDU is trasmitted at SFN mod 64=0 then stop MIB transmission
***SIB1-NB
*schedule response containing a NDLSCH pdu (with appropiate configuration) will be transmitted only at the beginning of each SIB1-NB period (256 rf)
*then repetitions are managed directly by the PHY layer
*if no new NDLSCH pdu (configured for SIB1-NB) at SFN mod 256 = 0 is transmitted. stop SIB1-NB transmission
****SI Messages
* -schedule_response is transmitted by the MAC in every subframe needed for the SI transmission (NDLSCH should have a proper configuration)
* -if the schedule_response carry any SDU for SI-Message (SDU!= NULL)--> put the SDU in the PHY buffer to be encoded ecc... and start the transmission
* -if the schedule_response not carry any SDU (SDU == NULL) but NDLSCH is properly set for SI, then PHY continue transmit the remaining part of the previous SDU
* (this because the PHY layer have no logic of repetition_pattern, si_window ecc.. so should be continuously instructed the PHY when to transmit.
*
* Furthermore, SI messages are transmitted in more that 1 subframe (2 or 8) and therefore MAC layer need to count how many subframes are available in the current frame for transmit it
* and take in consideration that other frames are needed before starting the transmission of a new one)
*
*
*We assume that whenever the NDLSCH pdu is a BCCH type, we consider as if it's a SIB1 while in other case can be data or SI-message depending on the RNTI
*
* **relevant aspects for the System information Transmission (Table 4-47 NDLSCH FAPi specs)
* 1)RNTI type = 0 (contains a BCCH)
* 2)Repetition number == scheduling info SIB1 mapped into 4-8-16
* 3)RNTI (0xFFFF = SI-RNTI)
* (see schedule_response implementation)
*
*/
/*
* This function is triggered by the schedule_response
* (the frequency at which is transmitted to the PHY depends on the MAC scheduler implementation)
* (in OAI in principle is every subframe)
*/
void phy_procedures_eNB_TX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
eNB_rxtx_proc_NB_IoT_t *proc,
int do_meas)
{
int frame = proc->frame_tx;
int subframe = proc->subframe_tx;
uint32_t aa;
DCI_PDU_NB_IoT *dci_pdu = eNB->DCI_pdu;
NB_IoT_DL_FRAME_PARMS *fp = &eNB->frame_parms_NB_IoT;
int8_t UE_id = 0;
int **txdataF = eNB->common_vars.txdataF[0];
uint32_t sib1_startFrame = -1;
//NB_IoT_eNB_NPDCCH_t*npdcch;
if(do_meas == 1)
//start_meas_NB_IoT(&eNB->phy_proc_tx);
/*the original scheduler "eNB_dlsch_ulsch_scheduler" now is no more done here but is triggered directly from UL_Indication (IF-Module Function)*/
// clear the transmit data array for the current subframe
for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++)
{
memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
}
//generate NPSS/NSSS
// common_signal_procedures_NB_IoT(eNB,proc); // to uncomment after NB-IoT testing
//Generate MIB
if(subframe ==0 && (eNB->npbch != NULL))
{
if(eNB->npbch->pdu != NULL)
{
//BCOM function
/*
* -the function get the MIB pdu and schedule the transmission over the 64 radio frame
* -need to check the subframe #0 (since encoding functions only check the frame)
* this functions should be called every frame (the function will transmit the remaining part of MIB)
* ( XXX Should check when the schedule_responce is transmitted by MAC scheduler)
* RB-ID only for the case of in-band operation but should be always considered
* (in stand alone i can put whatever the number)in other case consider the PRB index in the Table R&Shwartz pag 9
*
*/
/*
generate_npbch(eNB->npbch,
txdataF,
AMP,
fp,
eNB->npbch->pdu,
frame%64,
fp->NB_IoT_RB_ID);*/
}
//In the last frame in which the MIB-NB should be transmitted after we point to NULL since maybe we stop MIB trasnmission
//this should be in line with FAPI specs pag 94 (BCH procedure in Downlink 3.2.4.2 for NB-IoT)
if(frame%64 == 63)
{
eNB->npbch->pdu = NULL;
}
}
//Check for SIB1-NB transmission
/*
*
* the function should be called for each frame
* Parameters needed:
* -sib1-NB pdu if new one (should be given by the MAC at the start of each SIB1-NB period)
* -when start a new SIB1-NB repetition (sib1_rep_start)
* -the frame number relative to the 16 continuous frame within a repetition (relative_sib1_frame) 1st, 2nd ...
*
* we check that the transmission should occurr in subframe #4
*
* consider that if at the start of the new SIB1-NB period the MAC will not send an NPDSCH for the SIB1-NB transmission then SIB1-NB will be not transmitted (pdu = NULL)
*
*/
if(subframe == 4 && eNB->ndlsch_SIB1 != NULL && eNB->ndlsch_SIB1->harq_process->status == ACTIVE_NB_IoT)
{
//check if current frame is for SIB1-NB transmission (if yes get the starting frame of SIB1-NB) and set the flag for the encoding
sib1_startFrame = is_SIB1_NB_IoT(frame,
(long)eNB->ndlsch_SIB1->harq_process->repetition_number,
fp->Nid_cell,
eNB->ndlsch_SIB1); //set the flags
if(sib1_startFrame != -1 && eNB->ndlsch_SIB1->harq_process->pdu != NULL)
{
npdsch_procedures(eNB,
proc,
eNB->ndlsch_SIB1, //since we have no DCI for system information, this is filled directly when we receive the NDLSCH pdu from DL_CONFIG.request message
eNB->ndlsch_SIB1->harq_process->pdu);
}
//at the end of the period we put the PDU to NULL since we have to wait for the new one from the MAC for starting the next SIB1-NB transmission
if((frame-sib1_startFrame)%256 == 255)
{
//whenever we will not receive a new sdu from MAC at the start of the next SIB1-NB period we prevent future SIB1-NB transmission (may just only of the two condition is necessary)
eNB->ndlsch_SIB1->harq_process->status = DISABLED;
eNB->ndlsch_SIB1->harq_process->pdu = NULL;
}
}
//Check for SI transmission
/*
*Parameters needed:
* -total number of subframes for the transmission (2-8) (inside the NDLSCH structure --> HARQ process -->resource_assignment)
* XXX: in reality this flag is not needed because is enough to check if the PDU is NULL (continue the transmission) or not (new SI transmission)
* -SI_start (inside ndlsch structure): flag for indicate the starting of the SI transmission within the SI window (new PDU is received by the MAC) otherwise the PHY continue to transmit
* what have in its buffer (so check the remaining encoded data continuously)
*
* SI transmission should not occurr in reserved subframes
* subframe = 0 (MIB-NB)
* subframe = 4 (SIB1-NB) but depends on the frame
* subframe = 5 (NPSS)
* subframe = 9 (NSSS) but depends on the frame (if is even)
*
* [This condition should be known by the MAC layer so it should trigger an DLSCH pdu only at proper instants]
*
* XXX Important: in the case the SI-window finish the PHY layer should have also being able to conclude all the SI transmission in time
* (because this is managed by the MAC layer that stops transmitting the SDU to PHY in advance because is counting the remaining subframe for the transmission)
*
*
*XXX important: set the flag HARQ process->status to DISABLE when PHY finished the SI-transmission over the 2 or 8 subframes
*XXX important: whenever we enter for some error in the ndlsch_procedure with a pdu that is NULL but all the data of the SI have been transmitted (pdu_buffer_index = 0)
*XXX --> generate error
*XXX: the npdlsch_procedure in this case should be only called when is triggered by the MAC schedule_response (use the status flag set by the schedule_response)
*
*/
if(eNB->ndlsch_SI->harq_process->status == ACTIVE_NB_IoT && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4)) //condition on SIB1-NB
{
if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
{
if(eNB->ndlsch_SI != NULL && subframe!= 0 && subframe != 5 && subframe != 9)
{
//check if the PDU != NULL will be done inside just for understanding if a new SI message need to be transmitted or not
npdsch_procedures(eNB,
proc,
eNB->ndlsch_SI, //since we have no DCI for system information, this is filled directly when we receive the DL_CONFIG.request message
eNB->ndlsch_SI->harq_process->pdu);
eNB->ndlsch_SI->harq_process->status = DISABLED_NB_IoT;
}
} else {//this frame not foresee the transmission of NSSS (subframe 9 is available)
if(eNB->ndlsch_SI != NULL && subframe!= 0 && subframe != 5)
{
npdsch_procedures(eNB,
proc,
eNB->ndlsch_SI, //since we have no DCI for system information, this is filled directly when we receive the DL_CONFIG.request message
eNB->ndlsch_SI->harq_process->pdu);
eNB->ndlsch_SI->harq_process->status = DISABLED_NB_IoT;
}
}
}
///check for RAR transmission
if(eNB->ndlsch_ra != NULL && eNB->ndlsch_ra->active == 1 && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4)) //condition on SIB1-NB
{
if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
{
if(eNB->ndlsch_SI != NULL && subframe!= 0 && subframe != 5 && subframe != 9)
{
npdsch_procedures(eNB,
proc,
eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
eNB->ndlsch_ra->harq_process->pdu);
//it should be activated only when we receive the proper DCIN1_RAR
eNB->ndlsch_ra->active= 0;
}
}
else //this frame not foresee the transmission of NSSS (subframe 9 is available)
{
if(eNB->ndlsch_SI != NULL && subframe!= 0 && subframe != 5)
{
npdsch_procedures(eNB,
proc,
eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
eNB->ndlsch_ra->harq_process->pdu);
//it should be activated only when we receive the proper DCIN1_RAR
eNB->ndlsch_ra->active= 0; // maybe this is already done inside the ndlsch_procedure
}
}
}
//check for UE specific transmission
/*
* Delays between DCI transmission and NDLSCH transmission are taken in consideration by the MAC scheduler by sending in the proper subframe the scheduler_response
* (TS 36.213 ch 16.4.1: DCI format N1, N2, ending in subframe n intended for the UE, the UE shall decode, starting from subframe n+5 DL subframe,
* the corresponding NPDSCH transmission over the N consecutive NB/IoT DL subframes according to NPDCCH information)
* Transmission over more subframe and Repetitions are managed directly by the PHY layer
* We should have only 1 ue-specific ndlsch structure active at each time (active flag is set = 1 only at the corresponding NDLSCH pdu reception and not at the DCI time
* (NDLSCH transmission should be compliant with the FAPI procedure Figure 3-49)
*
* XXX how are managed the transmission and repetitions over the NPDSCH:
* -repetitions over the NPDSCH channel are defined inside the DCI
* -need to know the repetition number R (see specs)
* -repetition are made following a pattern rule (e.g. 00, 11 ...) (see specs)
* --whenever R>4 then repetition pattern rule changes
* -possibility to have DL-GAP (OPTIONAL) otherwise no gap in DCI transmission
*
* XXX During repetitions of DCI or NDLSCH we receive no schedule_response form MAC
*
*/
//this should give only 1 result (since only 1 ndlsch procedure is activated at once) so we brak after the transmission
for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
{
if(eNB->ndlsch[(uint8_t)UE_id] != NULL && eNB->ndlsch[(uint8_t)UE_id]->active == 1 && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4)) //condition on sib1-NB
{
if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
{
if( subframe!= 0 && subframe != 5 && subframe != 9)
{
npdsch_procedures(eNB,
proc,
eNB->ndlsch[(uint8_t)UE_id],
eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
break;
}
}
else //this frame not foresee the transmission of NSSS (subframe 9 is available)
{
if( subframe!= 0 && subframe != 5)
{
npdsch_procedures(eNB,
proc,
eNB->ndlsch[(uint8_t)UE_id],
eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
break;
}
}
}
}
//no dedicated phy config
/*If we have DCI to generate do it now
*
* DCI in NB-IoT are transmitted over NPDCCH search spaces as described in TS 36.213 ch 16.6
*
* Don-t care about the concept of search space since will be managed by the MAC.
* MAC also evaluate the starting position of NPDCCH transmission and will send the corresponding scheduling_response
*
*
* The PHY layer should evaluate R (repetitions of DCI) based on:
* -L (aggregation level) --> inside the NPDCCH PDU
* -Rmax
* -DCI subframe repetition number (2 bits) --> inside the NPDCCH PDU
* -TS 36.213 Table 16.6/1/2/3
*
*
* The higher layer parms (Rmax):
* -npdcch-NumRepetitions (UE-specific) [inside the NPDCCH UE-specific strucuture] --> configured through phyconfigDedicated
* -npdcch-NumRepetitionPaging (common)
* -npdcch-NumRepetitions-RA (common) [inside the NB_IoT_DL_FRAME_PARMS-> nprach_ParametersList] --> configured in phy_config_sib2
*
* PROBLEM: in FAPI specs seems there is no way to trasnmit Rmax to the PHY (waiting for answers)
*
* *Rmax is also needed for evaluate the scheduling delay for NDLSCH (see scheduling delay field in NPDCCH PDU FAPI)
*
* *Scrambling re-initialization is needed at the beginning of the Search Space or every 4th NPDCCH subframe (See TS 36.211)
* (this is taken in cosideration by the NPDCCH parameter "scrambling re-initialization batch index" in FAPI specs (Table 4-45)
*
****whenever we have aggregation level = 1 for UE-specific the R is always = 1 (see table 16.6-1)
****DCI DL transmission should not happen in case of reference signals or SI messages (this function should be triggered every subframe)
*
* */
for(UE_id = 0 ; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
{
if(eNB->npdcch[(uint8_t)UE_id] != NULL && eNB->npdcch[(uint8_t)UE_id]->rnti[(uint8_t)UE_id] == dci_pdu->dci_alloc->rnti && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4))
{
if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
{
if( subframe!= 0 && subframe != 5 && subframe != 9)
{
generate_dci_top_NB_IoT(eNB->npdcch[(uint8_t)UE_id],
dci_pdu->Num_dci,
dci_pdu->dci_alloc,
AMP,
fp,
eNB->common_vars.txdataF[0],
subframe,
dci_pdu->npdcch_start_symbol); //this parameter depends by eutraControlRegionSize (see TS36.213 16.6.1)
eNB->npdcch[(uint8_t)UE_id]->repetition_idx[(uint8_t)UE_id]++; //can do also inside also the management
break;
}
}
else //this frame not foresee the transmission of NSSS (subframe 9 is available)
{
if( subframe!= 0 && subframe != 5)
{
generate_dci_top_NB_IoT(eNB->npdcch[(uint8_t)UE_id],
dci_pdu->Num_dci,
dci_pdu->dci_alloc,
AMP,
fp,
eNB->common_vars.txdataF[0],
subframe,
dci_pdu->npdcch_start_symbol); //this parameter depends by eutraControlRegionSize (see TS36.213 16.6.1)
eNB->npdcch[(uint8_t)UE_id]->repetition_idx[(uint8_t)UE_id]++; //can do also inside also the management
break;
}
}
}
}
}
uint32_t rx_nprach_NB_IoT(PHY_VARS_eNB *eNB, int frame, uint8_t subframe, uint16_t *rnti, uint16_t *preamble_index, uint16_t *timing_advance) {
uint32_t estimated_TA;
//int frame,frame_mod; // subframe,
// subframe = eNB->proc.subframe_prach;
// frame = eNB->proc.frame_prach;
estimated_TA = process_nprach_NB_IoT(eNB,frame,subframe,rnti,preamble_index,timing_advance);
//printf("estim = %i\n",estimated_TA);
// }
return estimated_TA;
}
void fill_crc_indication_NB_IoT(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe,uint8_t decode_flag) {
pthread_mutex_lock(&eNB->UL_INFO_mutex);
nfapi_crc_indication_pdu_t *pdu = &eNB->UL_INFO.crc_ind.crc_pdu_list[0]; //[eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs];
pdu->rx_ue_information.rnti = eNB->ulsch_NB_IoT[0]->rnti; /// OK
pdu->crc_indication_rel8.crc_flag = decode_flag;
if(decode_flag == 1)
{
eNB->UL_INFO.crc_ind.number_of_crcs++;
} else {
eNB->UL_INFO.crc_ind.number_of_crcs =0;
}
// nfapi_crc_indication_pdu_t* crc_pdu_list
///eNB->UL_INFO.crc_ind.sfn_sf = frame<<4 | subframe;
//eNB->UL_INFO.crc_ind.header.message_id = NFAPI_CRC_INDICATION;
//eNB->UL_INFO.crc_ind.crc_indication_body.tl.tag = NFAPI_CRC_INDICATION_BODY_TAG;
//pdu->instance_length = 0; // don't know what to do with this
// pdu->rx_ue_information.handle = handle;
///////////////////////pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
//////////////////////////pdu->crc_indication_rel8.tl.tag = NFAPI_CRC_INDICATION_REL8_TAG;
//LOG_D(PHY, "%s() rnti:%04x crcs:%d crc_flag:%d\n", __FUNCTION__, pdu->rx_ue_information.rnti, eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs, crc_flag);
pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}
void fill_rx_indication_NB_IoT(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t data_or_control, uint8_t decode_flag)
{
nfapi_rx_indication_pdu_t *pdu;
nfapi_nb_harq_indication_pdu_t *ack_ind; // &eNB->UL_INFO.nb_harq_ind.nb_harq_indication_body.nb_harq_pdu_list[0] // nb_harq_indication_fdd_rel13->harq_tb1
pthread_mutex_lock(&eNB->UL_INFO_mutex);
if (data_or_control == 0) // format 1
{
if(decode_flag == 1)
{
eNB->UL_INFO.RX_NPUSCH.number_of_pdus = 1;
} else {
eNB->UL_INFO.RX_NPUSCH.number_of_pdus = 0;
}
pdu = &eNB->UL_INFO.RX_NPUSCH.rx_pdu_list[0];
pdu->rx_ue_information.rnti = eNB->ulsch_NB_IoT[0]->rnti;
pdu->rx_indication_rel8.length = eNB->ulsch_NB_IoT[0]->harq_process->TBS; //eNB->ulsch_NB_IoT[0]->harq_process->TBS>>3;
pdu->data = eNB->ulsch_NB_IoT[0]->harq_process->b;
} else { // format 2
if(decode_flag == 1)
{
eNB->UL_INFO.nb_harq_ind.nb_harq_indication_body.number_of_harqs =1;
ack_ind = &eNB->UL_INFO.nb_harq_ind.nb_harq_indication_body.nb_harq_pdu_list[0];
ack_ind->nb_harq_indication_fdd_rel13.harq_tb1 = 1;
ack_ind->rx_ue_information.rnti = eNB->ulsch_NB_IoT[0]->rnti;
} else {
eNB->UL_INFO.nb_harq_ind.nb_harq_indication_body.number_of_harqs =1;
ack_ind = &eNB->UL_INFO.nb_harq_ind.nb_harq_indication_body.nb_harq_pdu_list[0];
ack_ind->nb_harq_indication_fdd_rel13.harq_tb1 = 2;
ack_ind->rx_ue_information.rnti = eNB->ulsch_NB_IoT[0]->rnti;
}
}
//eNB->UL_INFO.RX_NPUSCH.rx_pdu_list.rx_ue_information.tl.tag = NFAPI_RX_INDICATION_BODY_TAG; // do we need this ??
//eNB->UL_INFO.RX_NPUSCH.rx_pdu_list.rx_ue_information.rnti = rnti; // rnti should be got from eNB structure
//pdu = &eNB->UL_INFO.RX_NPUSCH.rx_pdu_list[eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus];
// pdu->rx_ue_information.handle = eNB->ulsch[UE_id]->handle;
// pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG;
//pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG;
/*if(msg3_flag == 1)
{
pdu->rx_indication_rel8.length = 6; //eNB->ulsch_NB_IoT[0]->harq_process->TBS>>3;
int m =0;
for(m=0; m<6;m++)
{
pdu->data[m] = eNB->ulsch_NB_IoT[0]->harq_process->b[2+m];
printf(" pdu content = %d \n", eNB->ulsch_NB_IoT[0]->harq_process->b[2+m]);
}
} else { */
//}
//pdu->data = eNB->ulsch_NB_IoT[UE_id]->harq_processes[harq_pid]->b;
//eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++;
//eNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | subframe;
// do we need to transmit timing ?? however, the nfapi structure does not include timing paramters !!!!!
pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment