From ad98f5aa9e9ce9c254fa1e797eb4c86f6916d845 Mon Sep 17 00:00:00 2001 From: Raymond Knopp <raymond.knopp@eurecom.fr> Date: Mon, 7 Aug 2017 23:25:17 -0700 Subject: [PATCH] L1/L2 scheduling extensions for BL/CE operation, BR random-access procedure, BR PRACH detection. Still untested, but compilation succeeds. Missing elements in L2 - PUSCH programming for Msg3, Msg4 retransmission programming for BL/CE. DLSCH/ULSCH programming for UE-specific DLSCH/ULSCH for BL/CE --- openair1/PHY/INIT/lte_init.c | 527 +++++----- openair1/PHY/LTE_TRANSPORT/if4_tools.c | 70 +- openair1/PHY/LTE_TRANSPORT/if4_tools.h | 6 +- openair1/PHY/LTE_TRANSPORT/prach.c | 385 +++++-- openair1/PHY/LTE_TRANSPORT/proto.h | 18 +- openair1/PHY/defs.h | 94 +- openair1/PHY/impl_defs_lte.h | 61 +- openair1/SCHED/defs.h | 9 +- openair1/SCHED/phy_procedures_lte_eNb.c | 185 ++-- openair2/LAYER2/MAC/config.c | 54 +- openair2/LAYER2/MAC/defs.h | 28 +- openair2/LAYER2/MAC/eNB_scheduler_RA.c | 967 ++++++++++++------ .../LAYER2/MAC/eNB_scheduler_primitives.c | 63 ++ openair2/LAYER2/MAC/main.c | 2 + openair2/LAYER2/MAC/proto.h | 9 +- openair2/LAYER2/MAC/rar_tools.c | 90 ++ openair2/PHY_INTERFACE/IF_Module.c | 29 +- openair2/PHY_INTERFACE/IF_Module.h | 5 + targets/RT/USER/lte-enb.c | 153 ++- targets/RT/USER/lte-ru.c | 159 ++- 20 files changed, 2099 insertions(+), 815 deletions(-) diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index 1def93e8c2..81a8478e33 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -145,6 +145,61 @@ void phy_config_request(PHY_Config_t *phy_config) { LOG_I(PHY,"prach_config_common.prach_ConfigInfo.prach_FreqOffset = %d\n",cfg->prach_config.frequency_offset.value); init_prach_tables(839); +#ifdef Rel14 + fp->prach_emtc_config_common.prach_Config_enabled=1; + + fp->prach_emtc_config_common.rootSequenceIndex = cfg->emtc_config.prach_catm_root_sequence_index.value; + + fp->prach_emtc_config_common.prach_ConfigInfo.highSpeedFlag = cfg->emtc_config.prach_catm_high_speed_flag.value; + fp->prach_emtc_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig = cfg->emtc_config.prach_catm_zero_correlation_zone_configuration.value; + + // CE Level 3 parameters + fp->prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[3] = cfg->emtc_config.prach_ce_level_3_enable.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_starting_subframe_periodicity[3] = cfg->emtc_config.prach_ce_level_3_starting_subframe_periodicity.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[3] = cfg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt.value; + AssertFatal(fp->prach_emtc_config_common.prach_ConfigInfo.prach_starting_subframe_periodicity[3]>=fp->prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[3], + "prach_starting_subframe_periodicity[3] < prach_numPetitionPerPreambleAttempt[3]\n"); + + fp->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[3] = cfg->emtc_config.prach_ce_level_3_configuration_index.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[3] = cfg->emtc_config.prach_ce_level_3_frequency_offset.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_hopping_enable[3] = cfg->emtc_config.prach_ce_level_3_hopping_enable.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_hopping_offset[3] = cfg->emtc_config.prach_ce_level_3_hopping_offset.value; + + // CE Level 2 parameters + fp->prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[2] = cfg->emtc_config.prach_ce_level_2_enable.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_starting_subframe_periodicity[2] = cfg->emtc_config.prach_ce_level_2_starting_subframe_periodicity.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[2] = cfg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt.value; + AssertFatal(fp->prach_emtc_config_common.prach_ConfigInfo.prach_starting_subframe_periodicity[2]>=fp->prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[2], + "prach_starting_subframe_periodicity[2] < prach_numPetitionPerPreambleAttempt[2]\n"); + fp->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[2] = cfg->emtc_config.prach_ce_level_2_configuration_index.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[2] = cfg->emtc_config.prach_ce_level_2_frequency_offset.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_hopping_enable[2] = cfg->emtc_config.prach_ce_level_2_hopping_enable.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_hopping_offset[2] = cfg->emtc_config.prach_ce_level_2_hopping_offset.value; + + // CE Level 1 parameters + fp->prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[1] = cfg->emtc_config.prach_ce_level_1_enable.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_starting_subframe_periodicity[1] = cfg->emtc_config.prach_ce_level_1_starting_subframe_periodicity.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[1] = cfg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt.value; + AssertFatal(fp->prach_emtc_config_common.prach_ConfigInfo.prach_starting_subframe_periodicity[1]>=fp->prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[1], + "prach_starting_subframe_periodicity[1] < prach_numPetitionPerPreambleAttempt[1]\n"); + fp->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[1] = cfg->emtc_config.prach_ce_level_1_configuration_index.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[1] = cfg->emtc_config.prach_ce_level_1_frequency_offset.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_hopping_enable[1] = cfg->emtc_config.prach_ce_level_1_hopping_enable.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_hopping_offset[1] = cfg->emtc_config.prach_ce_level_1_hopping_offset.value; + + // CE Level 0 parameters + fp->prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[0] = cfg->emtc_config.prach_ce_level_0_enable.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_starting_subframe_periodicity[0] = cfg->emtc_config.prach_ce_level_0_starting_subframe_periodicity.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[0] = cfg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt.value; + AssertFatal(fp->prach_emtc_config_common.prach_ConfigInfo.prach_starting_subframe_periodicity[0]>=fp->prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[0], + "prach_starting_subframe_periodicity[0] < prach_numPetitionPerPreambleAttempt[0]\n"); + fp->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[0] = cfg->emtc_config.prach_ce_level_0_configuration_index.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[0] = cfg->emtc_config.prach_ce_level_0_frequency_offset.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_hopping_enable[0] = cfg->emtc_config.prach_ce_level_0_hopping_enable.value; + fp->prach_emtc_config_common.prach_ConfigInfo.prach_hopping_offset[0] = cfg->emtc_config.prach_ce_level_0_hopping_offset.value; + +#endif + compute_prach_seq(&fp->prach_config_common,fp->frame_type, RC.eNB[Mod_id][CC_id]->X_u); @@ -1278,31 +1333,30 @@ int init_lte_ue_signal(PHY_VARS_UE *ue, 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) ); - } + // 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++) { @@ -1333,140 +1387,140 @@ int init_lte_ue_signal(PHY_VARS_UE *ue, 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_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 ); } - 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 ); - } + + + //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) ); + } } - - // 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 ); - } + } + 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 ); } @@ -1476,16 +1530,12 @@ int init_lte_ue_signal(PHY_VARS_UE *ue, 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) ); - } + + 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) ); ue->sinr_CQI_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) ); @@ -1639,12 +1689,14 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, { // 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; - + 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; +#ifdef Rel14 + LTE_eNB_PRACH* const prach_vars_br = &eNB->prach_vars_br; +#endif int i, eNB_id, UE_id; @@ -1680,55 +1732,61 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, - if (abstraction_flag==0) { - common_vars->rxdata = (int32_t **)NULL; - common_vars->txdataF = (int32_t **)malloc16(NB_ANTENNA_PORTS_ENB*sizeof(int32_t*)); - common_vars->rxdataF = (int32_t **)malloc16(64*sizeof(int32_t*)); - - for (i=0; i<NB_ANTENNA_PORTS_ENB; i++) { - if (i<fp->nb_antenna_ports_eNB || i==5) { - common_vars->txdataF[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) ); - - LOG_D(PHY,"[INIT] common_vars->txdataF[%d] = %p (%lu bytes)\n", - i,common_vars->txdataF[i], - fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t)); - } + common_vars->rxdata = (int32_t **)NULL; + common_vars->txdataF = (int32_t **)malloc16(NB_ANTENNA_PORTS_ENB*sizeof(int32_t*)); + common_vars->rxdataF = (int32_t **)malloc16(64*sizeof(int32_t*)); + + for (i=0; i<NB_ANTENNA_PORTS_ENB; i++) { + if (i<fp->nb_antenna_ports_eNB || i==5) { + common_vars->txdataF[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) ); + + LOG_D(PHY,"[INIT] common_vars->txdataF[%d] = %p (%lu bytes)\n", + i,common_vars->txdataF[i], + fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t)); + } + } + + + // Channel estimates for SRS + for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { + + srs_vars[UE_id].srs_ch_estimates = (int32_t**)malloc16( 64*sizeof(int32_t*) ); + srs_vars[UE_id].srs_ch_estimates_time = (int32_t**)malloc16( 64*sizeof(int32_t*) ); + + for (i=0; i<64; i++) { + srs_vars[UE_id].srs_ch_estimates[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size ); + srs_vars[UE_id].srs_ch_estimates_time[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); } - + } //UE_id - // Channel estimates for SRS - for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { - - srs_vars[UE_id].srs_ch_estimates = (int32_t**)malloc16( 64*sizeof(int32_t*) ); - srs_vars[UE_id].srs_ch_estimates_time = (int32_t**)malloc16( 64*sizeof(int32_t*) ); - - for (i=0; i<64; i++) { - srs_vars[UE_id].srs_ch_estimates[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size ); - srs_vars[UE_id].srs_ch_estimates_time[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); - } - } //UE_id - } // abstraction_flag = 0 - else { //UPLINK abstraction = 1 - eNB->sinr_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) ); + 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)); } + // PRACH + prach_vars->prachF = (int16_t*)malloc16_clear( 1024*2*sizeof(int16_t) ); + + // assume maximum of 64 RX antennas for PRACH receiver + prach_vars->prach_ifft = (int16_t***)malloc16_clear(4*sizeof(int32_t**)); + prach_vars->prach_ifft[0] = (int16_t**)malloc16_clear(2*sizeof(int32_t*)); + prach_vars->prach_ifft[0][0] = (int16_t*)malloc16_clear(1024*2*sizeof(int32_t)); - if (abstraction_flag==0) { - 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)); - } + // PRACH BR +#ifdef Rel14 + prach_vars_br->prachF = (int16_t*)malloc16_clear( 1024*2*sizeof(int32_t) ); + + // assume maximum of 64 RX antennas for PRACH receiver + prach_vars_br->prach_ifft = (int32_t***)malloc16_clear(4*sizeof(int32_t**)); + for (int ce_level=0;ce_level<4;ce_level++) { + prach_vars_br->prach_ifft[ce_level] = (int32_t**)malloc16_clear(64*sizeof(int32_t*)); + for (i=0; i<64; i++) prach_vars_br->prach_ifft[ce_level][i] = (int32_t*)malloc16_clear(1024*2*sizeof(int32_t)); } - - - - - - prach_vars->prachF = (int16_t*)malloc16_clear( 1024*2*sizeof(int16_t) ); +#endif /* 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]), @@ -1738,40 +1796,35 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB, LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,prach_vars->rxsigF[i]); }*/ - - - 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) { - pusch_vars[UE_id]->rxdataF_ext = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->rxdataF_ext2 = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->drs_ch_estimates = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->drs_ch_estimates_time = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->rxdataF_comp = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_mag = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_magb = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - - AssertFatal(fp->ofdm_symbol_size > 127, "fp->ofdm_symbol_size %d<128\n",fp->ofdm_symbol_size); - AssertFatal(fp->symbols_per_tti > 11, "fp->symbols_per_tti %d < 12\n",fp->symbols_per_tti); - AssertFatal(fp->N_RB_UL > 5, "fp->N_RB_UL %d < 6\n",fp->N_RB_UL); - for (i=0; i<2; i++) { - // RK 2 times because of output format of FFT! - // FIXME We should get rid of this - pusch_vars[UE_id]->rxdataF_ext[i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->rxdataF_ext2[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->drs_ch_estimates[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[i] = (int32_t*)malloc16_clear( 2*2*sizeof(int32_t)*fp->ofdm_symbol_size ); - pusch_vars[UE_id]->rxdataF_comp[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); - pusch_vars[UE_id]->ul_ch_mag[i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); - pusch_vars[UE_id]->ul_ch_magb[i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + pusch_vars[UE_id]->rxdataF_ext = (int32_t**)malloc16( 2*sizeof(int32_t*) ); + pusch_vars[UE_id]->rxdataF_ext2 = (int32_t**)malloc16( 2*sizeof(int32_t*) ); + pusch_vars[UE_id]->drs_ch_estimates = (int32_t**)malloc16( 2*sizeof(int32_t*) ); + pusch_vars[UE_id]->drs_ch_estimates_time = (int32_t**)malloc16( 2*sizeof(int32_t*) ); + pusch_vars[UE_id]->rxdataF_comp = (int32_t**)malloc16( 2*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_mag = (int32_t**)malloc16( 2*sizeof(int32_t*) ); + pusch_vars[UE_id]->ul_ch_magb = (int32_t**)malloc16( 2*sizeof(int32_t*) ); + + AssertFatal(fp->ofdm_symbol_size > 127, "fp->ofdm_symbol_size %d<128\n",fp->ofdm_symbol_size); + AssertFatal(fp->symbols_per_tti > 11, "fp->symbols_per_tti %d < 12\n",fp->symbols_per_tti); + AssertFatal(fp->N_RB_UL > 5, "fp->N_RB_UL %d < 6\n",fp->N_RB_UL); + for (i=0; i<2; i++) { + // RK 2 times because of output format of FFT! + // FIXME We should get rid of this + pusch_vars[UE_id]->rxdataF_ext[i] = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->rxdataF_ext2[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->drs_ch_estimates[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[i] = (int32_t*)malloc16_clear( 2*2*sizeof(int32_t)*fp->ofdm_symbol_size ); + pusch_vars[UE_id]->rxdataF_comp[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti ); + pusch_vars[UE_id]->ul_ch_mag[i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); + pusch_vars[UE_id]->ul_ch_magb[i] = (int32_t*)malloc16_clear( fp->symbols_per_tti*sizeof(int32_t)*fp->N_RB_UL*12 ); } - - pusch_vars[UE_id]->llr = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); - } // abstraction_flag + + pusch_vars[UE_id]->llr = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); } //UE_id diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c index d832d7498c..1c77083deb 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c @@ -43,12 +43,15 @@ const uint8_t lin2alaw_if4p5[65536] = {213, 213, 213, 213, 213, 213, 213, 213, 2 void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { - LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; - int32_t **txdataF = ru->common.txdataF_BF; - int32_t **rxdataF = ru->common.rxdataF; - int16_t **prach_rxsigF = ru->prach_rxsigF; - void *tx_buffer = ru->ifbuffer.tx[subframe&1]; - void *tx_buffer_prach = ru->ifbuffer.tx_prach; + LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + int32_t **txdataF = ru->common.txdataF_BF; + int32_t **rxdataF = ru->common.rxdataF; + int16_t **prach_rxsigF = ru->prach_rxsigF; +#ifdef Rel14 + int16_t ***prach_rxsigF_br = ru->prach_rxsigF_br; +#endif + void *tx_buffer = ru->ifbuffer.tx[subframe&1]; + void *tx_buffer_prach = ru->ifbuffer.tx_prach; uint16_t symbol_id=0, element_id=0; @@ -175,7 +178,8 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { perror("ETHERNET write for IF4p5_PULFFT\n"); } } - } else if (packet_type == IF4p5_PRACH) { + } else if (packet_type >= IF4p5_PRACH && + packet_type <= IF4p5_PRACH+4) { // FIX: hard coded prach samples length LOG_D(PHY,"IF4p5_PRACH: frame %d, subframe %d\n",frame,subframe); db_fulllength = PRACH_NUM_SAMPLES; @@ -189,13 +193,24 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { } gen_IF4p5_prach_header(packet_header, frame, subframe); + + int16_t *rxF; + +#ifdef Rel14 + if (packet_type > IF4p5_PRACH) + rxF = &prach_rxsigF_br[packet_type - IF4p5_PRACH - 1][0][0]; + else +#else + rxF = &prach_rxsigF[0][0]; +#endif + if (eth->flags == ETH_RAW_IF4p5_MODE) { - memcpy((int16_t*)(tx_buffer_prach + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t), - (&prach_rxsigF[0][0]), - PRACH_BLOCK_SIZE_BYTES); + memcpy((void *)(tx_buffer_prach + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t), + (void*)rxF, + PRACH_BLOCK_SIZE_BYTES); } else { - memcpy((int16_t*)(tx_buffer_prach + sizeof_IF4p5_header_t), - (&prach_rxsigF[0][0]), + memcpy((void *)(tx_buffer_prach + sizeof_IF4p5_header_t), + (void *)rxF, PRACH_BLOCK_SIZE_BYTES); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 1 ); @@ -204,7 +219,7 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { &tx_buffer_prach, db_fulllength, 1, - IF4p5_PRACH)) < 0) { + packet_type)) < 0) { perror("ETHERNET write for IF4p5_PRACH\n"); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF, 0 ); @@ -217,11 +232,14 @@ void send_IF4p5(RU_t *ru, int frame, int subframe, uint16_t packet_type) { } void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint32_t *symbol_number) { - LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; - int32_t **txdataF = ru->common.txdataF_BF; - int32_t **rxdataF = ru->common.rxdataF; - int16_t **prach_rxsigF = ru->prach_rxsigF; - void *rx_buffer = ru->ifbuffer.rx; + LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + int32_t **txdataF = ru->common.txdataF_BF; + int32_t **rxdataF = ru->common.rxdataF; + int16_t **prach_rxsigF = ru->prach_rxsigF; +#ifdef Rel14 + int16_t ***prach_rxsigF_br = ru->prach_rxsigF_br; +#endif + void *rx_buffer = ru->ifbuffer.rx; uint16_t element_id; uint16_t db_fulllength, db_halflength; @@ -308,18 +326,28 @@ void recv_IF4p5(RU_t *ru, int *frame, int *subframe, uint16_t *packet_type, uint //if (element_id==0) LOG_I(PHY,"recv_if4p5: symbol %d rxdata0 = (%u,%u)\n",*symbol_number,*i,*(i+1)); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 ); - } else if (*packet_type == IF4p5_PRACH) { + } else if (*packet_type >= IF4p5_PRACH && + *packet_type <= IF4p5_PRACH + 4) { + int16_t *rxF; + +#ifdef Rel14 + if (*packet_type > IF4p5_PRACH) + rxF = &prach_rxsigF_br[*packet_type - IF4p5_PRACH - 1][0][0]; + else +#else + rxF = &prach_rxsigF[0][0]; +#endif // FIX: hard coded prach samples length db_fulllength = PRACH_NUM_SAMPLES; if (eth->flags == ETH_RAW_IF4p5_MODE) { - memcpy((&prach_rxsigF[0][0]), + memcpy(rxF, (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4p5_header_t), PRACH_BLOCK_SIZE_BYTES); } else { - memcpy((&prach_rxsigF[0][0]), + memcpy(rxF, (int16_t*) (rx_buffer+sizeof_IF4p5_header_t), PRACH_BLOCK_SIZE_BYTES); } diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h index 7a084a4b51..830c580eb0 100644 --- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h @@ -39,7 +39,11 @@ #define IF4p5_PULFFT 0x0019 #define IF4p5_PDLFFT 0x0020 #define IF4p5_PRACH 0x0021 -#define IF4p5_PULTICK 0x0022 +#define IF4p5_PRACH_BR_CE0 0x0021 +#define IF4p5_PRACH_BR_CE1 0x0022 +#define IF4p5_PRACH_BR_CE2 0x0023 +#define IF4p5_PRACH_BR_CE3 0x0024 +#define IF4p5_PULTICK 0x0025 struct IF4p5_header { /// Type diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index dff9c62d24..e616741e13 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -428,12 +428,14 @@ uint8_t get_prach_fmt(uint8_t prach_ConfigIndex,lte_frame_type_t frame_type) } } -uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, uint8_t tdd_mapindex, uint16_t Nf) +uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, + uint8_t prach_ConfigIndex, + uint8_t n_ra_prboffset, + uint8_t tdd_mapindex, uint16_t Nf) { lte_frame_type_t frame_type = frame_parms->frame_type; uint8_t tdd_config = frame_parms->tdd_config; - uint8_t prach_ConfigIndex = frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; - uint8_t n_ra_prboffset = frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset; + uint8_t n_ra_prb; uint8_t f_ra,t1_ra; uint8_t prach_fmt = get_prach_fmt(prach_ConfigIndex,frame_type); @@ -474,92 +476,90 @@ uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, uint8_t tdd_mapind return(n_ra_prb); } -int is_prach_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame, uint8_t subframe) +int is_prach_subframe0(LTE_DL_FRAME_PARMS *frame_parms,uint8_t prach_ConfigIndex,uint32_t frame, uint8_t subframe) { - - uint8_t prach_ConfigIndex = frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; + // uint8_t prach_ConfigIndex = frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; uint8_t tdd_config = frame_parms->tdd_config; uint8_t t0_ra; uint8_t t1_ra; uint8_t t2_ra; + int prach_mask = 0; if (frame_parms->frame_type == FDD) { //FDD //implement Table 5.7.1-2 from 36.211 (Rel-10, p.41) if ((((frame&1) == 1) && (subframe < 9)) || (((frame&1) == 0) && (subframe == 9))) // This is an odd frame, ignore even-only PRACH frames + + /* if (((prach_ConfigIndex&0xf)<3) || // 0,1,2,16,17,18,32,33,34,48,49,50 ((prach_ConfigIndex&0x1f)==18) || // 18,50 ((prach_ConfigIndex&0xf)==15)) // 15,47 return(0); + */ switch (prach_ConfigIndex&0x1f) { case 0: case 3: - return(subframe==1); + if (subframe==1) prach_mask = 1; break; case 1: case 4: - return(subframe==4); + if (subframe==4) prach_mask = 1; break; case 2: case 5: - return(subframe==7); + if (subframe==7) prach_mask = 1; break; case 6: - return((subframe==1) || (subframe==6)); + if ((subframe==1) || (subframe==6)) prach_mask=1; break; case 7: - return((subframe==2) || (subframe==7)); + if ((subframe==2) || (subframe==7)) prach_mask=1; break; case 8: - return((subframe==3) || (subframe==8)); + if ((subframe==3) || (subframe==8)) prach_mask=1; break; case 9: - return((subframe==1) || (subframe==4) || (subframe==7)); + if ((subframe==1) || (subframe==4) || (subframe==7)) prach_mask=1; break; case 10: - return((subframe==2) || (subframe==5) || (subframe==8)); + if ((subframe==2) || (subframe==5) || (subframe==8)) prach_mask=1; break; case 11: - return((subframe==3) || (subframe==6) || (subframe==9)); + if ((subframe==3) || (subframe==6) || (subframe==9)) prach_mask=1; break; case 12: - return((subframe&1)==0); + if ((subframe&1)==0) prach_mask=1; break; case 13: - return((subframe&1)==1); + if ((subframe&1)==1) prach_mask=1; break; case 14: - return(1==1); + prach_mask=1; break; case 15: - return(subframe==9); + if (subframe==9) prach_mask=1; break; } } else { // TDD - if (prach_ConfigIndex>=64) { - LOG_E(PHY,"[PHY] Illegal prach_ConfigIndex %d for ",prach_ConfigIndex); - return(0); - } - - if (tdd_preamble_map[prach_ConfigIndex][tdd_config].num_prach==0) { - LOG_E(PHY,"[PHY] Illegal prach_ConfigIndex %d for ",prach_ConfigIndex); - return(0); - } + AssertFatal(prach_ConfigIndex<64, + "Illegal prach_ConfigIndex %d for ",prach_ConfigIndex); + AssertFatal(tdd_preamble_map[prach_ConfigIndex][tdd_config].num_prach>0, + "Illegal prach_ConfigIndex %d for ",prach_ConfigIndex); t0_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t0_ra; t1_ra = tdd_preamble_map[prach_ConfigIndex][tdd_config].map[0].t1_ra; @@ -576,16 +576,29 @@ int is_prach_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame, uint8_t su (t0_ra == 0)) && // PRACH is in all frames (((subframe<5)&&(t1_ra==0)) || // PRACH is in 1st half-frame (((subframe>4)&&(t1_ra==1))))) { // PRACH is in 2nd half-frame - if (prach_ConfigIndex<48) // PRACH only in normal UL subframe - return((((subframe%5)-2)==t2_ra)); - else // PRACH can be in UpPTS - return((((subframe%5)-1)==t2_ra)); - } else - return(1==2); + if ((prach_ConfigIndex<48) && // PRACH only in normal UL subframe + (((subframe%5)-2)==t2_ra)) prach_mask=1; + else if ((((subframe%5)-1)==t2_ra)) prach_mask=1; // PRACH can be in UpPTS + } } - // shouldn't get here! - return(2==1); + return(prach_mask); +} + +int is_prach_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame, uint8_t subframe) { + + uint8_t prach_ConfigIndex = frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; + int prach_mask = is_prach_subframe0(frame_parms,prach_ConfigIndex,frame,subframe); + +#ifdef Rel14 + int i; + + for (i=0;i<4;i++) { + if (frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i] == 1) + prach_mask|=(is_prach_subframe0(frame_parms,frame_parms->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i],frame,subframe)<<(i+1)); + } +#endif + return(prach_mask); } int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint16_t Nf ) @@ -665,7 +678,10 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 NCS = NCS_restricted[Ncs_config]; } - n_ra_prb = get_prach_prb_offset(&(ue->frame_parms), tdd_mapindex, Nf); + n_ra_prb = get_prach_prb_offset(&(ue->frame_parms), + ue->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex, + ue->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset, + tdd_mapindex, Nf); prach_root_sequence_map = (prach_fmt<4) ? prach_root_sequence_map0_3 : prach_root_sequence_map4; /* @@ -1077,12 +1093,18 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 } //__m128i mmtmpX0,mmtmpX1,mmtmpX2,mmtmpX3; -void rx_prach(PHY_VARS_eNB *eNB, - RU_t *ru, - uint16_t *preamble_energy_list, - uint16_t *preamble_delay_list, - uint16_t Nf, - uint8_t tdd_mapindex) +void rx_prach0(PHY_VARS_eNB *eNB, + RU_t *ru, + int16_t *max_preamble, + int16_t *max_preamble_energy, + int16_t *max_preamble_delay, + uint16_t Nf, + uint8_t tdd_mapindex +#ifdef Rel14 + ,uint8_t br_flag, + uint8_t ce_level +#endif + ) { int i; @@ -1093,46 +1115,14 @@ void rx_prach(PHY_VARS_eNB *eNB, uint8_t prach_ConfigIndex; uint8_t Ncs_config; uint8_t restricted_set; + uint8_t n_ra_prb; int subframe; int16_t *prachF=NULL; int16_t **rxsigF=NULL; - int16_t **prach_ifft=NULL; int nb_rx; - if (ru) { - fp = &ru->frame_parms; - nb_rx = ru->nb_rx; - } - else if (eNB) { - fp = &eNB->frame_parms; - nb_rx = fp->nb_antennas_rx; - } - else AssertFatal(1==0,"rx_prach called without valid RU or eNB descriptor\n"); - - frame_type = fp->frame_type; - rootSequenceIndex = fp->prach_config_common.rootSequenceIndex; - prach_ConfigIndex = fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; - Ncs_config = fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; - restricted_set = fp->prach_config_common.prach_ConfigInfo.highSpeedFlag; - - int16_t *prach[nb_rx]; - - if (eNB) { - subframe = eNB->proc.subframe_prach; - prachF = eNB->prach_vars.prachF; - rxsigF = eNB->prach_vars.rxsigF; - prach_ifft = eNB->prach_vars.prach_ifft; - } - else { - subframe = ru->proc.subframe_prach; - rxsigF = ru->prach_rxsigF; - LOG_D(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", - subframe,fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex); - } - int16_t *prach2; - uint8_t n_ra_prb; uint8_t preamble_index; uint16_t NCS,NCS2; uint16_t preamble_offset=0,preamble_offset_old; @@ -1156,12 +1146,96 @@ void rx_prach(PHY_VARS_eNB *eNB, int32_t lev; int16_t levdB; int fft_size,log2_ifft_size; - - + int16_t prach_ifft_tmp[2048*2] __attribute__((aligned(32))); + int32_t *prach_ifft; + int32_t **prach_ifftp; +#ifdef Rel14 + int prach_ifft_cnt=0; +#endif #ifdef PRACH_DEBUG int en,en0=0; #endif + if (ru) { + fp = &ru->frame_parms; + nb_rx = ru->nb_rx; + } + else if (eNB) { + fp = &eNB->frame_parms; + nb_rx = fp->nb_antennas_rx; + } + else AssertFatal(1==0,"rx_prach called without valid RU or eNB descriptor\n"); + + frame_type = fp->frame_type; + +#ifdef Rel14 + if (br_flag == 1) { + AssertFatal(fp->prach_emtc_config_common.prach_Config_enabled==1, + "emtc prach_Config is not enabled\n"); + AssertFatal(fp->prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[ce_level]==1, + "ce_level %d is not active\n",ce_level); + rootSequenceIndex = fp->prach_emtc_config_common.rootSequenceIndex; + prach_ConfigIndex = fp->prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[ce_level]; + Ncs_config = fp->prach_emtc_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; + restricted_set = fp->prach_emtc_config_common.prach_ConfigInfo.highSpeedFlag; + n_ra_prb = get_prach_prb_offset(fp,prach_ConfigIndex, + fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level], + tdd_mapindex,Nf); + // update pointers to results for ce_level + max_preamble += ce_level; + max_preamble_energy += ce_level; + max_preamble_delay += ce_level; + } + else +#endif + { + rootSequenceIndex = fp->prach_config_common.rootSequenceIndex; + prach_ConfigIndex = fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; + Ncs_config = fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig; + restricted_set = fp->prach_config_common.prach_ConfigInfo.highSpeedFlag; + n_ra_prb = get_prach_prb_offset(fp,prach_ConfigIndex, + fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset, + tdd_mapindex,Nf); + } + + int16_t *prach[nb_rx]; + + if (eNB) { +#ifdef Rel14 + if (br_flag == 1) { + prach_ifftp = eNB->prach_vars_br.prach_ifft[ce_level]; + subframe = eNB->proc.subframe_prach_br; + prachF = eNB->prach_vars_br.prachF; + rxsigF = eNB->prach_vars_br.rxsigF; + } + else +#endif + { + prach_ifftp = eNB->prach_vars.prach_ifft[0]; + subframe = eNB->proc.subframe_prach; + prachF = eNB->prach_vars.prachF; + rxsigF = eNB->prach_vars.rxsigF; + } + } + else { +#ifdef Rel14 + if (br_flag == 1) { + subframe = ru->proc.subframe_prach_br; + rxsigF = ru->prach_rxsigF_br[ce_level]; + LOG_D(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", + subframe,fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level],prach_ConfigIndex); + } + else +#endif + { + subframe = ru->proc.subframe_prach; + rxsigF = ru->prach_rxsigF; + LOG_D(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", + subframe,fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex); + } + + } + AssertFatal(ru!=NULL,"ru is null\n"); for (aa=0; aa<nb_rx; aa++) { @@ -1186,7 +1260,7 @@ void rx_prach(PHY_VARS_eNB *eNB, if (eNB) start_meas(&eNB->rx_prach); - n_ra_prb = get_prach_prb_offset(fp,tdd_mapindex,Nf); + prach_root_sequence_map = (prach_fmt < 4) ? prach_root_sequence_map0_3 : prach_root_sequence_map4; // PDP is oversampled, e.g. 1024 sample instead of 839 @@ -1371,8 +1445,13 @@ void rx_prach(PHY_VARS_eNB *eNB, if ((eNB==NULL) && (ru!=NULL) && ru->function == NGFI_RRU_IF4p5) { - /// **** send_IF4 of rxsigF to RAU **** /// - send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH); + /// **** send_IF4 of rxsigF to RAU **** /// +#ifdef Rel14 + if (br_flag == 1) send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH+1+ce_level); + + else +#endif + send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH); #if 0 if (dB_fixed(en0)>30) { @@ -1402,6 +1481,30 @@ void rx_prach(PHY_VARS_eNB *eNB, preamble_offset_old = 99; + uint8_t update_TA = 4; + uint8_t update_TA2 = 1; + switch (eNB->frame_parms.N_RB_DL) { + case 6: + update_TA = 16; + break; + + case 25: + update_TA = 4; + break; + + case 50: + update_TA = 2; + break; + + case 75: + update_TA = 3; + update_TA2 = 2; + case 100: + update_TA = 1; + break; + } + + *max_preamble_energy=0; for (preamble_index=0 ; preamble_index<64 ; preamble_index++) { if (restricted_set == 0) { // This is the relative offset in the root sequence table (5.7.2-4 from 36.211) for the given preamble index @@ -1494,10 +1597,20 @@ void rx_prach(PHY_VARS_eNB *eNB, if (new_dft == 1) { new_dft = 0; Xu=(int16_t*)eNB->X_u[preamble_offset-first_nonzero_root_idx]; - +#ifdef Rel14 + if (br_flag == 1) { + prach_ifft = prach_ifftp[prach_ifft_cnt++]; + if (eNB->prach_vars_br.repetition_number[ce_level]==1) memset(prach_ifft,0,((N_ZC==839)?2048:256)*sizeof(int32_t)); + } + else +#endif + { + prach_ifft = prach_ifftp[0]; + memset(prach_ifft,0,((N_ZC==839) ? 2048 : 256)*sizeof(int32_t)); + } - memset( prachF, 0, sizeof(int16_t)*2*1024 ); + memset(prachF, 0, sizeof(int16_t)*2*1024 ); #ifdef PRACH_DEBUG if (prach[0]!= NULL) write_output("prach_rx0.m","prach_rx0",prach[0],6144+792,1,1); #endif @@ -1506,7 +1619,7 @@ void rx_prach(PHY_VARS_eNB *eNB, // write_output("prach_rxF1.m","prach_rxF1",rxsigF[1],6144,1,1); for (aa=0;aa<nb_rx; aa++) { - // Do componentwise product with Xu* + // Do componentwise product with Xu* on each antenna k=0; for (offset=0; offset<(N_ZC<<1); offset+=2) { @@ -1520,11 +1633,18 @@ void rx_prach(PHY_VARS_eNB *eNB, // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) if (N_ZC == 839) { log2_ifft_size = 10; - idft1024(prachF,prach_ifft[aa],1); + idft1024(prachF,prach_ifft_tmp,1); + // compute energy and accumulate over receive antennas and repetitions for BR + for (i=0;i<2048;i++) + prach_ifft[i] += (prach_ifft_tmp[i<<1]*prach_ifft_tmp[i<<1] + prach_ifft_tmp[1+(i<<1)]*prach_ifft_tmp[1+(i<<1)])>>15; } else { - idft256(prachF,prach_ifft[aa],1); + idft256(prachF,prach_ifft_tmp,1); log2_ifft_size = 8; + // compute energy and accumulate over receive antennas and repetitions for BR + for (i=0;i<256;i++) + prach_ifft[i] += (prach_ifft_tmp[i<<1]*prach_ifft_tmp[(i<<1)] + prach_ifft_tmp[1+(i<<1)]*prach_ifft_tmp[1+(i<<1)])>>15; } + #ifdef PRACH_DEBUG if (aa==0) write_output("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); #endif @@ -1545,42 +1665,85 @@ void rx_prach(PHY_VARS_eNB *eNB, write_output("rxsigF.m","prach_rxF",&rxsigF[0][0],12288,1,1); write_output("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); write_output("Xu.m","xu",Xu,N_ZC,1,1); - write_output("prach_ifft0.m","prach_t0",prach_ifft[0],1024,1,1); + write_output("prach_ifft0.m","prach_t0",prach_ifft[0][0],1024,1,1); exit(-1); } #endif } // new dft - // check energy in nth time shift - preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<<log2_ifft_size)/N_ZC)); - preamble_energy_list[preamble_index] = 0; - - for (i=0; i<NCS2; i++) { - lev = 0; - - for (aa=0; aa<nb_rx; aa++) { - lev += (int32_t)prach_ifft[aa][(preamble_shift2+i)<<1]*prach_ifft[aa][(preamble_shift2+i)<<1] + (int32_t)prach_ifft[aa][1+((preamble_shift2+i)<<1)]*prach_ifft[aa][1+((preamble_shift2+i)<<1)]; - } - - levdB = dB_fixed_times10(lev); - - if (levdB>preamble_energy_list[preamble_index] ) { - preamble_energy_list[preamble_index] = levdB; - preamble_delay_list[preamble_index] = (i*fft_size)>>log2_ifft_size; - } - } -#ifdef PRACH_DEBUG - LOG_D(PHY,"[RAPROC] Preamble %d => %d dB, %d (shift %d (%d), NCS2 %d(%d), Ncp %d)\n",preamble_index,preamble_energy_list[preamble_index],preamble_delay_list[preamble_index],preamble_shift2, - preamble_shift, NCS2,NCS,Ncp); - // exit(-1); + // check energy in nth time shift, for +#ifdef Rel14 + if ((br_flag==0) || + (eNB->prach_vars_br.repetition_number[ce_level]== + eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[ce_level])) #endif + { + preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<<log2_ifft_size)/N_ZC)); + + for (i=0; i<NCS2; i++) { + lev = (int32_t)prach_ifft[(preamble_shift2+i)<<1]; + levdB = dB_fixed_times10(lev); + + if (levdB>*max_preamble_energy) { + *max_preamble_energy = levdB; + *max_preamble_delay = ((i*fft_size)>>log2_ifft_size)*update_TA/update_TA2; + *max_preamble = preamble_index; + } + } + } }// preamble_index - + if (eNB) stop_meas(&eNB->rx_prach); - + } + + +#ifndef Rel14 +#define rx_prach rx_prach0 +#else +void rx_prach(PHY_VARS_eNB *eNB, + RU_t *ru, + uint16_t *max_preamble, + uint16_t *max_preamble_energy, + uint16_t *max_preamble_delay, + uint16_t Nf, + uint8_t tdd_mapindex, + uint8_t br_flag) { + + int i; + int prach_mask=0; + + if (br_flag == 0) { + rx_prach0(eNB,ru,max_preamble,max_preamble_energy,max_preamble_delay,Nf,tdd_mapindex,0,0); + } + else { // This is procedure for eMTC, basically handling the repetitions + prach_mask = is_prach_subframe(&eNB->frame_parms,eNB->proc.frame_prach_br,eNB->proc.subframe_prach_br); + for (i=0;i<4;i++) { + if ((eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i]==1) && + ((prach_mask&(1<<(i+1))) > 0)) { // check that prach CE level is active now + + // if first reception in group of repetitions store frame for later (in RA-RNTI for Msg2) + if (eNB->prach_vars_br.repetition_number[i]==0) eNB->prach_vars_br.first_frame[i]=eNB->proc.frame_prach_br; + + // increment repetition number + eNB->prach_vars_br.repetition_number[i]++; + + // do basic PRACH reception + rx_prach0(eNB,ru,max_preamble,max_preamble_energy,max_preamble_delay,Nf,tdd_mapindex,1,i); + + // if last repetition, clear counter + if (eNB->prach_vars_br.repetition_number[i] == eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[i]) { + eNB->prach_vars_br.repetition_number[i]=0; + + } + } + } + } +} +#endif + void init_prach_tables(int N_ZC) { diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index c1e3148ee4..024da7a810 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -2074,14 +2074,21 @@ int32_t generate_prach(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe, \brief Process PRACH waveform @param phy_vars_eNB Pointer to eNB top-level descriptor. If NULL, then this is an RRU @param ru Pointer to RU top-level descriptor. If NULL, then this is an eNB and we make use of the RU_list - @param preamble_energy_list List of energies for each candidate preamble - @param preamble_delay_list List of delays for each candidate preamble + @param max_preamble most likely preamble + @param max_preamble_energy Estimated Energy of most likely preamble + @param max_preamble_delay Estimated Delay of most likely preamble @param Nf System frame number @param tdd_mapindex Index of PRACH resource in Table 5.7.1-4 (TDD) + @param br_flag indicator to act on eMTC PRACH @returns 0 on success */ -void rx_prach(PHY_VARS_eNB *phy_vars_eNB,RU_t *ru,uint16_t *preamble_energy_list, uint16_t *preamble_delay_list, uint16_t Nf, uint8_t tdd_mapindex); +void rx_prach(PHY_VARS_eNB *phy_vars_eNB,RU_t *ru, + uint16_t *max_preamble, + uint16_t *max_preamble_energy, + uint16_t *max_preamble_delay, + uint16_t Nf, uint8_t tdd_mapindex, + uint8_t br_flag); /*! \brief Helper for MAC, returns number of available PRACH in TDD for a particular configuration index @@ -2169,7 +2176,10 @@ double computeRhoB_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, LTE_UE_DLSCH_t *dlsch_ue); */ -uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, uint8_t tdd_mapindex, uint16_t Nf); +uint8_t get_prach_prb_offset(LTE_DL_FRAME_PARMS *frame_parms, + uint8_t prach_ConfigIndex, + uint8_t n_ra_prboffset, + uint8_t tdd_mapindex, uint16_t Nf); uint8_t ul_subframe2pdcch_alloc_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t n); diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 13c4ce22b4..22df648149 100644 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -288,6 +288,10 @@ typedef struct RU_proc_t_s { int subframe_tx; /// subframe to act upon for reception of prach int subframe_prach; +#ifdef Rel14 + /// subframe to act upon for reception of prach BL/CE UEs + int subframe_prach_br; +#endif /// frame to act upon for reception int frame_rx; /// frame to act upon for transmission @@ -296,6 +300,10 @@ typedef struct RU_proc_t_s { int frame_tx_unwrap; /// frame to act upon for reception of prach int frame_prach; +#ifdef Rel14 + /// frame to act upon for reception of prach + int frame_prach_br; +#endif /// frame offset for slave RUs (to correct for frame asynchronism at startup) int frame_offset; /// \brief Instance count for FH processing thread. @@ -303,6 +311,10 @@ typedef struct RU_proc_t_s { int instance_cnt_FH; /// \internal This variable is protected by \ref mutex_prach. int instance_cnt_prach; +#ifdef Rel14 + /// \internal This variable is protected by \ref mutex_prach. + int instance_cnt_prach_br; +#endif /// \internal This variable is protected by \ref mutex_synch. int instance_cnt_synch; /// \internal This variable is protected by \ref mutex_eNBs. @@ -316,6 +328,10 @@ typedef struct RU_proc_t_s { pthread_t pthread_FH; /// pthread structure for RU prach processing thread pthread_t pthread_prach; +#ifdef Rel14 + /// pthread structure for RU prach processing thread BL/CE UEs + pthread_t pthread_prach_br; +#endif /// pthread struct for RU synch thread pthread_t pthread_synch; /// pthread struct for RU RX FEP thread @@ -330,6 +346,10 @@ typedef struct RU_proc_t_s { pthread_attr_t attr_FH; /// pthread attributes for RU prach pthread_attr_t attr_prach; +#ifdef Rel14 + /// pthread attributes for RU prach BL/CE UEs + pthread_attr_t attr_prach_br; +#endif /// pthread attributes for RU synch thread pthread_attr_t attr_synch; /// pthread attributes for asynchronous RX thread @@ -340,6 +360,10 @@ typedef struct RU_proc_t_s { struct sched_param sched_param_FH; /// scheduling parameters for RU prach thread struct sched_param sched_param_prach; +#ifdef Rel14 + /// scheduling parameters for RU prach thread BL/CE UEs + struct sched_param sched_param_prach_br; +#endif /// scheduling parameters for RU synch thread struct sched_param sched_param_synch; /// scheduling parameters for asynch_rxtx thread @@ -348,6 +372,10 @@ typedef struct RU_proc_t_s { pthread_cond_t cond_FH; /// condition variable for RU prach thread pthread_cond_t cond_prach; +#ifdef Rel14 + /// condition variable for RU prach thread BL/CE UEs + pthread_cond_t cond_prach_br; +#endif /// condition variable for RU synch thread pthread_cond_t cond_synch; /// condition variable for asynch RX/TX thread @@ -360,6 +388,10 @@ typedef struct RU_proc_t_s { pthread_mutex_t mutex_FH; /// mutex for RU prach pthread_mutex_t mutex_prach; +#ifdef Rel14 + /// mutex for RU prach BL/CE UEs + pthread_mutex_t mutex_prach_br; +#endif /// mutex for RU synch pthread_mutex_t mutex_synch; /// mutex for eNB signal @@ -390,20 +422,30 @@ typedef struct eNB_proc_t_s { int subframe_rx; /// subframe to act upon for PRACH int subframe_prach; +#ifdef Rel14 + /// subframe to act upon for reception of prach BL/CE UEs + int subframe_prach_br; +#endif /// frame to act upon for reception int frame_rx; /// frame to act upon for transmission int frame_tx; /// frame to act upon for PRACH int frame_prach; +#ifdef Rel14 + /// frame to act upon for PRACH BL/CE UEs + int frame_prach_br; +#endif /// \internal This variable is protected by \ref mutex_td. int instance_cnt_td; /// \internal This variable is protected by \ref mutex_te. int instance_cnt_te; - /// \brief Instance count for FH processing thread. - /// \brief Instance count for rx processing thread. /// \internal This variable is protected by \ref mutex_prach. int instance_cnt_prach; +#ifdef Rel14 + /// \internal This variable is protected by \ref mutex_prach for BL/CE UEs. + int instance_cnt_prach_br; +#endif // instance count for over-the-air eNB synchronization int instance_cnt_synch; /// \internal This variable is protected by \ref mutex_asynch_rxtx. @@ -424,6 +466,10 @@ typedef struct eNB_proc_t_s { pthread_attr_t attr_single; /// pthread attributes for prach processing thread pthread_attr_t attr_prach; +#ifdef Rel14 + /// pthread attributes for prach processing thread BL/CE UEs + pthread_attr_t attr_prach_br; +#endif /// pthread attributes for asynchronous RX thread pthread_attr_t attr_asynch_rxtx; /// scheduling parameters for parallel turbo-decoder thread @@ -434,6 +480,10 @@ typedef struct eNB_proc_t_s { struct sched_param sched_param_single; /// scheduling parameters for prach thread struct sched_param sched_param_prach; +#ifdef Rel14 + /// scheduling parameters for prach thread + struct sched_param sched_param_prach_br; +#endif /// scheduling parameters for asynch_rxtx thread struct sched_param sched_param_asynch_rxtx; /// pthread structure for parallel turbo-decoder thread @@ -442,12 +492,20 @@ typedef struct eNB_proc_t_s { pthread_t pthread_te; /// pthread structure for PRACH thread pthread_t pthread_prach; +#ifdef Rel14 + /// pthread structure for PRACH thread BL/CE UEs + pthread_t pthread_prach_br; +#endif /// condition variable for parallel turbo-decoder thread pthread_cond_t cond_td; /// condition variable for parallel turbo-encoder thread pthread_cond_t cond_te; /// condition variable for PRACH processing thread; pthread_cond_t cond_prach; +#ifdef Rel14 + /// condition variable for PRACH processing thread BL/CE UEs; + pthread_cond_t cond_prach_br; +#endif /// condition variable for asynch RX/TX thread pthread_cond_t cond_asynch_rxtx; /// mutex for parallel turbo-decoder thread @@ -456,16 +514,26 @@ typedef struct eNB_proc_t_s { pthread_mutex_t mutex_te; /// mutex for PRACH thread pthread_mutex_t mutex_prach; +#ifdef Rel14 + /// mutex for PRACH thread for BL/CE UEs + pthread_mutex_t mutex_prach_br; +#endif /// mutex for asynch RX/TX thread pthread_mutex_t mutex_asynch_rxtx; /// mutex for RU access to eNB processing (PDSCH/PUSCH) pthread_mutex_t mutex_RU; /// mutex for RU access to eNB processing (PRACH) pthread_mutex_t mutex_RU_PRACH; + /// mutex for RU access to eNB processing (PRACH BR) + pthread_mutex_t mutex_RU_PRACH_br; /// mask for RUs serving eNB (PDSCH/PUSCH) int RU_mask; /// mask for RUs serving eNB (PRACH) int RU_mask_prach; +#ifdef Rel14 + /// mask for RUs serving eNB (PRACH) + int RU_mask_prach_br; +#endif /// parameters for turbo-decoding worker thread td_params tdp; /// parameters for turbo-encoding worker thread @@ -631,6 +699,8 @@ typedef struct RU_t_s{ int (*wakeup_rxtx)(struct PHY_VARS_eNB_s *eNB,int frame_rx,int subframe_rx); /// function pointer to wakeup routine in lte-enb. int (*wakeup_prach_eNB)(struct PHY_VARS_eNB_s *eNB,struct RU_t_s *ru,int frame,int subframe); + /// function pointer to wakeup routine in lte-enb. + int (*wakeup_prach_eNB_br)(struct PHY_VARS_eNB_s *eNB,struct RU_t_s *ru,int frame,int subframe); /// function pointer to eNB entry routine void (*eNB_top)(struct PHY_VARS_eNB_s *eNB, int frame_rx, int subframe_rx, char *string); /// Timing statistics @@ -642,6 +712,8 @@ typedef struct RU_t_s{ /// received frequency-domain signal for PRACH (IF4p5 RRU) int16_t **prach_rxsigF; + /// received frequency-domain signal for PRACH BR (IF4p5 RRU) + int16_t **prach_rxsigF_br[4]; /// sequence number for IF5 uint8_t seqno; /// initial timestamp used as an offset make first real timestamp 0 @@ -829,12 +901,23 @@ typedef struct PHY_VARS_eNB_s { IF_Module_t *if_inst; UL_IND_t UL_INFO; pthread_mutex_t UL_INFO_mutex; + /// NFAPI RX ULSCH information nfapi_rx_indication_pdu_t rx_pdu_list[NFAPI_RX_IND_MAX_PDU]; + /// NFAPI RX ULSCH CRC information nfapi_crc_indication_pdu_t crc_pdu_list[NFAPI_CRC_IND_MAX_PDU]; + /// NFAPI PRACH information + nfapi_preamble_pdu_t preamble_list[MAX_NUM_RX_PRACH_PREAMBLES]; +#ifdef Rel14 + /// NFAPI PRACH information BL/CE UEs + nfapi_preamble_pdu_t preamble_list_br[MAX_NUM_RX_PRACH_PREAMBLES]; +#endif Sched_Rsp_t Sched_INFO; LTE_eNB_PDCCH pdcch_vars[2]; +#ifdef Rel14 LTE_eNB_EPDCCH epdcch_vars[2]; LTE_eNB_MPDCCH mpdcch_vars[2]; + LTE_eNB_PRACH prach_vars_br; +#endif LTE_eNB_COMMON common_vars; LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX]; LTE_eNB_PBCH pbch; @@ -1364,6 +1447,13 @@ typedef struct RRU_config_s { int prach_FreqOffset[MAX_BANDS_PER_RRU]; /// prach_ConfigIndex for IF4p5 int prach_ConfigIndex[MAX_BANDS_PER_RRU]; +#ifdef Rel14 + int emtc_prach_CElevel_enable[MAX_BANDS_PER_RRU][4]; + /// emtc_prach_FreqOffset for IF4p5 per CE Level + int emtc_prach_FreqOffset[MAX_BANDS_PER_RRU][4]; + /// emtc_prach_ConfigIndex for IF4p5 per CE Level + int emtc_prach_ConfigIndex[MAX_BANDS_PER_RRU][4]; +#endif } RRU_config_t; diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h index 4e6600acba..c0810f49f8 100644 --- a/openair1/PHY/impl_defs_lte.h +++ b/openair1/PHY/impl_defs_lte.h @@ -56,6 +56,8 @@ #define MAX_MBSFN_AREA 8 +#define NB_RX_ANTENNAS_MAX 64 + #ifdef OCP_FRAMEWORK #include "enums.h" #else @@ -99,6 +101,8 @@ typedef struct { uint8_t prach_FreqOffset; } PRACH_CONFIG_INFO; + + /// PRACH-ConfigSIB or PRACH-Config from 36.331 RRC spec typedef struct { /// Parameter: RACH_ROOT_SEQUENCE, see TS 36.211 (5.7.1). \vr{[0..837]} @@ -109,6 +113,44 @@ typedef struct { PRACH_CONFIG_INFO prach_ConfigInfo; } PRACH_CONFIG_COMMON; +#ifdef Rel14 + +/// PRACH-eMTC-Config from 36.331 RRC spec +typedef struct { + /// Parameter: High-speed-flag, see TS 36.211 (5.7.2). \vr{[0..1]} 1 corresponds to Restricted set and 0 to Unrestricted set. + uint8_t highSpeedFlag; +/// Parameter: \f$N_\text{CS}\f$, see TS 36.211 (5.7.2). \vr{[0..15]}\n Refer to table 5.7.2-2 for preamble format 0..3 and to table 5.7.2-3 for preamble format 4. + uint8_t zeroCorrelationZoneConfig; + /// Parameter: prach-FrequencyOffset, see TS 36.211 (5.7.1). \vr{[0..94]}\n For TDD the value range is dependent on the value of \ref prach_ConfigIndex. + + /// PRACH starting subframe periodicity, expressed in number of subframes available for preamble transmission (PRACH opportunities), see TS 36.211. Value 2 corresponds to 2 subframes, 4 corresponds to 4 subframes and so on. EUTRAN configures the PRACH starting subframe periodicity larger than or equal to the Number of PRACH repetitions per attempt for each CE level (numRepetitionPerPreambleAttempt). + uint8_t prach_starting_subframe_periodicity[4]; + /// number of repetitions per preamble attempt per CE level + uint8_t prach_numRepetitionPerPreambleAttempt[4]; + /// prach configuration index for each CE level + uint8_t prach_ConfigIndex[4]; + /// indicator for CE level activation + uint8_t prach_CElevel_enable[4]; + /// prach frequency offset for each CE level + uint8_t prach_FreqOffset[4]; + /// indicator for CE level hopping activation + uint8_t prach_hopping_enable[4]; + /// indicator for CE level hopping activation + uint8_t prach_hopping_offset[4]; +} PRACH_eMTC_CONFIG_INFO; + +#endif + +/// PRACH-ConfigSIB or PRACH-Config from 36.331 RRC spec +typedef struct { + /// Parameter: RACH_ROOT_SEQUENCE, see TS 36.211 (5.7.1). \vr{[0..837]} + uint16_t rootSequenceIndex; + /// prach_Config_enabled=1 means enabled. \vr{[0..1]} + uint8_t prach_Config_enabled; + /// PRACH Configuration Information + PRACH_eMTC_CONFIG_INFO prach_ConfigInfo; +} PRACH_eMTC_CONFIG_COMMON; + /// Enumeration for parameter \f$N_\text{ANRep}\f$ \ref PUCCH_CONFIG_DEDICATED::repetitionFactor. typedef enum { n2=0, @@ -546,6 +588,10 @@ typedef struct { uint8_t nb_antenna_ports_eNB; /// PRACH_CONFIG PRACH_CONFIG_COMMON prach_config_common; +#ifdef Rel14 + /// PRACH_eMTC_CONFIG + PRACH_eMTC_CONFIG_COMMON prach_emtc_config_common; +#endif /// PUCCH Config Common (from 36-331 RRC spec) PUCCH_CONFIG_COMMON pucch_config_common; /// PDSCH Config Common (from 36-331 RRC spec) @@ -1138,13 +1184,19 @@ typedef struct { /// \brief ?. /// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx. /// second index: ? [0..ofdm_symbol_size*12[ - int16_t *rxsigF[64]; + int16_t **rxsigF; /// \brief local buffer to compute prach_ifft (necessary in case of multiple CCs) /// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx. /// second index: ? [0..2047] (hard coded) - int16_t *prach_ifft[64]; - /// NFAPI PRACH information - nfapi_preamble_pdu_t preamble_list[MAX_NUM_RX_PRACH_PREAMBLES]; + int32_t ***prach_ifft; + + /// repetition number +#ifdef Rel14 + /// indicator of first frame in a group of PRACH repetitions + int first_frame[4]; + /// current repetition for each CE level + int repetition_number[4]; +#endif } LTE_eNB_PRACH; typedef struct { @@ -1162,6 +1214,7 @@ typedef struct { uint8_t *Msg3; } PRACH_RESOURCES_t; + typedef struct { /// Downlink Power offset field uint8_t dl_pow_off; diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index 26859b6528..f414e28f63 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -199,10 +199,13 @@ void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,re /*! \brief Scheduling for eNB PRACH RX procedures @param phy_vars_eNB Pointer to eNB variables on which to act - @param proc Pointer to RXn-TXnp4 proc information + @param br_flag indicator for eMTC PRACH */ -void prach_procedures(PHY_VARS_eNB *eNB); - +void prach_procedures(PHY_VARS_eNB *eNB, +#ifdef Rel14 + int br_flag +#endif + ); /*! \brief Function to compute subframe type as a function of Frame type and TDD Configuration (implements Table 4.2.2 from 36.211, p.11 from version 8.6) and subframe index. @param frame_parms Pointer to DL frame parameter descriptor @param subframe Subframe index diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 2ef387cf5d..546e6b7abf 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1179,7 +1179,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { handle_nfapi_dlsch_pdu(eNB,proc,dl_config_pdu, dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks-1, TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data); - if (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == eNB->prach_vars.preamble_list[0].preamble_rel8.rnti) {// is RAR pdu + if (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == eNB->preamble_list[0].preamble_rel8.rnti) {// is RAR pdu generate_eNB_ulsch_params_from_rar(eNB, TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data, @@ -1917,107 +1917,136 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB, } } -void prach_procedures(PHY_VARS_eNB *eNB) { +void prach_procedures(PHY_VARS_eNB *eNB, +#ifdef Rel14 + int br_flag +#endif + ) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - uint16_t preamble_energy_list[64],preamble_delay_list[64]; - uint16_t preamble_max,preamble_energy_max; + uint16_t max_preamble[4],max_preamble_energy[4],max_preamble_delay[4]; uint16_t i; - int subframe = eNB->proc.subframe_prach; - int frame = eNB->proc.frame_prach; + int frame,subframe; +#ifdef Rel14 + if (br_flag==1) { + subframe = eNB->proc.subframe_prach_br; + frame = eNB->proc.frame_prach_br; + } + else +#endif + { + subframe = eNB->proc.subframe_prach; + frame = eNB->proc.frame_prach; + } uint8_t CC_id = eNB->CC_id; RU_t *ru; int aa=0; int ru_aa; + LTE_eNB_PRACH *prach_vars; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); - memset(&preamble_energy_list[0],0,64*sizeof(uint16_t)); - memset(&preamble_delay_list[0],0,64*sizeof(uint16_t)); - for (i=0;i<eNB->num_RU;i++) { ru=eNB->RU_list[i]; - for (ru_aa=0;ru_aa<ru->nb_rx;ru_aa++) eNB->prach_vars.rxsigF[aa++] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; + for (ru_aa=0,aa=0;ru_aa<ru->nb_rx;ru_aa++,aa++) { + eNB->prach_vars.rxsigF[aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; +#ifdef Rel14 + int ce_level; + + if (br_flag==1) + for (ce_level=0;ce_level<4;ce_level++) eNB->prach_vars_br.rxsigF[aa] = eNB->RU_list[i]->prach_rxsigF_br[ce_level][ru_aa]; +#endif + } } + rx_prach(eNB, eNB->RU_list[0], - preamble_energy_list, - preamble_delay_list, + &max_preamble[0], + &max_preamble_energy[0], + &max_preamble_delay[0], frame, - 0); - preamble_energy_max = preamble_energy_list[0]; - preamble_max = 0; - - for (i=1; i<64; i++) { - if (preamble_energy_max < preamble_energy_list[i]) { - preamble_energy_max = preamble_energy_list[i]; - preamble_max = i; - } - } + 0 +#ifdef Rel14 + ,br_flag +#endif + ); //#ifdef DEBUG_PHY_PROC LOG_D(PHY,"[RAPROC] Frame %d, subframe %d : Most likely preamble %d, energy %d dB delay %d\n", frame,subframe, - preamble_max, - preamble_energy_list[preamble_max], - preamble_delay_list[preamble_max]); + max_preamble[0], + max_preamble_energy[0], + max_preamble_delay[0]); //#endif - if (preamble_energy_list[preamble_max] > 580) { +#ifdef Rel14 + if (br_flag==1) { - // UE_id = find_next_ue_index(eNB); - - // if (UE_id>=0) { - // eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits - - // eNB->UE_stats[(uint32_t)UE_id].sector = 0; - LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", - eNB->Mod_id, - eNB->CC_id, - frame, - subframe, - preamble_max, - preamble_energy_max/10, - preamble_energy_max%10, - preamble_delay_list[preamble_max]); + prach_vars = &eNB->prach_vars_br; + int prach_mask; + + prach_mask = is_prach_subframe(&eNB->frame_parms,eNB->proc.frame_prach_br,eNB->proc.subframe_prach_br); + + eNB->UL_INFO.rach_ind_br.preamble_list = eNB->preamble_list_br; - T(T_ENB_PHY_INITIATE_RA_PROCEDURE, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), 0, - T_INT(preamble_max), T_INT(preamble_energy_max), T_INT(preamble_delay_list[preamble_max])); + for (int ind=0,ce_level=0;ce_level<4;ce_level++) { + if ((prach_mask&(1<<(1+ce_level)) > 0) && // prach is active and CE level has finished its repetitions + (eNB->prach_vars_br.repetition_number[ce_level]== + eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[ce_level])) { + if (max_preamble_energy[ind] > 580) { + eNB->UL_INFO.rach_ind_br.number_of_preambles++; + + eNB->preamble_list_br[ind].preamble_rel8.timing_advance = max_preamble_delay[ind];// + eNB->preamble_list_br[ind].preamble_rel8.preamble = max_preamble[ind]; + // note: fid is implicitly 0 here, this is the rule for eMTC RA-RNTI from 36.321, Section 5.1.4 + eNB->preamble_list_br[ind].preamble_rel8.rnti = 1+subframe+(eNB->prach_vars_br.first_frame[ce_level]%40); + eNB->preamble_list_br[ind].instance_length = 0; //don't know exactly what this is + eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type = 1+ce_level; // CE Level + } + ind++; + } + } // ce_level + } + else +#endif - if (eNB->mac_enabled==1) { - LTE_eNB_PRACH *prach_vars = &eNB->prach_vars; - - uint8_t update_TA = 4; - uint8_t update_TA2 = 1; - switch (fp->N_RB_DL) { - case 6: - update_TA = 16; - break; - - case 25: - update_TA = 4; - break; - - case 50: - update_TA = 2; - break; + { + if (max_preamble_energy[0] > 580) { + + LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", + eNB->Mod_id, + eNB->CC_id, + frame, + subframe, + max_preamble[0], + max_preamble_energy[0]/10, + max_preamble_energy[0]%10, + max_preamble_delay[0]); - case 75: - update_TA = 3; - update_TA2 = 2; - case 100: - update_TA = 1; - break; - } - pthread_mutex_lock(&eNB->UL_INFO_mutex); - eNB->UL_INFO.rach_ind.number_of_preambles = 1; - eNB->UL_INFO.rach_ind.preamble_list = prach_vars->preamble_list; - - prach_vars->preamble_list[0].preamble_rel8.timing_advance = preamble_delay_list[preamble_max]*update_TA/update_TA2; - prach_vars->preamble_list[0].preamble_rel8.preamble = preamble_max; - prach_vars->preamble_list[0].preamble_rel8.rnti = 1+subframe; // note: fid is implicitly 0 here - prach_vars->preamble_list[0].instance_length = 0; //don't know exactly what this is - pthread_mutex_unlock(&eNB->UL_INFO_mutex); + T(T_ENB_PHY_INITIATE_RA_PROCEDURE, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), 0, + T_INT(max_preamble[0]), T_INT(max_preamble_energy[0]), T_INT(max_preamble_delay[0])); + + if (eNB->mac_enabled==1) { + + prach_vars = &eNB->prach_vars; + + + pthread_mutex_lock(&eNB->UL_INFO_mutex); + + eNB->UL_INFO.rach_ind.number_of_preambles = 1; + eNB->UL_INFO.rach_ind.preamble_list = eNB->preamble_list; + + eNB->preamble_list[0].preamble_rel8.timing_advance = max_preamble_delay[0]; + eNB->preamble_list[0].preamble_rel8.preamble = max_preamble[0]; + eNB->preamble_list[0].preamble_rel8.rnti = 1+subframe; // note: fid is implicitly 0 here + eNB->preamble_list[0].preamble_rel13.rach_resource_type = 0; + eNB->preamble_list[0].instance_length = 0; //don't know exactly what this is + + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + } + } // max_preamble_energy > 580 + } // else br_flag /* mac_xface->initiate_ra_proc(eNB->Mod_id, eNB->CC_id, @@ -2026,15 +2055,13 @@ void prach_procedures(PHY_VARS_eNB *eNB) { preamble_delay_list[preamble_max]*update_TA/update_TA2, 0,subframe,0);*/ - // fill eNB->UL_info with prach information - } /* } else { MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many"); LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n", eNB->Mod_id,frame, subframe); }*/ - } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); } diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index c035490105..0d9980ed10 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -330,7 +330,7 @@ void config_sib2(int Mod_idP, cfg->emtc_config.prach_catm_zero_correlation_zone_configuration.value = radioResourceConfigCommon_BRP->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; cfg->emtc_config.prach_catm_high_speed_flag.value = radioResourceConfigCommon_BRP->prach_Config.prach_ConfigInfo.highSpeedFlag; - struct PRACH_ConfigSIB_v1310 *ext4_prach=radioResourceConfigCommonP->ext4->prach_ConfigCommon_v1310; + struct PRACH_ConfigSIB_v1310 *ext4_prach=radioResourceConfigCommon_BRP->ext4->prach_ConfigCommon_v1310; PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13; int i; @@ -342,40 +342,44 @@ void config_sib2(int Mod_idP, switch (prach_ParametersListCE_r13->list.count) { case 4: p=prach_ParametersListCE_r13->list.array[3]; - cfg->emtc_config.prach_ce_level_3_enable.value = 1; - cfg->emtc_config.prach_ce_level_3_configuration_index.value = p->prach_ConfigIndex_r13; - cfg->emtc_config.prach_ce_level_3_frequency_offset.value = p->prach_FreqOffset_r13; + cfg->emtc_config.prach_ce_level_3_enable.value = 1; + cfg->emtc_config.prach_ce_level_3_configuration_index.value = p->prach_ConfigIndex_r13; + cfg->emtc_config.prach_ce_level_3_frequency_offset.value = p->prach_FreqOffset_r13; + cfg->emtc_config.prach_ce_level_3_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13; if (p->prach_StartingSubframe_r13) - cfg->emtc_config.prach_ce_level_3_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; - cfg->emtc_config.prach_ce_level_3_hopping_enable.value = p->prach_HoppingConfig_r13; - cfg->emtc_config.prach_ce_level_3_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; + cfg->emtc_config.prach_ce_level_3_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; + cfg->emtc_config.prach_ce_level_3_hopping_enable.value = p->prach_HoppingConfig_r13; + cfg->emtc_config.prach_ce_level_3_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; case 3: p=prach_ParametersListCE_r13->list.array[2]; - cfg->emtc_config.prach_ce_level_2_enable.value = 1; - cfg->emtc_config.prach_ce_level_2_configuration_index.value = p->prach_ConfigIndex_r13; - cfg->emtc_config.prach_ce_level_2_frequency_offset.value = p->prach_FreqOffset_r13; + cfg->emtc_config.prach_ce_level_2_enable.value = 1; + cfg->emtc_config.prach_ce_level_2_configuration_index.value = p->prach_ConfigIndex_r13; + cfg->emtc_config.prach_ce_level_2_frequency_offset.value = p->prach_FreqOffset_r13; + cfg->emtc_config.prach_ce_level_2_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13; if (p->prach_StartingSubframe_r13) - cfg->emtc_config.prach_ce_level_2_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; - cfg->emtc_config.prach_ce_level_2_hopping_enable.value = p->prach_HoppingConfig_r13; - cfg->emtc_config.prach_ce_level_2_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; + cfg->emtc_config.prach_ce_level_2_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; + cfg->emtc_config.prach_ce_level_2_hopping_enable.value = p->prach_HoppingConfig_r13; + cfg->emtc_config.prach_ce_level_2_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; case 2: p=prach_ParametersListCE_r13->list.array[1]; - cfg->emtc_config.prach_ce_level_1_enable.value = 1; - cfg->emtc_config.prach_ce_level_1_configuration_index.value = p->prach_ConfigIndex_r13; - cfg->emtc_config.prach_ce_level_1_frequency_offset.value = p->prach_FreqOffset_r13; + cfg->emtc_config.prach_ce_level_1_enable.value = 1; + cfg->emtc_config.prach_ce_level_1_configuration_index.value = p->prach_ConfigIndex_r13; + cfg->emtc_config.prach_ce_level_1_frequency_offset.value = p->prach_FreqOffset_r13; + cfg->emtc_config.prach_ce_level_1_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13; if (p->prach_StartingSubframe_r13) - cfg->emtc_config.prach_ce_level_1_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; - cfg->emtc_config.prach_ce_level_1_hopping_enable.value = p->prach_HoppingConfig_r13; - cfg->emtc_config.prach_ce_level_1_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; + cfg->emtc_config.prach_ce_level_1_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; + cfg->emtc_config.prach_ce_level_1_hopping_enable.value = p->prach_HoppingConfig_r13; + cfg->emtc_config.prach_ce_level_1_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; case 1: p=prach_ParametersListCE_r13->list.array[0]; - cfg->emtc_config.prach_ce_level_0_enable.value = 1; - cfg->emtc_config.prach_ce_level_0_configuration_index.value = p->prach_ConfigIndex_r13; - cfg->emtc_config.prach_ce_level_0_frequency_offset.value = p->prach_FreqOffset_r13; + cfg->emtc_config.prach_ce_level_0_enable.value = 1; + cfg->emtc_config.prach_ce_level_0_configuration_index.value = p->prach_ConfigIndex_r13; + cfg->emtc_config.prach_ce_level_0_frequency_offset.value = p->prach_FreqOffset_r13; + cfg->emtc_config.prach_ce_level_0_number_of_repetitions_per_attempt.value = p->numRepetitionPerPreambleAttempt_r13; if (p->prach_StartingSubframe_r13) - cfg->emtc_config.prach_ce_level_0_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; - cfg->emtc_config.prach_ce_level_0_hopping_enable.value = p->prach_HoppingConfig_r13; - cfg->emtc_config.prach_ce_level_0_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; + cfg->emtc_config.prach_ce_level_0_starting_subframe_periodicity.value = *p->prach_StartingSubframe_r13; + cfg->emtc_config.prach_ce_level_0_hopping_enable.value = p->prach_HoppingConfig_r13; + cfg->emtc_config.prach_ce_level_0_hopping_offset.value = cfg->rf_config.ul_channel_bandwidth.value-6; } struct FreqHoppingParameters_r13 *ext4_freqHoppingParameters = radioResourceConfigCommonP->ext4->freqHoppingParameters_r13; diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index 45619246c4..2c8b613b1d 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -824,10 +824,18 @@ typedef struct { uint8_t generate_rar; /// Subframe where preamble was received uint8_t preamble_subframe; + /// Subframe where Msg2 is to be sent + uint8_t Msg2_subframe; + /// Frame where Msg2 is to be sent + uint8_t Msg2_frame; /// Subframe where Msg3 is to be sent uint8_t Msg3_subframe; - /// Subframe where Msg3 is to be sent + /// Frame where Msg3 is to be sent uint8_t Msg3_frame; + /// Subframe where Msg4 is to be sent + uint8_t Msg4_subframe; + /// Frame where Msg4 is to be sent + uint8_t Msg4_frame; /// Flag to indicate the eNB should generate Msg4 upon reception of SDU from RRC. This is triggered by first ULSCH reception at eNB for new user. uint8_t generate_Msg4; /// Flag to indicate that eNB is waiting for ACK that UE has received Msg3. @@ -846,6 +854,13 @@ typedef struct { int16_t RRC_timer; /// Round of Msg3 HARQ uint8_t msg3_round; +#ifdef Rel14 + uint8_t rach_resource_type; + uint8_t msg2_mpdcch_repetition_cnt; + uint8_t msg4_mpdcch_repetition_cnt; + uint8_t msg2_narrowband; + uint8_t msg34_narrowband; +#endif } RA_TEMPLATE; @@ -962,7 +977,7 @@ typedef struct eNB_MAC_INST_s { /// Ethernet parameters for fronthaul interface eth_params_t eth_params_s; /// - uint16_t Node_id; + module_id_t Mod_id; /// frame counter frame_t frame; /// subframe counter @@ -1030,6 +1045,15 @@ typedef struct eNB_MAC_INST_s { * UE part */ +typedef enum { + TYPE0, + TYPE1, + TYPE1A, + TYPE2, + TYPE2A, + TYPEUESPEC +} MPDCCH_TYPES_t; + /*!\brief UE layer 2 status */ typedef enum { CONNECTION_OK=0, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c index d6e245d180..47a809f032 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c @@ -174,6 +174,31 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un int round; nfapi_dl_config_request_body_t *dl_req; +#ifdef Rel14 + int rmax = 0; + int rep = 0; + int reps = 0; + int num_nb = 0; + first_rb = 0; + + struct PRACH_ConfigSIB_v1310 *ext4_prach = cc[CC_id].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310; + PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13; + PRACH_ParametersCE_r13_t *p[3]; + + switch (prach_ParametersListCE_r13->list.count) { + case 4: + p[3]=prach_ParametersListCE_r13->list.array[3]; + case 3: + p[2]=prach_ParametersListCE_r13->list.array[2]; + case 2: + p[1]=prach_ParametersListCE_r13->list.array[1]; + case 1: + p[0]=prach_ParametersListCE_r13->list.array[0]; + default: + AssertFatal(1==0,"Illegal count for prach_ParametersListCE_r13 %d\n",prach_ParametersListCE_r13->list.count); + } +#endif + start_meas(&eNB->schedule_ra); for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { @@ -193,93 +218,248 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un module_idP,CC_id,i,RA_template->generate_rar,RA_template->generate_Msg4,RA_template->wait_ack_Msg4, RA_template->rnti); if (RA_template->generate_rar == 1) { + +#ifdef Rel14 + if (RA_template->rach_resource_type > 0) { + + // This uses an MPDCCH Type 2 allocation according to Section 9.1.5 36-213 + // Parameters: + // p=2+4 PRB set (number of PRB pairs 6) + // rmax = mpdcch-NumRepetition-RA-r13 => Table 9.1.5-3 + // if CELevel = 0,1 => Table 9.1.5-1b for MPDCCH candidates + // if CELevel = 2,3 => Table 9.1.5-2b for MPDCCH candidates + // distributed transmission + + // rmax from SIB2 information + rmax = p[RA_template->rach_resource_type-1]->mpdcch_NumRepetition_RA_r13; + // choose r3 by default for RAR + rep = 2; + // get actual repetition count from Table 9.1.5-3 + reps = (rmax<=8)?(1<<rep):(rmax>>(3-rep)); + // get narrowband according to higher-layer config + num_nb = p[RA_template->rach_resource_type-1]->mpdcch_NarrowbandsToMonitor_r13.list.count; + RA_template->msg2_narrowband = *p[RA_template->rach_resource_type-1]->mpdcch_NarrowbandsToMonitor_r13.list.array[RA_template->preamble_index%num_nb]; + first_rb = RA_template->msg2_narrowband*6; + + if ((RA_template->msg2_mpdcch_repetition_cnt == 0) && + (mpdcch_sf_condition(eNB,CC_id,frameP,subframeP,rmax,TYPE2)>0)){ + // MPDCCH configuration for RAR - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI (proc %d), RA_active %d format 1A (%d,%d))\n", - module_idP, CC_id, frameP, subframeP,i, - RA_template->RA_active, - RA_template->RA_dci_fmt1, - RA_template->RA_dci_size_bits1); - - first_rb = 0; - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = RA_template->RA_rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // RA-RNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,4); - - if (!CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->RA_rnti)) { - LOG_D(MAC,"Frame %d: Subframe %d : Adding common DCI for RA_RNTI %x\n", - frameP,subframeP,RA_template->RA_rnti); - dl_req->number_dci++; - dl_req->number_pdu++; - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = RA_template->RA_rnti; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,4); - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; - // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; - dl_req->number_pdu++; - - // Program UL processing for Msg3 - get_Msg3alloc(&cc[CC_id],subframeP,frameP,&RA_template->Msg3_frame,&RA_template->Msg3_subframe); - - - fill_rar(module_idP,CC_id,frameP,cc[CC_id].RAR_pdu.payload,N_RB_DL,7); - // DL request - eNB->TX_req[CC_id].sfn_sf = (frameP<<3)+subframeP; - TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; - TX_req->pdu_length = 7; // This should be changed if we have more than 1 preamble - TX_req->pdu_index = eNB->pdu_index[CC_id]++; - TX_req->num_segments = 1; - TX_req->segments[0].segment_length = 7; - TX_req->segments[0].segment_data = cc[CC_id].RAR_pdu.payload; - eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; - } - } else if (RA_template->generate_Msg4 == 1) { - - // check for Msg4 Message - UE_id = find_UE_id(module_idP,RA_template->rnti); - AssertFatal(UE_id>=0,"Can't find UE for t-crnti\n"); + + memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_mpdcch_pdu)); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_format = (RA_template->rach_resource_type > 1) ? 11 : 10; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_narrow_band = RA_template->msg2_narrowband; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_prb_pairs = 6; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_assignment = 0; // Note: this can be dynamic + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type = 1; + AssertFatal(cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13!=NULL, + "cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n"); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol = cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index = 0; // Note: this should be dynamic + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level = 16; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4 + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type = 2; // RA-RNTI + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti = RA_template->RA_rnti; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ce_mode = (RA_template->rach_resource_type < 3) ? 1 : 2; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.drms_scrambling_init = cc[CC_id].physCellId; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.initial_transmission_sf_io = (frameP*10)+subframeP; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.transmission_power = 6000; // 0dB + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_coding = getRIV(N_RB_DL,first_rb,6); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mcs = 4; // adjust according to size of RAR, 208 bits with N1A_PRB=3 + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pdsch_reptition_levels = 4; // fix to 4 for now + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.redundancy_version = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.new_data_indicator = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_process = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi_length = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_resource_offset = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_subframe_repetition_number = rep; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpc = 2;// N1A_PRB=3; => 208 bits + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index_length = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.allocate_prach_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.preamble_index = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.prach_mask_index = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.starting_ce_level = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.srs_request = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.frequency_hopping_enabled_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.paging_direct_indication_differentiation_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.direct_indication = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.total_dci_length_including_padding = 0; // this is not needed by OAI L1, but should be filled in + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_tx_antenna_ports = 1; + RA_template->msg2_mpdcch_repetition_cnt++; + dl_req->number_pdu++; + + } //repetition_count==0 && SF condition met + if (RA_template->msg2_mpdcch_repetition_cnt>0) { // we're in a stream of repetitions + RA_template->msg2_mpdcch_repetition_cnt++; + if (RA_template->msg2_mpdcch_repetition_cnt==reps) { // this is the last mpdcch repetition + if (cc[CC_id].tdd_Config==NULL) { // FDD case + // wait 2 subframes for PDSCH transmission + if (subframeP>7) RA_template->Msg2_frame = (frameP+1)&1023; + else RA_template->Msg2_frame = frameP; + RA_template->Msg2_subframe = (subframeP+2)%10; + } + else { + AssertFatal(1==0,"TDD case not done yet\n"); + } + } // mpdcch_repetition_count == reps + if ((RA_template->Msg2_frame == frameP) && (RA_template->Msg2_subframe == subframeP)) { + // Program PDSCH + RA_template->generate_rar = 0; + + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = RA_template->RA_rnti; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,6); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = (RA_template->rach_resource_type < 3) ? 1 : 2;; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not SI message + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = (10*frameP)+subframeP; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.drms_table_flag = 0; + dl_req->number_pdu++; + + // Program UL processing for Msg3, same as regular LTE + get_Msg3alloc(&cc[CC_id],subframeP,frameP,&RA_template->Msg3_frame,&RA_template->Msg3_subframe); + + + fill_rar_br(eNB,CC_id,i,frameP,subframeP,cc[CC_id].RAR_pdu.payload,RA_template->rach_resource_type-1); + // DL request + eNB->TX_req[CC_id].sfn_sf = (frameP<<3)+subframeP; + TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = 7; // This should be changed if we have more than 1 preamble + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = 7; + TX_req->segments[0].segment_data = cc[CC_id].RAR_pdu.payload; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + } + } + } + else +#endif + { + if ((RA_template->Msg2_frame == frameP) && (RA_template->Msg2_subframe == subframeP)) { + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI (proc %d), RA_active %d format 1A (%d,%d))\n", + module_idP, CC_id, frameP, subframeP,i, + RA_template->RA_active, + + RA_template->RA_dci_fmt1, + RA_template->RA_dci_size_bits1); + + first_rb = 0; + vrb_map[first_rb] = 1; + vrb_map[first_rb+1] = 1; + vrb_map[first_rb+2] = 1; + vrb_map[first_rb+3] = 1; + + memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = RA_template->RA_rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 2; // RA-RNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,4); + + if (!CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->RA_rnti)) { + LOG_D(MAC,"Frame %d: Subframe %d : Adding common DCI for RA_RNTI %x\n", + frameP,subframeP,RA_template->RA_rnti); + dl_req->number_dci++; + dl_req->number_pdu++; + + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = RA_template->RA_rnti; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,4); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + dl_req->number_pdu++; + + // Program UL processing for Msg3 + get_Msg3alloc(&cc[CC_id],subframeP,frameP,&RA_template->Msg3_frame,&RA_template->Msg3_subframe); + + + fill_rar(module_idP,CC_id,frameP,cc[CC_id].RAR_pdu.payload,N_RB_DL,7); + // DL request + eNB->TX_req[CC_id].sfn_sf = (frameP<<3)+subframeP; + TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = 7; // This should be changed if we have more than 1 preamble + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = 7; + TX_req->segments[0].segment_data = cc[CC_id].RAR_pdu.payload; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + } // PDCCH CCE allocation is feasible + } // Msg2 frame/subframe condition + } // else BL/CE + } // state generate_rar == 1 + else if (RA_template->generate_Msg4 == 1) { + + // check for Msg4 Message + + UE_id = find_UE_id(module_idP,RA_template->rnti); + AssertFatal(UE_id>=0,"Can't find UE for t-crnti\n"); + + // Get RRCConnectionSetup for Piggyback rrc_sdu_length = mac_rrc_data_req(module_idP, CC_id, @@ -292,224 +472,436 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un 0); // not used in this case AssertFatal(rrc_sdu_length>=0, - "[MAC][eNB Scheduler] CCCH not allocated\n"); - - - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, rrc_sdu_length %d\n", - module_idP, CC_id, frameP, subframeP,UE_id, rrc_sdu_length); - - if (rrc_sdu_length>0) { - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RA proc %d, RNTI %x)\n", - module_idP, CC_id, frameP, subframeP,i,RA_template->rnti); - - first_rb=0; + "[MAC][eNB Scheduler] CCCH not allocated\n"); + + + LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, rrc_sdu_length %d\n", + module_idP, CC_id, frameP, subframeP,UE_id, rrc_sdu_length); - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; +#ifdef Rel14 + if (RA_template->rach_resource_type>0) { - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = RA_template->rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // C-RNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + // Generate DCI + repetitions first + // This uses an MPDCCH Type 2 allocation according to Section 9.1.5 36-213 + // Parameters: + // p=2+4 PRB set (number of PRB pairs 6) + // rmax = mpdcch-NumRepetition-RA-r13 => Table 9.1.5-3 + // if CELevel = 0,1 => Table 9.1.5-1b for MPDCCH candidates + // if CELevel = 2,3 => Table 9.1.5-2b for MPDCCH candidates + // distributed transmission - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; - - // Compute MCS for 3 PRB - msg4_header = 1+6+1; // CR header, CR CE, SDU header - - - if ((rrc_sdu_length+msg4_header) <= 22) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 4; - TBsize = 22; - } else if ((rrc_sdu_length+msg4_header) <= 28) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 5; - TBsize = 28; - } else if ((rrc_sdu_length+msg4_header) <= 32) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 6; - TBsize = 32; - } else if ((rrc_sdu_length+msg4_header) <= 41) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 7; - TBsize = 41; - } else if ((rrc_sdu_length+msg4_header) <= 49) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 8; - TBsize = 49; - } else if ((rrc_sdu_length+msg4_header) <= 57) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 9; - TBsize = 57; - } - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding= getRIV(N_RB_DL,first_rb,4); - - if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->rnti)) { - dl_req->number_dci++; - dl_req->number_pdu++; - - RA_template->generate_Msg4=0; - RA_template->wait_ack_Msg4=1; - RA_template->RA_active = FALSE; - lcid=0; - - // set HARQ process 0 round to 0 for this UE - UE_list->UE_sched_ctrl[UE_id].round[CC_id] = 0; - - if ((TBsize - rrc_sdu_length - msg4_header) <= 2) { - msg4_padding = TBsize - rrc_sdu_length - msg4_header; - msg4_post_padding = 0; - } else { - msg4_padding = 0; - msg4_post_padding = TBsize - rrc_sdu_length - msg4_header -1; - } - - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", - module_idP,CC_id,frameP,subframeP,TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding); - DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return - // CHECK THIS: &cc[CC_id].CCCH_pdu.payload[0] - offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], - 1, //num_sdus - (unsigned short*)&rrc_sdu_length, // - &lcid, // sdu_lcid - 255, // no drx - 0, // no timing advance - RA_template->cont_res_id, // contention res id - msg4_padding, // no padding - msg4_post_padding); - - memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], - &cc[CC_id].CCCH_pdu.payload[0], - rrc_sdu_length); - - // DL request - eNB->TX_req[CC_id].sfn_sf = (frameP<<3)+subframeP; - TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; - TX_req->pdu_length = rrc_sdu_length; - TX_req->pdu_index = eNB->pdu_index[CC_id]++; - TX_req->num_segments = 1; - TX_req->segments[0].segment_length = rrc_sdu_length; - TX_req->segments[0].segment_data = eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]; - eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; - - T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(RA_template->rnti), T_INT(frameP), T_INT(subframeP), - T_INT(0 /*harq_pid always 0?*/), T_BUFFER(&eNB->UE_list.DLSCH_pdu[CC_id][0][UE_id].payload[0], TBsize)); + // rmax from SIB2 information + rmax = p[RA_template->rach_resource_type-1]->mpdcch_NumRepetition_RA_r13; + // choose r3 by default for Msg4 + rep = 2; + // get actual repetition count from Table 9.1.5-3 + reps = (rmax<=8)?(1<<rep):(rmax>>(3-rep)); + // get first narrowband + first_rb = RA_template->msg34_narrowband*6; + + if ((RA_template->msg4_mpdcch_repetition_cnt == 0) && + (mpdcch_sf_condition(eNB,CC_id,frameP,subframeP,rmax,TYPE2)>0)){ + // MPDCCH configuration for RAR - if (opt_enabled==1) { - trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], - rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id), - eNB->frame, eNB->subframe,0,0); - LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", - module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length); - } + memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_mpdcch_pdu)); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_format = (RA_template->rach_resource_type > 1) ? 11 : 10; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_narrow_band = RA_template->msg34_narrowband; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_prb_pairs = 6; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_assignment = 0; // Note: this can be dynamic + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type = 1; + AssertFatal(cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13!=NULL, + "cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n"); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol = cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index = 0; // Note: this should be dynamic + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level = 16; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4 + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type = 2; // RA-RNTI + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti = RA_template->RA_rnti; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ce_mode = (RA_template->rach_resource_type < 3) ? 1 : 2; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.drms_scrambling_init = cc[CC_id].physCellId; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.initial_transmission_sf_io = (frameP*10)+subframeP; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.transmission_power = 6000; // 0dB + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_coding = getRIV(N_RB_DL,first_rb,6); + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mcs = 4; // adjust according to size of RAR, 208 bits with N1A_PRB=3 + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pdsch_reptition_levels = 4; // fix to 4 for now + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.redundancy_version = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.new_data_indicator = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_process = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi_length = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_resource_offset = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_subframe_repetition_number = rep; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpc = 2;// N1A_PRB=3; => 208 bits + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index_length = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.allocate_prach_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.preamble_index = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.prach_mask_index = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.starting_ce_level = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.srs_request = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.frequency_hopping_enabled_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.paging_direct_indication_differentiation_flag = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.direct_indication = 0; + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.total_dci_length_including_padding = 0; // this is not needed by OAI L1, but should be filled in + dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_tx_antenna_ports = 1; + RA_template->msg4_mpdcch_repetition_cnt++; + dl_req->number_pdu++; - } - } - - //try here - } - - } else if (RA_template->wait_ack_Msg4==1) { + } //repetition_count==0 && SF condition met + if (RA_template->msg4_mpdcch_repetition_cnt>0) { // we're in a stream of repetitions + RA_template->msg4_mpdcch_repetition_cnt++; + if (RA_template->msg4_mpdcch_repetition_cnt==reps) { // this is the last mpdcch repetition + if (cc[CC_id].tdd_Config==NULL) { // FDD case + // wait 2 subframes for PDSCH transmission + if (subframeP>7) RA_template->Msg4_frame = (frameP+1)&1023; + else RA_template->Msg4_frame = frameP; + RA_template->Msg4_subframe = (subframeP+2)%10; + } + else { + AssertFatal(1==0,"TDD case not done yet\n"); + } + } // mpdcch_repetition_count == reps + if ((RA_template->Msg4_frame == frameP) && (RA_template->Msg4_subframe == subframeP)) { + // Program PDSCH + RA_template->generate_rar = 0; + + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 BR with RRC Piggyback (RA proc %d, RNTI %x)\n", + module_idP, CC_id, frameP, subframeP,i,RA_template->rnti); + + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = RA_template->rnti; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2; // format 1A/1B/1D + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0; // localized + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(N_RB_DL,first_rb,6); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = 2; //QPSK + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = 1;// first block + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = (cc->p_eNB==1 ) ? 0 : 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = ; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = 4; // 0 dB + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = 0; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = (cc->p_eNB==1 ) ? 1 : 2; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = 1; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = 1; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector = ; + + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type = (RA_template->rach_resource_type < 3) ? 1 : 2;; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type = 2; // not SI message + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = (10*frameP)+subframeP; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.drms_table_flag = 0; + dl_req->number_pdu++; + + RA_template->generate_Msg4=0; + RA_template->wait_ack_Msg4=1; + RA_template->RA_active = FALSE; + lcid=0; + + // set HARQ process 0 round to 0 for this UE + UE_list->UE_sched_ctrl[UE_id].round[CC_id] = 0; + + if ((TBsize - rrc_sdu_length - msg4_header) <= 2) { + msg4_padding = TBsize - rrc_sdu_length - msg4_header; + msg4_post_padding = 0; + } else { + msg4_padding = 0; + msg4_post_padding = TBsize - rrc_sdu_length - msg4_header -1; + } + + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", + module_idP,CC_id,frameP,subframeP,TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding); + DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return + // CHECK THIS: &cc[CC_id].CCCH_pdu.payload[0] + offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], + 1, //num_sdus + (unsigned short*)&rrc_sdu_length, // + &lcid, // sdu_lcid + 255, // no drx + 0, // no timing advance + RA_template->cont_res_id, // contention res id + msg4_padding, // no padding + msg4_post_padding); + + memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], + &cc[CC_id].CCCH_pdu.payload[0], + rrc_sdu_length); + + // DL request + eNB->TX_req[CC_id].sfn_sf = (frameP<<3)+subframeP; + TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = rrc_sdu_length; + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = rrc_sdu_length; + TX_req->segments[0].segment_data = eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + + T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(RA_template->rnti), T_INT(frameP), T_INT(subframeP), + T_INT(0 /*harq_pid always 0?*/), T_BUFFER(&eNB->UE_list.DLSCH_pdu[CC_id][0][UE_id].payload[0], TBsize)); + + if (opt_enabled==1) { + trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], + rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id), + eNB->frame, eNB->subframe,0,0); + LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", + module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length); + } + } // Msg4 frame/subframe + } // msg4_mpdcch_repetition_count + } // rach_resource_type > 0 + else +#endif + { + if ((RA_template->Msg4_frame == frameP) && (RA_template->Msg4_subframe == subframeP)) { + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RA proc %d, RNTI %x)\n", + module_idP, CC_id, frameP, subframeP,i,RA_template->rnti); + + first_rb=0; + + vrb_map[first_rb] = 1; + vrb_map[first_rb+1] = 1; + vrb_map[first_rb+2] = 1; + vrb_map[first_rb+3] = 1; + + + memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = RA_template->rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // C-RNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; + + // Compute MCS for 3 PRB + msg4_header = 1+6+1; // CR header, CR CE, SDU header + + + if ((rrc_sdu_length+msg4_header) <= 22) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 4; + TBsize = 22; + } else if ((rrc_sdu_length+msg4_header) <= 28) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 5; + TBsize = 28; + } else if ((rrc_sdu_length+msg4_header) <= 32) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 6; + TBsize = 32; + } else if ((rrc_sdu_length+msg4_header) <= 41) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 7; + TBsize = 41; + } else if ((rrc_sdu_length+msg4_header) <= 49) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 8; + TBsize = 49; + } else if ((rrc_sdu_length+msg4_header) <= 57) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 9; + TBsize = 57; + } + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding= getRIV(N_RB_DL,first_rb,4); + + if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->rnti)) { + dl_req->number_dci++; + dl_req->number_pdu++; + + RA_template->generate_Msg4=0; + RA_template->wait_ack_Msg4=1; + RA_template->RA_active = FALSE; + lcid=0; + + // set HARQ process 0 round to 0 for this UE + UE_list->UE_sched_ctrl[UE_id].round[CC_id] = 0; + + if ((TBsize - rrc_sdu_length - msg4_header) <= 2) { + msg4_padding = TBsize - rrc_sdu_length - msg4_header; + msg4_post_padding = 0; + } else { + msg4_padding = 0; + msg4_post_padding = TBsize - rrc_sdu_length - msg4_header -1; + } + + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", + module_idP,CC_id,frameP,subframeP,TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding); + DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return + // CHECK THIS: &cc[CC_id].CCCH_pdu.payload[0] + offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], + 1, //num_sdus + (unsigned short*)&rrc_sdu_length, // + &lcid, // sdu_lcid + 255, // no drx + 0, // no timing advance + RA_template->cont_res_id, // contention res id + msg4_padding, // no padding + msg4_post_padding); + + memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], + &cc[CC_id].CCCH_pdu.payload[0], + rrc_sdu_length); + + // DL request + eNB->TX_req[CC_id].sfn_sf = (frameP<<3)+subframeP; + TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = rrc_sdu_length; + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = rrc_sdu_length; + TX_req->segments[0].segment_data = eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + + T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(RA_template->rnti), T_INT(frameP), T_INT(subframeP), + T_INT(0 /*harq_pid always 0?*/), T_BUFFER(&eNB->UE_list.DLSCH_pdu[CC_id][0][UE_id].payload[0], TBsize)); + + if (opt_enabled==1) { + trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], + rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id), + eNB->frame, eNB->subframe,0,0); + LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", + module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length); + } + + } // CCE Allocation feasible + } // msg4 frame/subframe + } // else rach_resource_type + } else if (RA_template->wait_ack_Msg4==1) { // check HARQ status and retransmit if necessary - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \tn", - module_idP,CC_id,frameP,subframeP); - // Get candidate harq_pid from PHY - - UE_id = find_UE_id(module_idP,RA_template->rnti); - AssertFatal(UE_id>=0,"Can't find UE for t-crnti\n"); - round = UE_list->UE_sched_ctrl[UE_id].round[CC_id]; - - if (round>0) { - //RA_template->wait_ack_Msg4++; - // we have to schedule a retransmission + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \tn", + module_idP,CC_id,frameP,subframeP); + // Get candidate harq_pid from PHY - first_rb=0; - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = RA_template->rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // C-RNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; - - // Compute MCS for 3 PRB - msg4_header = 1+6+1; // CR header, CR CE, SDU header - - - if ((rrc_sdu_length+msg4_header) <= 22) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 4; - TBsize = 22; - } else if ((rrc_sdu_length+msg4_header) <= 28) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 5; - TBsize = 28; - } else if ((rrc_sdu_length+msg4_header) <= 32) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 6; - TBsize = 32; - } else if ((rrc_sdu_length+msg4_header) <= 41) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 7; - TBsize = 41; - } else if ((rrc_sdu_length+msg4_header) <= 49) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 8; - TBsize = 49; - } else if ((rrc_sdu_length+msg4_header) <= 57) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 9; - TBsize = 57; - } - - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding= getRIV(N_RB_DL,first_rb,4); + UE_id = find_UE_id(module_idP,RA_template->rnti); + AssertFatal(UE_id>=0,"Can't find UE for t-crnti\n"); + round = UE_list->UE_sched_ctrl[UE_id].round[CC_id]; - if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->rnti)) { - dl_req->number_dci++; - dl_req->number_pdu++; + if (round>0) { + +#ifdef Rel14 + AssertFatal(1==0,"Msg4 Retransmissions not handled yet for BL/CE UEs\n"); +#endif + { + if ( (RA_template->Msg4_frame == frameP) && (RA_template->Msg4_subframe == subframeP)) { + + //RA_template->wait_ack_Msg4++; + // we have to schedule a retransmission + + first_rb=0; + vrb_map[first_rb] = 1; + vrb_map[first_rb+1] = 1; + vrb_map[first_rb+2] = 1; + vrb_map[first_rb+3] = 1; + + memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = RA_template->rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // C-RNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0; + + // Compute MCS for 3 PRB + msg4_header = 1+6+1; // CR header, CR CE, SDU header + + + if ((rrc_sdu_length+msg4_header) <= 22) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 4; + TBsize = 22; + } else if ((rrc_sdu_length+msg4_header) <= 28) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 5; + TBsize = 28; + } else if ((rrc_sdu_length+msg4_header) <= 32) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 6; + TBsize = 32; + } else if ((rrc_sdu_length+msg4_header) <= 41) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 7; + TBsize = 41; + } else if ((rrc_sdu_length+msg4_header) <= 49) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 8; + TBsize = 49; + } else if ((rrc_sdu_length+msg4_header) <= 57) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = 9; + TBsize = 57; + } + + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding= getRIV(N_RB_DL,first_rb,4); + + if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->rnti)) { + dl_req->number_dci++; + dl_req->number_pdu++; - LOG_I(MAC,"msg4 retransmission for rnti %x (round %d) fsf %d/%d\n", RA_template->rnti, round, frameP, subframeP); + LOG_I(MAC,"msg4 retransmission for rnti %x (round %d) fsf %d/%d\n", RA_template->rnti, round, frameP, subframeP); + } + else + LOG_I(MAC,"msg4 retransmission for rnti %x (round %d) fsf %d/%d CCE allocation failed!\n", RA_template->rnti, round, frameP, subframeP); + LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n", + module_idP,CC_id,frameP,subframeP,RA_template->rnti); + } + } + + } else { + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_id,frameP,subframeP); + RA_template->wait_ack_Msg4=0; + RA_template->RA_active=FALSE; + UE_id = find_UE_id(module_idP,RA_template->rnti); + DevAssert( UE_id != -1 ); + eNB->UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE; } - else - LOG_I(MAC,"msg4 retransmission for rnti %x (round %d) fsf %d/%d CCE allocation failed!\n", RA_template->rnti, round, frameP, subframeP); - LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n", - module_idP,CC_id,frameP,subframeP,RA_template->rnti); - } else { - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_id,frameP,subframeP); - RA_template->wait_ack_Msg4=0; - RA_template->RA_active=FALSE; - UE_id = find_UE_id(module_idP,RA_template->rnti); - DevAssert( UE_id != -1 ); - eNB->UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE; - } - } + } //wait_ack_Msg4 == 1 + } // RA_active == TRUE } // for i=0 .. N_RA_PROC-1 } // CC_id - + stop_meas(&eNB->schedule_ra); } + // handles the event of MSG1 reception -void initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframeP,uint16_t preamble_index,int16_t timing_offset,uint16_t ra_rnti) +void initiate_ra_proc(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t subframeP, + uint16_t preamble_index, + int16_t timing_offset, + uint16_t ra_rnti +#ifdef Rel14 + , + uint8_t rach_resource_type +#endif + ) { uint8_t i; RA_TEMPLATE *RA_template = (RA_TEMPLATE *)&RC.mac[module_idP]->common_channels[CC_id].RA_template[0]; LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index); +#ifdef Rel14 + LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d PRACH resource type %d\n",module_idP,CC_id,frameP,preamble_index,rach_resource_type); +#endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,0); @@ -518,12 +910,17 @@ void initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, sub_fram if (RA_template[i].RA_active==FALSE && RA_template[i].wait_ack_Msg4 == 0) { int loop = 0; - RA_template[i].RA_active = TRUE; - RA_template[i].generate_rar = 1; - RA_template[i].generate_Msg4 = 0; - RA_template[i].wait_ack_Msg4 = 0; - RA_template[i].timing_offset = timing_offset; - RA_template[i].preamble_subframe = subframeP; + RA_template[i].RA_active = TRUE; + RA_template[i].generate_rar = 1; + RA_template[i].generate_Msg4 = 0; + RA_template[i].wait_ack_Msg4 = 0; + RA_template[i].timing_offset = timing_offset; + RA_template[i].preamble_subframe = subframeP; +#ifdef Rel14 + RA_template[i].rach_resource_type = rach_resource_type; + RA_template[i].msg2_mpdcch_repetition_cnt = 0; + RA_template[i].msg4_mpdcch_repetition_cnt = 0; +#endif /* TODO: find better procedure to allocate RNTI */ do { RA_template[i].rnti = taus(); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index afffd90dd0..dceff068d3 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -208,6 +208,8 @@ void get_Msg3alloc(COMMON_channels_t *cc, } } + + void get_Msg3allocret(COMMON_channels_t *cc, unsigned char current_subframe, unsigned int current_frame, @@ -401,6 +403,67 @@ uint8_t get_Msg3harqpid(COMMON_channels_t *cc, } +#ifdef Rel14 + +int get_numnarrowbands(long dl_Bandwidth) { + int nb_tab[6] = {1,2,4,8,12,16}; + + AssertFatal(dl_Bandwidth<7 || dl_Bandwidth>=0,"dl_Bandwidth not in [0..6]\n"); + return(nb_tab[dl_Bandwidth]); +} + +int get_numnarrowbandbits(long dl_Bandwidth) { + int nbbits_tab[6] = {0,1,2,3,4,4}; + + AssertFatal(dl_Bandwidth<7 || dl_Bandwidth>=0,"dl_Bandwidth not in [0..6]\n"); + return(nbbits_tab[dl_Bandwidth]); +} + +//This implements the frame/subframe condition for first subframe of MPDCCH transmission (Section 9.1.5 36.213, Rel 13/14) +int startSF_fdd_RA_times2[8] = {2,3,4,5,8,10,16,20}; +int startSF_tdd_RA[7] = {1,2,4,5,8,10,20}; + +int mpdcch_sf_condition(eNB_MAC_INST *eNB,int CC_id, frame_t frameP,sub_frame_t subframeP,int rmax,MPDCCH_TYPES_t mpdcch_type) { + + struct PRACH_ConfigSIB_v1310 *ext4_prach = eNB->common_channels[CC_id].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310; + int T; + + switch (mpdcch_type) { + case TYPE0: + AssertFatal(1==0,"MPDCCH Type 0 not handled yet\n"); + break; + case TYPE1: + AssertFatal(1==0,"MPDCCH Type 1 not handled yet\n"); + break; + case TYPE1A: + AssertFatal(1==0,"MPDCCH Type 1A not handled yet\n"); + break; + case TYPE2: // RAR + AssertFatal(ext4_prach->mpdcch_startSF_CSS_RA_r13!=NULL, + "mpdcch_startSF_CSS_RA_r13 is null\n"); + if (eNB->common_channels[CC_id].tdd_Config==NULL) //FDD + T = rmax*startSF_fdd_RA_times2[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.fdd_r13]>>1; + else //TDD + T = rmax*startSF_tdd_RA[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.tdd_r13]; + break; + case TYPE2A: + AssertFatal(1==0,"MPDCCH Type 2A not handled yet\n"); + break; + case TYPEUESPEC: + AssertFatal(1==0,"MPDCCH Type UESPEC not handled yet\n"); + break; + default: + return(0); + } + + if (((10*frameP) + subframeP)%T == 0) return(1); + else return(0); + +} + + +#endif + //------------------------------------------------------------------------------ void init_ue_sched_info(void) //------------------------------------------------------------------------------ diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index ef47b42736..6e5fa91f14 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -171,6 +171,7 @@ int mac_top_init_eNB() RC.nb_macrlc_inst*sizeof(eNB_MAC_INST*),RC.nb_macrlc_inst,sizeof(eNB_MAC_INST)); LOG_D(MAC,"[MAIN] ALLOCATE %zu Bytes for %d eNB_MAC_INST @ %p\n",sizeof(eNB_MAC_INST),RC.nb_macrlc_inst,RC.mac); bzero(RC.mac[i],sizeof(eNB_MAC_INST)); + RC.mac[i]->Mod_id = Mod_id; for (j=0;j<MAX_NUM_CCs;j++) { RC.mac[i]->DL_req[j].dl_config_request_body.dl_config_pdu_list = RC.mac[i]->dl_config_pdu_list[j]; RC.mac[i]->UL_req[j].ul_config_request_body.ul_config_pdu_list = RC.mac[i]->ul_config_pdu_list[j]; @@ -187,6 +188,7 @@ int mac_top_init_eNB() for(Mod_id=0; Mod_id<RC.nb_macrlc_inst; Mod_id++) { mac = RC.mac[Mod_id]; + mac->if_inst = IF_Module_init(Mod_id); UE_list = &mac->UE_list; diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h index 83f07bd306..63e717f90e 100644 --- a/openair2/LAYER2/MAC/proto.h +++ b/openair2/LAYER2/MAC/proto.h @@ -205,8 +205,15 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, uint8_t cooperation_flag, @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 +@param rnti RA rnti corresponding to this PRACH preamble +@param rach_resource type (0=non BL/CE,1 CE level 0,2 CE level 1, 3 CE level 2,4 CE level 3) */ -void initiate_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, sub_frame_t subframeP, uint16_t preamble_index,int16_t timing_offset,uint16_t rnti); +void initiate_ra_proc(module_id_t module_idP,int CC_id,frame_t frameP, sub_frame_t subframeP, uint16_t preamble_index,int16_t timing_offset,uint16_t rnti +#ifdef Rel14 + , + uint8_t rach_resource_type +#endif + ); /* \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 diff --git a/openair2/LAYER2/MAC/rar_tools.c b/openair2/LAYER2/MAC/rar_tools.c index 8ccfa81ceb..d40c3280ef 100644 --- a/openair2/LAYER2/MAC/rar_tools.c +++ b/openair2/LAYER2/MAC/rar_tools.c @@ -129,6 +129,96 @@ unsigned short fill_rar( return(RC.mac[module_idP]->common_channels[CC_id].RA_template[ra_idx].rnti); } +#ifdef Rel14 +//------------------------------------------------------------------------------ +unsigned short fill_rar_br(eNB_MAC_INST *eNB, + const int CC_id, + const int ra_idx, + const frame_t frameP, + const sub_frame_t subframeP, + uint8_t* const dlsch_buffer, + const uint8_t ce_level +) +//------------------------------------------------------------------------------ +{ + + RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)dlsch_buffer; + + uint8_t *rar = (uint8_t *)(dlsch_buffer+1); + int i; + uint8_t nb,rballoc,reps; + uint8_t mcs,TPC,ULdelay,cqireq; + COMMON_channels_t *cc = &eNB->common_channels[CC_id]; + int input_buffer_length; + + + AssertFatal(CC_id < MAX_NUM_CCs, "CC_id %u < MAX_NUM_CCs %u", CC_id, MAX_NUM_CCs); + + AssertFatal(ra_idx >= 0 && ra_idx < 4, "RA index not in [0..3]\n"); + + // subheader fixed + rarh->E = 0; // First and last RAR + rarh->T = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader + rarh->RAPID = cc->RA_template[ra_idx].preamble_index; // Respond to Preamble 0 only for the moment + cc->RA_template[ra_idx].timing_offset /= 16; //T_A = N_TA/16, where N_TA should be on a 30.72Msps + rar[0] = (uint8_t)(cc->RA_template[ra_idx].timing_offset>>(2+4)); // 7 MSBs of timing advance + divide by 4 + rar[1] = (uint8_t)(cc->RA_template[ra_idx].timing_offset<<(4-2))&0xf0; // 4 LSBs of timing advance + divide by 4 + + int N_NB_index; + + AssertFatal(1==0,"RAR for BL/CE Still to be finished ...\n"); + + // Copy the Msg2 narrowband + cc->RA_template[ra_idx].msg34_narrowband = cc->RA_template[ra_idx].msg2_narrowband; + + if (ce_level<2) { //CE Level 0,1, CEmodeA + input_buffer_length =6; + + N_NB_index = get_numnarrowbandbits(cc->mib->message.dl_Bandwidth); + + rar[4] = (uint8_t)(cc->RA_template[ra_idx].rnti>>8); + rar[5] = (uint8_t)(cc->RA_template[ra_idx].rnti&0xff); + //cc->RA_template[ra_idx].timing_offset = 0; + nb = 0; + rballoc = mac_computeRIV(6,1+ra_idx,1); // one PRB only for UL Grant in position 1+ra_idx within Narrowband + rar[1] |= (rballoc&15)<<(4-N_NB_index); // Hopping = 0 (bit 3), 3 MSBs of rballoc + + reps = 4; + mcs = 7; + TPC = 3; // no power increase + ULdelay = 0; + cqireq = 0; + rar[2] |= ((mcs&0x8)>>3); // mcs 10 + rar[3] = (((mcs&0x7)<<5)) | ((TPC&7)<<2) | ((ULdelay&1)<<1) | (cqireq&1); + } + else { // CE level 2,3 => CEModeB + + input_buffer_length =5; + + rar[3] = (uint8_t)(cc->RA_template[ra_idx].rnti>>8); + rar[4] = (uint8_t)(cc->RA_template[ra_idx].rnti&0xff); + } + LOG_D(MAC,"[RAPROC] CC_id %d Frame %d Generating RAR BR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for ra_idx %d, CRNTI %x,preamble %d/%d,TIMING OFFSET %d\n", + CC_id, + frameP, + *(uint8_t*)rarh,rar[0],rar[1],rar[2],rar[3],rar[4],rar[5], + ra_idx, + cc->RA_template[ra_idx].rnti, + rarh->RAPID,cc->RA_template[0].preamble_index, + cc->RA_template[ra_idx].timing_offset); + + if (opt_enabled) { + trace_pdu(1, dlsch_buffer, input_buffer_length, eNB->Mod_id, 2, 1, + eNB->frame, eNB->subframe, 0, 0); + LOG_D(OPT,"[eNB %d][RAPROC] CC_id %d RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n", + eNB->Mod_id, CC_id, frameP, cc->RA_template[ra_idx].rnti, + rarh->RAPID, input_buffer_length); + } + + return(cc->RA_template[ra_idx].rnti); +} +#endif + //------------------------------------------------------------------------------ uint16_t ue_process_rar( diff --git a/openair2/PHY_INTERFACE/IF_Module.c b/openair2/PHY_INTERFACE/IF_Module.c index e52b52203d..bac5878ece 100644 --- a/openair2/PHY_INTERFACE/IF_Module.c +++ b/openair2/PHY_INTERFACE/IF_Module.c @@ -11,6 +11,7 @@ IF_Module_t *if_inst[MAX_IF_MODULES]; Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; void handle_rach(UL_IND_t *UL_info) { + int i; if (UL_info->rach_ind.number_of_preambles>0) { @@ -23,8 +24,34 @@ void handle_rach(UL_IND_t *UL_info) { UL_info->subframe, UL_info->rach_ind.preamble_list[0].preamble_rel8.preamble, UL_info->rach_ind.preamble_list[0].preamble_rel8.timing_advance, - UL_info->rach_ind.preamble_list[0].preamble_rel8.rnti); + UL_info->rach_ind.preamble_list[0].preamble_rel8.rnti +#ifdef Rel14 + ,0 +#endif + ); + } + +#ifdef Rel14 + if (UL_info->rach_ind_br.number_of_preambles>0) { + + AssertFatal(UL_info->rach_ind_br.number_of_preambles<5,"More than 4 preambles not supported\n"); + for (i=0;i<UL_info->rach_ind_br.number_of_preambles;i++) { + AssertFatal(UL_info->rach_ind_br.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.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.preamble_list[i].preamble_rel8.preamble, + UL_info->rach_ind_br.preamble_list[i].preamble_rel8.timing_advance, + UL_info->rach_ind_br.preamble_list[i].preamble_rel8.rnti, + UL_info->rach_ind_br.preamble_list[i].preamble_rel13.rach_resource_type); + } + UL_info->rach_ind.number_of_preambles=0; } +#endif } void handle_ulsch(UL_IND_t *UL_info) { diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h index 9a6915b756..80844b10c8 100644 --- a/openair2/PHY_INTERFACE/IF_Module.h +++ b/openair2/PHY_INTERFACE/IF_Module.h @@ -89,6 +89,11 @@ typedef struct{ /// RACH indication list nfapi_rach_indication_body_t rach_ind; +#ifdef Rel14 + /// RACH indication list for BR UEs + nfapi_rach_indication_body_t rach_ind_br; +#endif + /// SRS indication list nfapi_srs_indication_body_t srs_ind; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 3ba16a32a8..a95342e8b6 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -144,6 +144,9 @@ void init_eNB(int,int); void stop_eNB(int nb_inst); void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe); +#ifdef Rel14 +void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe); +#endif static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) { @@ -153,8 +156,12 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam // Common RX procedures subframe n // if this is IF5 or 3GPP_eNB - if (eNB->RU_list[0]->function < NGFI_RAU_IF4p5) wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx); - + if (eNB->RU_list[0]->function < NGFI_RAU_IF4p5) { + wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx); +#ifdef Rel14 + wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx); +#endif + } // UE-specific RX processing for subframe n phy_procedures_eNB_uespec_RX(eNB, proc, no_relay ); @@ -432,6 +439,67 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { } +#ifdef Rel14 +void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { + + eNB_proc_t *proc = &eNB->proc; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + int i; + + if (ru!=NULL) { + pthread_mutex_lock(&proc->mutex_RU_PRACH_br); + for (i=0;i<eNB->num_RU;i++) { + if (ru == eNB->RU_list[i]) { + LOG_I(PHY,"frame %d, subframe %d: RU %d for eNB %d signals PRACH BR (mask %x, num_RU %d)\n",frame,subframe,i,eNB->Mod_id,proc->RU_mask_prach_br,eNB->num_RU); + if ((proc->RU_mask_prach_br&(1<<i)) > 0) + LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information (PRACH BR) from RU %d (num_RU %d, mask %x) has not been served yet!\n", + eNB->Mod_id,frame,subframe,ru->idx,eNB->num_RU,proc->RU_mask_prach_br); + proc->RU_mask_prach_br |= (1<<i); + } + } + if (proc->RU_mask_prach_br != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return + pthread_mutex_unlock(&proc->mutex_RU_PRACH_br); + return(0); + } + else { // all RUs have provided their information so continue on and wakeup eNB processing + proc->RU_mask_prach_br = 0; + pthread_mutex_unlock(&proc->mutex_RU_PRACH_br); + } + } + + // check if we have to detect PRACH first + if (is_prach_subframe(fp,frame,subframe)>0) { + LOG_D(PHY,"Triggering prach br processing, frame %d, subframe %d\n",frame,subframe); + if (proc->instance_cnt_prach_br == 0) { + LOG_W(PHY,"[eNB] Frame %d Subframe %d, dropping PRACH BR\n", frame,subframe); + return; + } + + // wake up thread for PRACH RX + if (pthread_mutex_lock(&proc->mutex_prach_br) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach_br); + exit_fun( "error locking mutex_prach" ); + return; + } + + ++proc->instance_cnt_prach_br; + // set timing for prach thread + proc->frame_prach_br = frame; + proc->subframe_prach_br = subframe; + + // the thread can now be woken up + if (pthread_cond_signal(&proc->cond_prach_br) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH BR thread %d\n", proc->thread_index); + exit_fun( "ERROR pthread_cond_signal" ); + return; + } + + pthread_mutex_unlock( &proc->mutex_prach_br ); + } + +} +#endif + /*! * \brief The prach receive thread of eNB. * \param param is a \ref eNB_proc_t structure which contains the info what to process. @@ -457,7 +525,11 @@ static void* eNB_thread_prach( void* param ) { if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break; LOG_D(PHY,"Running eNB prach procedures\n"); - prach_procedures(eNB); + prach_procedures(eNB +#ifdef Rel14 + ,0 +#endif + ); if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break; } @@ -468,6 +540,44 @@ static void* eNB_thread_prach( void* param ) { return &eNB_thread_prach_status; } +#ifdef Rel14 +/*! + * \brief The prach receive thread of eNB for BL/CE UEs. + * \param param is a \ref eNB_proc_t structure which contains the info what to process. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +static void* eNB_thread_prach_br( void* param ) { + static int eNB_thread_prach_status; + + + PHY_VARS_eNB *eNB= (PHY_VARS_eNB *)param; + eNB_proc_t *proc = &eNB->proc; + + // set default return value + eNB_thread_prach_status = 0; + + thread_top_init("eNB_thread_prach_br",1,500000L,1000000L,20000000L); + + while (!oai_exit) { + + if (oai_exit) break; + + + if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break; + + LOG_D(PHY,"Running eNB prach procedures for BL/CE UEs\n"); + prach_procedures(eNB,1); + + if (release_thread(&proc->mutex_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break; + } + + LOG_I(PHY, "Exiting eNB thread PRACH BR\n"); + + eNB_thread_prach_status = 0; + return &eNB_thread_prach_status; +} + +#endif extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *); @@ -482,6 +592,9 @@ void init_eNB_proc(int inst) { eNB_proc_t *proc; eNB_rxtx_proc_t *proc_rxtx; pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL,*attr_te=NULL,*attr_synch=NULL; +#ifdef Rel14 + pthread_attr_t *attr_prach_br=NULL; +#endif for (CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) { eNB = RC.eNB[inst][CC_id]; @@ -523,10 +636,22 @@ void init_eNB_proc(int inst) { pthread_attr_init( &proc->attr_te); pthread_attr_init( &proc_rxtx[0].attr_rxtx); pthread_attr_init( &proc_rxtx[1].attr_rxtx); +#ifdef Rel14 + proc->instance_cnt_prach_br = -1; + proc->RU_mask_prach_br=0; + pthread_mutex_init( &proc->mutex_prach_br, NULL); + pthread_mutex_init( &proc->mutex_RU_PRACH_br,NULL); + pthread_cond_init( &proc->cond_prach_br, NULL); + pthread_attr_init( &proc->attr_prach_br); +#endif #ifndef DEADLINE_SCHEDULER attr0 = &proc_rxtx[0].attr_rxtx; attr1 = &proc_rxtx[1].attr_rxtx; attr_prach = &proc->attr_prach; +#ifdef Rel14 + attr_prach_br = &proc->attr_prach_br; +#endif + attr_asynch = &proc->attr_asynch_rxtx; attr_single = &proc->attr_single; attr_td = &proc->attr_td; @@ -538,7 +663,9 @@ void init_eNB_proc(int inst) { pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] ); } pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, eNB ); - +#ifdef Rel14 + pthread_create( &proc->pthread_prach_br, attr_prach_br, eNB_thread_prach_br, eNB ); +#endif char name[16]; if (eNB->single_thread_flag==0) { snprintf( name, sizeof(name), "RXTX0 %d", i ); @@ -601,10 +728,18 @@ void kill_eNB_proc(int inst) { pthread_cond_signal( &proc_rxtx[0].cond_rxtx ); pthread_cond_signal( &proc_rxtx[1].cond_rxtx ); pthread_cond_signal( &proc->cond_prach ); + pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); pthread_join( proc->pthread_prach, (void**)&status ); + pthread_mutex_destroy( &proc->mutex_prach ); - pthread_cond_destroy( &proc->cond_prach ); + pthread_cond_destroy( &proc->cond_prach ); +#ifdef Rel14 + pthread_cond_signal( &proc->cond_prach_br ); + pthread_join( proc->pthread_prach_br, (void**)&status ); + pthread_mutex_destroy( &proc->mutex_prach_br ); + pthread_cond_destroy( &proc->cond_prach_br ); +#endif pthread_mutex_destroy(&eNB->UL_INFO_mutex); int i; for (i=0;i<2;i++) { @@ -756,11 +891,13 @@ void init_eNB_afterRU() { AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id); - RC.ru[ru_id]->wakeup_rxtx = wakeup_rxtx; - RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_eNB; - RC.ru[ru_id]->eNB_top = eNB_top; + RC.ru[ru_id]->wakeup_rxtx = wakeup_rxtx; + RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_eNB; + RC.ru[ru_id]->wakeup_prach_eNB_br = wakeup_prach_eNB_br; + RC.ru[ru_id]->eNB_top = eNB_top; } } + void init_eNB(int single_thread_flag,int wait_for_sync) { int CC_id; diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 6ee6633b3e..2d72b1d745 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -479,15 +479,19 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) { uint16_t packet_type; uint32_t symbol_number,symbol_mask,symbol_mask_full,prach_rx; - + uint32_t got_prach_info=0; symbol_number = 0; - symbol_mask = 0; - symbol_mask_full = (1<<fp->symbols_per_tti)-1; - prach_rx = 0; + symbol_mask = (1<<fp->symbols_per_tti)-1; + prach_rx = 0; do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! recv_IF4p5(ru, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); + // grab first prach information for this new subframe + if (got_prach_info==0) { + prach_rx = is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx); + got_prach_info = 1; + } if (proc->first_rx != 0) { *frame = proc->frame_rx; *subframe = proc->subframe_rx; @@ -503,13 +507,15 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) { exit_fun("Exiting"); } } - if (packet_type == IF4p5_PULFFT) { - symbol_mask = symbol_mask | (1<<symbol_number); - prach_rx = (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>0) ? 1 : 0; - } else if (packet_type == IF4p5_PRACH) { - prach_rx = 0; - } - } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1)); + if (packet_type == IF4p5_PULFFT) symbol_mask &= (~(1<<symbol_number)); + else if (packet_type == IF4p5_PRACH) prach_rx &= (~0x1); +#ifdef Rel14 + else if (packet_type == IF4p5_PRACH_BR_CE0) prach_rx &= (~0x2); + else if (packet_type == IF4p5_PRACH_BR_CE1) prach_rx &= (~0x4); + else if (packet_type == IF4p5_PRACH_BR_CE2) prach_rx &= (~0x8); + else if (packet_type == IF4p5_PRACH_BR_CE3) prach_rx &= (~0x10); +#endif + } while( (symbol_mask > 0) || (prach_rx >0)); // haven't received all PUSCH symbols and PRACH information } @@ -895,19 +901,59 @@ static void* ru_thread_prach( void* param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); rx_prach(NULL, ru, + NULL, NULL, NULL, proc->frame_prach, - 0); + 0 +#ifdef Rel14 + ,0 +#endif + ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 ); if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; } - printf( "Exiting RU thread PRACH\n"); + LOG_I(PHY, "Exiting RU thread PRACH\n"); + + ru_thread_prach_status = 0; + return &ru_thread_prach_status; +} + +#ifdef Rel14 +static void* ru_thread_prach_br( void* param ) { + + static int ru_thread_prach_status; + + RU_t *ru = (RU_t*)param; + RU_proc_t *proc = (RU_proc_t*)&ru->proc; + + // set default return value + ru_thread_prach_status = 0; + + thread_top_init("ru_thread_prach_br",1,500000L,1000000L,20000000L); + + while (!oai_exit) { + + if (oai_exit) break; + if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"ru_prach_thread_br") < 0) break; + rx_prach(NULL, + ru, + NULL, + NULL, + NULL, + proc->frame_prach_br, + 0, + 1); + if (release_thread(&proc->mutex_prach_br,&proc->instance_cnt_prach_br,"ru_prach_thread_br") < 0) break; + } + + LOG_I(PHY, "Exiting RU thread PRACH BR\n"); ru_thread_prach_status = 0; return &ru_thread_prach_status; } +#endif int wakeup_synch(RU_t *ru){ @@ -1058,6 +1104,35 @@ static inline int wakeup_prach_ru(RU_t *ru) { return(0); } +#ifdef Rel14 +static inline int wakeup_prach_ru_br(RU_t *ru) { + + struct timespec wait; + + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + if (pthread_mutex_timedlock(&ru->proc.mutex_prach_br,&wait) !=0) { + LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread BR (IC %d)\n", ru->proc.instance_cnt_prach_br); + exit_fun( "error locking mutex_rxtx" ); + return(-1); + } + if (ru->proc.instance_cnt_prach_br==-1) { + ++ru->proc.instance_cnt_prach_br; + ru->proc.frame_prach_br = ru->proc.frame_rx; + ru->proc.subframe_prach_br = ru->proc.subframe_rx; + + LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx); + // the thread can now be woken up + AssertFatal(pthread_cond_signal(&ru->proc.cond_prach_br) == 0, "ERROR pthread_cond_signal for RU prach thread BR\n"); + } + else LOG_W(PHY,"RU prach thread busy, skipping\n"); + pthread_mutex_unlock( &ru->proc.mutex_prach_br ); + + return(0); +} +#endif + static void* ru_thread( void* param ) { static int ru_thread_status; @@ -1150,10 +1225,10 @@ static void* ru_thread( void* param ) { is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx), proc->frame_rx,proc->subframe_rx); - if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>0)) - wakeup_prach_ru(ru); - - + if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)==1)) wakeup_prach_ru(ru); +#ifdef Rel14 + else if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>1)) wakeup_prach_ru_br(ru); +#endif // adjust for timing offset between RU if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; @@ -1298,7 +1373,9 @@ void init_RU_proc(RU_t *ru) { RU_proc_t *proc; pthread_attr_t *attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_synch=NULL; //pthread_attr_t *attr_fep=NULL; - +#ifdef Rel14 + pthread_attr_t *attr_prach_br=NULL; +#endif char name[100]; #ifndef OCP_FRAMEWORK @@ -1335,32 +1412,37 @@ void init_RU_proc(RU_t *ru) { pthread_attr_init( &proc->attr_synch); pthread_attr_init( &proc->attr_asynch_rxtx); pthread_attr_init( &proc->attr_fep); - + +#ifdef Rel14 + proc->instance_cnt_prach_br = -1; + pthread_mutex_init( &proc->mutex_prach_br, NULL); + pthread_cond_init( &proc->cond_prach_br, NULL); + pthread_attr_init( &proc->attr_prach_br); +#endif #ifndef DEADLINE_SCHEDULER - attr_FH = &proc->attr_FH; - attr_prach = &proc->attr_prach; - attr_synch = &proc->attr_synch; - attr_asynch = &proc->attr_asynch_rxtx; - // attr_fep = &proc->attr_fep; + attr_FH = &proc->attr_FH; + attr_prach = &proc->attr_prach; + attr_synch = &proc->attr_synch; + attr_asynch = &proc->attr_asynch_rxtx; +#ifdef Rel14 + attr_prach_br = &proc->attr_prach_br; +#endif #endif pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void*)ru ); if (ru->function == NGFI_RRU_IF4p5) { pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru ); - +#ifdef Rel14 + pthread_create( &proc->pthread_prach_br, attr_prach_br, ru_thread_prach_br, (void*)ru ); +#endif if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru); if ((ru->if_timing == synch_to_other) || (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) - - - pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, ru_thread_asynch_rxtx, (void*)ru ); - - + (ru->function == NGFI_RRU_IF4p5)) pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, ru_thread_asynch_rxtx, (void*)ru ); snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx ); pthread_setname_np( proc->pthread_FH, name ); @@ -1563,6 +1645,7 @@ void configure_ru(int idx, RRU_config_t *config = (RRU_config_t *)arg; RRU_capabilities_t *capabilities = (RRU_capabilities_t*)arg; int ret; + int i; LOG_I(PHY, "Received capabilities from RRU %d\n",idx); @@ -1588,6 +1671,13 @@ void configure_ru(int idx, LOG_I(PHY,"REMOTE_IF4p5: prach_FrequOffset %d, prach_ConfigIndex %d\n", config->prach_FreqOffset[0],config->prach_ConfigIndex[0]); +#ifdef Rel14 + for (i=0;i<4;i++) { + config->emtc_prach_CElevel_enable[0][i] = ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i]; + config->emtc_prach_FreqOffset[0][i] = ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[i]; + config->emtc_prach_ConfigIndex[0][i] = ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i]; + } +#endif } // take antenna capabilities of RRU ru->nb_tx = capabilities->nb_tx[0]; @@ -1621,6 +1711,13 @@ void configure_rru(int idx, config->prach_FreqOffset[0],config->prach_ConfigIndex[0]); ru->frame_parms.prach_config_common.prach_ConfigInfo.prach_FreqOffset = config->prach_FreqOffset[0]; ru->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex = config->prach_ConfigIndex[0]; +#ifdef Rel14 + for (int i=0;i<4;i++) { + ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i] = config->emtc_prach_CElevel_enable[0][i]; + ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[i] = config->emtc_prach_FreqOffset[0][i]; + ru->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_ConfigIndex[i] = config->emtc_prach_ConfigIndex[0][i]; + } +#endif } init_frame_parms(&ru->frame_parms,1); -- GitLab