Maintenance of Uplink Time Alignment. Introduced control on TA transmission and TA update application.
- ta_timer at gNB side to control the transmission of TA to the UE. This is now happening every 20 slots. - when the timer resets gNB is now transmitting the TA whether it is zero or not. - introduced struct NR_UL_TIME_ALIGNMENT_t to handle configuration of time alignment related parameters. - UE PHY RX: is now triggered through a flag when to store the TA command, the frame and slot when the application should occur. - UE PHY TX: when the tx frame and slot match the time alignment configuration, it process the TA command and applies the TA update
This commit is contained in:
+25
-1
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user