From 0bef84d0a5bf4027a9538590e3d6f4119568fbe2 Mon Sep 17 00:00:00 2001 From: Javier Morgade Date: Tue, 21 Jul 2020 15:16:49 +0200 Subject: [PATCH] fembms: - FeMBMS 36.213 eNB procedures v14.2 - FeMBMS 36.213 UE procedures v14.2 - Implementation of OFDM encoding for FeMBMS/eNB v14.2 Signed-off-by: Javier Morgade --- openair1/SCHED/phy_procedures_lte_eNb.c | 138 ++++++++++++++++++++-- openair1/SCHED/ru_procedures.c | 25 +++- openair1/SCHED_UE/phy_procedures_lte_ue.c | 50 +++++++- 3 files changed, 198 insertions(+), 15 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index fc9407f8d0..6717b045ac 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -20,12 +20,12 @@ */ /*! \file phy_procedures_lte_eNB.c - * \brief Implementation of eNB procedures from 36.213 LTE specifications - * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas + * \brief Implementation of eNB procedures from 36.213 LTE specifications / FeMBMS 36.231 LTE procedures v14.2 + * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas, J. Morgade * \date 2011 * \version 0.1 * \company Eurecom - * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk + * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk, javier.morgade@ieee.org * \note * \warning */ @@ -122,12 +122,32 @@ lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subfr } #ifdef MBMS_NFAPI_SCHEDULER -void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { +void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, int fembms_flag) { int subframe = proc->subframe_tx; // This is DL-Cell spec pilots in Control region - generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1); - if(eNB->dlsch_MCH->active==1) - generate_mch (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/); + if(!fembms_flag){ + generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1); + generate_mbsfn_pilot(eNB,proc, + eNB->common_vars.txdataF, + AMP); + }else + generate_mbsfn_pilot_khz_1dot25(eNB,proc, + eNB->common_vars.txdataF, + AMP); + + if(eNB->dlsch_MCH->active==1){ + if(!fembms_flag){ + generate_mch (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/); + } + else{ + generate_mch_khz_1dot25 (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/); + } + + LOG_D(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (TBS %d) fembms %d \n", + eNB->Mod_id,proc->frame_tx,subframe, + eNB->dlsch_MCH->harq_processes[0]->TBS>>3,fembms_flag); + + } eNB->dlsch_MCH->active = 0; } #else @@ -171,6 +191,80 @@ void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { } #endif +void common_signal_procedures_fembms (PHY_VARS_eNB *eNB,int frame, int subframe) { + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + int **txdataF = eNB->common_vars.txdataF; + uint8_t *pbch_pdu=&eNB->pbch_pdu[0]; + + if((frame&3)!=0 /*&& subframe != 0*/) + return; + + LOG_I(PHY,"common_signal_procedures: frame %d, subframe %d fdd:%s dir:%s index:%d\n",frame,subframe,fp->frame_type == FDD?"FDD":"TDD", subframe_select(fp,subframe) == SF_DL?"DL":"UL?",(frame&15)/4); + // generate Cell-Specific Reference Signals for both slots + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1); + + + if(subframe_select(fp,subframe) == SF_S) + generate_pilots_slot(eNB, + txdataF, + AMP, + subframe<<1,1); + else + generate_pilots_slot(eNB, + txdataF, + AMP, + subframe<<1,0); + + // check that 2nd slot is for DL + if (subframe_select (fp, subframe) == SF_DL) + generate_pilots_slot (eNB, txdataF, AMP, (subframe << 1) + 1, 0); + + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME (VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX, 0); + + // First half of PSS/SSS (FDD, slot 0) + if (subframe == 0) { + //if (fp->frame_type == FDD) { + generate_pss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 0); + generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 5 : 4, 0); + //} + + /// First half of SSS (TDD, slot 1) + + //if (fp->frame_type == TDD) { + generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 1); + //} + + // generate PBCH (Physical Broadcast CHannel) info + + /// generate PBCH + if ((frame&15)==0) { + //AssertFatal(eNB->pbch_configured==1,"PBCH was not configured by MAC\n"); + if (eNB->pbch_configured!=1) return; + + eNB->pbch_configured=0; + } + + T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), + T_BUFFER(pbch_pdu, 3)); + generate_pbch_fembms (&eNB->pbch, txdataF, AMP, fp, pbch_pdu, (frame & 15)/4); + } //else if ((subframe == 1) && (fp->frame_type == TDD)) { + //generate_pss (txdataF, AMP, fp, 2, 2); + // } + // Second half of PSS/SSS (FDD, slot 10) + else if ((subframe == 5) && (fp->frame_type == FDD) && is_fembms_nonMBSFN_subframe(frame,subframe,fp)) { + generate_pss (txdataF, AMP, &eNB->frame_parms, (fp->Ncp == NORMAL) ? 6 : 5, 10); + generate_sss (txdataF, AMP, &eNB->frame_parms, (fp->Ncp == NORMAL) ? 5 : 4, 10); + } + // Second-half of SSS (TDD, slot 11) + // else if ((subframe == 5) && (fp->frame_type == TDD)) { + // generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 11); + // } + // Second half of PSS (TDD, slot 12) + // else if ((subframe == 6) && (fp->frame_type == TDD)) { + // generate_pss (txdataF, AMP, fp, 2, 12); + // } +} + void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int **txdataF = eNB->common_vars.txdataF; @@ -417,12 +511,30 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, } if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + if (is_fembms_pmch_subframe(frame,subframe,fp)) { +#ifdef MBMS_NFAPI_SCHEDULER + pmch_procedures(eNB,proc,1); + LOG_D(MAC,"frame %d, subframe %d -> PMCH\n",frame,subframe); + return; +#endif + }else if(is_fembms_cas_subframe(frame,subframe,fp) || is_fembms_nonMBSFN_subframe(frame,subframe,fp)){ + LOG_D(MAC,"frame %d, subframe %d -> CAS\n",frame,subframe); + common_signal_procedures_fembms(eNB,proc->frame_tx, proc->subframe_tx); + //return; + } + + if((!is_fembms_cas_subframe(frame,subframe,fp)) && (!is_fembms_nonMBSFN_subframe(frame,subframe,fp))){ if (is_pmch_subframe(frame,subframe,fp)) { +#ifdef MBMS_NFAPI_SCHEDULER + pmch_procedures(eNB,proc,0); +#else pmch_procedures(eNB,proc); +#endif } else { // this is not a pmch subframe, so generate PSS/SSS/PBCH common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx); } + } } // clear existing ulsch dci allocations before applying info from MAC (this is table @@ -508,6 +620,18 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, if (do_meas==1) start_meas(&eNB->dlsch_ue_specific); + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + if (is_fembms_pmch_subframe(frame,subframe,fp)) { +#ifdef MBMS_NFAPI_SCHEDULER + pmch_procedures(eNB,proc,1); + return; +#endif + }else if(is_fembms_cas_subframe(frame,subframe,fp)){ + common_signal_procedures_fembms(eNB,proc->frame_tx, proc->subframe_tx); + } + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1); // Now scan UE specific DLSCH diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c index cb03821388..e472d64db4 100644 --- a/openair1/SCHED/ru_procedures.c +++ b/openair1/SCHED/ru_procedures.c @@ -41,6 +41,17 @@ * \warning */ +/*! \function feptx0 + * \brief Implementation of ofdm encoding for FeMBMS profile in one eNB + * \author J. Morgade + * \date 2020 + * \version 0.1 + * \email: javier.morgade@ieee.org + * \note + * \warning + */ + + #include "PHY/defs_eNB.h" #include "PHY/phy_extern.h" @@ -76,7 +87,7 @@ void feptx0(RU_t *ru, int slot_sizeF = (fp->ofdm_symbol_size) * ((fp->Ncp==1) ? 6 : 7); int subframe = ru->proc.tti_tx; - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+slot , 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(slot&1) , 1 ); slot_offset = slot*(fp->samples_per_tti>>1); //slot_offset = subframe*fp->samples_per_tti + (slot*(fp->samples_per_tti>>1)); @@ -91,7 +102,17 @@ void feptx0(RU_t *ru, fp->nb_prefix_samples, CYCLIC_PREFIX); } else { - if(is_pmch_subframe(ru->proc.frame_tx,subframe,fp)){ + if(is_fembms_pmch_subframe(ru->proc.frame_tx,subframe,fp)){ + if((slot&1)==0){//just use one slot chance + PHY_ofdm_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF], + (int*)&ru->common.txdata[aa][slot_offset], + fp->ofdm_symbol_size_khz_1dot25, + 1, + fp->ofdm_symbol_size_khz_1dot25>>2, + CYCLIC_PREFIX); + LOG_D(HW,"Generating PMCH FeMBMS TX subframe %d %d\n",subframe,fp->ofdm_symbol_size_khz_1dot25); + } + } else if(is_pmch_subframe(ru->proc.frame_tx,subframe,fp)){ if ((slot&1) == 0) {//just use one slot chance normal_prefix_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF], (int*)&ru->common.txdata[aa][slot_offset], diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index e0ea4ef2b2..9f0b965e0c 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -2383,10 +2383,12 @@ void ue_pbch_procedures(uint8_t eNB_id, if (pbch_phase>=4) pbch_phase=0; +if((ue->frame_parms.FeMBMS_active == 0)|| is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || first_run) { + for (pbch_trials=0; pbch_trials<4; pbch_trials++) { //for (pbch_phase=0;pbch_phase<4;pbch_phase++) { //LOG_I(PHY,"[UE %d] Frame %d, Trying PBCH %d (NidCell %d, eNB_id %d)\n",ue->Mod_id,frame_rx,pbch_phase,ue->frame_parms.Nid_cell,eNB_id); - if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms)) { + if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || ue->frame_parms.FeMBMS_active) { pbch_tx_ant = rx_pbch_fembms(&ue->common_vars, ue->pbch_vars[eNB_id], &ue->frame_parms, @@ -2431,9 +2433,10 @@ void ue_pbch_procedures(uint8_t eNB_id, ue->pbch_vars[eNB_id]->pdu_errors_conseq = 0; - if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms)) { + if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || ue->frame_parms.FeMBMS_active) { frame_tx = (int)((ue->pbch_vars[eNB_id]->decoded_output[2]&31)<<1); frame_tx += ue->pbch_vars[eNB_id]->decoded_output[1]>>7; + frame_tx = frame_tx<<4; frame_tx +=4*pbch_phase; } else { frame_tx = (((int)(ue->pbch_vars[eNB_id]->decoded_output[2]&0x03))<<8); @@ -2501,6 +2504,17 @@ void ue_pbch_procedures(uint8_t eNB_id, ue->frame_parms.phich_config_common.phich_duration, ue->frame_parms.phich_config_common.phich_resource); } + LOG_I(PHY,"[UE %d] frame %d, subframe %d, Received PBCH (MIB): nb_antenna_ports_eNB %d, tx_ant %d, frame_tx %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6!\n", + ue->Mod_id, + frame_rx, + subframe_rx, + ue->frame_parms.nb_antenna_ports_eNB, + pbch_tx_ant, + frame_tx, + ue->frame_parms.N_RB_DL, + ue->frame_parms.phich_config_common.phich_duration, + ue->frame_parms.phich_config_common.phich_resource); + } else { if (LOG_DUMPFLAG(DEBUG_UE_PHYPROC)) { LOG_E(PHY,"[UE %d] frame %d, subframe %d, Error decoding PBCH!\n", @@ -2533,6 +2547,8 @@ void ue_pbch_procedures(uint8_t eNB_id, ue->pbch_vars[eNB_id]->pdu_errors_conseq); } +} //if((ue->frame_parms.FeMBMS_active == 0)|| is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || first_run) + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT); } @@ -2691,6 +2707,7 @@ int ue_pdcch_procedures(uint8_t eNB_id, if (LOG_DEBUGFLAG(DEBUG_UE_PHYPROC)) { LOG_D(PHY,"[UE %d] subframe %d: Found rnti %x, format 1%s, dci_cnt %d\n",ue->Mod_id,subframe_rx,dci_alloc_rx[i].rnti,dci_alloc_rx[i].format==format1A?"A":"C",i); } + LOG_W(PHY,"[UE %d] subframe %d: Found rnti %x, format 1%s, dci_cnt %d\n",ue->Mod_id,subframe_rx,dci_alloc_rx[i].rnti,dci_alloc_rx[i].format==format1A?"A":"C",i); if (generate_ue_dlsch_params_from_dci(frame_rx, subframe_rx, @@ -2709,7 +2726,7 @@ int ue_pdcch_procedures(uint8_t eNB_id, ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id], 0)==0) { ue->dlsch_SI_received[eNB_id]++; - LOG_D(PHY,"[UE %d] Frame %d, subframe %d : Generate UE DLSCH SI_RNTI format 1%s\n",ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].format==format1A?"A":"C"); + LOG_W(PHY,"[UE %d] Frame %d, subframe %d : Generate UE DLSCH SI_RNTI format 1%s\n",ue->Mod_id,frame_rx,subframe_rx,dci_alloc_rx[i].format==format1A?"A":"C"); //dump_dci(&ue->frame_parms, &dci_alloc_rx[i]); } } else if ((dci_alloc_rx[i].rnti == P_RNTI) && @@ -2877,10 +2894,19 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, int l; int ret=0; - if (is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms)) { + if (is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms) || fembms_flag) { // LOG_D(PHY,"ue calling pmch subframe ..\n "); LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Querying for PMCH demodulation\n", ue->Mod_id,frame_rx,subframe_rx); + if(fembms_flag) + pmch_mcs = ue_query_mch_fembms(ue->Mod_id, + CC_id, + frame_rx, + subframe_rx, + eNB_id, + &sync_area, + &mcch_active); + else pmch_mcs = ue_query_mch(ue->Mod_id, CC_id, frame_rx, @@ -2960,6 +2986,7 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, LOG_D(PHY,"start turbo decode for MCH %d.%d --> Nl %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->harq_processes[0]->Nl); LOG_D(PHY,"start turbo decode for MCH %d.%d --> G %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->harq_processes[0]->G); LOG_D(PHY,"start turbo decode for MCH %d.%d --> Kmimo %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->Kmimo); + ret = dlsch_decoding(ue, ue->pdsch_vars_MCH[ue->current_thread_id[subframe_rx]][0]->llr[0], &ue->frame_parms, @@ -3007,14 +3034,14 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, // if (subframe_rx==9) // mac_xface->macphy_exit("Why are we exiting here?"); } else { // decoding successful - LOG_D(PHY,"[UE %d] Frame %d, subframe %d: PMCH OK (%d,%d), passing to L2 (TBS %d, iter %d,G %d)\n", + LOG_I(PHY,"[UE %d] Frame %d, subframe %d: PMCH OK (%d,%d), passing to L2 (TBS %d, iter %d,G %d) ret %d\n", ue->Mod_id, frame_rx,subframe_rx, ue->dlsch_mcch_errors[sync_area][0], ue->dlsch_mtch_errors[sync_area][0], ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, ue->dlsch_MCH[0]->max_turbo_iterations, - ue->dlsch_MCH[0]->harq_processes[0]->G); + ue->dlsch_MCH[0]->harq_processes[0]->G,ret); ue_send_mch_sdu(ue->Mod_id, CC_id, frame_rx, @@ -3022,6 +3049,8 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, eNB_id,// not relevant in eMBMS context sync_area); + //dump_mch(ue,0,ue->dlsch_MCH[0]->harq_processes[0]->G,subframe_rx); + //exit_fun("nothing to add"); if (mcch_active == 1) ue->dlsch_mcch_received[sync_area][0]++; @@ -4429,6 +4458,15 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue, ue_pmch_procedures(ue,proc,eNB_id,abstraction_flag,1); return 0; } else { // this gets closed at end + if (is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || is_fembms_nonMBSFN_subframe(frame_rx,subframe_rx,&ue->frame_parms) ) { + l=0; + slot_fep(ue, + l, + subframe_rx<<1, + 0, + 0, + 0); + } pmch_flag = is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms) ? 1 : 0; if (do_pdcch_flag) {