Commit 4e522af6 authored by Nick Ho's avatar Nick Ho

Merge branch 'develop-nb-iot-mac' into develop-nb-iot

parents f19315aa 9e228a74
......@@ -956,6 +956,7 @@ add_library(SECU_CN ${SECU_CN_SRC})
################################"
set(SCHED_SRC
${OPENAIR1_DIR}/SCHED/phy_procedures_lte_eNb.c
${OPENAIR1_DIR}/SCHED/phy_procedures_lte_eNb_nb_iot.c
${OPENAIR1_DIR}/SCHED/phy_procedures_lte_ue.c
${OPENAIR1_DIR}/SCHED/phy_procedures_lte_common.c
${OPENAIR1_DIR}/SCHED/phy_mac_stub.c
......@@ -1043,6 +1044,7 @@ set(PHY_SRC
${OPENAIR1_DIR}/PHY/CODING/viterbi.c
${OPENAIR1_DIR}/PHY/CODING/viterbi_lte.c
${OPENAIR1_DIR}/PHY/INIT/lte_init.c
${OPENAIR1_DIR}/PHY/INIT/lte_init_nb_iot.c
${OPENAIR1_DIR}/PHY/INIT/lte_parms.c
${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c
${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
......@@ -1127,17 +1129,22 @@ set(L2_SRC
set (MAC_SRC
${MAC_DIR}/lte_transport_init.c
${MAC_DIR}/main.c
${MAC_DIR}/IF_Module_nb_iot.c
${MAC_DIR}/ue_procedures.c
${MAC_DIR}/ra_procedures.c
${MAC_DIR}/l1_helpers.c
${MAC_DIR}/rar_tools.c
${MAC_DIR}/eNB_scheduler.c
${MAC_DIR}/eNB_scheduler_dlsch.c
${MAC_DIR}/eNB_scheduler_dlsch_nb_iot.c
${MAC_DIR}/eNB_scheduler_ulsch.c
${MAC_DIR}/eNB_scheduler_ulsch_nb_iot.c
${MAC_DIR}/eNB_scheduler_mch.c
${MAC_DIR}/eNB_scheduler_bch.c
${MAC_DIR}/eNB_scheduler_primitives.c
${MAC_DIR}/eNB_scheduler_primitives_nb_iot.c
${MAC_DIR}/eNB_scheduler_RA.c
${MAC_DIR}/eNB_scheduler_RA_nb_iot.c
${MAC_DIR}/pre_processor.c
${MAC_DIR}/config.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
*/
#ifndef __INIT_DEFS__H__
#define __INIT_DEFS__H__
#include "PHY/defs.h"
#include "SystemInformationBlockType2.h"
//#include "RadioResourceConfigCommonSIB.h"
#include "RadioResourceConfigDedicated.h"
#include "TDD-Config.h"
#include "MBSFN-SubframeConfigList.h"
#include "MobilityControlInfo.h"
#if defined(Rel10) || defined(Rel14)
#include "SCellToAddMod-r10.h"
#endif
/** @addtogroup _PHY_STRUCTURES_
* @{
*/
/*!
\fn int phy_init_top(LTE_DL_FRAME_PARMS *frame_parms)
\brief Allocate and Initialize the PHY variables after receiving static configuration
@param frame_parms Pointer to LTE_DL_FRAME_PARMS (common configuration)
@returns 0 on success
*/
int phy_init_top(LTE_DL_FRAME_PARMS *frame_parms);
/*!
\brief Allocate and Initialize the PHY variables relevant to the LTE implementation.
\details Only a subset of phy_vars_ue is initialized.
@param[out] phy_vars_ue Pointer to UE Variables
@param nb_connected_eNB Number of eNB that UE can process in one PDSCH demodulation subframe
@param abstraction_flag 1 indicates memory should be allocated for abstracted MODEM
@returns 0 on success
@returns -1 if any memory allocation failed
@note The current implementation will never return -1, but segfault.
*/
int phy_init_lte_ue(PHY_VARS_UE *phy_vars_ue,
int nb_connected_eNB,
uint8_t abstraction_flag);
/*!
\brief Allocate and initialize the PHY variables relevant to the LTE implementation (eNB).
\details Only a subset of phy_vars_eNb is initialized.
@param[out] phy_vars_eNb Pointer to eNB Variables
@param is_secondary_eNb Flag to indicate this eNB gets synch from another
@param abstraction_flag 1 indicates memory should be allocated for abstracted MODEM
@returns 0 on success
@returns -1 if any memory allocation failed
@note The current implementation will never return -1, but segfault.
*/
int phy_init_lte_eNB(PHY_VARS_eNB *phy_vars_eNb,
unsigned char is_secondary_eNb,
unsigned char abstraction_flag);
/** \brief Configure LTE_DL_FRAME_PARMS with components derived after initial synchronization (MIB decoding + primary/secondary synch).
\details The basically allows configuration of \f$N_{\mathrm{RB}}^{\mathrm{DL}}\f$, the cell id \f$N_{\mathrm{ID}}^{\mathrm{cell}}\f$, the normal/extended prefix mode, the frame type (FDD/TDD), \f$N_{\mathrm{cp}}\f$, the number of TX antennas at eNB (\f$p\f$) and the number of PHICH groups, \f$N_{\mathrm{group}}^{\mathrm{PHICH}}\f$
@param lte_frame_parms pointer to LTE parameter structure
@param N_RB_DL Number of DL resource blocks
@param Nid_cell Cell ID
@param Ncp Normal/Extended Prefix flag
@param frame_type FDD/TDD framing
@param p_eNB Number of eNB TX antennas
@param phich_config Pointer to PHICH_CONFIG_COMMON
*/
void phy_config_mib(LTE_DL_FRAME_PARMS *lte_frame_parms,
uint8_t N_RB_DL,
uint8_t Nid_cell,
uint8_t Ncp,
uint8_t frame_type,
uint8_t p_eNB,
PHICH_CONFIG_COMMON *phich_config);
/** \brief Configure LTE_DL_FRAME_PARMS with components derived after reception of SIB1.
\details From a PHY perspective this allows configuration of TDD framing parameters and SI reception.
@param Mod_id Instance ID of eNB
@param CC_id Component Carrier index
@param tdd_Config TDD UL/DL and S-subframe configurations
@param SIwindowsize Size of a SI window in frames where repetitions of a unique System Information message block is repeated
@param SIperiod Periodicity of System Information Messages (in multiples of a frame)*/
void phy_config_sib1_eNB(module_id_t Mod_id,
int CC_id,
TDD_Config_t *tdd_Config,
uint8_t SIwindowsize,
uint16_t SIperiod);
/** \brief Configure LTE_DL_FRAME_PARMS with components derived after reception of SIB1.
\details From a PHY perspective this allows configuration of TDD framing parameters and SI reception.
@param Mod_id Instance ID of UE
@param CC_id Component Carrier index
@param CH_index Index of eNB for this configuration
@param tdd_Config TDD UL/DL and S-subframe configurations
@param SIwindowsize Size of a SI window in frames where repetitions of a unique System Information message block is repeated
@param SIperiod Periodicity of System Information Messages (in multiples of a frame)*/
void phy_config_sib1_ue(module_id_t Mod_id,
int CC_id,
uint8_t CH_index,
TDD_Config_t *tdd_Config,
uint8_t SIwindowsize,
uint16_t SIperiod);
/*!
\fn void phy_config_sib2_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t CH_index,
RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
ARFCN_ValueEUTRA_t *ul_CArrierFreq,
long *ul_Bandwidth,
AdditionalSpectrumEmission_t additionalSpectrumEmission,
struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList)
\brief Configure LTE_DL_FRAME_PARMS with components derived after reception of SIB2 (at UE).
@param Mod_id Instance id
@param CC_id
@param CH_index Index of CH to which UE is connected
@param CC_id Component Carrier Index
@param radioResourceConfigCommon Radio Configuration from SIB2
@param ul_CarrierFreq UL carrier ARFCN, null if optional (i.e. implicit from DL)
@param ul_Bandwidth UL bandwidth, null if optional (i.e. same as DL)
@param additionalSpectrumEmission UL parameter (see 36.101)
@param mbsfn_SubframeConfigList MBSFN subframe configuration
*/
void phy_config_sib2_ue(module_id_t Mod_id,
int CC_id,
uint8_t CH_index,
RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
ARFCN_ValueEUTRA_t *ul_CArrierFreq,
long *ul_Bandwidth,
AdditionalSpectrumEmission_t *additionalSpectrumEmission,
struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList);
/*!
\fn phy_config_afterHO_ue
\brief Configure Common PHY parameters from mobilityControlInfo
@param Mod_id
@param CC_id
@param eNB_index
@param mobilityControlInfo pointer to the mobility control information for handover
@param ho_failed flag to indicated whether the ho was successful or not
*/
void phy_config_afterHO_ue(module_id_t Mod_id,
uint8_t CC_id,
uint8_t eNB_index,
MobilityControlInfo_t *mobilityControlInfo,
uint8_t ho_failed);
/*!
\fn void phy_config_sib2_eNB(module_id_t Mod_id,
RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
ARFCN_ValueEUTRA_t *ul_CArrierFreq,
long *ul_Bandwidth,
AdditionalSpectrumEmission_t additionalSpectrumEmission,
struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList)
\brief Configure LTE_DL_FRAME_PARMS with components of SIB2 (at eNB).
@param Mod_id Instance id
@param Mod_id Component Carrier index
@param radioResourceConfigCommon Radio Configuration from SIB2
@param ul_CarrierFreq UL carrier ARFCN, null if optional (i.e. implicit from DL)
@param ul_Bandwidth UL bandwidth, null if optional (i.e. same as DL)
@param additionalSpectrumEmission UL parameter (see 36.101)
@param mbsfn_SubframeConfigList MBSFN subframe configuration
*/
void phy_config_sib2_eNB(module_id_t Mod_id,
int CC_id,
RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
ARFCN_ValueEUTRA_t *ul_CArrierFreq,
long *ul_Bandwidth,
AdditionalSpectrumEmission_t *additionalSpectrumEmission,
struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList);
/*!
\fn void phy_config_dedicated_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t CH_index,
struct PhysicalConfigDedicated *physicalConfigDedicated)
\brief Configure UE dedicated parameters.
\details Invoked upon reception of RRCConnectionSetup or RRCConnectionReconfiguration from eNB.
@param Mod_id Instance ID for eNB
@param CC_id Component Carrier index
@param CH_index Index of eNB for this configuration
@param physicalConfigDedicated PHY Configuration information
*/
void phy_config_dedicated_ue(module_id_t Mod_id,
int CC_id,
uint8_t CH_index,
struct PhysicalConfigDedicated *physicalConfigDedicated);
/*!
\fn void phy_config_harq_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t CH_index,
uint16_t max_harq_tx)
\brief Configure UE UL max harq Tx.
\details Invoked upon reception of RRCConnectionSetup or RRCConnectionReconfiguration from eNB.
@param Mod_id Instance ID for eNB
@param CC_id Component Carrier index
@param CH_index Index of eNB for this configuration
@param max_harq_tx max harq tx information
*/
void phy_config_harq_ue(module_id_t Mod_id,int CC_id,uint8_t CH_index,
uint16_t max_harq_tx);
/**
\brief Configure UE MBSFN common parameters.
\details Invoked upon reception of SIB13 from eNB.
@param Mod_id Instance ID for UE
@param CC_id Component Carrier Index
@param CH_index eNB id (for multiple eNB reception)
@param mbsfn_Area_idx Index of MBSFN-Area for which this command operates
@param mbsfn_AreaId_r9 MBSFN-Area Id
*/
void phy_config_sib13_ue(module_id_t Mod_id,
int CC_id,uint8_t CH_index,int mbsfn_Area_idx,
long mbsfn_AreaId_r9);
/**
\brief Configure eNB MBSFN common parameters.
\details Invoked upon transmission of SIB13 from eNB.
@param Mod_id Instance ID for eNB
@param CC_id Component Carrier index
@param mbsfn_Area_idx Index of MBSFN-Area for which this command operates
@param mbsfn_AreaId_r9 MBSFN-Area Id
*/
void phy_config_sib13_eNB(module_id_t Mod_id,
int CC_id,
int mbsfn_Area_idx,
long mbsfn_AreaId_r9);
/**
\brief Configure cba rnti for .
@param Mod_id Instance ID for eNB
@param CC_id Component Carrier Index
@param eNB_flag flag indicating whether the nodeis eNB (1) or UE (0)
@param index index of the node
@param cba_rnti rnti for the cba transmission
@param num_active_cba_groups num active cba group
*/
void phy_config_cba_rnti (module_id_t Mod_id,int CC_id,eNB_flag_t eNB_flag, uint8_t index, rnti_t cba_rnti, uint8_t cba_group_id, uint8_t num_active_cba_groups);
/** \brief Configure RRC inter-cell measurements procedures
@param Mod_id Index of UE
@param CC_id
@param eNB_index Index of corresponding eNB
@param n_adj_cells Number of adjacent cells on which to perform the measuremnts
@param adj_cell_id Array of cell ids of adjacent cells
*/
void phy_config_meas_ue(module_id_t Mod_id,
uint8_t CC_id,
uint8_t eNB_index,
uint8_t n_adj_cells,
uint32_t *adj_cell_id);
/*!
\fn void phy_config_dedicated_eNB(module_id_t Mod_id,uint16_t rnti,
struct PhysicalConfigDedicated *physicalConfigDedicated)
\brief Prepare for configuration of PHY with dedicated parameters.
\details Invoked just prior to transmission of RRCConnectionSetup or RRCConnectionReconfiguration at eNB.
@param Mod_id Instance ID for eNB
@param CC_id Component Carrier index
@param rnti rnti for UE context
@param physicalConfigDedicated PHY Configuration information
*/
void phy_config_dedicated_eNB(module_id_t Mod_id,
int CC_id,
rnti_t rnti,
struct PhysicalConfigDedicated *physicalConfigDedicated);
/*!
\fn void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *phy_vars_eNB)
\brief Configure PHY with dedicated parameters between configuration of DLSCH (n) and ULSCH (n+4) in current subframe (n).
@param phy_vars_eNB Pointer to PHY_VARS_eNB structure
*/
void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *phy_vars_eNB);
/*
\fn int phy_init_secsys_eNB(PHY_VARS_eNB *phy_vars_eNb)
\brief Allocate and Initialize the PHY variables relevant to the LTE implementation.
@param phy_vars_eNb pointer to LTE parameter structure for the eNb
*/
int phy_init_secsys_eNB(PHY_VARS_eNB *phy_vars_eNb);
void phy_init_lte_top(LTE_DL_FRAME_PARMS *lte_frame_parms);
//void copy_lte_parms_to_phy_framing(LTE_DL_FRAME_PARMS *frame_parm, PHY_FRAMING *phy_framing);
void lte_param_init(unsigned char N_tx_port_eNB,
unsigned char N_tx,
unsigned char N_rx,
unsigned char transmission_mode,
uint8_t extended_prefix_flag,
frame_t frame_type,
uint16_t Nid_cell,
uint8_t tdd_config,
uint8_t N_RB_DL,
uint8_t threequarter_fs,
uint8_t osf,
uint32_t perfect_ce);
#if defined(Rel10) || defined(Rel14)
void phy_config_dedicated_scell_ue(uint8_t Mod_id,
uint8_t eNB_index,
SCellToAddMod_r10_t *sCellToAddMod_r10,
int CC_id);
void phy_config_dedicated_scell_eNB(uint8_t Mod_id,
uint16_t rnti,
SCellToAddMod_r10_t *sCellToAddMod_r10,
int CC_id);
#endif
/*brief Configure LTE_DL_FRAME_PARMS with components derived after initial synchronization (MIB-NB decoding + primary/secondary synch).*/
void NB_phy_config_mib_eNB(int Mod_id,
int CC_id,
int eutra_band,
int Nid_cell,
int Ncp,
int p_eNB,
uint32_t dl_CarrierFreq,
uint32_t ul_CarrierFreq,
struct MasterInformationBlock_NB__operationModeInfo_r13_u operationModeInfo);
/*NB_phy_config_sib1_eNB is not needed since NB-IoT use only FDD mode*/
/*brief Configure LTE_DL_FRAME_PARMS with components of SIB2-NB (at eNB).*/
void NB_phy_config_sib2_eNB(module_id_t Mod_id,
int CC_id,
RadioResourceConfigCommonSIB_NB_r13 *radioResourceConfigCommon,
ARFCN_ValueEUTRA_r9_t *ul_CArrierFreq,,
);
void NB_phy_config_dedicated_eNB(module_id_t Mod_id,
int CC_id,
rnti_t rnti,
struct PhysicalConfigDedicated_NB_r13 *physicalConfigDedicated);
/*! !\fn void phy_cleanup(void)
\brief Cleanup the PHY variables*/
void phy_cleanup(void);
int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf);
void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms);
void lte_param_init(unsigned char N_tx_port_eNB,
unsigned char N_tx_phy,
unsigned char N_rx,
unsigned char transmission_mode,
uint8_t extended_prefix_flag,
frame_t frame_type,
uint16_t Nid_cell,
uint8_t tdd_config,
uint8_t N_RB_DL,
uint8_t threequarter_fs,
uint8_t osf,
uint32_t perfect_ce);
/** @} */
#endif
......@@ -37,6 +37,70 @@ extern uint16_t prach_root_sequence_map0_3[838];
extern uint16_t prach_root_sequence_map4[138];
uint8_t dmrs1_tab[8] = {0,2,3,4,6,8,9,10};
#if defined(NB_IoT)
void NB_phy_config_mib_eNB(int Mod_id,
int CC_id,
int eutra_band,
int Nid_cell,
int Ncp,
int p_eNB,
uint32_t dl_CarrierFreq,
uint32_t ul_CarrierFreq) {
LTE_DL_FRAME_PARMS *fp;
LOG_I(PHY,"Configuring MIB for instance %d, CCid %d : (band %d,N_RB_DL %d,Nid_cell %d,p %d,DL freq %u)\n",
Mod_id, CC_id, eutra_band, N_RB_DL_array[dl_Bandwidth], Nid_cell, p_eNB,dl_CarrierFreq);
/*if (RC.eNB == NULL) {
RC.eNB = (PHY_VARS_eNB ***)malloc((1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB***));
LOG_I(PHY,"RC.eNB = %p\n",RC.eNB);
memset(RC.eNB,0,(1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB***));
}
if (RC.eNB[Mod_id] == NULL) {
RC.eNB[Mod_id] = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB**));
LOG_I(PHY,"RC.eNB[%d] = %p\n",Mod_id,RC.eNB[Mod_id]);
memset(RC.eNB[Mod_id],0,(1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB***));
}
if (RC.eNB[Mod_id][CC_id] == NULL) {
RC.eNB[Mod_id][CC_id] = (PHY_VARS_eNB *)malloc(sizeof(PHY_VARS_eNB));
LOG_I(PHY,"RC.eNB[%d][%d] = %p\n",Mod_id,CC_id,RC.eNB[Mod_id][CC_id]);
RC.eNB[Mod_id][CC_id]->Mod_id = Mod_id;
RC.eNB[Mod_id][CC_id]->CC_id = CC_id;
}
RC.eNB[Mod_id][CC_id]->mac_enabled = 1;
fp = &RC.eNB[Mod_id][CC_id]->frame_parms; */
fp->Nid_cell = Nid_cell;
fp->nushift = Nid_cell%6;
fp->eutra_band = eutra_band;
fp->Ncp = Ncp;
fp->nb_antenna_ports_eNB = p_eNB;
fp->dl_CarrierFreq = dl_CarrierFreq;
fp->ul_CarrierFreq = ul_CarrierFreq;
init_frame_parms(fp,1);
init_lte_top(fp);
}
void NB_phy_config_sib2_eNB(uint8_t Mod_id,
int CC_id,
RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
ARFCN_ValueEUTRA_t *ul_CArrierFreq,
AdditionalSpectrumEmission_t *additionalSpectrumEmission,
)
{
}
#endif
// FIXME not used anywhere
void phy_config_mib(LTE_DL_FRAME_PARMS *fp,
uint8_t N_RB_DL,
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "defs.h"
#include "SCHED/defs.h"
#include "PHY/extern.h"
#include "SIMULATION/TOOLS/defs.h"
#include "RadioResourceConfigCommonSIB.h"
#include "RadioResourceConfigDedicated.h"
#include "TDD-Config.h"
#include "LAYER2/MAC/extern.h"
#include "MBSFN-SubframeConfigList.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#define DEBUG_PHY
#include "assertions.h"
#include <math.h>
//NB-IoT
#include "defs_nb_iot.h"
#include "RadioResourceConfigCommonSIB-NB-r13.h"
#include "PHY/impl_defs_lte_nb_iot.h"
#include "RadioResourceConfigDedicated-NB-r13.h"
extern uint16_t prach_root_sequence_map0_3[838];
extern uint16_t prach_root_sequence_map4[138];
uint8_t dmrs1_tab[8] = {0,2,3,4,6,8,9,10};
void NB_phy_config_mib_eNB(int Mod_id,
int CC_id,
int eutra_band,
int Nid_cell,
int Ncp,
int p_eNB,
uint32_t dl_CarrierFreq,
uint32_t ul_CarrierFreq) {
/*Not sure if phy parameters should be initial here or not*/
/*the phy_config_mib_eNB as the entry point to allocate the context for L1. The RC contains the context for L1,L2. If RC.eNB is NULL, it hasn't been allocated earlier so we allocate it there.*/
/*if (RC.eNB == NULL) {
RC.eNB = (PHY_VARS_eNB ***)malloc((1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB***));
LOG_I(PHY,"RC.eNB = %p\n",RC.eNB);
memset(RC.eNB,0,(1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB***));
}
if (RC.eNB[Mod_id] == NULL) {
RC.eNB[Mod_id] = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB**));
LOG_I(PHY,"RC.eNB[%d] = %p\n",Mod_id,RC.eNB[Mod_id]);
memset(RC.eNB[Mod_id],0,(1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB***));
}
if (RC.eNB[Mod_id][CC_id] == NULL) {
RC.eNB[Mod_id][CC_id] = (PHY_VARS_eNB *)malloc(sizeof(PHY_VARS_eNB));
LOG_I(PHY,"RC.eNB[%d][%d] = %p\n",Mod_id,CC_id,RC.eNB[Mod_id][CC_id]);
RC.eNB[Mod_id][CC_id]->Mod_id = Mod_id;
RC.eNB[Mod_id][CC_id]->CC_id = CC_id;
}
RC.eNB[Mod_id][CC_id]->mac_enabled = 1;
fp = &RC.eNB[Mod_id][CC_id]->frame_parms; */
NB_DL_FRAME_PARMS *fp = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms;
//LOG_I(PHY,"Configuring MIB-NB for instance %d, CCid %d : (band %d,N_RB_DL %d,Nid_cell %d,p %d,DL freq %u)\n",
//Mod_id, CC_id, eutra_band, N_RB_DL_array[dl_Bandwidth], Nid_cell, p_eNB,dl_CarrierFreq);
fp->Nid_cell = Nid_cell;
fp->nushift = Nid_cell%6;
fp->eutra_band = eutra_band;
fp->Ncp = Ncp;
fp->nb_antenna_ports_eNB = p_eNB;
fp->dl_CarrierFreq = dl_CarrierFreq;
fp->ul_CarrierFreq = ul_CarrierFreq;
//init_frame_parms(fp,1);
//init_lte_top(fp);
}
void NB_phy_config_sib2_eNB(uint8_t Mod_id,
int CC_id,
RadioResourceConfigCommonSIB_NB_r13_t *radioResourceConfigCommon,
ARFCN_ValueEUTRA_r9_t *ul_CArrierFreq
)
{
NB_DL_FRAME_PARMS *fp = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms;
//LTE_eNB_UE_stats *eNB_UE_stats = PHY_vars_eNB_g[Mod_id][CC_id]->eNB_UE_stats;
//int32_t rx_total_gain_eNB_dB = PHY_vars_eNB_g[Mod_id][CC_id]->rx_total_gain_eNB_dB;
uint8_t MAX_NPRACH = 4;
NPRACH_Parameters_NB_r13_t *np;
LOG_D(PHY,"[eNB%d] CCid %d: Applying radioResourceConfigCommon_NB\n",Mod_id,CC_id);
/*NPRACH configCommon*/
fp->nprach_config_common.nprach_CP_Length =radioResourceConfigCommon->nprach_Config_r13.nprach_CP_Length_r13;
//LOG_D(PHY,"nprach_config_common.nprach_CP_Length = %d\n",fp->nprach_config_common.nprach_CP_Length);
//fp->nprach_config_common.rsrp_ThresholdsPrachInfoList.list =radioResourceConfigCommon->nprach_Config_r13.rsrp_ThresholdsPrachInfoList_r13.list;
//LOG_D(PHY,"nprach_config_common.rsrp_ThresholdsPrachInfoList = %d\n",fp->nprach_config_common.rsrp_ThresholdsPrachInfoList);
/*Loop over the configuration according to the maxNPRACH_Resources*/
for (fp->CE=1; fp->CE <= MAX_NPRACH;fp->CE++){
np = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[fp->CE];
/*fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->maxNumPreambleAttemptCE =np->maxNumPreambleAttemptCE_r13;
//LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.maxNumPreambleAttemptCE = %d\n",fp->nprach_config_common.nprach_ParametersList.list.maxNumPreambleAttemptCE);
fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_NumRepetitions_RA =np->npdcch_NumRepetitions_RA_r13;
//LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.npdcch_NumRepetitions_RA = %d\n",fp->nprach_config_common.nprach_ParametersList.list.npdcch_NumRepetitions_RA);
fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_Periodicity =np->nprach_Periodicity_r13;
//LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_Periodicity = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_Periodicity);
fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_StartTime =np->nprach_StartTime_r13;
//LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_StartTime = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_StartTime);
fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_SubcarrierOffset =np->nprach_SubcarrierOffset_r13;
//LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierOffset = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierOffset);
fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_SubcarrierMSG3_RangeStart =np->nprach_SubcarrierMSG3_RangeStart_r13;
//LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierMSG3_RangeStart = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierMSG3_RangeStart);
fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_Offset_RA =np->npdcch_Offset_RA_r13;
//LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.npdcch_Offset_RA = %d\n",fp->nprach_config_common.nprach_ParametersList.list.npdcch_Offset_RA);
fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_StartSF_CSS_RA =np->npdcch_StartSF_CSS_RA_r13;
//LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.npdcch_StartSF_CSS_RA = %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_StartSF_CSS_RA);
*/
}
/*Should modify to compute_nprach_seq*/
//compute_prach_seq(&fp->prach_config_common,fp->frame_type,PHY_vars_eNB_g[Mod_id][CC_id]->X_u);
/*NPDSCH ConfigCommon*/
fp->npdsch_config_common.nrs_Power = radioResourceConfigCommon->npdsch_ConfigCommon_r13.nrs_Power_r13;
/*NPUSCH ConfigCommon*/
/*A list (1-3) should be loop for ack_NACK_NumRepetitions_Msg4*/
for (fp->CE=1; fp->CE <= MAX_NPRACH;fp->CE++){
fp->npusch_config_common.ack_NACK_NumRepetitions_Msg4[fp->CE] = radioResourceConfigCommon->npusch_ConfigCommon_r13.ack_NACK_NumRepetitions_Msg4_r13.list.array[fp->CE];
//LOG_D(PHY,"npusch_config_common.ack_NACK_NumRepetitions_Msg4 = %d]n",fp->npusch_config_common.ack_NACK_NumRepetitions_Msg4);
}
fp->npusch_config_common.srs_SubframeConfig = radioResourceConfigCommon->npusch_ConfigCommon_r13.srs_SubframeConfig_r13;
LOG_D(PHY,"npusch_config_common.srs_SubframeConfig = %d]n",fp->npusch_config_common.srs_SubframeConfig);
fp->npusch_config_common.dmrs_Config.threeTone_BaseSequence = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_BaseSequence_r13;
LOG_D(PHY,"npusch_config_common.dmrs_Config.threeTone_BaseSequence = %d]n",fp->npusch_config_common.dmrs_Config.threeTone_BaseSequence);
fp->npusch_config_common.dmrs_Config.sixTone_BaseSequence = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_BaseSequence_r13;
LOG_D(PHY,"npusch_config_common.dmrs_Config.sixTone_BaseSequence = %d]n",fp->npusch_config_common.dmrs_Config.sixTone_BaseSequence);
fp->npusch_config_common.dmrs_Config.threeTone_CyclicShift = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_CyclicShift_r13;
LOG_D(PHY,"npusch_config_common.dmrs_Config.threeTone_CyclicShift = %d]n",fp->npusch_config_common.dmrs_Config.threeTone_CyclicShift);
fp->npusch_config_common.dmrs_Config.sixTone_CyclicShift = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_CyclicShift_r13;
LOG_D(PHY,"npusch_config_common.dmrs_Config.sixTone_CyclicShift = %d]n",fp->npusch_config_common.dmrs_Config.sixTone_CyclicShift);
fp->npusch_config_common.dmrs_Config.twelveTone_BaseSequence = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->twelveTone_BaseSequence_r13;
LOG_D(PHY,"npusch_config_common.dmrs_Config.twelveTone_BaseSequence = %d]n",fp->npusch_config_common.dmrs_Config.twelveTone_BaseSequence);
fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH = radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13;
LOG_D(PHY,"npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH = %d]n",fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH);
fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled = radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13;
LOG_D(PHY,"npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled = %d]n",fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled);
/*should change the part that implement the ul hopping in NB-IoT*/
//init_ul_hopping(fp);
/*UL Power Control Config Common*/
fp->ul_power_control_config_common.p0_NominalNPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon_r13.p0_NominalNPUSCH_r13;
fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon_r13.alpha_r13;
fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon_r13.deltaPreambleMsg3_r13;
/*DL gap*/
fp->DL_gap_config.dl_GapDurationCoeff = radioResourceConfigCommon->dl_Gap_r13->dl_GapDurationCoeff_r13;
fp->DL_gap_config.dl_GapPeriodicity = radioResourceConfigCommon->dl_Gap_r13->dl_GapPeriodicity_r13;
fp->DL_gap_config.dl_GapThreshold = radioResourceConfigCommon->dl_Gap_r13->dl_GapThreshold_r13;
/*PUCCH stuff in LTE*/
//init_ncs_cell(fp,PHY_vars_eNB_g[Mod_id][CC_id]->ncs_cell);
//init_ul_hopping(fp);
}
void NB_phy_config_dedicated_eNB(uint8_t Mod_id,
int CC_id,
uint16_t rnti,
struct PhysicalConfigDedicated_NB_r13 *physicalConfigDedicated)
{
PHY_VARS_eNB *eNB = PHY_vars_eNB_g[Mod_id][CC_id];
int8_t UE_id = find_ue(rnti,eNB);
if (UE_id == -1) {
LOG_E( PHY, "[eNB %"PRIu8"] find_ue() returns -1\n", Mod_id);
return;
}
/*physicalconfigDedicated is defined in PHY_VARS_eNB in defs.h in PHY layer*/
if (physicalConfigDedicated) {
eNB->physicalConfigDedicated[UE_id] = physicalConfigDedicated;
LOG_I(PHY,"phy_config_dedicated_eNB: physicalConfigDedicated=%p\n",physicalConfigDedicated);
} else {
LOG_E(PHY,"[eNB %d] Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, UE_id);
return;
}
}
/*
* 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/dci.h
* \brief typedefs for LTE DCI structures from 36-212, V8.6 2009-03. Limited to 5 MHz formats for the moment.Current LTE compliance V8.6 2009-03.
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
#ifndef USER_MODE
#include "PHY/types.h"
#else
#include <stdint.h>
#endif
typedef enum DCI_format_NB
{
DCIFormatN0 = 0,
DCIFormatN1,
DCIFormatN1_RA,
DCIFormatN1_RAR,
DCIFormatN2_Ind,
DCIFormatN2_Pag,
}e_DCI_format_NB;
/// DCI Format Type 0 (180 kHz, 23 bits)
struct DCIFormatN0{
/// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits
uint8_t type;
/// Subcarrier indication, 6 bits
uint8_t scind;
/// Resourse Assignment (RU Assignment), 3 bits
uint8_t ResAssign;
/// Modulation and Coding Scheme, 4 bits
uint8_t mcs;
/// New Data Indicator, 1 bits
uint8_t ndi;
/// Scheduling Delay, 2 bits
uint8_t Scheddly;
/// Repetition Number, 3 bits
uint8_t RepNum;
/// Redundancy version for HARQ (only use 0 and 2), 1 bits
uint8_t rv;
/// DCI subframe repetition Number, 2 bits
uint8_t DCIRep;
};
typedef struct DCIFormatN0 DCIFormatN0_t;
#define sizeof_DDCIFormatN0_t 23
/// DCI Format Type N1 for User data
struct DCIFormatN1{
/// type = 0 => DCI Format N0, type = 1 => DCI Format N1,1bits
uint8_t type;
//NPDCCH order indicator (set to 0), 1 bits
uint8_t orderIndicator;
// Scheduling Delay,3 bits
uint8_t Scheddly;
// Resourse Assignment (RU Assignment),3 bits
uint8_t ResAssign;
// Modulation and Coding Scheme,4 bits
uint8_t mcs;
// Repetition Number,4 bits
uint8_t RepNum;
// New Data Indicator,1 bits
uint8_t ndi;
// HARQ-ACK resource,4 bits
uint8_t HARQackRes;
// DCI subframe repetition Number,2 bits
uint8_t DCIRep;
};
typedef struct DCIFormatN1 DCIFormatN1_t;
#define sizeof_DCIFormatN1_t 23
/// DCI Format Type N1 for initial RA
struct DCIFormatN1_RA{
/// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits
uint8_t type;
//NPDCCH order indicator (set to 0),1 bits
uint8_t orderIndicator;
// Start number of NPRACH repetiiton, 2 bits
uint8_t Scheddly;
// Subcarrier indication of NPRACH, 6 bits
uint8_t scind;
// All the remainging bits, 13 bits
uint8_t remaingingBits;
};
typedef struct DCIFormatN1_RA DCIFormatN1_RA_t;
#define sizeof_DCIFormatN1_RA_t 23
/// DCI Format Type N1 for RAR
struct DCIFormatN1_RAR{
/// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits
uint8_t type;
//NPDCCH order indicator (set to 0),1 bits
uint8_t orderIndicator;
// Scheduling Delay, 3 bits
uint8_t Scheddly;
// Resourse Assignment (RU Assignment), 3 bits
uint8_t ResAssign;
// Modulation and Coding Scheme, 4 bits
uint8_t mcs;
// Repetition Number, 4 bits
uint8_t RepNum;
// Reserved 5 bits
uint8_t Reserved;
// DCI subframe repetition Number, 2 bits
uint8_t DCIRep;
};
typedef struct DCIFormatN1_RAR DCIFormatN1_RAR_t;
#define sizeof_DCIFormatN1_RAR_t 23
// DCI Format Type N2 for direct indication, 15 bits
struct DCIFormatN2_Ind{
//Flag for paging(1)/direct indication(0), set to 0,1 bits
uint8_t type;
//Direct indication information, 8 bits
uint8_t directIndInf;
// Reserved information bits, 6 bits
uint8_t resInfoBits;
};
typedef struct DCIFormatN2_Ind DCIFormatN2_Ind_t;
#define sizeof_DCIFormatN2_Ind_t 15
// DCI Format Type N2 for Paging, 15 bits
struct DCIFormatN2_Pag{
//Flag for paging(1)/direct indication(0), set to 1,1 bits
uint8_t type;
// Resourse Assignment (RU Assignment), 3 bits
uint8_t ResAssign;
// Modulation and Coding Scheme, 4 bits
uint8_t mcs;
// Repetition Number, 4 bits
uint8_t RepNum;
// Reserved 3 bits
uint8_t DCIRep;
};
typedef struct DCIFormatN2_Pag DCIFormatN2_Pag_t;
#define sizeof_DCIFormatN2_Pag_t 15
typedef union DCI_CONTENT {
//
DCIFormatN0_t DCIN0;
//
DCIFormatN1_t DCIN1;
//
DCIFormatN1_RA_t DCIN1_RA;
//
DCIFormatN1_RAR_t DCIN1_RAR;
//
DCIFormatN2_Ind_t DCIN2_Ind;
//
DCIFormatN2_Pag_t DCIN2_Pag;
}DCI_CONTENT;
\ No newline at end of file
/*
* 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/impl_defs_lte.h
* \brief LTE Physical channel configuration and variable structure definitions
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \note
* \warning
*/
#include "types.h"
//#include "defs.h"
#define A_SEQUENCE_OF(type) A_SET_OF(type)
#define A_SET_OF(type) \
struct { \
type **array; \
int count; /* Meaningful size */ \
int size; /* Allocated size */ \
void (*free)(type *); \
}
/// NPRACH-ParametersList-NB-r13 from 36.331 RRC spec
typedef struct {
/// the period time for nprach
uint8_t nprach_Periodicity;
/// for the start time for the NPRACH resource from 40ms-2560ms
uint8_t nprach_StartTime;
/// for the subcarrier of set to the NPRACH preamble from n0 - n34
uint8_t nprach_SubcarrierOffset;
/// where is the region that in NPRACH resource to indicate if this UE support MSG3 for multi-tone or not. from 0 - 1
uint8_t nprach_SubcarrierMSG3_RangeStart;
/// The max preamble transmission attempt for the CE level from 1 - 128
uint8_t maxNumPreambleAttemptCE;
/// The number of the repetition for DCI use in RAR/MSG3/MSG4 from 1 - 2048
uint8_t npdcch_NumRepetitions_RA;
/// Starting subframe for NPDCCH Common searching space for (RAR/MSG3/MSG4)
uint8_t npdcch_StartSF_CSS_RA;
/// Fractional period offset of starting subframe for NPDCCH common search space
uint8_t npdcch_Offset_RA;
} nprach_parameters_NB_t;
typedef struct{
A_SEQUENCE_OF(struct NPRACH_Parameters_NB) list;
}NPRACH_List_NB_t;
typedef long RSRP_Range_t;
typedef struct {
A_SEQUENCE_OF(RSRP_Range_t) list;
}rsrp_ThresholdsNPrachInfoList;
/// NPRACH_ConfigSIB-NB from 36.331 RRC spec
typedef struct {
/// nprach_CP_Length_r13, for the CP length(unit us) only 66.7 and 266.7 is implemented
uint8_t nprach_CP_Length;
/// The criterion for UEs to select a NPRACH resource. Up to 2 RSRP threshold values can be signalled. \vr{[1..2]}
struct rsrp_ThresholdsNPrachInfoList *rsrp_ThresholdsPrachInfoList;
/// NPRACH Parameters List
NPRACH_List_NB_t nprach_ParametersList;
} NPRACH_CONFIG_COMMON;
/// NPDSCH-ConfigCommon from 36.331 RRC spec
typedef struct {
///see TS 36.213 (16.2). \vr{[-60..50]}\n Provides the downlink reference-signal EPRE. The actual value in dBm.
int8_t nrs_Power;
} NPDSCH_CONFIG_COMMON;
typedef struct{
/// The base sequence of DMRS sequence in a cell for 3 tones transmission; see TS 36.211 [21, 10.1.4.1.2]. If absent, it is given by NB-IoT CellID mod 12. Value 12 is not used.
uint8_t threeTone_BaseSequence;
/// Define 3 cyclic shifts for the 3-tone case, see TS 36.211 [21, 10.1.4.1.2].
uint8_t threeTone_CyclicShift;
/// The base sequence of DMRS sequence in a cell for 6 tones transmission; see TS 36.211 [21, 10.1.4.1.2]. If absent, it is given by NB-IoT CellID mod 14. Value 14 is not used.
uint8_t sixTone_BaseSequence;
/// Define 4 cyclic shifts for the 6-tone case, see TS 36.211 [21, 10.1.4.1.2].
uint8_t sixTone_CyclicShift;
/// The base sequence of DMRS sequence in a cell for 12 tones transmission; see TS 36.211 [21, 10.1.4.1.2]. If absent, it is given by NB-IoT CellID mod 30. Value 30 is not used.
uint8_t twelveTone_BaseSequence;
}DMRS_CONFIG_t;
/// UL-ReferenceSignalsNPUSCH 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;
/// , see TS 36.211 (5.5.1.3). \vr{[0..29]}
uint8_t groupAssignmentNPUSCH;
} UL_REFERENCE_SIGNALS_NPUSCH_t;
/// PUSCH-ConfigCommon from 36.331 RRC spec.
typedef struct {
/// Number of repetitions for ACK/NACK HARQ response to NPDSCH containing Msg4 per NPRACH resource, see TS 36.213 [23, 16.4.2].
uint8_t ack_NACK_NumRepetitions_Msg4[3];
/// SRS SubframeConfiguration. See TS 36.211 [21, table 5.5.3.3-1]. Value sc0 corresponds to value 0, sc1 to value 1 and so on.
uint8_t srs_SubframeConfig;
/// Parameter: \f$N^{HO}_{RB}\f$, see TS 36.211 (5.3.4). \vr{[0..98]}
DMRS_CONFIG_t dmrs_Config;
/// Ref signals configuration
UL_REFERENCE_SIGNALS_NPUSCH_t ul_ReferenceSignalsNPUSCH;
} NPUSCH_CONFIG_COMMON;
typedef struct{
/// See TS 36.213 [23, 16.2.1.1], unit dBm.
uint8_t p0_NominalNPUSCH;
/// See TS 36.213 [23, 16.2.1.1] where al0 corresponds to 0, al04 corresponds to value 0.4, al05 to 0.5, al06 to 0.6, al07 to 0.7, al08 to 0.8, al09 to 0.9 and al1 corresponds to 1.
uint8_t alpha;
/// See TS 36.213 [23, 16.2.1.1]. Actual value = IE value * 2 [dB].
uint8_t deltaPreambleMsg3;
}UplinkPowerControlCommon_NB;
/* DL-GapConfig-NB-r13 */
typedef struct {
uint8_t dl_GapThreshold;
uint8_t dl_GapPeriodicity;
uint8_t dl_GapDurationCoeff;
} DL_GapConfig_NB;
typedef struct {
/// Cell ID
uint16_t Nid_cell;
/// 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;
/// indicates if node is a UE (NODE=2) or eNB (PRIMARY_CH=0).
uint8_t node_id;
/// Frequency index of CBMIMO1 card
uint8_t freq_idx;
/// RX Frequency for ExpressMIMO/LIME
uint32_t carrier_freq[4];
/// TX Frequency for ExpressMIMO/LIME
uint32_t carrier_freqtx[4];
/// RX gain for ExpressMIMO/LIME
uint32_t rxgain[4];
/// TX gain for ExpressMIMO/LIME
uint32_t txgain[4];
/// RF mode for ExpressMIMO/LIME
uint32_t rfmode[4];
/// RF RX DC Calibration for ExpressMIMO/LIME
uint32_t rxdc[4];
/// RF TX DC Calibration for ExpressMIMO/LIME
uint32_t rflocal[4];
/// RF VCO calibration for ExpressMIMO/LIME
uint32_t rfvcolocal[4];
/// Turns on second TX of CBMIMO1 card
uint8_t dual_tx;
/// flag to indicate SISO transmission
uint8_t mode1_flag;
/// Indicator that 20 MHz channel uses 3/4 sampling frequency
//uint8_t threequarter_fs;
/// Size of FFT
uint16_t ofdm_symbol_size;
/// 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;
/// Carrier offset in FFT buffer for first RE in PRB0
uint16_t first_carrier_offset;
/// 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 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;
/// NPRACH Config Common (from 36-331 RRC spec)
NPRACH_CONFIG_COMMON nprach_config_common;
/// NPDSCH Config Common (from 36-331 RRC spec)
NPDSCH_CONFIG_COMMON npdsch_config_common;
/// PUSCH Config Common (from 36-331 RRC spec)
NPUSCH_CONFIG_COMMON npusch_config_common;
/// UL Power Control (from 36-331 RRC spec)
UplinkPowerControlCommon_NB ul_power_control_config_common;
/// DL Gap
DL_GapConfig_NB DL_gap_config;
/// 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;
int eutra_band;
uint32_t dl_CarrierFreq;
uint32_t ul_CarrierFreq;
uint8_t CE;// CE level to determine the NPRACH Configuration
} NB_DL_FRAME_PARMS;
/*
* 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.c
* \brief Implementation of eNB procedures from 36.213 LTE specifications
* \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
* \note
* \warning
*/
//NB-IoT test
#include "openair2/PHY_INTERFACE/IF_Module_nb_iot.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
#ifdef EMOS
#include "SCHED/phy_procedures_emos.h"
#endif
//#define DEBUG_PHY_PROC (Already defined in cmake)
//#define DEBUG_ULSCH
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/defs.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
#if defined(FLEXRAN_AGENT_SB_IF)
//Agent-related headers
#include "ENB_APP/flexran_agent_extern.h"
#include "ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h"
#include "LAYER2/MAC/flexran_agent_mac_proto.h"
#endif
//#define DIAG_PHY
#define NS_PER_SLOT 500000
#define PUCCH 1
void exit_fun(const char* s);
extern int exit_openair;
struct timespec start_fh, start_fh_prev;
int start_fh_sf, start_fh_prev_sf;
// Fix per CC openair rf/if device update
// extern openair0_device openair0;
unsigned char dlsch_input_buffer[2700] __attribute__ ((aligned(32)));
int eNB_sync_buffer0[640*6] __attribute__ ((aligned(32)));
int eNB_sync_buffer1[640*6] __attribute__ ((aligned(32)));
int *eNB_sync_buffer[2] = {eNB_sync_buffer0, eNB_sync_buffer1};
extern uint16_t hundred_times_log10_NPRB[100];
unsigned int max_peak_val;
int max_sync_pos;
int harq_pid_updated[NUMBER_OF_UE_MAX][8] = {{0}};
int harq_pid_round[NUMBER_OF_UE_MAX][8] = {{0}};
//DCI_ALLOC_t dci_alloc[8];
#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif
#if defined(SMBV)
extern const char smbv_fname[];
extern unsigned short config_frames[4];
extern uint8_t smbv_frame_cnt;
#endif
#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif
void NB_phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type)
{
//RX processing for ue-specific resources (i
UNUSED(r_type);
uint32_t ret=0,i,j,k;
uint32_t harq_pid, harq_idx, round;
int sync_pos;
uint16_t rnti=0;
uint8_t access_mode;
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
const int subframe = proc->subframe_rx;
const int frame = proc->frame_rx;
int offset = eNB->CC_id;//(proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1;
/*NB-IoT IF module Common setting*/
UL_IND_t UL_Info;
UL_Info.module_id = eNB->Mod_id;
UL_Info.CC_id = eNB->CC_id;
UL_Info.frame = frame;
UL_Info.subframe = subframe;
T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
eNB->frame_parms.samples_per_tti * 4));
//if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 );
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe);
LOG_D(PHY,"[eNB %d] Frame %d: Set the Common part in UL_IND\n",eNB->Mod_id,frame);
#endif
//check if any RB using in this UL subframe
eNB->rb_mask_ul[0]=0;
eNB->rb_mask_ul[1]=0;
eNB->rb_mask_ul[2]=0;
eNB->rb_mask_ul[3]=0;
// Check for active processes in current subframe
// NB-IoT subframe2harq_pid is in dci_tools, always set the frame type to FDD, this would become simpler.
harq_pid = subframe2harq_pid(fp,frame,subframe);
// delete the cba
// delete the srs
/*Loop over the UE, i is the UE ID */
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
// delete srs
// delete Pucch procedure
// check for Msg3
if (eNB->mac_enabled==1) {
if (eNB->UE_stats[i].mode == RA_RESPONSE) {
/*Process Msg3 TODO*/
//process_Msg3(eNB,proc,i,harq_pid);
}
}
eNB->pusch_stats_rb[i][(frame*10)+subframe] = -63;
eNB->pusch_stats_round[i][(frame*10)+subframe] = 0;
eNB->pusch_stats_mcs[i][(frame*10)+subframe] = -63;
/*Check if this UE is has ULSCH scheduling*/
if ((eNB->ulsch[i]) &&
(eNB->ulsch[i]->rnti>0) &&
(eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) {
// UE is has ULSCH scheduling
round = eNB->ulsch[i]->harq_processes[harq_pid]->round;
/*NB-IoT The nb_rb always set to 1 */
for (int rb=0;
rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
rb++)
{
int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
}
/*Log for what kind of the ULSCH Reception*/
if (eNB->ulsch[i]->Msg3_flag == 1) {
LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n",
eNB->Mod_id,
frame,
subframe,
eNB->UE_stats[i].sector);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1);
} else {
LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n",
eNB->Mod_id,
frame,
subframe,
i,
mode_string[eNB->UE_stats[i].mode]);
}
/*Calculate for LTE C-RS*/
//nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
//eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +nPRS)%12;
if (fp->frame_type == FDD ) {
int sf = (subframe<4) ? (subframe+6) : (subframe-4);
/*After Downlink Data transmission, simply have a notice to received ACK from PUCCH, I think it's not use for now */
if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission
eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
} else {
eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
}
}
LOG_D(PHY,
"[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, mcs %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d), O_ACK %d \n",
eNB->Mod_id,harq_pid,frame,subframe,
eNB->ulsch[i]->harq_processes[harq_pid]->dci_alloc,
eNB->ulsch[i]->harq_processes[harq_pid]->rar_alloc,
eNB->ulsch[i]->harq_processes[harq_pid]->round,
eNB->ulsch[i]->harq_processes[harq_pid]->first_rb,
eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb,
eNB->ulsch[i]->harq_processes[harq_pid]->mcs,
eNB->ulsch[i]->harq_processes[harq_pid]->TBS,
eNB->ulsch[i]->harq_processes[harq_pid]->rvidx,
eNB->ulsch[i]->cyclicShift,
eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2,
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK);
eNB->pusch_stats_rb[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->round;
eNB->pusch_stats_mcs[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->mcs;
start_meas(&eNB->ulsch_demodulation_stats);
if (eNB->abstraction_flag==0) {
rx_ulsch(eNB,proc,
eNB->UE_stats[i].sector, // this is the effective sector id
i,
eNB->ulsch,
0);
}
#ifdef PHY_ABSTRACTION
else {
rx_ulsch_emul(eNB,proc,
eNB->UE_stats[i].sector, // this is the effective sector id
i);
}
#endif
stop_meas(&eNB->ulsch_demodulation_stats);
start_meas(&eNB->ulsch_decoding_stats);
if (eNB->abstraction_flag == 0) {
ret = ulsch_decoding(eNB,proc,
i,
0, // control_only_flag
eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI,
eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
}
#ifdef PHY_ABSTRACTION
else {
ret = ulsch_decoding_emul(eNB,
proc,
i,
&rnti);
}
#endif
stop_meas(&eNB->ulsch_decoding_stats);
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n",
eNB->Mod_id,harq_pid,
frame,subframe,
eNB->ulsch[i]->rnti,
dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]),
dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]),
eNB->UE_stats[i].UL_rssi[0],
eNB->UE_stats[i].UL_rssi[1],
eNB->measurements->n0_power_dB[0],
eNB->measurements->n0_power_dB[1],
eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1],
ret);
//compute the expected ULSCH RX power (for the stats)
eNB->ulsch[(uint32_t)i]->harq_processes[harq_pid]->delta_TF =
get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered
eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d Clearing subframe_scheduling_flag\n",
eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid);
#endif
eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) {
#ifdef DEBUG_PHY_PROC
//if (((frame%10) == 0) || (frame < 50))
print_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL);
#endif
extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,
eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,
&eNB->UE_stats[i],
fp->N_RB_DL,
&rnti, &access_mode);
eNB->UE_stats[i].rank = eNB->ulsch[i]->harq_processes[harq_pid]->o_RI[0];
}
if (eNB->ulsch[i]->Msg3_flag == 1)
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
if (ret == (1+MAX_TURBO_ITERATIONS))
{
T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(i), T_INT(eNB->ulsch[i]->rnti),
T_INT(harq_pid));
eNB->UE_stats[i].ulsch_round_errors[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 0;
eNB->ulsch[i]->harq_processes[harq_pid]->round++;
LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->round);
if (eNB->ulsch[i]->Msg3_flag == 1)
{
LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n",
eNB->Mod_id,
eNB->CC_id,
frame,subframe, i,
eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
fp->maxHARQ_Msg3Tx-1);
/*dump_ulsch(eNB,proc,i);
exit(-1);*/
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n",
eNB->Mod_id,harq_pid,
frame,subframe,
eNB->ulsch[i]->rnti,
dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]),
dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]),
eNB->UE_stats[i].UL_rssi[0],
eNB->UE_stats[i].UL_rssi[1],
eNB->measurements->n0_power_dB[0],
eNB->measurements->n0_power_dB[1],
eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1],
ret);
/*In NB-IoT MSG3 */
// activate retransmission for Msg3 (signalled to UE PHY by DCI
eNB->ulsch[(uint32_t)i]->Msg3_active = 1;
/* Need to check the procedure for NB-IoT retransmission
get_Msg3_alloc_ret(fp,subframe,frame,&eNB->ulsch[i]->Msg3_frame,&eNB->ulsch[i]->Msg3_subframe);
mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, eNB->ulsch[i]->rnti,eNB->ulsch[i]->Msg3_frame, eNB->ulsch[i]->Msg3_subframe);
*/
T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
T_INT(i), T_INT(eNB->ulsch[i]->rnti), T_INT(0 /* 0 is for retransmission*/),
T_INT(eNB->ulsch[i]->Msg3_frame), T_INT(eNB->ulsch[i]->Msg3_subframe));
LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
} // This is Msg3 error
else
{ //normal ULSCH
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n",
eNB->Mod_id,harq_pid,
frame,subframe, i,
eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
eNB->ulsch[i]->Mlimit,
eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1]);
#if defined(MESSAGE_CHART_GENERATOR_PHY)
MSC_LOG_RX_DISCARDED_MESSAGE(
MSC_PHY_ENB,MSC_PHY_UE,
NULL,0,
"%05u:%02u ULSCH received rnti %x harq id %u round %d",
frame,subframe,
eNB->ulsch[i]->rnti,harq_pid,
eNB->ulsch[i]->harq_processes[harq_pid]->round-1
);
#endif
if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit)
{
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n",
eNB->Mod_id,harq_pid,
frame,subframe, i,
eNB->ulsch[i]->Mlimit);
eNB->ulsch[i]->harq_processes[harq_pid]->round=0;
eNB->ulsch[i]->harq_processes[harq_pid]->phich_active=0;
eNB->UE_stats[i].ulsch_errors[harq_pid]++;
eNB->UE_stats[i].ulsch_consecutive_errors++;
/*if (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb > 20) {
dump_ulsch(eNB,proc,i);
exit(-1);
}*/
// indicate error to MAC
if (eNB->mac_enabled == 1)
{
//instead rx_sdu to report NAK to MAC
UL_Info.UL_SPEC_Info[i].rntiP= eNB->ulsch[i]->rnti;
UL_Info.UL_SPEC_Info[i].sdu = NULL;
UL_Info.UL_SPEC_Info[i].sdu_lenP = 0;
UL_Info.UL_SPEC_Info[i].harq_pidP = harq_pid;
UL_Info.UL_SPEC_Info[i].msg3_flagP = &eNB->ulsch[i]->Msg3_flag;
UL_Info.UL_SPEC_Info[i].NAK=1;
UL_Info.UE_NUM++;
}
}
}
} // ulsch in error
else {
T(T_ENB_PHY_ULSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(i), T_INT(eNB->ulsch[i]->rnti),
T_INT(harq_pid));
// Delete MSG3 log for the PHICH
#if defined(MESSAGE_CHART_GENERATOR_PHY)
MSC_LOG_RX_MESSAGE(
MSC_PHY_ENB,MSC_PHY_UE,
NULL,0,
"%05u:%02u ULSCH received rnti %x harq id %u",
frame,subframe,
eNB->ulsch[i]->rnti,harq_pid
);
#endif
for (j=0; j<fp->nb_antennas_rx; j++)
//this is the RSSI per RB
eNB->UE_stats[i].UL_rssi[j] =
dB_fixed(eNB->pusch_vars[i]->ulsch_power[j]*
(eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb*12)/
fp->ofdm_symbol_size) -
eNB->rx_total_gain_dB -
hundred_times_log10_NPRB[eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb-1]/100 -
get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100;
//for NB-IoT PHICH not work
/*eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 1;*/
eNB->ulsch[i]->harq_processes[harq_pid]->round = 0;
eNB->UE_stats[i].ulsch_consecutive_errors = 0;
if (eNB->ulsch[i]->Msg3_flag == 1)
{
if (eNB->mac_enabled==1)
{
LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
eNB->Mod_id,frame,harq_pid,i);
if (eNB->mac_enabled)
{
// store successful MSG3 in UL_Info instead rx_sdu
UL_Info.UL_SPEC_Info[i].rntiP= eNB->ulsch[i]->rnti;
UL_Info.UL_SPEC_Info[i].sdu = eNB->ulsch[i]->harq_processes[harq_pid]->b;
UL_Info.UL_SPEC_Info[i].sdu_lenP = eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3;
UL_Info.UL_SPEC_Info[i].harq_pidP = harq_pid;
UL_Info.UL_SPEC_Info[i].msg3_flagP = &eNB->ulsch[i]->Msg3_flag;
UL_Info.UE_NUM++;
}
/* Need check if this needed in NB-IoT
// one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
if (eNB->ulsch[i]->Msg3_flag == 0 ) {
eNB->UE_stats[i].mode = PRACH;
mac_xface->cancel_ra_proc(eNB->Mod_id,
eNB->CC_id,
frame,
eNB->UE_stats[i].crnti);
mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
} // Msg3_flag == 0*/
} // mac_enabled==1
eNB->UE_stats[i].mode = PUSCH;
eNB->ulsch[i]->Msg3_flag = 0;
LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",eNB->Mod_id,frame,subframe,i);
/*Init HARQ parameters, need to check*/
for (k=0; k<8; k++) { //harq_processes
for (j=0; j<eNB->dlsch[i][0]->Mlimit; j++) {
eNB->UE_stats[i].dlsch_NAK[k][j]=0;
eNB->UE_stats[i].dlsch_ACK[k][j]=0;
eNB->UE_stats[i].dlsch_trials[k][j]=0;
}
eNB->UE_stats[i].dlsch_l2_errors[k]=0;
eNB->UE_stats[i].ulsch_errors[k]=0;
eNB->UE_stats[i].ulsch_consecutive_errors=0;
for (j=0; j<eNB->ulsch[i]->Mlimit; j++) {
eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0;
eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
eNB->UE_stats[i].ulsch_round_errors[k][j]=0;
eNB->UE_stats[i].ulsch_round_fer[k][j]=0;
}
}
eNB->UE_stats[i].dlsch_sliding_cnt=0;
eNB->UE_stats[i].dlsch_NAK_round0=0;
eNB->UE_stats[i].dlsch_mcs_offset=0;
} // Msg3_flag==1
else { // Msg3_flag == 0
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3);
for (j=0; j<eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3; j++)
LOG_T(PHY,"%x.",eNB->ulsch[i]->harq_processes[harq_pid]->b[j]);
LOG_T(PHY,"\n");
#endif
#endif
if (eNB->mac_enabled==1)
{
// store successful Uplink data in UL_Info instead rx_sdu
UL_Info.UL_SPEC_Info[i].rntiP= eNB->ulsch[i]->rnti;
UL_Info.UL_SPEC_Info[i].sdu = eNB->ulsch[i]->harq_processes[harq_pid]->b;
UL_Info.UL_SPEC_Info[i].sdu_lenP = eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3;
UL_Info.UL_SPEC_Info[i].harq_pidP = harq_pid;
UL_Info.UL_SPEC_Info[i].msg3_flagP = NULL;
UL_Info.UE_NUM++;
#ifdef LOCALIZATION
start_meas(&eNB->localization_stats);
aggregate_eNB_UE_localization_stats(eNB,i,frame,subframe,get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100);
stop_meas(&eNB->localization_stats);
#endif
} // mac_enabled==1
} // Msg3_flag == 0
// estimate timing advance for MAC
if (eNB->abstraction_flag == 0)
{
sync_pos = lte_est_timing_advance_pusch(eNB,i);
eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
}
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n",
eNB->Mod_id,
frame, subframe,
i,
eNB->UE_stats[i].timing_advance_update);
#endif
} // ulsch not in error
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id,
eNB->dlsch[i][0]->rnti,
frame,subframe,
i);
#endif
// Process HARQ only in NPUSCH
/*process_HARQ_feedback(i,
eNB,proc,
1, // pusch_flag
0,
0,
0);*/
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d] Frame %d subframe %d, sect %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n",
eNB->Mod_id,frame,subframe,
eNB->UE_stats[i].sector,
harq_pid,
i,
ret,
eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status,
eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1],
eNB->UE_stats[i].ulsch_errors[harq_pid],
eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]);
#endif
// dump stats to VCD
if (i==0) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS0+harq_pid,eNB->pusch_stats_mcs[0][(frame*10)+subframe]);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB0+harq_pid,eNB->pusch_stats_rb[0][(frame*10)+subframe]);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND0+harq_pid,eNB->pusch_stats_round[0][(frame*10)+subframe]);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->pusch_vars[0]->ulsch_power[0]));
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES0+harq_pid,ret);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN0+harq_pid,(frame*10)+subframe);
}
} // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
//store the parameter to determine if UL failure or not
UL_Info.UL_SPEC_Info[i].ulsch_consecutive_errors = eNB->UE_stats[i].ulsch_consecutive_errors;
// update ULSCH statistics for tracing
if ((frame % 100 == 0) && (subframe == 4)) {
for (harq_idx=0; harq_idx<8; harq_idx++) {
for (round=0; round<eNB->ulsch[i]->Mlimit; round++) {
if ((eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round] -
eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]) != 0) {
eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] =
(100*(eNB->UE_stats[i].ulsch_round_errors[harq_idx][round] -
eNB->UE_stats[i].ulsch_round_errors_last[harq_idx][round]))/
(eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round] -
eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]);
} else {
eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0;
}
eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round] =
eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round];
eNB->UE_stats[i].ulsch_round_errors_last[harq_idx][round] =
eNB->UE_stats[i].ulsch_round_errors[harq_idx][round];
}
}
}
if ((frame % 100 == 0) && (subframe==4)) {
eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS -
eNB->UE_stats[i].total_TBS_last);
eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS;
}
} // loop i=0 ... NUMBER_OF_UE_MAX-1
if (eNB->abstraction_flag == 0) {
lte_eNB_I0_measurements(eNB,
subframe,
0,
eNB->first_run_I0_measurements);
eNB->first_run_I0_measurements = 0;
}
#ifdef PHY_ABSTRACTION
else {
lte_eNB_I0_measurements_emul(eNB,
0);
}
#endif
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 );
stop_meas(&eNB->phy_proc_rx);
/*Exact not here, but use to debug*/
UL_indication(UL_Info);
}
#undef DEBUG_PHY_PROC
void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
eNB_rxtx_proc_t *proc,
PHY_VARS_RN *rn,
int do_meas)
{
}
\ No newline at end of file
#include "openair2/PHY_INTERFACE/IF_Module_nb_iot.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/proto_nb_iot.h"
void UL_indication(UL_IND_t UL_INFO)
{
int i=0;
UL_INFO.test=1;
if(UL_INFO.test == 1)
{
/*If there is a preamble, do the initiate RA procedure*/
if(UL_INFO.preamble_index && UL_INFO.timing_offset)
NB_initiate_ra_proc(UL_INFO.module_id,UL_INFO.CC_id,UL_INFO.frame,UL_INFO.preamble_index,UL_INFO.timing_offset,UL_INFO.subframe);
/*If there is a Uplink SDU (even MSG3, NAK) need to send to MAC*/
for(i=0;i<UL_INFO.UE_NUM;i++)
{
/*For MSG3, Normal Uplink Data, NAK*/
if(UL_INFO.UL_SPEC_Info[i].rntiP)
NB_rx_sdu(UL_INFO.module_id,
UL_INFO.CC_id,
UL_INFO.frame,
UL_INFO.subframe,
UL_INFO.UL_SPEC_Info[i].rntiP,
UL_INFO.UL_SPEC_Info[i].sdu,
UL_INFO.UL_SPEC_Info[i].sdu_lenP,
UL_INFO.UL_SPEC_Info[i].harq_pidP,
UL_INFO.UL_SPEC_Info[i].msg3_flagP
);
}
}
NB_eNB_dlsch_ulsch_scheduler(UL_INFO.module_id,0,UL_INFO.frame,UL_INFO.subframe);
}
void Schedule_Response(Sched_Rsp_t Sched_INFO){
//todo
}
\ No newline at end of file
......@@ -30,7 +30,6 @@
* @{
*/
/*@}*/
#ifndef __LAYER2_MAC_DEFS_NB_IOT_H__
#define __LAYER2_MAC_DEFS_NB_IOT_H__
#ifdef USER_MODE
......@@ -47,7 +46,6 @@
#include "RACH-ConfigCommon-NB-r13.h"
#include "MasterInformationBlock-NB.h"
#include "BCCH-BCH-Message-NB.h"
//#ifdef PHY_EMUL
//#include "SIMULATION/PHY_EMULATION/impl_defs.h"
//#endif
......@@ -55,15 +53,11 @@
* @ingroup _oai2
* @{
*/
/*! \brief Downlink SCH PDU Structure */
typedef struct {
int8_t payload[8][SCH_PAYLOAD_SIZE_MAX];
uint16_t Pdu_size[8];
} __attribute__ ((__packed__)) DLSCH_PDU_NB;
/*! \brief eNB template for UE context information */
typedef struct {
/// C-RNTI of UE
......@@ -76,81 +70,56 @@ typedef struct {
boolean_t ul_active;
/// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received)
boolean_t configured;
/// MCS from last scheduling
//Modify uint8_t mcs[8];
/// TPC from last scheduling
//Delete uint8_t oldTPC[8];
// PHY interface info
/// DCI format for DLSCH
uint16_t DLSCH_dci_fmt;
/// Current Aggregation Level for DCI
uint8_t DCI_aggregation_min;
/// size of DLSCH size in bit
uint8_t DLSCH_dci_size_bits;
/// DCI buffer for DLSCH
/* rounded to 32 bits unit (actual value should be 8 due to the logic
* of the function generate_dci0) */
//Modifyuint8_t DLSCH_DCI[8][(((MAX_DCI_SIZE_BITS)+31)>>5)*4];
/// Number of Allocated RBs for DL after scheduling (prior to frequency allocation)
//Delete uint16_t nb_rb[8]; // num_max_harq
/// Number of Allocated RBs for UL after scheduling (prior to frequency allocation)
//Delete uint16_t nb_rb_ul[8]; // num_max_harq
/// Number of Allocated RBs by the ulsch preprocessor
//Delete uint8_t pre_allocated_nb_rb_ul;
/// index of Allocated RBs by the ulsch preprocessor
//Delete int8_t pre_allocated_rb_table_index_ul;
/// total allocated RBs
//Delete int8_t total_allocated_rbs;
/// pre-assigned MCS by the ulsch preprocessor
uint8_t pre_assigned_mcs_ul;
/// assigned MCS by the ulsch scheduler
uint8_t assigned_mcs_ul;
/// DCI buffer for ULSCH
/* rounded to 32 bits unit (actual value should be 8 due to the logic
* of the function generate_dci0) */
//Modify uint8_t ULSCH_DCI[8][(((MAX_DCI_SIZE_BITS)+31)>>5)*4];
/// DL DAI
//Delete uint8_t DAI;
/// UL DAI
//Delete uint8_t DAI_ul[10];
/// UL Scheduling Request Received
//Delete uint8_t ul_SR;
/// Resource Block indication for each sub-band in MU-MIMO
//Delete uint8_t rballoc_subband[8][50];
// Logical channel info for link with RLC
/// Last received UE BSR info for each logical channel group id
uint8_t bsr_info[MAX_NUM_LCGID];
/// LCGID mapping
//Delete long lcgidmap[11];
/// phr information, received from DPR MAC control element
int8_t phr_info_DPR;
int8_t phr_info;
/// phr information, received from DPR MAC control element
int8_t phr_info_configured_DPR;
int8_t phr_info_configured;
///dl buffer info
uint32_t dl_buffer_info[MAX_NUM_LCID];
/// total downlink buffer info
......@@ -167,7 +136,6 @@ typedef struct {
uint8_t dl_buffer_head_sdu_is_segmented[MAX_NUM_LCID];
/// size of remaining size to send for the downlink head SDU
uint32_t dl_buffer_head_sdu_remaining_size_to_send[MAX_NUM_LCID];
/// total uplink buffer size
uint32_t ul_total_buffer;
/// uplink buffer creation time for each LCID
......@@ -176,24 +144,17 @@ typedef struct {
uint32_t ul_buffer_creation_time_max;
/// uplink buffer size per LCID
uint32_t ul_buffer_info[MAX_NUM_LCGID];
/// UE tx power
int32_t ue_tx_power;
/// stores the frame where the last TPC was transmitted
//Delete uint32_t pusch_tpc_tx_frame;
//Delete uint32_t pusch_tpc_tx_subframe;
//Delete uint32_t pucch_tpc_tx_frame;
//Delete uint32_t pucch_tpc_tx_subframe;
//Delete eNB_UE_estimated_distances distance;
} UE_TEMPLATE_NB;
/*! \brief eNB statistics for the connected UEs*/
typedef struct {
/// CRNTI of UE
rnti_t crnti; ///user id (rnti) of connected UEs
// rrc status
......@@ -212,7 +173,6 @@ typedef struct {
uint16_t ncce_used;
/// total avilable nccc for a retransmission: num control channel element
uint16_t ncce_used_retx;
// mcs1 before the rate adaptaion
uint8_t dlsch_mcs1;
/// Target mcs2 after rate-adaptation
......@@ -225,7 +185,6 @@ typedef struct {
uint32_t total_rbs_used;
// total rb used for retransmission
uint32_t total_rbs_used_retx;
/// TX
/// Num pkt
uint32_t num_pdu_tx[NB_RB_MAX];
......@@ -235,7 +194,6 @@ typedef struct {
uint32_t num_retransmission;
/// instantaneous tx throughput for each TTI
// uint32_t tti_throughput[NB_RB_MAX];
/// overall
//
uint32_t dlsch_bitrate;
......@@ -251,19 +209,15 @@ typedef struct {
uint64_t total_sdu_bytes;
// total MAC pdu bytes
uint64_t total_pdu_bytes;
// total num pdu
uint32_t total_num_pdus;
//
// uint32_t avg_pdu_size;
/// RX
/// preassigned mcs after rate adaptation
uint8_t ulsch_mcs1;
/// adjusted mcs
uint8_t ulsch_mcs2;
/// estimated average pdu inter-departure time
uint32_t avg_pdu_idt;
/// estimated average pdu size
......@@ -271,10 +225,8 @@ typedef struct {
///
uint32_t aggregated_pdu_size;
uint32_t aggregated_pdu_arrival;
/// uplink transport block size
uint32_t ulsch_TBS;
/// total rb used for a new uplink transmission
uint32_t num_retransmission_rx;
/// total rb used for a new uplink transmission
......@@ -287,7 +239,6 @@ typedef struct {
int32_t normalized_rx_power;
/// target rx power
int32_t target_rx_power;
/// num rx pdu
uint32_t num_pdu_rx[NB_RB_MAX];
/// num bytes rx
......@@ -296,7 +247,6 @@ typedef struct {
// uint32_t tti_goodput[NB_RB_MAX];
/// errors
uint32_t num_errors_rx;
uint64_t overhead_bytes_rx;
/// headers+ CE + padding bytes for a MAC PDU
uint64_t total_overhead_bytes_rx;
......@@ -315,21 +265,16 @@ typedef struct {
uint32_t total_num_pdus_rx;
/// num of error pdus
uint32_t total_num_errors_rx;
} eNB_UE_STATS_NB;
/*! \brief scheduling control information set through an API (not used)*/
typedef struct {
///UL transmission bandwidth in RBs
uint8_t ul_bandwidth[MAX_NUM_LCID];
///DL transmission bandwidth in RBs
uint8_t dl_bandwidth[MAX_NUM_LCID];
//To do GBR bearer
uint8_t min_ul_bandwidth[MAX_NUM_LCID];
uint8_t min_dl_bandwidth[MAX_NUM_LCID];
///aggregated bit rate of non-gbr bearer per UE
uint64_t ue_AggregatedMaximumBitrateDL;
///aggregated bit rate of non-gbr bearer per UE
......@@ -338,13 +283,9 @@ typedef struct {
//Delete uint16_t cqiSchedInterval;
///Contention resolution timer used during random access
uint8_t mac_ContentionResolutionTimer;
//Delete uint16_t max_allowed_rbs[MAX_NUM_LCID];
uint8_t max_mcs[MAX_NUM_LCID];
uint16_t priority[MAX_NUM_LCID];
// resource scheduling information
uint8_t harq_pid[MAX_NUM_CCs];
uint8_t round[MAX_NUM_CCs];
......@@ -362,8 +303,6 @@ typedef struct {
int32_t ul_out_of_sync;
int32_t phr_received;// received from Msg3 MAC Control Element
} UE_sched_ctrl_NB;
/*! \brief UE list used by eNB to order UEs/CC for scheduling*/
typedef struct {
/// DLSCH pdu
......@@ -373,20 +312,14 @@ typedef struct {
/// DCI template and MAC connection for RA processes
int pCC_id[NUMBER_OF_UE_MAX];
/// Delete sorted downlink component carrier for the scheduler
/// Delete number of downlink active component carrier
/// Delete sorted uplink component carrier for the scheduler
/// Delete number of uplink active component carrier
/// Delete number of downlink active component carrier
/// eNB to UE statistics
eNB_UE_STATS_NB eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
/// scheduling control info
UE_sched_ctrl_NB UE_sched_ctrl[NUMBER_OF_UE_MAX];
int next[NUMBER_OF_UE_MAX];
int head;
int next_ul[NUMBER_OF_UE_MAX];
......@@ -395,9 +328,6 @@ typedef struct {
int num_UEs;
boolean_t active[NUMBER_OF_UE_MAX];
} UE_list_NB_t;
/*!\brief Values of BCCH0 logical channel for MIB*/
#define BCCH0 11 // MIB-NB
/*!\brief Values of BCCH1 logical channel for SIBs */
......@@ -415,9 +345,76 @@ typedef struct {
/*!\brief DTCH1 DRB1 logical channel */
#define DTCH1 5 // DRB1
// DLSCH LCHAN ID all the same as NB-IoT
/*!\brief DCI PDU filled by MAC for the PHY */
/*
* eNB part
*/
/*!\brief DCI PDU filled by MAC for the PHY */
/*
* UE/ENB common part
*/
/*!\brief MAC header of Random Access Response for Random access preamble identifier (RAPID) for NB-IoT */
typedef struct {
uint8_t RAPID:6;
uint8_t T:1;
uint8_t E:1;
} __attribute__((__packed__))RA_HEADER_RAPID_NB;
/*!\brief MAC header of Random Access Response for backoff indicator (BI) for NB-IoT*/
typedef struct {
uint8_t BI:4;
uint8_t R:2;
uint8_t T:1;
uint8_t E:1;
} __attribute__((__packed__))RA_HEADER_BI_NB;
/*Seems not to do the packed of RAR pdu*/
/*!\brief MAC subheader short with 7bit Length field */
typedef struct {
uint8_t LCID:5; // octet 1 LSB
uint8_t E:1;
uint8_t R:2; // octet 1 MSB
uint8_t L:7; // octet 2 LSB
uint8_t F:1; // octet 2 MSB
} __attribute__((__packed__))SCH_SUBHEADER_SHORT_NB;
/*!\brief MAC subheader long with 15bit Length field */
typedef struct {
uint8_t LCID:5; // octet 1 LSB
uint8_t E:1;
uint8_t R:2; // octet 1 MSB
uint8_t L_MSB:7;
uint8_t F:1; // octet 2 MSB
uint8_t L_LSB:8;
uint8_t padding;
} __attribute__((__packed__))SCH_SUBHEADER_LONG_NB;
/*!\brief MAC subheader short without length field */
typedef struct {
uint8_t LCID:5;
uint8_t E:1;
uint8_t R:2;
} __attribute__((__packed__))SCH_SUBHEADER_FIXED_NB;
/*!\brief mac control element: short buffer status report for a specific logical channel group ID*/
typedef struct {
uint8_t Buffer_size:6; // octet 1 LSB
uint8_t LCGID:2; // octet 1 MSB
} __attribute__((__packed__))BSR_SHORT_NB;
/*!\TRUNCATED BSR and Long BSR is not supported in NB-IoT*/
/*!\brief mac control element: timing advance */
typedef struct {
uint8_t TA:6;
uint8_t R:2;
} __attribute__((__packed__))TIMING_ADVANCE_CMD_NB;
/*!\brief mac control element: power headroom report */
typedef struct {
uint8_t PH:6;
uint8_t R:2;
} __attribute__((__packed__))POWER_HEADROOM_CMD_NB;
typedef struct {
uint8_t Num_ue_spec_dci ;
uint8_t Num_common_dci ;
......@@ -425,19 +422,13 @@ typedef struct {
uint32_t num_pdcch_symbols;
DCI_ALLOC_t dci_alloc[NUM_DCI_MAX] ;
} DCI_PDU_NB;
typedef struct {
uint8_t payload[BCCH_PAYLOAD_SIZE_MAX] ;
} __attribute__((__packed__))BCCH_PDU_NB;
/*! \brief CCCH payload */
typedef struct {
uint8_t payload[CCCH_PAYLOAD_SIZE_MAX] ;
} __attribute__((__packed__))CCCH_PDU_NB;
/*! \brief eNB template for the Random access information */
typedef struct {
/// Flag to indicate this process is active
......@@ -472,8 +463,8 @@ typedef struct {
rnti_t rnti;
/// RA RNTI allocated from received PRACH
uint16_t RA_rnti;
/// Delete Received preamble_index, use subcarrier index?
/// Re-use preamble_index, but it would be subcarrier index (0-47)
uint8_t preamble_index;
/// Received UE Contention Resolution Identifier
uint8_t cont_res_id[6];
/// Timing offset indicated by PHY
......@@ -481,7 +472,6 @@ typedef struct {
/// Timeout for RRC connection
int16_t RRC_timer;
} RA_TEMPLATE_NB;
/*! \brief eNB common channels */
typedef struct {
int physCellId;
......@@ -493,8 +483,6 @@ typedef struct {
RadioResourceConfigCommonSIB_NB_r13_t *radioResourceConfigCommon;
ARFCN_ValueEUTRA_r9_t ul_CarrierFreq;
struct MasterInformationBlock_NB__operationModeInfo_r13 operationModeInfo;
/// Outgoing DCI for PHY generated by eNB scheduler
DCI_PDU_NB DCI_pdu;
/// Outgoing BCCH pdu for PHY
......@@ -505,45 +493,26 @@ typedef struct {
CCCH_PDU_NB CCCH_pdu;
RA_TEMPLATE_NB RA_template[NB_RA_PROC_MAX];
/// Delete VRB map for common channels
/// Delete MBSFN SubframeConfig
/// Delete number of subframe allocation pattern available for MBSFN sync area
// #if defined(Rel10) || defined(Rel14)
/// Delete MBMS Flag
/// Delete Outgoing MCCH pdu for PHY
/// Delete MCCH active flag
/// Delete MCCH active flag
/// Delete MTCH active flag
/// Delete number of active MBSFN area
/// Delete MBSFN Area Info
/// Delete PMCH Config
/// Delete MBMS session info list
/// Delete Outgoing MCH pdu for PHY
// #endif
// #ifdef CBA
/// Delete number of CBA groups
/// Delete RNTI for each CBA group
/// Delete MCS for each CBA group
// #endif
}COMMON_channels_NB_t;
/*! \brief eNB overall statistics */
typedef struct {
/// num BCCH PDU per CC
......@@ -554,7 +523,6 @@ typedef struct {
uint32_t total_bcch_buffer;
/// BCCH MCS
uint32_t bcch_mcs;
/// num CCCH PDU per CC
uint32_t total_num_ccch_pdu;
/// BCCH buffer size
......@@ -563,7 +531,6 @@ typedef struct {
uint32_t total_ccch_buffertotal_ccch_buffer;
/// BCCH MCS
uint32_t ccch_mcs;
/// num active users
uint16_t num_dlactive_UEs;
/// available number of PRBs for a give SF fixed in 1 in NB-IoT
......@@ -586,7 +553,6 @@ typedef struct {
uint32_t total_dlsch_bytes_tx;
//
uint32_t total_dlsch_pdus_tx;
// here for RX
//
uint32_t ulsch_bitrate;
......@@ -594,23 +560,17 @@ typedef struct {
uint32_t ulsch_bytes_rx;
//
uint64_t ulsch_pdus_rx;
uint32_t total_ulsch_bitrate;
//
uint32_t total_ulsch_bytes_rx;
//
uint32_t total_ulsch_pdus_rx;
/// MAC agent-related stats
/// total number of scheduling decisions
int sched_decisions;
/// missed deadlines
int missed_deadlines;
} eNB_STATS_NB;
/*! \brief top level eNB MAC structure */
typedef struct {
///
......@@ -622,12 +582,9 @@ typedef struct {
/// Common cell resources
COMMON_channels_NB_t common_channels[MAX_NUM_CCs];
UE_list_NB_t UE_list;
///Delete subband bitmap configuration, no related CQI report
// / Modify CCE table used to build DCI scheduling information
int CCE_table[MAX_NUM_CCs][12];//180 khz for Anchor carrier
/// active flag for Other lcid
uint8_t lcid_active[NB_RB_MAX];
/// eNB stats
......@@ -648,12 +605,7 @@ typedef struct {
/// processing time of eNB DLSCH scheduler
time_stats_t schedule_dlsch; // include rlc_data_req + MAC header + preprocessor
/// Delete processing time of eNB MCH scheduler
/// processing time of eNB ULSCH reception
time_stats_t rx_ulsch_sdu; // include rlc_data_ind
} eNB_MAC_INST_NB;
#endif /*__LAYER2_MAC_DEFS_NB_IoT_H__ */
/*
* 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 eNB_scheduler_RA.c
* \brief primitives used for random access
* \author Navid Nikaein and Raymond Knopp
* \date 2010 - 2014
* \email: navid.nikaein@eurecom.fr
* \version 1.0
* @ingroup _mac
*/
#include "assertions.h"
#include "platform_types.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "msc.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/proto.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
//NB-IoT
#include "proto_nb_iot.h"
#include "defs_nb_iot.h"
#include "math.h"
#include "openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h"
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
#include "SIMULATION/TOOLS/defs.h" // for taus
#include "T.h"
void NB_schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP)
{
int CC_id;
eNB_MAC_INST_NB *eNB = &eNB_mac_inst_NB[module_idP];
RA_TEMPLATE_NB *RA_template;
unsigned char i,harq_pid,round;
int16_t rrc_sdu_length;
unsigned char lcid,offset;
int UE_id = -1;
unsigned short TBsize = -1;
unsigned short msg4_padding,msg4_post_padding,msg4_header;
DCI_PDU_NB *DCI_pdu;
// start_meas(&eNB->schedule_ra);
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu;
for (i=0; i<NB_RA_PROC_MAX; i++) {
RA_template = (RA_TEMPLATE_NB *)&eNB->common_channels[CC_id].RA_template[i];
if (RA_template->RA_active == TRUE) {
LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d RA %d is active (generate RAR %d, generate_Msg4 %d, wait_ack_Msg4 %d, rnti %x)\n",
module_idP,CC_id,i,RA_template->generate_rar,RA_template->generate_Msg4,RA_template->wait_ack_Msg4, RA_template->rnti);
if (RA_template->generate_rar == 1) {
LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI (proc %d), RA_active %d format 1A (%d,%d))\n",
module_idP, CC_id, frameP, subframeP,i,
RA_template->RA_active,
RA_template->RA_dci_fmt1,
RA_template->RA_dci_size_bits1);
//directly fill DCI Filed base on DCI Nq for RAR
((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->type=1;
((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->orderIndicator=0;
((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->Scheddly=1;//fixed delay approach?
((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->ResAssign=0;
((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0;//fixes?//fixes? base on CE levels?
((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->RepNum=0;//fixes? base on CE levels?
((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->Reserved=0;
((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->DCIRep=0;//fixes?
}
//New appoach for CCE allocaton, delete !CCE_allocation_infeasible..
else if (RA_template->generate_Msg4 == 1) {
// check for Msg4 Message
UE_id = find_UE_id(module_idP,RA_template->rnti);
if (UE_id == -1) { printf("%s:%d:%s: FATAL ERROR\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (Is_rrc_registered == 1) {//Fixed mac_rrc_data_req
// Get RRCConnectionSetup for Piggyback
rrc_sdu_length = mac_rrc_data_req(module_idP,
CC_id,
frameP,
CCCH,
1, // 1 transport block
&eNB->common_channels[CC_id].CCCH_pdu.payload[0],
ENB_FLAG_YES,
module_idP,
0); // not used in this case
if (rrc_sdu_length == -1) {
mac_xface->macphy_exit("[MAC][eNB Scheduler] CCCH not allocated\n");
return; // not reached
} else {
//msg("[MAC][eNB %d] Frame %d, subframeP %d: got %d bytes from RRC\n",module_idP,frameP, subframeP,rrc_sdu_length);
}
}
LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, Is_rrc_registered %d, rrc_sdu_length %d\n",
module_idP, CC_id, frameP, subframeP,UE_id, Is_rrc_registered,rrc_sdu_length);
if (rrc_sdu_length>0) {
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RA proc %d, RNTI %x)\n",
module_idP, CC_id, frameP, subframeP,i,RA_template->rnti);
// Compute MCS for 3 PRB
msg4_header = 1+6+1; // CR header, CR CE, SDU header
//need to fixed ndi & msc base on NB-IoT DCI for Msg4
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1;
if ((rrc_sdu_length+msg4_header) <= 22) {
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4;
TBsize = 22;
} else if ((rrc_sdu_length+msg4_header) <= 28) {
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5;
TBsize = 28;
} else if ((rrc_sdu_length+msg4_header) <= 32) {
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6;
TBsize = 32;
} else if ((rrc_sdu_length+msg4_header) <= 41) {
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7;
TBsize = 41;
} else if ((rrc_sdu_length+msg4_header) <= 49) {
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8;
TBsize = 49;
} else if ((rrc_sdu_length+msg4_header) <= 57) {
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9;
TBsize = 57;
}
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->type=1;
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->orderIndicator=0;
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->Scheddly=1;//fixed delay approach?
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->ResAssign=5;//fixed depend on mcs/tbs to Nsf
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->RepNum=1;//fixed base on CE levels
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->HARQackRes=0;//Avoid confict multiple Msg ACk
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->DCIRep=0;//fixed base on CE levels
}
}else if (RA_template->wait_ack_Msg4==1) {
// check HARQ status and retransmit if necessary
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n",
module_idP,CC_id,frameP,subframeP);
// Get candidate harq_pid from PHY
mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,openair_harq_RA);
if (round>0) {
//RA_template->wait_ack_Msg4++;
// we have to schedule a retransmission
((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1;
// if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,2,RA_template->rnti)) {
// add_ue_spec_dci(DCI_pdu,
// (void*)&RA_template->RA_alloc_pdu2[0],
// RA_template->rnti,
// RA_template->RA_dci_size_bytes2,
// 2,
// RA_template->RA_dci_size_bits2,
// RA_template->RA_dci_fmt2,
// 0);
// printf("MAC: msg4 retransmission for rnti %x (round %d) fsf %d/%d\n", RA_template->rnti, round, frameP, subframeP);
// }
}else
printf("MAC: msg4 retransmission for rnti %x (round %d) fsf %d/%d CCE allocation failed!\n", RA_template->rnti, round, frameP, subframeP);
LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n",
module_idP,CC_id,frameP,subframeP,RA_template->rnti);
} else {
/* msg4 not received
if ((round == 0) && (RA_template->wait_ack_Msg4>1){
remove UE instance across all the layers: mac_xface->cancel_RA();
}
*/
printf("MAC: msg4 acknowledged for rnti %x fsf %d/%d, let's configure it\n", RA_template->rnti, frameP, subframeP);
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_id,frameP,subframeP);
RA_template->wait_ack_Msg4=0;
RA_template->RA_active=FALSE;
UE_id = find_UE_id(module_idP,RA_template->rnti);
DevAssert( UE_id != -1 );
eNB_mac_inst_NB[module_idP].UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE;
}
}// RA_active
} // for i=0 .. N_RA_PROC-1
} // CC_id
// stop_meas(&eNB->schedule_ra);
}
/*This function should loop all over the preamble index*/
void NB_initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, uint16_t preamble_index,int16_t timing_offset,sub_frame_t subframeP)
{
uint8_t i;
uint8_t carrier_id = 0;/*The index of the UL carrier associated with the NPRACH, the carrier_id of the anchor carrier is 0*/
RA_TEMPLATE_NB *RA_template = (RA_TEMPLATE_NB *)&eNB_mac_inst_NB[module_idP].common_channels[CC_id].RA_template[0];
/*preamble index will be a subcarrier index (0-47)*/
LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,1);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,0);
/*May up to 48 RA Procdeure MAX at the moment*/
for (i=0; i<NB_RA_PROC_MAX; i++) {
if (RA_template[i].RA_active==FALSE &&
RA_template[i].wait_ack_Msg4 == 0) {
int loop = 0;
RA_template[i].RA_active=TRUE;
RA_template[i].generate_rar=1;
RA_template[i].generate_Msg4=0;
RA_template[i].wait_ack_Msg4=0;
RA_template[i].timing_offset=timing_offset;
/* TODO: find better procedure to allocate RNTI */
do {
RA_template[i].rnti = taus();
loop++;
} while (loop != 100 &&
/* TODO: this is not correct, the rnti may be in use without
* being in the MAC yet. To be refined.
*/
!(find_UE_id(module_idP, RA_template[i].rnti) == -1 &&
/* 1024 and 60000 arbirarily chosen, not coming from standard */
RA_template[i].rnti >= 1024 && RA_template[i].rnti < 60000));
if (loop == 100) { printf("%s:%d:%s: FATAL ERROR! contact the authors\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
//RA_template[i].RA_rnti = 1+subframeP+(10*f_id);
/*for NB-IoT, RA_rnti is counted in 36.321 5.1.4*/
RA_template[i].RA_rnti = 1+floor(frameP/4)+256*carrier_id;
RA_template[i].preamble_index = preamble_index;
LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Activating RAR generation for process %d, rnti %x, RA_active %d\n",
module_idP,CC_id,frameP,i,RA_template[i].rnti,
RA_template[i].RA_active);
return;
}
}
LOG_E(MAC,"[eNB %d][RAPROC] FAILURE: CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index);
}
/*
* 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 eNB_scheduler_dlsch.c
* \brief procedures related to eNB for the DLSCH transport channel
* \author Navid Nikaein and Raymond Knopp
* \date 2010 - 2014
* \email: navid.nikaein@eurecom.fr
* \version 1.0
* @ingroup _mac
*/
#include "assertions.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/proto.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
//NB-IoT
#include "defs_nb_iot.h"
#include "proto_nb_iot.h"
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
#include "SIMULATION/TOOLS/defs.h" // for taus
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
#include "T.h"
#define ENABLE_MAC_PAYLOAD_DEBUG
//#define DEBUG_eNB_SCHEDULER 1
uint8_t *NB_get_dlsch_sdu(
module_id_t module_idP,
int CC_id,
frame_t frameP,
rnti_t rntiP,
uint8_t TBindex
)
//------------------------------------------------------------------------------
{
int UE_id;
eNB_MAC_INST_NB *eNB=&eNB_mac_inst_NB[module_idP];
/*for SIBs*/
if (rntiP==SI_RNTI) {
LOG_D(MAC,"[eNB %d] CC_id %d Frame %d Get DLSCH sdu for BCCH \n", module_idP, CC_id, frameP);
return((unsigned char *)&eNB->common_channels[CC_id].BCCH_pdu.payload[0]);
}
UE_id = find_UE_id(module_idP,rntiP);
if (UE_id != -1) {
LOG_D(MAC,"[eNB %d] Frame %d: CC_id %d Get DLSCH sdu for rnti %x => UE_id %d\n",module_idP,frameP,CC_id,rntiP,UE_id);
return((unsigned char *)&eNB->UE_list.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]);
} else {
LOG_E(MAC,"[eNB %d] Frame %d: CC_id %d UE with RNTI %x does not exist\n", module_idP,frameP,CC_id,rntiP);
return NULL;
}
}
/*
* 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 eNB_scheduler_primitives.c
* \brief primitives used by eNB for BCH, RACH, ULSCH, DLSCH scheduling
* \author Navid Nikaein and Raymond Knopp
* \date 2010 - 2014
* \email: navid.nikaein@eurecom.fr
* \version 1.0
* @ingroup _mac
*/
#include "assertions.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/proto.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
//NB-IoT
#include "defs_nb_iot.h"
#include "proto_nb_iot.h"
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
/*TODO NB_mac_phy_remove_ue*/
int NB_rrc_mac_remove_ue(
module_id_t mod_idP,
rnti_t rntiP)
{
int i;
UE_list_NB_t *UE_list = &eNB_mac_inst_NB[mod_idP].UE_list;
int UE_id = find_UE_id(mod_idP,rntiP); //may should be changed
int pCC_id;
if (UE_id == -1) {
printf("MAC: cannot remove UE rnti %x\n", rntiP);
LOG_W(MAC,"NB_rrc_mac_remove_ue: UE %x not found\n", rntiP);
//NB_mac_phy_remove_ue(mod_idP, rntiP);
return 0;
}
pCC_id = UE_PCCID(mod_idP,UE_id);
printf("MAC: remove UE %d rnti %x\n", UE_id, rntiP);
LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",UE_id,pCC_id, rntiP);
//dump_ue_list(UE_list,0); //may should be changed
UE_list->active[UE_id] = FALSE;
UE_list->num_UEs--;
// clear all remaining pending transmissions no lcgid in NB-IoT
/*UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0] = 0;
UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1] = 0;
UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID2] = 0;
UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID3] = 0;*/
//UE_list->UE_template[pCC_id][UE_id].ul_SR = 0;
UE_list->UE_template[pCC_id][UE_id].rnti = NOT_A_RNTI;
UE_list->UE_template[pCC_id][UE_id].ul_active = FALSE;
eNB_ulsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI;
eNB_ulsch_info[mod_idP][pCC_id][UE_id].status = S_UL_NONE;
eNB_dlsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI;
eNB_dlsch_info[mod_idP][pCC_id][UE_id].status = S_DL_NONE;
//NB_mac_phy_remove_ue(mod_idP,rntiP);
// check if this has an RA process active
RA_TEMPLATE_NB *RA_template;
for (i=0;i<NB_RA_PROC_MAX;i++) {
RA_template = (RA_TEMPLATE_NB *)&eNB_mac_inst_NB[mod_idP].common_channels[pCC_id].RA_template[i];
if (RA_template->rnti == rntiP){
RA_template->RA_active=FALSE;
RA_template->generate_rar=0;
RA_template->generate_Msg4=0;
RA_template->wait_ack_Msg4=0;
RA_template->timing_offset=0;
RA_template->RRC_timer=20;
RA_template->rnti = 0;
//break;
}
}
return 0;
}
//------------------------------------------------------------------------------
DCI_PDU_NB *NB_get_dci_sdu(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframeP)
//------------------------------------------------------------------------------
{
return(&eNB_mac_inst_NB[module_idP].common_channels[CC_id].DCI_pdu);
}
//NB_UL_failure_indication... some of the used primitive haven't defined
/*
* 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 eNB_scheduler_ulsch.c
* \brief eNB procedures for the ULSCH transport channel
* \author Navid Nikaein and Raymond Knopp
* \date 2010 - 2014
* \email: navid.nikaein@eurecom.fr
* \version 1.0
* @ingroup _mac
*/
#include "assertions.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
//#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/proto.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
//NB-IoT
#include "LAYER2/MAC/defs_nb_iot.h"
#include "LAYER2/MAC/proto_nb_iot.h"
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
#include "T.h"
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
// This table holds the allowable PRB sizes for ULSCH transmissions
uint8_t rb_table[33] = {1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36,40,45,48,50,54,60,72,75,80,81,90,96,100};
void NB_rx_sdu(const module_id_t enb_mod_idP,
const int CC_idP,
const frame_t frameP,
const sub_frame_t subframeP,
const rnti_t rntiP,
uint8_t *sduP,
const uint16_t sdu_lenP,
const int harq_pidP,
uint8_t *msg3_flagP)
{
unsigned char rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr;
unsigned char rx_lcids[NB_RB_MAX];//for NB-IoT, NB_RB_MAX should be fixed to 5 (2 DRB+ 3SRB)
unsigned short rx_lengths[NB_RB_MAX];
int UE_id = find_UE_id(enb_mod_idP,rntiP);
int ii,j;
eNB_MAC_INST_NB *eNB = &eNB_mac_inst_NB[enb_mod_idP];
UE_list_NB_t *UE_list= &eNB->UE_list;
int crnti_rx=0;
//int old_buffer_info;
start_meas(&eNB->rx_ulsch_sdu);
/*if there is an error for UE_id> max or UE_id==-1, set rx_lengths to 0*/
if ((UE_id > NUMBER_OF_UE_MAX) || (UE_id == -1) )
for(ii=0; ii<NB_RB_MAX; ii++) {
rx_lengths[ii] = 0;
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,1);
if (opt_enabled == 1) {
trace_pdu(0, sduP,sdu_lenP, 0, 3, rntiP, frameP, subframeP, 0,0);
LOG_D(OPT,"[eNB %d][ULSCH] Frame %d rnti %x with size %d\n",
enb_mod_idP, frameP, rntiP, sdu_lenP);
}
LOG_D(MAC,"[eNB %d] CC_id %d Received ULSCH sdu from PHY (rnti %x, UE_id %d), parsing header\n",enb_mod_idP,CC_idP,rntiP,UE_id);
if (sduP==NULL) { // we've got an error after N rounds
UE_list->UE_sched_ctrl[UE_id].ul_scheduled &= (~(1<<harq_pidP)); //ul_scheduled: A kind of resource scheduling information
return;
}
if (UE_id!=-1) {
UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer=0;
UE_list->UE_sched_ctrl[UE_id].ul_failure_timer =0;
UE_list->UE_sched_ctrl[UE_id].ul_scheduled &= (~(1<<harq_pidP));
/*RLF procedure this part just check UE context is NULL or not, if not, means UL in synch*/
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=0;
NB_mac_eNB_rrc_ul_in_sync(enb_mod_idP,CC_idP,frameP,subframeP,UE_RNTI(enb_mod_idP,UE_id));
}
}
payload_ptr = parse_ulsch_header(sduP,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,sdu_lenP);
T(T_ENB_MAC_UE_UL_PDU, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
T_INT(harq_pidP), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu));
T(T_ENB_MAC_UE_UL_PDU_WITH_DATA, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
T_INT(harq_pidP), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu), T_BUFFER(sduP, sdu_lenP));
eNB->eNB_stats[CC_idP].ulsch_bytes_rx=sdu_lenP;
eNB->eNB_stats[CC_idP].total_ulsch_bytes_rx+=sdu_lenP;
eNB->eNB_stats[CC_idP].total_ulsch_pdus_rx+=1;
// control element
for (i=0; i<num_ce; i++) {
T(T_ENB_MAC_UE_UL_CE, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
T_INT(rx_ces[i]));
/*rx_ces = lcid in parse_ulsch_header() if not short padding*/
switch (rx_ces[i]) { // implement and process BSR + CRNTI + PHR
case POWER_HEADROOM:
if (UE_id != -1) {
UE_list->UE_template[CC_idP][UE_id].phr_info = (payload_ptr[0] & 0x3f) - PHR_MAPPING_OFFSET;
LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received PHR PH = %d (db)\n",
enb_mod_idP, CC_idP, rx_ces[i], UE_list->UE_template[CC_idP][UE_id].phr_info);
UE_list->UE_template[CC_idP][UE_id].phr_info_configured=1;
UE_list->UE_sched_ctrl[UE_id].phr_received = 1;
}
payload_ptr+=sizeof(POWER_HEADROOM_CMD);
break;
case CRNTI:
UE_id = find_UE_id(enb_mod_idP,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1]);
LOG_I(MAC, "[eNB %d] Frame %d, Subframe %d CC_id %d MAC CE_LCID %d (ce %d/%d): CRNTI %x (UE_id %d) in Msg3\n",
frameP,subframeP,enb_mod_idP, CC_idP, rx_ces[i], i,num_ce,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1],UE_id);
if (UE_id!=-1) {
UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer=0;
UE_list->UE_sched_ctrl[UE_id].ul_failure_timer=0;
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=0;
/*In RRC branch*/
//NB_mac_eNB_rrc_ul_in_sync(enb_mod_idP,CC_idP,frameP,subframeP,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1]);
}
}
crnti_rx=1;
payload_ptr+=2;
if (msg3_flagP != NULL) {
*msg3_flagP = 0;
break;
/*For this moment, long bsr is not processed in the case*/
//case TRUNCATED_BSR:
/*DV lcid =???*/
//case DATA_VOLUME_INDICATOR
case SHORT_BSR: {
uint8_t lcgid;
lcgid = (payload_ptr[0] >> 6);
LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n",
enb_mod_idP, CC_idP, rx_ces[i], lcgid, payload_ptr[0] & 0x3f);
if (crnti_rx==1)
LOG_I(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n",
enb_mod_idP, CC_idP, rx_ces[i], lcgid, payload_ptr[0] & 0x3f);
if (UE_id != -1) {
UE_list->UE_template[CC_idP][UE_id].bsr_info[lcgid] = (payload_ptr[0] & 0x3f);
// update buffer info
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid]=BSR_TABLE[UE_list->UE_template[CC_idP][UE_id].bsr_info[lcgid]];
UE_list->UE_template[CC_idP][UE_id].ul_total_buffer= UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid];
PHY_vars_eNB_g[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP*10)+subframeP] = (payload_ptr[0] & 0x3f);
if (UE_id == UE_list->head)
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR,PHY_vars_eNB_g[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP*10)+subframeP]);
if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[lcgid] == 0 ) {
UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[lcgid]=frameP;
}
if (mac_eNB_get_rrc_status(enb_mod_idP,UE_RNTI(enb_mod_idP,UE_id)) < RRC_CONNECTED)
LOG_I(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : ul_total_buffer = %d (lcg increment %d)\n",
enb_mod_idP, CC_idP, rx_ces[i], UE_list->UE_template[CC_idP][UE_id].ul_total_buffer,
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid]);
}
else {
}
payload_ptr += 1;//sizeof(SHORT_BSR); // fixme
}
break;
default:
LOG_E(MAC, "[eNB %d] CC_id %d Received unknown MAC header (0x%02x)\n", enb_mod_idP, CC_idP, rx_ces[i]);
break;
}
}
for (i=0; i<num_sdu; i++) {
LOG_D(MAC,"SDU Number %d MAC Subheader SDU_LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]);
T(T_ENB_MAC_UE_UL_SDU, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
T_INT(rx_lcids[i]), T_INT(rx_lengths[i]));
T(T_ENB_MAC_UE_UL_SDU_WITH_DATA, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
T_INT(rx_lcids[i]), T_INT(rx_lengths[i]), T_BUFFER(payload_ptr, rx_lengths[i]));
switch (rx_lcids[i]) {
case CCCH :
if (rx_lengths[i] > CCCH_PAYLOAD_SIZE_MAX) {
LOG_E(MAC, "[eNB %d/%d] frame %d received CCCH of size %d (too big, maximum allowed is %d), dropping packet\n",
enb_mod_idP, CC_idP, frameP, rx_lengths[i], CCCH_PAYLOAD_SIZE_MAX);
break;
}
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, Received CCCH: %x.%x.%x.%x.%x.%x, Terminating RA procedure for UE rnti %x\n",
enb_mod_idP,CC_idP,frameP,
payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4], payload_ptr[5], rntiP);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC,1);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC,0);
for (ii=0; ii<NB_RA_PROC_MAX; ii++) {
LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Checking proc %d : rnti (%x, %x), active %d\n",
enb_mod_idP, CC_idP, ii,
eNB->common_channels[CC_idP].RA_template[ii].rnti, rntiP,
eNB->common_channels[CC_idP].RA_template[ii].RA_active);
if ((eNB->common_channels[CC_idP].RA_template[ii].rnti==rntiP) &&
(eNB->common_channels[CC_idP].RA_template[ii].RA_active==TRUE)) {
//payload_ptr = parse_ulsch_header(msg3,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,msg3_len);
if (UE_id < 0) {
memcpy(&eNB->common_channels[CC_idP].RA_template[ii].cont_res_id[0],payload_ptr,6);
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3: length %d, offset %ld\n",
enb_mod_idP,CC_idP,frameP,rx_lengths[i],payload_ptr-sduP);
if ((UE_id=add_new_ue(enb_mod_idP,CC_idP,eNB->common_channels[CC_idP].RA_template[ii].rnti,harq_pidP)) == -1 ) {
mac_xface->macphy_exit("[MAC][eNB] Max user count reached\n");
// kill RA procedure
} else
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Added user with rnti %x => UE %d\n",
enb_mod_idP,CC_idP,frameP,eNB->common_channels[CC_idP].RA_template[ii].rnti,UE_id);
} else {
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %ld\n",
enb_mod_idP,CC_idP,frameP,UE_id,rx_lengths[i],payload_ptr-sduP);
// kill RA procedure
}
if (Is_rrc_registered == 1)
/* In RRC branch
NB_mac_rrc_data_ind(
enb_mod_idP,
CC_idP,
frameP,subframeP,
rntiP,
CCCH,
(uint8_t*)payload_ptr,
rx_lengths[i],
ENB_FLAG_YES,
enb_mod_idP,
0);*/
if (num_ce >0) { // handle msg3 which is not RRCConnectionRequest
// process_ra_message(msg3,num_ce,rx_lcids,rx_ces);
}
eNB->common_channels[CC_idP].RA_template[ii].generate_Msg4 = 1;
eNB->common_channels[CC_idP].RA_template[ii].wait_ack_Msg4 = 0;
} // if process is active
} // loop on RA processes
break ;
/*DCCH0 is for SRB1bis, DCCH1 is for SRB1*/
case DCCH0 :
case DCCH1 :
// if(eNB_mac_inst[module_idP][CC_idP].Dcch_lchan[UE_id].Active==1){
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sduP));
for (j=0; j<32; j++) {
LOG_T(MAC,"%x ",payload_ptr[j]);
}
LOG_T(MAC,"\n");
#endif
if (UE_id != -1) {
/*NO lcg in NB-IoT, anyway set to 0*/
// adjust buffer occupancy of the correponding logical channel group
/*if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] >= rx_lengths[i])
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] -= rx_lengths[i];
else
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] = 0;*/
LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DCCH, received %d bytes form UE %d on LCID %d \n",
enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id, rx_lcids[i]);
/*TODO*/
/*mac_rlc_data_ind(
enb_mod_idP,
rntiP,
enb_mod_idP,
frameP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
rx_lcids[i],
(char *)payload_ptr,
rx_lengths[i],
1,
NULL);//(unsigned int*)crc_status);*/
UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]]+=1;
UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i];
} /* UE_id != -1 */
// }
break;
// all the DRBS
case DTCH0:
default :
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sduP));
for (j=0; j<32; j++) {
LOG_T(MAC,"%x ",payload_ptr[j]);
}
LOG_T(MAC,"\n");
#endif
if (rx_lcids[i] < NB_RB_MAX ) {
LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d\n",
enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id, rx_lcids[i]);
if (UE_id != -1) {
// adjust buffer occupancy of the correponding logical channel group
LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d\n",
enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id,rx_lcids[i]);
/*if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] >= rx_lengths[i])
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] -= rx_lengths[i];
else
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] = 0;*/
if ((rx_lengths[i] <SCH_PAYLOAD_SIZE_MAX) && (rx_lengths[i] > 0) ) { // MAX SIZE OF transport block
/*mac_rlc_data_ind(
enb_mod_idP,
rntiP,
enb_mod_idP,
frameP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
rx_lcids[i],
(char *)payload_ptr,
rx_lengths[i],
1,
NULL);//(unsigned int*)crc_status);*/
UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]]+=1;
UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i];
}
else { /* rx_length[i] */
UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx+=1;
LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : Max size of transport block reached LCID %d from UE %d ",
enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id);
}
}
else {/*(UE_id != -1*/
LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : received unsupported or unknown LCID %d from UE %d ",
enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id);
}
}
break;
}
payload_ptr+=rx_lengths[i];
}
/* NN--> FK: we could either check the payload, or use a phy helper to detect a false msg3 */
if ((num_sdu == 0) && (num_ce==0)) {
if (UE_id != -1)
UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_errors_rx+=1;
if (msg3_flagP != NULL) {
if( *msg3_flagP == 1 ) {
LOG_N(MAC,"[eNB %d] CC_id %d frame %d : false msg3 detection: signal phy to canceling RA and remove the UE\n", enb_mod_idP, CC_idP, frameP);
*msg3_flagP=0;
}
}
} else {
if (UE_id != -1) {
UE_list->eNB_UE_stats[CC_idP][UE_id].pdu_bytes_rx=sdu_lenP;
UE_list->eNB_UE_stats[CC_idP][UE_id].total_pdu_bytes_rx+=sdu_lenP;
UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_pdus_rx+=1;
}
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,0);
stop_meas(&eNB->rx_ulsch_sdu);
}
}
\
......@@ -45,6 +45,7 @@
#endif //PHY_EMUL
#include "PHY_INTERFACE/defs.h"
#include "RRC/LITE/defs.h"
#include "defs_nb_iot.h"
extern const uint32_t BSR_TABLE[BSR_TABLE_SIZE];
//extern uint32_t EBSR_Level[63];
......
/*
* 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 LAYER2/MAC/proto.h
* \brief MAC functions prototypes for eNB and UE
* \author Navid Nikaein and Raymond Knopp
* \date 2010 - 2014
* \email navid.nikaein@eurecom.fr
* \version 1.0
*/
/** \addtogroup _mac
* @{
*/
/*for NB-IoT*/
/* \brief Function to indicate a received SDU on ULSCH for NB-IoT.
*/
void NB_rx_sdu(const module_id_t module_idP, const int CC_id,const frame_t frameP, const sub_frame_t subframeP, const rnti_t rnti, uint8_t *sdu, const uint16_t sdu_len, const int harq_pid,uint8_t *msg3_flag);
/* \brief Function to retrieve result of scheduling (DCI) in current subframe. Can be called an arbitrary numeber of times after eNB_dlsch_ulsch_scheduler
in a given subframe.
*/
DCI_PDU_NB *NB_get_dci_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subframe);
/* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f
and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f. The resultant DCI_PDU is
ready after returning from this call.
*/
void NB_eNB_dlsch_ulsch_scheduler(module_id_t module_idP, uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP);
/* \brief Function to indicate a received preamble on PRACH. It initiates the RA procedure.
In NB-IoT, it indicate preamble using the frequency to indicate the preamble.
*/
void NB_schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP);
void NB_initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, uint16_t preamble_index,int16_t timing_offset,sub_frame_t subframeP);
uint8_t *NB_get_dlsch_sdu(module_id_t module_idP,int CC_id,frame_t frameP,rnti_t rnti,uint8_t TBindex);
int NB_rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP);
int NB_l2_init_eNB(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,uint8_t cba_group_active, uint8_t HO_active);
......@@ -41,6 +41,9 @@
#include "PHY_INTERFACE/defs.h"
#include "COMMON/mac_rrc_primitives.h"
//NB-IoT
eNB_MAC_INST_NB *eNB_mac_inst_NB;
const uint32_t BSR_TABLE[BSR_TABLE_SIZE]= {0,10,12,14,17,19,22,26,31,36,42,49,57,67,78,91,
105,125,146,171,200,234,274,321,376,440,515,603,706,826,967,1132,
1326,1552,1817,2127,2490,2915,3413,3995,4677,5467,6411,7505,8787,10287,12043,14099,
......
/*This is the interface module between PHY
* this will trigger the corresponding function in MAC or PHY layer according to the type of the message
*
*
*
*/
#include "platform_types.h"
#include "openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h"
#define NUMBER_OF_UE_MAX 20
typedef struct{
//flag to show which message is
uint8_t UL_MSG_flag;
//rnti
rnti_t rntiP;
//Pointer to sdu
uint8_t *sdu;
//Pointer to sdu length
uint16_t sdu_lenP;
//HARQ ID
int harq_pidP;
//MSG3 flag
uint8_t *msg3_flagP;
//ACK/NAK
boolean_t NAK;
// ULSCH consecutive error
uint32_t ulsch_consecutive_errors;
}UL_SPEC_t;
//UL_IND
typedef struct{
/*Start at the common part*/
int test;
//Module ID
module_id_t module_id;
//CC ID
int CC_id;
//frame
frame_t frame;
//subframe
sub_frame_t subframe;
//Number of availble UE
int UE_NUM;
/*preamble part*/
//index of the preamble
uint16_t preamble_index;
//timing offset by PHY
int16_t timing_offset;
/*UE specific part*/
UL_SPEC_t UL_SPEC_Info[NUMBER_OF_UE_MAX];
}UL_IND_t;
typedef struct{
/*Common part*/
module_id_t module_idP;
int CC_id;
frame_t frameP;
sub_frame_t subframeP;
rnti_t rntiP;
/*Downlink data*/
//TB size for Downlink data
uint8_t TBindex;
//PDU for MIB,SIBs
uint8_t *BCCH_pdu_payload;
//PDU for DL-SCH
uint8_t *DLSCH_pdu_payload;
/*DCI start*/
// Format of DCI
uint8_t DCI_Format;
// Content of DCI
DCI_CONTENT DCI_Content;
}Sched_Rsp_t;
/*Interface for uplink, transmitting the Preamble(list), ULSCH SDU, NAK, Tick (trigger scheduler)
*/
void UL_indication(UL_IND_t UL_INFO);
/*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/
void Schedule_Response(Sched_Rsp_t Sched_INFO);
/*Interface for Configuration*/
//void Config_Request();
......@@ -128,50 +128,8 @@ init_SI(
#if defined(Rel10) || defined(Rel14)
int i;
#endif
/*
uint32_t mib=0;
int i;
int N_RB_DL,phich_resource;
do_MIB(enb_mod_idP, mac_xface->lte_frame_parms,0x321,&mib);
for (i=0;i<1024;i+=4)
do_MIB(enb_mod_idP, mac_xface->lte_frame_parms,i,&mib);
N_RB_DL=6;
while (N_RB_DL != 0) {
phich_resource = 1;
while (phich_resource != 0) {
for (i=0;i<2;i++) {
mac_xface->lte_frame_parms->N_RB_DL = N_RB_DL;
mac_xface->lte_frame_parms->phich_config_common.phich_duration=i;
mac_xface->lte_frame_parms->phich_config_common.phich_resource = phich_resource;
do_MIB(enb_mod_idP, mac_xface->lte_frame_parms,0,&mib);
}
if (phich_resource == 1)
phich_resource = 3;
else if (phich_resource == 3)
phich_resource = 6;
else if (phich_resource == 6)
phich_resource = 12;
else if (phich_resource == 12)
phich_resource = 0;
}
if (N_RB_DL == 6)
N_RB_DL = 15;
else if (N_RB_DL == 15)
N_RB_DL = 25;
else if (N_RB_DL == 25)
N_RB_DL = 50;
else if (N_RB_DL == 50)
N_RB_DL = 75;
else if (N_RB_DL == 75)
N_RB_DL = 100;
else if (N_RB_DL == 100)
N_RB_DL = 0;
}
exit(-1);
*/
/*Nick Start*/
/*Here will copy basic parameters and implement do_MIB, rrc_eNB_carrier_data_t will add some parameters in MIB*/
eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1 = 0;
eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23 = 0;
......@@ -185,6 +143,7 @@ init_SI(
*/
if (eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].SIB1)
/*the I/O of do_SIB1 will modify, the parameters like SIB1 siblock1 sib1 will assign in the carrier structure */
eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1 = do_SIB1(
ctxt_pP->module_id,
CC_id,
......@@ -215,6 +174,7 @@ init_SI(
eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].SIB23 = (uint8_t*) malloc16(64);
if (eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].SIB23) {
/*Modify as do_sib1*/
eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23 = do_SIB23(
ctxt_pP->module_id,
CC_id,
......@@ -232,16 +192,7 @@ init_SI(
#endif
);
/*
eNB_rrc_inst[ctxt_pP->module_id].sizeof_SIB23 = do_SIB2_AT4(ctxt_pP->module_id,
eNB_rrc_inst[ctxt_pP->module_id].SIB23,
&eNB_rrc_inst[ctxt_pP->module_id].systemInformation,
&eNB_rrc_inst[ctxt_pP->module_id].sib2,
#if defined(ENABLE_ITTI)
, configuration
#endif
);
*/
if (eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23 == 255) {
mac_xface->macphy_exit("[RRC][init_SI] FATAL, eNB_rrc_inst[mod].carrier[CC_id].sizeof_SIB23 == 255");
}
......@@ -322,6 +273,7 @@ init_SI(
LOG_D(RRC,
PROTOCOL_RRC_CTXT_FMT" RRC_UE --- MAC_CONFIG_REQ (SIB1.tdd & SIB2 params) ---> MAC_UE\n",
PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
/*modify to rrc_mac_config_req_eNB*/
rrc_mac_config_req(ctxt_pP->module_id, CC_id, ENB_FLAG_YES, 0, 0,
(RadioResourceConfigCommonSIB_t *) &
eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib2->radioResourceConfigCommon,
......
Develop record:
Nick (nick133371@gmail.com)
5/13
Add: openair1/PHY/impl_defs_lte_nb_iot.h
Add: openair1/PHY/INIT/defs_nb_iot.h
Add: openair1/PHY/INIT/Lte_init_nb_iot.c
Comment:
Functions: NB_phy_config_mib_eNB(), NB_phy_config_sib2_eNB(), NB_phy_config_dedicated_eNB().
Parameters: NB_DL_FRAME_PARAMS(Original LTE_DL_FRAME_PARAMS)
5/14
Add: openair2/Layer2/MAC/defs_nb_iot.h
Add: openair2/Layer2/MAC/proto_nb_iot.h
Add: openair2/Layer2/MAC/eNB_scheduler_ulsch_nb_iot.c
Add: openair2/Layer2/MAC/eNB_scheduler_prmitives_nb_iot.c
Add: openair2/Layer2/MAC/eNB_scheduler_dlsch_nb_iot.c
comment:
Functions: NB_rx_sdu(), NB_get_dci_sdu(), NB_rrc_mac_remove_ue(), NB_get_dlsch_sdu();
Parameters: All parameters/structures used in MAC Layer.
5/15
Add: openair2/Layer2/MAC/eNB_scheduler_RA_nb_iot.c
comment:
Functions: NB_initiate_ra_proc()
5/15
modified: openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h
modified: openair1/PHY/LTE_TRANSPORT/defs.hod
modified: openair2/LAYER2/MAC/eNB_scheduler_RA_nb_iot.c
modified: openair2/LAYER2/MAC/proto_nb_iot.h
comment:
Functions: NB_schedule_RA()
Parameters: Add DCI unpacked format
5/16
Add: openair2/LAYER2/MAC/IF_Module_nb_iot.c
Add: openair2/PHY_INTERFACE/IF_Module_nb_iot.h
Add: openair1/PHY/sched/phy_procedures_lte_eNB_nb_iot.c
Comment: Modify NB_phy_procedures_uespec_RX, change the way using primitive, use UL_IND data structure to store the needed parameters.
Add the implementation for UL_INDICATION, it handles the Uplink information from PHY, also trigger the scheduler.
Functions: NB_phy_procedures_uespec_RX(), UL_INDICATION()
Parameters: UL_IND for Interface Module
5/18
Modified: openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h
Modified: openair2/PHY_INTERFACE/IF_Module_nb_iot.h
Modified: openair2/LAYER2/MAC/IF_Module_nb_iot.c
Comment: Complete the UL_INDICATION
Functions: UL_INDICATION()
Parameters: Sched_Rsp for Interface Module
5/19
Comment: 15 warnings fixed
NB-IoT_Docs Folder
BMW lab./NTUST
Document list:
1. images - The figures of the Message Sequence Chart compared LTE with NB-IoT, in Attach/MT/MO.
2. NB_L2_interface - Describe the interface between MAC and other layers (mainly PHY layer), and show the basic concept for development.
3. NB_MAC_Design_Document - This document is mainly describing about the NB-IoT MAC module design based on OAI in the system/block/process/procedure side.
4. NB_MAC_Module_List - This document is mainly descrbing about the difference beween MAC in LTE and NB-IoT from 3gpp specification.
5. NB_MAC_SAP - This document is mainly describling about the Service Access Point (primitives) between the MAC and other layers in OAI.
6. NB_MAC_Fapi_interface - This document is mainly for the FAPI style interface between OAI MAC and PHY for NB-IoT, and described how old messages in OAI go through in the FAPI style interface.
If there is anything wrong, please do not hesitate to contact us, Thanks!
Advisor : Prof.Ray Guang, Cheng crg@mail.ntust.edu.tw
The response block for each person:
Scheduling:Eric qqq1993qqq029@gmail.com
DownlinkProcedure:Xavier/Alan sephiroth7277@gmail.com/Rely4679@gmail.com
UplinkProcedure:Nick nick133371@gmail.com
Config:Kenny kroempa@gmail.com
SystemInformation:Calvin calvin820119@gmail.com
20170405
\ No newline at end of file
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