From 3b7960d8516395b2a481028565d2370440f6bcf9 Mon Sep 17 00:00:00 2001 From: Calvin <kai-hsiang.hsu@eurecom.fr> Date: Fri, 25 May 2018 16:16:22 +0200 Subject: [PATCH] 1. nr_rrc_mac_config_req_ue 2. copy IF module from eNB to new folder --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 67 +- openair2/LAYER2/NR_MAC_UE/defs.h | 23 + openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 6 + openair2/LAYER2/NR_MAC_UE/vars.c | 34 + openair2/NR_UE_PHY_INTERFACE/IF_Module.c | 647 ++++++++++++++++++ openair2/NR_UE_PHY_INTERFACE/IF_Module.h | 142 ++++ openair2/NR_UE_PHY_INTERFACE/defs.h | 373 ++++++++++ openair2/NR_UE_PHY_INTERFACE/extern.h | 27 + .../NR_UE_PHY_INTERFACE/mac_phy_primitives.c | 283 ++++++++ .../NR_UE_PHY_INTERFACE/mac_phy_primitives.h | 232 +++++++ openair2/NR_UE_PHY_INTERFACE/vars.h | 44 ++ 11 files changed, 1867 insertions(+), 11 deletions(-) create mode 100644 openair2/LAYER2/NR_MAC_UE/vars.c create mode 100644 openair2/NR_UE_PHY_INTERFACE/IF_Module.c create mode 100644 openair2/NR_UE_PHY_INTERFACE/IF_Module.h create mode 100644 openair2/NR_UE_PHY_INTERFACE/defs.h create mode 100644 openair2/NR_UE_PHY_INTERFACE/extern.h create mode 100644 openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.c create mode 100644 openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.h create mode 100644 openair2/NR_UE_PHY_INTERFACE/vars.h diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 6e75276264..c699ad5232 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -39,43 +39,88 @@ nr_rrc_mac_config_req_ue( PhysicalCellGroupConfig_t *phy_cell_group_config, SpCellConfig_t *spcell_config){ + NR_UE_MAC_INST *mac = get_mac_inst(Mod_idP); + + ServingCellConfig_t *serving_cell_config = spcell_config->spCellConfigDedicated; // TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc. if(mac_cell_group_config != (MAC_CellGroupConfig_t *)0){ if(mac_cell_group_config->drx_Config != (drx_Config_t *)0 ){ - NR_UE_mac_inst->drx_Config = mac_cell_group_config->drx_Config; + mac->drx_Config = mac_cell_group_config->drx_Config; } if(mac_cell_group_config->SchedulingRequestConfig != (SchedulingRequestConfig_t *)0 ){ - NR_UE_mac_inst->SchedulingRequestConfig = mac_cell_group_config->SchedulingRequestConfig; + mac->SchedulingRequestConfig = mac_cell_group_config->SchedulingRequestConfig; } if(mac_cell_group_config->BSR_Config != (BSR_Config_t *)0 ){ - NR_UE_mac_inst->BSR_Config = mac_cell_group_config->BSR_Config; + mac->BSR_Config = mac_cell_group_config->BSR_Config; } if(mac_cell_group_config->TAG_Config != (TAG_Config_t *)0 ){ - NR_UE_mac_inst->TAG_Config = mac_cell_group_config->TAG_Config; + mac->TAG_Config = mac_cell_group_config->TAG_Config; } if(mac_cell_group_config->phr_Config != (phr_Config_t *)0 ){ - NR_UE_mac_inst->phr_Config = mac_cell_group_config->phr_Config; + mac->phr_Config = mac_cell_group_config->phr_Config; } if(mac_cell_group_config->cs_RNTI != (cs_RNTI_t *)0 ){ - NR_UE_mac_inst->cs_RNTI = mac_cell_group_config->cs_RNTI; + mac->cs_RNTI = mac_cell_group_config->cs_RNTI; } - - } if(phy_cell_group_config != (PhysicalCellGroupConfig_t *)0){ - + config_phy(phy_cell_group_config, NULL); } - if(spcell_config != (SpCellConfig_t *)0){ - + if(serving_cell_config_config != (SpCellConfig_t *)0){ + config_phy(NULL, spcell_config); + mac->servCellIndex = spcell_config->servCellIndex; } + + if(serving_cell_config != (spCellConfigDedicated_t *)0){ + if(serving_cell_config->tdd_UL_DL_ConfigurationDedicated != (TDD_UL_DL_ConfigDedicated_t *)0){ + mac->tdd_UL_DL_ConfigurationDedicated = serving_cell_config->tdd_UL_DL_ConfigurationDedicated; + } + + if(spcell_config->initialDownlinkBWP != (BWP_DownlinkDedicated_t *)0){ + mac->init_DL_BWP = spcell_config->initialDownlinkBWP; + } + + // storage list of DL BWP config. TODO should be modify to maintain(add/release) a list inside MAC instance, this implementation just use for one-shot RRC configuration setting. + if(spcell_config->downlinkBWP_ToAddModList != (struct ServingCellConfig__downlinkBWP_ToAddModList *)0){ + mac->BWP_Downlink_list = spcell_config->downlinkBWP_ToAddModList->list; + mac->BWP_Downlink_count = spcell_config->downlinkBWP_ToAddModList->count; + } + + if(spcell_config->bwp_InactivityTimer != (long *)0){ + mac->bwp_InactivityTimer = spcell_config->bwp_InactivityTimer; + } + + if(spcell_config->defaultDownlinkBWP_Id != (BWP_Id_t *)0){ + mac->defaultDownlinkBWP_Id = spcell_config->defaultDownlinkBWP_Id; + } + + if(spcell_config->pdsch_ServingCellConfig != (PDSCH_ServingCellConfig_t *)0){ + mac->pdsch_ServingCellConfig = spcell_config->pdsch_ServingCellConfig; + } + + if(spcell_config->csi_MeasConfig != (CSI_MeasConfig_t *)0){ + mac->csi_MeasConfig = spcell_config->csi_MeasConfig; + } + + spcell_config->tag_Id = spcell_config.tag_Id; + } + + //scell config not yet + + + + + + + return (0); } diff --git a/openair2/LAYER2/NR_MAC_UE/defs.h b/openair2/LAYER2/NR_MAC_UE/defs.h index b2a3ec259f..e7329616b7 100644 --- a/openair2/LAYER2/NR_MAC_UE/defs.h +++ b/openair2/LAYER2/NR_MAC_UE/defs.h @@ -72,12 +72,35 @@ /*!\brief Top level UE MAC structure */ typedef struct { + //// MAC config drx_Config_t *drx_config; SchedulingRequestConfig_t *SchedulingRequestConfig; BSR_Config_t *BSR_Config; TAG_Config_t *TAG_Config; phr_Config_t *phr_Config; cs_RNTI_t *cs_RNTI; + ServCellIndex_t *servCellIndex; + + //// Serving cell config + TDD_UL_DL_ConfigDedicated_t *tdd_UL_DL_ConfigurationDedicated; + // init DL BWP + BWP_DownlinkDedicated_t *init_DL_BWP; + // DL BWP list, not default one + BWP_Downlink_t **BWP_Downlink_list; + int BWP_Downlink_count; + //BWP_Id_t *firstActiveDownlinkBWP_Id; + long *bwp_InactivityTimer; + BWP_Id_t *defaultDownlinkBWP_Id; + //struct UplinkConfig *uplinkConfig; + //struct UplinkConfig *supplementaryUplink; + PDSCH_ServingCellConfig_t *pdsch_ServingCellConfig; + CSI_MeasConfig_t *csi_MeasConfig; + //SRS_CarrierSwitching_t *carrierSwitching; + //long *sCellDeactivationTimer /* OPTIONAL */; + //struct CrossCarrierSchedulingConfig *crossCarrierSchedulingConfig /* OPTIONAL */; + TAG_Id_t tag_Id; + //long *ue_BeamLockFunction /* OPTIONAL */; + //long *pathlossReferenceLinking /* OPTIONAL */; } UE_MAC_INST; #include "proto.h" diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index d682cf5870..a1c3688fc4 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -34,6 +34,7 @@ #include "extern.h" #include "assertions.h" +static NR_UE_MAC_INST_t *nr_ue_mac_inst; int nr_l2_init_ue(void) @@ -43,7 +44,12 @@ nr_l2_init_ue(void) LOG_I(MAC, "[MAIN] init UE MAC functions \n"); //init mac here + nr_ue_mac_inst = (NR_UE_MAC_INST_t *)malloc(sizeof(NR_UE_MAC_INST_t)*NB_NR_UE_MAC_INST); + return (1); } +NR_UE_MAC_INST_t *get_mac_inst(Module_id_t Mod_idP){ + return &nr_ue_mac_inst[(int)Mod_idP]; +} diff --git a/openair2/LAYER2/NR_MAC_UE/vars.c b/openair2/LAYER2/NR_MAC_UE/vars.c new file mode 100644 index 0000000000..300917b3c1 --- /dev/null +++ b/openair2/LAYER2/NR_MAC_UE/vars.c @@ -0,0 +1,34 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file vars.h +* \brief mac vars +* \author Navid Nikaein and Raymond Knopp +* \date 2010 - 2014 +* \version 1.0 +* \email navid.nikaein@eurecom.fr +* @ingroup _mac + +*/ + +UE_MAC_INST_t UE_mac_inst; //[NB_MODULE_MAX]; + + diff --git a/openair2/NR_UE_PHY_INTERFACE/IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/IF_Module.c new file mode 100644 index 0000000000..d0b8e57558 --- /dev/null +++ b/openair2/NR_UE_PHY_INTERFACE/IF_Module.c @@ -0,0 +1,647 @@ +#include "openair1/PHY/defs.h" +#include "openair2/PHY_INTERFACE/IF_Module.h" +#include "openair1/PHY/extern.h" +#include "LAYER2/MAC/extern.h" +#include "LAYER2/MAC/proto.h" +#include "common/ran_context.h" + +#define MAX_IF_MODULES 100 + +IF_Module_t *if_inst[MAX_IF_MODULES]; +Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; + +extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind); +extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); +extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); +extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind); +extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind); +extern uint8_t nfapi_mode; +extern uint16_t sf_ahead; + +void handle_rach(UL_IND_t *UL_info) { + int i; + + if (UL_info->rach_ind.rach_indication_body.number_of_preambles>0) { + + AssertFatal(UL_info->rach_ind.rach_indication_body.number_of_preambles==1,"More than 1 preamble not supported\n"); + UL_info->rach_ind.rach_indication_body.number_of_preambles=0; + LOG_D(MAC,"UL_info[Frame %d, Subframe %d] Calling initiate_ra_proc RACH:SFN/SF:%d\n",UL_info->frame,UL_info->subframe, NFAPI_SFNSF2DEC(UL_info->rach_ind.sfn_sf)); + initiate_ra_proc(UL_info->module_id, + UL_info->CC_id, + NFAPI_SFNSF2SFN(UL_info->rach_ind.sfn_sf), + NFAPI_SFNSF2SF(UL_info->rach_ind.sfn_sf), + UL_info->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.preamble, + UL_info->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.timing_advance, + UL_info->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.rnti +#ifdef Rel14 + ,0 +#endif + ); + } + +#ifdef Rel14 + if (UL_info->rach_ind_br.rach_indication_body.number_of_preambles>0) { + + AssertFatal(UL_info->rach_ind_br.rach_indication_body.number_of_preambles<5,"More than 4 preambles not supported\n"); + for (i=0;i<UL_info->rach_ind_br.rach_indication_body.number_of_preambles;i++) { + AssertFatal(UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel13.rach_resource_type>0, + "Got regular PRACH preamble, not BL/CE\n"); + LOG_D(MAC,"Frame %d, Subframe %d Calling initiate_ra_proc (CE_level %d)\n",UL_info->frame,UL_info->subframe, + UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel13.rach_resource_type-1); + initiate_ra_proc(UL_info->module_id, + UL_info->CC_id, + UL_info->frame, + UL_info->subframe, + UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel8.preamble, + UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel8.timing_advance, + UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel8.rnti, + UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel13.rach_resource_type); + } + UL_info->rach_ind_br.rach_indication_body.number_of_preambles=0; + } +#endif +} + +void handle_sr(UL_IND_t *UL_info) { + + int i; + + if (nfapi_mode == 1) // PNF + { + if (UL_info->sr_ind.sr_indication_body.number_of_srs>0) + { + oai_nfapi_sr_indication(&UL_info->sr_ind); + } + } + else + { + for (i=0;i<UL_info->sr_ind.sr_indication_body.number_of_srs;i++) + SR_indication(UL_info->module_id, + UL_info->CC_id, + UL_info->frame, + UL_info->subframe, + UL_info->sr_ind.sr_indication_body.sr_pdu_list[i].rx_ue_information.rnti, + UL_info->sr_ind.sr_indication_body.sr_pdu_list[i].ul_cqi_information.ul_cqi); + } + + UL_info->sr_ind.sr_indication_body.number_of_srs=0; +} + +void handle_cqi(UL_IND_t *UL_info) { + + int i; + + if (nfapi_mode == 1) + { + if (UL_info->cqi_ind.number_of_cqis>0) + { + LOG_D(PHY,"UL_info->cqi_ind.number_of_cqis:%d\n", UL_info->cqi_ind.number_of_cqis); + nfapi_cqi_indication_t ind; + + ind.header.message_id = NFAPI_RX_CQI_INDICATION; + ind.sfn_sf = UL_info->frame<<4 | UL_info->subframe; + ind.cqi_indication_body = UL_info->cqi_ind; + + oai_nfapi_cqi_indication(&ind); + + UL_info->cqi_ind.number_of_cqis=0; + } + } + else + { + for (i=0;i<UL_info->cqi_ind.number_of_cqis;i++) + cqi_indication(UL_info->module_id, + UL_info->CC_id, + UL_info->frame, + UL_info->subframe, + UL_info->cqi_ind.cqi_pdu_list[i].rx_ue_information.rnti, + &UL_info->cqi_ind.cqi_pdu_list[i].cqi_indication_rel9, + UL_info->cqi_ind.cqi_raw_pdu_list[i].pdu, + &UL_info->cqi_ind.cqi_pdu_list[i].ul_cqi_information); + + UL_info->cqi_ind.number_of_cqis=0; + } +} + +void handle_harq(UL_IND_t *UL_info) { + + int i; + + if (nfapi_mode == 1 && UL_info->harq_ind.harq_indication_body.number_of_harqs>0) // PNF + { + //LOG_D(PHY, "UL_info->harq_ind.harq_indication_body.number_of_harqs:%d Send to VNF\n", UL_info->harq_ind.harq_indication_body.number_of_harqs); + + int retval = oai_nfapi_harq_indication(&UL_info->harq_ind); + + if (retval!=0) + { + LOG_E(PHY, "Failed to encode NFAPI HARQ_IND retval:%d\n", retval); + } + + UL_info->harq_ind.harq_indication_body.number_of_harqs = 0; + } + else + { + for (i=0;i<UL_info->harq_ind.harq_indication_body.number_of_harqs;i++) + harq_indication(UL_info->module_id, + UL_info->CC_id, + NFAPI_SFNSF2SFN(UL_info->harq_ind.sfn_sf), + NFAPI_SFNSF2SF(UL_info->harq_ind.sfn_sf), + &UL_info->harq_ind.harq_indication_body.harq_pdu_list[i]); + + UL_info->harq_ind.harq_indication_body.number_of_harqs=0; + } +} + +void handle_ulsch(UL_IND_t *UL_info) { + + int i,j; + + if(nfapi_mode == 1) + { + if (UL_info->crc_ind.crc_indication_body.number_of_crcs>0) + { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + + oai_nfapi_crc_indication(&UL_info->crc_ind); + + UL_info->crc_ind.crc_indication_body.number_of_crcs = 0; + } + + if (UL_info->rx_ind.rx_indication_body.number_of_pdus>0) + { + //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); + oai_nfapi_rx_ind(&UL_info->rx_ind); + UL_info->rx_ind.rx_indication_body.number_of_pdus = 0; + } + } + else + { + if (UL_info->rx_ind.rx_indication_body.number_of_pdus>0 && UL_info->crc_ind.crc_indication_body.number_of_crcs>0) { + for (i=0;i<UL_info->rx_ind.rx_indication_body.number_of_pdus;i++) { + for (j=0;j<UL_info->crc_ind.crc_indication_body.number_of_crcs;j++) { + // find crc_indication j corresponding rx_indication i + LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].rx_ue_information.rnti:%04x UL_info->rx_ind.rx_indication_body.rx_pdu_list[%d].rx_ue_information.rnti:%04x\n", j, UL_info->crc_ind.crc_indication_body.crc_pdu_list[j].rx_ue_information.rnti, i, UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti); + if (UL_info->crc_ind.crc_indication_body.crc_pdu_list[j].rx_ue_information.rnti == + UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti) { + LOG_D(PHY, "UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].crc_indication_rel8.crc_flag:%d\n", j, UL_info->crc_ind.crc_indication_body.crc_pdu_list[j].crc_indication_rel8.crc_flag); + if (UL_info->crc_ind.crc_indication_body.crc_pdu_list[j].crc_indication_rel8.crc_flag == 1) { // CRC error indication + LOG_D(MAC,"Frame %d, Subframe %d Calling rx_sdu (CRC error) \n",UL_info->frame,UL_info->subframe); + rx_sdu(UL_info->module_id, + UL_info->CC_id, + NFAPI_SFNSF2SFN(UL_info->rx_ind.sfn_sf), //UL_info->frame, + NFAPI_SFNSF2SF(UL_info->rx_ind.sfn_sf), //UL_info->subframe, + UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti, + (uint8_t *)NULL, + UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length, + UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.timing_advance, + UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.ul_cqi); + } + else { + LOG_D(MAC,"Frame %d, Subframe %d Calling rx_sdu (CRC ok) \n",UL_info->frame,UL_info->subframe); + rx_sdu(UL_info->module_id, + UL_info->CC_id, + NFAPI_SFNSF2SFN(UL_info->rx_ind.sfn_sf), //UL_info->frame, + NFAPI_SFNSF2SF(UL_info->rx_ind.sfn_sf), //UL_info->subframe, + UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti, + UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].data, + UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length, + UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.timing_advance, + UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.ul_cqi); + } + break; + } //if (UL_info->crc_ind.crc_pdu_list[j].rx_ue_information.rnti == + // UL_info->rx_ind.rx_pdu_list[i].rx_ue_information.rnti) + } // for (j=0;j<UL_info->crc_ind.crc_indication_body.number_of_crcs;j++) + } // for (i=0;i<UL_info->rx_ind.number_of_pdus;i++) + UL_info->crc_ind.crc_indication_body.number_of_crcs=0; + UL_info->rx_ind.rx_indication_body.number_of_pdus = 0; + } // UL_info->rx_ind.rx_indication_body.number_of_pdus>0 && UL_info->subframe && UL_info->crc_ind.crc_indication_body.number_of_crcs>0 + else if (UL_info->rx_ind.rx_indication_body.number_of_pdus!=0 || UL_info->crc_ind.crc_indication_body.number_of_crcs!=0) { + LOG_E(PHY,"hoping not to have mis-match between CRC ind and RX ind - hopefully the missing message is coming shortly rx_ind:%d(SFN/SF:%05d) crc_ind:%d(SFN/SF:%05d) UL_info(SFN/SF):%04d%d\n", + UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf), + UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf), + UL_info->frame, UL_info->subframe); + } + } +} + +/****************************************************************************/ +/* debug utility functions begin */ +/****************************************************************************/ + +//#define DUMP_FAPI + +#ifdef DUMP_FAPI + +#define C do { size = 0; put(0); } while (0) +#define A(...) do { char t[4096]; sprintf(t, __VA_ARGS__); append_string(t); } while (0) + +#if 0 + +/* eats lots of ms at startup, disrupts realtime */ +static char *s; +static int size; +static int maxsize; + +static void put(char x) +{ + if (size == maxsize) { + maxsize += 32768; + s = realloc(s, maxsize); if (s == NULL) abort(); + } + s[size++] = x; +} + +#else + +/* eats nothing at startup, but fixed size */ +#define SMAX 65536 +static char s[SMAX]; +static int size; +static int maxsize = SMAX; + +static void put(char x) +{ + if (size == maxsize) { printf("incrase SMAX\n"); exit(1); } + s[size++] = x; +} + +#endif + +static void append_string(char *t) +{ + size--; + while (*t) put(*t++); + put(0); +} + +static void dump_ul(UL_IND_t *u) +{ + int i; + + C; + A("XXXX UL mod %d CC %d f.sf %d.%d\n", + u->module_id, u->CC_id, u->frame, u->subframe); + + A("XXXX harq_ind %d\n", u->harq_ind.harq_indication_body.number_of_harqs); + for (i = 0; i < u->harq_ind.harq_indication_body.number_of_harqs; i++) { + nfapi_harq_indication_pdu_t *v = &u->harq_ind.harq_indication_body.harq_pdu_list[i]; + A("XXXX harq ind %d\n", i); + A("XXXX rnti %d\n", v->rx_ue_information.rnti); + A("XXXX tb1 %d tb2 %d\n", v->harq_indication_fdd_rel8.harq_tb1, + v->harq_indication_fdd_rel8.harq_tb2); + A("XXXX number_of_ack_nack %d\n", + v->harq_indication_fdd_rel9.number_of_ack_nack); + A("XXXX harq[0] = %d\n", + v->harq_indication_fdd_rel9.harq_tb_n[0]); + A("XXXX harq ul_cqi %d channel %d\n", v->ul_cqi_information.ul_cqi, + v->ul_cqi_information.channel); + } + + A("XXXX crc_ind %d\n", u->crc_ind.crc_indication_body.number_of_crcs); + + A("XXXX sr_ind %d\n", u->sr_ind.sr_indication_body.number_of_srs); + + A("XXXX cqi_ind %d\n", u->cqi_ind.number_of_cqis); + for (i = 0; i < u->cqi_ind.number_of_cqis; i++) { + nfapi_cqi_indication_pdu_t *v = &u->cqi_ind.cqi_pdu_list[i]; + A("XXXX cqi ind %d\n", i); + A("XXXX cqi ul_cqi %d channel %d\n", v->ul_cqi_information.ul_cqi, + v->ul_cqi_information.channel); + } + + A("XXXX rach_ind %d\n", u->rach_ind.rach_indication_body.number_of_preambles); + + A("XXXX rx_ind %d\n", u->rx_ind.rx_indication_body.number_of_pdus); + for (i = 0; i < u->rx_ind.rx_indication_body.number_of_pdus; i++) { + nfapi_rx_indication_pdu_t *v = &u->rx_ind.rx_indication_body.rx_pdu_list[i]; + A("XXXX rx ind %d\n", i); + A("XXXX timing_advance %d\n", + v->rx_indication_rel8.timing_advance); + A("XXXX rx ul_cqi %d\n", v->rx_indication_rel8.ul_cqi); + } + + LOG_I(PHY, "XXXX UL\nXXXX UL\n%s", s); +} + +static char *DL_PDU_TYPE(int x) +{ + switch (x) { + case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: return "NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE"; + case NFAPI_DL_CONFIG_BCH_PDU_TYPE: return "NFAPI_DL_CONFIG_BCH_PDU_TYPE"; + case NFAPI_DL_CONFIG_MCH_PDU_TYPE: return "NFAPI_DL_CONFIG_MCH_PDU_TYPE"; + case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: return "NFAPI_DL_CONFIG_DLSCH_PDU_TYPE"; + case NFAPI_DL_CONFIG_PCH_PDU_TYPE: return "NFAPI_DL_CONFIG_PCH_PDU_TYPE"; + case NFAPI_DL_CONFIG_PRS_PDU_TYPE: return "NFAPI_DL_CONFIG_PRS_PDU_TYPE"; + case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: return "NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE"; + case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: return "NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE"; + case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: return "NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE"; + case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: return "NFAPI_DL_CONFIG_NBCH_PDU_TYPE"; + case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: return "NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE"; + case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: return "NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE"; + } + return "UNKNOWN"; +} + +static char *UL_PDU_TYPE(int x) +{ + switch (x) { + case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_PDU_TYPE"; + case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE"; + case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE"; + case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE"; + case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE"; + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE"; + case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE"; + case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE"; + case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE"; + case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE"; + case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE"; + case NFAPI_UL_CONFIG_SRS_PDU_TYPE: return "NFAPI_UL_CONFIG_SRS_PDU_TYPE"; + case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: return "NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE"; + case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE"; + case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE"; + case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE"; + case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: return "NFAPI_UL_CONFIG_NULSCH_PDU_TYPE"; + case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: return "NFAPI_UL_CONFIG_NRACH_PDU_TYPE"; + } + return "UNKNOWN"; +} + +static char *HI_DCI0_PDU_TYPE(int x) +{ + switch (x) { + case NFAPI_HI_DCI0_HI_PDU_TYPE: return "NFAPI_HI_DCI0_HI_PDU_TYPE"; + case NFAPI_HI_DCI0_DCI_PDU_TYPE: return "NFAPI_HI_DCI0_DCI_PDU_TYPE"; + case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: return "NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE"; + case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: return "NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE"; + case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: return "NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE"; + } + return "UNKNOWN"; +} + +static void dump_dl(Sched_Rsp_t *d) +{ + int i; + + C; + A("XXXX DL mod %d CC %d f.sf %d.%d\n", + d->module_id, d->CC_id, d->frame, d->subframe); + + if (d->DL_req != NULL) { + nfapi_dl_config_request_body_t *v=&d->DL_req->dl_config_request_body; + nfapi_dl_config_request_pdu_t *p = v->dl_config_pdu_list; + A("XXXX DL_req sfnsf %d\n", d->DL_req->sfn_sf); + A("XXXX PDCCH size %d\n", v->number_pdcch_ofdm_symbols); + A("XXXX DCIs %d\n", v->number_dci); + A("XXXX PDUs %d\n", v->number_pdu); + A("XXXX rntis %d\n", v->number_pdsch_rnti); + A("XXXX pcfich power %d\n", v->transmission_power_pcfich); + for (i = 0; i < v->number_pdu; i++) { + A("XXXX pdu %d\n", i); + A("XXXX type %d %s\n", p[i].pdu_type, DL_PDU_TYPE(p[i].pdu_type)); + switch (p[i].pdu_type) { + case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: { + nfapi_dl_config_dci_dl_pdu_rel8_t *q = + &p[i].dci_dl_pdu.dci_dl_pdu_rel8; + A("XXXX dci format %d\n", q->dci_format); + A("XXXX cce idx %d\n", q->cce_idx); + A("XXXX agg lvl %d\n", q->aggregation_level); + A("XXXX rnti %d\n", q->rnti); + A("XXXX rb coding %8.8x\n", q->resource_block_coding); + A("XXXX mcs_1 %d\n", q->mcs_1); + A("XXXX rv_1 %d\n", q->redundancy_version_1); + A("XXXX ndi_1 %d\n", q->new_data_indicator_1); + A("XXXX harq pid %d\n", q->harq_process); + A("XXXX tpc %d\n", q->tpc); + A("XXXX tbs idx %d\n", q->transport_block_size_index); + A("XXXX dl pow off %d\n", q->downlink_power_offset); + A("XXXX rnti type %d\n", q->rnti_type); + A("XXXX xmit pow %d\n", q->transmission_power); + break; + } + case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: { + nfapi_dl_config_dlsch_pdu_rel8_t *q = + &p[i].dlsch_pdu.dlsch_pdu_rel8; + A("XXXX pdu_index %d\n", q->pdu_index); + A("XXXX rnti %d\n", q->rnti); + A("XXXX rv %d\n", q->redundancy_version); + A("XXXX mcs %d\n", q->modulation); + A("XXXX pa %d\n", q->pa); + break; + }} + } + } + + if (d->HI_DCI0_req != NULL) { + nfapi_hi_dci0_request_body_t *v=&d->HI_DCI0_req->hi_dci0_request_body; + A("XXXX up HI_DCI0_req sfnsf %d (%d.%d)\n", d->HI_DCI0_req->sfn_sf, + d->HI_DCI0_req->sfn_sf/16, d->HI_DCI0_req->sfn_sf%16); + A("XXXX up sfnsf %d\n", v->sfnsf); + A("XXXX up DCIs %d\n", v->number_of_dci); + A("XXXX up HIs %d\n", v->number_of_hi); + for (i = 0; i < v->number_of_dci + v->number_of_hi; i++) { + nfapi_hi_dci0_request_pdu_t *p = &v->hi_dci0_pdu_list[i]; + A("XXXX up pdu %d\n", i); + A("XXXX up type %d %s\n",p->pdu_type,HI_DCI0_PDU_TYPE(p->pdu_type)); + if (p->pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) { + nfapi_hi_dci0_dci_pdu_rel8_t *q = &p->dci_pdu.dci_pdu_rel8; + A("XXXX up dci_format %d\n", q->dci_format); + A("XXXX up cce_index %d\n", q->cce_index); + A("XXXX up aggregation_level %d\n", q->aggregation_level); + A("XXXX up rnti %d\n", q->rnti); + A("XXXX up rb start %d\n", q->resource_block_start); + A("XXXX up # rb %d\n", q->number_of_resource_block); + A("XXXX up mcs_1 %d\n", q->mcs_1); + A("XXXX up cshift_2_for_drms %d\n", q->cyclic_shift_2_for_drms); + A("XXXX up freq hop enabled %d\n", q->frequency_hopping_enabled_flag); + A("XXXX up fre hop bits %d\n", q->frequency_hopping_bits); + A("XXXX up NDI_1 %d\n", q->new_data_indication_1); + A("XXXX up tx_antenna_seleciton %d\n", q->ue_tx_antenna_seleciton); + A("XXXX up tpc %d\n", q->tpc); + A("XXXX up cqi_csi_request %d\n", q->cqi_csi_request); + A("XXXX up ul_index %d\n", q->ul_index); + A("XXXX up dl_assignment_index %d\n", q->dl_assignment_index); + A("XXXX up tpc_bitmap %d\n", q->tpc_bitmap); + A("XXXX up transmission_power %d\n", q->transmission_power); + } + if (p->pdu_type == NFAPI_HI_DCI0_HI_PDU_TYPE) { + nfapi_hi_dci0_hi_pdu_rel8_t *q = &p->hi_pdu.hi_pdu_rel8; + A("XXXX up rb start %d\n", q->resource_block_start); + A("XXXX up cs2_drms %d\n", q->cyclic_shift_2_for_drms); + A("XXXX up ack %d\n", q->hi_value); + A("XXXX up i_phich %d\n", q->i_phich); + A("XXXX up power %d\n", q->transmission_power); + } + } + } + + if (d->UL_req != NULL) { + nfapi_ul_config_request_body_t *v=&d->UL_req->ul_config_request_body; + A("XXXX UL_req sfnsf %d (%d.%d)\n", d->UL_req->sfn_sf, + d->UL_req->sfn_sf/16, d->UL_req->sfn_sf%16); + A("XXXX PDUs %d\n", v->number_of_pdus); + A("XXXX ra freq %d\n", v->rach_prach_frequency_resources); + A("XXXX srs? %d\n", v->srs_present); + for (i = 0; i < v->number_of_pdus; i++) { + nfapi_ul_config_request_pdu_t *p = &v->ul_config_pdu_list[i]; + A("XXXX pdu %d\n", i); + A("XXXX type %d %s\n", p->pdu_type, UL_PDU_TYPE(p->pdu_type)); + switch(p->pdu_type) { + case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: { + nfapi_ul_config_uci_harq_pdu *q = &p->uci_harq_pdu; + nfapi_ul_config_harq_information_rel9_fdd_t *h = + &q->harq_information.harq_information_rel9_fdd; + A("XXXX rnti %d\n", + q->ue_information.ue_information_rel8.rnti); + A("XXXX harq size %d\n", h->harq_size); + A("XXXX ack_nack_mode %d\n", h->ack_nack_mode); + A("XXXX # pucch res %d\n", h->number_of_pucch_resources); + A("XXXX n_pucch_1_0 %d\n", h->n_pucch_1_0); + A("XXXX n_pucch_1_1 %d\n", h->n_pucch_1_1); + A("XXXX n_pucch_1_2 %d\n", h->n_pucch_1_2); + A("XXXX n_pucch_1_3 %d\n", h->n_pucch_1_3); + break; + } + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: { + nfapi_ul_config_uci_sr_pdu *q = &p->uci_sr_pdu; + nfapi_ul_config_sr_information_rel8_t *h = + &q->sr_information.sr_information_rel8; + A("XXXX rnti %d\n", + q->ue_information.ue_information_rel8.rnti); + A("XXXX pucch_index %d\n", h->pucch_index); + }} + } + } + + LOG_I(PHY, "XXXX DL\nXXXX DL\n%s", s); +} + +#undef C +#undef A + +#endif /* DUMP_FAPI */ + +/****************************************************************************/ +/* debug utility functions end */ +/****************************************************************************/ + +void UL_indication(UL_IND_t *UL_info) +{ + + AssertFatal(UL_info!=NULL,"UL_INFO is null\n"); + +#ifdef DUMP_FAPI + dump_ul(UL_info); +#endif + + module_id_t module_id = UL_info->module_id; + int CC_id = UL_info->CC_id; + Sched_Rsp_t *sched_info = &Sched_INFO[module_id][CC_id]; + IF_Module_t *ifi = if_inst[module_id]; + eNB_MAC_INST *mac = RC.mac[module_id]; + + LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rx_ind:%d harqs:%d crcs:%d cqis:%d preambles:%d sr_ind:%d]\n", + UL_info->frame,UL_info->subframe, + module_id,CC_id, + UL_info->rx_ind.rx_indication_body.number_of_pdus, UL_info->harq_ind.harq_indication_body.number_of_harqs, UL_info->crc_ind.crc_indication_body.number_of_crcs, UL_info->cqi_ind.number_of_cqis, UL_info->rach_ind.rach_indication_body.number_of_preambles, UL_info->sr_ind.sr_indication_body.number_of_srs); + + if (nfapi_mode != 1) + { + if (ifi->CC_mask==0) { + ifi->current_frame = UL_info->frame; + ifi->current_subframe = UL_info->subframe; + } + else { + AssertFatal(UL_info->frame != ifi->current_frame,"CC_mask %x is not full and frame has changed\n",ifi->CC_mask); + AssertFatal(UL_info->subframe != ifi->current_subframe,"CC_mask %x is not full and subframe has changed\n",ifi->CC_mask); + } + ifi->CC_mask |= (1<<CC_id); + } + + + // clear DL/UL info for new scheduling round + clear_nfapi_information(RC.mac[module_id],CC_id, + UL_info->frame,UL_info->subframe); + + handle_rach(UL_info); + + handle_sr(UL_info); + + handle_cqi(UL_info); + + handle_harq(UL_info); + + // clear HI prior to handling ULSCH + mac->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_hi = 0; + + handle_ulsch(UL_info); + + if (nfapi_mode != 1) + { + if (ifi->CC_mask == ((1<<MAX_NUM_CCs)-1)) { + + eNB_dlsch_ulsch_scheduler(module_id, + (UL_info->frame+((UL_info->subframe>(9-sf_ahead))?1:0)) % 1024, + (UL_info->subframe+sf_ahead)%10); + + ifi->CC_mask = 0; + + sched_info->module_id = module_id; + sched_info->CC_id = CC_id; + sched_info->frame = (UL_info->frame + ((UL_info->subframe>(9-sf_ahead)) ? 1 : 0)) % 1024; + sched_info->subframe = (UL_info->subframe+sf_ahead)%10; + sched_info->DL_req = &mac->DL_req[CC_id]; + sched_info->HI_DCI0_req = &mac->HI_DCI0_req[CC_id]; + if ((mac->common_channels[CC_id].tdd_Config==NULL) || + (is_UL_sf(&mac->common_channels[CC_id],(sched_info->subframe+sf_ahead)%10)>0)) + sched_info->UL_req = &mac->UL_req[CC_id]; + else + sched_info->UL_req = NULL; + + sched_info->TX_req = &mac->TX_req[CC_id]; + +#ifdef DUMP_FAPI + dump_dl(sched_info); +#endif + + if (ifi->schedule_response) + { + AssertFatal(ifi->schedule_response!=NULL, + "schedule_response is null (mod %d, cc %d)\n", + module_id, + CC_id); + ifi->schedule_response(sched_info); + } + + LOG_D(PHY,"Schedule_response: SFN_SF:%d%d dl_pdus:%d\n",sched_info->frame,sched_info->subframe,sched_info->DL_req->dl_config_request_body.number_pdu); + } + } +} + +IF_Module_t *IF_Module_init(int Mod_id){ + + AssertFatal(Mod_id<MAX_MODULES,"Asking for Module %d > %d\n",Mod_id,MAX_IF_MODULES); + + LOG_D(PHY,"Installing callbacks for IF_Module - UL_indication\n"); + + if (if_inst[Mod_id]==NULL) { + if_inst[Mod_id] = (IF_Module_t*)malloc(sizeof(IF_Module_t)); + memset((void*)if_inst[Mod_id],0,sizeof(IF_Module_t)); + + if_inst[Mod_id]->CC_mask=0; + if_inst[Mod_id]->UL_indication = UL_indication; + + AssertFatal(pthread_mutex_init(&if_inst[Mod_id]->if_mutex,NULL)==0, + "allocation of if_inst[%d]->if_mutex fails\n",Mod_id); + } + return if_inst[Mod_id]; +} + +void IF_Module_kill(int Mod_id) { + + AssertFatal(Mod_id>MAX_MODULES,"Asking for Module %d > %d\n",Mod_id,MAX_IF_MODULES); + if (if_inst[Mod_id]!=NULL) free(if_inst[Mod_id]); + +} diff --git a/openair2/NR_UE_PHY_INTERFACE/IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/IF_Module.h new file mode 100644 index 0000000000..3b1c88dda0 --- /dev/null +++ b/openair2/NR_UE_PHY_INTERFACE/IF_Module.h @@ -0,0 +1,142 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file openair2/PHY_INTERFACE/IF_Module.h +* \brief data structures for PHY/MAC interface modules +* \author EURECOM/NTUST +* \date 2017 +* \version 0.1 +* \company Eurecom +* \email: raymond.knopp@eurecom.fr +* \note +* \warning +*/ +#ifndef __IF_MODULE__H__ +#define __IF_MODULE__H__ + + +#include <stdint.h> +#include "openair1/PHY/LTE_TRANSPORT/defs.h" +#include "nfapi_interface.h" + + +#define MAX_NUM_DL_PDU 100 +#define MAX_NUM_UL_PDU 100 +#define MAX_NUM_HI_DCI0_PDU 100 +#define MAX_NUM_TX_REQUEST_PDU 100 + +#define MAX_NUM_HARQ_IND 100 +#define MAX_NUM_CRC_IND 100 +#define MAX_NUM_SR_IND 100 +#define MAX_NUM_CQI_IND 100 +#define MAX_NUM_RACH_IND 100 +#define MAX_NUM_SRS_IND 100 + +typedef struct{ + /// Module ID + module_id_t module_id; + /// CC ID + int CC_id; + /// frame + frame_t frame; + /// subframe + sub_frame_t subframe; + + /// harq indication list + nfapi_harq_indication_t harq_ind; + + /// crc indication list + nfapi_crc_indication_t crc_ind; + + /// SR indication list + nfapi_sr_indication_t sr_ind; + + /// CQI indication list + nfapi_cqi_indication_body_t cqi_ind; + + /// RACH indication list + nfapi_rach_indication_t rach_ind; + +#ifdef Rel14 + /// RACH indication list for BR UEs + nfapi_rach_indication_t rach_ind_br; +#endif + + /// SRS indication list + nfapi_srs_indication_body_t srs_ind; + + /// RX indication + nfapi_rx_indication_t rx_ind; + +} UL_IND_t; + +// Downlink subframe P7 + + +typedef struct{ + /// Module ID + module_id_t module_id; + /// CC ID + uint8_t CC_id; + /// frame + frame_t frame; + /// subframe + sub_frame_t subframe; + /// nFAPI DL Config Request + nfapi_dl_config_request_t *DL_req; + /// nFAPI UL Config Request + nfapi_ul_config_request_t *UL_req; + /// nFAPI HI_DCI Request + nfapi_hi_dci0_request_t *HI_DCI0_req; + /// Pointers to DL SDUs + nfapi_tx_request_t *TX_req; +}Sched_Rsp_t; + +typedef struct { + uint8_t Mod_id; + int CC_id; + nfapi_config_request_t *cfg; +}PHY_Config_t; + +typedef struct IF_Module_s{ +//define the function pointer + void (*UL_indication)(UL_IND_t *UL_INFO); + void (*schedule_response)(Sched_Rsp_t *Sched_INFO); + void (*PHY_config_req)(PHY_Config_t* config_INFO); + uint32_t CC_mask; + uint16_t current_frame; + uint8_t current_subframe; + pthread_mutex_t if_mutex; +}IF_Module_t; + +/*Initial */ +IF_Module_t *IF_Module_init(int Mod_id); +void IF_Module_kill(int Mod_id); + +/*Interface for uplink, transmitting the Preamble(list), ULSCH SDU, NAK, Tick (trigger scheduler) + */ +void UL_indication(UL_IND_t *UL_INFO); + +/*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/ +void Schedule_Response(Sched_Rsp_t *Sched_INFO); + +#endif + diff --git a/openair2/NR_UE_PHY_INTERFACE/defs.h b/openair2/NR_UE_PHY_INTERFACE/defs.h new file mode 100644 index 0000000000..deb07443f1 --- /dev/null +++ b/openair2/NR_UE_PHY_INTERFACE/defs.h @@ -0,0 +1,373 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PHY_INTERFACE/defs.h +* \brief mac phy interface primitives +* \author Raymond Knopp and Navid Nikaein +* \date 2011 +* \version 0.5 +* \mail navid.nikaein@eurecom.fr or openair_tech@eurecom.fr +*/ + +#ifndef __MAC_PHY_PRIMITIVES_H__ +# define __MAC_PHY_PRIMITIVES_H__ + +#include "LAYER2/MAC/defs.h" + + +#define MAX_NUMBER_OF_MAC_INSTANCES 16 + +#define NULL_PDU 255 +#define DCI 0 +#define DLSCH 1 +#define ULSCH 2 + +#define mac_exit_wrapper(sTRING) \ +do { \ + char temp[300]; \ + snprintf(temp, sizeof(temp), "%s in file "__FILE__" at line %d\n", sTRING, __LINE__); \ + mac_xface->macphy_exit(temp); \ +} while(0) + +/** @defgroup _phy_if MAC-PHY interface + * @ingroup _oai2 + * @{ + */ +/*! \brief MACPHY Interface */ +/* +typedef struct { + /// Pointer function that initializes L2 + int (*macphy_init)(int eMBMS_active, char *uecap_xer, uint8_t CBA_active,uint8_t HO_active); + + /// Pointer function that stops the low-level scheduler due an exit condition + void (*macphy_exit)(const char *); + + // eNB functions + /// Invoke dlsch/ulsch scheduling procedure for new subframe + void (*eNB_dlsch_ulsch_scheduler)(module_id_t Mod_id,uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP);//, int calibration_flag); + + /// Fill random access response sdu, passing timing advance + uint16_t (*fill_rar)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t *dlsch_buffer,uint16_t N_RB_UL, uint8_t input_buffer_length); + + /// Initiate the RA procedure upon reception (hypothetical) of a valid preamble + void (*initiate_ra_proc)(module_id_t Mod_id,int CC_id,frame_t frameP,uint16_t preamble,int16_t timing_offset,uint8_t sect_id,sub_frame_t subframe,uint8_t f_id); + + /// cancel an ongoing RA procedure + void (*cancel_ra_proc)(module_id_t Mod_id,int CC_id,frame_t frameP,uint16_t preamble); + + /// Inform MAC layer 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. + void (*set_msg3_subframe)(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + int rnti, + int Msg3_frame, + int Msg3_subframe); + + /// Get DCI for current subframe from MAC + DCI_PDU* (*get_dci_sdu)(module_id_t Mod_id,int CC_id,frame_t frameP,sub_frame_t subframe); + + /// Get DLSCH sdu for particular RNTI and Transport block index + uint8_t* (*get_dlsch_sdu)(module_id_t Mod_id,int CC_id,frame_t frameP,rnti_t rnti,uint8_t TB_index); + + /// Send ULSCH sdu to MAC for given rnti + void (*rx_sdu)(module_id_t Mod_id,int CC_id,frame_t frameP, sub_frame_t sub_frameP,rnti_t rnti, uint8_t *sdu,uint16_t sdu_len, int harq_pid,uint8_t *msg3_flag); + + /// Indicate failure to synch to external source + void (*mrbch_phy_sync_failure) (module_id_t Mod_id,frame_t frameP, uint8_t free_eNB_index); + + /// Indicate Scheduling Request from UE + void (*SR_indication)(module_id_t Mod_id,int CC_id,frame_t frameP,rnti_t rnti,sub_frame_t subframe); + /// Indicate UL Failure to eNodeB MAC + void (*UL_failure_indication)(module_id_t Mod_id,int CC_id,frame_t frameP,rnti_t rnti,sub_frame_t subframe); + + /// Configure Common PHY parameters from SIB1 + void (*phy_config_mib_eNB)(module_id_t Mod_id,int CC_id, + int eutra_band, + int N_RB_DL, + PHICH_Config_t *phich_Config, + int Nid_cell, + int Ncp, + int p_eNB, + uint32_t dl_CarrierFreq, + uint32_t ul_CarrierFreq); + + /// Configure Common PHY parameters from SIB1 + void (*phy_config_sib1_eNB)(module_id_t Mod_id,int CC_id, + TDD_Config_t *tdd_config, + uint8_t SIwindowsize, + uint16_t SIperiod); + + /// Configure Common PHY parameters from SIB2 + void (*phy_config_sib2_eNB)(module_id_t Mod_id, int CC_id, + RadioResourceConfigCommonSIB_t *radioResourceConfigCommon, + ARFCN_ValueEUTRA_t *ul_CArrierFreq, + long *ul_Bandwidth, + AdditionalSpectrumEmission_t *additionalSpectrumEmission, + struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList); + +#if defined(Rel10) || defined(Rel14) + /// Configure Common PHY parameters from SIB13 + void (*phy_config_sib13_eNB)(module_id_t Mod_id,int CC_id, int mbsfn_Area_idx, + long mbsfn_AreaId_r9); + + void (*phy_config_dedicated_scell_eNB)(uint8_t Mod_id, + uint16_t rnti, + SCellToAddMod_r10_t *sCellToAddMod_r10, + int CC_id); +#endif + + /// PHY-Config-Dedicated eNB + void (*phy_config_dedicated_eNB)(module_id_t Mod_id,int CC_id,rnti_t rnti, + struct PhysicalConfigDedicated *physicalConfigDedicated); + +#if defined(Rel10) || defined(Rel14) + /// Get MCH sdu and corresponding MCS for particular MBSFN subframe + MCH_PDU* (*get_mch_sdu)(module_id_t Mod_id, int CC_id, frame_t frameP,sub_frame_t subframe); +#endif + // configure the cba rnti at the physical layer + void (*phy_config_cba_rnti)(module_id_t Mod_id,int CC_id,eNB_flag_t eNB_flag, uint8_t index, uint16_t cba_rnti, uint8_t cba_group_id, uint8_t num_active_cba_groups); + /// get delta mcs for fast UL AMC + int16_t (*estimate_ue_tx_power)(uint32_t tbs, uint32_t nb_rb, uint8_t control_only, lte_prefix_type_t ncp, uint8_t use_srs); + + int (*mac_phy_remove_ue)(module_id_t Mod_idP,rnti_t rntiP); + /// UE functions + + /// reset the ue phy + void (*phy_reset_ue)(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index); + + /// Indicate loss of synchronization of PBCH for this eNB to MAC layer + void (*out_of_sync_ind)(module_id_t Mod_id,frame_t frameP,uint16_t eNB_index); + + /// Send a received SI sdu + void (*ue_decode_si)(module_id_t Mod_id,int CC_id,frame_t frameP, uint8_t CH_index, void *pdu, uint16_t len); + + /// Send a received Paging sdu + void (*ue_decode_p)(module_id_t Mod_id,int CC_id,frame_t frameP, uint8_t CH_index, void *pdu, uint16_t len); + + /// Send a received DLSCH sdu to MAC + void (*ue_send_sdu)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,sub_frame_t subframe,uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index); + +#if defined(Rel10) || defined(Rel14) + /// Send a received MCH sdu to MAC + void (*ue_send_mch_sdu)(module_id_t Mod_id,uint8_t CC_id, frame_t frameP,uint8_t *sdu,uint16_t sdu_len,uint8_t eNB_index,uint8_t sync_area); + + /// Function to check if UE PHY needs to decode MCH for MAC + /// get the sync area id, and return MCS value if need to decode, otherwise -1 + int (*ue_query_mch)(module_id_t Mod_id, uint8_t CC_id,frame_t frameP,sub_frame_t subframe,uint8_t eNB_index,uint8_t *sync_area, uint8_t *mcch_active); +#endif + + /// Retrieve ULSCH sdu from MAC + void (*ue_get_sdu)(module_id_t Mod_id,int CC_id,frame_t frameP,sub_frame_t subframe, uint8_t CH_index,uint8_t *ulsch_buffer,uint16_t buflen,uint8_t *access_mode); + + /// Retrieve RRCConnectionReq from MAC + PRACH_RESOURCES_t* (*ue_get_rach)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t Msg3_flag,sub_frame_t subframe); + + /// Process Random-Access Response + uint16_t (*ue_process_rar)(module_id_t Mod_id,int CC_id,frame_t frameP, uint16_t ra_rnti, uint8_t *dlsch_buffer, uint16_t *t_crnti,uint8_t preamble_index, uint8_t* selected_rar_buffer); + + /// Get SR payload (0,1) from UE MAC + uint32_t (*ue_get_SR)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t eNB_id,rnti_t rnti,sub_frame_t subframe); + + /// Indicate synchronization with valid PBCH + void (*dl_phy_sync_success) (module_id_t Mod_id,frame_t frameP, uint8_t CH_index,uint8_t first_sync); + + /// Only calls the PDCP for now + UE_L2_STATE_t (*ue_scheduler)(module_id_t Mod_id, frame_t rxFrameP,sub_frame_t rxSubframe, frame_t txFrameP,sub_frame_t txSubframe, lte_subframe_t direction, uint8_t eNB_id, int CC_id); + + /// PHY-Config-Dedicated UE + void (*phy_config_dedicated_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index, + struct PhysicalConfigDedicated *physicalConfigDedicated); + + /// PHY-Config-harq UE + void (*phy_config_harq_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index, + uint16_t max_harq_tx); + /// Configure Common PHY parameters from SIB1 + void (*phy_config_sib1_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index, + TDD_Config_t *tdd_config, + uint8_t SIwindowsize, + uint16_t SIperiod); + + /// Configure Common PHY parameters from SIB2 + void (*phy_config_sib2_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index, + RadioResourceConfigCommonSIB_t *radioResourceConfigCommon, + ARFCN_ValueEUTRA_t *ul_CArrierFreq, + long *ul_Bandwidth, + AdditionalSpectrumEmission_t *additionalSpectrumEmission, + struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList); + +#if defined(Rel10) || defined(Rel14) + /// Configure Common PHY parameters from SIB13 + void (*phy_config_sib13_ue)(uint8_t Mod_id,int CC_id, uint8_t eNB_index,int mbsfn_Area_idx, + long mbsfn_AreaId_r9); + + void (*phy_config_dedicated_scell_ue)(uint8_t Mod_id, + uint8_t eNB_index, + SCellToAddMod_r10_t *sCellToAddMod_r10, + int CC_id); +#endif + /// Configure Common PHY parameters from mobilityControlInfo + void (*phy_config_afterHO_ue)(module_id_t Mod_id,uint8_t CC_id,uint8_t CH_index, + MobilityControlInfo_t *mobilityControlInfo, + uint8_t ho_failed); + + /// Function to indicate failure of contention resolution or RA procedure + void (*ra_failed)(module_id_t Mod_id, uint8_t CC_id,uint8_t eNB_index); + + /// Function to indicate success of contention resolution or RA procedure + void (*ra_succeeded)(module_id_t Mod_id,uint8_t CC_id, uint8_t eNB_index); + + /// Function to indicate the transmission of msg1/rach to MAC + void (*Msg1_transmitted)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,uint8_t eNB_id); + + /// Function to indicate Msg3 transmission/retransmission which initiates/reset Contention Resolution Timer + void (*Msg3_transmitted)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,uint8_t eNB_id); + + /// Function to pass inter-cell measurement parameters to PHY (cell Ids) + void (*phy_config_meas_ue)(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index,uint8_t n_adj_cells,uint32_t *adj_cell_id); + + // PHY Helper Functions + + /// RIV computation from PHY + uint16_t (*computeRIV)(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs); + + /// Downlink TBS table lookup from PHY + uint32_t (*get_TBS_DL)(uint8_t mcs, uint16_t nb_rb); + + /// Uplink TBS table lookup from PHY + uint32_t (*get_TBS_UL)(uint8_t mcs, uint16_t nb_rb); + + /// Function to retrieve the HARQ round index for a particular UL/DLSCH and harq_pid + int (*get_ue_active_harq_pid)(module_id_t Mod_id, uint8_t CC_id,rnti_t rnti, int frame, uint8_t subframe, uint8_t *harq_pid, uint8_t *round, uint8_t ul_flag); + + /// Function to retrieve number of CCE + uint16_t (*get_nCCE_max)(module_id_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int subframe); + + + 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); + + /// Function to retrieve number of PRB in an rb_alloc + uint32_t (*get_nb_rb)(uint8_t ra_header, uint32_t rb_alloc, int n_rb_dl); + + /// Function to convert VRB to PRB for distributed allocation + uint32_t (*get_prb)(int N_RB_DL,int odd_slot,int vrb,int Ngap); + + /// Function to retrieve transmission mode for UE + uint8_t (*get_transmission_mode)(module_id_t Mod_id,uint8_t CC_id,rnti_t rnti); + + /// Function to retrieve rb_alloc bitmap from dci rballoc field and VRB type + uint32_t (*get_rballoc)(vrb_t vrb_type, uint16_t rb_alloc_dci); + + /// Function for UE MAC to retrieve current PHY connectivity mode (PRACH,RA_RESPONSE,PUSCH) + UE_MODE_t (*get_ue_mode)(module_id_t Mod_id, uint8_t CC_id,uint8_t eNB_index); + + /// Function for UE MAC to retrieve measured Path Loss + int16_t (*get_PL)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index); + + /// Function for UE MAC to retrieve the rssi + uint32_t (*get_RSSI)(uint8_t Mod_id,uint8_t CC_id); + + /// Function for UE MAC to retrieve the total gain + uint32_t (*get_rx_total_gain_dB)(uint8_t Mod_id,uint8_t CC_id); + + /// Function for UE MAC to retrieve the number of adjustent cells + uint8_t (*get_n_adj_cells)(uint8_t Mod_id,uint8_t CC_id); + + /// Function for UE MAC to retrieve RSRP/RSRQ measurements + uint32_t (*get_RSRP)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index); + + /// Function for UE MAC to retrieve RSRP/RSRQ measurements + uint32_t (*get_RSRQ)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index); + + /// Function for UE MAC to set the layer3 filtered RSRP/RSRQ measurements + uint8_t (*set_RSRP_filtered)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrp); + + /// Function for UE MAC to set the layer3 filtered RSRP/RSRQ measurements + uint8_t (*set_RSRQ_filtered)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrp); + + /// Function for UE/eNB MAC to retrieve number of PRACH in TDD + uint8_t (*get_num_prach_tdd)(LTE_DL_FRAME_PARMS *frame_parms); + + /// Function for UE/eNB MAC to retrieve f_id of particular PRACH resource in TDD + uint8_t (*get_fid_prach_tdd)(LTE_DL_FRAME_PARMS *frame_parms,uint8_t tdd_map_index); + + /// Function for eNB MAC to retrieve subframe direction + lte_subframe_t (*get_subframe_direction)(module_id_t Mod_id, uint8_t CC_id, uint8_t subframe); + + // MAC Helper functions + /// Function for UE/PHY to compute PUSCH transmit power in power-control procedure (Po_NOMINAL_PUSCH parameter) + int8_t (*get_Po_NOMINAL_PUSCH)(module_id_t Mod_id,uint8_t CC_id); + + /// Function for UE/PHY to compute PUSCH transmit power in power-control procedure (deltaP_rampup parameter) + int8_t (*get_deltaP_rampup)(module_id_t Mod_id,uint8_t CC_id); + + /// Function for UE/PHY to compute PHR + int8_t (*get_PHR)(module_id_t Mod_id, uint8_t CC_id,uint8_t eNB_index); + + /// Function for UE to process the timing advance command + void (*process_timing_advance)(module_id_t Mod_id,uint8_t CC_id, int16_t timing_advance); + + /// Function for MAC to get the UE stats from the PHY + LTE_eNB_UE_stats* (*get_eNB_UE_stats)(module_id_t Mod_id, uint8_t CC_id, rnti_t rnti); + + /// get the frame parameters from the PHY + LTE_DL_FRAME_PARMS* (*get_lte_frame_parms)(module_id_t Mod_id, uint8_t CC_id); + + /// get the Multiuser mimo mode + MU_MIMO_mode* (*get_mu_mimo_mode) (module_id_t Mod_id, uint8_t CC_id, rnti_t rnti); + + /// get the delta TF for Uplink Power Control Calculation + int16_t (*get_hundred_times_delta_TF) (module_id_t module_idP, uint8_t CC_id, rnti_t rnti, uint8_t harq_pid); + /// get target PUSCH received power + int16_t (*get_target_pusch_rx_power) (module_id_t module_idP, uint8_t CC_id); + /// get target PUSCH received power + int16_t (*get_target_pucch_rx_power) (module_id_t module_idP, uint8_t CC_id); + + unsigned char is_cluster_head; + unsigned char is_primary_cluster_head; + unsigned char is_secondary_cluster_head; + unsigned char cluster_head_index; + + /// PHY Frame Configuration + LTE_DL_FRAME_PARMS *frame_parms; + + uint8_t (*get_prach_prb_offset)(LTE_DL_FRAME_PARMS *frame_parms, uint8_t tdd_mapindex, uint16_t Nf); + + int (*is_prach_subframe)(LTE_DL_FRAME_PARMS *frame_parms,frame_t frame, uint8_t subframe); + + /// ICIC algos + uint8_t (*get_SB_size)(uint8_t n_rb_dl); + ///end ALU's algo + +} MAC_xface; + +*/ + +#endif + + +/** @} */ diff --git a/openair2/NR_UE_PHY_INTERFACE/extern.h b/openair2/NR_UE_PHY_INTERFACE/extern.h new file mode 100644 index 0000000000..b87fa42fe4 --- /dev/null +++ b/openair2/NR_UE_PHY_INTERFACE/extern.h @@ -0,0 +1,27 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef __PHY_INTERFACE_EXTERN_H__ +#define __PHY_INTERFACE_EXTERN_H__ + + + +#endif diff --git a/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.c b/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.c new file mode 100644 index 0000000000..06e06d096d --- /dev/null +++ b/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.c @@ -0,0 +1,283 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*________________________mac_phy_primitives.c________________________ + + Authors : Hicham Anouar, Raymond Knopp + Company : EURECOM + Emails : anouar@eurecom.fr, knopp@eurecom.fr +________________________________________________________________*/ + + +//#include "openair_extern.h" + +#ifdef MAC_CONTEXT +#include "LAYER2/MAC/defs.h" +#include "LAYER2/MAC/extern.h" +//#include "extern.h" +#include "defs.h" +#endif //MAC_CONTEXT + + +//#define DEBUG_UE_DECODE_SACH +//#define DEBUG_NODEB_DECODE_SACH + +#ifdef PHY_CONTEXT +#ifdef PHY_EMUL +#include "extern.h" +#include "SIMULATION/simulation_defs.h" +#else //PHY_EMUL +#include "MAC_INTERFACE/extern.h" +#endif //PHY_EMUL + +void clear_macphy_data_req(unsigned char Mod_id) +{ + //msg("CLEAR DATA_REQ\n"); + unsigned char i; + + Macphy_req_table[Mod_id].Macphy_req_cnt = 0; + + for (i=0; i<NB_REQ_MAX; i++) + Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active = 0; +} + +/* +unsigned char phy_resources_compare(PHY_RESOURCES *Phy1,PHY_RESOURCES* Phy2 ){ + + if(Phy1->Time_alloc==Phy2->Time_alloc && Phy1->Freq_alloc==Phy2->Freq_alloc)// && Phy1->Coding_fmt==Phy2->Coding_fmt && Phy1->Seq_index==Phy2->Seq_index) + return 1; + else + return 0; + +} +*/ + +MACPHY_DATA_REQ_TABLE_ENTRY* find_data_req_entry(unsigned char Mod_id,MACPHY_REQ_ENTRY_KEY *Search_key) +{ + + unsigned char i; + + //msg("[MAC_PHY]MAC_PHY_REQUEST_CNT=%d\n",Macphy_req_table.Macphy_req_cnt); + if (Macphy_req_table[Mod_id].Macphy_req_cnt > 0) { +#ifdef DEBUG_PHY + // msg("[MACPHY_FIND_REQ] SEARCH KEY=%d\n",Search_key->Key_type); +#endif //DEBUG_PHY + //msg("[MACPHY_FIND_REQ] SEARCH KEY=%d, NB_REQ_MAX=%d\n",Search_key->Key_type,NB_REQ_MAX); + + switch(Search_key->Key_type) { + case PDU_TYPE_KEY: + for(i=0; i<NB_REQ_MAX; i++) { + if ( (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Pdu_type==Search_key->Key.Pdu_type) && + (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) ) { + //msg("[MACPHY_FIND] MACPHY_req_table_entry=%p,idx=%d,Phy_resources %p", &Macphy_req_table.Macphy_req_table_entry[i],i,Macphy_req_table.Macphy_req_table_entry[i].Macphy_data_req.Phy_Resources_Entry); + return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]); + } + } + + break; + /* + case LCHAN_KEY: + for(i=0;i<NB_REQ_MAX;i++){ + if ((Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Lchan_id.Index==Search_key->Key.Lchan_id->Index) && + (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) ) + return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]); + } + break; + + case PHY_RESOURCES_KEY: + for(i=0;i<NB_REQ_MAX;i++){ + if(Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) + if ( ( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Time_alloc == + Search_key->Key.Phy_resources.Time_alloc ) + &&( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Freq_alloc == + Search_key->Key.Phy_resources.Freq_alloc ) + &&( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.CH_index == + Search_key->CH_index ) + && ( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Direction == RX)) + return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]); + } + break; + */ + } + } + +#ifndef PHY_EMUL + // msg("[PHY][PHY_MAC] Frame %d : No data request\n",mac_xface->frame); +#endif //PHY_EMUL + + + return (MACPHY_DATA_REQ_TABLE_ENTRY*)0; + +} + + + + + + +void print_active_requests(unsigned char Mod_id) +{ + + int i; + msg("_________________________INST %d , FRAME %d ACTIVE_REQUESTS_________________\n",Mod_id,mac_xface->frame); + + for (i=0; i<NB_REQ_MAX; i++) { + + if (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) { + msg("[MACPHY][DATA][REQ] Request %d: Direction %d, Pdu_type %d\n", + i, + Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Direction, + Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Pdu_type); + // Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Lchan_id.Index); + // Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources, + // Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Time_alloc, + // Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Freq_alloc); + //if(Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Pdu_type==RACH) + //msg("[RACH_REQ] Rach_pdu %p, Payload %p\n",Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Dir.Req_rx.Pdu.Rach_pdu, + // Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Dir.Req_rx.Pdu.Rach_pdu->Rach_payload); + + } + } +} + + +/*___________________________________________________________________________________________________*/ +#define RCNT Macphy_req_table[Mod_id].Macphy_req_cnt + +MACPHY_DATA_REQ *new_macphy_data_req(unsigned char Mod_id) +{ + /*___________________________________________________________________________________________________*/ + unsigned char i; + + + + for (i=0; i<NB_REQ_MAX; i++) { + if (Macphy_req_table[Mod_id].Macphy_req_table_entry[(i)%NB_REQ_MAX].Active == 0) { + Macphy_req_table[Mod_id].Macphy_req_table_entry[(i)%NB_REQ_MAX].Active = 1; + RCNT = (RCNT + 1)%NB_REQ_MAX; + // msg("[MAC_PHY]NEW MAC_REQUEST_CNT=%d,frame %d, Module %d, entry %d \n",Macphy_req_table[Mod_id].Macphy_req_cnt,mac_xface->frame,Mod_id,i); + // Macphy_req_table[Mod_id].Macphy_req_table_entry[i%NB_REQ_MAX].Macphy_data_req.Phy_resources=(PHY_RESOURCES*)malloc16(sizeof(PHY_RESOURCES)); + return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i%NB_REQ_MAX].Macphy_data_req); + } + } + + msg("[OPENAIR][MAC][ERROR] frame %d: No more DATA_REQ !!!!\n",mac_xface->frame); + + print_active_requests(Mod_id); + mac_xface->macphy_exit("new_macphy_data_req: no more DATA_REQ"); + //rt_sleep(nano2count(2000)); + + return((MACPHY_DATA_REQ*)0); +} + + +#endif //PHY_CONTEXT + +#ifdef MAC_CONTEXT +#include "LAYER2/MAC/extern.h" + +// Function called by PHY to indicate available data/measurements for MAC + +/*___________________________________________________________________________________________________*/ +void macphy_data_ind(unsigned char Mod_id,unsigned char Pdu_type,void *pdu,unsigned short rnti) +{ + /*___________________________________________________________________________________________________*/ + //msg("[OPENAIR][MACPHY] Calling mac_resp In\n"); + + int i; + + // if (Req_rx->crc_status[0]!= -1) { //CRC_STATUS + + // msg("[OPENAIR][MACPHY] Calling mac_indicate In\n"); + // Req_rx->Meas.UL_meas=&UL_meas[Mod_id]; + // Req_rx->Meas.DL_meas=&DL_meas[Mod_id]; + + switch (Pdu_type) { + case ULSCH: + + // msg("[OPENAIR][MACPHY] Received RACH, Sending to MAC\n"); + nodeb_decode_ulsch(Mod_id,(ULSCH_PDU *)pdu,rnti); + + break; + + case DLSCH: +#ifdef DEBUG_UE_DECODE_SACH + msg("[MAC][UE][MAC_PHY] TTI %d Inst %d\n",mac_xface->frame,Mod_id); +#endif + + // ue_decode_dlsch(Mod_id-NB_CH_INST, + // (DLSCH_PDU *)pdu,rnti); + + break; + + default: + break; + } + + // msg("Freeing Req %p\n",Macphy_data_req_table_entry); + // } + +} + + + + + +/*PHY_RESOURCES_TABLE_ENTRY *new_phy_resources() { + + + unsigned char i; + + //msg("[OPENAIR][PHY][MAC Interface] New Phy Resource, cnt %d\n",Phy_resources_table.Phy_resources_cnt); + + for (i=0;i<NB_PHY_RESOURCES_MAX;i++){ + + if (Phy_resources_table.Phy_resources_table_entry[(i+Phy_resources_table.Phy_resources_cnt+1)%NB_PHY_RESOURCES_MAX].Active == 0) { + Phy_resources_table.Phy_resources_table_entry[(i+Phy_resources_table.Phy_resources_cnt+1)%NB_PHY_RESOURCES_MAX].Active = 1; + Phy_resources_table.Phy_resources_cnt = (Phy_resources_table.Phy_resources_cnt + 1)%NB_PHY_RESOURCES_MAX; + // msg("[OPENAIR][PHY][MAC Interface] NEW PHY_RESOURCES: Taking index %d\n\n",(i+Phy_resources_table.Phy_resources_cnt+1)%NB_PHY_RESOURCES_MAX); + + return(&Phy_resources_table.Phy_resources_table_entry[(i+Phy_resources_table.Phy_resources_cnt)%NB_PHY_RESOURCES_MAX]); + } + } + msg("[OPENAIR][MAC][ERROR] No more PHY_RESOURCES !!!!\n"); + exit(-1); +} +*/ + +#endif //MAC_CONTEXT + + +// Measurements, etc .. + +//short phy_resource_cnt = 0, macphy_data_req_cnt = 0, macphy_data_ind_cnt = 0; + + + + + + + + + + + + diff --git a/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.h b/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.h new file mode 100644 index 0000000000..889cb503dc --- /dev/null +++ b/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.h @@ -0,0 +1,232 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*________________________mac_phy_primitives.h________________________ + + Authors : Hicham Anouar, Raymond Knopp + Company : EURECOM + Emails : anouar@eurecom.fr, knopp@eurecom.fr +________________________________________________________________*/ + + +#ifndef __MAC_PHY_PRIMITIVES_H__ +# define __MAC_PHY_PRIMITIVES_H__ + +#include "../LAYER2/MAC/defs.h" + + +/**@defgroup _mac_phy_primitives_ MAC Layer Primitives for Communications with PHY + *@ingroup w3g4f_mac_layer_ + *@{ + +This subclause describes the primitives for communications between the MAC and PHY sub-layers. + +The primitives for dynamic MAC-PHY PDU exchange (Transport channel interface) are: + +- MACPHY_DATA_REQ: transfers or requests a PDU from PHY. The data is passed along with the dynamic PHY transmission +format (coding and modulation, time/freq/space resource allocation) + +- MACPHY_DATA_IND: Function call (by PHY) to deliver a new PDU and corresponding measurements to MAC. This implicitly confirms the MACPHY_DATA_REQ by +filling the fields of the request (TX or RX) with the data and measurements. + +One primitive is used for semi-static configuration (during logical channel establishment) +relaying the puncturing/repetition patterns for HARQ: + +- MACPHY_CONFIG_SACH_HARQ_REQ (still to be defined...) + +The primitive for static (re)configuration is: +- MACPHY_CONFIG_REQ : This primitive transports the initial configuration during the setup phase of equipment, both for CH and UE. +Static configuration is used during the initialization phase of the equipment. For a CH, it is done prior to any communication. For a UE, some +structures may be set after receiving configuration information from the network via the BCCH/CCCH. +*/ + + + + +/*! \brief MACPHY-DATA-REQ_RX structure is used to request transfer a new PDU from PHY corresponding to a particular transport channel*/ +typedef struct { + int crc_status[MAX_NUMBER_TB_PER_LCHAN]; /*!< This field indicates the CRC status of the PDU upon reception from PHY*/ + unsigned char num_tb; /*!< This field indicates the number of transport blocks to be received*/ + unsigned short tb_size_bytes; /*!< This field indicates the number of bytes per transpor block*/ + unsigned int Active_process_map; /*!< HARQ indicator for active processes*/ + union { + CHBCH_PDU *Chbch_pdu; /*!< This is a pointer to CHBCH data*/ + DL_SACH_PDU *DL_sach_pdu; /*!< This is a pointer to DL_SACH data*/ + UL_SACH_PDU *UL_sach_pdu; /*!< This is a pointer to UL_SACH data*/ + RACH_PDU *Rach_pdu; /*!< This is a pointer to RACH data*/ + MRBCH_PDU *Mrbch_pdu; /*!< This is a pointer to MRBCH data*/ + } Pdu; + union { + DL_MEAS *DL_meas; /*!< This is an array of pointers to the current measurements of DL quality at UE (indexed by CH_id) */ + UL_MEAS *UL_meas; /*!< This is an array of pointers to the current measurements of UL quality at Node-B (indexed by user_id) */ + } Meas; +} MACPHY_DATA_REQ_RX; + + +/*! \brief MACPHY-DATA-REQ_TX structure is used to transfer a new PDU to PHY corresponding to a particular transport channel*/ +typedef struct { + unsigned char num_tb; /*!< This field indicates the number of transport blocks to be received*/ + unsigned short tb_size_bytes; /*!< This field indicates the number of bytes per transpor block*/ + unsigned int Active_process_map; /*!< HARQ indicator for active processes*/ + unsigned int New_process_map; /*!< HARQ indicator for new processes*/ + // unsigned char round_indices_tx; + union { + CHBCH_PDU *Chbch_pdu; /*!< pointer to CHBCH data */ + DL_SACH_PDU DL_sach_pdu; /*!< pointer to DL_SACH data*/ + UL_SACH_PDU UL_sach_pdu; /*!< pointer to UL_SACH data*/ + RACH_PDU Rach_pdu; //H.A /*!< pointer to RACH data */ + MRBCH_PDU *Mrbch_pdu; /*!< pointer to MRBCH data */ + } Pdu; +} MACPHY_DATA_REQ_TX; + +/*! \brief MACPHY-DATA-REQ primitive is used to transfer a new PDU to PHY corresponding to a particular transport channel*/ +typedef struct { + unsigned char Direction; + unsigned char Pdu_type; /*!< This field indicates the type of PDU requested */ + LCHAN_ID Lchan_id; /*!< This field indicates the flow id of the PDU */ + PHY_RESOURCES *Phy_resources; /*!< This field indicates to PHY the physical resources */ + unsigned int format_flag; /*!< This field indicates to PHY something about a SACH, e.g. presense of SACCH*/ + union { + MACPHY_DATA_REQ_RX Req_rx; /*!< This field contains the request corresponding to an RX resource*/ + MACPHY_DATA_REQ_TX Req_tx; /*!< This field contains the request corresponding to a TX resource*/ + } Dir; +} MACPHY_DATA_REQ; + +/*!\fn void macphy_data_ind(unsigned char Mod_id,MACPHY_DATA_REQ_RX *Req_rx,unsigned char Pdu_type,unsigned short Index); +\brief MACPHY_DATA_IND function call. Called by PHY to upload PDU and measurements in response to a MACPHY_DATA_REQ_RX. +@param Mod_id MAC instance ID (only useful if multiple MAC instances run in the same machine) +@param Req_rx Pointer to MACPHY_DTA_REQ_RX received previously +@param Pdu_type Type of PDU (redundant!) +@param Index CH Index for CH, UEid for UE +*/ +void macphy_data_ind(unsigned char Mod_id, + MACPHY_DATA_REQ_RX *Req_rx, + unsigned char Pdu_type, + unsigned short Index); + +/*! \brief MACPHY-CONFIG-REQ primitive is used to configure a new instance of OpenAirInterface (static configuration) during initialization*/ +typedef struct { + PHY_FRAMING Phy_framing; /*!< Framing Configuration*/ + PHY_CHSCH Phy_chsch[8]; /*!< CHSCH Static Configuration*/ + PHY_CHBCH Phy_chbch; /*!< CHBCH Static Configuration*/ + PHY_SCH Phy_sch[8]; /*!< SCH Static Configuration*/ + PHY_SACH Phy_sach; /*!< SACH Statuc Configuration*/ +} MACPHY_CONFIG_REQ; + +/*! \brief MACPHY-CONFIG-SACH-HARQ-REQ primitive is used to configure a new SACH transport channel (dynamic configuration) during logical channel establishment*/ +//typedef struct { +// LCHAN_ID Lchan_id; /*!< This is the identifier of the SACH, which should simply be the logical channel id*/ +// HARQ_PARAMS Harq_params; /*!< This is the set of HARQ parameters corresponding to the QoS description of the logical channel*/ +//} MACPHY_CONFIG_SACH_HARQ_REQ; + +/** @} */ + +#define MAX_NUMBER_OF_MAC_INSTANCES 16 + +#define NULL_PDU 255 +#define CHBCH 0 +#define DL_SACH 1 +#define UL_SACH 2 +#define UL_SACCH_SACH 3 +#define RACH 4 +#define MRBCH 5 + + +#define NUMBER_OF_SUBBANDS 64 +#define LCHAN_KEY 0 +#define PDU_TYPE_KEY 1 +#define PHY_RESOURCES_KEY 2 + +typedef struct Macphy_req_entry_key { + unsigned char Key_type; + union { + LCHAN_ID *Lchan_id; //SACH, EMULATION + unsigned char Pdu_type;//CHBCH, RACH, EMULATION + PHY_RESOURCES Phy_resources;//REAL PHY + } Key; +} MACPHY_REQ_ENTRY_KEY; + +/** @ingroup _PHY_TRANSPORT_CHANNEL_PROCEDURES_ + * @{ +\var typedef struct Macphy_data_req_table_entry { + MACPHY_DATA_REQ Macphy_data_req; + unsigned char Active; +} MACPHY_DATA_REQ_TABLE_ENTRY; +\brief An entry in the MACPHY_DATA_REQ Table. +*/ + +typedef struct Macphy_data_req_table_entry { + /// The MACPHY_DATA_REQ Structure itself + MACPHY_DATA_REQ Macphy_data_req; + /// Active flag. Active=1 means that the REQ is pending. + unsigned char Active; +} MACPHY_DATA_REQ_TABLE_ENTRY; + +/*!\var typedef struct { + MACPHY_DATA_REQ_TABLE_ENTRY *Macphy_req_table_entry; + unsigned int Macphy_req_cnt; +} MACPHY_DATA_REQ_TABLE +\brief The MACPHY_DATA_REQ interface between MAC and PHY. This table stores the pending requests from MAC which are serviced by PHY. The pointer Macphy_req_table_entry points +to an array of idle reqests allocated during initialization of the MAC-layer. +*/ + +typedef struct { + /// Pointer to a MACPHY_DATA_REQ + MACPHY_DATA_REQ_TABLE_ENTRY *Macphy_req_table_entry; + /// Number of active requests + unsigned int Macphy_req_cnt; +} MACPHY_DATA_REQ_TABLE; + +/** @} */ + +/*typedef struct Tx_Phy_Pdu{ //H.A + PHY_RESOURCES *Phy_resources; + MACPHY_DATA_IND *Macphy_data_ind; +}T_PHY_PDU; + +typedef struct Rx_Phy_Pdu{ //H.A + PHY_RESOURCES *Phy_resources; + char *Phy_payload; + }RX_PHY_PDU;*/ + + +typedef struct GRANTED_LCHAN_TABLE_ENTRY { + PHY_RESOURCES *Phy_resources; + LCHAN_ID Lchan_id; +} GRANTED_LCHAN_TABLE_ENTRY; + +void clear_macphy_data_req(uint8_t); +//void clean_macphy_interface(void); +unsigned char phy_resources_compare(PHY_RESOURCES *,PHY_RESOURCES*); +MACPHY_DATA_REQ_TABLE_ENTRY* find_data_req_entry(uint8_t,MACPHY_REQ_ENTRY_KEY*); +void print_active_requests(uint8_t); +void mac_process_meas_ul(uint8_t Mod_id,UL_MEAS *UL_meas, uint16_t Index); +void mac_process_meas_dl(uint8_t Mod_id,DL_MEAS *DL_meas, uint16_t Index); + + + + +MACPHY_DATA_REQ *new_macphy_data_req(uint8_t); +//PHY_RESOURCES_TABLE_ENTRY *new_phy_resources(void); +//MACPHY_DATA_IND *new_macphy_data_ind(void); +#endif + + diff --git a/openair2/NR_UE_PHY_INTERFACE/vars.h b/openair2/NR_UE_PHY_INTERFACE/vars.h new file mode 100644 index 0000000000..566f4347b6 --- /dev/null +++ b/openair2/NR_UE_PHY_INTERFACE/vars.h @@ -0,0 +1,44 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef __PHY_INTERFACE_VARS_H__ +#define __PHY_INTERFACE_VARS_H__ + +//#include "SIMULATION/PHY_EMULATION/spec_defs.h" +#include "defs.h" + +#ifdef PHY_EMUL +#include "SIMULATION/PHY_EMULATION/DEVICE_DRIVER/defs.h" +#include "SIMULATION/simulation_defs.h" +#endif + + +unsigned int mac_debug; + +//MAC_xface *mac_xface; + +//MACPHY_PARAMS MACPHY_params; + +unsigned int mac_registered; + + +#endif + -- GitLab