Commit 76334007 authored by Nick Ho's avatar Nick Ho

Add part of the MAC primitives & FAPI Style Interfaces figure

parent 26407d26
...@@ -1134,10 +1134,13 @@ set (MAC_SRC ...@@ -1134,10 +1134,13 @@ set (MAC_SRC
${MAC_DIR}/rar_tools.c ${MAC_DIR}/rar_tools.c
${MAC_DIR}/eNB_scheduler.c ${MAC_DIR}/eNB_scheduler.c
${MAC_DIR}/eNB_scheduler_dlsch.c ${MAC_DIR}/eNB_scheduler_dlsch.c
${MAC_DIR}/eNB_scheduler_dlsch-nb.c
${MAC_DIR}/eNB_scheduler_ulsch.c ${MAC_DIR}/eNB_scheduler_ulsch.c
${MAC_DIR}/eNB_scheduler_ulsch-nb.c
${MAC_DIR}/eNB_scheduler_mch.c ${MAC_DIR}/eNB_scheduler_mch.c
${MAC_DIR}/eNB_scheduler_bch.c ${MAC_DIR}/eNB_scheduler_bch.c
${MAC_DIR}/eNB_scheduler_primitives.c ${MAC_DIR}/eNB_scheduler_primitives.c
${MAC_DIR}/eNB_scheduler_primitives-nb.c
${MAC_DIR}/eNB_scheduler_RA.c ${MAC_DIR}/eNB_scheduler_RA.c
${MAC_DIR}/pre_processor.c ${MAC_DIR}/pre_processor.c
${MAC_DIR}/config.c ${MAC_DIR}/config.c
......
...@@ -213,1610 +213,6 @@ void NB_phy_config_dedicated_eNB(uint8_t Mod_id, ...@@ -213,1610 +213,6 @@ void NB_phy_config_dedicated_eNB(uint8_t Mod_id,
return; return;
} }
}
// FIXME not used anywhere
void phy_config_mib(LTE_DL_FRAME_PARMS *fp,
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)
{
fp->N_RB_DL = N_RB_DL;
fp->Nid_cell = Nid_cell;
fp->nushift = Nid_cell%6;
fp->Ncp = Ncp;
fp->frame_type = frame_type;
fp->nb_antenna_ports_eNB = p_eNB;
fp->phich_config_common.phich_resource = phich_config->phich_resource;
fp->phich_config_common.phich_duration = phich_config->phich_duration;
}
void phy_config_sib1_eNB(uint8_t Mod_id,
int CC_id,
TDD_Config_t *tdd_Config,
uint8_t SIwindowsize,
uint16_t SIPeriod)
{
LTE_DL_FRAME_PARMS *fp = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms;
if (tdd_Config) {
fp->tdd_config = tdd_Config->subframeAssignment;
fp->tdd_config_S = tdd_Config->specialSubframePatterns;
}
fp->SIwindowsize = SIwindowsize;
fp->SIPeriod = SIPeriod;
}
void phy_config_sib1_ue(uint8_t Mod_id,int CC_id,
uint8_t eNB_id,
TDD_Config_t *tdd_Config,
uint8_t SIwindowsize,
uint16_t SIperiod)
{
LTE_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms;
if (tdd_Config) {
fp->tdd_config = tdd_Config->subframeAssignment;
fp->tdd_config_S = tdd_Config->specialSubframePatterns;
}
fp->SIwindowsize = SIwindowsize;
fp->SIPeriod = SIperiod;
}
void phy_config_sib2_eNB(uint8_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)
{
LTE_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;
int i;
LOG_D(PHY,"[eNB%d] CCid %d: Applying radioResourceConfigCommon\n",Mod_id,CC_id);
fp->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex;
LOG_D(PHY,"prach_config_common.rootSequenceIndex = %d\n",fp->prach_config_common.rootSequenceIndex );
fp->prach_config_common.prach_Config_enabled=1;
fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex;
LOG_D(PHY,"prach_config_common.prach_ConfigInfo.prach_ConfigIndex = %d\n",fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex);
fp->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag;
LOG_D(PHY,"prach_config_common.prach_ConfigInfo.highSpeedFlag = %d\n",fp->prach_config_common.prach_ConfigInfo.highSpeedFlag);
fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig;
LOG_D(PHY,"prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig = %d\n",fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig);
fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset;
LOG_D(PHY,"prach_config_common.prach_ConfigInfo.prach_FreqOffset = %d\n",fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset);
compute_prach_seq(&fp->prach_config_common,fp->frame_type,
PHY_vars_eNB_g[Mod_id][CC_id]->X_u);
fp->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift;
fp->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI;
fp->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN;
fp->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN;
fp->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower;
fp->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b;
fp->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB;
LOG_D(PHY,"pusch_config_common.n_SB = %d\n",fp->pusch_config_common.n_SB );
fp->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode;
LOG_D(PHY,"pusch_config_common.hoppingMode = %d\n",fp->pusch_config_common.hoppingMode);
fp->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset;
LOG_D(PHY,"pusch_config_common.pusch_HoppingOffset = %d\n",fp->pusch_config_common.pusch_HoppingOffset);
fp->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM;
LOG_D(PHY,"pusch_config_common.enable64QAM = %d\n",fp->pusch_config_common.enable64QAM );
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled;
LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = %d\n",fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled);
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH;
LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = %d\n",fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH);
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled;
LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = %d\n",fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled);
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift];
LOG_D(PHY,"pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = %d\n",fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift);
init_ul_hopping(fp);
fp->soundingrs_ul_config_common.enabled_flag = 0;
if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.present==SoundingRS_UL_ConfigCommon_PR_setup) {
fp->soundingrs_ul_config_common.enabled_flag = 1;
fp->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig;
fp->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig;
fp->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission;
if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts)
fp->soundingrs_ul_config_common.srs_MaxUpPts = 1;
else
fp->soundingrs_ul_config_common.srs_MaxUpPts = 0;
}
fp->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH;
fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha;
fp->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH;
fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3;
fp->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1;
fp->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b;
fp->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2;
fp->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a;
fp->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b;
fp->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx;
// Now configure some of the Physical Channels
// PUCCH
init_ncs_cell(fp,PHY_vars_eNB_g[Mod_id][CC_id]->ncs_cell);
init_ul_hopping(fp);
// MBSFN
if (mbsfn_SubframeConfigList != NULL) {
fp->num_MBSFN_config = mbsfn_SubframeConfigList->list.count;
for (i=0; i<mbsfn_SubframeConfigList->list.count; i++) {
fp->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod;
fp->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset;
if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) {
fp->MBSFN_config[i].fourFrames_flag = 0;
fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration
LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %d\n", i,
fp->MBSFN_config[i].mbsfn_SubframeConfig);
} else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration
fp->MBSFN_config[i].fourFrames_flag = 1;
fp->MBSFN_config[i].mbsfn_SubframeConfig =
mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]|
(mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)|
(mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]<<16);
LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %d\n", i,
fp->MBSFN_config[i].mbsfn_SubframeConfig);
}
}
} else
fp->num_MBSFN_config = 0;
}
void phy_config_sib2_ue(uint8_t Mod_id,int CC_id,
uint8_t eNB_id,
RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
ARFCN_ValueEUTRA_t *ul_CarrierFreq,
long *ul_Bandwidth,
AdditionalSpectrumEmission_t *additionalSpectrumEmission,
struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList)
{
PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
LTE_DL_FRAME_PARMS *fp = &ue->frame_parms;
int i;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_FUNCTION_IN);
LOG_I(PHY,"[UE%d] Applying radioResourceConfigCommon from eNB%d\n",Mod_id,eNB_id);
fp->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex;
fp->prach_config_common.prach_Config_enabled=1;
fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex;
fp->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag;
fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig;
fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset;
compute_prach_seq(&fp->prach_config_common,fp->frame_type,ue->X_u);
fp->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift;
fp->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI;
fp->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN;
fp->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN;
fp->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower;
fp->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b;
fp->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB;
fp->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode;
fp->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset;
fp->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM;
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled;
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH;
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled;
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift];
init_ul_hopping(fp);
fp->soundingrs_ul_config_common.enabled_flag = 0;
if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.present==SoundingRS_UL_ConfigCommon_PR_setup) {
fp->soundingrs_ul_config_common.enabled_flag = 1;
fp->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig;
fp->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig;
fp->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission;
if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts)
fp->soundingrs_ul_config_common.srs_MaxUpPts = 1;
else
fp->soundingrs_ul_config_common.srs_MaxUpPts = 0;
}
fp->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH;
fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha;
fp->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH;
fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3;
fp->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1;
fp->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b;
fp->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2;
fp->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a;
fp->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b;
fp->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx;
// Now configure some of the Physical Channels
// PUCCH
init_ncs_cell(fp,ue->ncs_cell);
init_ul_hopping(fp);
// PCH
init_ue_paging_info(ue,radioResourceConfigCommon->pcch_Config.defaultPagingCycle,radioResourceConfigCommon->pcch_Config.nB);
// MBSFN
if (mbsfn_SubframeConfigList != NULL) {
fp->num_MBSFN_config = mbsfn_SubframeConfigList->list.count;
for (i=0; i<mbsfn_SubframeConfigList->list.count; i++) {
fp->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod;
fp->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset;
if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) {
fp->MBSFN_config[i].fourFrames_flag = 0;
fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration
LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %d\n", i,
fp->MBSFN_config[i].mbsfn_SubframeConfig);
} else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration
fp->MBSFN_config[i].fourFrames_flag = 1;
fp->MBSFN_config[i].mbsfn_SubframeConfig =
mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]|
(mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)|
(mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]<<16);
LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %d\n", i,
fp->MBSFN_config[i].mbsfn_SubframeConfig);
}
}
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_FUNCTION_OUT);
}
void phy_config_sib13_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,int mbsfn_Area_idx,
long mbsfn_AreaId_r9)
{
LTE_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms;
LOG_I(PHY,"[UE%d] Applying MBSFN_Area_id %ld for index %d\n",Mod_id,mbsfn_AreaId_r9,mbsfn_Area_idx);
if (mbsfn_Area_idx == 0) {
fp->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9;
LOG_N(PHY,"Fix me: only called when mbsfn_Area_idx == 0)\n");
}
lte_gold_mbsfn(fp,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_mbsfn_table,fp->Nid_cell_mbsfn);
}
void phy_config_sib13_eNB(uint8_t Mod_id,int CC_id,int mbsfn_Area_idx,
long mbsfn_AreaId_r9)
{
LTE_DL_FRAME_PARMS *fp = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms;
LOG_I(PHY,"[eNB%d] Applying MBSFN_Area_id %ld for index %d\n",Mod_id,mbsfn_AreaId_r9,mbsfn_Area_idx);
if (mbsfn_Area_idx == 0) {
fp->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9;
LOG_N(PHY,"Fix me: only called when mbsfn_Area_idx == 0)\n");
}
lte_gold_mbsfn(fp,PHY_vars_eNB_g[Mod_id][CC_id]->lte_gold_mbsfn_table,fp->Nid_cell_mbsfn);
}
void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *eNB)
{
uint8_t UE_id;
struct PhysicalConfigDedicated *physicalConfigDedicated;
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
physicalConfigDedicated = eNB->physicalConfigDedicated[UE_id];
if (physicalConfigDedicated != NULL) {
LOG_I(PHY,"[eNB %d] Sent physicalConfigDedicated=%p for UE %d\n",eNB->Mod_id,physicalConfigDedicated,UE_id);
LOG_D(PHY,"------------------------------------------------------------------------\n");
if (physicalConfigDedicated->pdsch_ConfigDedicated) {
eNB->pdsch_config_dedicated[UE_id].p_a=physicalConfigDedicated->pdsch_ConfigDedicated->p_a;
LOG_D(PHY,"pdsch_config_dedicated.p_a %d\n",eNB->pdsch_config_dedicated[UE_id].p_a);
LOG_D(PHY,"\n");
}
if (physicalConfigDedicated->pucch_ConfigDedicated) {
if (physicalConfigDedicated->pucch_ConfigDedicated->ackNackRepetition.present==PUCCH_ConfigDedicated__ackNackRepetition_PR_release)
eNB->pucch_config_dedicated[UE_id].ackNackRepetition=0;
else {
eNB->pucch_config_dedicated[UE_id].ackNackRepetition=1;
}
if (fp->frame_type == FDD) {
eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode = multiplexing;
} else {
if (physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode)
eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode = *physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode;
else
eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode = bundling;
}
if ( eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == multiplexing)
LOG_D(PHY,"pucch_config_dedicated.tdd_AckNackFeedbackMode = multiplexing\n");
else
LOG_D(PHY,"pucch_config_dedicated.tdd_AckNackFeedbackMode = bundling\n");
}
if (physicalConfigDedicated->pusch_ConfigDedicated) {
eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_ACK_Index;
eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index;
eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index;
LOG_D(PHY,"pusch_config_dedicated.betaOffset_ACK_Index %d\n",eNB->pusch_config_dedicated[UE_id].betaOffset_ACK_Index);
LOG_D(PHY,"pusch_config_dedicated.betaOffset_RI_Index %d\n",eNB->pusch_config_dedicated[UE_id].betaOffset_RI_Index);
LOG_D(PHY,"pusch_config_dedicated.betaOffset_CQI_Index %d\n",eNB->pusch_config_dedicated[UE_id].betaOffset_CQI_Index);
LOG_D(PHY,"\n");
}
if (physicalConfigDedicated->uplinkPowerControlDedicated) {
eNB->ul_power_control_dedicated[UE_id].p0_UE_PUSCH = physicalConfigDedicated->uplinkPowerControlDedicated->p0_UE_PUSCH;
eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled= physicalConfigDedicated->uplinkPowerControlDedicated->deltaMCS_Enabled;
eNB->ul_power_control_dedicated[UE_id].accumulationEnabled= physicalConfigDedicated->uplinkPowerControlDedicated->accumulationEnabled;
eNB->ul_power_control_dedicated[UE_id].p0_UE_PUCCH= physicalConfigDedicated->uplinkPowerControlDedicated->p0_UE_PUCCH;
eNB->ul_power_control_dedicated[UE_id].pSRS_Offset= physicalConfigDedicated->uplinkPowerControlDedicated->pSRS_Offset;
eNB->ul_power_control_dedicated[UE_id].filterCoefficient= *physicalConfigDedicated->uplinkPowerControlDedicated->filterCoefficient;
LOG_D(PHY,"ul_power_control_dedicated.p0_UE_PUSCH %d\n",eNB->ul_power_control_dedicated[UE_id].p0_UE_PUSCH);
LOG_D(PHY,"ul_power_control_dedicated.deltaMCS_Enabled %d\n",eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled);
LOG_D(PHY,"ul_power_control_dedicated.accumulationEnabled %d\n",eNB->ul_power_control_dedicated[UE_id].accumulationEnabled);
LOG_D(PHY,"ul_power_control_dedicated.p0_UE_PUCCH %d\n",eNB->ul_power_control_dedicated[UE_id].p0_UE_PUCCH);
LOG_D(PHY,"ul_power_control_dedicated.pSRS_Offset %d\n",eNB->ul_power_control_dedicated[UE_id].pSRS_Offset);
LOG_D(PHY,"ul_power_control_dedicated.filterCoefficient %d\n",eNB->ul_power_control_dedicated[UE_id].filterCoefficient);
LOG_D(PHY,"\n");
}
if (physicalConfigDedicated->antennaInfo) {
eNB->transmission_mode[UE_id] = 1+(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode);
LOG_D(PHY,"Transmission Mode (phy_config_dedicated_eNB_step2) %d\n",eNB->transmission_mode[UE_id]);
LOG_D(PHY,"\n");
}
if (physicalConfigDedicated->schedulingRequestConfig) {
if (physicalConfigDedicated->schedulingRequestConfig->present == SchedulingRequestConfig_PR_setup) {
eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex = physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex;
eNB->scheduling_request_config[UE_id].sr_ConfigIndex=physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_ConfigIndex;
eNB->scheduling_request_config[UE_id].dsr_TransMax=physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax;
LOG_D(PHY,"scheduling_request_config.sr_PUCCH_ResourceIndex %d\n",eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex);
LOG_D(PHY,"scheduling_request_config.sr_ConfigIndex %d\n",eNB->scheduling_request_config[UE_id].sr_ConfigIndex);
LOG_D(PHY,"scheduling_request_config.dsr_TransMax %d\n",eNB->scheduling_request_config[UE_id].dsr_TransMax);
}
LOG_D(PHY,"------------------------------------------------------------\n");
}
if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated) {
if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
eNB->soundingrs_ul_config_dedicated[UE_id].srsConfigDedicatedSetup = 1;
eNB->soundingrs_ul_config_dedicated[UE_id].duration = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.duration;
eNB->soundingrs_ul_config_dedicated[UE_id].cyclicShift = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;
eNB->soundingrs_ul_config_dedicated[UE_id].freqDomainPosition = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
eNB->soundingrs_ul_config_dedicated[UE_id].srs_Bandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
eNB->soundingrs_ul_config_dedicated[UE_id].srs_HoppingBandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;
eNB->soundingrs_ul_config_dedicated[UE_id].transmissionComb = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
LOG_D(PHY,"soundingrs_ul_config_dedicated.srs_ConfigIndex %d\n",eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex);
}
LOG_D(PHY,"------------------------------------------------------------\n");
}
eNB->physicalConfigDedicated[UE_id] = NULL;
}
}
}
/*
* Configures UE MAC and PHY with radioResourceCommon received in mobilityControlInfo IE during Handover
*/
void phy_config_afterHO_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_id, MobilityControlInfo_t *mobilityControlInfo, uint8_t ho_failed)
{
if(mobilityControlInfo!=NULL) {
RadioResourceConfigCommon_t *radioResourceConfigCommon = &mobilityControlInfo->radioResourceConfigCommon;
LOG_I(PHY,"radioResourceConfigCommon %p\n", radioResourceConfigCommon);
memcpy((void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms_before_ho,
(void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms,
sizeof(LTE_DL_FRAME_PARMS));
PHY_vars_UE_g[Mod_id][CC_id]->ho_triggered = 1;
//PHY_vars_UE_g[UE_id]->UE_mode[0] = PRACH;
LTE_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms;
// int N_ZC;
// uint8_t prach_fmt;
// int u;
LOG_I(PHY,"[UE%d] Handover triggered: Applying radioResourceConfigCommon from eNB %d\n",
Mod_id,eNB_id);
fp->prach_config_common.rootSequenceIndex =radioResourceConfigCommon->prach_Config.rootSequenceIndex;
fp->prach_config_common.prach_Config_enabled=1;
fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex;
fp->prach_config_common.prach_ConfigInfo.highSpeedFlag =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->highSpeedFlag;
fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->zeroCorrelationZoneConfig;
fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_FreqOffset;
// prach_fmt = get_prach_fmt(radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex,fp->frame_type);
// N_ZC = (prach_fmt <4)?839:139;
// u = (prach_fmt < 4) ? prach_root_sequence_map0_3[fp->prach_config_common.rootSequenceIndex] :
// prach_root_sequence_map4[fp->prach_config_common.rootSequenceIndex];
//compute_prach_seq(u,N_ZC, PHY_vars_UE_g[Mod_id]->X_u);
compute_prach_seq(&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common,
fp->frame_type,
PHY_vars_UE_g[Mod_id][CC_id]->X_u);
fp->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon->deltaPUCCH_Shift;
fp->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon->nRB_CQI;
fp->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon->nCS_AN;
fp->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon->n1PUCCH_AN;
fp->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon->referenceSignalPower;
fp->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon->p_b;
fp->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB;
fp->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode;
fp->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset;
fp->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM;
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled;
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH;
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled;
fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift;
init_ul_hopping(fp);
fp->soundingrs_ul_config_common.enabled_flag = 0;
if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon->present==SoundingRS_UL_ConfigCommon_PR_setup) {
fp->soundingrs_ul_config_common.enabled_flag = 1;
fp->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_BandwidthConfig;
fp->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig;
fp->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.ackNackSRS_SimultaneousTransmission;
if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_MaxUpPts)
fp->soundingrs_ul_config_common.srs_MaxUpPts = 1;
else
fp->soundingrs_ul_config_common.srs_MaxUpPts = 0;
}
fp->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUSCH;
fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon->alpha;
fp->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUCCH;
fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaPreambleMsg3;
fp->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1;
fp->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1b;
fp->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2;
fp->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2a;
fp->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2b;
fp->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon->maxHARQ_Msg3Tx;
// Now configure some of the Physical Channels
if (radioResourceConfigCommon->antennaInfoCommon)
fp->nb_antennas_tx = (1<<radioResourceConfigCommon->antennaInfoCommon->antennaPortsCount);
else
fp->nb_antennas_tx = 1;
//PHICH
if (radioResourceConfigCommon->antennaInfoCommon) {
fp->phich_config_common.phich_resource = radioResourceConfigCommon->phich_Config->phich_Resource;
fp->phich_config_common.phich_duration = radioResourceConfigCommon->phich_Config->phich_Duration;
}
//Target CellId
fp->Nid_cell = mobilityControlInfo->targetPhysCellId;
fp->nushift = fp->Nid_cell%6;
// PUCCH
init_ncs_cell(fp,PHY_vars_UE_g[Mod_id][CC_id]->ncs_cell);
init_ul_hopping(fp);
// RNTI
PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8);
PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8);
LOG_I(PHY,"SET C-RNTI %x %x\n",PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_id]->crnti,
PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_id]->crnti);
}
if(ho_failed) {
LOG_D(PHY,"[UE%d] Handover failed, triggering RACH procedure\n",Mod_id);
memcpy((void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms,(void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms_before_ho, sizeof(LTE_DL_FRAME_PARMS));
PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_id] = PRACH;
}
}
void phy_config_meas_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,uint8_t n_adj_cells,unsigned int *adj_cell_id)
{
PHY_MEASUREMENTS *phy_meas = &PHY_vars_UE_g[Mod_id][CC_id]->measurements;
int i;
LOG_I(PHY,"Configuring inter-cell measurements for %d cells, ids: \n",n_adj_cells);
for (i=0; i<n_adj_cells; i++) {
LOG_I(PHY,"%d\n",adj_cell_id[i]);
lte_gold(&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_table[i+1],adj_cell_id[i]);
}
phy_meas->n_adj_cells = n_adj_cells;
memcpy((void*)phy_meas->adj_cell_id,(void *)adj_cell_id,n_adj_cells*sizeof(unsigned int));
}
void phy_config_dedicated_eNB(uint8_t Mod_id,
int CC_id,
uint16_t rnti,
struct PhysicalConfigDedicated *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;
}
if (physicalConfigDedicated) {
eNB->physicalConfigDedicated[UE_id] = physicalConfigDedicated;
LOG_I(PHY,"phy_config_dedicated_eNB: physicalConfigDedicated=%p\n",physicalConfigDedicated);
if (physicalConfigDedicated->antennaInfo) {
switch(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode) {
case AntennaInfoDedicated__transmissionMode_tm1:
eNB->transmission_mode[UE_id] = 1;
break;
case AntennaInfoDedicated__transmissionMode_tm2:
eNB->transmission_mode[UE_id] = 2;
break;
case AntennaInfoDedicated__transmissionMode_tm3:
eNB->transmission_mode[UE_id] = 3;
break;
case AntennaInfoDedicated__transmissionMode_tm4:
eNB->transmission_mode[UE_id] = 4;
break;
case AntennaInfoDedicated__transmissionMode_tm5:
eNB->transmission_mode[UE_id] = 5;
break;
case AntennaInfoDedicated__transmissionMode_tm6:
eNB->transmission_mode[UE_id] = 6;
break;
case AntennaInfoDedicated__transmissionMode_tm7:
lte_gold_ue_spec_port5(eNB->lte_gold_uespec_port5_table[0],eNB->frame_parms.Nid_cell,rnti);
eNB->do_precoding = 1;
eNB->transmission_mode[UE_id] = 7;
break;
default:
LOG_E(PHY,"Unknown transmission mode!\n");
break;
}
LOG_I(PHY,"Transmission Mode (phy_config_dedicated_eNB) %d\n",eNB->transmission_mode[UE_id]);
} else {
LOG_D(PHY,"[eNB %d] : Received NULL radioResourceConfigDedicated->antennaInfo from eNB %d\n",Mod_id,UE_id);
}
} else {
LOG_E(PHY,"[eNB %d] Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, UE_id);
return;
}
}
#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)
{
uint8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][0]);
struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10 = sCellToAddMod_r10->radioResourceConfigDedicatedSCell_r10->physicalConfigDedicatedSCell_r10;
//struct RadioResourceConfigCommonSCell_r10 *physicalConfigCommonSCell_r10 = sCellToAddMod_r10->radioResourceConfigCommonSCell_r10;
//PhysCellId_t physCellId_r10 = sCellToAddMod_r10->cellIdentification_r10->physCellId_r10;
ARFCN_ValueEUTRA_t dl_CarrierFreq_r10 = sCellToAddMod_r10->cellIdentification_r10->dl_CarrierFreq_r10;
uint32_t carrier_freq_local;
if ((dl_CarrierFreq_r10>=36000) && (dl_CarrierFreq_r10<=36199)) {
carrier_freq_local = 1900000000 + (dl_CarrierFreq_r10-36000)*100000; //band 33 from 3GPP 36.101 v 10.9 Table 5.7.3-1
LOG_I(PHY,"[eNB %d] Frame %d: Configured SCell %d to frequency %d (ARFCN %ld) for UE %d\n",Mod_id,/*eNB->frame*/0,CC_id,carrier_freq_local,dl_CarrierFreq_r10,UE_id);
} else if ((dl_CarrierFreq_r10>=6150) && (dl_CarrierFreq_r10<=6449)) {
carrier_freq_local = 832000000 + (dl_CarrierFreq_r10-6150)*100000; //band 20 from 3GPP 36.101 v 10.9 Table 5.7.3-1
// this is actually for the UL only, but we use it for DL too, since there is no TDD mode for this band
LOG_I(PHY,"[eNB %d] Frame %d: Configured SCell %d to frequency %d (ARFCN %ld) for UE %d\n",Mod_id,/*eNB->frame*/0,CC_id,carrier_freq_local,dl_CarrierFreq_r10,UE_id);
} else {
LOG_E(PHY,"[eNB %d] Frame %d: ARFCN %ld of SCell %d for UE %d not supported\n",Mod_id,/*eNB->frame*/0,dl_CarrierFreq_r10,CC_id,UE_id);
}
if (physicalConfigDedicatedSCell_r10) {
//#warning " eNB->physicalConfigDedicatedSCell_r10 does not exist in eNB"
// eNB->physicalConfigDedicatedSCell_r10[UE_id] = physicalConfigDedicatedSCell_r10;
LOG_I(PHY,"[eNB %d] Frame %d: Configured phyConfigDedicatedSCell with CC_id %d for UE %d\n",Mod_id,/*eNB->frame*/0,CC_id,UE_id);
} else {
LOG_E(PHY,"[eNB %d] Frame %d: Received NULL radioResourceConfigDedicated (CC_id %d, UE %d)\n",Mod_id, /*eNB->frame*/0,CC_id,UE_id);
return;
}
}
#endif
void phy_config_harq_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
uint16_t max_harq_tx )
{
PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id];
phy_vars_ue->ulsch[eNB_id]->Mlimit = max_harq_tx;
}
void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
struct PhysicalConfigDedicated *physicalConfigDedicated )
{
PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id];
phy_vars_ue->total_TBS[eNB_id]=0;
phy_vars_ue->total_TBS_last[eNB_id]=0;
phy_vars_ue->bitrate[eNB_id]=0;
phy_vars_ue->total_received_bits[eNB_id]=0;
phy_vars_ue->dlsch_errors[eNB_id]=0;
phy_vars_ue->dlsch_errors_last[eNB_id]=0;
phy_vars_ue->dlsch_received[eNB_id]=0;
phy_vars_ue->dlsch_received_last[eNB_id]=0;
phy_vars_ue->dlsch_fer[eNB_id]=0;
phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1;
phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1;
if (physicalConfigDedicated) {
LOG_D(PHY,"[UE %d] Received physicalConfigDedicated from eNB %d\n",Mod_id, eNB_id);
LOG_D(PHY,"------------------------------------------------------------------------\n");
if (physicalConfigDedicated->pdsch_ConfigDedicated) {
phy_vars_ue->pdsch_config_dedicated[eNB_id].p_a=physicalConfigDedicated->pdsch_ConfigDedicated->p_a;
LOG_D(PHY,"pdsch_config_dedicated.p_a %d\n",phy_vars_ue->pdsch_config_dedicated[eNB_id].p_a);
LOG_D(PHY,"\n");
}
if (physicalConfigDedicated->pucch_ConfigDedicated) {
if (physicalConfigDedicated->pucch_ConfigDedicated->ackNackRepetition.present==PUCCH_ConfigDedicated__ackNackRepetition_PR_release)
phy_vars_ue->pucch_config_dedicated[eNB_id].ackNackRepetition=0;
else {
phy_vars_ue->pucch_config_dedicated[eNB_id].ackNackRepetition=1;
}
if (physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode)
phy_vars_ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode = *physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode;
else
phy_vars_ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode = bundling;
if ( phy_vars_ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode == multiplexing)
LOG_D(PHY,"pucch_config_dedicated.tdd_AckNackFeedbackMode = multiplexing\n");
else
LOG_D(PHY,"pucch_config_dedicated.tdd_AckNackFeedbackMode = bundling\n");
}
if (physicalConfigDedicated->pusch_ConfigDedicated) {
phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_ACK_Index;
phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_RI_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index;
phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index;
LOG_D(PHY,"pusch_config_dedicated.betaOffset_ACK_Index %d\n",phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index);
LOG_D(PHY,"pusch_config_dedicated.betaOffset_RI_Index %d\n",phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_RI_Index);
LOG_D(PHY,"pusch_config_dedicated.betaOffset_CQI_Index %d\n",phy_vars_ue->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index);
LOG_D(PHY,"\n");
}
if (physicalConfigDedicated->uplinkPowerControlDedicated) {
phy_vars_ue->ul_power_control_dedicated[eNB_id].p0_UE_PUSCH = physicalConfigDedicated->uplinkPowerControlDedicated->p0_UE_PUSCH;
phy_vars_ue->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled= physicalConfigDedicated->uplinkPowerControlDedicated->deltaMCS_Enabled;
phy_vars_ue->ul_power_control_dedicated[eNB_id].accumulationEnabled= physicalConfigDedicated->uplinkPowerControlDedicated->accumulationEnabled;
phy_vars_ue->ul_power_control_dedicated[eNB_id].p0_UE_PUCCH= physicalConfigDedicated->uplinkPowerControlDedicated->p0_UE_PUCCH;
phy_vars_ue->ul_power_control_dedicated[eNB_id].pSRS_Offset= physicalConfigDedicated->uplinkPowerControlDedicated->pSRS_Offset;
phy_vars_ue->ul_power_control_dedicated[eNB_id].filterCoefficient= *physicalConfigDedicated->uplinkPowerControlDedicated->filterCoefficient;
LOG_D(PHY,"ul_power_control_dedicated.p0_UE_PUSCH %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].p0_UE_PUSCH);
LOG_D(PHY,"ul_power_control_dedicated.deltaMCS_Enabled %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled);
LOG_D(PHY,"ul_power_control_dedicated.accumulationEnabled %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].accumulationEnabled);
LOG_D(PHY,"ul_power_control_dedicated.p0_UE_PUCCH %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].p0_UE_PUCCH);
LOG_D(PHY,"ul_power_control_dedicated.pSRS_Offset %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].pSRS_Offset);
LOG_D(PHY,"ul_power_control_dedicated.filterCoefficient %d\n",phy_vars_ue->ul_power_control_dedicated[eNB_id].filterCoefficient);
LOG_D(PHY,"\n");
}
if (physicalConfigDedicated->antennaInfo) {
phy_vars_ue->transmission_mode[eNB_id] = 1+(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode);
LOG_I(PHY,"Transmission Mode %d\n",phy_vars_ue->transmission_mode[eNB_id]);
switch(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode) {
case AntennaInfoDedicated__transmissionMode_tm1:
phy_vars_ue->transmission_mode[eNB_id] = 1;
break;
case AntennaInfoDedicated__transmissionMode_tm2:
phy_vars_ue->transmission_mode[eNB_id] = 2;
break;
case AntennaInfoDedicated__transmissionMode_tm3:
phy_vars_ue->transmission_mode[eNB_id] = 3;
break;
case AntennaInfoDedicated__transmissionMode_tm4:
phy_vars_ue->transmission_mode[eNB_id] = 4;
break;
case AntennaInfoDedicated__transmissionMode_tm5:
phy_vars_ue->transmission_mode[eNB_id] = 5;
break;
case AntennaInfoDedicated__transmissionMode_tm6:
phy_vars_ue->transmission_mode[eNB_id] = 6;
break;
case AntennaInfoDedicated__transmissionMode_tm7:
lte_gold_ue_spec_port5(phy_vars_ue->lte_gold_uespec_port5_table, phy_vars_ue->frame_parms.Nid_cell, phy_vars_ue->pdcch_vars[0][eNB_id]->crnti);
phy_vars_ue->transmission_mode[eNB_id] = 7;
break;
default:
LOG_E(PHY,"Unknown transmission mode!\n");
break;
}
} else {
LOG_D(PHY,"[UE %d] Received NULL physicalConfigDedicated->antennaInfo from eNB %d\n",Mod_id, eNB_id);
}
if (physicalConfigDedicated->schedulingRequestConfig) {
if (physicalConfigDedicated->schedulingRequestConfig->present == SchedulingRequestConfig_PR_setup) {
phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex = physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex;
phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex=physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_ConfigIndex;
phy_vars_ue->scheduling_request_config[eNB_id].dsr_TransMax=physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax;
LOG_D(PHY,"scheduling_request_config.sr_PUCCH_ResourceIndex %d\n",phy_vars_ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
LOG_D(PHY,"scheduling_request_config.sr_ConfigIndex %d\n",phy_vars_ue->scheduling_request_config[eNB_id].sr_ConfigIndex);
LOG_D(PHY,"scheduling_request_config.dsr_TransMax %d\n",phy_vars_ue->scheduling_request_config[eNB_id].dsr_TransMax);
}
LOG_D(PHY,"------------------------------------------------------------\n");
}
if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated) {
phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srsConfigDedicatedSetup = 0;
if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srsConfigDedicatedSetup = 1;
phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].duration = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.duration;
phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].cyclicShift = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;
phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].freqDomainPosition = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_Bandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_ConfigIndex = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_HoppingBandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;
phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].transmissionComb = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
LOG_D(PHY,"soundingrs_ul_config_dedicated.srs_ConfigIndex %d\n",phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_ConfigIndex);
}
LOG_D(PHY,"------------------------------------------------------------\n");
}
if (physicalConfigDedicated->cqi_ReportConfig) {
if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic) {
// configure PUSCH CQI reporting
phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic;
if ((phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm12) &&
(phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm30) &&
(phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm31))
LOG_E(PHY,"Unsupported Aperiodic CQI Feedback Mode : %d\n",phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic);
}
if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) {
if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_setup) {
// configure PUCCH CQI reporting
phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_pmi_ConfigIndex;
if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex)
phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex;
}
else if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_release) {
// handle release
phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1;
phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1;
}
}
}
#ifdef CBA
if (physicalConfigDedicated->pusch_CBAConfigDedicated_vlola) {
phy_vars_ue->pusch_ca_config_dedicated[eNB_id].betaOffset_CA_Index = (uint16_t) *physicalConfigDedicated->pusch_CBAConfigDedicated_vlola->betaOffset_CBA_Index;
phy_vars_ue->pusch_ca_config_dedicated[eNB_id].cShift = (uint16_t) *physicalConfigDedicated->pusch_CBAConfigDedicated_vlola->cShift_CBA;
LOG_D(PHY,"[UE %d ] physicalConfigDedicated pusch CBA config dedicated: beta offset %d cshift %d \n",Mod_id,
phy_vars_ue->pusch_ca_config_dedicated[eNB_id].betaOffset_CA_Index,
phy_vars_ue->pusch_ca_config_dedicated[eNB_id].cShift);
}
#endif
} else {
LOG_D(PHY,"[PHY][UE %d] Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id,eNB_id);
return;
}
// fill cqi parameters for periodic CQI reporting
get_cqipmiri_params(phy_vars_ue,eNB_id);
// disable MIB SIB decoding once we are on connected mode
LOG_I(PHY,"Disabling SIB MIB decoding \n");
phy_vars_ue->decode_SIB = 0;
phy_vars_ue->decode_MIB = 0;
//phy_vars_ue->pdcch_vars[1][eNB_id]->crnti = phy_vars_ue->pdcch_vars[0][eNB_id]->crnti;
if(phy_vars_ue->pdcch_vars[0][eNB_id]->crnti == 0x1234)
phy_vars_ue->pdcch_vars[0][eNB_id]->crnti = phy_vars_ue->pdcch_vars[1][eNB_id]->crnti;
else
phy_vars_ue->pdcch_vars[1][eNB_id]->crnti = phy_vars_ue->pdcch_vars[0][eNB_id]->crnti;
LOG_I(PHY,"C-RNTI %x %x \n", phy_vars_ue->pdcch_vars[0][eNB_id]->crnti,
phy_vars_ue->pdcch_vars[1][eNB_id]->crnti);
}
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)
{
// uint8_t i;
if (eNB_flag == 0 ) {
//LOG_D(PHY,"[UE %d] configure cba group %d with rnti %x, num active cba grp %d\n", index, index, cba_rnti, num_active_cba_groups);
PHY_vars_UE_g[Mod_id][CC_id]->ulsch[index]->num_active_cba_groups=num_active_cba_groups;
PHY_vars_UE_g[Mod_id][CC_id]->ulsch[index]->cba_rnti[cba_group_id]=cba_rnti;
} else {
//for (i=index; i < NUMBER_OF_UE_MAX; i+=num_active_cba_groups){
// LOG_D(PHY,"[eNB %d] configure cba group %d with rnti %x for UE %d, num active cba grp %d\n",Mod_id, i%num_active_cba_groups, cba_rnti, i, num_active_cba_groups);
PHY_vars_eNB_g[Mod_id][CC_id]->ulsch[index]->num_active_cba_groups=num_active_cba_groups;
PHY_vars_eNB_g[Mod_id][CC_id]->ulsch[index]->cba_rnti[cba_group_id] = cba_rnti;
//}
}
}
void phy_init_lte_top(LTE_DL_FRAME_PARMS *frame_parms)
{
crcTableInit();
ccodedot11_init();
ccodedot11_init_inv();
ccodelte_init();
ccodelte_init_inv();
treillis_table_init();
phy_generate_viterbi_tables();
phy_generate_viterbi_tables_lte();
init_td8();
init_td16();
#ifdef __AVX2__
init_td16avx2();
#endif
lte_sync_time_init(frame_parms);
generate_ul_ref_sigs();
generate_ul_ref_sigs_rx();
generate_64qam_table();
generate_16qam_table();
generate_RIV_tables();
init_unscrambling_lut();
init_scrambling_lut();
//set_taus_seed(1328);
}
/*! \brief Helper function to allocate memory for DLSCH data structures.
* \param[out] pdsch Pointer to the LTE_UE_PDSCH structure to initialize.
* \param[in] frame_parms LTE_DL_FRAME_PARMS structure.
* \note This function is optimistic in that it expects malloc() to succeed.
*/
void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS* const fp )
{
AssertFatal( pdsch, "pdsch==0" );
pdsch->pmi_ext = (uint8_t*)malloc16_clear( fp->N_RB_DL );
pdsch->llr[0] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) );
pdsch->llr128 = (int16_t**)malloc16_clear( sizeof(int16_t*) );
// FIXME! no further allocation for (int16_t*)pdsch->llr128 !!! expect SIGSEGV
// FK, 11-3-2015: this is only as a temporary pointer, no memory is stored there
pdsch->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch->rxdataF_uespec_pilots = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch->rxdataF_comp0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch->rho = (int32_t**)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t*) );
pdsch->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch->dl_bf_ch_estimates = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch->dl_bf_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
//pdsch->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
//pdsch->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch->dl_ch_mag0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch->dl_ch_magb0 = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
// the allocated memory size is fixed:
AssertFatal( fp->nb_antennas_rx <= 2, "nb_antennas_rx > 2" );
for (int i=0; i<fp->nb_antennas_rx; i++) {
pdsch->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->N_RB_DL*12*7*2) );
for (int j=0; j<4; j++) { //fp->nb_antennas_tx; j++)
const int idx = (j<<1)+i;
const size_t num = 7*2*fp->N_RB_DL*12;
pdsch->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdsch->rxdataF_uespec_pilots[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * fp->N_RB_DL*12);
pdsch->rxdataF_comp0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdsch->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdsch->dl_bf_ch_estimates[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * fp->ofdm_symbol_size*7*2);
pdsch->dl_bf_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
//pdsch->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
//pdsch->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdsch->dl_ch_mag0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdsch->dl_ch_magb0[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
}
}
}
int phy_init_lte_ue(PHY_VARS_UE *ue,
int nb_connected_eNB,
uint8_t abstraction_flag)
{
// create shortcuts
LTE_DL_FRAME_PARMS* const fp = &ue->frame_parms;
LTE_UE_COMMON* const common_vars = &ue->common_vars;
LTE_UE_PDSCH** const pdsch_vars_th0 = ue->pdsch_vars[0];
LTE_UE_PDSCH** const pdsch_vars_th1 = ue->pdsch_vars[1];
LTE_UE_PDSCH** const pdsch_vars_SI = ue->pdsch_vars_SI;
LTE_UE_PDSCH** const pdsch_vars_ra = ue->pdsch_vars_ra;
LTE_UE_PDSCH** const pdsch_vars_mch = ue->pdsch_vars_MCH;
LTE_UE_PBCH** const pbch_vars = ue->pbch_vars;
LTE_UE_PDCCH** const pdcch_vars_th0 = ue->pdcch_vars[0];
LTE_UE_PDCCH** const pdcch_vars_th1 = ue->pdcch_vars[1];
LTE_UE_PRACH** const prach_vars = ue->prach_vars;
int i,j,k,l;
int eNB_id;
printf("Initializing UE vars (abstraction %"PRIu8") for eNB TXant %"PRIu8", UE RXant %"PRIu8"\n",abstraction_flag,fp->nb_antennas_tx,fp->nb_antennas_rx);
LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_UE][MOD %02u][]\n", ue->Mod_id+NB_eNB_INST);
// many memory allocation sizes are hard coded
AssertFatal( fp->nb_antennas_rx <= 2, "hard coded allocation for ue_common_vars->dl_ch_estimates[eNB_id]" );
AssertFatal( ue->n_connected_eNB <= NUMBER_OF_CONNECTED_eNB_MAX, "n_connected_eNB is too large" );
// init phy_vars_ue
for (i=0; i<4; i++) {
ue->rx_gain_max[i] = 135;
ue->rx_gain_med[i] = 128;
ue->rx_gain_byp[i] = 120;
}
ue->n_connected_eNB = nb_connected_eNB;
for(eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) {
ue->total_TBS[eNB_id] = 0;
ue->total_TBS_last[eNB_id] = 0;
ue->bitrate[eNB_id] = 0;
ue->total_received_bits[eNB_id] = 0;
}
for (i=0;i<10;i++)
ue->tx_power_dBm[i]=-127;
if (abstraction_flag == 0) {
// init TX buffers
common_vars->txdata = (int32_t**)malloc16( fp->nb_antennas_tx*sizeof(int32_t*) );
common_vars->txdataF = (int32_t **)malloc16( fp->nb_antennas_tx*sizeof(int32_t*) );
for (i=0; i<fp->nb_antennas_tx; i++) {
common_vars->txdata[i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) );
common_vars->txdataF[i] = (int32_t *)malloc16_clear( fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) );
}
// init RX buffers
common_vars->rxdata = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
common_vars->common_vars_rx_data_per_thread[0].rxdataF = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
common_vars->common_vars_rx_data_per_thread[1].rxdataF = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
for (i=0; i<fp->nb_antennas_rx; i++) {
common_vars->rxdata[i] = (int32_t*) malloc16_clear( (fp->samples_per_tti*10+2048)*sizeof(int32_t) );
common_vars->common_vars_rx_data_per_thread[0].rxdataF[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->ofdm_symbol_size*14) );
common_vars->common_vars_rx_data_per_thread[1].rxdataF[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->ofdm_symbol_size*14) );
}
}
// Channel estimates
for (eNB_id=0; eNB_id<7; eNB_id++) {
common_vars->common_vars_rx_data_per_thread[0].dl_ch_estimates[eNB_id] = (int32_t**)malloc16_clear(8*sizeof(int32_t*));
common_vars->common_vars_rx_data_per_thread[1].dl_ch_estimates[eNB_id] = (int32_t**)malloc16_clear(8*sizeof(int32_t*));
common_vars->common_vars_rx_data_per_thread[0].dl_ch_estimates_time[eNB_id] = (int32_t**)malloc16_clear(8*sizeof(int32_t*));
common_vars->common_vars_rx_data_per_thread[1].dl_ch_estimates_time[eNB_id] = (int32_t**)malloc16_clear(8*sizeof(int32_t*));
for (i=0; i<fp->nb_antennas_rx; i++)
for (j=0; j<4; j++) {
int idx = (j<<1) + i;
common_vars->common_vars_rx_data_per_thread[0].dl_ch_estimates[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->symbols_per_tti*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH) );
common_vars->common_vars_rx_data_per_thread[1].dl_ch_estimates[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->symbols_per_tti*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH) );
common_vars->common_vars_rx_data_per_thread[0].dl_ch_estimates_time[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 );
common_vars->common_vars_rx_data_per_thread[1].dl_ch_estimates_time[eNB_id][idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 );
}
}
// DLSCH
for (eNB_id=0; eNB_id<ue->n_connected_eNB; eNB_id++) {
pdsch_vars_th0[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
pdsch_vars_th1[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
pdsch_vars_SI[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
pdsch_vars_ra[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
pdsch_vars_mch[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear(sizeof(LTE_UE_PDSCH));
pdcch_vars_th0[eNB_id] = (LTE_UE_PDCCH *)malloc16_clear(sizeof(LTE_UE_PDCCH));
pdcch_vars_th1[eNB_id] = (LTE_UE_PDCCH *)malloc16_clear(sizeof(LTE_UE_PDCCH));
prach_vars[eNB_id] = (LTE_UE_PRACH *)malloc16_clear(sizeof(LTE_UE_PRACH));
pbch_vars[eNB_id] = (LTE_UE_PBCH *)malloc16_clear(sizeof(LTE_UE_PBCH));
if (abstraction_flag == 0) {
phy_init_lte_ue__PDSCH( pdsch_vars_th0[eNB_id], fp );
phy_init_lte_ue__PDSCH( pdsch_vars_th1[eNB_id], fp );
// thread 0
pdsch_vars_th0[eNB_id]->llr_shifts = (uint8_t*)malloc16_clear(7*2*fp->N_RB_DL*12);
pdsch_vars_th0[eNB_id]->llr_shifts_p = pdsch_vars_th0[eNB_id]->llr_shifts;
pdsch_vars_th0[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) );
pdsch_vars_th0[eNB_id]->llr128_2ndstream = (int16_t**)malloc16_clear( sizeof(int16_t*) );
pdsch_vars_th0[eNB_id]->rho = (int32_t**)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t*) );
// thread 0
pdsch_vars_th1[eNB_id]->llr_shifts = (uint8_t*)malloc16_clear(7*2*fp->N_RB_DL*12);
pdsch_vars_th1[eNB_id]->llr_shifts_p = pdsch_vars_th0[eNB_id]->llr_shifts;
pdsch_vars_th1[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) );
pdsch_vars_th1[eNB_id]->llr128_2ndstream = (int16_t**)malloc16_clear( sizeof(int16_t*) );
pdsch_vars_th1[eNB_id]->rho = (int32_t**)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t*) );
for (int i=0; i<fp->nb_antennas_rx; i++){
pdsch_vars_th0[eNB_id]->rho[i] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
pdsch_vars_th1[eNB_id]->rho[i] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
}
pdsch_vars_th0[eNB_id]->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch_vars_th1[eNB_id]->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
for (i=0; i<fp->nb_antennas_rx; i++)
for (j=0; j<4; j++) {
const int idx = (j<<1)+i;
const size_t num = 7*2*fp->N_RB_DL*12+4;
pdsch_vars_th0[eNB_id]->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdsch_vars_th1[eNB_id]->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
}
//const size_t num = 7*2*fp->N_RB_DL*12+4;
for (k=0;k<8;k++) { //harq_pid
for (l=0;l<8;l++) { //round
pdsch_vars_th0[eNB_id]->rxdataF_comp1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch_vars_th0[eNB_id]->dl_ch_rho_ext[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch_vars_th0[eNB_id]->dl_ch_mag1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch_vars_th0[eNB_id]->dl_ch_magb1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch_vars_th1[eNB_id]->rxdataF_comp1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch_vars_th1[eNB_id]->dl_ch_rho_ext[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch_vars_th1[eNB_id]->dl_ch_mag1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdsch_vars_th1[eNB_id]->dl_ch_magb1[k][l] = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
for (int i=0; i<fp->nb_antennas_rx; i++)
for (int j=0; j<4; j++) { //frame_parms->nb_antennas_tx; j++)
const int idx = (j<<1)+i;
pdsch_vars_th0[eNB_id]->dl_ch_rho_ext[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
pdsch_vars_th0[eNB_id]->rxdataF_comp1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
pdsch_vars_th0[eNB_id]->dl_ch_mag1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
pdsch_vars_th0[eNB_id]->dl_ch_magb1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
pdsch_vars_th1[eNB_id]->dl_ch_rho_ext[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
pdsch_vars_th1[eNB_id]->rxdataF_comp1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
pdsch_vars_th1[eNB_id]->dl_ch_mag1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
pdsch_vars_th1[eNB_id]->dl_ch_magb1[k][l][idx] = (int32_t*)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) );
}
}
}
phy_init_lte_ue__PDSCH( pdsch_vars_SI[eNB_id], fp );
phy_init_lte_ue__PDSCH( pdsch_vars_ra[eNB_id], fp );
phy_init_lte_ue__PDSCH( pdsch_vars_mch[eNB_id], fp );
// 100 PRBs * 12 REs/PRB * 4 PDCCH SYMBOLS * 2 LLRs/RE
pdcch_vars_th0[eNB_id]->llr = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) );
pdcch_vars_th0[eNB_id]->llr16 = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) );
pdcch_vars_th0[eNB_id]->wbar = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) );
pdcch_vars_th0[eNB_id]->e_rx = (int8_t*)malloc16_clear( 4*2*100*12 );
pdcch_vars_th0[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdcch_vars_th0[eNB_id]->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdcch_vars_th0[eNB_id]->rho = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
pdcch_vars_th0[eNB_id]->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdcch_vars_th0[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdcch_vars_th1[eNB_id]->llr = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) );
pdcch_vars_th1[eNB_id]->llr16 = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) );
pdcch_vars_th1[eNB_id]->wbar = (uint16_t*)malloc16_clear( 2*4*100*12*sizeof(uint16_t) );
pdcch_vars_th1[eNB_id]->e_rx = (int8_t*)malloc16_clear( 4*2*100*12 );
pdcch_vars_th1[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdcch_vars_th1[eNB_id]->dl_ch_rho_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdcch_vars_th1[eNB_id]->rho = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
pdcch_vars_th1[eNB_id]->rxdataF_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pdcch_vars_th1[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
for (i=0; i<fp->nb_antennas_rx; i++) {
//ue_pdcch_vars[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->N_RB_DL*12*7*2) );
pdcch_vars_th0[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(100*12*4) );
pdcch_vars_th1[eNB_id]->rho[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(100*12*4) );
for (j=0; j<4; j++) { //fp->nb_antennas_tx; j++)
int idx = (j<<1)+i;
// size_t num = 7*2*fp->N_RB_DL*12;
size_t num = 4*100*12; // 4 symbols, 100 PRBs, 12 REs per PRB
pdcch_vars_th0[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdcch_vars_th0[eNB_id]->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdcch_vars_th0[eNB_id]->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdcch_vars_th0[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdcch_vars_th1[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdcch_vars_th1[eNB_id]->dl_ch_rho_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdcch_vars_th1[eNB_id]->rxdataF_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
pdcch_vars_th1[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
}
}
// PBCH
pbch_vars[eNB_id]->rxdataF_ext = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
pbch_vars[eNB_id]->rxdataF_comp = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pbch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
pbch_vars[eNB_id]->llr = (int8_t*)malloc16_clear( 1920 );
prach_vars[eNB_id]->prachF = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) );
prach_vars[eNB_id]->prach = (int16_t*)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) );
for (i=0; i<fp->nb_antennas_rx; i++) {
pbch_vars[eNB_id]->rxdataF_ext[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 );
for (j=0; j<4; j++) {//fp->nb_antennas_tx;j++) {
int idx = (j<<1)+i;
pbch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 );
pbch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t)*6*12*4 );
}
}
}
pbch_vars[eNB_id]->decoded_output = (uint8_t*)malloc16_clear( 64 );
}
// initialization for the last instance of pdsch_vars (used for MU-MIMO)
pdsch_vars_th0[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) );
pdsch_vars_th1[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) );
pdsch_vars_SI[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) );
pdsch_vars_ra[eNB_id] = (LTE_UE_PDSCH *)malloc16_clear( sizeof(LTE_UE_PDSCH) );
if (abstraction_flag == 0) {
phy_init_lte_ue__PDSCH( pdsch_vars_th0[eNB_id], fp );
pdsch_vars_th0[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) );
phy_init_lte_ue__PDSCH( pdsch_vars_th1[eNB_id], fp );
pdsch_vars_th1[eNB_id]->llr[1] = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) );
} else { //abstraction == 1
ue->sinr_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) );
}
ue->sinr_CQI_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) );
ue->init_averaging = 1;
// default value until overwritten by RRCConnectionReconfiguration
if (fp->nb_antenna_ports_eNB==2)
ue->pdsch_config_dedicated->p_a = dBm3;
else
ue->pdsch_config_dedicated->p_a = dB0;
// set channel estimation to do linear interpolation in time
ue->high_speed_flag = 1;
ue->ch_est_alpha = 24576;
// enable MIB/SIB decoding by default
ue->decode_MIB = 1;
ue->decode_SIB = 1;
init_prach_tables(839);
return 0;
} }
int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
unsigned char is_secondary_eNB,
unsigned char abstraction_flag)
{
// shortcuts
LTE_DL_FRAME_PARMS* const fp = &eNB->frame_parms;
LTE_eNB_COMMON* const common_vars = &eNB->common_vars;
LTE_eNB_PUSCH** const pusch_vars = eNB->pusch_vars;
LTE_eNB_SRS* const srs_vars = eNB->srs_vars;
LTE_eNB_PRACH* const prach_vars = &eNB->prach_vars;
int i, j, eNB_id, UE_id;
int re;
eNB->total_dlsch_bitrate = 0;
eNB->total_transmitted_bits = 0;
eNB->total_system_throughput = 0;
eNB->check_for_MUMIMO_transmissions=0;
LOG_I(PHY,"[eNB %"PRIu8"] Initializing DL_FRAME_PARMS : N_RB_DL %"PRIu8", PHICH Resource %d, PHICH Duration %d\n",
eNB->Mod_id,
fp->N_RB_DL,fp->phich_config_common.phich_resource,
fp->phich_config_common.phich_duration);
LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_eNB][MOD %02"PRIu8"][]\n", eNB->Mod_id);
if (eNB->node_function != NGFI_RRU_IF4p5) {
lte_gold(fp,eNB->lte_gold_table,fp->Nid_cell);
generate_pcfich_reg_mapping(fp);
generate_phich_reg_mapping(fp);
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
eNB->first_run_timing_advance[UE_id] =
1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here.
// clear whole structure
bzero( &eNB->UE_stats[UE_id], sizeof(LTE_eNB_UE_stats) );
eNB->physicalConfigDedicated[UE_id] = NULL;
}
eNB->first_run_I0_measurements = 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here.
}
// for (eNB_id=0; eNB_id<3; eNB_id++) {
{
eNB_id=0;
if (abstraction_flag==0) {
// TX vars
if (eNB->node_function != NGFI_RCC_IF4p5)
common_vars->txdata[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_tx*sizeof(int32_t*));
common_vars->txdataF[eNB_id] = (int32_t **)malloc16(NB_ANTENNA_PORTS_ENB*sizeof(int32_t*));
common_vars->txdataF_BF[eNB_id] = (int32_t **)malloc16(fp->nb_antennas_tx*sizeof(int32_t*));
if (eNB->node_function != NGFI_RRU_IF5) {
for (i=0; i<NB_ANTENNA_PORTS_ENB; i++) {
if (i<fp->nb_antenna_ports_eNB || i==5) {
common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) );
#ifdef DEBUG_PHY
printf("[openair][LTE_PHY][INIT] common_vars->txdataF[%d][%d] = %p (%lu bytes)\n",
eNB_id,i,common_vars->txdataF[eNB_id][i],
fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t));
#endif
}
}
}
for (i=0; i<fp->nb_antennas_tx; i++) {
common_vars->txdataF_BF[eNB_id][i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t) );
if (eNB->node_function != NGFI_RCC_IF4p5)
// Allocate 10 subframes of I/Q TX signal data (time) if not
common_vars->txdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) );
#ifdef DEBUG_PHY
printf("[openair][LTE_PHY][INIT] common_vars->txdata[%d][%d] = %p (%lu bytes)\n",eNB_id,i,common_vars->txdata[eNB_id][i],
fp->samples_per_tti*10*sizeof(int32_t));
#endif
}
for (i=0; i<NB_ANTENNA_PORTS_ENB; i++) {
if (i<fp->nb_antenna_ports_eNB || i==5) {
common_vars->beam_weights[eNB_id][i] = (int32_t **)malloc16_clear(fp->nb_antennas_tx*sizeof(int32_t*));
for (j=0; j<fp->nb_antennas_tx; j++) {
common_vars->beam_weights[eNB_id][i][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t));
// antenna ports 0-3 are mapped on antennas 0-3
// antenna port 4 is mapped on antenna 0
// antenna ports 5-14 are mapped on all antennas
if (((i<4) && (i==j)) || ((i==4) && (j==0))) {
for (re=0; re<fp->ofdm_symbol_size; re++)
common_vars->beam_weights[eNB_id][i][j][re] = 0x00007fff;
}
else if (i>4) {
for (re=0; re<fp->ofdm_symbol_size; re++)
common_vars->beam_weights[eNB_id][i][j][re] = 0x00007fff/fp->nb_antennas_tx;
}
#ifdef DEBUG_PHY
msg("[openair][LTE_PHY][INIT] lte_common_vars->beam_weights[%d][%d][%d] = %p (%zu bytes)\n",
eNB_id,i,j,common_vars->beam_weights[eNB_id][i][j],
fp->ofdm_symbol_size*sizeof(int32_t));
#endif
}
}
}
// RX vars
if (eNB->node_function != NGFI_RCC_IF4p5) {
common_vars->rxdata[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) );
common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) );
}
common_vars->rxdataF[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) );
for (i=0; i<fp->nb_antennas_rx; i++) {
if (eNB->node_function != NGFI_RCC_IF4p5) {
// allocate 2 subframes of I/Q signal data (time) if not an RCC (no time-domain signals)
common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) );
if (eNB->node_function != NGFI_RRU_IF5)
// allocate 2 subframes of I/Q signal data (time, 7.5 kHz offset)
common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( 2*fp->samples_per_tti*2*sizeof(int32_t) );
}
if (eNB->node_function != NGFI_RRU_IF5)
// allocate 2 subframes of I/Q signal data (frequency)
common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(2*fp->ofdm_symbol_size*fp->symbols_per_tti) );
#ifdef DEBUG_PHY
printf("[openair][LTE_PHY][INIT] common_vars->rxdata[%d][%d] = %p (%lu bytes)\n",eNB_id,i,common_vars->rxdata[eNB_id][i],fp->samples_per_tti*10*sizeof(int32_t));
if (eNB->node_function != NGFI_RRU_IF5)
printf("[openair][LTE_PHY][INIT] common_vars->rxdata_7_5kHz[%d][%d] = %p (%lu bytes)\n",eNB_id,i,common_vars->rxdata_7_5kHz[eNB_id][i],fp->samples_per_tti*2*sizeof(int32_t));
#endif
common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(fp->ofdm_symbol_size*fp->symbols_per_tti) );
}
if ((eNB->node_function != NGFI_RRU_IF4p5)&&(eNB->node_function != NGFI_RRU_IF5)) {
// Channel estimates for SRS
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
srs_vars[UE_id].srs_ch_estimates[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
srs_vars[UE_id].srs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
for (i=0; i<fp->nb_antennas_rx; i++) {
srs_vars[UE_id].srs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size );
srs_vars[UE_id].srs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 );
}
} //UE_id
common_vars->sync_corr[eNB_id] = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*fp->samples_per_tti );
}
} // abstraction_flag = 0
else { //UPLINK abstraction = 1
eNB->sinr_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) );
}
} //eNB_id
if (abstraction_flag==0) {
if ((eNB->node_function != NGFI_RRU_IF4p5)&&(eNB->node_function != NGFI_RRU_IF5)) {
generate_ul_ref_sigs_rx();
// SRS
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
srs_vars[UE_id].srs = (int32_t*)malloc16_clear(2*fp->ofdm_symbol_size*sizeof(int32_t));
}
}
}
// ULSCH VARS, skip if NFGI_RRU_IF4
if ((eNB->node_function!=NGFI_RRU_IF4p5)&&(eNB->node_function != NGFI_RRU_IF5))
prach_vars->prachF = (int16_t*)malloc16_clear( 1024*2*sizeof(int16_t) );
/* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */
AssertFatal(fp->nb_antennas_rx <= sizeof(prach_vars->rxsigF) / sizeof(prach_vars->rxsigF[0]),
"nb_antennas_rx too large");
for (i=0; i<fp->nb_antennas_rx; i++) {
prach_vars->rxsigF[i] = (int16_t*)malloc16_clear( fp->ofdm_symbol_size*12*2*sizeof(int16_t) );
#ifdef DEBUG_PHY
printf("[openair][LTE_PHY][INIT] prach_vars->rxsigF[%d] = %p\n",i,prach_vars->rxsigF[i]);
#endif
}
if ((eNB->node_function != NGFI_RRU_IF4p5)&&(eNB->node_function != NGFI_RRU_IF5)) {
AssertFatal(fp->nb_antennas_rx <= sizeof(prach_vars->prach_ifft) / sizeof(prach_vars->prach_ifft[0]),
"nb_antennas_rx too large");
for (i=0; i<fp->nb_antennas_rx; i++) {
prach_vars->prach_ifft[i] = (int16_t*)malloc16_clear(1024*2*sizeof(int16_t));
#ifdef DEBUG_PHY
printf("[openair][LTE_PHY][INIT] prach_vars->prach_ifft[%d] = %p\n",i,prach_vars->prach_ifft[i]);
#endif
}
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
//FIXME
pusch_vars[UE_id] = (LTE_eNB_PUSCH*)malloc16_clear( NUMBER_OF_UE_MAX*sizeof(LTE_eNB_PUSCH) );
if (abstraction_flag==0) {
for (eNB_id=0; eNB_id<3; eNB_id++) {
pusch_vars[UE_id]->rxdataF_ext[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
pusch_vars[UE_id]->rxdataF_ext2[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
pusch_vars[UE_id]->drs_ch_estimates[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
pusch_vars[UE_id]->rxdataF_comp[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
pusch_vars[UE_id]->ul_ch_mag[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
pusch_vars[UE_id]->ul_ch_magb[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
for (i=0; i<fp->nb_antennas_rx; i++) {
// RK 2 times because of output format of FFT!
// FIXME We should get rid of this
pusch_vars[UE_id]->rxdataF_ext[eNB_id][i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti );
pusch_vars[UE_id]->rxdataF_ext2[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti );
pusch_vars[UE_id]->drs_ch_estimates[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti );
pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id][i] = (int32_t*)malloc16_clear( 2*2*sizeof(int32_t)*fp->ofdm_symbol_size );
pusch_vars[UE_id]->rxdataF_comp[eNB_id][i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti );
pusch_vars[UE_id]->ul_ch_mag[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 );
pusch_vars[UE_id]->ul_ch_magb[eNB_id][i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 );
}
} //eNB_id
pusch_vars[UE_id]->llr = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) );
} // abstraction_flag
} //UE_id
if (abstraction_flag==0) {
if (is_secondary_eNB) {
for (eNB_id=0; eNB_id<3; eNB_id++) {
eNB->dl_precoder_SeNB[eNB_id] = (int **)malloc16(4*sizeof(int*));
if (eNB->dl_precoder_SeNB[eNB_id]) {
#ifdef DEBUG_PHY
printf("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] allocated at %p\n",eNB_id,
eNB->dl_precoder_SeNB[eNB_id]);
#endif
} else {
printf("[openair][SECSYS_PHY][INIT] eNB->dl_precoder_SeNB[%d] not allocated\n",eNB_id);
return(-1);
}
for (j=0; j<fp->nb_antennas_tx; j++) {
eNB->dl_precoder_SeNB[eNB_id][j] = (int *)malloc16(2*sizeof(int)*(fp->ofdm_symbol_size)); // repeated format (hence the '2*')
if (eNB->dl_precoder_SeNB[eNB_id][j]) {
#ifdef DEBUG_PHY
printf("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] allocated at %p\n",eNB_id,j,
eNB->dl_precoder_SeNB[eNB_id][j]);
#endif
memset(eNB->dl_precoder_SeNB[eNB_id][j],0,2*sizeof(int)*(fp->ofdm_symbol_size));
} else {
printf("[openair][LTE_PHY][INIT] eNB->dl_precoder_SeNB[%d][%d] not allocated\n",eNB_id,j);
return(-1);
}
} //for(j=...nb_antennas_tx
} //for(eNB_id...
}
}
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
eNB->UE_stats_ptr[UE_id] = &eNB->UE_stats[UE_id];
//defaul value until overwritten by RRCConnectionReconfiguration
if (fp->nb_antenna_ports_eNB==2)
eNB->pdsch_config_dedicated->p_a = dBm3;
else
eNB->pdsch_config_dedicated->p_a = dB0;
init_prach_tables(839);
} // node_function != NGFI_RRU_IF4p5
return (0);
}
...@@ -18,374 +18,143 @@ ...@@ -18,374 +18,143 @@
* For more information about the OpenAirInterface (OAI) Software Alliance: * For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file LAYER2/MAC/defs.h /*! \file LAYER2/MAC/defs.h
* \brief MAC data structures, constant, and function prototype * \brief MAC data structures, constant, and function prototype
* \author Navid Nikaein and Raymond Knopp * \author Navid Nikaein and Raymond Knopp
* \date 2011 * \date 2011
* \version 0.5 * \version 0.5
* \email navid.nikaein@eurecom.fr * \email navid.nikaein@eurecom.fr
*/ */
/** @defgroup _oai2 openair2 Reference Implementation /** @defgroup _oai2 openair2 Reference Implementation
* @ingroup _ref_implementation_ * @ingroup _ref_implementation_
* @{ * @{
*/ */
/*@}*/ /*@}*/
#ifndef __LAYER2_MAC_DEFS_NB_IOT_H__
#ifndef __LAYER2_MAC_DEFS_H__ #define __LAYER2_MAC_DEFS_NB_IOT_H__
#define __LAYER2_MAC_DEFS_H__
#ifdef USER_MODE #ifdef USER_MODE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#endif #endif
//#include "COMMON/openair_defs.h" //#include "COMMON/openair_defs.h"
#include "COMMON/platform_constants.h" #include "COMMON/platform_constants.h"
#include "COMMON/mac_rrc_primitives.h" #include "COMMON/mac_rrc_primitives.h"
#include "PHY/defs.h" #include "PHY/defs.h"
#include "RadioResourceConfigCommon.h" #include "RadioResourceConfigCommonSIB-NB-r13.h"
#include "RadioResourceConfigDedicated.h" #include "RadioResourceConfigDedicated-NB-r13.h"
#include "MeasGapConfig.h" #include "RACH-ConfigCommon-NB-r13.h"
#include "TDD-Config.h" #include "MasterInformationBlock-NB.h"
#include "RACH-ConfigCommon.h" #include "BCCH-BCH-Message-NB.h"
#include "MeasObjectToAddModList.h"
#include "MobilityControlInfo.h"
#if defined(Rel10) || defined(Rel14)
#include "MBSFN-AreaInfoList-r9.h"
#include "MBSFN-SubframeConfigList.h"
#include "PMCH-InfoList-r9.h"
#include "SCellToAddMod-r10.h"
#endif
//#ifdef PHY_EMUL //#ifdef PHY_EMUL
//#include "SIMULATION/PHY_EMULATION/impl_defs.h" //#include "SIMULATION/PHY_EMULATION/impl_defs.h"
//#endif //#endif
/** @defgroup _mac MAC /** @defgroup _mac MAC
* @ingroup _oai2 * @ingroup _oai2
* @{ * @{
*/ */
#define BCCH_PAYLOAD_SIZE_MAX 128
#define CCCH_PAYLOAD_SIZE_MAX 128
#define PCCH_PAYLOAD_SIZE_MAX 128
#define SCH_PAYLOAD_SIZE_MAX 4096
/// Logical channel ids from 36-311 (Note BCCH is not specified in 36-311, uses the same as first DRB)
/*!MBMS is not supported in NB-IoT */
#ifdef USER_MODE
#define printk printf
#endif //USER_MODE
/*In NB-IoT, 36.321 6.1.3.1 Logical channel group ID is set to #0 */
/*!\brief Maximum number of logical channel group IDs */
#define MAX_NUM_LCGID 4
/*!\brief logical channl group ID 0 */
#define LCGID0 0
/*!\brief Maximum number of logical chanels 0-10*/
#define MAX_NUM_LCID 11
/*!\brief Maximum number od control elemenets */
#define MAX_NUM_CE 5
/*!\brief Maximum number of random access process */
#define NB_RA_PROC_MAX 4
/*!\brief size of buffer status report table */
#define BSR_TABLE_SIZE 64
/*!\brief The power headroom reporting range is from -23 ...+40 dB and beyond, with step 1 */
#define PHR_MAPPING_OFFSET 23 // if ( x>= -23 ) val = floor (x + 23)
/*There is no CQI & RB concept in NB-IoT*/
/*!\brief maximum number of resource block groups, not used in NB-IoT */
/*!\brief minimum value for channel quality indicator, not used in NB-IoT */
/*!\brief maximum value for channel quality indicator, not used in NB-IoT */
/*!\brief maximum number of supported bandwidth (1.4, 5, 10, 20 MHz) */
#define MAX_SUPPORTED_BW 4
/*!\brief CQI values range from 1 to 15 (4 bits), not used in NB-IoT */
/*!\brief value for indicating BSR Timer is not running */
#define MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF)
#define LCID_EMPTY 0
#define LCID_NOT_EMPTY 1
/*!\brief minimum RLC PDU size to be transmitted = min RLC Status PDU or RLC UM PDU SN 5 bits */
#define MIN_RLC_PDU_SIZE (2)
/*!\brief minimum MAC data needed for transmitting 1 min RLC PDU size + 1 byte MAC subHeader */
#define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE)
/*!\brief maximum number of slices / groups */
#define MAX_NUM_SLICES 4
/*
* eNB part
*/
/*
* 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;
/*!\brief DCI PDU filled by MAC for the PHY */
typedef struct {
uint8_t Num_ue_spec_dci ;
uint8_t Num_common_dci ;
// uint32_t nCCE;
uint32_t num_pdcch_symbols;
DCI_ALLOC_t dci_alloc[NUM_DCI_MAX] ;
} DCI_PDU_NB;
/*! \brief CCCH payload */
typedef struct {
uint8_t payload[CCCH_PAYLOAD_SIZE_MAX] ;
} __attribute__((__packed__))CCCH_PDU_NB;
/*! \brief BCCH payload */
typedef struct {
uint8_t payload[BCCH_PAYLOAD_SIZE_MAX] ;
} __attribute__((__packed__))BCCH_PDU_NB;
/*! \brief PCCH payload */
typedef struct {
uint8_t payload[PCCH_PAYLOAD_SIZE_MAX] ;
} __attribute__((__packed__))PCCH_PDU_NB;
/*MCCH & CC is not used in NB-IoT*/
/*! \brief Values of CCCH LCID for DLSCH */
//#define CCCH_LCHANID 0 not used in OAI
/*!\brief Values of BCCH0 logical channel for MIB*/
#define BCCH0 11 // MIB-NB
/*!\brief Values of BCCH1 logical channel for SIBs */
#define BCCH1 12 // SI-SIB-NBs
/*!\brief Values of PCCH logical channel */
#define PCCH 13 // Paging
/*!\brief Value of CCCH / SRB0 logical channel */
#define CCCH 0 // srb0
/*!\brief DCCH0 / SRB1bis logical channel */
#define DCCH0 3 // srb1bis
/*!\brief DCCH1 / SRB1 logical channel */
#define DCCH1 1 // srb1
/*!\brief DTCH0 DRB0 logical channel */
#define DTCH0 4 // DRB0
/*!\brief DTCH1 DRB1 logical channel */
#define DTCH1 5 // DRB1
// DLSCH LCHAN ID all the same as NB-IoT
/*!\brief LCID of UE contention resolution identity for DLSCH*/
#define UE_CONT_RES 28
/*!\brief LCID of timing advance for DLSCH */
#define TIMING_ADV_CMD 29
/*!\brief LCID of discontinous reception mode for DLSCH */
#define DRX_CMD 30
/*!\brief LCID of padding LCID for DLSCH */
#define SHORT_PADDING 31
//MCH/CC not defined in NB-IoT
// ULSCH LCHAN IDs the EXTENDED_POWER_HEADROOM POWER_HEADROOM TRUNCATED_BSR LONG_BSR is not used in NB-IoT
/*!\brief LCID of CRNTI for ULSCH */
#define CRNTI 27
/*!\brief LCID of short BSR for ULSCH */
#define SHORT_BSR 29
/*!\bitmaps for BSR Triggers */
#define BSR_TRIGGER_NONE (0) /* No BSR Trigger */
#define BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */
#define BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */
#define BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */
/*! \brief Downlink SCH PDU Structure */ /*! \brief Downlink SCH PDU Structure */
typedef struct { typedef struct {
int8_t payload[8][SCH_PAYLOAD_SIZE_MAX]; int8_t payload[8][SCH_PAYLOAD_SIZE_MAX];
uint16_t Pdu_size[8]; uint16_t Pdu_size[8];
} __attribute__ ((__packed__)) DLSCH_PDU_NB; } __attribute__ ((__packed__)) DLSCH_PDU_NB;
/*! \brief eNB template for UE context information */
/*MCH is not defined in NB-IoT*/
/*! \brief Uplink SCH PDU Structure */
typedef struct {
int8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */
uint16_t Pdu_size;
} __attribute__ ((__packed__)) ULSCH_PDU_NB;
#include "PHY/impl_defs_top.h"
/*!\brief UE ULSCH scheduling states*/
typedef enum {
S_UL_NONE =0,// used in rrc_mac_remove_ue
S_UL_WAITING,// used in add_new_ue
S_UL_SCHEDULED,// used in scheudle_ulsch_rnti
S_UL_BUFFERED,// not used
S_UL_NUM_STATUS// not used
} UE_ULSCH_STATUS_NB;
/*!\brief UE DLSCH scheduling states*/
typedef enum {
S_DL_NONE =0,//used in rrc_mac_remove_ue, scheudle_ue_spec,init_ue_sched_info
S_DL_WAITING,//used in schedule_next_dlue,fill_DLSCH_dci,add_new_ue
S_DL_SCHEDULED,//used in scheudle_ue_spec,fill_DLSCH_dci
S_DL_BUFFERED,//used in schedule_next_dlue
S_DL_NUM_STATUS// not used
} UE_DLSCH_STATUS_NB;
/*!\brief scheduling policy for the contention-based access */
/*CBA is not defined in NB-IoT*/
/*! \brief temporary struct for ULSCH sched */
typedef struct {
rnti_t rnti;
uint16_t subframe;
uint16_t serving_num;
UE_ULSCH_STATUS status;
} eNB_ULSCH_INFO_NB;
/*! \brief temp struct for DLSCH sched */
typedef struct { typedef struct {
/// C-RNTI of UE
rnti_t rnti; rnti_t rnti;
uint16_t weight; /// NDI from last scheduling
uint16_t subframe; uint8_t oldNDI[8];
uint16_t serving_num; /// NDI from last UL scheduling
UE_DLSCH_STATUS status; uint8_t oldNDI_UL[8];
} eNB_DLSCH_INFO_NB; /// Flag to indicate UL has been scheduled at least once
/*! \brief eNB overall statistics */ boolean_t ul_active;
typedef struct { /// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received)
/// num BCCH PDU per CC boolean_t configured;
uint32_t total_num_bcch_pdu; /// MCS from last scheduling
/// BCCH buffer size //Modify uint8_t mcs[8];
uint32_t bcch_buffer; /// TPC from last scheduling
/// total BCCH buffer size //Delete uint8_t oldTPC[8];
uint32_t total_bcch_buffer; // PHY interface info
/// BCCH MCS /// DCI format for DLSCH
uint32_t bcch_mcs; uint16_t DLSCH_dci_fmt;
/// Current Aggregation Level for DCI
/// num CCCH PDU per CC uint8_t DCI_aggregation_min;
uint32_t total_num_ccch_pdu; /// size of DLSCH size in bit
/// BCCH buffer size uint8_t DLSCH_dci_size_bits;
uint32_t ccch_buffer; /// DCI buffer for DLSCH
/// total BCCH buffer size /* rounded to 32 bits unit (actual value should be 8 due to the logic
uint32_t total_ccch_buffertotal_ccch_buffer; * of the function generate_dci0) */
/// BCCH MCS //Modifyuint8_t DLSCH_DCI[8][(((MAX_DCI_SIZE_BITS)+31)>>5)*4];
uint32_t ccch_mcs; /// Number of Allocated RBs for DL after scheduling (prior to frequency allocation)
//Delete uint16_t nb_rb[8]; // num_max_harq
/// num active users /// Number of Allocated RBs for UL after scheduling (prior to frequency allocation)
uint16_t num_dlactive_UEs; //Delete uint16_t nb_rb_ul[8]; // num_max_harq
/// available number of PRBs for a give SF fixed in 1 in NB-IoT /// Number of Allocated RBs by the ulsch preprocessor
uint16_t available_prbs; //Delete uint8_t pre_allocated_nb_rb_ul;
/// total number of PRB available for the user plane fixed in 1 in NB-IoT /// index of Allocated RBs by the ulsch preprocessor
uint32_t total_available_prbs; //Delete int8_t pre_allocated_rb_table_index_ul;
/// aggregation /// total allocated RBs
/// total avilable nccc : num control channel element //Delete int8_t total_allocated_rbs;
uint16_t available_ncces; /// pre-assigned MCS by the ulsch preprocessor
// only for a new transmission, should be extended for retransmission uint8_t pre_assigned_mcs_ul;
// current dlsch bit rate for all transport channels /// assigned MCS by the ulsch scheduler
uint32_t dlsch_bitrate; uint8_t assigned_mcs_ul;
// /// DCI buffer for ULSCH
uint32_t dlsch_bytes_tx; /* rounded to 32 bits unit (actual value should be 8 due to the logic
// * of the function generate_dci0) */
uint32_t dlsch_pdus_tx; //Modify uint8_t ULSCH_DCI[8][(((MAX_DCI_SIZE_BITS)+31)>>5)*4];
// /// DL DAI
uint32_t total_dlsch_bitrate; //Delete uint8_t DAI;
// /// UL DAI
uint32_t total_dlsch_bytes_tx; //Delete uint8_t DAI_ul[10];
// /// UL Scheduling Request Received
uint32_t total_dlsch_pdus_tx; //Delete uint8_t ul_SR;
/// Resource Block indication for each sub-band in MU-MIMO
// here for RX //Delete uint8_t rballoc_subband[8][50];
// // Logical channel info for link with RLC
uint32_t ulsch_bitrate; /// Last received UE BSR info for each logical channel group id
// uint8_t bsr_info[MAX_NUM_LCGID];
uint32_t ulsch_bytes_rx; /// LCGID mapping
// //Delete long lcgidmap[11];
uint64_t ulsch_pdus_rx; /// phr information, received from DPR MAC control element
int8_t phr_info;
uint32_t total_ulsch_bitrate; /// phr information, received from DPR MAC control element
// int8_t phr_info_configured;
uint32_t total_ulsch_bytes_rx; ///dl buffer info
// uint32_t dl_buffer_info[MAX_NUM_LCID];
uint32_t total_ulsch_pdus_rx; /// total downlink buffer info
uint32_t dl_buffer_total;
/// total downlink pdus
/// MAC agent-related stats uint32_t dl_pdus_total;
/// total number of scheduling decisions /// downlink pdus for each LCID
int sched_decisions; uint32_t dl_pdus_in_buffer[MAX_NUM_LCID];
/// missed deadlines /// creation time of the downlink buffer head for each LCID
int missed_deadlines; uint32_t dl_buffer_head_sdu_creation_time[MAX_NUM_LCID];
/// maximum creation time of the downlink buffer head across all LCID
} eNB_STATS_NB; uint32_t dl_buffer_head_sdu_creation_time_max;
/// a flag indicating that the downlink head SDU is segmented
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
uint32_t ul_buffer_creation_time[MAX_NUM_LCGID];
/// maximum uplink buffer creation time across all the LCIDs
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*/ /*! \brief eNB statistics for the connected UEs*/
typedef struct { typedef struct {
/// CRNTI of UE /// CRNTI of UE
rnti_t crnti; ///user id (rnti) of connected UEs rnti_t crnti; ///user id (rnti) of connected UEs
// rrc status // rrc status
...@@ -404,7 +173,6 @@ typedef struct { ...@@ -404,7 +173,6 @@ typedef struct {
uint16_t ncce_used; uint16_t ncce_used;
/// total avilable nccc for a retransmission: num control channel element /// total avilable nccc for a retransmission: num control channel element
uint16_t ncce_used_retx; uint16_t ncce_used_retx;
// mcs1 before the rate adaptaion // mcs1 before the rate adaptaion
uint8_t dlsch_mcs1; uint8_t dlsch_mcs1;
/// Target mcs2 after rate-adaptation /// Target mcs2 after rate-adaptation
...@@ -417,7 +185,6 @@ typedef struct { ...@@ -417,7 +185,6 @@ typedef struct {
uint32_t total_rbs_used; uint32_t total_rbs_used;
// total rb used for retransmission // total rb used for retransmission
uint32_t total_rbs_used_retx; uint32_t total_rbs_used_retx;
/// TX /// TX
/// Num pkt /// Num pkt
uint32_t num_pdu_tx[NB_RB_MAX]; uint32_t num_pdu_tx[NB_RB_MAX];
...@@ -427,7 +194,6 @@ typedef struct { ...@@ -427,7 +194,6 @@ typedef struct {
uint32_t num_retransmission; uint32_t num_retransmission;
/// instantaneous tx throughput for each TTI /// instantaneous tx throughput for each TTI
// uint32_t tti_throughput[NB_RB_MAX]; // uint32_t tti_throughput[NB_RB_MAX];
/// overall /// overall
// //
uint32_t dlsch_bitrate; uint32_t dlsch_bitrate;
...@@ -443,19 +209,15 @@ typedef struct { ...@@ -443,19 +209,15 @@ typedef struct {
uint64_t total_sdu_bytes; uint64_t total_sdu_bytes;
// total MAC pdu bytes // total MAC pdu bytes
uint64_t total_pdu_bytes; uint64_t total_pdu_bytes;
// total num pdu // total num pdu
uint32_t total_num_pdus; uint32_t total_num_pdus;
// //
// uint32_t avg_pdu_size; // uint32_t avg_pdu_size;
/// RX /// RX
/// preassigned mcs after rate adaptation /// preassigned mcs after rate adaptation
uint8_t ulsch_mcs1; uint8_t ulsch_mcs1;
/// adjusted mcs /// adjusted mcs
uint8_t ulsch_mcs2; uint8_t ulsch_mcs2;
/// estimated average pdu inter-departure time /// estimated average pdu inter-departure time
uint32_t avg_pdu_idt; uint32_t avg_pdu_idt;
/// estimated average pdu size /// estimated average pdu size
...@@ -463,10 +225,8 @@ typedef struct { ...@@ -463,10 +225,8 @@ typedef struct {
/// ///
uint32_t aggregated_pdu_size; uint32_t aggregated_pdu_size;
uint32_t aggregated_pdu_arrival; uint32_t aggregated_pdu_arrival;
/// uplink transport block size /// uplink transport block size
uint32_t ulsch_TBS; uint32_t ulsch_TBS;
/// total rb used for a new uplink transmission /// total rb used for a new uplink transmission
uint32_t num_retransmission_rx; uint32_t num_retransmission_rx;
/// total rb used for a new uplink transmission /// total rb used for a new uplink transmission
...@@ -479,7 +239,6 @@ typedef struct { ...@@ -479,7 +239,6 @@ typedef struct {
int32_t normalized_rx_power; int32_t normalized_rx_power;
/// target rx power /// target rx power
int32_t target_rx_power; int32_t target_rx_power;
/// num rx pdu /// num rx pdu
uint32_t num_pdu_rx[NB_RB_MAX]; uint32_t num_pdu_rx[NB_RB_MAX];
/// num bytes rx /// num bytes rx
...@@ -488,7 +247,6 @@ typedef struct { ...@@ -488,7 +247,6 @@ typedef struct {
// uint32_t tti_goodput[NB_RB_MAX]; // uint32_t tti_goodput[NB_RB_MAX];
/// errors /// errors
uint32_t num_errors_rx; uint32_t num_errors_rx;
uint64_t overhead_bytes_rx; uint64_t overhead_bytes_rx;
/// headers+ CE + padding bytes for a MAC PDU /// headers+ CE + padding bytes for a MAC PDU
uint64_t total_overhead_bytes_rx; uint64_t total_overhead_bytes_rx;
...@@ -507,178 +265,170 @@ typedef struct { ...@@ -507,178 +265,170 @@ typedef struct {
uint32_t total_num_pdus_rx; uint32_t total_num_pdus_rx;
/// num of error pdus /// num of error pdus
uint32_t total_num_errors_rx; uint32_t total_num_errors_rx;
} eNB_UE_STATS_NB; } eNB_UE_STATS_NB;
/*! \brief eNB template for UE context information */ /*! \brief scheduling control information set through an API (not used)*/
typedef struct { typedef struct {
/// C-RNTI of UE ///UL transmission bandwidth in RBs
rnti_t rnti; uint8_t ul_bandwidth[MAX_NUM_LCID];
/// NDI from last scheduling ///DL transmission bandwidth in RBs
uint8_t oldNDI[8]; uint8_t dl_bandwidth[MAX_NUM_LCID];
/// NDI from last UL scheduling //To do GBR bearer
uint8_t oldNDI_UL[8]; uint8_t min_ul_bandwidth[MAX_NUM_LCID];
/// Flag to indicate UL has been scheduled at least once uint8_t min_dl_bandwidth[MAX_NUM_LCID];
boolean_t ul_active; ///aggregated bit rate of non-gbr bearer per UE
/// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received) uint64_t ue_AggregatedMaximumBitrateDL;
boolean_t configured; ///aggregated bit rate of non-gbr bearer per UE
uint64_t ue_AggregatedMaximumBitrateUL;
/// MCS from last scheduling ///CQI scheduling interval in subframes.
//Modify uint8_t mcs[8]; //Delete uint16_t cqiSchedInterval;
///Contention resolution timer used during random access
/// TPC from last scheduling uint8_t mac_ContentionResolutionTimer;
//Delete uint8_t oldTPC[8]; //Delete uint16_t max_allowed_rbs[MAX_NUM_LCID];
uint8_t max_mcs[MAX_NUM_LCID];
// PHY interface info uint16_t priority[MAX_NUM_LCID];
// resource scheduling information
/// DCI format for DLSCH uint8_t harq_pid[MAX_NUM_CCs];
uint16_t DLSCH_dci_fmt; uint8_t round[MAX_NUM_CCs];
uint8_t dl_pow_off[MAX_NUM_CCs];
/// Current Aggregation Level for DCI //Delete uint16_t pre_nb_available_rbs[MAX_NUM_CCs];
uint8_t DCI_aggregation_min; //Delete unsigned char rballoc_sub_UE[MAX_NUM_CCs][N_RBG_MAX];
uint16_t ta_timer;
/// size of DLSCH size in bit int16_t ta_update;
uint8_t DLSCH_dci_size_bits; int32_t context_active_timer;
//Delete int32_t cqi_req_timer;
/// DCI buffer for DLSCH int32_t ul_inactivity_timer;
/* rounded to 32 bits unit (actual value should be 8 due to the logic int32_t ul_failure_timer;
* of the function generate_dci0) */ int32_t ul_scheduled;
//Modifyuint8_t DLSCH_DCI[8][(((MAX_DCI_SIZE_BITS)+31)>>5)*4]; int32_t ra_pdcch_order_sent;
int32_t ul_out_of_sync;
/// Number of Allocated RBs for DL after scheduling (prior to frequency allocation) int32_t phr_received;// received from Msg3 MAC Control Element
//Delete uint16_t nb_rb[8]; // num_max_harq } UE_sched_ctrl_NB;
/*! \brief UE list used by eNB to order UEs/CC for scheduling*/
/// Number of Allocated RBs for UL after scheduling (prior to frequency allocation) typedef struct {
//Delete uint16_t nb_rb_ul[8]; // num_max_harq /// DLSCH pdu
DLSCH_PDU_NB DLSCH_pdu[MAX_NUM_CCs][2][NUMBER_OF_UE_MAX];
/// Number of Allocated RBs by the ulsch preprocessor /// DCI template and MAC connection parameters for UEs
//Delete uint8_t pre_allocated_nb_rb_ul; UE_TEMPLATE_NB UE_template[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
/// DCI template and MAC connection for RA processes
/// index of Allocated RBs by the ulsch preprocessor int pCC_id[NUMBER_OF_UE_MAX];
//Delete int8_t pre_allocated_rb_table_index_ul; /// Delete sorted downlink component carrier for the scheduler
/// Delete number of downlink active component carrier
/// total allocated RBs /// Delete sorted uplink component carrier for the scheduler
//Delete int8_t total_allocated_rbs; /// Delete number of uplink active component carrier
/// Delete number of downlink active component carrier
/// pre-assigned MCS by the ulsch preprocessor /// eNB to UE statistics
uint8_t pre_assigned_mcs_ul; eNB_UE_STATS_NB eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
/// scheduling control info
/// assigned MCS by the ulsch scheduler UE_sched_ctrl_NB UE_sched_ctrl[NUMBER_OF_UE_MAX];
uint8_t assigned_mcs_ul; int next[NUMBER_OF_UE_MAX];
int head;
/// DCI buffer for ULSCH int next_ul[NUMBER_OF_UE_MAX];
/* rounded to 32 bits unit (actual value should be 8 due to the logic int head_ul;
* of the function generate_dci0) */ int avail;
//Modify uint8_t ULSCH_DCI[8][(((MAX_DCI_SIZE_BITS)+31)>>5)*4]; int num_UEs;
boolean_t active[NUMBER_OF_UE_MAX];
/// DL DAI } UE_list_NB_t;
//Delete uint8_t DAI; /*!\brief Values of BCCH0 logical channel for MIB*/
#define BCCH0 11 // MIB-NB
/// UL DAI /*!\brief Values of BCCH1 logical channel for SIBs */
//Delete uint8_t DAI_ul[10]; #define BCCH1 12 // SI-SIB-NBs
/*!\brief Values of PCCH logical channel */
/// UL Scheduling Request Received //#define PCCH 13 // Paging XXX not used for the moment
//Delete uint8_t ul_SR; /*!\brief Value of CCCH / SRB0 logical channel */
//#define CCCH 0 // srb0 ---> XXX exactly the same as in LTE (commented for compilation purposes)
/// Resource Block indication for each sub-band in MU-MIMO /*!\brief DCCH0 / SRB1bis logical channel */
//Delete uint8_t rballoc_subband[8][50]; #define DCCH0 3 // srb1bis
/*!\brief DCCH1 / SRB1 logical channel */
// Logical channel info for link with RLC //#define DCCH1 1 // srb1 //XXX we redefine it for the SRB1
/*!\brief DTCH0 DRB0 logical channel */
/// Last received UE BSR info for each logical channel group id #define DTCH0 4 // DRB0
uint8_t bsr_info[MAX_NUM_LCGID]; /*!\brief DTCH1 DRB1 logical channel */
#define DTCH1 5 // DRB1
/// LCGID mapping // DLSCH LCHAN ID all the same as NB-IoT
//Delete long lcgidmap[11]; /*!\brief DCI PDU filled by MAC for the PHY */
/*
/// phr information, received from DPR MAC control element * eNB part
int8_t phr_info_DPR; */
/// phr information, received from DPR MAC control element
int8_t phr_info_configured_DPR;
///dl buffer info
uint32_t dl_buffer_info[MAX_NUM_LCID];
/// total downlink buffer info
uint32_t dl_buffer_total;
/// total downlink pdus
uint32_t dl_pdus_total;
/// downlink pdus for each LCID
uint32_t dl_pdus_in_buffer[MAX_NUM_LCID];
/// creation time of the downlink buffer head for each LCID
uint32_t dl_buffer_head_sdu_creation_time[MAX_NUM_LCID];
/// maximum creation time of the downlink buffer head across all LCID
uint32_t dl_buffer_head_sdu_creation_time_max;
/// a flag indicating that the downlink head SDU is segmented
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
uint32_t ul_buffer_creation_time[MAX_NUM_LCGID];
/// maximum uplink buffer creation time across all the LCIDs
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; * UE/ENB common part
//Delete uint32_t pusch_tpc_tx_subframe; */
//Delete uint32_t pucch_tpc_tx_frame; /*!\brief MAC header of Random Access Response for Random access preamble identifier (RAPID) for NB-IoT */
//Delete uint32_t pucch_tpc_tx_subframe; typedef struct {
uint8_t RAPID:6;
uint8_t T:1;
uint8_t E:1;
} __attribute__((__packed__))RA_HEADER_RAPID_NB;
//Delete eNB_UE_estimated_distances distance; /*!\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;
} UE_TEMPLATE_NB; /*Seems not to do the packed of RAR pdu*/
/*! \brief scheduling control information set through an API (not used)*/ /*!\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 { typedef struct {
///UL transmission bandwidth in RBs uint8_t LCID:5;
uint8_t ul_bandwidth[MAX_NUM_LCID]; uint8_t E:1;
///DL transmission bandwidth in RBs uint8_t R:2;
uint8_t dl_bandwidth[MAX_NUM_LCID]; } __attribute__((__packed__))SCH_SUBHEADER_FIXED_NB;
//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
uint64_t ue_AggregatedMaximumBitrateUL;
///CQI scheduling interval in subframes.
//Delete uint16_t cqiSchedInterval;
///Contention resolution timer used during random access
uint8_t mac_ContentionResolutionTimer;
//Delete uint16_t max_allowed_rbs[MAX_NUM_LCID]; /*!\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;
uint8_t max_mcs[MAX_NUM_LCID]; /*!\TRUNCATED BSR and Long BSR is not supported in NB-IoT*/
uint16_t priority[MAX_NUM_LCID]; /*!\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;
// resource scheduling information typedef struct {
uint8_t harq_pid[MAX_NUM_CCs]; uint8_t Num_ue_spec_dci ;
uint8_t round[MAX_NUM_CCs]; uint8_t Num_common_dci ;
uint8_t dl_pow_off[MAX_NUM_CCs]; // uint32_t nCCE;
//Delete uint16_t pre_nb_available_rbs[MAX_NUM_CCs]; uint32_t num_pdcch_symbols;
//Delete unsigned char rballoc_sub_UE[MAX_NUM_CCs][N_RBG_MAX]; DCI_ALLOC_t dci_alloc[NUM_DCI_MAX] ;
uint16_t ta_timer; } DCI_PDU_NB;
int16_t ta_update; typedef struct {
int32_t context_active_timer; uint8_t payload[BCCH_PAYLOAD_SIZE_MAX] ;
//Delete int32_t cqi_req_timer; } __attribute__((__packed__))BCCH_PDU_NB;
int32_t ul_inactivity_timer; /*! \brief CCCH payload */
int32_t ul_failure_timer; typedef struct {
int32_t ul_scheduled; uint8_t payload[CCCH_PAYLOAD_SIZE_MAX] ;
int32_t ra_pdcch_order_sent; } __attribute__((__packed__))CCCH_PDU_NB;
int32_t ul_out_of_sync;
int32_t phr_received;// received from Msg3 MAC Control Element
} UE_sched_ctrl_NB;
/*! \brief eNB template for the Random access information */ /*! \brief eNB template for the Random access information */
typedef struct { typedef struct {
/// Flag to indicate this process is active /// Flag to indicate this process is active
...@@ -714,7 +464,6 @@ typedef struct { ...@@ -714,7 +464,6 @@ typedef struct {
/// RA RNTI allocated from received PRACH /// RA RNTI allocated from received PRACH
uint16_t RA_rnti; uint16_t RA_rnti;
/// Delete Received preamble_index, use subcarrier index? /// Delete Received preamble_index, use subcarrier index?
/// Received UE Contention Resolution Identifier /// Received UE Contention Resolution Identifier
uint8_t cont_res_id[6]; uint8_t cont_res_id[6];
/// Timing offset indicated by PHY /// Timing offset indicated by PHY
...@@ -722,42 +471,6 @@ typedef struct { ...@@ -722,42 +471,6 @@ typedef struct {
/// Timeout for RRC connection /// Timeout for RRC connection
int16_t RRC_timer; int16_t RRC_timer;
} RA_TEMPLATE_NB; } RA_TEMPLATE_NB;
/*! \Delete struct SBMAP_CONF, brief subband bitmap confguration (for ALU icic algo purpose), in test phase */
/*! \brief UE list used by eNB to order UEs/CC for scheduling*/
typedef struct {
/// DLSCH pdu
DLSCH_PDU_NB DLSCH_pdu[MAX_NUM_CCs][2][NUMBER_OF_UE_MAX];
/// DCI template and MAC connection parameters for UEs
UE_TEMPLATE_NB UE_template[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
/// 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 eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
/// scheduling control info
UE_sched_ctrl UE_sched_ctrl[NUMBER_OF_UE_MAX];
int next[NUMBER_OF_UE_MAX];
int head;
int next_ul[NUMBER_OF_UE_MAX];
int head_ul;
int avail;
int num_UEs;
boolean_t active[NUMBER_OF_UE_MAX];
} UE_list_NB_t;
/*! \brief eNB common channels */ /*! \brief eNB common channels */
typedef struct { typedef struct {
int physCellId; int physCellId;
...@@ -765,12 +478,10 @@ typedef struct { ...@@ -765,12 +478,10 @@ typedef struct {
int Ncp; int Ncp;
int eutra_band; int eutra_band;
uint32_t dl_CarrierFreq; uint32_t dl_CarrierFreq;
BCCH_BCH_Message_NB_t *mib; BCCH_BCH_Message_NB_t *mib_NB;
RadioResourceConfigCommonSIB_NB_r13 *radioResourceConfigCommon; RadioResourceConfigCommonSIB_NB_r13_t *radioResourceConfigCommon;
ARFCN_ValueEUTRA_r9_t ul_CarrierFreq; ARFCN_ValueEUTRA_r9_t ul_CarrierFreq;
struct MasterInformationBlock_NB__operationModeInfo_r13_u operationModeInfo; struct MasterInformationBlock_NB__operationModeInfo_r13 operationModeInfo;
/// Outgoing DCI for PHY generated by eNB scheduler /// Outgoing DCI for PHY generated by eNB scheduler
DCI_PDU_NB DCI_pdu; DCI_PDU_NB DCI_pdu;
/// Outgoing BCCH pdu for PHY /// Outgoing BCCH pdu for PHY
...@@ -778,45 +489,87 @@ typedef struct { ...@@ -778,45 +489,87 @@ typedef struct {
/// Outgoing BCCH DCI allocation /// Outgoing BCCH DCI allocation
uint32_t BCCH_alloc_pdu; uint32_t BCCH_alloc_pdu;
/// Outgoing CCCH pdu for PHY /// Outgoing CCCH pdu for PHY
CCCH_PDU CCCH_pdu; CCCH_PDU_NB CCCH_pdu;
RA_TEMPLATE_NB RA_template[NB_RA_PROC_MAX]; RA_TEMPLATE_NB RA_template[NB_RA_PROC_MAX];
/// Delete VRB map for common channels /// Delete VRB map for common channels
/// Delete MBSFN SubframeConfig /// Delete MBSFN SubframeConfig
/// Delete number of subframe allocation pattern available for MBSFN sync area /// Delete number of subframe allocation pattern available for MBSFN sync area
// #if defined(Rel10) || defined(Rel14) // #if defined(Rel10) || defined(Rel14)
/// Delete MBMS Flag /// Delete MBMS Flag
/// Delete Outgoing MCCH pdu for PHY /// Delete Outgoing MCCH pdu for PHY
/// Delete MCCH active flag /// Delete MCCH active flag
/// Delete MCCH active flag /// Delete MCCH active flag
/// Delete MTCH active flag /// Delete MTCH active flag
/// Delete number of active MBSFN area /// Delete number of active MBSFN area
/// Delete MBSFN Area Info /// Delete MBSFN Area Info
/// Delete PMCH Config /// Delete PMCH Config
/// Delete MBMS session info list /// Delete MBMS session info list
/// Delete Outgoing MCH pdu for PHY /// Delete Outgoing MCH pdu for PHY
// #endif // #endif
// #ifdef CBA // #ifdef CBA
/// Delete number of CBA groups /// Delete number of CBA groups
/// Delete RNTI for each CBA group /// Delete RNTI for each CBA group
/// Delete MCS for each CBA group /// Delete MCS for each CBA group
// #endif // #endif
} COMMON_channels_NB_t; }COMMON_channels_NB_t;
/*! \brief eNB overall statistics */
typedef struct {
/// num BCCH PDU per CC
uint32_t total_num_bcch_pdu;
/// BCCH buffer size
uint32_t bcch_buffer;
/// total BCCH buffer size
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
uint32_t ccch_buffer;
/// total BCCH buffer size
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
uint16_t available_prbs;
/// total number of PRB available for the user plane fixed in 1 in NB-IoT
uint32_t total_available_prbs;
/// aggregation
/// total avilable nccc : num control channel element
uint16_t available_ncces;
// only for a new transmission, should be extended for retransmission
// current dlsch bit rate for all transport channels
uint32_t dlsch_bitrate;
//
uint32_t dlsch_bytes_tx;
//
uint32_t dlsch_pdus_tx;
//
uint32_t total_dlsch_bitrate;
//
uint32_t total_dlsch_bytes_tx;
//
uint32_t total_dlsch_pdus_tx;
// here for RX
//
uint32_t ulsch_bitrate;
//
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 */ /*! \brief top level eNB MAC structure */
typedef struct { typedef struct {
/// ///
...@@ -828,16 +581,13 @@ typedef struct { ...@@ -828,16 +581,13 @@ typedef struct {
/// Common cell resources /// Common cell resources
COMMON_channels_NB_t common_channels[MAX_NUM_CCs]; COMMON_channels_NB_t common_channels[MAX_NUM_CCs];
UE_list_NB_t UE_list; UE_list_NB_t UE_list;
///Delete subband bitmap configuration, no related CQI report ///Delete subband bitmap configuration, no related CQI report
// / Modify CCE table used to build DCI scheduling information // / Modify CCE table used to build DCI scheduling information
int CCE_table[MAX_NUM_CCs][12];//180 khz for Anchor carrier int CCE_table[MAX_NUM_CCs][12];//180 khz for Anchor carrier
/// active flag for Other lcid /// active flag for Other lcid
uint8_t lcid_active[NB_RB_MAX]; uint8_t lcid_active[NB_RB_MAX];
/// eNB stats /// eNB stats
eNB_STATS eNB_stats[MAX_NUM_CCs]; eNB_STATS_NB eNB_stats[MAX_NUM_CCs];
// MAC function execution peformance profiler // MAC function execution peformance profiler
/// processing time of eNB scheduler /// processing time of eNB scheduler
time_stats_t eNB_scheduler; time_stats_t eNB_scheduler;
...@@ -854,221 +604,7 @@ typedef struct { ...@@ -854,221 +604,7 @@ typedef struct {
/// processing time of eNB DLSCH scheduler /// processing time of eNB DLSCH scheduler
time_stats_t schedule_dlsch; // include rlc_data_req + MAC header + preprocessor time_stats_t schedule_dlsch; // include rlc_data_req + MAC header + preprocessor
/// Delete processing time of eNB MCH scheduler /// Delete processing time of eNB MCH scheduler
/// processing time of eNB ULSCH reception /// processing time of eNB ULSCH reception
time_stats_t rx_ulsch_sdu; // include rlc_data_ind time_stats_t rx_ulsch_sdu; // include rlc_data_ind
} eNB_MAC_INST_NB; } eNB_MAC_INST_NB;
#endif /*__LAYER2_MAC_DEFS_NB_IoT_H__ */
/*
* UE part
*/
/*!\brief UE layer 2 status */
typedef enum {
CONNECTION_OK=0,
CONNECTION_LOST,
PHY_RESYNCH,
PHY_HO_PRACH
} UE_L2_STATE_t_NB;
/*!\brief UE scheduling info */
typedef struct {
/// buffer status for each lcgid
uint8_t BSR[MAX_NUM_LCGID]; // should be more for mesh topology
/// keep the number of bytes in rlc buffer for each lcgid
int32_t BSR_bytes[MAX_NUM_LCGID];
/// after multiplexing buffer remain for each lcid
int32_t LCID_buffer_remain[MAX_NUM_LCID];
/// sum of all lcid buffer size
uint16_t All_lcid_buffer_size_lastTTI;
/// buffer status for each lcid
uint8_t LCID_status[MAX_NUM_LCID];
/// Delete SR pending as defined in 36.321
/// Delete SR_COUNTER as defined in 36.321
/// logical channel group ide for each LCID
uint8_t LCGID[MAX_NUM_LCID];
/// retxBSR-Timer, default value is sf2560
uint16_t retxBSR_Timer;
/// retxBSR_SF, number of subframe before triggering a regular BSR
uint16_t retxBSR_SF;
/// periodicBSR-Timer, default to infinity
uint16_t periodicBSR_Timer;
/// periodicBSR_SF, number of subframe before triggering a periodic BSR
uint16_t periodicBSR_SF;
/// Delete sr_ProhibitTimer in MAC_MainConfig, default value is 0: not configured
/// Delete sr ProhibitTime running
/// Delete maxHARQ_Tx in MAC_MainConfig, default value to n5
/// delete ttiBundling in MAC_MainConfig, default value is false
/// default value is release
struct DRX_Config *drx_config;
/// Delete phr_config in MAC_MainConfig, default value is release
///Delete timer before triggering a periodic PHR
///Delete timer before triggering a prohibit PHR
///DL Pathloss change value
uint16_t PathlossChange;
///Delete number of subframe before triggering a periodic PHR
///Delete number of subframe before triggering a prohibit PHR
///DL Pathloss Change in db
uint16_t PathlossChange_db;
/// Delete extendedBSR_Sizes_r10, default value is false, only support short BSR
/// Delete extendedPHR_r10, default value is false
//For NB-IoT in TS 36.321, prioritisedBitRate, bucketSizeDuration and the corresponding steps of the Logical Channel Prioritisation procedure (i.e., Step 1 and Step 2 below) are not applicable.
//Delete Bj bucket usage per lcid,
//Delete Bucket size per lcid
} UE_SCHEDULING_INFO_NB;
/*!\brief Top level UE MAC structure */
typedef struct {
uint16_t Node_id;
/// RX frame counter
frame_t rxFrame;
/// RX subframe counter
sub_frame_t rxSubframe;
/// TX frame counter
frame_t txFrame;
/// TX subframe counter
sub_frame_t txSubframe;
/// C-RNTI of UE
uint16_t crnti;
/// Delete C-RNTI of UE before HO
/// uplink active flag
uint8_t ul_active;
/// pointer to RRC PHY configuration
RadioResourceConfigCommonSIB_NB_r13 *radioResourceConfigCommon;
/// pointer to RACH_ConfigDedicated (NULL when not active, i.e. upon HO completion or T304 expiry)
struct RACH_ConfigDedicated *rach_ConfigDedicated;
/// pointer to RRC PHY configuration
struct PhysicalConfigDedicated_NB_r13 *physicalConfigDedicated;
#if defined(Rel10) || defined(Rel14)
/// Delete pointer to RRC PHY configuration SCEll
#endif
/// Delete pointer to TDD Configuration (NULL for FDD)
/// Delete Number of adjacent cells to measure
/// Delete Array of adjacent physical cell ids
/// Pointer to RRC MAC configuration
MAC_MainConfig_NB_r13 *macConfig;
/// Delete Pointer to RRC Measurement gap configuration
/// Pointers to LogicalChannelConfig indexed by LogicalChannelIdentity. Note NULL means LCHAN is inactive.
LogicalChannelConfig_NB_r13 *logicalChannelConfig[MAX_NUM_LCID];
/// Scheduling Information
UE_SCHEDULING_INFO_NB scheduling_info;
/// Outgoing CCCH pdu for PHY
CCCH_PDU_NB CCCH_pdu;
/// Incoming DLSCH pdu for PHY
//DLSCH_PDU DLSCH_pdu[NUMBER_OF_UE_MAX][2];
/// number of attempt for rach
uint8_t RA_attempt_number;
/// Random-access procedure flag
uint8_t RA_active;
/// Random-access window counter
int8_t RA_window_cnt;
/// Random-access Msg3 size in bytes
uint8_t RA_Msg3_size;
/// delete Random-access prachMaskIndex, NB use subcarrier index
/// Flag indicating Preamble set (A,B) used for first Msg3 transmission
uint8_t RA_usedGroupA;
/// Delete Random-access Resources, cause it use for ra_PreambleIndex and ra_RACH_MaskIndex.
/// Random-access PREAMBLE_TRANSMISSION_COUNTER
uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER;
/// Random-access backoff counter
int16_t RA_backoff_cnt;
/// Random-access variable for window calculation (frame of last change in window counter)
uint32_t RA_tx_frame;
/// Random-access variable for window calculation (subframe of last change in window counter)
uint8_t RA_tx_subframe;
/// Random-access Group B maximum path-loss
/// Random-access variable for backoff (frame of last change in backoff counter)
uint32_t RA_backoff_frame;
/// Random-access variable for backoff (subframe of last change in backoff counter)
uint8_t RA_backoff_subframe;
/// Random-access Group B maximum path-loss
uint16_t RA_maxPL;
/// Random-access Contention Resolution Timer active flag
uint8_t RA_contention_resolution_timer_active;
/// Random-access Contention Resolution Timer count value
uint8_t RA_contention_resolution_cnt;
/// power headroom reporitng reconfigured
uint8_t PHR_reconfigured;
/// power headroom state as configured by the higher layers
uint8_t PHR_state;
/// power backoff due to power management (as allowed by P-MPRc) for this cell
uint8_t PHR_reporting_active;
/// power backoff due to power management (as allowed by P-MPRc) for this cell
uint8_t power_backoff_db[NUMBER_OF_eNB_MAX];
/// BSR report falg management
uint8_t BSR_reporting_active;
/// retxBSR-Timer expires flag
uint8_t retxBSRTimer_expires_flag;
/// periodBSR-Timer expires flag
uint8_t periodBSRTimer_expires_flag;
/// Delete MBSFN_Subframe Configuration
/// Delete number of subframe allocation pattern available for MBSFN sync area
// #if defined(Rel10) || defined(Rel14)
/// Delete number of active MBSFN area
/// Delete MBSFN Area Info
/// Delete PMCH Config
/// Delete MCCH status
/// Delete MSI status
// #endif
/// Delete UE query for MCH subframe processing time
//#ifdef CBA
/// CBA RNTI for each group
/// Delete last SFN for CBA channel access
//#endif
/// total UE scheduler processing time
time_stats_t ue_scheduler; // total
/// UE ULSCH tx processing time inlcuding RLC interface (rlc_data_req) and mac header generation
time_stats_t tx_ulsch_sdu;
/// UE DLSCH rx processing time inlcuding RLC interface (mac_rrc_data_ind or mac_rlc_status_ind+mac_rlc_data_ind) and mac header parser
time_stats_t rx_dlsch_sdu;
/// Delete UE query for MCH subframe processing time
/* Delete UE MCH rx processing time , no support in NB-IoT*/
/// UE BCCH rx processing time including RLC interface (mac_rrc_data_ind)
time_stats_t rx_si;
/// UE PCCH rx processing time including RLC interface (mac_rrc_data_ind)
time_stats_t rx_p;
} UE_MAC_INST_NB;
/* Delete struct neigh_cell_id_t, no support in NB-IoT*/
#include "proto.h"
/*@}*/
#endif /*__LAYER2_MAC_DEFS_H__ */
\ 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 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"
#include "defs-nb.h"
#include "proto-nb.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
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"
#include "defs-nb.h"
#include "proto-nb.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
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);
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_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"
#include "LAYER2/MAC/defs-nb.h"
#include "LAYER2/MAC/proto-nb.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;
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)
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 @@ ...@@ -45,6 +45,7 @@
#endif //PHY_EMUL #endif //PHY_EMUL
#include "PHY_INTERFACE/defs.h" #include "PHY_INTERFACE/defs.h"
#include "RRC/LITE/defs.h" #include "RRC/LITE/defs.h"
#include "defs-nb.h"
extern const uint32_t BSR_TABLE[BSR_TABLE_SIZE]; extern const uint32_t BSR_TABLE[BSR_TABLE_SIZE];
//extern uint32_t EBSR_Level[63]; //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
*/
#ifndef __LAYER2_MAC_PROTO_H__
#define __LAYER2_MAC_PROTO_H__
/** \addtogroup _mac
* @{
*/
/** \fn void add_ue_spec_dci(DCI_PDU *DCI_pdu,void *pdu,rnti_t rnti,unsigned char dci_size_bytes,unsigned char aggregation,unsigned char dci_size_bits,unsigned char dci_fmt,uint8_t ra_flag);
\brief
*/
void add_ue_spec_dci(DCI_PDU *DCI_pdu,void *pdu,rnti_t rnti,unsigned char dci_size_bytes,unsigned char aggregation,unsigned char dci_size_bits,unsigned char dci_fmt,uint8_t ra_flag);
//LG commented cause compilation error for RT eNB extern inline unsigned int taus(void);
/** \fn void schedule_RA(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,uint8_t Msg3_subframe,unsigned int *nprb);
\brief First stage of Random-Access Scheduling. Loops over the RA_templates and checks if RAR, Msg3 or its retransmission are to be scheduled in the subframe. It returns the total number of PRB used for RA SDUs. For Msg3 it retrieves the L3msg from RRC and fills the appropriate buffers. For the others it just computes the number of PRBs. Each DCI uses 3 PRBs (format 1A)
for the message.
@param Mod_id Instance ID of eNB
@param frame Frame index
@param subframe Subframe number on which to act
*/
void schedule_RA(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,uint8_t Msg3_subframe);
/** \brief First stage of SI Scheduling. Gets a SI SDU from RRC if available and computes the MCS required to transport it as a function of the SDU length. It assumes a length less than or equal to 64 bytes (MCS 6, 3 PRBs).
@param Mod_id Instance ID of eNB
@param frame Frame index
@param subframe Subframe number on which to act
@param Msg3_subframe Subframe where Msg3 will be transmitted
*/
void schedule_SI(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP);
/** \brief MBMS scheduling: Checking the position for MBSFN subframes. Create MSI, transfer MCCH from RRC to MAC, transfer MTCHs from RLC to MAC. Multiplexing MSI,MCCH&MTCHs. Return 1 if there are MBSFN data being allocated, otherwise return 0;
@param Mod_id Instance ID of eNB
@param frame Frame index
@param subframe Subframe number on which to act
*/
int schedule_MBMS(module_id_t module_idP,uint8_t CC_id, frame_t frameP, sub_frame_t subframe);
/** \brief check the mapping between sf allocation and sync area, Currently only supports 1:1 mapping
@param Mod_id Instance ID of eNB
@param mbsfn_sync_area index of mbsfn sync area
@param[out] index of sf pattern
*/
int8_t get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t CC_id, uint8_t mbsfn_sync_area);
/** \brief check the mapping between sf allocation and sync area, Currently only supports 1:1 mapping
@param Mod_id Instance ID of eNB
@param mbsfn_sync_area index of mbsfn sync area
@param eNB_index index of eNB
@param[out] index of sf pattern
*/
int8_t ue_get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t mbsfn_sync_area, unsigned char eNB_index);
/** \brief top ULSCH Scheduling for TDD (config 1-6).
@param Mod_id Instance ID of eNB
@param frame Frame index
@param subframe Subframe number on which to act
@param sched_subframe Subframe number where PUSCH is transmitted (for DAI lookup)
*/
void schedule_ulsch(module_id_t module_idP,frame_t frameP,unsigned char cooperation_flag,sub_frame_t subframe,unsigned char sched_subframe);
/** \brief ULSCH Scheduling per RNTI
@param Mod_id Instance ID of eNB
@param frame Frame index
@param subframe Subframe number on which to act
@param sched_subframe Subframe number where PUSCH is transmitted (for DAI lookup)
*/
void schedule_ulsch_rnti(module_id_t module_idP, unsigned char cooperation_flag, frame_t frameP, sub_frame_t subframe, unsigned char sched_subframe, uint16_t *first_rb);
/** \brief ULSCH Scheduling for CBA RNTI
@param Mod_id Instance ID of eNB
@param frame Frame index
@param subframe Subframe number on which to act
@param sched_subframe Subframe number where PUSCH is transmitted (for DAI lookup)
*/
void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_flag, frame_t frameP, sub_frame_t subframe, unsigned char sched_subframe, uint16_t *first_rb);
/** \brief Second stage of DLSCH scheduling, after schedule_SI, schedule_RA and schedule_dlsch have been called. This routine first allocates random frequency assignments for SI and RA SDUs using distributed VRB allocations and adds the corresponding DCI SDU to the DCI buffer for PHY. It then loops over the UE specific DCIs previously allocated and fills in the remaining DCI fields related to frequency allocation. It assumes localized allocation of type 0 (DCI.rah=0). The allocation is done for tranmission modes 1,2,4.
@param Mod_id Instance of eNB
@param frame Frame index
@param subframe Index of subframe
@param mbsfn_flag Indicates that this subframe is for MCH/MCCH
*/
void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag);
/** \brief UE specific DLSCH scheduling. Retrieves next ue to be schduled from round-robin scheduler and gets the appropriate harq_pid for the subframe from PHY. If the process is active and requires a retransmission, it schedules the retransmission with the same PRB count and MCS as the first transmission. Otherwise it consults RLC for DCCH/DTCH SDUs (status with maximum number of available PRBS), builds the MAC header (timing advance sent by default) and copies
@param Mod_id Instance ID of eNB
@param frame Frame index
@param subframe Subframe on which to act
@param mbsfn_flag Indicates that MCH/MCCH is in this subframe
*/
void schedule_ue_spec(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag);
/** \brief Function for UE/PHY to compute PUSCH transmit power in power-control procedure.
@param Mod_id Module id of UE
@returns Po_NOMINAL_PUSCH (PREAMBLE_RECEIVED_TARGET_POWER+DELTA_PREAMBLE
*/
int8_t get_Po_NOMINAL_PUSCH(module_id_t module_idP,uint8_t CC_id);
/** \brief Function to compute DELTA_PREAMBLE from 36.321 (for RA power ramping procedure and Msg3 PUSCH power control policy)
@param Mod_id Module id of UE
@returns DELTA_PREAMBLE
*/
int8_t get_DELTA_PREAMBLE(module_id_t module_idP,int CC_id);
/** \brief Function for compute deltaP_rampup from 36.321 (for RA power ramping procedure and Msg3 PUSCH power control policy)
@param Mod_id Module id of UE
@param CC_id carrier component id of UE
@returns deltaP_rampup
*/
int8_t get_deltaP_rampup(module_id_t module_idP,uint8_t CC_id);
//main.c
void chbch_phy_sync_success(module_id_t module_idP,frame_t frameP,uint8_t eNB_index);
void mrbch_phy_sync_failure(module_id_t module_idP, frame_t frameP,uint8_t free_eNB_index);
int mac_top_init(int eMBMS_active, char *uecap_xer,uint8_t cba_group_active, uint8_t HO_active);
char layer2_init_UE(module_id_t module_idP);
char layer2_init_eNB(module_id_t module_idP, uint8_t Free_ch_index);
void mac_switch_node_function(module_id_t module_idP);
int mac_init_global_param(void);
void mac_top_cleanup(void);
void mac_UE_out_of_sync_ind(module_id_t module_idP,frame_t frameP, uint16_t eNB_index);
void dlsch_scheduler_pre_processor_reset (int module_idP,int UE_id,
uint8_t CC_id,
int frameP,
int subframeP,
int N_RBG,
uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],
unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]);
// eNB functions
/* \brief This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
@param Mod_id Instance ID of eNB
@param frame Index of frame
@param subframe Index of current subframe
@param N_RBS Number of resource block groups
*/
void dlsch_scheduler_pre_processor (module_id_t module_idP,
frame_t frameP,
sub_frame_t subframe,
int N_RBG[MAX_NUM_CCs],
int *mbsfn_flag);
void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id,
int UE_id,
uint8_t CC_id,
int N_RBG,
int transmission_mode,
int min_rb_unit,
uint8_t N_RB_DL,
uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],
unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]);
/* \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.
@param Mod_id Instance ID of eNB
@param cooperation_flag Flag to indicated that this cell has cooperating nodes (i.e. that there are collaborative transport channels that
can be scheduled.
@param subframe Index of current subframe
@param calibration_flag Flag to indicate that eNB scheduler should schedule TDD auto-calibration PUSCH.
*/
void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP);//, int calibration_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.
@param Mod_id Instance ID of eNB
@param CC_id Component Carrier Index
@param subframe Index of current subframe
@returns Pointer to generated DCI for subframe
*/
DCI_PDU *get_dci_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subframe);
/* \brief Function to indicate a received preamble on PRACH. It initiates the RA procedure.
@param Mod_id Instance ID of eNB
@param preamble_index index of the received RA request
@param timing_offset Offset in samples of the received PRACH w.r.t. eNB timing. This is used to
*/
void initiate_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, uint16_t preamble_index,int16_t timing_offset,uint8_t sect_id,sub_frame_t subframe,uint8_t f_id);
/* \brief Function in eNB to fill RAR pdu when requested by PHY. This provides a single RAR SDU for the moment and returns the t-CRNTI.
@param Mod_id Instance ID of eNB
@param dlsch_buffer Pointer to DLSCH input buffer
@param N_RB_UL Number of UL resource blocks
@returns t_CRNTI
*/
unsigned short fill_rar(
const module_id_t module_idP,
const int CC_id,
const frame_t frameP,
uint8_t * const dlsch_buffer,
const uint16_t N_RB_UL,
const uint8_t input_buffer_length
);
/* \brief Function to indicate a failed RA response. It removes all temporary variables related to the initial connection of a UE
@param Mod_id Instance ID of eNB
@param preamble_index index of the received RA request.
*/
void cancel_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, uint16_t preamble_index);
/* \brief Function used by PHY to inform MAC that an uplink is scheduled
for Msg3 in given subframe. This is used so that the MAC
scheduler marks as busy the RBs used by the Msg3.
@param Mod_id Instance ID of eNB
@param CC_id CC ID of eNB
@param frame current frame
@param subframe current subframe
@param rnti UE rnti concerned
@param Msg3_frame frame where scheduling takes place
@param Msg3_subframe subframe where scheduling takes place
*/
void set_msg3_subframe(module_id_t Mod_id,
int CC_id,
int frame,
int subframe,
int rnti,
int Msg3_frame,
int Msg3_subframe);
/* \brief Function to indicate a received SDU on ULSCH.
@param Mod_id Instance ID of eNB
@param rnti RNTI of UE transmitting the SR
@param sdu Pointer to received SDU
@param harq_pid Index of harq process corresponding to this sdu
@param msg3_flag flag indicating that this sdu is msg3
*/
void 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 indicate a scheduled schduling request (SR) was received by eNB.
@param Mod_id Instance ID of eNB
@param rnti RNTI of UE transmitting the SR
@param subframe Index of subframe where SR was received
*/
void SR_indication(module_id_t module_idP,int CC_id,frame_t frameP,rnti_t rnti, sub_frame_t subframe);
/* \brief Function to indicate a UL failure was detected by eNB PHY.
@param Mod_id Instance ID of eNB
@param CC_id Component carrier
@param frameP Frame index
@param rnti RNTI of UE transmitting the SR
@param subframe Index of subframe where SR was received
*/
void UL_failure_indication(module_id_t Mod_id,int CC_id,frame_t frameP,rnti_t rnti,sub_frame_t subframe);
uint8_t *get_dlsch_sdu(module_id_t module_idP,int CC_id,frame_t frameP,rnti_t rnti,uint8_t TBindex);
/* \brief Function to retrieve MCH transport block and MCS used for MCH in this MBSFN subframe. Returns null if no MCH is to be transmitted
@param Mod_id Instance ID of eNB
@param frame Index of frame
@param subframe Index of current subframe
@param mcs Pointer to mcs used by PHY (to be filled by MAC)
@returns Pointer to MCH transport block and mcs for subframe
*/
MCH_PDU *get_mch_sdu( module_id_t Mod_id, int CC_id, frame_t frame, sub_frame_t subframe);
//added for ALU icic purpose
uint32_t Get_Cell_SBMap(module_id_t module_idP);
void UpdateSBnumber(module_id_t module_idP);
//end ALU's algo
void ue_mac_reset (module_id_t module_idP,uint8_t eNB_index);
void ue_init_mac (module_id_t module_idP);
void init_ue_sched_info(void);
void add_ue_ulsch_info (module_id_t module_idP, int CC_id, int UE_id, sub_frame_t subframe,UE_ULSCH_STATUS status);
void add_ue_dlsch_info (module_id_t module_idP, int CC_id,int UE_id, sub_frame_t subframe,UE_DLSCH_STATUS status);
int find_UE_id (module_id_t module_idP, rnti_t rnti) ;
rnti_t UE_RNTI (module_id_t module_idP, int UE_id);
int UE_PCCID (module_id_t module_idP, int UE_id);
uint8_t find_active_UEs (module_id_t module_idP);
boolean_t is_UE_active (module_id_t module_idP, int UE_id);
uint8_t get_aggregation (uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt);
int8_t find_active_UEs_with_traffic(module_id_t module_idP);
void init_CCE_table(int module_idP,int CC_idP);
int get_nCCE_offset(int *CCE_table,
const unsigned char L,
const int nCCE,
const int common_dci,
const unsigned short rnti,
const unsigned char subframe);
int allocate_CCEs(int module_idP,
int CC_idP,
int subframe,
int test_only);
boolean_t CCE_allocation_infeasible(int module_idP,
int CC_idP,
int common_flag,
int subframe,
int aggregation,
int rnti);
void set_ue_dai(sub_frame_t subframeP,
uint8_t tdd_config,
int UE_id,
uint8_t CC_id,
UE_list_t *UE_list);
uint8_t find_num_active_UEs_in_cbagroup(module_id_t module_idP, unsigned char group_id);
uint8_t UE_is_to_be_scheduled(module_id_t module_idP,int CC_id,uint8_t UE_id);
/** \brief Round-robin scheduler for ULSCH traffic.
@param Mod_id Instance ID for eNB
@param subframe Subframe number on which to act
@returns UE index that is to be scheduled if needed/room
*/
module_id_t schedule_next_ulue(module_id_t module_idP, int UE_id,sub_frame_t subframe);
/** \brief Round-robin scheduler for DLSCH traffic.
@param Mod_id Instance ID for eNB
@param subframe Subframe number on which to act
@returns UE index that is to be scheduled if needed/room
*/
int schedule_next_dlue(module_id_t module_idP, int CC_id, sub_frame_t subframe);
/* \brief Allocates a set of PRBS for a particular UE. This is a simple function for the moment, later it should process frequency-domain CQI information and/or PMI information. Currently it just returns the first PRBS that are available in the subframe based on the number requested.
@param UE_id Index of UE on which to act
@param nb_rb Number of PRBs allocated to UE by scheduler
@param rballoc Pointer to bit-map of current PRB allocation given to previous users/control channels. This is updated for subsequent calls to the routine.
@returns an rballoc bitmap for resource type 0 allocation (DCI).
*/
uint32_t allocate_prbs(int UE_id,uint8_t nb_rb, uint32_t *rballoc);
/* \fn uint32_t req_new_ulsch(module_id_t module_idP)
\brief check for a new transmission in any drb
@param Mod_id Instance id of UE in machine
@returns 1 for new transmission, 0 for none
*/
uint32_t req_new_ulsch(module_id_t module_idP);
/* \brief Get SR payload (0,1) from UE MAC
@param Mod_id Instance id of UE in machine
@param CC_id Component Carrier index
@param eNB_id Index of eNB that UE is attached to
@param rnti C_RNTI of UE
@param subframe subframe number
@returns 0 for no SR, 1 for SR
*/
uint32_t ue_get_SR(module_id_t module_idP, int CC_id,frame_t frameP, uint8_t eNB_id,rnti_t rnti,sub_frame_t subframe);
uint8_t get_ue_weight(module_id_t module_idP, int CC_id, int UE_id);
// UE functions
void mac_out_of_sync_ind(module_id_t module_idP, frame_t frameP, uint16_t CH_index);
void ue_decode_si(module_id_t module_idP, int CC_id,frame_t frame, uint8_t CH_index, void *pdu, uint16_t len);
void ue_decode_p(module_id_t module_idP, int CC_id,frame_t frame, uint8_t CH_index, void *pdu, uint16_t len);
void ue_send_sdu(module_id_t module_idP, uint8_t CC_id,frame_t frame, sub_frame_t subframe, uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index);
#if defined(Rel10) || defined(Rel14)
/* \brief Called by PHY to transfer MCH transport block to ue MAC.
@param Mod_id Index of module instance
@param frame Frame index
@param sdu Pointer to transport block
@param sdu_len Length of transport block
@param eNB_index Index of attached eNB
@param sync_area the index of MBSFN sync area
*/
void ue_send_mch_sdu(module_id_t module_idP,uint8_t CC_id, frame_t frameP,uint8_t *sdu,uint16_t sdu_len,uint8_t eNB_index,uint8_t sync_area) ;
/*\brief Function to check if UE PHY needs to decode MCH for MAC.
@param Mod_id Index of protocol instance
@param frame Index of frame
@param subframe Index of subframe
@param eNB_index index of eNB for this MCH
@param[out] sync_area return the sync area
@param[out] mcch_active flag indicating whether this MCCH is active in this SF
*/
int ue_query_mch(uint8_t Mod_id,uint8_t CC_id, uint32_t frame,sub_frame_t subframe, uint8_t eNB_index, uint8_t *sync_area, uint8_t *mcch_active);
#endif
/* \brief Called by PHY to get sdu for PUSCH transmission. It performs the following operations: Checks BSR for DCCH, DCCH1 and DTCH corresponding to previous values computed either in SR or BSR procedures. It gets rlc status indications on DCCH,DCCH1 and DTCH and forms BSR elements and PHR in MAC header. CRNTI element is not supported yet. It computes transport block for up to 3 SDUs and generates header and forms the complete MAC SDU.
@param Mod_id Instance id of UE in machine
@param eNB_id Index of eNB that UE is attached to
@param rnti C_RNTI of UE
@param subframe subframe number
@returns 0 for no SR, 1 for SR
*/
void ue_get_sdu(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframe, uint8_t eNB_index,uint8_t *ulsch_buffer,uint16_t buflen,uint8_t *access_mode);
/* \brief Function called by PHY to retrieve information to be transmitted using the RA procedure. If the UE is not in PUSCH mode for a particular eNB index, this is assumed to be an Msg3 and MAC attempts to retrieves the CCCH message from RRC. If the UE is in PUSCH mode for a particular eNB index and PUCCH format 0 (Scheduling Request) is not activated, the MAC may use this resource for random-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 from 36.321)
@param Mod_id Index of UE instance
@param Mod_id Component Carrier Index
@param New_Msg3 Flag to indicate this call is for a new Msg3
@param subframe Index of subframe for PRACH transmission (0 ... 9)
@returns A pointer to a PRACH_RESOURCES_t */
PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t new_Msg3,sub_frame_t subframe);
/* \brief Function called by PHY to process the received RAR. It checks that the preamble matches what was sent by the eNB and provides the timing advance and t-CRNTI.
@param Mod_id Index of UE instance
@param CC_id Index to a component carrier
@param frame Frame index
@param ra_rnti RA_RNTI value
@param dlsch_buffer Pointer to dlsch_buffer containing RAR PDU
@param t_crnti Pointer to PHY variable containing the T_CRNTI
@param preamble_index Preamble Index used by PHY to transmit the PRACH. This should match the received RAR to trigger the rest of
random-access procedure
@param selected_rar_buffer the output buffer for storing the selected RAR header and RAR payload
@returns timing advance or 0xffff if preamble doesn't match
*/
uint16_t
ue_process_rar(
const module_id_t module_idP,
const int CC_id,
const frame_t frameP,
const rnti_t ra_rnti,
uint8_t * const dlsch_buffer,
rnti_t * const t_crnti,
const uint8_t preamble_index,
uint8_t* selected_rar_buffer
);
/* \brief Generate header for UL-SCH. This function parses the desired control elements and sdus and generates the header as described
in 36-321 MAC layer specifications. It returns the number of bytes used for the header to be used as an offset for the payload
in the ULSCH buffer.
@param mac_header Pointer to the first byte of the MAC header (UL-SCH buffer)
@param num_sdus Number of SDUs in the payload
@param short_padding Number of bytes for short padding (0,1,2)
@param sdu_lengths Pointer to array of SDU lengths
@param sdu_lcids Pointer to array of LCIDs (the order must be the same as the SDU length array)
@param power_headroom Pointer to power headroom command (NULL means not present in payload)
@param crnti Pointer to CRNTI command (NULL means not present in payload)
@param truncated_bsr Pointer to Truncated BSR command (NULL means not present in payload)
@param short_bsr Pointer to Short BSR command (NULL means not present in payload)
@param long_bsr Pointer to Long BSR command (NULL means not present in payload)
@param post_padding Number of bytes for padding at the end of MAC PDU
@returns Number of bytes used for header
*/
unsigned char generate_ulsch_header(uint8_t *mac_header,
uint8_t num_sdus,
uint8_t short_padding,
uint16_t *sdu_lengths,
uint8_t *sdu_lcids,
POWER_HEADROOM_CMD *power_headroom,
uint16_t *crnti,
BSR_SHORT *truncated_bsr,
BSR_SHORT *short_bsr,
BSR_LONG *long_bsr,
unsigned short post_padding);
/* \brief Parse header for UL-SCH. This function parses the received UL-SCH header as described
in 36-321 MAC layer specifications. It returns the number of bytes used for the header to be used as an offset for the payload
in the ULSCH buffer.
@param mac_header Pointer to the first byte of the MAC header (UL-SCH buffer)
@param num_ces Number of SDUs in the payload
@param num_sdu Number of SDUs in the payload
@param rx_ces Pointer to received CEs in the header
@param rx_lcids Pointer to array of LCIDs (the order must be the same as the SDU length array)
@param rx_lengths Pointer to array of SDU lengths
@returns Pointer to payload following header
*/
uint8_t *parse_ulsch_header(uint8_t *mac_header,
uint8_t *num_ce,
uint8_t *num_sdu,
uint8_t *rx_ces,
uint8_t *rx_lcids,
uint16_t *rx_lengths,
uint16_t tx_lenght);
int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active);
int mac_init(void);
int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti,int harq_pid);
int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP);
int maxround(module_id_t Mod_id,uint16_t rnti,int frame,sub_frame_t subframe,uint8_t ul_flag);
void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag);
int prev(UE_list_t *listP, int nodeP, int ul_flag);
void dump_ue_list(UE_list_t *listP, int ul_flag);
int UE_num_active_CC(UE_list_t *listP,int ue_idP);
int UE_PCCID(module_id_t mod_idP,int ue_idP);
rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP);
void ulsch_scheduler_pre_processor(module_id_t module_idP, int frameP, sub_frame_t subframeP, uint16_t *first_rb);
void store_ulsch_buffer(module_id_t module_idP, int frameP, sub_frame_t subframeP);
void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP);
void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subframeP,uint16_t *first_rb);
void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, UE_TEMPLATE *UE_template);
int phy_stats_exist(module_id_t Mod_id, int rnti);
/*! \fn UE_L2_state_t ue_scheduler(const module_id_t module_idP,const frame_t frameP, const sub_frame_t subframe, const lte_subframe_t direction,const uint8_t eNB_index)
\brief UE scheduler where all the ue background tasks are done. This function performs the following: 1) Trigger PDCP every 5ms 2) Call RRC for link status return to PHY3) Perform SR/BSR procedures for scheduling feedback 4) Perform PHR procedures.
\param[in] module_idP instance of the UE
\param[in] rxFrame the RX frame number
\param[in] rxSubframe the RX subframe number
\param[in] txFrame the TX frame number
\param[in] txSubframe the TX subframe number
\param[in] direction subframe direction
\param[in] eNB_index instance of eNB
@returns L2 state (CONNETION_OK or CONNECTION_LOST or PHY_RESYNCH)
*/
UE_L2_STATE_t ue_scheduler(
const module_id_t module_idP,
const frame_t rxFrameP,
const sub_frame_t rxSubframe,
const frame_t txFrameP,
const sub_frame_t txSubframe,
const lte_subframe_t direction,
const uint8_t eNB_index,
const int CC_id);
/*! \fn int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint16_t buflen);
\brief determine whether to use cba resource to transmit or not
\param[in] Mod_id instance of the UE
\param[in] frame the frame number
\param[in] subframe the subframe number
\param[in] eNB_index instance of eNB
\param[out] access(1) or postpone (0)
*/
int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint16_t buflen);
/*! \fn BSR_SHORT * get_bsr_short(module_id_t module_idP, uint8_t bsr_len)
\brief get short bsr level
\param[in] Mod_id instance of the UE
\param[in] bsr_len indicator for no, short, or long bsr
\param[out] bsr_s pointer to short bsr
*/
BSR_SHORT *get_bsr_short(module_id_t module_idP, uint8_t bsr_len);
/*! \fn BSR_LONG * get_bsr_long(module_id_t module_idP, uint8_t bsr_len)
\brief get long bsr level
\param[in] Mod_id instance of the UE
\param[in] bsr_len indicator for no, short, or long bsr
\param[out] bsr_l pointer to long bsr
*/
BSR_LONG * get_bsr_long(module_id_t module_idP, uint8_t bsr_len);
/*! \fn boolean_t update_bsr(module_id_t module_idP, frame_t frameP,sub_frame_t subframeP)
\brief get the rlc stats and update the bsr level for each lcid
\param[in] Mod_id instance of the UE
\param[in] frame Frame index
*/
boolean_t update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP,eNB_index_t eNB_index);
/*! \fn locate_BsrIndexByBufferSize (int *table, int size, int value)
\brief locate the BSR level in the table as defined in 36.321. This function requires that he values in table to be monotonic, either increasing or decreasing. The returned value is not less than 0, nor greater than n-1, where n is the size of table.
\param[in] *table Pointer to BSR table
\param[in] size Size of the table
\param[in] value Value of the buffer
\return the index in the BSR_LEVEL table
*/
uint8_t locate_BsrIndexByBufferSize (const uint32_t *table, int size, int value);
/*! \fn int get_sf_periodicBSRTimer(uint8_t periodicBSR_Timer)
\brief get the number of subframe from the periodic BSR timer configured by the higher layers
\param[in] periodicBSR_Timer timer for periodic BSR
\return the number of subframe
*/
int get_sf_periodicBSRTimer(uint8_t bucketSize);
/*! \fn int get_ms_bucketsizeduration(uint8_t bucketSize)
\brief get the time in ms form the bucket size duration configured by the higher layer
\param[in] bucketSize the bucket size duration
\return the time in ms
*/
int get_ms_bucketsizeduration(uint8_t bucketsizeduration);
/*! \fn int get_sf_retxBSRTimer(uint8_t retxBSR_Timer)
\brief get the number of subframe form the bucket size duration configured by the higher layer
\param[in] retxBSR_Timer timer for regular BSR
\return the time in sf
*/
int get_sf_retxBSRTimer(uint8_t retxBSR_Timer);
/*! \fn int get_sf_perioidicPHR_Timer(uint8_t perioidicPHR_Timer){
\brief get the number of subframe form the periodic PHR timer configured by the higher layer
\param[in] perioidicPHR_Timer timer for reguluar PHR
\return the time in sf
*/
int get_sf_perioidicPHR_Timer(uint8_t perioidicPHR_Timer);
/*! \fn int get_sf_prohibitPHR_Timer(uint8_t prohibitPHR_Timer)
\brief get the number of subframe form the prohibit PHR duration configured by the higher layer
\param[in] prohibitPHR_Timer timer for PHR
\return the time in sf
*/
int get_sf_prohibitPHR_Timer(uint8_t prohibitPHR_Timer);
/*! \fn int get_db_dl_PathlossChange(uint8_t dl_PathlossChange)
\brief get the db form the path loss change configured by the higher layer
\param[in] dl_PathlossChange path loss for PHR
\return the pathloss in db
*/
int get_db_dl_PathlossChange(uint8_t dl_PathlossChange);
/*! \fn uint8_t get_phr_mapping (module_id_t module_idP, int CC_id,uint8_t eNB_index)
\brief get phr mapping as described in 36.313
\param[in] Mod_id index of eNB
\param[in] CC_id Component Carrier Index
\return phr mapping
*/
uint8_t get_phr_mapping (module_id_t module_idP, int CC_id, uint8_t eNB_index);
/*! \fn void update_phr (module_id_t module_idP)
\brief update/reset the phr timers
\param[in] Mod_id index of eNB
\param[in] CC_id Component carrier index
\return void
*/
void update_phr (module_id_t module_idP,int CC_id);
/*! \brief Function to indicate Msg3 transmission/retransmission which initiates/reset Contention Resolution Timer
\param[in] Mod_id Instance index of UE
\param[in] eNB_id Index of eNB
*/
void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP,uint8_t eNB_id);
/*! \brief Function to indicate the transmission of msg1/rach
\param[in] Mod_id Instance index of UE
\param[in] eNB_id Index of eNB
*/
void Msg1_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id);
void dl_phy_sync_success(module_id_t module_idP,
frame_t frameP,
unsigned char eNB_index,
uint8_t first_sync);
int dump_eNB_l2_stats(char *buffer, int length);
double uniform_rngen(int min, int max);
void add_common_dci(DCI_PDU *DCI_pdu,
void *pdu,
rnti_t rnti,
unsigned char dci_size_bytes,
unsigned char aggregation,
unsigned char dci_size_bits,
unsigned char dci_fmt,
uint8_t ra_flag);
uint32_t allocate_prbs_sub(int nb_rb, uint8_t *rballoc);
void update_ul_dci(module_id_t module_idP,uint8_t CC_id,rnti_t rnti,uint8_t dai);
int get_bw_index(module_id_t module_id, uint8_t CC_id);
int get_min_rb_unit(module_id_t module_idP, uint8_t CC_id);
/* \brief Generate header for DL-SCH. This function parses the desired control elements and sdus and generates the header as described
in 36-321 MAC layer specifications. It returns the number of bytes used for the header to be used as an offset for the payload
in the DLSCH buffer.
@param mac_header Pointer to the first byte of the MAC header (DL-SCH buffer)
@param num_sdus Number of SDUs in the payload
@param sdu_lengths Pointer to array of SDU lengths
@param sdu_lcids Pointer to array of LCIDs (the order must be the same as the SDU length array)
@param drx_cmd dicontinous reception command
@param timing_advancd_cmd timing advanced command
@param ue_cont_res_id Pointer to contention resolution identifier (NULL means not present in payload)
@param short_padding Number of bytes for short padding (0,1,2)
@param post_padding number of bytes for padding at the end of MAC PDU
@returns Number of bytes used for header
*/
unsigned char generate_dlsch_header(unsigned char *mac_header,
unsigned char num_sdus,
unsigned short *sdu_lengths,
unsigned char *sdu_lcids,
unsigned char drx_cmd,
short timing_advance_cmd,
unsigned char *ue_cont_res_id,
unsigned char short_padding,
unsigned short post_padding);
/** \brief RRC Configuration primitive for PHY/MAC. Allows configuration of PHY/MAC resources based on System Information (SI), RRCConnectionSetup and RRCConnectionReconfiguration messages.
@param Mod_id Instance ID of eNB
@param CC_id Component Carrier of the eNB
@param eNB_flag Indicates if this is a eNB or UE configuration
@param rntiP id of UE if this is an eNB configuration
@param eNB_id Index of eNB if this is a UE configuration
@param radioResourceConfigCommon Structure from SIB2 for common radio parameters (if NULL keep existing configuration)
@param physcialConfigDedicated Structure from RRCConnectionSetup or RRCConnectionReconfiguration for dedicated PHY parameters (if NULL keep existing configuration)
@param measObj Structure from RRCConnectionReconfiguration for UE measurement procedures
@param mac_MainConfig Structure from RRCConnectionSetup or RRCConnectionReconfiguration for dedicated MAC parameters (if NULL keep existing configuration)
@param logicalChannelIdentity Logical channel identity index of corresponding logical channel config
@param logicalChannelConfig Pointer to logical channel configuration
@param measGapConfig Measurement Gap configuration for MAC (if NULL keep existing configuration)
@param tdd_Config TDD Configuration from SIB1 (if NULL keep existing configuration)
@param mobilityControlInfo mobility control info received for Handover
@param SIwindowsize SI Windowsize from SIB1 (if NULL keep existing configuration)
@param SIperiod SI Period from SIB1 (if NULL keep existing configuration)
@param MBMS_Flag indicates MBMS transmission
@param mbsfn_SubframeConfigList pointer to mbsfn subframe configuration list from SIB2
@param mbsfn_AreaInfoList pointer to MBSFN Area Info list from SIB13
@param pmch_InfoList pointer to PMCH_InfoList from MBSFNAreaConfiguration Message (MCCH Message)
*/
int rrc_mac_config_req(module_id_t module_idP,
int CC_id,
eNB_flag_t eNB_flag,
rnti_t rntiP,
uint8_t eNB_index,
RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
struct PhysicalConfigDedicated *physicalConfigDedicated,
#if defined(Rel10) || defined(Rel14)
SCellToAddMod_r10_t *sCellToAddMod_r10,
//struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
MeasObjectToAddMod_t **measObj,
MAC_MainConfig_t *mac_MainConfig,
long logicalChannelIdentity,
LogicalChannelConfig_t *logicalChannelConfig,
MeasGapConfig_t *measGapConfig,
TDD_Config_t *tdd_Config,
MobilityControlInfo_t *mobilityControlInfo,
uint8_t *SIwindowsize,
uint16_t *SIperiod,
ARFCN_ValueEUTRA_t *ul_CarrierFreq,
long *ul_Bandwidth,
AdditionalSpectrumEmission_t *additionalSpectrumEmission,
struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList
#if defined(Rel10) || defined(Rel14)
,
uint8_t MBMS_Flag,
MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList,
PMCH_InfoList_r9_t *pmch_InfoList
#endif
#ifdef CBA
,
uint8_t num_active_cba_groups,
uint16_t cba_rnti
#endif
);
/** \brief get the estimated UE distance from the PHY->MAC layer.
@param Mod_id Instance ID of eNB
@param UE_id Index of UE if this is an eNB configuration
@param CC_id Component Carrier Index
@param loc_type localization type: time-based or power-based
@return the estimated distance in meters
*/
double
rrc_get_estimated_ue_distance(
const protocol_ctxt_t * const ctxt_pP,
const int CC_idP,
const uint8_t loc_typeP);
void fill_dci(DCI_PDU *DCI_pdu, PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc);
/* \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_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_initiate_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, uint16_t preamble_index,int16_t timing_offset,uint8_t sect_id,sub_frame_t subframe,uint8_t f_id);
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_rrc_mac_config_req_eNB(
module_id_t Mod_idP,
int CC_idP,
int rntiP, //FIXME: Raymond bug?
int physCellId,
int p_eNB,
int Ncp,
int eutra_band,//FIXME: frequencyBandIndicator in sib1 (is a long not an int!!)
struct NS_PmaxList_NB_r13 frequencyBandInfo, //optional
struct MultiBandInfoList_NB_r13 multiBandInfoList, //optional
struct DL_Bitmap_NB_r13 dl_bitmap, //optional
long* eutraControlRegionSize, //optional
long* nrs_CRS_PowerOffset, //optional
uint8_t *SIwindowsize, //maybe no more needed because TDD only
uint16_t *SIperiod, //maybe no more needed because TDD only
uint32_t dl_CarrierFreq,
uint32_t ul_CarrierFreq,
BCCH_BCH_Message_NB_t *mib_NB,
RadioResourceConfigCommonSIB_NB_r13_t *radioResourceConfigCommon,
struct PhysicalConfigDedicated_NB_r13 *physicalConfigDedicated,
MAC_MainConfig_NB_r13_t *mac_MainConfig,
long logicalChannelIdentity,//FIXME: maybe is not needed
LogicalChannelConfig_NB_r13_t *logicalChannelConfig
);
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);
#endif
/** @}*/
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
#include "PHY_INTERFACE/defs.h" #include "PHY_INTERFACE/defs.h"
#include "COMMON/mac_rrc_primitives.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, 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, 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, 1326,1552,1817,2127,2490,2915,3413,3995,4677,5467,6411,7505,8787,10287,12043,14099,
......
Develop record:
Nick (nick133371@gmail.com)
5/13
openair1/PHY/impl_defs_lte-nb.h
openair1/PHY/INIT/defs-nb.h
openair1/PHY/INIT/Lte_init-nb.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
openair2/Layer2/MAC/defs-nb.h
openair2/Layer2/MAC/proto-nb.h
openair2/Layer2/MAC/eNB_scheduler_ulsch-nb.c
openair2/Layer2/MAC/eNB_scheduler_prmitives-nb.c
openair2/Layer2/MAC/eNB_scheduler_dlsch-nb.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.
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