diff --git a/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf b/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf index ab5cd5ac69..fb227fbaab 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf @@ -118,7 +118,8 @@ gNBs = pucchGroupHopping = 0; hoppingId = 40; p0_nominal = -70; - n_TimingAdvanceOffset = 0; + # TimingAdvanceOffset_n25600 + n_TimingAdvanceOffset = 1; ssb_PositionsInBurst_Bitmap = 1; diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index f851c26eee..fafc1bcd47 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1149,6 +1149,20 @@ void init_delay_table(uint16_t ofdm_symbol_size, } } +int set_default_nta_offset(frequency_range_t freq_range, uint32_t samples_per_subframe) +{ + // ta_offset_samples : ta_offset = samples_per_subframe : (Δf_max x N_f / 1000) + // As described in Section 4.3.1 in 38.211 + + // TODO There is no way for the UE to know about LTE-NR coexistence case + // as mentioned in Table 7.1.2-2 of 38.133 + // LTE-NR coexistence means the presence of an active LTE service in the same band as NR in current deployment + // We assume no coexistence + + uint64_t numer = (freq_range == FR1 ? 25600 : 13792) * (uint64_t)samples_per_subframe; + return numer / (4096 * 480); +} + void nr_timer_start(NR_timer_t *timer) { timer->active = true; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 3c04bca581..1e4fecc4f5 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -177,7 +177,7 @@ bool nr_timer_is_active(const NR_timer_t *timer); */ uint32_t nr_timer_elapsed_time(const NR_timer_t *timer); - +int set_default_nta_offset(frequency_range_t freq_range, uint32_t samples_per_subframe); extern const nr_bandentry_t nr_bandtable[]; static inline int get_num_dmrs(uint16_t dmrs_mask ) diff --git a/doc/SW_archi.md b/doc/SW_archi.md index 277b4e3a9e..b186bea524 100644 --- a/doc/SW_archi.md +++ b/doc/SW_archi.md @@ -98,12 +98,6 @@ The infinite loop: raw incoming data is in buffer called "rxdata" We derivate frame number, slot number, ... from the RX timestamp {: .func2} -## nr_fep_full() -"front end processing" of uplink signal -performs DFT on the signal -it computes the buffer rxdataF (for frequency) from rxdata (samples over time) -rxdataF is the rxdata in frequency domain, phase aligned -{: .func3} ## gNB_top() only compute frame numbre, slot number, ... {: .func3} diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 8a29e6ac2f..7f5d193d34 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -959,43 +959,10 @@ int setup_RU_buffers(RU_t *ru) { int mu = config->ssb_config.scs_common.value; int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; - if (config->cell_config.frame_duplex_type.value == TDD) { - int N_TA_offset = config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 - double factor=1; - - switch (mu) { - case 0: //15 kHz scs - AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n"); - factor = fp->samples_per_subframe / 30720.0; - break; - - case 1: //30 kHz sc - AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n"); - factor = fp->samples_per_subframe / 30720.0; - break; - - case 2: //60 kHz scs - AssertFatal(1==0, "scs_common should not be 60 kHz\n"); - break; - - case 3: //120 kHz scs - AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n"); - factor = fp->samples_per_subframe / 61440.0; - break; - - case 4: //240 kHz scs - AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n"); - factor = fp->samples_per_subframe / 61440.0; - break; - - default: - AssertFatal(1==0, "Invalid scs_common!\n"); - } - - ru->N_TA_offset = (int)(N_TA_offset * factor); - LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d, mu %d)\n",ru->idx,ru->N_TA_offset,factor, - config->carrier_config.uplink_frequency.value, N_RB, mu); - } else ru->N_TA_offset = 0; + ru->N_TA_offset = set_default_nta_offset(fp->freq_range, fp->samples_per_subframe); + LOG_I(PHY, + "RU %d Setting N_TA_offset to %d samples (UL Freq %d, N_RB %d, mu %d)\n", + ru->idx, ru->N_TA_offset, config->carrier_config.uplink_frequency.value, N_RB, mu); if (ru->openair0_cfg.mmapped_dma == 1) { // replace RX signal buffers with mmaped HW versions diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 1c0c596253..f0d9b73e63 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -550,6 +550,7 @@ typedef struct { int ta_frame; int ta_slot; int ta_command; + int ta_offset; bool is_rar; } fapi_nr_ta_command_pdu; diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 3985efb9b7..577f7a44d8 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -499,47 +499,21 @@ void clean_UE_harq(PHY_VARS_NR_UE *UE) } -void init_N_TA_offset(PHY_VARS_NR_UE *ue){ - +void init_N_TA_offset(PHY_VARS_NR_UE *ue) +{ NR_DL_FRAME_PARMS *fp = &ue->frame_parms; // No timing offset for Sidelink, refer to 3GPP 38.211 Section 8.5 - if (fp->frame_type == FDD || ue->sl_mode == 2) { + if (ue->sl_mode == 2) ue->N_TA_offset = 0; - } else { - int N_TA_offset = fp->ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 + else + ue->N_TA_offset = set_default_nta_offset(fp->freq_range, fp->samples_per_subframe); + ue->ta_frame = -1; + ue->ta_slot = -1; - double factor = 1.0; - switch (fp->numerology_index) { - case 0: //15 kHz scs - AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n"); - factor = fp->samples_per_subframe / 30720.0; - break; - case 1: //30 kHz sc - AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n"); - factor = fp->samples_per_subframe / 30720.0; - break; - case 2: //60 kHz scs - AssertFatal(1==0, "scs_common should not be 60 kHz\n"); - break; - case 3: //120 kHz scs - AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n"); - factor = fp->samples_per_subframe / 61440.0; - break; - case 4: //240 kHz scs - AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n"); - factor = fp->samples_per_subframe / 61440.0; - break; - default: - AssertFatal(1==0, "Invalid scs_common!\n"); - } - - ue->N_TA_offset = (int)(N_TA_offset * factor); - ue->ta_frame = -1; - ue->ta_slot = -1; - - LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d, mu %d)\n", ue->Mod_id, ue->N_TA_offset, factor, fp->ul_CarrierFreq, fp->N_RB_DL, fp->numerology_index); - } + LOG_I(PHY, + "UE %d Setting N_TA_offset to %d samples (UL Freq %lu, N_RB %d, mu %d)\n", + ue->Mod_id, ue->N_TA_offset, fp->ul_CarrierFreq, fp->N_RB_DL, fp->numerology_index); } void phy_init_nr_top(PHY_VARS_NR_UE *ue) { diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 6a2c300b72..939478f35c 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -316,7 +316,7 @@ void nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, NR_DL_FRAME_PARMS * fp->get_samples_slot_timestamp = &get_samples_slot_timestamp; fp->get_slot_from_timestamp = &get_slot_from_timestamp; fp->samples_per_frame = 10 * fp->samples_per_subframe; - fp->freq_range = (fp->dl_CarrierFreq < 6e9)? FR1 : FR2; + fp->freq_range = (fp->dl_CarrierFreq < 6e9) ? FR1 : FR2; fp->Ncp = Ncp; @@ -400,7 +400,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->get_samples_per_slot = &get_samples_per_slot; fp->get_samples_slot_timestamp = &get_samples_slot_timestamp; fp->samples_per_frame = 10 * fp->samples_per_subframe; - fp->freq_range = (fp->dl_CarrierFreq < 6e9)? FR1 : FR2; + fp->freq_range = (fp->dl_CarrierFreq < 6e9) ? FR1 : FR2; uint8_t sco = 0; if (((fp->freq_range == FR1) && (config->ssb_table.ssb_subcarrier_offset < 24)) || diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index 16a06c6e97..2b26848170 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -224,42 +224,6 @@ void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx) { stop_meas(&ru->precoding_stats); } - -void nr_fep_full(RU_t *ru, int slot) { - - RU_proc_t *proc = &ru->proc; - int l, aa; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - - // if ((fp->frame_type == TDD) && - // (subframe_select(fp,proc->tti_rx) != NR_UPLINK_SLOT)) return; - - LOG_D(PHY,"In fep_full for slot = %d\n", proc->tti_rx); - - start_meas(&ru->ofdm_demod_stats); - if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 ); - - - // remove_7_5_kHz(ru,proc->tti_rx<<1); - // remove_7_5_kHz(ru,1+(proc->tti_rx<<1)); - int offset = (proc->tti_rx % RU_RX_SLOT_DEPTH) * (fp->symbols_per_slot * fp->ofdm_symbol_size); - for (l = 0; l < fp->symbols_per_slot; l++) { - for (aa = 0; aa < fp->nb_antennas_rx; aa++) { - nr_slot_fep_ul(fp, - ru->common.rxdata[aa], - &ru->common.rxdataF[aa][offset], - l, - proc->tti_rx, - ru->N_TA_offset); - } - } - - if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 0 ); - stop_meas(&ru->ofdm_demod_stats); - - -} - // core routine for FEP TX, called from threads in RU TX thread-pool void nr_feptx(void *arg) { @@ -363,8 +327,8 @@ void nr_feptx_tp(RU_t *ru, int frame_tx, int slot) { } // core RX FEP routine, called by threads in RU thread-pool -void nr_fep(void* arg) { - +void nr_fep(void* arg) +{ feprx_cmd_t *feprx_cmd = (feprx_cmd_t *)arg; RU_t *ru = feprx_cmd->ru; diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index 4e1c7e2509..c31d3669a4 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -40,10 +40,8 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx); void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa); -void fep_full(RU_t *ru,int slot); void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx); void nr_feptx_prec_control(RU_t *ru,int frame,int tti_tx); -void nr_fep_full(RU_t *ru, int slot); void nr_fep_tp(RU_t *ru, int slot); void nr_feptx_tp(RU_t *ru, int frame_tx, int slot); void feptx_prec(RU_t *ru,int frame_tx,int tti_tx); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 312d5778b3..32fa53cc60 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -328,7 +328,6 @@ static void configure_dlsch(NR_UE_DLSCH_t *dlsch0, static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_command_pdu) { - /* Time Alignment procedure // - UE processing capability 1 // - Setting the TA update to be applied after the reception of the TA command @@ -369,7 +368,7 @@ static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_ /* Time alignment procedure */ // N_t_1 + N_t_2 + N_TA_max must be in msec const double t_subframe = 1.0; // subframe duration of 1 msec - const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe*(N_t_1 + N_t_2 + N_TA_max + 0.5)/t_subframe); + const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe * (N_t_1 + N_t_2 + N_TA_max + 0.5) / t_subframe); if (ta_command_pdu->is_rar) { ue->ta_slot = ta_command_pdu->ta_slot; @@ -383,8 +382,19 @@ static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_ ue->ta_frame = ta_command_pdu->ta_frame; ue->ta_command = ta_command_pdu->ta_command; } - LOG_D(PHY,"TA command received in Frame.Slot %d.%d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", + + LOG_D(PHY, + "TA command received in %d.%d Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", ta_command_pdu->ta_frame, ta_command_pdu->ta_slot, ue->ta_frame, ue->ta_slot); + + if (ta_command_pdu->ta_offset != -1) { + // ta_offset_samples : ta_offset = samples_per_subframe : (Δf_max x N_f / 1000) + // As described in Section 4.3.1 in 38.211 + int ta_offset_samples = (ta_command_pdu->ta_offset * samples_per_subframe) / (4096 * 480); + ue->N_TA_offset = ta_offset_samples; + LOG_D(PHY, "Received N_TA offset %d from upper layers. Corresponds to %d samples.\n", + ta_command_pdu->ta_offset, ta_offset_samples); + } } static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 0958172537..fab0fb7a7c 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1545,6 +1545,45 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up } } +static void configure_timeAlignmentTimer(NR_timer_t *time_alignment_timer, NR_TimeAlignmentTimer_t timer_config, int scs) +{ + uint32_t timer_ms = 0; + switch (timer_config) { + case NR_TimeAlignmentTimer_ms500 : + timer_ms = 500; + break; + case NR_TimeAlignmentTimer_ms750 : + timer_ms = 750; + break; + case NR_TimeAlignmentTimer_ms1280 : + timer_ms = 1280; + break; + case NR_TimeAlignmentTimer_ms1920 : + timer_ms = 1920; + break; + case NR_TimeAlignmentTimer_ms2560 : + timer_ms = 2560; + break; + case NR_TimeAlignmentTimer_ms5120 : + timer_ms = 5120; + break; + case NR_TimeAlignmentTimer_ms10240 : + timer_ms = 10240; + break; + case NR_TimeAlignmentTimer_infinity : + timer_ms = UINT_MAX; + break; + default : + AssertFatal(false, "Invalid timeAlignmentTimer\n"); + } + // length of slot is (1/2^scs)ms + uint32_t n_slots = timer_ms != UINT_MAX ? (timer_ms << scs) : UINT_MAX; + bool timer_was_active = nr_timer_is_active(time_alignment_timer); + nr_timer_setup(time_alignment_timer, n_slots, 1); // 1 slot update rate + if (timer_was_active) + nr_timer_start(time_alignment_timer); +} + void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause) { @@ -1577,6 +1616,8 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, nr_ue_mac_default_configs(mac); nr_ue_reset_sync_state(mac); release_mac_configuration(mac, cause); + // apply the timeAlignmentTimerCommon included in SIB1 + configure_timeAlignmentTimer(&mac->time_alignment_timer, mac->timeAlignmentTimerCommon, mac->current_UL_BWP->scs); // new sync with old cell ID (re-establishment on the same cell) sync_req.target_Nid_cell = mac->physCellId; sync_req.ssb_bw_scan = false; @@ -1587,6 +1628,24 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, } } +static int get_ta_offset(long *n_TimingAdvanceOffset) +{ + if (!n_TimingAdvanceOffset) + return -1; + + switch (*n_TimingAdvanceOffset) { + case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n0 : + return 0; + case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n25600 : + return 25600; + case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n39936 : + return 39936; + default : + AssertFatal(false, "Invalid n-TimingAdvanceOffset\n"); + } + return -1; +} + void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SI_SchedulingInfo_t *si_SchedulingInfo, @@ -1599,15 +1658,18 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t); UPDATE_IE(mac->si_SchedulingInfo, si_SchedulingInfo, NR_SI_SchedulingInfo_t); UPDATE_IE(mac->si_SchedulingInfo_v1700, si_SchedulingInfo_v1700, NR_SI_SchedulingInfo_v1700_t); + mac->n_ta_offset = get_ta_offset(scc->n_TimingAdvanceOffset); config_common_ue_sa(mac, scc, cc_idP); configure_common_BWP_dl(mac, 0, // bwp-id &scc->downlinkConfigCommon.initialDownlinkBWP); - if (scc->uplinkConfigCommon) + if (scc->uplinkConfigCommon) { + mac->timeAlignmentTimerCommon = scc->uplinkConfigCommon->timeAlignmentTimerCommon; configure_common_BWP_ul(mac, 0, // bwp-id &scc->uplinkConfigCommon->initialUplinkBWP); + } // set current BWP only if coming from non-connected state // otherwise it is just a periodically update of the SIB1 content if (mac->state < UE_CONNECTED) { @@ -1615,6 +1677,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, AssertFatal(mac->current_DL_BWP, "Couldn't find DL-BWP0\n"); mac->current_UL_BWP = get_ul_bwp_structure(mac, 0, false); AssertFatal(mac->current_UL_BWP, "Couldn't find DL-BWP0\n"); + configure_timeAlignmentTimer(&mac->time_alignment_timer, mac->timeAlignmentTimerCommon, mac->current_UL_BWP->scs); } // Setup the SSB to Rach Occasions mapping according to the config @@ -1652,6 +1715,7 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, if (reconfigurationWithSync->spCellConfigCommon) { NR_ServingCellConfigCommon_t *scc = reconfigurationWithSync->spCellConfigCommon; + mac->n_ta_offset = get_ta_offset(scc->n_TimingAdvanceOffset); if (scc->physCellId) mac->physCellId = *scc->physCellId; mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position; @@ -1939,12 +2003,29 @@ static void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroup } } if (mcg->tag_Config) { - // TODO TAG not handled - if(mcg->tag_Config->tag_ToAddModList) { + if (mcg->tag_Config->tag_ToReleaseList) { + for (int i = 0; i < mcg->tag_Config->tag_ToReleaseList->list.count; i++) { + for (int j = 0; j < mac->TAG_list.count; j++) { + if (*mcg->tag_Config->tag_ToReleaseList->list.array[i] == mac->TAG_list.array[j]->tag_Id) + asn_sequence_del(&mac->TAG_list, j, 1); + } + } + } + if (mcg->tag_Config->tag_ToAddModList) { for (int i = 0; i < mcg->tag_Config->tag_ToAddModList->list.count; i++) { - if (mcg->tag_Config->tag_ToAddModList->list.array[i]->timeAlignmentTimer != - NR_TimeAlignmentTimer_infinity) - LOG_E(NR_MAC, "TimeAlignmentTimer not handled\n"); + int j; + for (j = 0; j < mac->TAG_list.count; j++) { + if (mac->TAG_list.array[j]->tag_Id == mcg->tag_Config->tag_ToAddModList->list.array[i]->tag_Id) + break; + } + if (j < mac->TAG_list.count) { + UPDATE_IE(mac->TAG_list.array[j], mcg->tag_Config->tag_ToAddModList->list.array[i], NR_TAG_t); + } + else { + NR_TAG_t *local_tag = NULL; + UPDATE_IE(local_tag, mcg->tag_Config->tag_ToAddModList->list.array[i], NR_TAG_t); + ASN_SEQUENCE_ADD(&mac->TAG_list, local_tag); + } } } } @@ -2428,6 +2509,7 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, handle_reconfiguration_with_sync(mac, cc_idP, spCellConfig->reconfigurationWithSync); } if (scd) { + mac->tag_Id = scd->tag_Id; configure_servingcell_info(mac, scd); configure_BWPs(mac, scd); } @@ -2436,6 +2518,12 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, if (cell_group_config->mac_CellGroupConfig) configure_maccellgroup(mac, cell_group_config->mac_CellGroupConfig); + for (int j = 0; j < mac->TAG_list.count; j++) { + // apply the Timing Advance Command for the indicated TAG + if (mac->TAG_list.array[j]->tag_Id == mac->tag_Id) + configure_timeAlignmentTimer(&mac->time_alignment_timer, mac->TAG_list.array[j]->timeAlignmentTimer, mac->current_UL_BWP->scs); + } + configure_logicalChannelBearer(mac, cell_group_config->rlc_BearerToAddModList, cell_group_config->rlc_BearerToReleaseList); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index fb727aeb5e..d9c5fa2345 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -76,7 +76,6 @@ #define NR_INVALID_LCGID (NR_MAX_NUM_LCGID) #define MAX_NUM_BWP_UE 5 -#define NUM_SLOT_FRAME 10 #define NR_MAX_SR_ID 8 // SchedulingRequestId ::= INTEGER (0..7) /*!\brief value for indicating BSR Timer is not running */ @@ -424,10 +423,9 @@ typedef enum ta_type { } ta_type_t; typedef struct NR_UL_TIME_ALIGNMENT { - /// TA command and TAGID received from the gNB + /// TA command received from the gNB ta_type_t ta_apply; int ta_command; - uint32_t tag_id; int frame; int slot; } NR_UL_TIME_ALIGNMENT_t; @@ -576,6 +574,7 @@ typedef struct NR_UE_MAC_INST_s { int dmrs_TypeA_Position; int p_Max; int p_Max_alt; + int n_ta_offset; // -1 not present, otherwise value to be applied long pdsch_HARQ_ACK_Codebook; @@ -594,6 +593,11 @@ typedef struct NR_UE_MAC_INST_s { NR_UE_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES]; NR_UL_HARQ_INFO_t ul_harq_info[NR_MAX_HARQ_PROCESSES]; + NR_TAG_Id_t tag_Id; + A_SEQUENCE_OF(NR_TAG_t) TAG_list; + NR_TimeAlignmentTimer_t timeAlignmentTimerCommon; + NR_timer_t time_alignment_timer; + nr_emulated_l1_t nr_ue_emul_l1; pthread_mutex_t mutex_dl_info; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index bb42701ec3..e2d6125145 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -349,8 +349,9 @@ void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id); void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac); void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac); void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id); +void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac); void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); - +void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac); int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, NR_PDSCH_Config_t *pdsch_Config, diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index e60c163236..a60d8d2c43 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -69,6 +69,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) mac->uecap_maxMIMO_PUSCH_layers_nocb = 0; mac->p_Max = INT_MIN; mac->p_Max_alt = INT_MIN; + mac->n_ta_offset = -1; reset_mac_inst(mac); // need to inizialize because might not been setup (optional timer) @@ -201,6 +202,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) } if (nr_mac->data_inactivity_timer) nr_timer_stop(nr_mac->data_inactivity_timer); + nr_timer_stop(&nr_mac->time_alignment_timer); nr_timer_stop(&nr_mac->ra.contention_resolution_timer); nr_timer_stop(&nr_mac->scheduling_info.sr_DelayTimer); nr_timer_stop(&nr_mac->scheduling_info.retxBSR_Timer); @@ -208,7 +210,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) nr_timer_stop(&nr_mac->scheduling_info.sr_info[i].prohibitTimer); // consider all timeAlignmentTimers as expired and perform the corresponding actions in clause 5.2 - // TODO + handle_time_alignment_timer_expired(nr_mac); // set the NDIs for all uplink HARQ processes to the value 0 for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) @@ -320,6 +322,8 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t ca memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); memset(&mac->csirs_measurements, 0, sizeof(mac->csirs_measurements)); memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); + for (int i = mac->TAG_list.count; i > 0 ; i--) + asn_sequence_del(&mac->TAG_list, i - 1, 1); } void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index c52a67c5a2..6272c4c33f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -912,9 +912,14 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER++; - if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER == ra->preambleTransMax + 1){ + // when the Contention Resolution is considered not successful + // stop timeAlignmentTimer + nr_timer_stop(&mac->time_alignment_timer); - LOG_D(MAC, "[UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n", + if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER == ra->preambleTransMax + 1) { + + LOG_D(NR_MAC, + "[UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n", mac->ue_id, frame, slot, @@ -931,23 +936,12 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr } } -void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac) +void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac) { LOG_W(NR_MAC, "Triggering new RA procedure for UE with RNTI %x\n", mac->crnti); mac->state = UE_SYNC; reset_ra(mac, false); mac->ra.msg3_C_RNTI = true; - // release PUCCH for all Serving Cells; - // release SRS for all Serving Cells; - release_PUCCH_SRS(mac); - // clear any configured downlink assignments and uplink grants; - int scs = mac->current_UL_BWP->scs; - if (mac->dl_config_request) - memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request)); - if (mac->ul_config_request) - clear_ul_config_request(mac, scs); - // clear any PUSCH resources for semi-persistent CSI reporting - // TODO we don't have semi-persistent CSI reporting } void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index ccfa861587..32d0dc72cf 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2953,8 +2953,11 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN); - LOG_D(MAC, "In [%d.%d] Handling DLSCH PDU type %d\n", - dl_info->frame, dl_info->slot, dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type); + LOG_D(NR_MAC, + "In [%d.%d] Handling DLSCH PDU type %d\n", + dl_info->frame, + dl_info->slot, + dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type); // Processing MAC PDU // it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs @@ -2964,15 +2967,19 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in // DCCH logical channel, or CCCH logical channel if (mac->data_inactivity_timer) nr_timer_start(mac->data_inactivity_timer); + // DL data arrival during RRC_CONNECTED when UL synchronisation status is "non-synchronised" + if (!nr_timer_is_active(&mac->time_alignment_timer) && mac->state == UE_CONNECTED && !get_softmodem_params()->phy_test) { + trigger_MAC_UE_RA(mac); + break; + } nr_ue_process_mac_pdu(mac, dl_info, pdu_id); break; case FAPI_NR_RX_PDU_TYPE_RAR : nr_ue_process_rar(mac, dl_info, pdu_id); break; - default: - AssertFatal(false, "Invalid PDU type\n"); + default : + AssertFatal(false, "Invalid DLSCH PDU type\n"); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT); } @@ -3412,6 +3419,21 @@ static nr_dci_format_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, return format; } +static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, int frame, int slot) +{ + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment; + ul_time_alignment->ta_command = ta; + ul_time_alignment->ta_apply = type; + + const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs); + const int n_slots_frame = nr_slots_per_frame[mac->current_UL_BWP->scs]; + ul_time_alignment->frame = (frame + (slot + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER; + ul_time_alignment->slot = (slot + ntn_ue_koffset) % n_slots_frame; + + // start or restart the timeAlignmentTimer associated with the indicated TAG + nr_timer_start(&mac->time_alignment_timer); +} + /////////////////////////////////// // brief: nr_ue_process_mac_pdu // function: parsing DL PDU header @@ -3563,33 +3585,21 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i // 38.321 Ch6.1.3.4 mac_len = 1; - /*uint8_t ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; - uint8_t tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID;*/ - const int ta = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; const int tag = ((NR_MAC_CE_TA *)pduP)[1].TAGID; - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment; - ul_time_alignment->tag_id = tag; - ul_time_alignment->ta_command = ta; - ul_time_alignment->ta_apply = adjustment_ta; + if (tag != mac->tag_Id) { + LOG_E(NR_MAC, "MAC CE TAG %d does not correspond to the one configured at MAC %ld\n", tag, mac->tag_Id); + done = 1; + break; + } - const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs); - const int n_slots_frame = nr_slots_per_frame[mac->current_UL_BWP->scs]; - ul_time_alignment->frame = (frameP + (slot + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER; - ul_time_alignment->slot = (slot + ntn_ue_koffset) % n_slots_frame; - - /* - #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pduP[1]); - #endif - */ + set_time_alignment(mac, ta, adjustment_ta, frameP, slot); if (ta == 31) LOG_D(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d \n", frameP, slot, ta, tag, CC_id); else LOG_I(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d \n", frameP, slot, ta, tag, CC_id); - break; case DL_SCH_LCID_CON_RES_ID: // Clause 5.1.5 and 6.1.3.3 of 3GPP TS 38.321 version 16.2.1 Release 16 @@ -3933,13 +3943,15 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d } } - #ifdef DEBUG_RAR - LOG_D(MAC, "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n", +#ifdef DEBUG_RAR + LOG_D(NR_MAC, + "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n", frame, slot, n_subheaders, n_subPDUs); - LOG_D(MAC, "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", + LOG_D(NR_MAC, + "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", *(uint8_t *) rarh, rar[0], rar[1], @@ -3949,30 +3961,18 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d rar[5], rarh->RAPID, preamble_index); - #endif +#endif if (ra->RA_RAPID_found) { RAR_grant_t rar_grant; - unsigned char tpc_command; -#ifdef DEBUG_RAR - unsigned char csi_req; -#endif - - // TA command - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment; - const int ta = rar->TA2 + (rar->TA1 << 5); - ul_time_alignment->ta_command = ta; - ul_time_alignment->ta_apply = rar_ta; - - LOG_W(MAC, "received TA command %d\n", 31 + ta); #ifdef DEBUG_RAR // CSI - csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); + unsigned char csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); #endif // TPC - tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); + unsigned char tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); switch (tpc_command){ case 0: ra->Msg3_TPC = -6; @@ -4010,6 +4010,31 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d // frequency hopping rar_grant.freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2); + // Schedule Msg3 + const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; + const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP; + const NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[current_DL_BWP->bwp_id]; + NR_tda_info_t tda_info = get_ul_tda_info(current_UL_BWP, + *pdcch_config->ra_SS->controlResourceSetId, + pdcch_config->ra_SS->searchSpaceType->present, + TYPE_RA_RNTI_, + rar_grant.Msg3_t_alloc); + if (!tda_info.valid_tda || tda_info.nrOfSymbols == 0) { + LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n"); + return; + } + const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs); + ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset); + + // TA command + // if the timeAlignmentTimer associated with this TAG is not running + if (!nr_timer_is_active(&mac->time_alignment_timer)) { + const int ta = rar->TA2 + (rar->TA1 << 5); + set_time_alignment(mac, ta, rar_ta, frame_tx, slot_tx); + LOG_W(MAC, "received TA command %d\n", 31 + ta); + } + // else ignore the received Timing Advance Command + #ifdef DEBUG_RAR LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E); LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T); @@ -4040,26 +4065,6 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d tpc_command); #endif - // Schedule Msg3 - const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; - const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP; - const NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[current_DL_BWP->bwp_id]; - NR_tda_info_t tda_info = get_ul_tda_info(current_UL_BWP, - *pdcch_config->ra_SS->controlResourceSetId, - pdcch_config->ra_SS->searchSpaceType->present, - TYPE_RA_RNTI_, - rar_grant.Msg3_t_alloc); - if (!tda_info.valid_tda || tda_info.nrOfSymbols == 0) { - LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n"); - return; - } - const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs); - ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset); - - const int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs]; - ul_time_alignment->frame = (frame_tx + (slot_tx + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER; - ul_time_alignment->slot = (slot_tx + ntn_ue_koffset) % n_slots_frame; - if (ret != -1) { uint16_t rnti = mac->crnti; // Upon successful reception, set the T-CRNTI to the RAR value if the RA preamble is selected among the contention-based RA Preambles @@ -4089,6 +4094,9 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d } else { ra->t_crnti = 0; + // TODO if the Random Access Preamble was not selected by the MAC entity + // among the contention-based Random Access Preamble + // apply the Timing Advance Command and start or restart the timeAlignmentTimer } return; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index e9a2fb58de..84a35dcf52 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -61,7 +61,7 @@ } static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_frame_t slotP); -static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment); +static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac); static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac, NR_SINGLE_ENTRY_PHR_MAC_CE *phr, float P_CMAX, @@ -152,6 +152,30 @@ static void trigger_regular_bsr(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity nr_timer_stop(&mac->scheduling_info.sr_DelayTimer); } +void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac) +{ + // flush all HARQ buffers for all Serving Cells + for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { + memset(&mac->dl_harq_info[k], 0, sizeof(NR_UE_HARQ_STATUS_t)); + memset(&mac->ul_harq_info[k], 0, sizeof(NR_UL_HARQ_INFO_t)); + mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value + mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value + } + // release PUCCH for all Serving Cells; + // release SRS for all Serving Cells; + release_PUCCH_SRS(mac); + // clear any configured downlink assignments and uplink grants; + int scs = mac->current_UL_BWP ? mac->current_UL_BWP->scs : get_softmodem_params()->numerology; + if (mac->dl_config_request) + memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request)); + if (mac->ul_config_request) + clear_ul_config_request(mac, scs); + // clear any PUSCH resources for semi-persistent CSI reporting + // TODO we don't have semi-persistent CSI reporting + // maintain N_TA + // TODO not sure what to do here +} + void update_mac_timers(NR_UE_MAC_INST_t *mac) { if (mac->data_inactivity_timer) { @@ -159,6 +183,9 @@ void update_mac_timers(NR_UE_MAC_INST_t *mac) if (inactivity_timer_expired) nr_mac_rrc_inactivity_timer_ind(mac->ue_id); } + bool alignment_timer_expired = nr_timer_tick(&mac->time_alignment_timer); + if (alignment_timer_expired) + handle_time_alignment_timer_expired(mac); nr_timer_tick(&mac->ra.contention_resolution_timer); for (int j = 0; j < NR_MAX_SR_ID; j++) nr_timer_tick(&mac->scheduling_info.sr_info[j].prohibitTimer); @@ -1245,7 +1272,7 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info ue_dci_configuration(mac, dl_config, rx_frame, rx_slot); if (mac->ul_time_alignment.ta_apply != no_ta) - schedule_ta_command(dl_config, &mac->ul_time_alignment); + schedule_ta_command(dl_config, mac); nr_scheduled_response_t scheduled_response = {.dl_config = dl_config, .module_id = mac->ue_id, @@ -1271,6 +1298,24 @@ static bool check_pucchres_for_pending_SR(NR_PUCCH_Config_t *pucch_Config, int t return false; } +void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac) +{ + if (get_softmodem_params()->phy_test) + return; // cannot trigger RA in phytest mode + trigger_MAC_UE_RA(mac); + // release PUCCH for all Serving Cells; + // release SRS for all Serving Cells; + release_PUCCH_SRS(mac); + // clear any configured downlink assignments and uplink grants; + int scs = mac->current_UL_BWP->scs; + if (mac->dl_config_request) + memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request)); + if (mac->ul_config_request) + clear_ul_config_request(mac, scs); + // clear any PUSCH resources for semi-persistent CSI reporting + // TODO we don't have semi-persistent CSI reporting +} + static void nr_update_sr(NR_UE_MAC_INST_t *mac) { NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info; @@ -1459,6 +1504,11 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) } else { if (ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator && (mac->state == UE_CONNECTED || (ra->ra_state == nrRA_WAIT_RAR && ra->cfra))) { + if (!nr_timer_is_active(&mac->time_alignment_timer) && mac->state == UE_CONNECTED && !get_softmodem_params()->phy_test) { + // UL data arrival during RRC_CONNECTED when UL synchronisation status is "non-synchronised" + trigger_MAC_UE_RA(mac); + return; + } // Getting IP traffic to be transmitted int tx_power = ulcfg_pdu->pusch_config_pdu.tx_power; int P_CMAX = nr_get_Pcmax(mac->p_Max, @@ -3534,11 +3584,13 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, return num_sdus > 0 ? 1 : 0; } -static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment) +static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac) { + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment; fapi_nr_ta_command_pdu *ta = &dl_config->dl_config_list[dl_config->number_pdus].ta_command_pdu; ta->ta_frame = ul_time_alignment->frame; ta->ta_slot = ul_time_alignment->slot; + ta->ta_offset = mac->n_ta_offset; ta->is_rar = ul_time_alignment->ta_apply == rar_ta; ta->ta_command = ul_time_alignment->ta_command; dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_CONFIG_TA_COMMAND;