diff --git a/executables/nr-ue.c b/executables/nr-ue.c index fcbd659bbea7832b5b8f75c5394058fb5530a5f3..a781c5fdcdc46373e997ceae42dfe1f6e6a50897 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -461,6 +461,15 @@ void UE_processing(void *arg) { UE_nr_rxtx_proc_t *proc = &rxtxD->proc; PHY_VARS_NR_UE *UE = rxtxD->UE; processSlotRX(UE, proc); + uint8_t gNB_id = 0; + + // params for UL time alignment procedure + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &UE->ul_time_alignment[gNB_id]; + uint8_t numerology = UE->frame_parms.numerology_index; + uint16_t bwp_ul_NB_RB = UE->frame_parms.N_RB_UL; + int slot_tx = proc->nr_tti_tx; + int frame_tx = proc->frame_tx; + //printf(">>> mac ended\n"); // Prepare the future Tx data /* @@ -473,6 +482,21 @@ void UE_processing(void *arg) { #endif */ + /* UL time alignment + // If the current tx frame and slot match the TA configuration in ul_time_alignment + // then timing advance is processed and set to be applied in the next UL transmission */ + if (UE->mac_enabled == 1) { + + if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot){ + LOG_D(PHY,"Applying timing advance -- frame %d -- slot %d\n", frame_tx, slot_tx); + + //if (nfapi_mode!=3){ + nr_process_timing_advance(UE->Mod_id, UE->CC_id, ul_time_alignment->ta_command, numerology, bwp_ul_NB_RB); + ul_time_alignment->ta_frame = -1; + ul_time_alignment->ta_slot = -1; + //} + } + } if (proc->nr_tti_tx == NR_UPLINK_SLOT || UE->frame_parms.frame_type == FDD){ @@ -480,7 +504,7 @@ void UE_processing(void *arg) { if (UE->mode != loop_through_memory) - phy_procedures_nrUE_TX(UE,proc,0,thread_id); + phy_procedures_nrUE_TX(UE,proc,gNB_id,thread_id); } diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 19f4365a298ac47b8054d87f9e1c4ed6a4f32341..663e005d65ae8d409e7dde0d03715543ef55897d 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -871,6 +871,16 @@ typedef struct UE_NR_SCAN_INFO_s { int32_t freq_offset_Hz[3][10]; } UE_NR_SCAN_INFO_t; +typedef struct { + /// flag used by MAC to inform PHY about a TA to be applied + unsigned char apply_ta; + /// frame and slot when to apply the TA as stated in TS 38.213 setion 4.2 + int16_t ta_frame; + char ta_slot; + /// TA command and TAGID received from the gNB + uint8_t ta_command; + uint8_t tag_id; +} NR_UL_TIME_ALIGNMENT_t; #include "NR_IF_Module.h" @@ -1066,9 +1076,14 @@ typedef struct { int rx_offset; /// Timing offset int rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP int time_sync_cell; - int timing_advance; ///timing advance signalled from eNB - int hw_timing_advance; - int N_TA_offset; ///timing offset used in TDD + + /// Timing Advance updates variables + /// Timing advance update computed from the TA command signalled from gNB + int timing_advance; + int hw_timing_advance; + int N_TA_offset; ///timing offset used in TDD + NR_UL_TIME_ALIGNMENT_t ul_time_alignment[NUMBER_OF_CONNECTED_gNB_MAX]; + /// Flag to tell if UE is secondary user (cognitive mode) unsigned char is_secondary_ue; /// Flag to tell if secondary eNB has channel estimates to create NULL-beams from. diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 66398c393e9cebe56bfd6e2b8004a18497d93484..4b4800398e94c34b5886a4dc8689f28b4e9dd6e8 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -292,10 +292,10 @@ int8_t nr_find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); /*! \brief Compute the timing adjustment at UE side from the old TA offset and the new received TA command @param Mod_id Local UE index on which to act @param CC_id Component Carrier Index - @param timing_advance TA command + @param ta_command TA command received from the network @param mu numerology index (0,1,2..) */ -void nr_process_timing_advance(module_id_t Mod_id,uint8_t CC_id,uint8_t timing_advance, uint8_t mu, uint16_t bwp_ul_NB_RB); +void nr_process_timing_advance(module_id_t Mod_id,uint8_t CC_id,uint8_t ta_command, uint8_t mu, uint16_t bwp_ul_NB_RB); void nr_process_timing_advance_rar(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint16_t timing_advance); unsigned int get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 138f40790f47ffccc2196c9fa93aa00893c6a43c..c4df96c56a0efc59a12bbfdf680fb36900919d74 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1545,7 +1545,7 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDUR #endif -void nr_process_timing_advance(module_id_t Mod_id, uint8_t CC_id, uint8_t timing_advance, uint8_t mu, uint16_t bwp_ul_NB_RB){ +void nr_process_timing_advance(module_id_t Mod_id, uint8_t CC_id, uint8_t ta_command, uint8_t mu, uint16_t bwp_ul_NB_RB){ // 3GPP TS 38.213 p4.2 // scale by the scs numerology @@ -1561,9 +1561,9 @@ void nr_process_timing_advance(module_id_t Mod_id, uint8_t CC_id, uint8_t timing default: abort(); } - PHY_vars_UE_g[Mod_id][CC_id]->timing_advance += (timing_advance - 31) * bw_scaling / factor_mu; + PHY_vars_UE_g[Mod_id][CC_id]->timing_advance += (ta_command - 31) * bw_scaling / factor_mu; - LOG_D(PHY,"[UE %d] Got timing advance %u from MAC, new value is %u\n",Mod_id, timing_advance, PHY_vars_UE_g[Mod_id][CC_id]->timing_advance); + LOG_D(PHY, "[UE %d] Got timing advance command %u from MAC, new value is %u\n", Mod_id, ta_command, PHY_vars_UE_g[Mod_id][CC_id]->timing_advance); } void ue_ulsch_uespec_procedures(PHY_VARS_NR_UE *ue, @@ -3545,6 +3545,11 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, uint16_t nb_symb_sch = 9; nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind; + // params for UL time alignment procedure + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[eNB_id]; + unsigned char *apply_ta = &ul_time_alignment->apply_ta; + uint16_t slots_per_frame = ue->frame_parms.slots_per_frame; + int ul_tx_timing_adjustment = 6; // temporary hardcoded if (dlsch0==NULL) AssertFatal(0,"dlsch0 should be defined at this level \n"); @@ -3850,7 +3855,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, nr_tti_rx, dlsch0->harq_processes[harq_pid]->b, dlsch0->harq_processes[harq_pid]->TBS>>3, - eNB_id); + eNB_id, + ul_time_alignment); break; case SI_PDSCH: /*ue_decode_si(ue->Mod_id, @@ -3880,6 +3886,20 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, AssertFatal(1==0,"exiting");*/ break; } + + /* Time alignment procedure set the TA to be applied 6 slots + // after the reception of the command */ + if (ul_time_alignment->apply_ta == 1){ + ul_time_alignment->ta_slot = (nr_tti_rx + ul_tx_timing_adjustment) % slots_per_frame; + if (nr_tti_rx + ul_tx_timing_adjustment > slots_per_frame){ + ul_time_alignment->ta_frame = (frame_rx + 1) % 1024; + } else { + ul_time_alignment->ta_frame = frame_rx; + } + // reset TA flag + ul_time_alignment->apply_ta = 0; + LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", frame_rx, nr_tti_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot); + } } /*ue->total_TBS[eNB_id] = ue->total_TBS[eNB_id] + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 6cbe7b32c43e36c49b2305883a471c40e0e82403..6e369ac2745361cbc06082e4d875fd04b26e36f3 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -137,14 +137,15 @@ uint32_t mr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t @returns void */ void nr_ue_send_sdu(module_id_t module_idP,uint8_t CC_id, frame_t frameP, uint8_t ttiP, - uint8_t * pdu, uint16_t pdu_len, uint8_t eNB_index); + uint8_t * pdu, uint16_t pdu_len, uint8_t eNB_index, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment); void nr_ue_process_mac_pdu( module_id_t module_idP, uint8_t CC_id, uint8_t *pduP, uint16_t mac_pdu_len, - uint8_t eNB_index); + uint8_t eNB_index, + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment); int8_t nr_ue_process_dlsch(module_id_t module_id, int cc_id, uint8_t gNB_index, fapi_nr_dci_indication_t *dci_ind, void *pduP, uint32_t pdu_len); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index f63620b1d0c77f5eca707a5bb5fac29406099059..758d165ceab140bb1bd61e103a12ec6356903ebd 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2047,7 +2047,7 @@ void nr_ue_send_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP, uint8_t ttiP, - uint8_t * pdu, uint16_t pdu_len, uint8_t eNB_index){ + uint8_t * pdu, uint16_t pdu_len, uint8_t eNB_index, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment){ printf("nr_ue_send_sdu frame %d\n", frameP); @@ -2094,7 +2094,7 @@ void nr_ue_send_sdu(module_id_t module_idP, // Processing MAC PDU // it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs - nr_ue_process_mac_pdu(module_idP, CC_id, pduP, pdu_len, eNB_index); + nr_ue_process_mac_pdu(module_idP, CC_id, pduP, pdu_len, eNB_index, ul_time_alignment); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT); @@ -2110,7 +2110,8 @@ void nr_ue_process_mac_pdu( uint8_t CC_id, uint8_t *pduP, uint16_t mac_pdu_len, - uint8_t eNB_index){ + uint8_t eNB_index, + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment){ // This function is adapting code from the old // parse_header(...) and ue_send_sdu(...) functions of OAI LTE @@ -2123,8 +2124,9 @@ void nr_ue_process_mac_pdu( uint16_t mac_sdu_len; NR_UE_MAC_INST_t *UE_mac_inst = get_mac_inst(module_idP); - uint8_t scs = UE_mac_inst->mib->subCarrierSpacingCommon; - uint16_t bwp_ul_NB_RB = UE_mac_inst->initial_bwp_ul.N_RB; + //uint8_t scs = UE_mac_inst->mib->subCarrierSpacingCommon; + //uint16_t bwp_ul_NB_RB = UE_mac_inst->initial_bwp_ul.N_RB; + // For both DL/UL-SCH // Except: // - UL/DL-SCH: fixed-size MAC CE(known by LCID) @@ -2280,9 +2282,12 @@ void nr_ue_process_mac_pdu( // 38.321 Ch6.1.3.4 mac_ce_len = 1; - uint8_t ta_command = ((NR_MAC_CE_TA *)pdu_ptr)[1].TA_COMMAND; + /*uint8_t ta_command = ((NR_MAC_CE_TA *)pdu_ptr)[1].TA_COMMAND; + uint8_t tag_id = ((NR_MAC_CE_TA *)pdu_ptr)[1].TAGID;*/ - uint8_t tag_id = ((NR_MAC_CE_TA *)pdu_ptr)[1].TAGID; + ul_time_alignment->apply_ta = 1; + ul_time_alignment->ta_command = ((NR_MAC_CE_TA *)pdu_ptr)[1].TA_COMMAND; + ul_time_alignment->tag_id = ((NR_MAC_CE_TA *)pdu_ptr)[1].TAGID; /* #ifdef DEBUG_HEADER_PARSING @@ -2290,11 +2295,8 @@ void nr_ue_process_mac_pdu( #endif */ - LOG_D(MAC, "Received TA_COMMAND %u TAGID %u CC_id %d\n", ta_command, tag_id, CC_id); - - //if (nfapi_mode!=3){ // TODO check nfapi_mode - nr_process_timing_advance(module_idP, CC_id, ta_command, scs, bwp_ul_NB_RB); - //} + LOG_D(MAC, "Received TA_COMMAND %u TAGID %u CC_id %d\n", + ul_time_alignment->ta_command, ul_time_alignment->tag_id, CC_id); break; case DL_SCH_LCID_CON_RES_ID: diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index d2f6d805dedb4e38ab81cddb5cb5eefd9014af1f..3c654ac66cc4565a1557cef246c1910516124c20 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -53,6 +53,7 @@ int nr_generate_dlsch_pdu(unsigned char *sdus_payload, unsigned char drx_cmd, unsigned short timing_advance_cmd, NR_TAG_Id_t tag_id, + int ta_length, unsigned char *ue_cont_res_id, unsigned short post_padding){ @@ -76,25 +77,30 @@ int nr_generate_dlsch_pdu(unsigned char *sdus_payload, } // Timing Advance subheader - if (timing_advance_cmd != 31) { + /* This was done only when timing_advance_cmd != 31 + // now TA is always send when ta_timer resets regardless of its value + // this is done to avoid issues with the timeAlignmentTimer which is + // supposed to monitor if the UE received TA or not */ + if (ta_length){ mac_pdu_ptr->R = 0; mac_pdu_ptr->LCID = DL_SCH_LCID_TA_COMMAND; //last_size = 1; mac_pdu_ptr++; - // TA MAC CE (1 octet) + // TA MAC CE (1 octet) AssertFatal(timing_advance_cmd < 64,"timing_advance_cmd %d > 63\n", timing_advance_cmd); ((NR_MAC_CE_TA *) ce_ptr)->TA_COMMAND = timing_advance_cmd; //(timing_advance_cmd+31)&0x3f; ((NR_MAC_CE_TA *) ce_ptr)->TAGID = tag_id; LOG_D(MAC, "NR MAC CE timing advance command =%d (%d) TAG ID =%d\n", timing_advance_cmd, ((NR_MAC_CE_TA *) ce_ptr)->TA_COMMAND, tag_id); mac_ce_size = sizeof(NR_MAC_CE_TA); - + // Copying bytes for MAC CEs to the mac pdu pointer memcpy((void *) mac_pdu_ptr, (void *) ce_ptr, mac_ce_size); ce_ptr += mac_ce_size; - mac_pdu_ptr += (unsigned char) mac_ce_size; - } + mac_pdu_ptr += (unsigned char) mac_ce_size; + } + // Contention resolution fixed subheader and MAC CE if (ue_cont_res_id) { @@ -199,35 +205,35 @@ nr_schedule_ue_spec(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){ int UE_id = 0; // UE_list->head is -1 ! UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - ta_update = ue_sched_ctl->ta_update; + //ta_update = ue_sched_ctl->ta_update; - for (CC_id = 0; CC_id < RC.nb_nr_mac_CC[module_idP] + 1; CC_id++) { - LOG_D(MAC, "doing nr_schedule_ue_spec for CC_id %d\n", CC_id); + for (CC_id = 0; CC_id < RC.nb_nr_mac_CC[module_idP]; CC_id++) { + LOG_D(MAC, "doing nr_schedule_ue_spec for UE_id %d CC_id %d frame %d slot %d\n", + UE_id, CC_id, frameP, slotP); dl_req = &gNB->DL_req[CC_id].dl_config_request_body; //for (UE_id = UE_list->head; UE_id >= -1; UE_id = UE_list->next[UE_id]) { - /* + // this was taken from the preprocessor + if (ue_sched_ctl->ta_timer) ue_sched_ctl->ta_timer--; + + /* //process retransmission if (round != 8) { - + } else { // This is a potentially new SDU opportunity */ - if (gNB->tag->timeAlignmentTimer != NULL) { - printf(" SHOULD NOT ENTER HERE \n"); - if (gNB->tag->timeAlignmentTimer == 0) { - ta_update = ue_sched_ctl->ta_update; - /* if we send TA then set timer to not send it for a while */ - if (ta_update != 31) - ue_sched_ctl->ta_timer = 20; - /* reset ta_update */ - ue_sched_ctl->ta_update = 31; - } else { - ta_update = 31; - } - } + if (ue_sched_ctl->ta_timer == 0) { + ta_update = ue_sched_ctl->ta_update; + /* if time is up, then set the timer to not send it for 20 NR_DOWNLINK_SLOT (20 frames) + // regardless of the TA value */ + ue_sched_ctl->ta_timer = 2; //set to 20 when transmission will be in every slot + /* reset ta_update */ + ue_sched_ctl->ta_update = 31; + ta_len = 2; + } // else ta_update = 31; - ta_len = (ta_update != 31) ? 2 : 0; + //ta_len = (ta_update != 31) ? 2 : 0; // retrieve TAG ID if(gNB->tag->tag_Id != NULL ){ @@ -307,6 +313,7 @@ nr_schedule_ue_spec(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){ 255, // no drx ta_update, // timing advance tag_id, + ta_len, NULL, // contention res id post_padding); // Padding: fill remainder of DLSCH with 0 diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 185c866661a5aae2b7d46e46d1e9226e8b4f8769..530911f359c52cb343e243fad38e45e13ad4b2f0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -79,6 +79,7 @@ int nr_generate_dlsch_pdu(unsigned char *sdus_payload, unsigned char drx_cmd, unsigned short timing_advance_cmd, NR_TAG_Id_t tag_id, + int ta_length, unsigned char *ue_cont_res_id, unsigned short post_padding);