Commit 6d09b217 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/NR_UE_UL_time_alignment' into integration_2024_w39

parents ed4af195 e1218f9b
......@@ -118,7 +118,8 @@ gNBs =
pucchGroupHopping = 0;
hoppingId = 40;
p0_nominal = -70;
n_TimingAdvanceOffset = 0;
# TimingAdvanceOffset_n25600
n_TimingAdvanceOffset = 1;
ssb_PositionsInBurst_Bitmap = 1;
......
......@@ -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;
......
......@@ -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 )
......
......@@ -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}
......
......@@ -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
......
......@@ -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;
......
......@@ -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
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);
}
else
ue->N_TA_offset = set_default_nta_offset(fp->freq_range, fp->samples_per_subframe);
ue->ta_frame = -1;
ue->ta_slot = -1;
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) {
......
......@@ -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)) ||
......
......@@ -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;
......
......@@ -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);
......
......@@ -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,
......
......@@ -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);
......
......@@ -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;
......
......@@ -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,
......
......@@ -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)
......
......@@ -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)
......
......@@ -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;
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;
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;
}
/*
#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;
}
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment